This commit is contained in:
elvis
2025-12-02 05:01:16 +01:00
parent a85c372462
commit ca6f6e7b39
6 changed files with 178 additions and 76 deletions

View File

@ -211,6 +211,7 @@ impl Reaction {
.fold(Set::default(), |acc, r| acc.union(&r.products)) .fold(Set::default(), |acc, r| acc.union(&r.products))
} }
/// Returns all reactions that have a certain product
pub fn all_reactions_with_product<'a>( pub fn all_reactions_with_product<'a>(
reactions: &'a [Self], reactions: &'a [Self],
el: &IdType, el: &IdType,
@ -238,7 +239,8 @@ impl BasicReaction for PositiveReaction {
type Set = PositiveSet; type Set = PositiveSet;
fn enabled(&self, state: &Self::Set) -> bool { 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> { 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 { pub fn create(reactants: Set, inhibitors: Set, products: Set) -> Self {
Self { Self {
reactants: reactants 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<PositiveSet> { pub fn differ_only_one_element(&self, other: &Self) -> Option<PositiveSet> {
if self.products != other.products { if self.products != other.products {
return None; return None;
@ -334,9 +338,10 @@ impl Reaction {
r.reactants.clone(), r.reactants.clone(),
r.inhibitors.clone(), r.inhibitors.clone(),
Set::from([el]), Set::from([el]),
)) ));
} }
tmp.sort_by(|r1, r2| r1.reactants.cmp(&r2.reactants)); tmp.sort_by(|r1, r2| r1.reactants.cmp(&r2.reactants));
tmp.dedup();
// remove reactions with only one element of opposite state // remove reactions with only one element of opposite state
// as intersection (same product ```el```) // as intersection (same product ```el```)
@ -344,6 +349,7 @@ impl Reaction {
while pos > 0 { while pos > 0 {
if let Some(intersection) = if let Some(intersection) =
tmp[pos].differ_only_one_element(&tmp[pos - 1]) tmp[pos].differ_only_one_element(&tmp[pos - 1])
// && !intersection.is_empty()
{ {
tmp[pos - 1].reactants = intersection; tmp[pos - 1].reactants = intersection;
tmp.remove(pos); tmp.remove(pos);
@ -364,6 +370,7 @@ impl Reaction {
}) })
} }
} }
res res
} }
} }

View File

@ -352,9 +352,13 @@ impl Set {
}, },
} }
} }
t t
}; };
t.sort();
t.dedup();
// minimization // minimization
// remove sets that contain other sets // 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<IdType>) { fn remove_elements(&mut self, other: Vec<IdType>) {
for element in other { for element in other {
self.identifiers.remove(&element); self.identifiers.remove(&element);
@ -703,7 +721,7 @@ impl PositiveSet {
self_copy.is_empty() self_copy.is_empty()
} }
// Returns only the positive entities. /// Returns only the positive entities.
pub fn positives(&self) -> Self { pub fn positives(&self) -> Self {
self.iter() self.iter()
.filter(|el| *el.1 == IdState::Positive) .filter(|el| *el.1 == IdState::Positive)
@ -711,7 +729,7 @@ impl PositiveSet {
.collect::<PositiveSet>() .collect::<PositiveSet>()
} }
// Returns only the negative entities. /// Returns only the negative entities.
pub fn negatives(&self) -> Self { pub fn negatives(&self) -> Self {
self.iter() self.iter()
.filter(|el| *el.1 == IdState::Negative) .filter(|el| *el.1 == IdState::Negative)
@ -719,6 +737,7 @@ impl PositiveSet {
.collect::<PositiveSet>() .collect::<PositiveSet>()
} }
/// Adds only the elements not in self that are in other.
pub fn add_unique(&self, other: &Self) -> Self { pub fn add_unique(&self, other: &Self) -> Self {
other other
.iter() .iter()
@ -731,4 +750,27 @@ impl PositiveSet {
pub fn elements(&self) -> Set { pub fn elements(&self) -> Set {
self.iter().map(|el| *el.0).collect::<Vec<_>>().into() self.iter().map(|el| *el.0).collect::<Vec<_>>().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::<Vec<_>>().into()
)
}
} }

View File

@ -715,6 +715,26 @@ impl System {
self.products_elements = self.products_elements =
Arc::new(Mutex::new(Some(new_product_elements))); Arc::new(Mutex::new(Some(new_product_elements)));
} }
pub fn precomputed_context_elements(&mut self, new_context_elements: Option<Set>) {
if let Some(nce) = new_context_elements {
self.overwrite_context_elements(nce);
}
}
pub fn precomputed_product_elements(&mut self, new_product_elements: Option<Set>) {
if let Some(npe) = new_product_elements {
self.overwrite_product_elements(npe);
}
}
pub fn direct_get_product_elements(&self) -> Option<Set> {
self.products_elements.lock().unwrap().clone()
}
pub fn direct_get_context_elements(&self) -> Option<Set> {
self.context_elements.lock().unwrap().clone()
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -1005,7 +1025,7 @@ impl PrintableWithTranslator for PositiveSystem {
if it.peek().is_none() { if it.peek().is_none() {
write!(f, "{}", Formatter::from(translator, el))?; write!(f, "{}", Formatter::from(translator, el))?;
} else { } else {
write!(f, "{}, ", Formatter::from(translator, el))?; writeln!(f, "{},", Formatter::from(translator, el))?;
} }
} }
write!(f, "]\n]") write!(f, "]\n]")
@ -1023,22 +1043,25 @@ impl From<System> for PositiveSystem {
let positive_entities = let positive_entities =
value.available_entities.to_positive_set(IdState::Positive); value.available_entities.to_positive_set(IdState::Positive);
let negative_entities = value // let negative_entities = value
.context_process // .context_process
.all_elements() // .all_elements()
.union(&value.environment().all_elements()) // .union(&value.environment().all_elements())
.union(&value.reactions().iter().fold( // .union(&value.reactions().iter().fold(
Set::default(), // Set::default(),
|acc: Set, el| { // |acc: Set, el| {
acc.union(&el.inhibitors) // acc.union(&el.inhibitors)
.union(&el.products) // .union(&el.products)
.union(&el.reactants) // .union(&el.reactants)
}, // },
)) // ))
.subtraction(&value.available_entities) // .subtraction(&value.available_entities)
// .to_positive_set(IdState::Negative);
let negative_entities =
value.products_elements()
.to_positive_set(IdState::Negative); .to_positive_set(IdState::Negative);
let new_available_entities = let new_available_entities =
positive_entities.union(&negative_entities); positive_entities.add_unique(&negative_entities);
let new_reactions = let new_reactions =
Arc::new(PositiveReaction::from_reactions(value.reactions())); Arc::new(PositiveReaction::from_reactions(value.reactions()));
@ -1091,4 +1114,24 @@ impl PositiveSystem {
self.products_elements = self.products_elements =
Arc::new(Mutex::new(Some(new_product_elements))); Arc::new(Mutex::new(Some(new_product_elements)));
} }
pub fn precomputed_context_elements(&mut self, new_context_elements: Option<PositiveSet>) {
if let Some(nce) = new_context_elements {
self.overwrite_context_elements(nce);
}
}
pub fn precomputed_product_elements(&mut self, new_product_elements: Option<PositiveSet>) {
if let Some(npe) = new_product_elements {
self.overwrite_product_elements(npe);
}
}
pub fn direct_get_product_elements(&self) -> Option<PositiveSet> {
self.products_elements.lock().unwrap().clone()
}
pub fn direct_get_context_elements(&self) -> Option<PositiveSet> {
self.context_elements.lock().unwrap().clone()
}
} }

View File

@ -328,7 +328,6 @@ fn conversion_entities() {
PositiveSet::from([ PositiveSet::from([
(1, Positive), (1, Positive),
(2, Positive), (2, Positive),
(3, Negative),
(5, Negative) (5, Negative)
]) ])
); );

View File

@ -323,7 +323,7 @@ impl SlicingTrace<PositiveSet, PositiveReaction, PositiveSystem> {
reversed_elements[reverse_i].context.push( reversed_elements[reverse_i].context.push(
&self.reactions[*r] &self.reactions[*r]
.reactants() .reactants()
.mask(&self.context_elements), .inverted_mask(&self.products_elements),
); );
reversed_elements[reverse_i].reaction_products.push( reversed_elements[reverse_i].reaction_products.push(
&self.reactions[*r] &self.reactions[*r]
@ -361,45 +361,6 @@ impl<
f: &mut std::fmt::Formatter, f: &mut std::fmt::Formatter,
translator: &crate::translator::Translator, translator: &crate::translator::Translator,
) -> std::fmt::Result { ) -> 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:")?; writeln!(f, "Trace:")?;
let mut elements = self.elements.iter().peekable(); 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(()) Ok(())
} }
} }

View File

@ -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(), self.system.available_entities.clone(),
(*c).clone(), (*c).clone(),
t,
reactants, reactants,
reactants_absent, reactants_absent,
inhibitors, inhibitors,
inhibitors_present, inhibitors_present,
products.clone(), products.clone(),
); );
let new_system = System::from( let mut new_system = System::from(
Arc::clone(&self.system.delta), Arc::clone(&self.system.delta),
products, products,
(*k).clone(), (*k).clone(),
Arc::clone(&self.system.reaction_rules), 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)) Some((label, new_system))
} }
} }
@ -136,6 +139,7 @@ impl<'a> Iterator
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let (c, k) = self.choices_iterator.next()?; let (c, k) = self.choices_iterator.next()?;
let t = self.system.available_entities.union(c.as_ref()); let t = self.system.available_entities.union(c.as_ref());
let ( let (
reactants, reactants,
reactants_absent, reactants_absent,
@ -175,23 +179,26 @@ impl<'a> Iterator
}, },
); );
let label = PositiveLabel::from( let label = PositiveLabel::create(
self.system.available_entities.clone(), self.system.available_entities.clone(),
(*c).clone(), (*c).clone(),
t,
reactants, reactants,
reactants_absent, reactants_absent,
inhibitors, inhibitors,
inhibitors_present, inhibitors_present,
products.clone(), products.clone(),
); );
let new_system = PositiveSystem::from( let mut new_system = PositiveSystem::from(
Arc::clone(&self.system.delta), Arc::clone(&self.system.delta),
// products.add_unique(&self.system.negated_products_elements()), products.push_unique(&self.system.negated_products_elements()),
products, // products,
(*k).clone(), (*k).clone(),
Arc::clone(&self.system.reaction_rules), 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)) 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), Arc::clone(&self.system.delta),
// all_products.add_unique(&self.system. // all_products.add_unique(&self.system.
// negated_products_elements()), // negated_products_elements()),
@ -269,6 +276,9 @@ impl<'a> Iterator for TraceIterator<'a, Set, System, Process> {
Arc::clone(&self.system.reaction_rules), 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(( Some((
context.as_ref().clone(), context.as_ref().clone(),
all_products, all_products,
@ -285,8 +295,7 @@ impl<'a> Iterator
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let (context, k) = self.choices_iterator.next()?; let (context, k) = self.choices_iterator.next()?;
let total_entities = let total_entities = self.system.available_entities().union(context.as_ref());
self.system.available_entities().union(context.as_ref());
let (enabled_reaction_positions, all_products) = let (enabled_reaction_positions, all_products) =
self.system.reactions().iter().enumerate().fold( 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), Arc::clone(&self.system.delta),
// all_products.add_unique(&self.system. all_products.push_unique(&self.system.negated_products_elements()),
// negated_products_elements()), // all_products.clone(),
all_products.clone(),
(*k).clone(), (*k).clone(),
Arc::clone(&self.system.reaction_rules), 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(( Some((
context.as_ref().clone(), context.as_ref().clone(),
all_products.mask(&self.system.products_elements()), all_products.mask(&self.system.products_elements()),