From 75c10dc3134f7c58419311a9768d8920385cdff3 Mon Sep 17 00:00:00 2001 From: elvis Date: Thu, 12 Jun 2025 16:23:39 +0200 Subject: [PATCH] Adding allTransitions --- src/main.rs | 76 +++++++++++++++- src/rsprocess/grammar.lalrpop | 9 +- src/rsprocess/structure.rs | 158 +++++++++++++++++++++++++++++++--- src/rsprocess/transitions.rs | 62 +++++++++++-- 4 files changed, 279 insertions(+), 26 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2a43499..f338f99 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,9 +31,79 @@ fn main() -> Result<(), Box> { // ------------------------------------------------------------------------- - let env = grammar::EnvironmentParser::new().parse("[x = {a}.{b}.x , y = ({a,c}.y + {b,c}.y)]").unwrap(); - let process = grammar::ContextParser::new().parse("[({a}.nil + x + y)]").unwrap(); + // let env = grammar::EnvironmentParser::new().parse("[x = {a}.{b}.x , y = ({a,c}.y + {b,c}.y)]").unwrap(); + // let process = grammar::ContextParser::new().parse("[({a}.nil + x + y)]").unwrap(); - println!("{:?}", rsprocess::transitions::unfold(&env, &process)); + // println!("{:?}", rsprocess::transitions::unfold(&env, &process)); + + // println!("--------------------"); + + // println!("{:?}", env); + + + // ------------------------------------------------------------------------- + // allTransitions(sys([],[a,b],[],[react([a],[c],[a]),react([b],[d],[b])]) , Moves). + + // let env = grammar::EnvironmentParser::new().parse("[]").unwrap(); + // let process = grammar::ContextParser::new().parse("[]").unwrap(); + + // let sys = rsprocess::structure::RSsystem::from(*env, + // rsprocess::structure::RSset::from(vec!["a", "b"]), + // *process, + // vec![ + // rsprocess::structure::RSreaction::from( + // rsprocess::structure::RSset::from(vec!["a"]), + // rsprocess::structure::RSset::from(vec!["c"]), + // rsprocess::structure::RSset::from(vec!["a"]) + // ), + // rsprocess::structure::RSreaction::from( + // rsprocess::structure::RSset::from(vec!["b"]), + // rsprocess::structure::RSset::from(vec!["d"]), + // rsprocess::structure::RSset::from(vec!["b"]) + // ) + // ]); + + + // println!("all_transitions: {:?}", rsprocess::transitions::all_transitions(&sys)); + // ------------------------------------------------------------------------- + // parse_ctx("[({a}.nil + {b}.nil)]",Ks) , allTransitions(sys([],[],Ks,[react([a],[c],[a]),react([b],[d],[b])]),Moves). + let env = grammar::EnvironmentParser::new().parse("[]").unwrap(); + let process = grammar::ContextParser::new().parse("[({a}.nil + {b}.nil)]").unwrap(); + + let sys = rsprocess::structure::RSsystem::from(*env, + rsprocess::structure::RSset::from(vec![]), + *process, + vec![ + rsprocess::structure::RSreaction::from( + rsprocess::structure::RSset::from(vec!["a"]), + rsprocess::structure::RSset::from(vec!["c"]), + rsprocess::structure::RSset::from(vec!["a"]) + ), + rsprocess::structure::RSreaction::from( + rsprocess::structure::RSset::from(vec!["b"]), + rsprocess::structure::RSset::from(vec!["d"]), + rsprocess::structure::RSset::from(vec!["b"]) + ) + ]); + + + println!("all_transitions: {:?}", rsprocess::transitions::all_transitions(&sys)); + + // ------------------------------------------------------------------------- + // use std::rc::Rc; + // let mut a = rsprocess::structure::RSChoices::from(vec![ + // (Rc::new(rsprocess::structure::RSset::from(vec!["a"])), + // Rc::new(rsprocess::structure::RSprocess::Nill)), + // ]); + + // let b = rsprocess::structure::RSChoices::from(vec![ + // (Rc::new(rsprocess::structure::RSset::from(vec!["b"])), + // Rc::new(rsprocess::structure::RSprocess::Nill)), + // ]); + + // a.shuffle(b); + // println!("shuffle: {:?}", a); + + println!("--------------------"); Ok(()) } diff --git a/src/rsprocess/grammar.lalrpop b/src/rsprocess/grammar.lalrpop index 35bc5c7..8104dc9 100644 --- a/src/rsprocess/grammar.lalrpop +++ b/src/rsprocess/grammar.lalrpop @@ -38,8 +38,13 @@ Set_of_entities: RSset<'input> = { // ----- ContextParser ----- pub Context: Box> = { - "[" "]" => Box::new(RSprocess::Nill), - "[" "]" => Box::new(t), + // "[" "]" => Box::new(RSprocess::Nill), + // "[" "]" => Box::new(t), + // "[" > "]" => + // Box::new(RSprocess::NondeterministicChoice{ children: t }) + + "[" "]" => Box::new(RSprocess::NondeterministicChoice{ children: vec![] }), + "[" "]" => Box::new(RSprocess::NondeterministicChoice{ children: vec![Rc::new(t)] }), "[" > "]" => Box::new(RSprocess::NondeterministicChoice{ children: t }) }; diff --git a/src/rsprocess/structure.rs b/src/rsprocess/structure.rs index bc7d917..d7a476c 100644 --- a/src/rsprocess/structure.rs +++ b/src/rsprocess/structure.rs @@ -43,7 +43,7 @@ impl<'a> RSset<'a> { } pub fn union(&self, b: &RSset<'a>) -> RSset<'a> { - // TODO maybe find more efficient way + // TODO maybe find more efficient way without copy/clone let mut ret: RSset = b.clone(); ret.identifiers.extend(self.identifiers.iter()); ret @@ -51,14 +51,27 @@ impl<'a> RSset<'a> { pub fn union_option(&self, b: Option<&RSset<'a>>) -> RSset<'a> { if let Some(b) = b { - // TODO maybe find more efficient way - let mut ret: RSset = b.clone(); - ret.identifiers.extend(self.identifiers.iter()); - ret + self.union(b) } else { self.clone() } } + + pub fn intersection(&self, b: &RSset<'a>) -> RSset<'a> { + // TODO maybe find more efficient way without copy/clone + let res: HashSet<_> = b.identifiers.intersection(&self.identifiers) + .copied() + .collect(); + RSset { identifiers: res } + } + + pub fn subtraction(&self, b: &RSset<'a>) -> RSset<'a> { + // TODO maybe find more efficient way without copy/clone + let res: HashSet<_> = self.identifiers.difference(&b.identifiers) + .copied() + .collect(); + RSset { identifiers: res } + } } @@ -94,6 +107,14 @@ impl<'a> RSreaction<'a> { self.products.clone() } + pub fn reactants(&self) -> &RSset<'a> { + &self.reactants + } + + pub fn inihibitors(&self) -> &RSset<'a> { + &self.inihibitors + } + pub fn products(&self) -> &RSset<'a> { &self.products } @@ -144,6 +165,10 @@ impl<'a> RSChoices<'a> { RSChoices{ context_moves: vec![] } } + pub fn new_not_empty() -> Self { + RSChoices{ context_moves: vec![(Rc::new(RSset::new()), Rc::new(RSprocess::Nill))] } + } + pub fn append(&mut self, a: &mut RSChoices<'a>) { self.context_moves.append(&mut a.context_moves); } @@ -156,21 +181,33 @@ impl<'a> RSChoices<'a> { } pub fn shuffle(&mut self, choices: RSChoices<'a>) { - if self.context_moves.is_empty() || choices.context_moves.is_empty() { - self.context_moves = vec![]; - } else { - let mut new_self = vec![]; - for item_self in &self.context_moves { - for item_choices in &choices.context_moves { - new_self.push((Rc::new(item_self.0.union(&item_choices.0)), - Rc::new(item_self.1.concat(&item_choices.1)))); + match (self.context_moves.is_empty(), choices.context_moves.is_empty()) { + (true, true) => {} + (true, false) => { self.context_moves = choices.context_moves } + (false, true) => {} + (false, false) => { + let mut new_self = vec![]; + for item_self in &self.context_moves { + for item_choices in &choices.context_moves { + new_self.push((Rc::new(item_self.0.union(&item_choices.0)), + Rc::new(item_self.1.concat(&item_choices.1)))); + } } + self.context_moves = new_self; } - self.context_moves = new_self; } } } +impl<'a> IntoIterator for RSChoices<'a> { + type Item = (Rc>, Rc>); + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.context_moves.into_iter() + } +} + impl<'a, const N: usize> From<[(Rc>, Rc>); N]> for RSChoices<'a> { fn from(arr: [(Rc>, Rc>); N]) -> Self { RSChoices{context_moves: arr.to_vec()} @@ -225,6 +262,99 @@ impl<'a> From)>> for RSenvironment<'a> { } } +// ----------------------------------------------------------------------------- +// RSsystem +// ----------------------------------------------------------------------------- +#[derive(Clone, Debug)] +pub struct RSsystem<'a> { + delta: RSenvironment<'a>, + available_entities: RSset<'a>, + context_process: RSprocess<'a>, + reaction_rules: Vec>, +} + +impl<'a> RSsystem<'a> { + pub fn new() -> RSsystem<'a> { + RSsystem { + delta: RSenvironment::new(), + available_entities: RSset::new(), + context_process: RSprocess::Nill, + reaction_rules: vec![], + } + } + + pub fn from(delta: RSenvironment<'a>, + available_entities: RSset<'a>, + context_process: RSprocess<'a>, + reaction_rules: Vec>) -> RSsystem<'a> { + RSsystem { delta, available_entities, context_process, reaction_rules } + } + + pub fn get_delta(&self) -> &RSenvironment<'a> { + &self.delta + } + + pub fn get_available_entities(&self) -> &RSset<'a> { + &self.available_entities + } + + pub fn get_context_process(&self) -> &RSprocess<'a> { + &self.context_process + } + + pub fn get_reaction_rules(&self) -> &Vec> { + &self.reaction_rules + } +} + +// ----------------------------------------------------------------------------- +// RSsystem +// ----------------------------------------------------------------------------- +#[derive(Clone, Debug)] +pub struct RSlabel<'a> { + available_entities: RSset<'a>, + c: RSset<'a>, /// TODO: what is c? what is t? (c comes from choices, t is + t: RSset<'a>, /// the union of available_entities and c) + reactants: RSset<'a>, + reactantsi: RSset<'a>, + inihibitors: RSset<'a>, + ireactants: RSset<'a>, + products: RSset<'a>, +} + +impl<'a> RSlabel<'a> { + pub fn new() -> Self { + RSlabel { available_entities: RSset::new(), + c: RSset::new(), + t: RSset::new(), + reactants: RSset::new(), + reactantsi: RSset::new(), + inihibitors: RSset::new(), + ireactants: RSset::new(), + products: RSset::new() } + } + + #[allow(clippy::too_many_arguments)] + pub fn from(available_entities: RSset<'a>, + c: RSset<'a>, + t: RSset<'a>, + reactants: RSset<'a>, + reactantsi: RSset<'a>, + inihibitors: RSset<'a>, + ireactants: RSset<'a>, + products: RSset<'a>,) -> Self { + RSlabel { available_entities, + c, + t, + reactants, + reactantsi, + inihibitors, + ireactants, + products } + } +} + + // ----------------------------------------------------------------------------- // RSassertOp // ----------------------------------------------------------------------------- diff --git a/src/rsprocess/transitions.rs b/src/rsprocess/transitions.rs index cc48852..df25d27 100644 --- a/src/rsprocess/transitions.rs +++ b/src/rsprocess/transitions.rs @@ -1,7 +1,8 @@ #![allow(dead_code)] use std::rc::Rc; -use super::structure::{RSChoices, RSenvironment, RSprocess}; +use super::structure::{RSset, RSChoices, RSenvironment, RSprocess, RSsystem, RSlabel}; + pub fn unfold<'a>(environment: &'a RSenvironment<'a>, context_process: &'a RSprocess<'a>) -> Result, String> { match context_process { @@ -47,12 +48,59 @@ pub fn unfold<'a>(environment: &'a RSenvironment<'a>, context_process: &'a RSpro }, RSprocess::NondeterministicChoice{children} => { // short-circuits with try_fold. - children.iter().try_fold(RSChoices::new(), |mut acc, x| { - match unfold(environment, x) { - Ok(choices) => {acc.shuffle(choices); Ok(acc)}, - Err(e) => Err(e) - } - }) + if children.is_empty() { + Ok(RSChoices::from(vec![(Rc::new(RSset::new()), Rc::new(RSprocess::Nill))])) + } else { + children.iter().try_fold(RSChoices::new(), |mut acc, x| { + acc.shuffle(unfold(environment, x)?); + Ok(acc) + }) + } } } } + +pub fn all_transitions<'a>(system: &'a RSsystem<'a>) -> Result, RSsystem<'a>)>, String> { + let choices = unfold(system.get_delta(), system.get_context_process())?; + println!("choices: {:?}", choices); + println!("\n\n"); + let mut results = vec![]; + + for choice in choices { + let t = system.get_available_entities().union(choice.0.as_ref()); + let (reactants, reactantsi, inihibitors, ireactants, products) + = system.get_reaction_rules().iter() + .fold((RSset::new(), RSset::new(), RSset::new(), RSset::new(), RSset::new()), + |acc, reaction| if reaction.enabled(&t) { + (acc.0.union(reaction.reactants()), + acc.1, + acc.2.union(reaction.inihibitors()), + acc.3, + acc.4.union(reaction.products())) + } else { + (acc.0, + acc.1.union(&reaction.inihibitors().intersection(&t)), + acc.2, + acc.3.union(&reaction.reactants().subtraction(&t)), + acc.4) + } + + ); + + let label = RSlabel::from(system.get_available_entities().clone(), + (*choice.0).clone(), + t, + reactants, + reactantsi, + inihibitors, + ireactants, + products.clone()); + let new_system = RSsystem::from(system.get_delta().clone(), + products, + (*choice.1).clone(), + system.get_reaction_rules().clone()); + results.push((label, new_system)) + } + + Ok(results) +}