From 25dfe9147d1d3cd767575c3ef06273f8dd94ad52 Mon Sep 17 00:00:00 2001 From: elvis Date: Mon, 22 Dec 2025 00:58:45 +0100 Subject: [PATCH] Boolean networks to Reaction Systems and Positive RS --- rsprocess/src/system.rs | 135 +++++++++++++++++++++++++++-------- rsprocess/src/system_test.rs | 89 ++++++++++++++++++++++- 2 files changed, 195 insertions(+), 29 deletions(-) diff --git a/rsprocess/src/system.rs b/rsprocess/src/system.rs index 9d1ef6a..3c903f4 100644 --- a/rsprocess/src/system.rs +++ b/rsprocess/src/system.rs @@ -774,6 +774,75 @@ impl System { } } +impl From for System { + fn from(value: BooleanNetwork) -> Self { + let reactions: Vec = { + let mut res = vec![]; + for (el, bf) in value.update_rules.iter() { + let bf_p = bf.remove_literals(); + let dnf_p = DNFBooleanFunction::from(bf_p.clone()); + + for conjunctive in dnf_p.formula { + let mut partial_r = vec![]; + let mut partial_i = vec![]; + let mut all_true = true; + let mut one_false = false; + + for l in conjunctive { + match l { + | DNFLiteral::False => { + one_false = true; + all_true = false; + break; + }, + | DNFLiteral::True => {}, + | DNFLiteral::Variable { positive, variable } => { + if positive { + partial_r.push(variable); + } else { + partial_i.push(variable); + } + all_true = false; + }, + } + } + if !one_false && !all_true { + res.push(Reaction::from( + Set::from(partial_r), + Set::from(partial_i), + Set::from([*el]), + )); + } else if all_true { + res.push(Reaction::from( + Set::default(), + Set::default(), + Set::from([*el]), + )); + } + } + } + res + }; + + Self::from( + Arc::new(Environment::default()), + Set::from_iter( + value + .initial_state + .iter() + .filter_map( + |(el, p)| + if *p { Some(*el) } else { None } + ) + .collect::>(), + ), + Process::default(), + Arc::new(reactions), + ) + } +} + + // ----------------------------------------------------------------------------- // Statistics // ----------------------------------------------------------------------------- @@ -1103,30 +1172,27 @@ impl From for PositiveSystem { for conjunctive in dnf_p.formula { let mut partial = vec![]; - let mut all_true = false; - for c in conjunctive { - match c { - | DNFLiteral::False => {}, - | DNFLiteral::True => { - res.push(PositiveReaction::from( - PositiveSet::default(), - PositiveSet::from([PositiveType::from(( - *el, - IdState::Positive, - ))]), - )); - all_true = true; + let mut all_true = true; + let mut one_false = false; + + for l in conjunctive { + match l { + | DNFLiteral::False => { + one_false = true; + all_true = false; break; }, + | DNFLiteral::True => {}, | DNFLiteral::Variable { positive, variable } => { partial.push(PositiveType::from(( variable, positive.into(), ))); + all_true = false; }, } } - if !all_true { + if !one_false && !all_true { res.push(PositiveReaction::from( PositiveSet::from(partial), PositiveSet::from([PositiveType::from(( @@ -1134,6 +1200,14 @@ impl From for PositiveSystem { IdState::Positive, ))]), )); + } else if all_true { + res.push(PositiveReaction::from( + PositiveSet::default(), + PositiveSet::from([PositiveType::from(( + *el, + IdState::Positive, + ))]), + )); } } let bf_n = @@ -1142,30 +1216,27 @@ impl From for PositiveSystem { for conjunctive in dnf_n.formula { let mut partial = vec![]; - let mut all_true = false; - for c in conjunctive { - match c { - | DNFLiteral::False => {}, - | DNFLiteral::True => { - res.push(PositiveReaction::from( - PositiveSet::default(), - PositiveSet::from([PositiveType::from(( - *el, - IdState::Negative, - ))]), - )); - all_true = true; + let mut all_true = true; + let mut one_false = false; + + for l in conjunctive { + match l { + | DNFLiteral::False => { + one_false = true; + all_true = false; break; }, + | DNFLiteral::True => {}, | DNFLiteral::Variable { positive, variable } => { partial.push(PositiveType::from(( variable, positive.into(), ))); + all_true = false; }, } } - if !all_true { + if !one_false && !all_true { res.push(PositiveReaction::from( PositiveSet::from(partial), PositiveSet::from([PositiveType::from(( @@ -1173,6 +1244,14 @@ impl From for PositiveSystem { IdState::Negative, ))]), )); + } else if all_true { + res.push(PositiveReaction::from( + PositiveSet::default(), + PositiveSet::from([PositiveType::from(( + *el, + IdState::Negative, + ))]), + )); } } } diff --git a/rsprocess/src/system_test.rs b/rsprocess/src/system_test.rs index 7edcc74..deb092a 100644 --- a/rsprocess/src/system_test.rs +++ b/rsprocess/src/system_test.rs @@ -363,7 +363,7 @@ fn slice_trace_2() { } #[test] -fn from_boolean_positive() { +fn from_boolean_positive_1() { let bn = BooleanNetwork { initial_state: BTreeMap::from([(1, true), (2, true), (3, true)]), update_rules: BTreeMap::from([ @@ -390,3 +390,90 @@ fn from_boolean_positive() { assert_eq!(rs.reaction_rules.len(), 8); } + +#[test] +fn from_boolean_positive_2() { + let bn = BooleanNetwork { + initial_state: BTreeMap::from([(1, true), (2, true), (3, true)]), + update_rules: BTreeMap::from([ + ( + 1, + BooleanFunction::Or( + Box::new(BooleanFunction::Not(Box::new( + BooleanFunction::Variable(1), + ))), + Box::new(BooleanFunction::And( + Box::new(BooleanFunction::True), + Box::new(BooleanFunction::Variable(3)), + )), + ), + ), + (2, BooleanFunction::True), + ( + 3, + BooleanFunction::Not(Box::new(BooleanFunction::Variable(2))), + ), + ]), + }; + let rs: PositiveSystem = bn.into(); + + assert_eq!(rs.reaction_rules.len(), 6); +} + +#[test] +fn from_boolean_1() { + let bn = BooleanNetwork { + initial_state: BTreeMap::from([(1, true), (2, true), (3, true)]), + update_rules: BTreeMap::from([ + ( + 1, + BooleanFunction::Or( + Box::new(BooleanFunction::Not(Box::new( + BooleanFunction::Variable(1), + ))), + Box::new(BooleanFunction::And( + Box::new(BooleanFunction::Variable(2)), + Box::new(BooleanFunction::Variable(3)), + )), + ), + ), + (2, BooleanFunction::Variable(3)), + ( + 3, + BooleanFunction::Not(Box::new(BooleanFunction::Variable(2))), + ), + ]), + }; + let rs: System = bn.into(); + + assert_eq!(rs.reaction_rules.len(), 4); +} + +#[test] +fn from_boolean_2() { + let bn = BooleanNetwork { + initial_state: BTreeMap::from([(1, true), (2, true), (3, true)]), + update_rules: BTreeMap::from([ + ( + 1, + BooleanFunction::Or( + Box::new(BooleanFunction::Not(Box::new( + BooleanFunction::Variable(1), + ))), + Box::new(BooleanFunction::And( + Box::new(BooleanFunction::True), + Box::new(BooleanFunction::Variable(3)), + )), + ), + ), + (2, BooleanFunction::True), + ( + 3, + BooleanFunction::Not(Box::new(BooleanFunction::Variable(2))), + ), + ]), + }; + let rs: System = bn.into(); + + assert_eq!(rs.reaction_rules.len(), 4); +}