Correct hanlding of reactions

while converting from System to PositiveSystem
This commit is contained in:
elvis
2025-09-08 19:04:26 +02:00
parent 49051358f0
commit 2571148e74
6 changed files with 232 additions and 53 deletions

View File

@ -67,3 +67,15 @@ impl PrintableWithTranslator for PositiveType {
)
}
}
impl From<(IdType, IdState)> for PositiveType {
fn from(value: (IdType, IdState)) -> Self {
Self { id: value.0, state: value.1 }
}
}
impl From<(&IdType, &IdState)> for PositiveType {
fn from(value: (&IdType, &IdState)) -> Self {
Self { id: *value.0, state: *value.1 }
}
}

View File

@ -236,4 +236,27 @@ impl PositiveReaction {
products: products.to_positive_set(IdState::Positive),
}
}
/// returns the reactants that are equal
pub fn differ_only_one_element(&self, other: &Self) -> Option<PositiveSet> {
if self.products != other.products {
return None
}
let mut found = false;
for el in self.reactants.iter() {
match other.reactants.identifiers.get(el.0) {
None => return None,
Some(s) => {
if s != el.1 {
if found {
return None
} else {
found = true
}
}
}
}
}
Some(self.reactants.intersection(&other.reactants))
}
}

View File

@ -349,6 +349,9 @@ impl Set {
set1.equal_except_negated_elements(set2)
) {
let intersection = set1.opposite_intersection(set2);
if intersection.len() != 1 {
continue
}
set1.remove_elements(intersection);
t[pos_set1 - removed] = set1.clone();

View File

@ -107,3 +107,26 @@ fn prohibiting_set_4() {
]
)
}
#[test]
fn prohibiting_set_5() {
use super::element::IdState::*;
use super::set::{PositiveSet, Set};
let r1r = Set::from(vec![1]);
let r1i = Set::from(vec![2]);
let r2r = Set::from(vec![1, 2]);
let r2i = Set::from(vec![]);
let mut prohibiting_set =
Set::prohibiting_set(&[r1r, r2r], &[r1i, r2i]).unwrap();
prohibiting_set.sort();
assert_eq!(
prohibiting_set,
vec![
PositiveSet::from([(1, Negative)]),
]
)
}

View File

@ -648,7 +648,8 @@ impl From<System> for PositiveSystem {
/// Should never fail.
fn from(value: System) -> Self {
let new_env = Rc::new((&*value.delta).into());
let positive_entities = value.available_entities.to_positive_set(IdState::Positive);
let positive_entities =
value.available_entities.to_positive_set(IdState::Positive);
let negative_entities = value
.context_process
@ -666,27 +667,46 @@ impl From<System> for PositiveSystem {
)
.subtraction(&value.available_entities)
.to_positive_set(IdState::Negative);
let new_available_entities = positive_entities.union(&negative_entities);
let new_available_entities =
positive_entities.union(&negative_entities);
let new_context = value.context_process.into();
let new_reactions = {
let mut res = vec![];
let old_reactions = &value.reaction_rules;
old_reactions.iter().for_each(|r| {
res.push(PositiveReaction::create(
r.reactants.clone(),
r.inhibitors.clone(),
r.products.clone(),
))
});
let all_products = Reaction::all_products(old_reactions);
for el in all_products {
let p = Reaction::all_reactions_with_product(old_reactions, &el);
let p =
Reaction::all_reactions_with_product(old_reactions, &el);
let mut tmp = vec![];
for r in p.iter() {
tmp.push(PositiveReaction::create(
r.reactants.clone(),
r.inhibitors.clone(),
Set::from([el])
))
}
tmp.sort_by(|r1, r2| r1.reactants.cmp(&r2.reactants));
// remove reactions with only one element of opposite state
// as intersection (same product ```el```)
let mut pos = tmp.len()-1;
while pos > 0 {
if let Some(intersection)
= tmp[pos].differ_only_one_element(&tmp[pos-1])
{
tmp[pos-1].reactants = intersection;
tmp.remove(pos);
}
pos -= 1;
}
res.extend(tmp);
let prohib_set = Set::prohibiting_set(
&p.iter().map(|p| p.reactants.clone()).collect::<Vec<_>>(),
&p.iter().map(|p| p.inhibitors.clone()).collect::<Vec<_>>(),
)
.unwrap();
).unwrap(); // since we have in input a valid system
for s in prohib_set {
res.push(PositiveReaction {
reactants: s,
@ -694,6 +714,8 @@ impl From<System> for PositiveSystem {
})
}
}
Rc::new(res)
};

View File

@ -1,3 +1,5 @@
use crate::rsprocess::{set::PositiveSet, system::BasicSystem};
#[test]
fn one_transition() {
use super::environment::Environment;
@ -14,11 +16,13 @@ fn one_transition() {
entities: Set::from([]),
next_process: Rc::new(Process::Nill),
},
Rc::new(vec![Reaction {
reactants: Set::from([1]),
inhibitors: Set::from([3]),
products: Set::from([3]),
}]),
Rc::new(vec![
Reaction::from(
Set::from([1]),
Set::from([3]),
Set::from([3]),
),
]),
);
match system.one_transition() {
@ -59,7 +63,8 @@ fn one_transition_2() {
},
Rc::new(vec![
PositiveReaction {
reactants: PositiveSet::from([(1, IdState::Positive), (3, IdState::Negative)]),
reactants: PositiveSet::from([(1, IdState::Positive),
(3, IdState::Negative)]),
products: PositiveSet::from([(3, IdState::Positive)]),
},
PositiveReaction {
@ -122,11 +127,13 @@ fn convertion() {
entities: Set::from([]),
next_process: Rc::new(Process::Nill),
},
Rc::new(vec![Reaction {
reactants: Set::from([1]),
inhibitors: Set::from([3]),
products: Set::from([3]),
}]),
Rc::new(vec![
Reaction::from(
Set::from([1]),
Set::from([3]),
Set::from([3]),
),
]),
);
let system: PositiveSystem = system.into();
@ -202,21 +209,21 @@ fn traces_1() {
available_entities: Set::from([1, 2]),
context_process: Process::RecursiveIdentifier { identifier: 101 },
reaction_rules: Rc::new(vec![
Reaction {
reactants: Set::from([1]),
inhibitors: Set::from([3]),
products: Set::from([3]),
},
Reaction {
reactants: Set::from([3]),
inhibitors: Set::from([1]),
products: Set::from([1]),
},
Reaction {
reactants: Set::from([2]),
inhibitors: Set::default(),
products: Set::from([4]),
},
Reaction::from(
Set::from([1]),
Set::from([3]),
Set::from([3]),
),
Reaction::from(
Set::from([3]),
Set::from([1]),
Set::from([1]),
),
Reaction::from(
Set::from([2]),
Set::default(),
Set::from([4]),
),
]),
};
@ -261,21 +268,21 @@ fn traces_empty_env() {
next_process: Rc::new(Process::Nill),
},
reaction_rules: Rc::new(vec![
Reaction {
reactants: Set::from([1]),
inhibitors: Set::from([3]),
products: Set::from([3]),
},
Reaction {
reactants: Set::from([3]),
inhibitors: Set::from([1]),
products: Set::from([1]),
},
Reaction {
reactants: Set::from([2]),
inhibitors: Set::default(),
products: Set::from([4]),
},
Reaction::from(
Set::from([1]),
Set::from([3]),
Set::from([3]),
),
Reaction::from(
Set::from([3]),
Set::from([1]),
Set::from([1]),
),
Reaction::from(
Set::from([2]),
Set::default(),
Set::from([4]),
),
]),
};
@ -283,3 +290,92 @@ fn traces_empty_env() {
assert_eq!(res.len(), 1);
assert_eq!(res[0].len(), 10);
}
#[test]
fn conversion_reactions() {
use std::rc::Rc;
use super::system::{System, PositiveSystem};
use super::environment::Environment;
use super::set::Set;
use super::process::Process;
use super::reaction::{Reaction, PositiveReaction};
use super::element::IdState::*;
let system = System {
delta: Rc::new(Environment::from([])),
available_entities: Set::from([1, 2]),
context_process: Process::Nill,
reaction_rules: Rc::new(vec![
Reaction::from(
Set::from([2]),
Set::from([1, 3]),
Set::from([5]),
),
Reaction::from(
Set::from([1, 2]),
Set::from([3]),
Set::from([5]),
),
]),
};
let converted_system: PositiveSystem = system.into();
let mut reactions = converted_system.reactions().clone();
reactions.sort_by(|a, b| a.products.cmp(&b.products)
.then(a.reactants.cmp(&b.reactants)));
assert_eq!(reactions,
vec![
PositiveReaction::from(
PositiveSet::from([(2, Positive), (3, Negative)]),
PositiveSet::from([(5, Positive)]),
),
PositiveReaction::from(
PositiveSet::from([(2, Negative)]),
PositiveSet::from([(5, Negative)]),
),
PositiveReaction::from(
PositiveSet::from([(3, Positive)]),
PositiveSet::from([(5, Negative)]),
),
]);
}
#[test]
fn conversion_entities() {
use std::rc::Rc;
use super::system::{System, PositiveSystem};
use super::environment::Environment;
use super::set::Set;
use super::process::Process;
use super::reaction::Reaction;
use super::element::IdState::*;
let system = System {
delta: Rc::new(Environment::from([])),
available_entities: Set::from([1, 2]),
context_process: Process::Nill,
reaction_rules: Rc::new(vec![
Reaction::from(
Set::from([2]),
Set::from([1, 3]),
Set::from([5]),
),
Reaction::from(
Set::from([1, 2]),
Set::from([3]),
Set::from([5]),
),
]),
};
let converted_system: PositiveSystem = system.into();
let entities = converted_system.available_entities().clone();
assert_eq!(entities,
PositiveSet::from([(1, Positive),
(2, Positive),
(3, Negative),
(5, Negative)
]));
}