diff --git a/src/main.rs b/src/main.rs index 3e07f37..2a43499 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,21 +12,28 @@ fn main() -> Result<(), Box> { // let result = grammar::SetParser::new().parse(&buffer).unwrap(); - let reactants = grammar::SetParser::new().parse("{a}").unwrap(); - let inihibitors = grammar::SetParser::new().parse("{c}").unwrap(); - let products = grammar::SetParser::new().parse("{a,c}").unwrap(); + // ------------------------------------------------------------------------- + // let reactants = grammar::SetParser::new().parse("{a}").unwrap(); + // let inihibitors = grammar::SetParser::new().parse("{c}").unwrap(); + // let products = grammar::SetParser::new().parse("{a,c}").unwrap(); - let process1 = rsprocess::structure::RSreaction::from(reactants, inihibitors, products); + // let process1 = rsprocess::structure::RSreaction::from(reactants, inihibitors, products); - let reactants = grammar::SetParser::new().parse("{b}").unwrap(); - let inihibitors = grammar::SetParser::new().parse("{c}").unwrap(); - let products = grammar::SetParser::new().parse("{b,c}").unwrap(); + // let reactants = grammar::SetParser::new().parse("{b}").unwrap(); + // let inihibitors = grammar::SetParser::new().parse("{c}").unwrap(); + // let products = grammar::SetParser::new().parse("{b,c}").unwrap(); - let process2 = rsprocess::structure::RSreaction::from(reactants, inihibitors, products); + // let process2 = rsprocess::structure::RSreaction::from(reactants, inihibitors, products); - let current_state = grammar::SetParser::new().parse("{b}").unwrap(); + // let current_state = grammar::SetParser::new().parse("{b}").unwrap(); - println!("{:?}", rsprocess::classical::compute_all(¤t_state, vec![&process1, &process2])); + // println!("{:?}", rsprocess::classical::compute_all(¤t_state, vec![&process1, &process2])); + + // ------------------------------------------------------------------------- + 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)); Ok(()) } diff --git a/src/rsprocess/classical.rs b/src/rsprocess/classical.rs index f56b793..1355325 100644 --- a/src/rsprocess/classical.rs +++ b/src/rsprocess/classical.rs @@ -4,6 +4,7 @@ //! Reaction System (RS) Framework. //! The data is held in RSset or RSreaction, in the latter the reagents, //! inhibitors and products are held. +#![allow(dead_code)] use super::structure::{RSset, RSreaction}; diff --git a/src/rsprocess/grammar.lalrpop b/src/rsprocess/grammar.lalrpop index e77030f..35bc5c7 100644 --- a/src/rsprocess/grammar.lalrpop +++ b/src/rsprocess/grammar.lalrpop @@ -1,3 +1,4 @@ +use std::rc::Rc; use std::str::FromStr; use lalrpop_util::ParseError; use crate::rsprocess::structure::{RSset, RSprocess, RSenvironment, RSassert, RSassertOp, RSBHML}; @@ -39,23 +40,27 @@ Set_of_entities: RSset<'input> = { pub Context: Box> = { "[" "]" => Box::new(RSprocess::Nill), "[" "]" => Box::new(t), - "[" > "]" => + "[" > "]" => Box::new(RSprocess::NondeterministicChoice{ children: t }) }; +Boxed_CTX_process: Rc> = { + => Rc::new(t) +} + CTX_process: RSprocess<'input> = { "." => - RSprocess::EntitySet{ entities: c, next_process: Box::new(k) }, + RSprocess::EntitySet{ entities: c, next_process: Rc::new(k) }, "(" ")" => k, "(" > ")" => RSprocess::Summation{ children: k }, "<" ">" "." => RSprocess::WaitEntity{ repeat: n, - repeated_process: Box::new(k1), - next_process: Box::new(k)}, + repeated_process: Rc::new(k1), + next_process: Rc::new(k)}, "nil" => RSprocess::Nill, => - RSprocess::ConstantIdentifier{ identifier } + RSprocess::RecursiveIdentifier{ identifier } }; // ----- EnvironmentParser ----- @@ -64,8 +69,8 @@ pub Environment: Box> = { "[" > "]" => Box::new(RSenvironment::from(t)) }; -Env_term: (&'input str, Box>) = { - "=" => (identifier, Box::new(k)) +Env_term: (&'input str, RSprocess<'input>) = { + "=" => (identifier, k) }; // ----- AssertParser ----- diff --git a/src/rsprocess/mod.rs b/src/rsprocess/mod.rs index 79a78c9..19a7a5a 100644 --- a/src/rsprocess/mod.rs +++ b/src/rsprocess/mod.rs @@ -1,2 +1,3 @@ pub mod structure; pub mod classical; +pub mod transitions; diff --git a/src/rsprocess/structure.rs b/src/rsprocess/structure.rs index e6232be..bc7d917 100644 --- a/src/rsprocess/structure.rs +++ b/src/rsprocess/structure.rs @@ -1,10 +1,12 @@ -use std::collections::{BTreeMap, HashSet}; +#![allow(dead_code)] + +use std::collections::{HashMap, HashSet}; +use std::rc::Rc; // ----------------------------------------------------------------------------- // RSset // ----------------------------------------------------------------------------- #[derive(Clone, Debug)] -#[allow(dead_code)] pub struct RSset<'a> { identifiers: HashSet<&'a str> } @@ -40,7 +42,6 @@ impl<'a> RSset<'a> { self.identifiers.is_disjoint(&b.identifiers) } - #[allow(dead_code)] pub fn union(&self, b: &RSset<'a>) -> RSset<'a> { // TODO maybe find more efficient way let mut ret: RSset = b.clone(); @@ -65,7 +66,6 @@ impl<'a> RSset<'a> { // RSreaction // ----------------------------------------------------------------------------- #[derive(Clone, Debug)] -#[allow(dead_code)] pub struct RSreaction<'a> { reactants: RSset<'a>, inihibitors: RSset<'a>, @@ -73,7 +73,6 @@ pub struct RSreaction<'a> { } impl<'a> RSreaction<'a> { - #[allow(dead_code)] pub fn new() -> Self { RSreaction{ reactants: RSset::new(), inihibitors: RSset::new(), @@ -91,7 +90,6 @@ impl<'a> RSreaction<'a> { && self.inihibitors.is_disjoint(current_state) } - #[allow(dead_code)] pub fn products_clone(&self) -> RSset<'a> { self.products.clone() } @@ -107,47 +105,123 @@ impl<'a> RSreaction<'a> { // RSprocess // ----------------------------------------------------------------------------- #[derive(Clone, Debug)] -#[allow(dead_code)] pub enum RSprocess<'a> { Nill, - ConstantIdentifier{identifier: &'a str}, - EntitySet{entities: RSset<'a>, next_process: Box>}, - WaitEntity{repeat: i64, repeated_process: Box>, next_process: Box>}, - NondeterministicChoice{children: Vec>}, - Summation{children: Vec>} + RecursiveIdentifier{identifier: &'a str}, + EntitySet{entities: RSset<'a>, next_process: Rc>}, + WaitEntity{repeat: i64, repeated_process: Rc>, next_process: Rc>}, + Summation{children: Vec>}, + NondeterministicChoice{children: Vec>>} } +impl<'a> RSprocess<'a> { + // TODO: remove all the clone() + pub fn concat(&self, new: &RSprocess<'a>) -> RSprocess<'a>{ + match (self, new) { + (RSprocess::NondeterministicChoice{children: c1}, RSprocess::NondeterministicChoice{children: c2}) => { + RSprocess::NondeterministicChoice { children: [c1.clone(), c2.clone()].concat() } + }, + (RSprocess::NondeterministicChoice{children}, new) | + (new, RSprocess::NondeterministicChoice{children}) => { + let mut new_children = children.clone(); + new_children.push(Rc::new(new.clone())); + RSprocess::NondeterministicChoice{ children: new_children } + }, + (_, _) => { + RSprocess::NondeterministicChoice { children: vec![Rc::new(self.clone()), Rc::new(new.clone())] } + } + } + } +} + +#[derive(Clone, Debug)] +pub struct RSChoices<'a> { + context_moves: Vec<(Rc>, Rc>)> +} + +impl<'a> RSChoices<'a> { + pub fn new() -> Self { + RSChoices{ context_moves: vec![] } + } + + pub fn append(&mut self, a: &mut RSChoices<'a>) { + self.context_moves.append(&mut a.context_moves); + } + + pub fn replace(&mut self, a: Rc>) { + self.context_moves = + self.context_moves + .iter_mut() + .map(|(c1, _)| (Rc::clone(c1), Rc::clone(&a))).collect::>(); + } + + 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)))); + } + } + self.context_moves = new_self; + } + } +} + +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()} + } +} + +impl<'a> From<&[(Rc>, Rc>)]> for RSChoices<'a> { + fn from(arr: &[(Rc>, Rc>)]) -> Self { + RSChoices{context_moves: arr.to_vec()} + } +} + +impl<'a> From>, Rc>)>> for RSChoices<'a> { + fn from(arr: Vec<(Rc>, Rc>)>) -> Self { + RSChoices{context_moves: arr} + } +} // ----------------------------------------------------------------------------- // RSenvironment // ----------------------------------------------------------------------------- #[derive(Clone, Debug)] -#[allow(dead_code)] pub struct RSenvironment<'a> { - definitions: BTreeMap<&'a str, Box>>, + definitions: HashMap<&'a str, RSprocess<'a>>, } impl<'a> RSenvironment<'a> { pub fn new() -> RSenvironment<'a> { - RSenvironment{definitions: BTreeMap::new()} + RSenvironment{definitions: HashMap::new()} + } + + pub fn get(&self, k: &'a str) -> Option<&RSprocess<'a>> { + self.definitions.get(k) } } -impl<'a, const N: usize> From<[(&'a str, Box>); N]> for RSenvironment<'a> { - fn from(arr: [(&'a str, Box>); N]) -> Self { - RSenvironment{definitions: BTreeMap::from(arr)} +impl<'a, const N: usize> From<[(&'a str, RSprocess<'a>); N]> for RSenvironment<'a> { + fn from(arr: [(&'a str, RSprocess<'a>); N]) -> Self { + RSenvironment{definitions: HashMap::from(arr)} } } -impl<'a> From<&[(&'a str, Box>)]> for RSenvironment<'a> { - fn from(arr: &[(&'a str, Box>)]) -> Self { - RSenvironment{definitions: BTreeMap::from_iter(arr.to_vec())} +impl<'a> From<&[(&'a str, RSprocess<'a>)]> for RSenvironment<'a> { + fn from(arr: &[(&'a str, RSprocess<'a>)]) -> Self { + RSenvironment{definitions: HashMap::from_iter(arr.to_vec())} } } -impl<'a> From>)>> for RSenvironment<'a> { - fn from(arr: Vec<(&'a str, Box>)>) -> Self { - RSenvironment{definitions: BTreeMap::from_iter(arr)} +impl<'a> From)>> for RSenvironment<'a> { + fn from(arr: Vec<(&'a str, RSprocess<'a>)>) -> Self { + RSenvironment{definitions: HashMap::from_iter(arr)} } } @@ -155,7 +229,6 @@ impl<'a> From>)>> for RSenvironment<'a> { // RSassertOp // ----------------------------------------------------------------------------- #[derive(Clone, Debug)] -#[allow(dead_code)] pub enum RSassertOp { InW, InR, @@ -167,7 +240,6 @@ pub enum RSassertOp { // RSassert // ----------------------------------------------------------------------------- #[derive(Clone, Debug)] -#[allow(dead_code)] pub enum RSassert<'a> { Not(Box>), Xor(Box>, Box>), @@ -181,7 +253,6 @@ pub enum RSassert<'a> { // RSBHML // ----------------------------------------------------------------------------- #[derive(Clone, Debug)] -#[allow(dead_code)] #[allow(clippy::upper_case_acronyms)] pub enum RSBHML<'a> { True, diff --git a/src/rsprocess/transitions.rs b/src/rsprocess/transitions.rs new file mode 100644 index 0000000..cc48852 --- /dev/null +++ b/src/rsprocess/transitions.rs @@ -0,0 +1,58 @@ +#![allow(dead_code)] + +use std::rc::Rc; +use super::structure::{RSChoices, RSenvironment, RSprocess}; + +pub fn unfold<'a>(environment: &'a RSenvironment<'a>, context_process: &'a RSprocess<'a>) -> Result, String> { + match context_process { + RSprocess::Nill => Ok(RSChoices::new()), + RSprocess::RecursiveIdentifier{identifier} => { + let newprocess = environment.get(identifier); + if let Some(newprocess) = newprocess { + unfold(environment, newprocess) + } else { + Err(format!("Recursive call to missing symbol: {identifier}")) + } + }, + RSprocess::EntitySet{entities, next_process} => { + Ok(RSChoices::from(vec![(Rc::new(entities.clone()), Rc::clone(next_process))])) + }, + RSprocess::WaitEntity{repeat, repeated_process: _, next_process} if *repeat <= 0 => { + unfold(environment, next_process) + }, + RSprocess::WaitEntity{repeat, repeated_process, next_process} if *repeat == 1 => { + let mut choices1 = unfold(environment, repeated_process)?; + choices1.replace(Rc::clone(next_process)); + Ok(choices1) + }, + RSprocess::WaitEntity{repeat, repeated_process, next_process} => { + let mut choices1 = unfold(environment, repeated_process)?; + choices1.replace( + Rc::new( + RSprocess::WaitEntity{ repeat: (*repeat - 1), + repeated_process: Rc::clone(repeated_process), + next_process: Rc::clone(next_process) } + ) + ); + Ok(choices1) + }, + RSprocess::Summation{children} => { + // short-circuits with try_fold. + children.iter().try_fold(RSChoices::new(), |mut acc, x| { + match unfold(environment, x) { + Ok(mut choices) => {acc.append(&mut choices); Ok(acc)}, + Err(e) => Err(e) + } + }) + }, + 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) + } + }) + } + } +}