use std::fmt::Debug; use std::ops::{Index, IndexMut}; use std::rc::Rc; use std::slice::SliceIndex; use crate::reaction::{BasicReaction, PositiveReaction, Reaction}; use crate::set::{BasicSet, PositiveSet, Set}; use crate::system::{BasicSystem, PositiveSystem, System}; use crate::translator::{Formatter, PrintableWithTranslator}; type TraceElement = (Option>, Rc); #[derive(Clone, Default)] pub struct Trace { pub values: Vec>, } impl Trace { pub fn push(&mut self, val: TraceElement) { self.values.push(val) } pub fn len(&self) -> usize { self.values.len() } pub fn is_empty(&self) -> bool { self.values.is_empty() } } impl From<&[TraceElement]> for Trace { fn from(value: &[TraceElement]) -> Self { Self { values: value.to_vec(), } } } impl From<&[TraceElement; N]> for Trace { fn from(value: &[TraceElement; N]) -> Self { Self { values: value.to_vec(), } } } impl<'a, L, Sys> From<&'a Vec>> for Trace { fn from(value: &'a Vec>) -> Self { Self { values: value.to_vec(), } } } impl From>> for Trace { fn from(value: Vec>) -> Self { Self { values: value } } } impl]>> Index for Trace { type Output = I::Output; fn index(&self, index: I) -> &Self::Output { &self.values[index] } } impl]>> IndexMut for Trace { fn index_mut(&mut self, index: I) -> &mut Self::Output { &mut self.values[index] } } // ----------------------------------------------------------------------------- // Slicing Trace // ----------------------------------------------------------------------------- #[derive(Clone, Default)] pub struct SlicingElement { pub context: S, pub reaction_products: S, } impl Debug for SlicingElement where S: Debug, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "{{context: {:?} - reaction_products: {:?}}}", self.context, self.reaction_products ) } } impl PrintableWithTranslator for SlicingElement where S: PrintableWithTranslator, { fn print( &self, f: &mut std::fmt::Formatter, translator: &crate::translator::Translator, ) -> std::fmt::Result { write!( f, "{{context: {}, ", Formatter::from(translator, &self.context) )?; write!( f, "reaction products: {}}}", Formatter::from(translator, &self.reaction_products) ) } } #[derive(Clone, Default, Debug)] pub struct EnabledReactions { pub data: Vec, } impl PrintableWithTranslator for EnabledReactions { fn print( &self, f: &mut std::fmt::Formatter, _translator: &crate::translator::Translator, ) -> std::fmt::Result { let mut elements = self.data.iter().peekable(); while let Some(e) = elements.next() { if elements.peek().is_some() { write!(f, "{e}, ")?; } else { write!(f, "{e}")?; } } Ok(()) } } impl<'a> IntoIterator for &'a EnabledReactions { type Item = &'a usize; type IntoIter = std::slice::Iter<'a, usize>; fn into_iter(self) -> Self::IntoIter { self.data.iter() } } impl EnabledReactions { pub fn iter(&self) -> std::slice::Iter<'_, usize> { self.into_iter() } } #[derive(Clone)] pub struct SlicingTrace, Sys: BasicSystem> { pub elements: Vec>, pub enabled_reactions: Vec, pub reactions: Rc>, pub systems: Vec>, pub context_elements: Rc, pub products_elements: Rc, } impl, Sys: BasicSystem> Default for SlicingTrace { fn default() -> Self { Self { elements: Vec::default(), enabled_reactions: Vec::default(), reactions: Rc::new(Vec::default()), systems: Vec::default(), context_elements: Rc::new(S::default()), products_elements: Rc::new(S::default()), } } } impl, Sys: BasicSystem> SlicingTrace { pub fn is_empty(&self) -> bool { self.elements.is_empty() } pub fn len(&self) -> usize { self.elements.len() } } impl SlicingTrace { pub fn slice(&self, marking: Set) -> Result { let mut reversed_elements = Vec::with_capacity(self.elements.len()); reversed_elements.push(SlicingElement { context: self .elements .last() .ok_or("Trace with length zero.")? .context .clone(), reaction_products: marking, }); let mut reversed_enabled_reactions: Vec = Vec::with_capacity(self.enabled_reactions.len()); for i in (1..(self.len())).rev() { let reverse_i: usize = self.len() - i; let i = i - 1; if reversed_elements.len() <= reverse_i { reversed_elements.push(SlicingElement::default()); } if reversed_enabled_reactions.len() <= reverse_i { reversed_enabled_reactions.push(EnabledReactions::default()); } for r in self.enabled_reactions[i].iter() { if !reversed_elements[reverse_i - 1] .reaction_products .is_disjoint(self.reactions[*r].products()) { reversed_enabled_reactions[reverse_i - 1].data.push(*r); reversed_elements[reverse_i].context.push( &self.reactions[*r] .reactants() .intersection(&self.context_elements), ); reversed_elements[reverse_i].reaction_products.push( &self.reactions[*r] .reactants() .intersection(&self.products_elements), ) } } } reversed_elements.reverse(); reversed_enabled_reactions.reverse(); let new_trace = Self { elements: reversed_elements, enabled_reactions: reversed_enabled_reactions, reactions: Rc::clone(&self.reactions), systems: self.systems.to_vec(), context_elements: Rc::clone(&self.context_elements), products_elements: Rc::clone(&self.products_elements), }; Ok(new_trace) } } impl SlicingTrace { pub fn slice(&self, marking: PositiveSet) -> Result { let mut reversed_elements = Vec::with_capacity(self.elements.len()); reversed_elements.push(SlicingElement { context: self .elements .last() .ok_or("Trace with length zero.")? .context .clone(), reaction_products: marking, }); let mut reversed_enabled_reactions: Vec = Vec::with_capacity(self.enabled_reactions.len()); for i in (1..(self.len())).rev() { let reverse_i: usize = self.len() - i; let i = i - 1; if reversed_elements.len() <= reverse_i { reversed_elements.push(SlicingElement::default()); } if reversed_enabled_reactions.len() <= reverse_i { reversed_enabled_reactions.push(EnabledReactions::default()); } for r in self.enabled_reactions[i].iter() { if !reversed_elements[reverse_i - 1] .reaction_products .intersection(self.reactions[*r].products()).is_empty() { reversed_enabled_reactions[reverse_i - 1].data.push(*r); reversed_elements[reverse_i].context.push( &self.reactions[*r] .reactants() .mask(&self.context_elements), ); reversed_elements[reverse_i].reaction_products.push( &self.reactions[*r] .reactants() .mask(&self.products_elements), ) } } } reversed_elements.reverse(); reversed_enabled_reactions.reverse(); let new_trace = Self { elements: reversed_elements, enabled_reactions: reversed_enabled_reactions, reactions: Rc::clone(&self.reactions), systems: self.systems.to_vec(), context_elements: Rc::clone(&self.context_elements), products_elements: Rc::clone(&self.products_elements), }; Ok(new_trace) } } impl, Sys: BasicSystem,> PrintableWithTranslator for SlicingTrace { fn print( &self, f: &mut std::fmt::Formatter, translator: &crate::translator::Translator, ) -> std::fmt::Result { // let mut systems = self.systems.iter().peekable(); // writeln!(f, "Systems:")?; // while let Some(system) = systems.next() { // if systems.peek().is_some() { // write!(f, "{} --> ", Formatter::from(translator, // &**system))?; } else { // writeln!(f, "{}", Formatter::from(translator, &**system))?; // } // } let mut reactions = self.reactions.iter().enumerate().peekable(); writeln!(f, "Reactions:")?; while let Some((pos, reaction)) = reactions.next() { if reactions.peek().is_some() { writeln!( f, "\t({pos}) {},", Formatter::from(translator, reaction) )?; } else { writeln!( f, "\t({pos}) {}.", Formatter::from(translator, reaction) )?; } } writeln!( f, "Context Elements: {}", Formatter::from(translator, &*self.context_elements) )?; writeln!( f, "Product Elements: {}", Formatter::from(translator, &*self.products_elements) )?; let mut elements = self.elements.iter().peekable(); let mut enabled_reactions = self.enabled_reactions.iter(); writeln!(f, "Trace:")?; while let Some(el) = elements.next() { if let Some(r) = enabled_reactions.next() { if elements.peek().is_some() { writeln!( f, "{}\n\t|\n{: ^17}\n\t|\n\t▼", Formatter::from(translator, el), format!("({})", Formatter::from(translator, r)), )?; } else { writeln!( f, "{}\n\t|\n{: ^17}\n\t|\n\t?", Formatter::from(translator, el), format!("({})", Formatter::from(translator, r)), )?; } } else if elements.peek().is_some() { writeln!( f, "{}\n\t|\n\t|\n\t|\n\t▼", Formatter::from(translator, el) )?; } else { writeln!(f, "{}", Formatter::from(translator, el))?; } } Ok(()) } }