diff --git a/rsprocess/src/reaction.rs b/rsprocess/src/reaction.rs index 01e29d4..16c8a16 100644 --- a/rsprocess/src/reaction.rs +++ b/rsprocess/src/reaction.rs @@ -211,6 +211,7 @@ impl Reaction { .fold(Set::default(), |acc, r| acc.union(&r.products)) } + /// Returns all reactions that have a certain product pub fn all_reactions_with_product<'a>( reactions: &'a [Self], el: &IdType, @@ -238,7 +239,8 @@ impl BasicReaction for PositiveReaction { type Set = PositiveSet; fn enabled(&self, state: &Self::Set) -> bool { - self.reactants.is_subset(state) + self.reactants.has_positives(state) + // self.reactants.is_subset(state) } fn compute_step(&self, state: &Self::Set) -> Option<&Self::Set> { @@ -281,6 +283,8 @@ impl PositiveReaction { } } + /// Creates a Positive Reaction from the positive reactants and negative + /// inhibitors that produces positive products. pub fn create(reactants: Set, inhibitors: Set, products: Set) -> Self { Self { reactants: reactants @@ -290,7 +294,7 @@ impl PositiveReaction { } } - /// returns the reactants that are equal + /// Returns the reactants that are equal pub fn differ_only_one_element(&self, other: &Self) -> Option { if self.products != other.products { return None; @@ -334,9 +338,10 @@ impl Reaction { r.reactants.clone(), r.inhibitors.clone(), Set::from([el]), - )) + )); } tmp.sort_by(|r1, r2| r1.reactants.cmp(&r2.reactants)); + tmp.dedup(); // remove reactions with only one element of opposite state // as intersection (same product ```el```) @@ -344,6 +349,7 @@ impl Reaction { while pos > 0 { if let Some(intersection) = tmp[pos].differ_only_one_element(&tmp[pos - 1]) + // && !intersection.is_empty() { tmp[pos - 1].reactants = intersection; tmp.remove(pos); @@ -364,6 +370,7 @@ impl Reaction { }) } } + res } } diff --git a/rsprocess/src/set.rs b/rsprocess/src/set.rs index 4e33e6b..28f9cf6 100644 --- a/rsprocess/src/set.rs +++ b/rsprocess/src/set.rs @@ -352,9 +352,13 @@ impl Set { }, } } + t }; + t.sort(); + t.dedup(); + // minimization // remove sets that contain other sets { @@ -682,6 +686,20 @@ impl PositiveSet { ) } + pub fn inverted_mask(&self, other: &Self) -> Self { + Self::from_iter( + self.iter() + .filter(|el| { + !other.contains(&PositiveType::from(( + *el.0, + IdState::Positive + )) + ) + }) + .map(|el| (*el.0, *el.1)) + ) + } + fn remove_elements(&mut self, other: Vec) { for element in other { self.identifiers.remove(&element); @@ -703,7 +721,7 @@ impl PositiveSet { self_copy.is_empty() } - // Returns only the positive entities. + /// Returns only the positive entities. pub fn positives(&self) -> Self { self.iter() .filter(|el| *el.1 == IdState::Positive) @@ -711,7 +729,7 @@ impl PositiveSet { .collect::() } - // Returns only the negative entities. + /// Returns only the negative entities. pub fn negatives(&self) -> Self { self.iter() .filter(|el| *el.1 == IdState::Negative) @@ -719,6 +737,7 @@ impl PositiveSet { .collect::() } + /// Adds only the elements not in self that are in other. pub fn add_unique(&self, other: &Self) -> Self { other .iter() @@ -731,4 +750,27 @@ impl PositiveSet { pub fn elements(&self) -> Set { self.iter().map(|el| *el.0).collect::>().into() } + + pub fn has_positives(&self, state: &Self) -> bool { + self.iter() + .all(|a| { + if *a.1 == IdState::Positive { + state.contains(&PositiveType::from(a)) + } else { + !state.contains(&PositiveType::from((*a.0, IdState::Positive))) + } + }) + } + + fn has_element(&self, el: &PositiveType) -> bool { + self.identifiers.contains_key(&el.id) + } + + pub fn push_unique(&self, other: &Self) -> Self { + self.union( + &other.iter().filter(|el| { + !self.has_element(&PositiveType::from(*el)) + }).map(|el| (*el.0, *el.1)).collect::>().into() + ) + } } diff --git a/rsprocess/src/system.rs b/rsprocess/src/system.rs index 3f5ccbb..2fb023a 100644 --- a/rsprocess/src/system.rs +++ b/rsprocess/src/system.rs @@ -715,6 +715,26 @@ impl System { self.products_elements = Arc::new(Mutex::new(Some(new_product_elements))); } + + pub fn precomputed_context_elements(&mut self, new_context_elements: Option) { + if let Some(nce) = new_context_elements { + self.overwrite_context_elements(nce); + } + } + + pub fn precomputed_product_elements(&mut self, new_product_elements: Option) { + if let Some(npe) = new_product_elements { + self.overwrite_product_elements(npe); + } + } + + pub fn direct_get_product_elements(&self) -> Option { + self.products_elements.lock().unwrap().clone() + } + + pub fn direct_get_context_elements(&self) -> Option { + self.context_elements.lock().unwrap().clone() + } } // ----------------------------------------------------------------------------- @@ -1005,7 +1025,7 @@ impl PrintableWithTranslator for PositiveSystem { if it.peek().is_none() { write!(f, "{}", Formatter::from(translator, el))?; } else { - write!(f, "{}, ", Formatter::from(translator, el))?; + writeln!(f, "{},", Formatter::from(translator, el))?; } } write!(f, "]\n]") @@ -1023,22 +1043,25 @@ impl From for PositiveSystem { let positive_entities = value.available_entities.to_positive_set(IdState::Positive); - let negative_entities = value - .context_process - .all_elements() - .union(&value.environment().all_elements()) - .union(&value.reactions().iter().fold( - Set::default(), - |acc: Set, el| { - acc.union(&el.inhibitors) - .union(&el.products) - .union(&el.reactants) - }, - )) - .subtraction(&value.available_entities) + // let negative_entities = value + // .context_process + // .all_elements() + // .union(&value.environment().all_elements()) + // .union(&value.reactions().iter().fold( + // Set::default(), + // |acc: Set, el| { + // acc.union(&el.inhibitors) + // .union(&el.products) + // .union(&el.reactants) + // }, + // )) + // .subtraction(&value.available_entities) + // .to_positive_set(IdState::Negative); + let negative_entities = + value.products_elements() .to_positive_set(IdState::Negative); let new_available_entities = - positive_entities.union(&negative_entities); + positive_entities.add_unique(&negative_entities); let new_reactions = Arc::new(PositiveReaction::from_reactions(value.reactions())); @@ -1091,4 +1114,24 @@ impl PositiveSystem { self.products_elements = Arc::new(Mutex::new(Some(new_product_elements))); } + + pub fn precomputed_context_elements(&mut self, new_context_elements: Option) { + if let Some(nce) = new_context_elements { + self.overwrite_context_elements(nce); + } + } + + pub fn precomputed_product_elements(&mut self, new_product_elements: Option) { + if let Some(npe) = new_product_elements { + self.overwrite_product_elements(npe); + } + } + + pub fn direct_get_product_elements(&self) -> Option { + self.products_elements.lock().unwrap().clone() + } + + pub fn direct_get_context_elements(&self) -> Option { + self.context_elements.lock().unwrap().clone() + } } diff --git a/rsprocess/src/system_test.rs b/rsprocess/src/system_test.rs index fe07341..3812c94 100644 --- a/rsprocess/src/system_test.rs +++ b/rsprocess/src/system_test.rs @@ -328,7 +328,6 @@ fn conversion_entities() { PositiveSet::from([ (1, Positive), (2, Positive), - (3, Negative), (5, Negative) ]) ); diff --git a/rsprocess/src/trace.rs b/rsprocess/src/trace.rs index f2a3aec..9bbee9d 100644 --- a/rsprocess/src/trace.rs +++ b/rsprocess/src/trace.rs @@ -323,7 +323,7 @@ impl SlicingTrace { reversed_elements[reverse_i].context.push( &self.reactions[*r] .reactants() - .mask(&self.context_elements), + .inverted_mask(&self.products_elements), ); reversed_elements[reverse_i].reaction_products.push( &self.reactions[*r] @@ -361,45 +361,6 @@ impl< 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) - )?; - writeln!(f, "Trace:")?; let mut elements = self.elements.iter().peekable(); @@ -440,6 +401,45 @@ impl< } } + // 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) + )?; + Ok(()) } } diff --git a/rsprocess/src/transitions.rs b/rsprocess/src/transitions.rs index d838b91..5a2e8cd 100644 --- a/rsprocess/src/transitions.rs +++ b/rsprocess/src/transitions.rs @@ -84,22 +84,25 @@ impl<'a> Iterator for TransitionsIterator<'a, Set, System, Process> { }, ); - let label = Label::from( + let label = Label::create( self.system.available_entities.clone(), (*c).clone(), - t, reactants, reactants_absent, inhibitors, inhibitors_present, products.clone(), ); - let new_system = System::from( + let mut new_system = System::from( Arc::clone(&self.system.delta), products, (*k).clone(), Arc::clone(&self.system.reaction_rules), ); + + new_system.precomputed_context_elements(self.system.direct_get_context_elements()); + new_system.precomputed_product_elements(self.system.direct_get_product_elements()); + Some((label, new_system)) } } @@ -136,6 +139,7 @@ impl<'a> Iterator fn next(&mut self) -> Option { let (c, k) = self.choices_iterator.next()?; let t = self.system.available_entities.union(c.as_ref()); + let ( reactants, reactants_absent, @@ -175,23 +179,26 @@ impl<'a> Iterator }, ); - let label = PositiveLabel::from( + let label = PositiveLabel::create( self.system.available_entities.clone(), (*c).clone(), - t, reactants, reactants_absent, inhibitors, inhibitors_present, products.clone(), ); - let new_system = PositiveSystem::from( + let mut new_system = PositiveSystem::from( Arc::clone(&self.system.delta), - // products.add_unique(&self.system.negated_products_elements()), - products, + products.push_unique(&self.system.negated_products_elements()), + // products, (*k).clone(), Arc::clone(&self.system.reaction_rules), ); + + new_system.precomputed_context_elements(self.system.direct_get_context_elements()); + new_system.precomputed_product_elements(self.system.direct_get_product_elements()); + Some((label, new_system)) } } @@ -260,7 +267,7 @@ impl<'a> Iterator for TraceIterator<'a, Set, System, Process> { }, ); - let new_system = System::from( + let mut new_system = System::from( Arc::clone(&self.system.delta), // all_products.add_unique(&self.system. // negated_products_elements()), @@ -269,6 +276,9 @@ impl<'a> Iterator for TraceIterator<'a, Set, System, Process> { Arc::clone(&self.system.reaction_rules), ); + new_system.precomputed_context_elements(self.system.direct_get_context_elements()); + new_system.precomputed_product_elements(self.system.direct_get_product_elements()); + Some(( context.as_ref().clone(), all_products, @@ -285,8 +295,7 @@ impl<'a> Iterator fn next(&mut self) -> Option { let (context, k) = self.choices_iterator.next()?; - let total_entities = - self.system.available_entities().union(context.as_ref()); + let total_entities = self.system.available_entities().union(context.as_ref()); let (enabled_reaction_positions, all_products) = self.system.reactions().iter().enumerate().fold( @@ -301,15 +310,17 @@ impl<'a> Iterator }, ); - let new_system = PositiveSystem::from( + let mut new_system = PositiveSystem::from( Arc::clone(&self.system.delta), - // all_products.add_unique(&self.system. - // negated_products_elements()), - all_products.clone(), + all_products.push_unique(&self.system.negated_products_elements()), + // all_products.clone(), (*k).clone(), Arc::clone(&self.system.reaction_rules), ); + new_system.precomputed_context_elements(self.system.direct_get_context_elements()); + new_system.precomputed_product_elements(self.system.direct_get_product_elements()); + Some(( context.as_ref().clone(), all_products.mask(&self.system.products_elements()),