From 478ca52816226a479e7c4c5ff3e9b0e61a18a931 Mon Sep 17 00:00:00 2001 From: elvis Date: Sun, 21 Dec 2025 17:16:51 +0100 Subject: [PATCH] Boolean network to positive system --- rsprocess/src/boolean.rs | 6 +- rsprocess/src/boolean_test.rs | 26 ++++--- rsprocess/src/element.rs | 10 +++ rsprocess/src/system.rs | 128 ++++++++++++++++++++++++++++++---- rsprocess/src/system_test.rs | 93 ++++++++++-------------- 5 files changed, 180 insertions(+), 83 deletions(-) diff --git a/rsprocess/src/boolean.rs b/rsprocess/src/boolean.rs index 6500172..5999b4e 100644 --- a/rsprocess/src/boolean.rs +++ b/rsprocess/src/boolean.rs @@ -38,7 +38,7 @@ impl BooleanFunction { | Self::False => Self::True, | Self::True => Self::False, | Self::Not(bf) => bf.remove_literals(), - | _ => bf.remove_literals(), + | _ => Self::Not(Box::new(bf.remove_literals())), }, | Self::Variable(i) => Self::Variable(*i), | Self::And(bf1, bf2) => match (&**bf1, &**bf2) { @@ -524,8 +524,8 @@ impl DNFBooleanFunction { #[derive(Default, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct BooleanNetwork { - initial_state: BTreeMap, - update_rules: BTreeMap, + pub initial_state: BTreeMap, + pub update_rules: BTreeMap, } impl BooleanNetwork { diff --git a/rsprocess/src/boolean_test.rs b/rsprocess/src/boolean_test.rs index c6078e6..80be17f 100644 --- a/rsprocess/src/boolean_test.rs +++ b/rsprocess/src/boolean_test.rs @@ -638,11 +638,11 @@ fn dnf_22() { let correct_results = [ true, true, false, true, true, true, true, true, false, false, false, - false, false, false, false, false, true, true, false, true, true, - true, true, true, true, true, false, true, true, true, true, true, - true, true, false, true, true, true, true, true, true, true, false, - true, true, true, true, true, true, true, false, true, true, true, - true, true, true, true, false, true, true, true, true, true + false, false, false, false, false, true, true, false, true, true, true, + true, true, true, true, false, true, true, true, true, true, true, + true, false, true, true, true, true, true, true, true, false, true, + true, true, true, true, true, true, false, true, true, true, true, + true, true, true, false, true, true, true, true, true, ]; for (assignment, res) in assignments.iter().zip(correct_results) { @@ -655,8 +655,10 @@ fn dnf_23() { let bf = boolean!(And((Or((Variable(0)), (Variable(1)))), (Variable(2)))); let cnf: DNFBooleanFunction = bf.into(); - assert_eq!(cnf.formula, [vec![dnfl!(true, 0), dnfl!(true, 2)], - vec![dnfl!(true, 1), dnfl!(true, 2)]]); + assert_eq!(cnf.formula, [vec![dnfl!(true, 0), dnfl!(true, 2)], vec![ + dnfl!(true, 1), + dnfl!(true, 2) + ]]); } #[test] @@ -672,7 +674,9 @@ fn dnf_25() { let bf = boolean!(Or((Variable(0)), (Or((Variable(1)), (Variable(2)))))); let cnf: DNFBooleanFunction = bf.into(); - assert_eq!(cnf.formula, [[dnfl!(true, 0)],[dnfl!(true, 1)],[dnfl!(true, 2)]]); + assert_eq!(cnf.formula, [[dnfl!(true, 0)], [dnfl!(true, 1)], [dnfl!( + true, 2 + )]]); } #[test] @@ -748,8 +752,10 @@ fn dnf_32() { let bf = boolean!(Not(Or((Variable(0)), (Not(Or((True), (False))))))); let cnf: DNFBooleanFunction = bf.into(); - assert_eq!(cnf.formula, [[dnfl!(false, 0), dnfl!(True)], - [dnfl!(false, 0), dnfl!(False)]]); + assert_eq!(cnf.formula, [[dnfl!(false, 0), dnfl!(True)], [ + dnfl!(false, 0), + dnfl!(False) + ]]); } #[test] diff --git a/rsprocess/src/element.rs b/rsprocess/src/element.rs index 1240cff..331c3df 100644 --- a/rsprocess/src/element.rs +++ b/rsprocess/src/element.rs @@ -59,6 +59,16 @@ impl std::ops::Not for IdState { } } +impl From for IdState { + fn from(value: bool) -> Self { + if value { + Self::Positive + } else { + Self::Negative + } + } +} + #[derive( Clone, Copy, diff --git a/rsprocess/src/system.rs b/rsprocess/src/system.rs index 8a67a0b..9d1ef6a 100644 --- a/rsprocess/src/system.rs +++ b/rsprocess/src/system.rs @@ -21,6 +21,10 @@ use super::set::{BasicSet, ExtensionsSet, PositiveSet, Set}; use super::trace::Trace; use super::transitions::TransitionsIterator; use super::translator::{Formatter, PrintableWithTranslator, Translator}; +use crate::boolean::{ + BooleanFunction, BooleanNetwork, DNFBooleanFunction, DNFLiteral, +}; +use crate::element::PositiveType; use crate::trace::{EnabledReactions, SlicingElement, SlicingTrace}; use crate::transitions::TraceIterator; @@ -1076,20 +1080,6 @@ 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) - // .to_positive_set(IdState::Negative); let negative_entities = value.products_elements().to_positive_set(IdState::Negative); let new_available_entities = @@ -1103,6 +1093,116 @@ impl From for PositiveSystem { } } +impl From for PositiveSystem { + 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 = 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; + break; + }, + | DNFLiteral::Variable { positive, variable } => { + partial.push(PositiveType::from(( + variable, + positive.into(), + ))); + }, + } + } + if !all_true { + res.push(PositiveReaction::from( + PositiveSet::from(partial), + PositiveSet::from([PositiveType::from(( + *el, + IdState::Positive, + ))]), + )); + } + } + let bf_n = + BooleanFunction::Not(Box::new(bf_p)).remove_literals(); + let dnf_n = DNFBooleanFunction::from(bf_n); + + 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; + break; + }, + | DNFLiteral::Variable { positive, variable } => { + partial.push(PositiveType::from(( + variable, + positive.into(), + ))); + }, + } + } + if !all_true { + res.push(PositiveReaction::from( + PositiveSet::from(partial), + PositiveSet::from([PositiveType::from(( + *el, + IdState::Negative, + ))]), + )); + } + } + } + res + }; + + Self::from( + Arc::new(PositiveEnvironment::default()), + PositiveSet::from_iter( + value + .initial_state + .iter() + .map(|el| { + ( + *el.0, + if *el.1 { + IdState::Positive + } else { + IdState::Negative + }, + ) + }) + .collect::>(), + ), + PositiveProcess::default(), + Arc::new(reactions), + ) + } +} + impl PositiveSystem { pub fn from( delta: Arc, diff --git a/rsprocess/src/system_test.rs b/rsprocess/src/system_test.rs index 9c31886..7edcc74 100644 --- a/rsprocess/src/system_test.rs +++ b/rsprocess/src/system_test.rs @@ -1,17 +1,16 @@ +use std::collections::BTreeMap; use std::sync::Arc; -use super::set::PositiveSet; -use super::system::BasicSystem; -use crate::system::ExtensionsSystem; +use super::element::{IdState, PositiveType}; +use super::environment::{Environment, PositiveEnvironment}; +use super::process::{PositiveProcess, Process}; +use super::reaction::{PositiveReaction, Reaction}; +use super::set::{BasicSet, PositiveSet, Set}; +use super::system::{BasicSystem, ExtensionsSystem, PositiveSystem, System}; +use crate::boolean::{BooleanFunction, BooleanNetwork}; #[test] fn one_transition() { - use super::environment::Environment; - use super::process::Process; - use super::reaction::Reaction; - use super::set::{BasicSet, Set}; - use super::system::{ExtensionsSystem, System}; - let system = System::from( Arc::new(Environment::default()), Set::from([1, 2]), @@ -41,13 +40,6 @@ fn one_transition() { #[test] fn one_transition_2() { - use super::element::{IdState, PositiveType}; - use super::environment::PositiveEnvironment; - use super::process::PositiveProcess; - use super::reaction::PositiveReaction; - use super::set::{BasicSet, PositiveSet}; - use super::system::{ExtensionsSystem, PositiveSystem}; - let system = PositiveSystem::from( Arc::new(PositiveEnvironment::default()), PositiveSet::from([ @@ -117,12 +109,6 @@ fn one_transition_2() { #[test] fn convertion() { - use super::environment::Environment; - use super::process::Process; - use super::reaction::Reaction; - use super::set::{BasicSet, Set}; - use super::system::{PositiveSystem, System}; - let system = System::from( Arc::new(Environment::default()), Set::from([1, 2]), @@ -145,12 +131,6 @@ fn convertion() { #[test] fn traces_1() { - use super::environment::Environment; - use super::process::Process; - use super::reaction::Reaction; - use super::set::Set; - use super::system::{ExtensionsSystem, System}; - let system = System::from( Arc::new(Environment::from([ (100, Process::WaitEntity { @@ -231,12 +211,6 @@ fn traces_1() { #[test] fn traces_empty_env() { - use super::environment::Environment; - use super::process::Process; - use super::reaction::Reaction; - use super::set::Set; - use super::system::{ExtensionsSystem, System}; - let system = System::from( Arc::new(Environment::from([])), Set::from([1, 2]), @@ -263,11 +237,6 @@ fn traces_empty_env() { #[test] fn conversion_reactions() { use super::element::IdState::*; - use super::environment::Environment; - use super::process::Process; - use super::reaction::{PositiveReaction, Reaction}; - use super::set::Set; - use super::system::{PositiveSystem, System}; let system = System::from( Arc::new(Environment::from([])), @@ -305,11 +274,6 @@ fn conversion_reactions() { #[test] fn conversion_entities() { use super::element::IdState::*; - use super::environment::Environment; - use super::process::Process; - use super::reaction::Reaction; - use super::set::Set; - use super::system::{PositiveSystem, System}; let system = System::from( Arc::new(Environment::from([])), @@ -331,12 +295,6 @@ fn conversion_entities() { #[test] fn slice_trace() { - use super::environment::Environment; - use super::process::Process; - use super::reaction::Reaction; - use super::set::Set; - use super::system::{PositiveSystem, System}; - let mut translator = crate::translator::Translator::new(); let mut tr = |a| translator.encode(a); @@ -368,12 +326,6 @@ fn slice_trace() { #[test] fn slice_trace_2() { - use super::environment::Environment; - use super::process::Process; - use super::reaction::Reaction; - use super::set::Set; - use super::system::{PositiveSystem, System}; - let mut translator = crate::translator::Translator::new(); let mut tr = |a| translator.encode(a); @@ -409,3 +361,32 @@ fn slice_trace_2() { assert_eq!(res_slice.systems, res_run); } + +#[test] +fn from_boolean_positive() { + 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: PositiveSystem = bn.into(); + + assert_eq!(rs.reaction_rules.len(), 8); +}