From 91f69c9e6d7b1f9df128d2b6151faebfa85d41f0 Mon Sep 17 00:00:00 2001 From: elvis Date: Wed, 10 Sep 2025 22:41:40 +0200 Subject: [PATCH] rustfmt and now grouping working --- .rustfmt.toml | 1 + build.rs | 2 +- src/rsprocess/assert/dsl.rs | 275 +++-- src/rsprocess/assert/fmt.rs | 138 ++- src/rsprocess/assert/mod.rs | 6 +- src/rsprocess/assert/rsassert.rs | 96 +- src/rsprocess/assert/tests.rs | 176 +-- .../bisimilarity_kanellakis_smolka.rs | 12 +- .../bisimilarity/bisimilarity_paige_tarkan.rs | 113 +- .../bisimilarity/test_paige_tarjan.rs | 4 +- src/rsprocess/choices.rs | 20 +- src/rsprocess/dot.rs | 42 +- src/rsprocess/element.rs | 36 +- src/rsprocess/environment.rs | 177 ++- src/rsprocess/format_helpers.rs | 89 +- src/rsprocess/frequency.rs | 62 +- src/rsprocess/grammar.lalrpop | 1048 ++++++++++------- src/rsprocess/graph.rs | 216 +++- src/rsprocess/label.rs | 46 +- src/rsprocess/presets.rs | 224 +++- src/rsprocess/process.rs | 79 +- src/rsprocess/reaction.rs | 63 +- src/rsprocess/serialize.rs | 4 +- src/rsprocess/set.rs | 104 +- src/rsprocess/set_test.rs | 7 +- src/rsprocess/system.rs | 168 ++- src/rsprocess/system_test.rs | 182 ++- src/rsprocess/transitions.rs | 137 ++- src/rsprocess/translator.rs | 6 +- testing/examples/digraph.system | 23 +- 30 files changed, 2368 insertions(+), 1188 deletions(-) create mode 100644 .rustfmt.toml diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..5c8d931 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1 @@ +max_width = 80 \ No newline at end of file diff --git a/build.rs b/build.rs index ca5c283..7e68f91 100644 --- a/build.rs +++ b/build.rs @@ -1,3 +1,3 @@ fn main() { - lalrpop::process_root().unwrap(); + lalrpop::process_src().unwrap(); } diff --git a/src/rsprocess/assert/dsl.rs b/src/rsprocess/assert/dsl.rs index c8d1d52..f8b0cc9 100644 --- a/src/rsprocess/assert/dsl.rs +++ b/src/rsprocess/assert/dsl.rs @@ -31,7 +31,12 @@ pub enum Variable { /// Trait needed for special variables. pub(super) trait SpecialVariables: - translator::PrintableWithTranslator + std::fmt::Debug + Sized + Eq + Copy + std::hash::Hash + translator::PrintableWithTranslator + + std::fmt::Debug + + Sized + + Eq + + Copy + + std::hash::Hash { /// Returns the type of the specific special variable. fn type_of(&self) -> AssertionTypes; @@ -40,7 +45,8 @@ pub(super) trait SpecialVariables: fn type_qualified(&self, q: &Qualifier) -> Result; /// Creates a new context. - fn new_context(input: HashMap) -> HashMap; + fn new_context(input: HashMap) + -> HashMap; /// Returns true if fn correct_type(&self, other: &AssertReturnValue) -> bool; @@ -188,7 +194,10 @@ pub enum AssertReturnValue { // ----------------------------------------------------------------------------- impl QualifierRestricted { - pub(super) fn referenced_mut<'a>(&self, label: &'a mut label::Label) -> &'a mut set::Set { + pub(super) fn referenced_mut<'a>( + &self, + label: &'a mut label::Label, + ) -> &'a mut set::Set { match self { Self::Entities => &mut label.available_entities, Self::Context => &mut label.context, @@ -200,7 +209,10 @@ impl QualifierRestricted { } } - pub(super) fn referenced<'a>(&self, label: &'a label::Label) -> &'a set::Set { + pub(super) fn referenced<'a>( + &self, + label: &'a label::Label, + ) -> &'a set::Set { match self { Self::Entities => &label.available_entities, Self::Context => &label.context, @@ -220,13 +232,15 @@ impl QualifierRestricted { impl QualifierLabel { pub(super) fn get(&self, l: &label::Label) -> AssertReturnValue { match self { - QualifierLabel::AvailableEntities => AssertReturnValue::Set(l.t.clone()), + QualifierLabel::AvailableEntities => { + AssertReturnValue::Set(l.t.clone()) + } QualifierLabel::AllReactants => { AssertReturnValue::Set(l.reactants.union(&l.reactants_absent)) } - QualifierLabel::AllInhibitors => { - AssertReturnValue::Set(l.inhibitors.union(&l.inhibitors_present)) - } + QualifierLabel::AllInhibitors => AssertReturnValue::Set( + l.inhibitors.union(&l.inhibitors_present), + ), } } } @@ -234,8 +248,12 @@ impl QualifierLabel { impl QualifierSystem { pub(super) fn get(&self, l: &system::System) -> AssertReturnValue { match self { - Self::Context => AssertReturnValue::Context(l.context_process.clone()), - Self::Entities => AssertReturnValue::Set(l.available_entities.clone()), + Self::Context => { + AssertReturnValue::Context(l.context_process.clone()) + } + Self::Entities => { + AssertReturnValue::Set(l.available_entities.clone()) + } } } } @@ -244,7 +262,11 @@ impl Unary { pub(super) fn is_prefix(&self) -> bool { match self { Self::Not | Self::Rand => true, - Self::Empty | Self::Length | Self::ToStr | Self::Qualifier(_) | Self::ToEl => false, + Self::Empty + | Self::Length + | Self::ToStr + | Self::Qualifier(_) + | Self::ToEl => false, } } @@ -252,42 +274,72 @@ impl Unary { !self.is_prefix() } - pub(super) fn associate(&self, type_exp: &AssertionTypes) -> Result { + pub(super) fn associate( + &self, + type_exp: &AssertionTypes, + ) -> Result { match (self, type_exp) { (Self::Not, AssertionTypes::Boolean) => Ok(AssertionTypes::Boolean), - (Self::Rand, AssertionTypes::Integer) => Ok(AssertionTypes::Integer), + (Self::Rand, AssertionTypes::Integer) => { + Ok(AssertionTypes::Integer) + } (Self::Empty, AssertionTypes::Set) => Ok(AssertionTypes::Boolean), - (Self::Length, AssertionTypes::Set) | (Self::Length, AssertionTypes::String) => { + (Self::Length, AssertionTypes::Set) + | (Self::Length, AssertionTypes::String) => { Ok(AssertionTypes::Integer) } (Self::ToStr, AssertionTypes::Boolean) | (Self::ToStr, AssertionTypes::Element) - | (Self::ToStr, AssertionTypes::Integer) => Ok(AssertionTypes::String), + | (Self::ToStr, AssertionTypes::Integer) => { + Ok(AssertionTypes::String) + } (Self::Qualifier(Qualifier::Label(_)), AssertionTypes::Label) => { Ok(AssertionTypes::Set) } - (Self::Qualifier(Qualifier::Restricted(_)), AssertionTypes::Label) => { - Ok(AssertionTypes::Set) - } + ( + Self::Qualifier(Qualifier::Restricted(_)), + AssertionTypes::Label, + ) => Ok(AssertionTypes::Set), (Self::ToEl, AssertionTypes::String) => Ok(AssertionTypes::Element), - (Self::Qualifier(Qualifier::Edge(_)), AssertionTypes::Edge) => Ok(AssertionTypes::Node), - (Self::Qualifier(Qualifier::Node(QualifierNode::Neighbours)), AssertionTypes::Node) => { - Ok(AssertionTypes::RangeNeighbours) + (Self::Qualifier(Qualifier::Edge(_)), AssertionTypes::Edge) => { + Ok(AssertionTypes::Node) } + ( + Self::Qualifier(Qualifier::Node(QualifierNode::Neighbours)), + AssertionTypes::Node, + ) => Ok(AssertionTypes::RangeNeighbours), ( Self::Qualifier(Qualifier::System(QualifierSystem::Entities)), AssertionTypes::System, ) => Ok(AssertionTypes::Set), + ( + Self::Qualifier(Qualifier::Restricted( + QualifierRestricted::Entities, + )), + AssertionTypes::System, + ) + | ( + Self::Qualifier(Qualifier::Restricted( + QualifierRestricted::Context, + )), + AssertionTypes::System, + ) => Err(format!( + "Expression has incompatible type with operation: type \ + system with operation \"{self:?}\" (be sure to use \ + \".SystemEntities\" and \".SystemContext\" to refer to \ + the system fields)." + )), ( Self::Qualifier(Qualifier::System(QualifierSystem::Context)), AssertionTypes::System, ) => Ok(AssertionTypes::Context), - (Self::Qualifier(Qualifier::Node(QualifierNode::System)), AssertionTypes::Node) => { - Ok(AssertionTypes::System) - } + ( + Self::Qualifier(Qualifier::Node(QualifierNode::System)), + AssertionTypes::Node, + ) => Ok(AssertionTypes::System), (op, type_exp) => Err(format!( - "Expression has incompatible type with operation: \ - {type_exp:?} with operation {op:?}." + "Expression has incompatible type with operation: type \ + {type_exp:?} with operation \"{op:?}\"." )), } } @@ -355,14 +407,24 @@ impl Binary { (Self::Xor, AssertionTypes::Boolean, AssertionTypes::Boolean) => { Ok(AssertionTypes::Boolean) } - (Self::Xor, AssertionTypes::Set, AssertionTypes::Set) => Ok(AssertionTypes::Set), + (Self::Xor, AssertionTypes::Set, AssertionTypes::Set) => { + Ok(AssertionTypes::Set) + } (Self::Less, AssertionTypes::Integer, AssertionTypes::Integer) | (Self::Less, AssertionTypes::Set, AssertionTypes::Set) - | (Self::LessEq, AssertionTypes::Integer, AssertionTypes::Integer) + | ( + Self::LessEq, + AssertionTypes::Integer, + AssertionTypes::Integer, + ) | (Self::LessEq, AssertionTypes::Set, AssertionTypes::Set) | (Self::More, AssertionTypes::Integer, AssertionTypes::Integer) | (Self::More, AssertionTypes::Set, AssertionTypes::Set) - | (Self::MoreEq, AssertionTypes::Integer, AssertionTypes::Integer) + | ( + Self::MoreEq, + AssertionTypes::Integer, + AssertionTypes::Integer, + ) | (Self::MoreEq, AssertionTypes::Set, AssertionTypes::Set) => { Ok(AssertionTypes::Boolean) } @@ -387,12 +449,24 @@ impl Binary { } (Self::Plus, AssertionTypes::Set, AssertionTypes::Set) | (Self::Minus, AssertionTypes::Set, AssertionTypes::Set) - | (Self::Times, AssertionTypes::Set, AssertionTypes::Set) => Ok(AssertionTypes::Set), - (Self::Exponential, AssertionTypes::Integer, AssertionTypes::Integer) - | (Self::Quotient, AssertionTypes::Integer, AssertionTypes::Integer) - | (Self::Reminder, AssertionTypes::Integer, AssertionTypes::Integer) => { - Ok(AssertionTypes::Integer) + | (Self::Times, AssertionTypes::Set, AssertionTypes::Set) => { + Ok(AssertionTypes::Set) } + ( + Self::Exponential, + AssertionTypes::Integer, + AssertionTypes::Integer, + ) + | ( + Self::Quotient, + AssertionTypes::Integer, + AssertionTypes::Integer, + ) + | ( + Self::Reminder, + AssertionTypes::Integer, + AssertionTypes::Integer, + ) => Ok(AssertionTypes::Integer), (Self::Concat, AssertionTypes::String, AssertionTypes::String) => { Ok(AssertionTypes::String) } @@ -403,9 +477,11 @@ impl Binary { | (Self::Max, AssertionTypes::Integer, AssertionTypes::Integer) => { Ok(AssertionTypes::Integer) } - (Self::CommonSubStr, AssertionTypes::String, AssertionTypes::String) => { - Ok(AssertionTypes::String) - } + ( + Self::CommonSubStr, + AssertionTypes::String, + AssertionTypes::String, + ) => Ok(AssertionTypes::String), _ => Err(format!( "Expressions have incompatible types: {t1:?} and \ {t2:?} with operation {self:?}." @@ -421,7 +497,11 @@ impl AssertReturnValue { val: AssertReturnValue, ) -> Result<(), String> { match (self, q, val) { - (Self::Label(l), Qualifier::Restricted(q), AssertReturnValue::Set(set)) => { + ( + Self::Label(l), + Qualifier::Restricted(q), + AssertReturnValue::Set(set), + ) => { *q.referenced_mut(l) = set; Ok(()) } @@ -493,16 +573,20 @@ impl TypeContext { trying to assign to qualification {q:?}, \ assign first a value." )), - std::collections::hash_map::Entry::Occupied(oe) => match (oe.get(), q, ty) { - (AssertionTypes::Label, Qualifier::Restricted(_), AssertionTypes::Set) => { - Ok(()) - } - (t, q, ty) => Err(format!( - "Variable {v:?} has type {t:?}, \ + std::collections::hash_map::Entry::Occupied(oe) => { + match (oe.get(), q, ty) { + ( + AssertionTypes::Label, + Qualifier::Restricted(_), + AssertionTypes::Set, + ) => Ok(()), + (t, q, ty) => Err(format!( + "Variable {v:?} has type {t:?}, \ but was assigned with qualifier \ {q:?} value with type {ty:?}." - )), - }, + )), + } + } }, (Variable::Special(s), None) => { if s.type_of() == ty { @@ -530,7 +614,11 @@ impl TypeContext { } } - fn assign_range(&mut self, v: &Variable, ty: AssertionTypes) -> Result<(), String> + fn assign_range( + &mut self, + v: &Variable, + ty: AssertionTypes, + ) -> Result<(), String> where S: SpecialVariables, { @@ -661,10 +749,12 @@ impl Context { "Variable {v:?} used, but no value \ assigned." )), - Variable::Special(s) => self.special.get(s).cloned().ok_or(format!( - "Variable {v:?} used but no value \ + Variable::Special(s) => { + self.special.get(s).cloned().ok_or(format!( + "Variable {v:?} used but no value \ assigned." - )), + )) + } } } } @@ -677,7 +767,9 @@ impl AssertReturnValue { graph: &graph::SystemGraph, ) -> Result { match (self, u) { - (AssertReturnValue::Boolean(b), Unary::Not) => Ok(AssertReturnValue::Boolean(!b)), + (AssertReturnValue::Boolean(b), Unary::Not) => { + Ok(AssertReturnValue::Boolean(!b)) + } (AssertReturnValue::Integer(i), Unary::Rand) => { Ok(AssertReturnValue::Integer(rand::random_range(0..i))) } @@ -699,15 +791,21 @@ impl AssertReturnValue { (AssertReturnValue::Integer(i), Unary::ToStr) => { Ok(AssertReturnValue::String(format!("{i}"))) } - (AssertReturnValue::Element(el), Unary::ToStr) => Ok(AssertReturnValue::String( - translator - .decode(el) - .ok_or(format!("Could not find element {el:?}."))?, - )), - (AssertReturnValue::Label(l), Unary::Qualifier(Qualifier::Label(q))) => Ok(q.get(&l)), - (AssertReturnValue::Label(l), Unary::Qualifier(Qualifier::Restricted(q))) => { - Ok(q.get(&l)) + (AssertReturnValue::Element(el), Unary::ToStr) => { + Ok(AssertReturnValue::String( + translator + .decode(el) + .ok_or(format!("Could not find element {el:?}."))?, + )) } + ( + AssertReturnValue::Label(l), + Unary::Qualifier(Qualifier::Label(q)), + ) => Ok(q.get(&l)), + ( + AssertReturnValue::Label(l), + Unary::Qualifier(Qualifier::Restricted(q)), + ) => Ok(q.get(&l)), (AssertReturnValue::String(s), Unary::ToEl) => { Ok(AssertReturnValue::Element(translator.encode(s))) } @@ -733,9 +831,10 @@ impl AssertReturnValue { ) => Ok(AssertReturnValue::System( graph.node_weight(node).unwrap().clone(), )), - (AssertReturnValue::System(sys), Unary::Qualifier(Qualifier::System(q))) => { - Ok(q.get(&sys)) - } + ( + AssertReturnValue::System(sys), + Unary::Qualifier(Qualifier::System(q)), + ) => Ok(q.get(&sys)), (val, u) => Err(format!( "Incompatible unary operation {u:?} on value \ {val:?}." @@ -758,11 +857,15 @@ impl AssertReturnValue { Set(s1.union(&s2).subtraction(&s1.intersection(&s2))) } (Binary::Less, Integer(i1), Integer(i2)) => Boolean(i1 < i2), - (Binary::Less, Set(s1), Set(s2)) => Boolean(s1.is_subset(&s2) && !s2.is_subset(&s1)), + (Binary::Less, Set(s1), Set(s2)) => { + Boolean(s1.is_subset(&s2) && !s2.is_subset(&s1)) + } (Binary::LessEq, Integer(i1), Integer(i2)) => Boolean(i1 <= i2), (Binary::LessEq, Set(s1), Set(s2)) => Boolean(s1.is_subset(&s2)), (Binary::More, Integer(i1), Integer(i2)) => Boolean(i1 > i2), - (Binary::More, Set(s1), Set(s2)) => Boolean(s2.is_subset(&s1) && !s1.is_subset(&s2)), + (Binary::More, Set(s1), Set(s2)) => { + Boolean(s2.is_subset(&s1) && !s1.is_subset(&s2)) + } (Binary::MoreEq, Integer(i1), Integer(i2)) => Boolean(i1 >= i2), (Binary::MoreEq, Set(s1), Set(s2)) => Boolean(s1.is_subset(&s2)), (Binary::Eq, Integer(i1), Integer(i2)) => Boolean(i1 == i2), @@ -780,9 +883,13 @@ impl AssertReturnValue { (Binary::Plus, Integer(i1), Integer(i2)) => Integer(i1 + i2), (Binary::Plus, Set(set1), Set(set2)) => Set(set1.union(&set2)), (Binary::Minus, Integer(i1), Integer(i2)) => Integer(i1 - i2), - (Binary::Minus, Set(set1), Set(set2)) => Set(set1.subtraction(&set2)), + (Binary::Minus, Set(set1), Set(set2)) => { + Set(set1.subtraction(&set2)) + } (Binary::Times, Integer(i1), Integer(i2)) => Integer(i1 * i2), - (Binary::Times, Set(set1), Set(set2)) => Set(set1.intersection(&set2)), + (Binary::Times, Set(set1), Set(set2)) => { + Set(set1.intersection(&set2)) + } (Binary::Exponential, Integer(i1), Integer(i2)) => { if i2 < 0 { Integer(0) @@ -790,8 +897,12 @@ impl AssertReturnValue { Integer(i1.pow(i2 as u32)) } } - (Binary::Quotient, Integer(i1), Integer(i2)) => Integer(i1.div_euclid(i2)), - (Binary::Reminder, Integer(i1), Integer(i2)) => Integer(i1.rem_euclid(i2)), + (Binary::Quotient, Integer(i1), Integer(i2)) => { + Integer(i1.div_euclid(i2)) + } + (Binary::Reminder, Integer(i1), Integer(i2)) => { + Integer(i1.rem_euclid(i2)) + } (Binary::Concat, String(s1), String(s2)) => String(s1 + &s2), (Binary::SubStr, String(s1), String(s2)) => { let mut len = s1.len() as i64; @@ -825,7 +936,10 @@ impl AssertReturnValue { } } -fn typecheck_helper(tree: &Tree, c: &mut TypeContext) -> Result +fn typecheck_helper( + tree: &Tree, + c: &mut TypeContext, +) -> Result where S: SpecialVariables, { @@ -880,7 +994,10 @@ where } } -pub(super) fn typecheck(tree: &Tree, c: &mut TypeContext) -> Result +pub(super) fn typecheck( + tree: &Tree, + c: &mut TypeContext, +) -> Result where S: SpecialVariables, { @@ -917,7 +1034,10 @@ where } } -fn typecheck_range(range: &Range, c: &mut TypeContext) -> Result +fn typecheck_range( + range: &Range, + c: &mut TypeContext, +) -> Result where S: SpecialVariables, { @@ -925,7 +1045,9 @@ where Range::IterateInRange(exp1, exp2) => { let type_exp1 = typecheck_expression(exp1, c)?; let type_exp2 = typecheck_expression(exp2, c)?; - if let (AssertionTypes::Integer, AssertionTypes::Integer) = (type_exp1, type_exp2) { + if let (AssertionTypes::Integer, AssertionTypes::Integer) = + (type_exp1, type_exp2) + { Ok(AssertionTypes::RangeInteger) } else { Err(format!( @@ -938,7 +1060,9 @@ where let type_exp = typecheck_expression(exp, c)?; match type_exp { AssertionTypes::Set => Ok(AssertionTypes::RangeSet), - AssertionTypes::RangeNeighbours => Ok(AssertionTypes::RangeNeighbours), + AssertionTypes::RangeNeighbours => { + Ok(AssertionTypes::RangeNeighbours) + } _ => Err(format!( "Expressions in range is not a set or \ neighbours of a node, but is: {type_exp:?}." @@ -1034,7 +1158,10 @@ where let val1 = execute_exp(exp1, c, translator, graph)?; let val2 = execute_exp(exp2, c, translator, graph)?; match (val1, val2) { - (AssertReturnValue::Integer(i1), AssertReturnValue::Integer(i2)) => Ok((i1..i2) + ( + AssertReturnValue::Integer(i1), + AssertReturnValue::Integer(i2), + ) => Ok((i1..i2) .map(AssertReturnValue::Integer) .collect::>() .into_iter()), diff --git a/src/rsprocess/assert/fmt.rs b/src/rsprocess/assert/fmt.rs index 0cbd545..cf9fb51 100644 --- a/src/rsprocess/assert/fmt.rs +++ b/src/rsprocess/assert/fmt.rs @@ -1,7 +1,9 @@ // ----------------------------------------------------------------------------- // Display Implementation for all types // ----------------------------------------------------------------------------- -use super::super::translator::{Formatter, PrintableWithTranslator, Translator}; +use super::super::translator::{ + Formatter, PrintableWithTranslator, Translator, +}; use super::dsl::*; use std::fmt; @@ -243,7 +245,9 @@ impl fmt::Debug for AssertReturnValue { Self::Element(el) => write!(f, "{{debug: {el:?}}}"), Self::Edge(edge) => write!(f, "{{debug: {edge:?}}}"), Self::Node(node) => write!(f, "{{debug: {node:?}}}"), - Self::Neighbours(node) => write!(f, "{{debug: {node:?}}}.neighbours"), + Self::Neighbours(node) => { + write!(f, "{{debug: {node:?}}}.neighbours") + } Self::System(sys) => write!(f, "{{debug: {sys:?}}}"), Self::Context(ctx) => write!(f, "{{debug: {ctx:?}}}"), } @@ -277,7 +281,11 @@ impl PrintableWithTranslator for Assert where S: PrintableWithTranslator, { - fn print(&self, f: &mut fmt::Formatter, translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + translator: &Translator, + ) -> fmt::Result { write!( f, "label {{\n{}\n}}", @@ -290,7 +298,11 @@ impl PrintableWithTranslator for Tree where S: PrintableWithTranslator, { - fn print(&self, f: &mut fmt::Formatter, translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + translator: &Translator, + ) -> fmt::Result { match self { Self::Concat(t1, t2) => write!( f, @@ -331,7 +343,9 @@ where ) } } - Self::Return(exp) => write!(f, "return {}", Formatter::from(translator, &**exp)), + Self::Return(exp) => { + write!(f, "return {}", Formatter::from(translator, &**exp)) + } Self::For(v, r, t) => { write!( f, @@ -349,7 +363,11 @@ impl PrintableWithTranslator for Variable where S: PrintableWithTranslator, { - fn print(&self, f: &mut fmt::Formatter, translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + translator: &Translator, + ) -> fmt::Result { match self { Self::Special(s) => write!(f, "{}", Formatter::from(translator, s)), Self::Id(s) => write!(f, "{s}"), @@ -361,14 +379,22 @@ impl PrintableWithTranslator for Expression where S: PrintableWithTranslator, { - fn print(&self, f: &mut fmt::Formatter, translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + translator: &Translator, + ) -> fmt::Result { match self { Self::True => write!(f, "True"), Self::False => write!(f, "False"), Self::Integer(i) => write!(f, "{i}"), - Self::Label(l) => write!(f, "{}", Formatter::from(translator, &**l)), + Self::Label(l) => { + write!(f, "{}", Formatter::from(translator, &**l)) + } Self::Set(set) => write!(f, "{}", Formatter::from(translator, set)), - Self::Element(el) => write!(f, "'{}'", Formatter::from(translator, el)), + Self::Element(el) => { + write!(f, "'{}'", Formatter::from(translator, el)) + } Self::String(s) => write!(f, r#""{s}""#), Self::Var(v) => write!(f, "{}", Formatter::from(translator, v)), Self::Unary(u, exp) => { @@ -427,9 +453,15 @@ impl PrintableWithTranslator for Range where S: PrintableWithTranslator, { - fn print(&self, f: &mut fmt::Formatter, translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + translator: &Translator, + ) -> fmt::Result { match self { - Self::IterateOverSet(exp) => write!(f, "{}", Formatter::from(translator, &**exp)), + Self::IterateOverSet(exp) => { + write!(f, "{}", Formatter::from(translator, &**exp)) + } Self::IterateInRange(exp1, exp2) => write!( f, "{}..{}", @@ -441,7 +473,11 @@ where } impl PrintableWithTranslator for Unary { - fn print(&self, f: &mut fmt::Formatter, translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + translator: &Translator, + ) -> fmt::Result { match self { Self::Not => write!(f, "not"), Self::Rand => write!(f, "rand"), @@ -449,46 +485,74 @@ impl PrintableWithTranslator for Unary { Self::Length => write!(f, ".length"), Self::ToStr => write!(f, ".tostr"), Self::ToEl => write!(f, ".toel"), - Self::Qualifier(q) => write!(f, ".{}", Formatter::from(translator, q)), + Self::Qualifier(q) => { + write!(f, ".{}", Formatter::from(translator, q)) + } } } } impl PrintableWithTranslator for QualifierRestricted { - fn print(&self, f: &mut fmt::Formatter, _translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + _translator: &Translator, + ) -> fmt::Result { write!(f, "{self:?}") } } impl PrintableWithTranslator for QualifierLabel { - fn print(&self, f: &mut fmt::Formatter, _translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + _translator: &Translator, + ) -> fmt::Result { write!(f, "{self:?}") } } impl PrintableWithTranslator for QualifierSystem { - fn print(&self, f: &mut fmt::Formatter, _translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + _translator: &Translator, + ) -> fmt::Result { write!(f, "{self:?}") } } impl PrintableWithTranslator for QualifierEdge { - fn print(&self, f: &mut fmt::Formatter, _translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + _translator: &Translator, + ) -> fmt::Result { write!(f, "{self:?}") } } impl PrintableWithTranslator for QualifierNode { - fn print(&self, f: &mut fmt::Formatter, _translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + _translator: &Translator, + ) -> fmt::Result { write!(f, "{self:?}") } } impl PrintableWithTranslator for Qualifier { - fn print(&self, f: &mut fmt::Formatter, translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + translator: &Translator, + ) -> fmt::Result { match self { Self::Label(q) => write!(f, "{}", Formatter::from(translator, q)), - Self::Restricted(q) => write!(f, "{}", Formatter::from(translator, q)), + Self::Restricted(q) => { + write!(f, "{}", Formatter::from(translator, q)) + } Self::System(q) => write!(f, "{}", Formatter::from(translator, q)), Self::Edge(q) => write!(f, "{}", Formatter::from(translator, q)), Self::Node(q) => write!(f, "{}", Formatter::from(translator, q)), @@ -497,31 +561,51 @@ impl PrintableWithTranslator for Qualifier { } impl PrintableWithTranslator for Binary { - fn print(&self, f: &mut fmt::Formatter, _translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + _translator: &Translator, + ) -> fmt::Result { write!(f, "{self:?}") } } impl PrintableWithTranslator for AssertReturnValue { - fn print(&self, f: &mut fmt::Formatter, translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + translator: &Translator, + ) -> fmt::Result { match self { Self::Boolean(b) => write!(f, "{b}"), Self::Integer(i) => write!(f, "{i}"), Self::String(s) => write!(f, r#""{s}""#), Self::Label(l) => write!(f, "{}", Formatter::from(translator, l)), Self::Set(set) => write!(f, "{}", Formatter::from(translator, set)), - Self::Element(el) => write!(f, "{}", Formatter::from(translator, el)), + Self::Element(el) => { + write!(f, "{}", Formatter::from(translator, el)) + } Self::Edge(edge) => write!(f, "{{edge: {edge:?}}}"), Self::Node(node) => write!(f, "{{node: {node:?}}}"), - Self::Neighbours(node) => write!(f, "{{node: {node:?}}}.neighbours"), - Self::System(sys) => write!(f, "{}", Formatter::from(translator, sys)), - Self::Context(ctx) => write!(f, "{}", Formatter::from(translator, ctx)), + Self::Neighbours(node) => { + write!(f, "{{node: {node:?}}}.neighbours") + } + Self::System(sys) => { + write!(f, "{}", Formatter::from(translator, sys)) + } + Self::Context(ctx) => { + write!(f, "{}", Formatter::from(translator, ctx)) + } } } } impl PrintableWithTranslator for AssertionTypes { - fn print(&self, f: &mut fmt::Formatter, _translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + _translator: &Translator, + ) -> fmt::Result { write!(f, "{self:?}") } } diff --git a/src/rsprocess/assert/mod.rs b/src/rsprocess/assert/mod.rs index 1899f24..b2c12b0 100644 --- a/src/rsprocess/assert/mod.rs +++ b/src/rsprocess/assert/mod.rs @@ -1,10 +1,14 @@ pub mod dsl; pub mod rsassert; -pub mod types { +pub mod relabel { pub use super::rsassert::useful_types_edge_relabeler::*; } +pub mod grouping { + pub use super::rsassert::useful_types_node_relabeler::*; +} + mod fmt; #[cfg(test)] diff --git a/src/rsprocess/assert/rsassert.rs b/src/rsprocess/assert/rsassert.rs index a382f15..19dfb06 100644 --- a/src/rsprocess/assert/rsassert.rs +++ b/src/rsprocess/assert/rsassert.rs @@ -8,7 +8,7 @@ use std::collections::HashMap; // Specific Assert Implementation // ---------------------------------------------------------------------------- -/// Module that has all types and structures. +/// Module that has all types and structures for bisimilarity relabeler. pub mod useful_types_edge_relabeler { macro_rules! export_types { ( $( $x:ident ),* ) => { @@ -67,10 +67,13 @@ impl SpecialVariables for EdgeRelablerInput { fn type_qualified(&self, q: &Qualifier) -> Result { match (self, q) { - (Self::Label, Qualifier::Label(_)) | (Self::Label, Qualifier::Restricted(_)) => { + (Self::Label, Qualifier::Label(_)) + | (Self::Label, Qualifier::Restricted(_)) => { Ok(AssertionTypes::Set) } - (s, q) => Err(format!("Wrong use of qualifier {q:?} on variable {s:?}.")), + (s, q) => { + Err(format!("Wrong use of qualifier {q:?} on variable {s:?}.")) + } } } @@ -80,8 +83,12 @@ impl SpecialVariables for EdgeRelablerInput { input .iter() .map(|(key, value)| match value { - EdgeRelablerInputValues::Edge(e) => (*key, AssertReturnValue::Edge(*e)), - EdgeRelablerInputValues::Label(l) => (*key, AssertReturnValue::Label(l.clone())), + EdgeRelablerInputValues::Edge(e) => { + (*key, AssertReturnValue::Edge(*e)) + } + EdgeRelablerInputValues::Label(l) => { + (*key, AssertReturnValue::Label(l.clone())) + } }) .collect::>() } @@ -129,15 +136,15 @@ impl Assert { | AssertionTypes::Node | AssertionTypes::System | AssertionTypes::Context => Ok(()), - AssertionTypes::NoType => Err("No return type, at least one return statement \ - required." - .into()), + AssertionTypes::NoType => { + Err("No return type, at least one return statement required." + .into()) + } AssertionTypes::RangeInteger | AssertionTypes::RangeSet - | AssertionTypes::RangeNeighbours => Err(format!( - "Returned type {ty:?} is not a valid return \ - type." - )), + | AssertionTypes::RangeNeighbours => { + Err(format!("Returned type {ty:?} is not a valid return type.")) + } } } @@ -174,6 +181,41 @@ impl Assert { // Implementation for node grouping. // ----------------------------------------------------------------------------- +/// Module that has all types and structures for bisimilarity relabeler. +pub mod useful_types_node_relabeler { + macro_rules! export_types { + ( $( $x:ident ),* ) => { + $( + pub type $x = super::super::dsl::$x; + )* + }; + } + + macro_rules! export_types_no_parameter { + ( $( $x:ident ),* ) => { + $( + pub type $x = super::super::dsl::$x; + )* + }; + } + + export_types!(Assert, Tree, Variable, Expression, Range); + + export_types_no_parameter!( + Unary, + QualifierRestricted, + QualifierLabel, + QualifierSystem, + QualifierEdge, + QualifierNode, + Qualifier, + Binary, + AssertReturnValue + ); + + pub type Special = super::NodeRelablerInput; +} + #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub enum NodeRelablerInput { Entities, @@ -196,11 +238,15 @@ impl SpecialVariables for NodeRelablerInput { fn type_qualified(&self, q: &Qualifier) -> Result { match (self, q) { - (Self::Node, Qualifier::Node(QualifierNode::System)) => Ok(AssertionTypes::System), + (Self::Node, Qualifier::Node(QualifierNode::System)) => { + Ok(AssertionTypes::System) + } (Self::Node, Qualifier::Node(QualifierNode::Neighbours)) => { Ok(AssertionTypes::RangeNeighbours) } - (s, q) => Err(format!("Wrong use of qualifier {q:?} on variable {s:?}.")), + (s, q) => { + Err(format!("Wrong use of qualifier {q:?} on variable {s:?}.")) + } } } @@ -210,8 +256,12 @@ impl SpecialVariables for NodeRelablerInput { input .iter() .map(|(key, value)| match value { - NodeRelablerInputValues::Entities(e) => (*key, AssertReturnValue::Set(e.clone())), - NodeRelablerInputValues::Node(n) => (*key, AssertReturnValue::Node(*n)), + NodeRelablerInputValues::Entities(e) => { + (*key, AssertReturnValue::Set(e.clone())) + } + NodeRelablerInputValues::Node(n) => { + (*key, AssertReturnValue::Node(*n)) + } }) .collect::>() } @@ -259,15 +309,15 @@ impl Assert { | AssertionTypes::Node | AssertionTypes::System | AssertionTypes::Context => Ok(()), - AssertionTypes::NoType => Err("No return type, at least one return statement \ - required." - .into()), + AssertionTypes::NoType => { + Err("No return type, at least one return statement required." + .into()) + } AssertionTypes::RangeInteger | AssertionTypes::RangeSet - | AssertionTypes::RangeNeighbours => Err(format!( - "Returned type {ty:?} is not a valid return \ - type." - )), + | AssertionTypes::RangeNeighbours => { + Err(format!("Returned type {ty:?} is not a valid return type.")) + } } } diff --git a/src/rsprocess/assert/tests.rs b/src/rsprocess/assert/tests.rs index a71cc4a..a4bb434 100644 --- a/src/rsprocess/assert/tests.rs +++ b/src/rsprocess/assert/tests.rs @@ -139,9 +139,9 @@ fn return_incompatible_2() { None, Box::new(Expression::Integer(10)), )), - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "a".into(), - ))))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("a".into()), + )))), )), ), }; @@ -163,9 +163,9 @@ fn return_2() { None, Box::new(Expression::False), )), - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "a".into(), - ))))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("a".into()), + )))), )), ), }; @@ -198,9 +198,9 @@ fn return_3() { None, Box::new(Expression::False), )), - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "a".into(), - ))))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("a".into()), + )))), )), Box::new(Tree::Return(Box::new(Expression::True))), ), @@ -419,7 +419,11 @@ fn if_else_4() { #[test] fn assignment_1() { let tree = LocalAssert { - tree: Tree::Assignment(Variable::Id("a".into()), None, Box::new(Expression::True)), + tree: Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::True), + ), }; assert!(tree.typecheck().is_err()); } @@ -519,12 +523,12 @@ fn assignment_5() { Box::new(Expression::Integer(10)), )), Box::new(Tree::Concat( - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "a".into(), - ))))), - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "a".into(), - ))))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("a".into()), + )))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("a".into()), + )))), )), ), }; @@ -564,12 +568,12 @@ fn assignment_6() { )), )), Box::new(Tree::Concat( - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "a".into(), - ))))), - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "b".into(), - ))))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("a".into()), + )))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("b".into()), + )))), )), ), }; @@ -609,9 +613,9 @@ fn assignment_7() { )), )), Box::new(Tree::Concat( - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "a".into(), - ))))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("a".into()), + )))), Box::new(Tree::Return(Box::new(Expression::False))), )), ), @@ -652,12 +656,12 @@ fn assignment_8() { )), )), Box::new(Tree::Concat( - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "a".into(), - ))))), - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "b".into(), - ))))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("a".into()), + )))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("b".into()), + )))), )), ), }; @@ -697,9 +701,9 @@ fn assignment_9() { )), )), Box::new(Tree::Concat( - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "b".into(), - ))))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("b".into()), + )))), Box::new(Tree::Return(Box::new(Expression::Integer(200)))), )), ), @@ -745,9 +749,9 @@ fn assignment_10() { None, Box::new(Expression::Integer(200)), )), - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "b".into(), - ))))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("b".into()), + )))), )), ), }; @@ -789,7 +793,9 @@ fn for_1() { )), Box::new(Tree::For( Variable::Id("c".into()), - Range::IterateOverSet(Box::new(Expression::Var(Variable::Id("a".into())))), + Range::IterateOverSet(Box::new(Expression::Var(Variable::Id( + "a".into(), + )))), Box::new(Tree::Return(Box::new(Expression::Integer(200)))), )), ), @@ -829,10 +835,12 @@ fn for_2() { )), Box::new(Tree::For( Variable::Id("c".into()), - Range::IterateOverSet(Box::new(Expression::Var(Variable::Id("a".into())))), - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "b".into(), - ))))), + Range::IterateOverSet(Box::new(Expression::Var(Variable::Id( + "a".into(), + )))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("b".into()), + )))), )), ), }; @@ -886,12 +894,14 @@ fn for_3() { Box::new(Tree::For( Variable::Id("c".into()), Range::IterateOverSet(Box::new(Expression::Unary( - Unary::Qualifier(Qualifier::Restricted(QualifierRestricted::Entities)), + Unary::Qualifier(Qualifier::Restricted( + QualifierRestricted::Entities, + )), Box::new(Expression::Var(Variable::Id("a".into()))), ))), - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "b".into(), - ))))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("b".into()), + )))), )), ), }; @@ -945,12 +955,14 @@ fn for_4() { Box::new(Tree::For( Variable::Id("c".into()), Range::IterateOverSet(Box::new(Expression::Unary( - Unary::Qualifier(Qualifier::Label(QualifierLabel::AvailableEntities)), + Unary::Qualifier(Qualifier::Label( + QualifierLabel::AvailableEntities, + )), Box::new(Expression::Var(Variable::Id("a".into()))), ))), - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "c".into(), - ))))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("c".into()), + )))), )), ), }; @@ -1006,7 +1018,9 @@ fn for_5() { Box::new(Tree::For( Variable::Id("c".into()), Range::IterateOverSet(Box::new(Expression::Unary( - Unary::Qualifier(Qualifier::Label(QualifierLabel::AvailableEntities)), + Unary::Qualifier(Qualifier::Label( + QualifierLabel::AvailableEntities, + )), Box::new(Expression::Var(Variable::Id("a".into()))), ))), Box::new(Tree::Assignment( @@ -1019,9 +1033,9 @@ fn for_5() { )), )), )), - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "b".into(), - ))))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("b".into()), + )))), )), ), }; @@ -1086,7 +1100,9 @@ fn for_6() { Range::IterateOverSet(Box::new(Expression::Binary( Binary::Plus, Box::new(Expression::Unary( - Unary::Qualifier(Qualifier::Restricted(QualifierRestricted::Context)), + Unary::Qualifier(Qualifier::Restricted( + QualifierRestricted::Context, + )), Box::new(Expression::Var(Variable::Id("a".into()))), )), Box::new(Expression::Var(Variable::Id("b".into()))), @@ -1101,9 +1117,9 @@ fn for_6() { )), )), )), - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "c".into(), - ))))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("c".into()), + )))), )), ), }; @@ -1151,9 +1167,9 @@ fn for_7() { Box::new(Expression::Var(Variable::Id("a".into()))), Box::new(Expression::Var(Variable::Id("b".into()))), ), - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "c".into(), - ))))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("c".into()), + )))), )), ), }; @@ -1185,10 +1201,16 @@ fn for_8() { Variable::Id("a".into()), None, Box::new(Expression::Unary( - Unary::Qualifier(Qualifier::Node(QualifierNode::Neighbours)), + Unary::Qualifier(Qualifier::Node( + QualifierNode::Neighbours, + )), Box::new(Expression::Unary( - Unary::Qualifier(Qualifier::Edge(QualifierEdge::Source)), - Box::new(Expression::Var(Variable::Special(EdgeRelablerInput::Edge))), + Unary::Qualifier(Qualifier::Edge( + QualifierEdge::Source, + )), + Box::new(Expression::Var(Variable::Special( + EdgeRelablerInput::Edge, + ))), )), )), )), @@ -1201,7 +1223,9 @@ fn for_8() { Box::new(Tree::Concat( Box::new(Tree::For( Variable::Id("c".into()), - Range::IterateOverSet(Box::new(Expression::Var(Variable::Id("a".into())))), + Range::IterateOverSet(Box::new(Expression::Var( + Variable::Id("a".into()), + ))), Box::new(Tree::Assignment( Variable::Id("b".into()), None, @@ -1212,9 +1236,9 @@ fn for_8() { )), )), )), - Box::new(Tree::Return(Box::new(Expression::Var(Variable::Id( - "b".into(), - ))))), + Box::new(Tree::Return(Box::new(Expression::Var( + Variable::Id("b".into()), + )))), )), ), }; @@ -1263,12 +1287,20 @@ fn nodes() { Variable::Id("a".into()), None, Box::new(Expression::Unary( - Unary::Qualifier(Qualifier::System(QualifierSystem::Entities)), + Unary::Qualifier(Qualifier::System( + QualifierSystem::Entities, + )), Box::new(Expression::Unary( - Unary::Qualifier(Qualifier::Node(QualifierNode::System)), + Unary::Qualifier(Qualifier::Node( + QualifierNode::System, + )), Box::new(Expression::Unary( - Unary::Qualifier(Qualifier::Edge(QualifierEdge::Target)), - Box::new(Expression::Var(Variable::Special(EdgeRelablerInput::Edge))), + Unary::Qualifier(Qualifier::Edge( + QualifierEdge::Target, + )), + Box::new(Expression::Var(Variable::Special( + EdgeRelablerInput::Edge, + ))), )), )), )), diff --git a/src/rsprocess/bisimilarity/bisimilarity_kanellakis_smolka.rs b/src/rsprocess/bisimilarity/bisimilarity_kanellakis_smolka.rs index 1b1803a..7dc2e2c 100644 --- a/src/rsprocess/bisimilarity/bisimilarity_kanellakis_smolka.rs +++ b/src/rsprocess/bisimilarity/bisimilarity_kanellakis_smolka.rs @@ -5,7 +5,8 @@ use std::collections::{BTreeSet, HashMap, HashSet}; use petgraph::visit::{ - EdgeRef, GraphBase, IntoEdgeReferences, IntoEdges, IntoNodeIdentifiers, IntoNodeReferences, + EdgeRef, GraphBase, IntoEdgeReferences, IntoEdges, IntoNodeIdentifiers, + IntoNodeReferences, }; // ----------------------------------------------------------------------------- @@ -96,7 +97,11 @@ where G: IntoEdges, G::NodeId: std::cmp::Eq + std::hash::Hash, { - fn reachable_blocks(&self, label: &G::EdgeWeight, s: &(usize, G::NodeId)) -> Vec + fn reachable_blocks( + &self, + label: &G::EdgeWeight, + s: &(usize, G::NodeId), + ) -> Vec where G::EdgeWeight: PartialEq, { @@ -162,7 +167,8 @@ where { let graphs = [graph_a, graph_b]; - let mut partition: GraphPartition = GraphPartition::new(graph_a, graph_b); + let mut partition: GraphPartition = + GraphPartition::new(graph_a, graph_b); for (p, graph) in graphs.iter().enumerate() { for node in graph.node_identifiers() { partition.add_node_last_partition(node, p); diff --git a/src/rsprocess/bisimilarity/bisimilarity_paige_tarkan.rs b/src/rsprocess/bisimilarity/bisimilarity_paige_tarkan.rs index 0cf0061..f65fcc7 100644 --- a/src/rsprocess/bisimilarity/bisimilarity_paige_tarkan.rs +++ b/src/rsprocess/bisimilarity/bisimilarity_paige_tarkan.rs @@ -9,8 +9,8 @@ use std::rc::Rc; use petgraph::Direction::{Incoming, Outgoing}; use petgraph::visit::{ - EdgeCount, EdgeRef, GraphBase, IntoEdgeReferences, IntoNeighborsDirected, IntoNodeIdentifiers, - IntoNodeReferences, NodeCount, + EdgeCount, EdgeRef, GraphBase, IntoEdgeReferences, IntoNeighborsDirected, + IntoNodeIdentifiers, IntoNodeReferences, NodeCount, }; type NodeIdType = u32; @@ -234,12 +234,16 @@ where let leaf_node_block = SimpleBlock { block: leaf_node_indices, - coarse_block_that_supersets_self: Rc::clone(&compound_initial_block_pointer), + coarse_block_that_supersets_self: Rc::clone( + &compound_initial_block_pointer, + ), }; let non_leaf_node_block = SimpleBlock { block: non_leaf_node_indices, - coarse_block_that_supersets_self: Rc::clone(&compound_initial_block_pointer), + coarse_block_that_supersets_self: Rc::clone( + &compound_initial_block_pointer, + ), }; ( @@ -265,7 +269,8 @@ where .iter() .copied() .for_each(|value| { - node_to_block.insert(value, Rc::clone(&non_leaf_node_block_pointer)); + node_to_block + .insert(value, Rc::clone(&non_leaf_node_block_pointer)); }); (*leaf_node_block_pointer) @@ -274,7 +279,8 @@ where .iter() .copied() .for_each(|value| { - node_to_block.insert(value, Rc::clone(&leaf_node_block_pointer)); + node_to_block + .insert(value, Rc::clone(&leaf_node_block_pointer)); }); node_to_block }; @@ -300,7 +306,8 @@ where block.block().iter().for_each(|node_index_pointer| { backedges.insert(*node_index_pointer, { - let (node_id, graph_id) = convert_nodes.decode(node_index_pointer).unwrap(); + let (node_id, graph_id) = + convert_nodes.decode(node_index_pointer).unwrap(); graphs[*graph_id as usize] .neighbors_directed(*node_id, Incoming) .collect::>() @@ -315,7 +322,10 @@ where backedges } -fn group_by_backedges(backedges: BackEdges, node_to_block: &NodeToBlock) -> BackEdgesGrouped { +fn group_by_backedges( + backedges: BackEdges, + node_to_block: &NodeToBlock, +) -> BackEdgesGrouped { let mut backedges_grouped: BackEdgesGrouped = HashMap::new(); for incoming_neighbor_group in backedges.values() { @@ -324,7 +334,9 @@ fn group_by_backedges(backedges: BackEdges, node_to_block: &NodeToBlock) -> Back let key = (*block).borrow().block.clone(); match backedges_grouped.entry(key) { - Entry::Occupied(mut entry) => entry.get_mut().subblock.push(*node), + Entry::Occupied(mut entry) => { + entry.get_mut().subblock.push(*node) + } Entry::Vacant(entry) => { entry.insert(BackEdgesGroup { block: Rc::clone(&block), @@ -360,7 +372,9 @@ fn split_blocks_with_grouped_backedges( let simple_block = SimpleBlock { block: back_edges_group.subblock.clone(), - coarse_block_that_supersets_self: Rc::clone(&borrowed_compound_block), + coarse_block_that_supersets_self: Rc::clone( + &borrowed_compound_block, + ), }; Rc::new(RefCell::new(simple_block)) @@ -384,7 +398,8 @@ fn split_blocks_with_grouped_backedges( .collect(); if (*back_edges_group.block).borrow().block.is_empty() { - borrowed_compound_block.remove_simple_block(&back_edges_group.block); + borrowed_compound_block + .remove_simple_block(&back_edges_group.block); all_removed_simple_blocks.push(Rc::clone(&back_edges_group.block)); } all_new_simple_blocks.push(Rc::clone(&proper_subblock)); @@ -441,7 +456,8 @@ where } }; - let smaller_component = simple_blocks_in_splitter_block.remove(smaller_component_index); + let smaller_component = + simple_blocks_in_splitter_block.remove(smaller_component_index); let simple_splitter_block_values: Block = splitter_block .block @@ -454,7 +470,9 @@ where let simple_splitter_block = CompoundBlock { block: simple_splitter_block_values, - simple_blocks_subsets_of_self: RefCell::new(simple_blocks_in_splitter_block), + simple_blocks_subsets_of_self: RefCell::new( + simple_blocks_in_splitter_block, + ), }; let simple_splitter_block_pointer = Rc::new(simple_splitter_block); @@ -478,20 +496,32 @@ where Rc::clone(&simple_splitter_block); }); - let mut back_edges = build_backedges(graphs, smaller_component, &converter); + let mut back_edges = + build_backedges(graphs, smaller_component, &converter); - let back_edges_group = group_by_backedges(back_edges.clone(), &node_to_block); - let ((new_simple_blocks, removeable_simple_blocks), compound_block_that_are_now_compound) = - split_blocks_with_grouped_backedges(back_edges_group, &mut node_to_block); + let back_edges_group = + group_by_backedges(back_edges.clone(), &node_to_block); + let ( + (new_simple_blocks, removeable_simple_blocks), + compound_block_that_are_now_compound, + ) = split_blocks_with_grouped_backedges( + back_edges_group, + &mut node_to_block, + ); all_simple_blocks.extend(new_simple_blocks); - all_simple_blocks.retain(|x| !removeable_simple_blocks.iter().any(|y| Rc::ptr_eq(x, y))); + all_simple_blocks.retain(|x| { + !removeable_simple_blocks.iter().any(|y| Rc::ptr_eq(x, y)) + }); queue.extend(compound_block_that_are_now_compound); // back edges = E^{-1}(B) - E^{-1}(S-B) { - let back_edges_splitter_complement = - build_backedges(graphs, (*simple_splitter_block).clone(), &converter); + let back_edges_splitter_complement = build_backedges( + graphs, + (*simple_splitter_block).clone(), + &converter, + ); back_edges_splitter_complement.keys().for_each(|node| { back_edges.remove(node); @@ -499,11 +529,18 @@ where } let back_edges_group = group_by_backedges(back_edges, &node_to_block); - let ((new_fine_blocks, removeable_fine_blocks), coarse_block_that_are_now_compound) = - split_blocks_with_grouped_backedges(back_edges_group, &mut node_to_block); + let ( + (new_fine_blocks, removeable_fine_blocks), + coarse_block_that_are_now_compound, + ) = split_blocks_with_grouped_backedges( + back_edges_group, + &mut node_to_block, + ); all_simple_blocks.extend(new_fine_blocks); - all_simple_blocks.retain(|x| !removeable_fine_blocks.iter().any(|y| Rc::ptr_eq(x, y))); + all_simple_blocks.retain(|x| { + !removeable_fine_blocks.iter().any(|y| Rc::ptr_eq(x, y)) + }); queue.extend(coarse_block_that_are_now_compound); } @@ -532,7 +569,10 @@ where G::EdgeWeight: std::cmp::Eq + std::hash::Hash + Clone, { let mut new_graph_a: petgraph::Graph<_, u32> = - petgraph::Graph::with_capacity(graph.node_count() * 4, graph.edge_count() * 4); + petgraph::Graph::with_capacity( + graph.node_count() * 4, + graph.edge_count() * 4, + ); let mut association_weight_id = HashMap::new(); let mut original_nodes = HashSet::new(); let mut last_id = 0; @@ -611,7 +651,8 @@ where } // slight optimization: we reorder the edges such that edges with the // most occurrences have smaller index - let mut labels: Vec<(G::EdgeWeight, u32)> = labels.into_iter().collect(); + let mut labels: Vec<(G::EdgeWeight, u32)> = + labels.into_iter().collect(); labels.sort_by(|a, b| b.1.cmp(&a.1)); for (label, _) in labels.into_iter() { @@ -643,7 +684,8 @@ where val.into_iter().all(|el| { let mut keep_track = [false, false]; for e in el { - let (_node_id, graph_id) = converter_bisimulated_graph.decode(&e).unwrap(); + let (_node_id, graph_id) = + converter_bisimulated_graph.decode(&e).unwrap(); if original_nodes[*graph_id as usize].contains(&e.0) { keep_track[*graph_id as usize] = true; } @@ -671,13 +713,18 @@ where let ((new_graph_a, original_nodes_a), (new_graph_b, original_nodes_b)) = modify_graph(graph_a, graph_b); - let (result, _converter) = match maximum_bisimulation(&[&&new_graph_a, &&new_graph_b]) { - (None, _) => return false, - (Some(val), converter) => ( - check_bisimilarity::(val, &converter, [original_nodes_a, original_nodes_b]), - converter, - ), - }; + let (result, _converter) = + match maximum_bisimulation(&[&&new_graph_a, &&new_graph_b]) { + (None, _) => return false, + (Some(val), converter) => ( + check_bisimilarity::( + val, + &converter, + [original_nodes_a, original_nodes_b], + ), + converter, + ), + }; result } diff --git a/src/rsprocess/bisimilarity/test_paige_tarjan.rs b/src/rsprocess/bisimilarity/test_paige_tarjan.rs index 6d11437..3de4da9 100644 --- a/src/rsprocess/bisimilarity/test_paige_tarjan.rs +++ b/src/rsprocess/bisimilarity/test_paige_tarjan.rs @@ -1,4 +1,6 @@ -use super::bisimilarity_paige_tarkan::{bisimilarity, bisimilarity_ignore_labels}; +use super::bisimilarity_paige_tarkan::{ + bisimilarity, bisimilarity_ignore_labels, +}; #[test] fn identity_paige_tarjan() { diff --git a/src/rsprocess/choices.rs b/src/rsprocess/choices.rs index 4690a6e..c88370b 100644 --- a/src/rsprocess/choices.rs +++ b/src/rsprocess/choices.rs @@ -100,7 +100,11 @@ impl From, Rc)>> for Choices { } impl PrintableWithTranslator for Choices { - fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator) -> std::fmt::Result { + fn print( + &self, + f: &mut std::fmt::Formatter, + translator: &Translator, + ) -> std::fmt::Result { write!(f, "[")?; let mut it = self.iter().peekable(); while let Some(el) = it.next() { @@ -180,7 +184,11 @@ impl IntoIterator for PositiveChoices { } impl PrintableWithTranslator for PositiveChoices { - fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator) -> std::fmt::Result { + fn print( + &self, + f: &mut std::fmt::Formatter, + translator: &Translator, + ) -> std::fmt::Result { write!(f, "[")?; let mut it = self.iter().peekable(); while let Some(el) = it.next() { @@ -205,12 +213,16 @@ impl PrintableWithTranslator for PositiveChoices { } impl PositiveChoices { - fn iter(&self) -> std::slice::Iter<'_, (Rc, Rc)> { + fn iter( + &self, + ) -> std::slice::Iter<'_, (Rc, Rc)> { self.context_moves.iter() } } -impl From<[(Rc, Rc); N]> for PositiveChoices { +impl From<[(Rc, Rc); N]> + for PositiveChoices +{ fn from(arr: [(Rc, Rc); N]) -> Self { Self { context_moves: arr.to_vec(), diff --git a/src/rsprocess/dot.rs b/src/rsprocess/dot.rs index 7606dbe..c4056d8 100644 --- a/src/rsprocess/dot.rs +++ b/src/rsprocess/dot.rs @@ -6,7 +6,10 @@ static PRINTNAMES: bool = false; use core::fmt::{self, Display, Write}; use petgraph::{ data::DataMap, - visit::{EdgeRef, GraphProp, IntoEdgeReferences, IntoNodeReferences, NodeIndexable, NodeRef}, + visit::{ + EdgeRef, GraphProp, IntoEdgeReferences, IntoNodeReferences, + NodeIndexable, NodeRef, + }, }; pub struct Dot<'a, G> @@ -166,9 +169,18 @@ make_config_struct!(); impl Dot<'_, G> where - G: IntoNodeReferences + IntoEdgeReferences + NodeIndexable + GraphProp + DataMap, + G: IntoNodeReferences + + IntoEdgeReferences + + NodeIndexable + + GraphProp + + DataMap, { - fn graph_fmt(&self, f: &mut fmt::Formatter, node_fmt: NF, edge_fmt: EF) -> fmt::Result + fn graph_fmt( + &self, + f: &mut fmt::Formatter, + node_fmt: NF, + edge_fmt: EF, + ) -> fmt::Result where NF: Fn(&G::NodeWeight, &mut fmt::Formatter) -> fmt::Result, EF: Fn(&G::EdgeWeight, &mut fmt::Formatter) -> fmt::Result, @@ -249,7 +261,11 @@ where impl fmt::Display for Dot<'_, G> where - G: IntoEdgeReferences + IntoNodeReferences + NodeIndexable + GraphProp + DataMap, + G: IntoEdgeReferences + + IntoNodeReferences + + NodeIndexable + + GraphProp + + DataMap, G::EdgeWeight: fmt::Display, G::NodeWeight: fmt::Display, { @@ -260,7 +276,11 @@ where impl fmt::LowerHex for Dot<'_, G> where - G: IntoEdgeReferences + IntoNodeReferences + NodeIndexable + GraphProp + DataMap, + G: IntoEdgeReferences + + IntoNodeReferences + + NodeIndexable + + GraphProp + + DataMap, G::EdgeWeight: fmt::LowerHex, G::NodeWeight: fmt::LowerHex, { @@ -271,7 +291,11 @@ where impl fmt::UpperHex for Dot<'_, G> where - G: IntoEdgeReferences + IntoNodeReferences + NodeIndexable + GraphProp + DataMap, + G: IntoEdgeReferences + + IntoNodeReferences + + NodeIndexable + + GraphProp + + DataMap, G::EdgeWeight: fmt::UpperHex, G::NodeWeight: fmt::UpperHex, { @@ -282,7 +306,11 @@ where impl fmt::Debug for Dot<'_, G> where - G: IntoEdgeReferences + IntoNodeReferences + NodeIndexable + GraphProp + DataMap, + G: IntoEdgeReferences + + IntoNodeReferences + + NodeIndexable + + GraphProp + + DataMap, G::EdgeWeight: fmt::Debug, G::NodeWeight: fmt::Debug, { diff --git a/src/rsprocess/element.rs b/src/rsprocess/element.rs index 7abcec0..0727734 100644 --- a/src/rsprocess/element.rs +++ b/src/rsprocess/element.rs @@ -21,7 +21,18 @@ impl PrintableWithTranslator for IdType { // ----------------------------------------------------------------------------- -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +#[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Serialize, + Deserialize, +)] pub enum IdState { Positive, Negative, @@ -47,7 +58,18 @@ impl std::ops::Not for IdState { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +#[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Serialize, + Deserialize, +)] pub struct PositiveType { pub id: IdType, pub state: IdState, @@ -70,12 +92,18 @@ impl PrintableWithTranslator for PositiveType { impl From<(IdType, IdState)> for PositiveType { fn from(value: (IdType, IdState)) -> Self { - Self { id: value.0, state: value.1 } + 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 } + Self { + id: *value.0, + state: *value.1, + } } } diff --git a/src/rsprocess/environment.rs b/src/rsprocess/environment.rs index 825b2fe..dc08d21 100644 --- a/src/rsprocess/environment.rs +++ b/src/rsprocess/environment.rs @@ -7,7 +7,9 @@ use std::rc::Rc; use super::choices::{BasicChoices, Choices, PositiveChoices}; use super::element::IdType; use super::process::{BasicProcess, PositiveProcess, Process}; -use super::reaction::{BasicReaction, ExtensionReaction, PositiveReaction, Reaction}; +use super::reaction::{ + BasicReaction, ExtensionReaction, PositiveReaction, Reaction, +}; use super::set::{BasicSet, PositiveSet, Set}; use super::translator::{Formatter, PrintableWithTranslator, Translator}; @@ -116,8 +118,13 @@ where // satisfy X = pre(Q, rec(X)) let filtered = self.iter().filter_map(|l| l.1.filter_delta(l.0)); - let find_loop_fn = - |q| T::Reaction::find_loop(reaction_rules, available_entities.clone(), q); + let find_loop_fn = |q| { + T::Reaction::find_loop( + reaction_rules, + available_entities.clone(), + q, + ) + }; filtered.map(find_loop_fn).collect::>() } @@ -129,8 +136,13 @@ where ) -> Vec<(usize, Vec)> { let filtered = self.iter().filter_map(|l| l.1.filter_delta(l.0)); - let find_loop_fn = - |q| T::Reaction::find_prefix_len_loop(reaction_rules, available_entities.clone(), q); + let find_loop_fn = |q| { + T::Reaction::find_prefix_len_loop( + reaction_rules, + available_entities.clone(), + q, + ) + }; filtered.map(find_loop_fn).collect::>() } @@ -143,7 +155,9 @@ where ) -> Vec> { let filtered = self.iter().filter_map(|l| l.1.filter_delta(l.0)); - let find_loop_fn = |q| T::Reaction::find_only_loop(reaction_rules, available_entities, q); + let find_loop_fn = |q| { + T::Reaction::find_only_loop(reaction_rules, available_entities, q) + }; filtered.map(find_loop_fn).collect::>() } @@ -174,8 +188,13 @@ where }) .next(); - let find_loop_fn = - |q| T::Reaction::find_loop(reaction_rules, available_entities.clone(), q); + let find_loop_fn = |q| { + T::Reaction::find_loop( + reaction_rules, + available_entities.clone(), + q, + ) + }; filtered.map(find_loop_fn) } @@ -197,8 +216,13 @@ where }) .next(); - let find_loop_fn = - |q| T::Reaction::find_prefix_len_loop(reaction_rules, available_entities.clone(), q); + let find_loop_fn = |q| { + T::Reaction::find_prefix_len_loop( + reaction_rules, + available_entities.clone(), + q, + ) + }; filtered.map(find_loop_fn) } @@ -221,7 +245,9 @@ where }) .next(); - let find_loop_fn = |q| T::Reaction::find_only_loop(reaction_rules, available_entities, q); + let find_loop_fn = |q| { + T::Reaction::find_only_loop(reaction_rules, available_entities, q) + }; filtered.map(find_loop_fn) } @@ -257,7 +283,11 @@ impl BasicEnvironment for Environment { /// definitions environment. choices::Choices is a list of context moves /// mapping a set of entities and the continuation. /// see unfold - fn unfold(&self, context_process: &Process, current_entities: &Set) -> Result { + fn unfold( + &self, + context_process: &Process, + current_entities: &Set, + ) -> Result { match context_process { Process::Nill => Ok(Choices::default()), Process::RecursiveIdentifier { identifier } => { @@ -298,7 +328,8 @@ impl BasicEnvironment for Environment { repeated_process, next_process, } if *repeat == 1 => { - let mut choices1 = self.unfold(repeated_process, current_entities)?; + let mut choices1 = + self.unfold(repeated_process, current_entities)?; choices1.replace(Rc::clone(next_process)); Ok(choices1) } @@ -307,7 +338,8 @@ impl BasicEnvironment for Environment { repeated_process, next_process, } => { - let mut choices1 = self.unfold(repeated_process, current_entities)?; + let mut choices1 = + self.unfold(repeated_process, current_entities)?; choices1.replace(Rc::new(Process::WaitEntity { repeat: (*repeat - 1), repeated_process: Rc::clone(repeated_process), @@ -335,10 +367,13 @@ impl BasicEnvironment for Environment { Rc::new(Process::Nill), )])) } else { - children.iter().try_fold(Choices::default(), |mut acc, x| { - acc.shuffle(self.unfold(x, current_entities)?); - Ok(acc) - }) + children.iter().try_fold( + Choices::default(), + |mut acc, x| { + acc.shuffle(self.unfold(x, current_entities)?); + Ok(acc) + }, + ) } } } @@ -346,7 +381,11 @@ impl BasicEnvironment for Environment { } impl PrintableWithTranslator for Environment { - fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator) -> std::fmt::Result { + fn print( + &self, + f: &mut std::fmt::Formatter, + translator: &Translator, + ) -> std::fmt::Result { write!(f, "{{env:")?; let mut it = self.iter().peekable(); while let Some(el) = it.next() { @@ -428,18 +467,23 @@ impl Environment { reaction_rules: &[Reaction], entities: &[Set], ) -> Option<(usize, usize, Vec)> { - let all_loops = - self.lollipops_prefix_len_loop_decomposed(reaction_rules, entities.first()?); + let all_loops = self.lollipops_prefix_len_loop_decomposed( + reaction_rules, + entities.first()?, + ); let (prefix_len, hoop) = all_loops.first()?.clone(); let dimension = hoop.len(); let mut max_distance = prefix_len; for available_entities in entities.iter().skip(1) { - let all_loops = - self.lollipops_prefix_len_loop_decomposed(reaction_rules, available_entities); + let all_loops = self.lollipops_prefix_len_loop_decomposed( + reaction_rules, + available_entities, + ); let (prefix_len, new_hoop) = all_loops.first()?; - if new_hoop.len() != dimension || !hoop.contains(new_hoop.first()?) { + if new_hoop.len() != dimension || !hoop.contains(new_hoop.first()?) + { return None; } max_distance = cmp::max(max_distance, *prefix_len); @@ -459,23 +503,26 @@ impl Environment { entities: &[Set], symb: IdType, ) -> Option<(usize, usize, Vec)> { - let (prefix_len, first_hoop) = self.lollipops_prefix_len_loop_decomposed_named( - reaction_rules, - entities.first()?, - symb, - )?; + let (prefix_len, first_hoop) = self + .lollipops_prefix_len_loop_decomposed_named( + reaction_rules, + entities.first()?, + symb, + )?; let dimension = first_hoop.len(); let mut max_distance = prefix_len; let hoop = first_hoop; for available_entities in entities.iter().skip(1) { - let (prefix_len, new_hoop) = self.lollipops_prefix_len_loop_decomposed_named( - reaction_rules, - available_entities, - symb, - )?; + let (prefix_len, new_hoop) = self + .lollipops_prefix_len_loop_decomposed_named( + reaction_rules, + available_entities, + symb, + )?; - if new_hoop.len() != dimension || !hoop.contains(new_hoop.first()?) { + if new_hoop.len() != dimension || !hoop.contains(new_hoop.first()?) + { return None; } max_distance = cmp::max(max_distance, prefix_len); @@ -493,17 +540,24 @@ impl Environment { entities: &[Set], symb: IdType, ) -> Option<(Vec, Vec)> { - let (prefix, hoop) = - self.lollipops_decomposed_named(reaction_rules, entities.first()?, symb)?; + let (prefix, hoop) = self.lollipops_decomposed_named( + reaction_rules, + entities.first()?, + symb, + )?; let mut invariant = vec![]; invariant.append(&mut prefix.clone()); invariant.append(&mut hoop.clone()); let dimension = hoop.len(); for available_entities in entities { - let (new_prefix, new_hoop) = - self.lollipops_decomposed_named(reaction_rules, available_entities, symb)?; - if new_hoop.len() != dimension || !hoop.contains(new_hoop.first()?) { + let (new_prefix, new_hoop) = self.lollipops_decomposed_named( + reaction_rules, + available_entities, + symb, + )?; + if new_hoop.len() != dimension || !hoop.contains(new_hoop.first()?) + { return None; } invariant.append(&mut new_prefix.clone()); @@ -559,7 +613,8 @@ impl Environment { deltas .iter() .map(|q| { - let (invariant, hoop) = q.invariant_named(reaction_rules, entities, symb)?; + let (invariant, hoop) = + q.invariant_named(reaction_rules, entities, symb)?; let length = invariant.len(); Some((invariant, length, hoop)) }) @@ -659,17 +714,16 @@ impl BasicEnvironment for PositiveEnvironment { } PositiveProcess::Summation { children } => { // short-circuits with try_fold. - children - .iter() - .try_fold(Self::Choices::default(), |mut acc, x| { - match self.unfold(x, entities) { - Ok(mut choices) => { - acc.append(&mut choices); - Ok(acc) - } - Err(e) => Err(e), + children.iter().try_fold( + Self::Choices::default(), + |mut acc, x| match self.unfold(x, entities) { + Ok(mut choices) => { + acc.append(&mut choices); + Ok(acc) } - }) + Err(e) => Err(e), + }, + ) } PositiveProcess::NondeterministicChoice { children } => { // short-circuits with try_fold. @@ -679,12 +733,13 @@ impl BasicEnvironment for PositiveEnvironment { Rc::new(Self::Process::default()), )])) } else { - children - .iter() - .try_fold(Self::Choices::default(), |mut acc, x| { + children.iter().try_fold( + Self::Choices::default(), + |mut acc, x| { acc.shuffle(self.unfold(x, entities)?); Ok(acc) - }) + }, + ) } } } @@ -692,7 +747,11 @@ impl BasicEnvironment for PositiveEnvironment { } impl PrintableWithTranslator for PositiveEnvironment { - fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator) -> std::fmt::Result { + fn print( + &self, + f: &mut std::fmt::Formatter, + translator: &Translator, + ) -> std::fmt::Result { write!(f, "{{env:")?; let mut it = self.iter().peekable(); while let Some(el) = it.next() { @@ -718,7 +777,8 @@ impl PrintableWithTranslator for PositiveEnvironment { impl IntoIterator for PositiveEnvironment { type Item = (IdType, PositiveProcess); - type IntoIter = std::collections::hash_map::IntoIter; + type IntoIter = + std::collections::hash_map::IntoIter; fn into_iter(self) -> Self::IntoIter { self.definitions.into_iter() @@ -727,7 +787,8 @@ impl IntoIterator for PositiveEnvironment { impl<'a> IntoIterator for &'a PositiveEnvironment { type Item = (&'a IdType, &'a PositiveProcess); - type IntoIter = std::collections::hash_map::Iter<'a, IdType, PositiveProcess>; + type IntoIter = + std::collections::hash_map::Iter<'a, IdType, PositiveProcess>; fn into_iter(self) -> Self::IntoIter { self.definitions.iter() diff --git a/src/rsprocess/format_helpers.rs b/src/rsprocess/format_helpers.rs index 9f5af71..46e8092 100644 --- a/src/rsprocess/format_helpers.rs +++ b/src/rsprocess/format_helpers.rs @@ -4,21 +4,29 @@ pub mod graph_map_nodes_ty_from { use super::super::translator; use std::rc::Rc; - type GraphMapNodesFnTy = dyn Fn(petgraph::prelude::NodeIndex, &System) -> String; + type GraphMapNodesFnTy = + dyn Fn(petgraph::prelude::NodeIndex, &System) -> String; pub fn format_string(s: String) -> Box { Box::new(move |_, _| s.clone()) } - pub fn format_hide(_translator: Rc) -> Box { + pub fn format_hide( + _translator: Rc, + ) -> Box { Box::new(|_, _| String::new()) } - pub fn format_entities(translator: Rc) -> Box { + pub fn format_entities( + translator: Rc, + ) -> Box { Box::new(move |_, node: &System| { format!( "{}", - translator::Formatter::from(&translator, &node.available_entities) + translator::Formatter::from( + &translator, + &node.available_entities + ) ) }) } @@ -49,7 +57,9 @@ pub mod graph_map_nodes_ty_from { }) } - pub fn format_context(translator: Rc) -> Box { + pub fn format_context( + translator: Rc, + ) -> Box { Box::new(move |_, node: &System| { format!( "{}", @@ -65,7 +75,8 @@ pub mod graph_map_edges_ty_from { use super::super::translator; use std::rc::Rc; - type GraphMapEdgesFnTy<'a> = dyn Fn(petgraph::prelude::EdgeIndex, &'a Label) -> String + 'a; + type GraphMapEdgesFnTy<'a> = + dyn Fn(petgraph::prelude::EdgeIndex, &'a Label) -> String + 'a; pub fn format_string<'a>( _translator: Rc, @@ -74,7 +85,9 @@ pub mod graph_map_edges_ty_from { Box::new(move |_, _| s.clone()) } - pub fn format_hide<'a>(_translator: Rc) -> Box> { + pub fn format_hide<'a>( + _translator: Rc, + ) -> Box> { Box::new(|_, _| String::new()) } @@ -93,21 +106,42 @@ pub mod graph_map_edges_ty_from { if let Some($mask_name) = $mask_name { if let Some($common_name) = $common_name { Box::new(move |_, $edge_name: &Label| { - format!("{}", translator::Formatter::from(&translator, $mask_common)) + format!( + "{}", + translator::Formatter::from( + &translator, + $mask_common + ) + ) }) } else { Box::new(move |_, $edge_name: &Label| { - format!("{}", translator::Formatter::from(&translator, $mask)) + format!( + "{}", + translator::Formatter::from(&translator, $mask) + ) }) } } else { if let Some($common_name) = $common_name { Box::new(move |_, $edge_name: &Label| { - format!("{}", translator::Formatter::from(&translator, $common)) + format!( + "{}", + translator::Formatter::from( + &translator, + $common + ) + ) }) } else { Box::new(move |_, $edge_name: &Label| { - format!("{}", translator::Formatter::from(&translator, $default)) + format!( + "{}", + translator::Formatter::from( + &translator, + $default + ) + ) }) } } @@ -173,7 +207,8 @@ pub mod graph_map_edges_ty_from { &mask .intersection(&edge.available_entities.subtraction(&edge.products)) .subtraction(&common), - &mask.intersection(&edge.available_entities.subtraction(&edge.products)), + &mask + .intersection(&edge.available_entities.subtraction(&edge.products)), &edge .available_entities .subtraction(&edge.products) @@ -187,7 +222,8 @@ pub mod graph_map_edges_ty_from { &mask .intersection(&edge.products.subtraction(&edge.available_entities)) .subtraction(&common), - &mask.intersection(&edge.products.subtraction(&edge.available_entities)), + &mask + .intersection(&edge.products.subtraction(&edge.available_entities)), &edge .products .subtraction(&edge.available_entities) @@ -207,8 +243,10 @@ pub mod node_formatter { use super::super::set::Set; type RSdotGraph = Graph; - type RSformatNodeTy = - dyn Fn(&RSdotGraph, <&RSdotGraph as IntoNodeReferences>::NodeRef) -> Option; + type RSformatNodeTy = dyn Fn( + &RSdotGraph, + <&RSdotGraph as IntoNodeReferences>::NodeRef, + ) -> Option; pub fn format_nill( original_graph: Rc, @@ -237,7 +275,9 @@ pub mod node_formatter { (true, Process::RecursiveIdentifier { identifier: _ }) => { Some(", fillcolor=".to_string() + &color) } - (false, Process::RecursiveIdentifier { identifier: id }) if id == &s => { + (false, Process::RecursiveIdentifier { identifier: id }) + if id == &s => + { Some(", fillcolor=".to_string() + &color) } _ => None, @@ -258,7 +298,9 @@ pub mod node_formatter { Process::EntitySet { entities, next_process: _, - } if ot.evaluate(entities, &set) => Some(", fillcolor=".to_string() + &color), + } if ot.evaluate(entities, &set) => { + Some(", fillcolor=".to_string() + &color) + } _ => None, } }) @@ -271,7 +313,9 @@ pub mod node_formatter { ) -> Box { Box::new(move |_, n| { let rssystem = original_graph.node_weight(n.0).unwrap(); - if let Process::NondeterministicChoice { children: _ } = rssystem.context_process { + if let Process::NondeterministicChoice { children: _ } = + rssystem.context_process + { Some(", fillcolor=".to_string() + &color) } else { None @@ -286,7 +330,8 @@ pub mod node_formatter { ) -> Box { Box::new(move |_, n| { let rssystem = original_graph.node_weight(n.0).unwrap(); - if let Process::Summation { children: _ } = rssystem.context_process { + if let Process::Summation { children: _ } = rssystem.context_process + { Some(", fillcolor=".to_string() + &color) } else { None @@ -341,8 +386,10 @@ pub mod edge_formatter { use super::super::set::Set; type RSdotGraph = Graph; - type RSformatEdgeTy = - dyn Fn(&RSdotGraph, <&RSdotGraph as IntoEdgeReferences>::EdgeRef) -> Option; + type RSformatEdgeTy = dyn Fn( + &RSdotGraph, + <&RSdotGraph as IntoEdgeReferences>::EdgeRef, + ) -> Option; pub fn format_entities( original_graph: Rc, diff --git a/src/rsprocess/frequency.rs b/src/rsprocess/frequency.rs index 447167e..88b2757 100644 --- a/src/rsprocess/frequency.rs +++ b/src/rsprocess/frequency.rs @@ -5,14 +5,23 @@ use std::fmt::Debug; use super::element::{IdType, PositiveType}; use super::environment::{BasicEnvironment, Environment, PositiveEnvironment}; -use super::reaction::{BasicReaction, ExtensionReaction, PositiveReaction, Reaction}; +use super::reaction::{ + BasicReaction, ExtensionReaction, PositiveReaction, Reaction, +}; use super::set::{BasicSet, ExtensionsSet, PositiveSet, Set}; -use super::system::{BasicSystem, ExtensionsSystem, LoopSystem, PositiveSystem, System}; -use super::translator::{Formatter, PRECISION, PrintableWithTranslator, Translator}; +use super::system::{ + BasicSystem, ExtensionsSystem, LoopSystem, PositiveSystem, System, +}; +use super::translator::{ + Formatter, PRECISION, PrintableWithTranslator, Translator, +}; -pub trait BasicFrequency: Debug + Clone + Default + PrintableWithTranslator { +pub trait BasicFrequency: + Debug + Clone + Default + PrintableWithTranslator +{ type Set: BasicSet; - type Sys: BasicSystem + LoopSystem; + type Sys: BasicSystem + + LoopSystem; type Env: BasicEnvironment; type R: BasicReaction; type Id; @@ -47,7 +56,8 @@ pub struct Frequency { impl Frequency { fn add(&mut self, e: Set, run: usize) { for el in e.iter() { - let entry = self.frequency_map.entry(*el).or_insert(vec![0; run + 1]); + let entry = + self.frequency_map.entry(*el).or_insert(vec![0; run + 1]); if entry.len() < run + 1 { entry.resize(run + 1, 0); } @@ -70,7 +80,11 @@ impl Frequency { } impl PrintableWithTranslator for Frequency { - fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator) -> std::fmt::Result { + fn print( + &self, + f: &mut std::fmt::Formatter, + translator: &Translator, + ) -> std::fmt::Result { use std::cmp::max; write!(f, "[")?; @@ -161,8 +175,11 @@ impl BasicFrequency for Frequency { let mut available_entities = available_entities.clone(); for q in q.iter().rev().skip(1).rev() { - let res = - Self::R::lollipops_only_loop_decomposed_q(reaction_rules, q, &available_entities); + let res = Self::R::lollipops_only_loop_decomposed_q( + reaction_rules, + q, + &available_entities, + ); available_entities = res.into_iter().next()?; } @@ -197,8 +214,11 @@ impl BasicFrequency for Frequency { for (pos, (q, &w)) in q.iter().zip(weights).enumerate() { freq.append_weight(w); - let hoop = - Self::R::lollipops_only_loop_decomposed_q(reaction_rules, q, &available_entities); + let hoop = Self::R::lollipops_only_loop_decomposed_q( + reaction_rules, + q, + &available_entities, + ); hoop.iter().cloned().for_each(|e| freq.add(e, pos)); available_entities = hoop.into_iter().next()?; } @@ -246,7 +266,11 @@ impl PositiveFrequency { } impl PrintableWithTranslator for PositiveFrequency { - fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator) -> std::fmt::Result { + fn print( + &self, + f: &mut std::fmt::Formatter, + translator: &Translator, + ) -> std::fmt::Result { use std::cmp::max; write!(f, "[")?; @@ -337,8 +361,11 @@ impl BasicFrequency for PositiveFrequency { let mut available_entities = available_entities.clone(); for q in q.iter().rev().skip(1).rev() { - let res = - Self::R::lollipops_only_loop_decomposed_q(reaction_rules, q, &available_entities); + let res = Self::R::lollipops_only_loop_decomposed_q( + reaction_rules, + q, + &available_entities, + ); available_entities = res.into_iter().next()?; } @@ -373,8 +400,11 @@ impl BasicFrequency for PositiveFrequency { for (pos, (q, &w)) in q.iter().zip(weights).enumerate() { freq.append_weight(w); - let hoop = - Self::R::lollipops_only_loop_decomposed_q(reaction_rules, q, &available_entities); + let hoop = Self::R::lollipops_only_loop_decomposed_q( + reaction_rules, + q, + &available_entities, + ); hoop.iter().cloned().for_each(|e| freq.add(e, pos)); available_entities = hoop.into_iter().next()?; } diff --git a/src/rsprocess/grammar.lalrpop b/src/rsprocess/grammar.lalrpop index f131f8e..f5850e8 100644 --- a/src/rsprocess/grammar.lalrpop +++ b/src/rsprocess/grammar.lalrpop @@ -2,10 +2,10 @@ use std::rc::Rc; use std::str::FromStr; use lalrpop_util::ParseError; use crate::rsprocess::{set, reaction, process, environment, system, label}; -use crate::rsprocess::assert::types; use crate::rsprocess::element::IdType; use crate::rsprocess::translator::Translator; use crate::rsprocess::presets; +use crate::rsprocess::assert::{relabel, grouping}; use crate::rsprocess::graph; grammar(translator: &mut Translator); @@ -41,9 +41,10 @@ match { "Difference", "MaskDifference", "UncommonDifference", "UncommonMaskDifference", "EntitiesDeleted", "MaskEntitiesDeleted", - "UncommonEntitiesDeleted", "UncommonMaskEntitiesDeleted", + "UncommonEntitiesDeleted", "UncommonMaskEntitiesDeleted", "EntitiesAdded", "MaskEntitiesAdded", - "UncommonEntitiesAdded", "UncommonMaskEntitiesAdded", + "UncommonEntitiesAdded", "UncommonMaskEntitiesAdded", + "node", "entities", "system", "neighbours", "label", "edge", "if", "then", "else", "let", "=", "return", "for", "in", "not", "rand", "empty", "length", "tostr", "source", "target", "&&", "||", "^^", "<=", ">=", "==", "!=", "+", "*", "/", "%", @@ -121,7 +122,11 @@ LiteralProcess: String = { "MaskEntitiesAdded" => <>.into(), "UncommonEntitiesAdded" => <>.into(), "UncommonMaskEntitiesAdded" => <>.into(), + "node" => <>.into(), + "entities" => <>.into(), + "system" => <>.into(), "label" => <>.into(), + "neighbours" => <>.into(), "edge" => <>.into(), "if" => <>.into(), "then" => <>.into(), @@ -152,7 +157,7 @@ LiteralProcess: String = { // all numbers are i64 Num: i64 = { NUMBER =>? i64::from_str(<>) - .map_err(|_| ParseError::User { error: "Number is too big" }) + .map_err(|_| ParseError::User { error: "Number is too big" }) }; Path: String = { @@ -162,11 +167,11 @@ Path: String = { // macro for matching sequence of patterns with C as separator Separated: Vec = { C)+> => match e { - None => v, - Some(e) => { - v.push(e); - v - } + None => v, + Some(e) => { + v.push(e); + v + } } }; @@ -185,8 +190,8 @@ pub Set: set::Set = { Set_of_entities: set::Set = { "{" "}" => set::Set::from(vec![]), "{" > "}" => - set::Set::from(t.into_iter().map(|t| translator.encode(t)) - .collect::>()) + set::Set::from(t.into_iter().map(|t| translator.encode(t)) + .collect::>()) }; @@ -202,11 +207,11 @@ pub Reactions: Vec = { Reaction: reaction::Reaction = { #[precedence(level="1")] "[" "," "," "]" => - reaction::Reaction::from(r, i, p), + reaction::Reaction::from(r, i, p), #[precedence(level="0")] "[" "r:" "," "i:" "," "p:" "]" => - reaction::Reaction::from(r, i, p), + reaction::Reaction::from(r, i, p), } @@ -216,7 +221,7 @@ Reaction: reaction::Reaction = { pub Context: process::Process = { "[" "]" => process::Process::NondeterministicChoice{ children: vec![] }, "[" > "]" => - process::Process::NondeterministicChoice{ children: t } + process::Process::NondeterministicChoice{ children: t } }; Boxed_CTX_process: Rc = { @@ -227,27 +232,27 @@ CTX_process: process::Process = { "nill" => process::Process::Nill, "." => - process::Process::EntitySet{ entities: c, next_process: Rc::new(k) }, + process::Process::EntitySet{ entities: c, next_process: Rc::new(k) }, "(" ")" => k, "(" > ")" => - process::Process::Summation{ - children: k.into_iter().map(Rc::new).collect::>() - }, + process::Process::Summation{ + children: k.into_iter().map(Rc::new).collect::>() + }, "?" "?" "." => - process::Process::Guarded{ reaction: r, next_process: Rc::new(k) }, + process::Process::Guarded{ reaction: r, next_process: Rc::new(k) }, "<" "," ">" "." => - process::Process::WaitEntity{ repeat: n, - repeated_process: Rc::new(k1), - next_process: Rc::new(k) }, + process::Process::WaitEntity{ repeat: n, + repeated_process: Rc::new(k1), + next_process: Rc::new(k) }, => - process::Process::RecursiveIdentifier{ - identifier: translator.encode(identifier) - } + process::Process::RecursiveIdentifier{ + identifier: translator.encode(identifier) + } }; @@ -256,199 +261,21 @@ CTX_process: process::Process = { // ----------------------------------------------------------------------------- pub Environment: Box = { "[" "]" => - Box::new(environment::Environment::default()), + Box::new(environment::Environment::default()), "[" > "]" => - Box::new(environment::Environment::from(t)) + Box::new(environment::Environment::from(t)) }; Env_term: (IdType, process::Process) = { "=" => - (translator.encode(identifier), k) + (translator.encode(identifier), k) }; - // ----------------------------------------------------------------------------- -// AssertParser +// LabelParser // ----------------------------------------------------------------------------- -pub Assert: Box = { - "label" "{" "}" => - Box::new(types::Assert{tree: f}), -}; -AssertTree: types::Tree = { - ";" => - types::Tree::Concat(Box::new(t1), Box::new(t2)), - => t, -} - -AssertTree2: types::Tree = { - #[precedence(level="1")] - "if" - "then" "{" "}" => - types::Tree::If(Box::new(e), Box::new(t)), - - #[precedence(level="0")] - "if" - "then" "{" "}" - "else" "{" "}" => - types::Tree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)), - - #[precedence(level="2")] - "let" "=" => - types::Tree::Assignment(v, q, Box::new(e)), - - #[precedence(level="3")] - "return" => - types::Tree::Return(Box::new(e)), - - #[precedence(level="4")] - "for" "in" "{" "}" => - types::Tree::For(v, r, Box::new(t)), -} - -AssertVariable: types::Variable = { - #[precedence(level="0")] - "label" => types::Variable::Special(types::Special::Label), - #[precedence(level="1")] - "edge" => types::Variable::Special(types::Special::Edge), - #[precedence(level="2")] - => types::Variable::Id(v), -} - - -AssertExpression: types::Expression = { - // Unary - #[precedence(level="0")] - => - types::Expression::Unary(unp, Box::new(e)), - #[precedence(level="2")] - => - types::Expression::Unary(uns, Box::new(e)), - - // binary - #[precedence(level="3")] #[assoc(side="left")] - => - types::Expression::Binary(b, Box::new(e1), Box::new(e2)), - #[precedence(level="1")] - - "(" "," ")" => - types::Expression::Binary(b, Box::new(e1), Box::new(e2)), - - #[precedence(level="4")] - "(" ")" => e, - "true" => types::Expression::True, - "false" => types::Expression::False, - - #[precedence(level="5")] - => types::Expression::Var(v), - - // If changing IntegerType in assert.rs, also change from Num to another - // similar parser with different return type - #[precedence(level="6")] - => types::Expression::Integer(i), - - #[precedence(level="7")] - => types::Expression::Label(Box::new(lab)), - => types::Expression::Set(set), - "'" "'" => types::Expression::Element(translator.encode(el)), - - // strings - #[precedence(level="8")] - PATH => types::Expression::String(<>.trim_end_matches("\"") - .trim_start_matches("\"") - .to_string()), -} - -AssertRange: types::Range = { - "{" "}" => types::Range::IterateOverSet(Box::new(e)), - "{" ".." "}" => - types::Range::IterateInRange(Box::new(e1), Box::new(e2)), -} - -AssertUnaryPrefix: types::Unary = { - "not" => types::Unary::Not, - "rand" => types::Unary::Rand, -} - -AssertUnarySuffix: types::Unary = { - #[precedence(level="0")] - "." "empty" => types::Unary::Empty, - "." "length" => types::Unary::Length, - "." "tostr" => types::Unary::ToStr, - "." "toel" => types::Unary::ToEl, - - #[precedence(level="1")] - "." => types::Unary::Qualifier(q), -} - -AssertQualifierRestricted: types::QualifierRestricted = { - "Entities" => types::QualifierRestricted::Entities, - "Context" => types::QualifierRestricted::Context, - "Reactants" => types::QualifierRestricted::Reactants, - "ReactantsAbsent" => types::QualifierRestricted::ReactantsAbsent, - "Inhibitors" => types::QualifierRestricted::Inhibitors, - "InhibitorsPresent" => types::QualifierRestricted::InhibitorsPresent, - "Products" => types::QualifierRestricted::Products, -} - -AssertQualifierLabel: types::QualifierLabel = { - "AvailableEntities" => types::QualifierLabel::AvailableEntities, - "AllReactants" => types::QualifierLabel::AllReactants, - "AllInhibitors" => types::QualifierLabel::AllInhibitors, -} - -AssertQualifierSystem: types::QualifierSystem = { - "SystemEntities" => types::QualifierSystem::Entities, - "SystemContext" => types::QualifierSystem::Context, -} - -AssertQualifierEdge: types::QualifierEdge = { - "source" => types::QualifierEdge::Source, - "target" => types::QualifierEdge::Target, -} - -AssertQualifierNode: types::QualifierNode = { - "neighbours" => types::QualifierNode::Neighbours, - "system" => types::QualifierNode::System, -} - -AssertQualifier: types::Qualifier = { - => types::Qualifier::System(q), - => types::Qualifier::Label(q), - => types::Qualifier::Restricted(q), - => types::Qualifier::Edge(q), - => types::Qualifier::Node(q), -} - - -AssertBinary: types::Binary = { - "&&" => types::Binary::And, - "||" => types::Binary::Or, - "^^" => types::Binary::Xor, - "<" => types::Binary::Less, - "<=" => types::Binary::LessEq, - ">" => types::Binary::More, - ">=" => types::Binary::MoreEq, - "==" => types::Binary::Eq, - "!=" => types::Binary::NotEq, - "+" => types::Binary::Plus, - "-" => types::Binary::Minus, - "*" => types::Binary::Times, - "^" => types::Binary::Exponential, - "/" => types::Binary::Quotient, - "%" => types::Binary::Reminder, - "::" => types::Binary::Concat, -} - -AssertBinaryPrefix: types::Binary = { - "substr" => types::Binary::SubStr, - "min" => types::Binary::Min, - "max" => types::Binary::Max, - "commonsubstr" => types::Binary::CommonSubStr, -} - - -AssertLabel: label::Label = { +Label: label::Label = { "[" "Entities" ":" "," "Context" ":" "," @@ -460,6 +287,370 @@ AssertLabel: label::Label = { "]" => label::Label::create(e, c, r, r_a, i, i_p, p) } + +// ----------------------------------------------------------------------------- +// AssertParser +// ----------------------------------------------------------------------------- +pub Assert: Box = { + "label" "{" "}" => + Box::new(relabel::Assert{tree: f}), +}; + +AssertTree: relabel::Tree = { + ";" => + relabel::Tree::Concat(Box::new(t1), Box::new(t2)), + => t, +} + +AssertTree2: relabel::Tree = { + #[precedence(level="1")] + "if" + "then" "{" "}" => + relabel::Tree::If(Box::new(e), Box::new(t)), + + #[precedence(level="0")] + "if" + "then" "{" "}" + "else" "{" "}" => + relabel::Tree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)), + + #[precedence(level="2")] + "let" "=" => + relabel::Tree::Assignment(v, q, Box::new(e)), + + #[precedence(level="3")] + "return" => + relabel::Tree::Return(Box::new(e)), + + #[precedence(level="4")] + "for" "in" "{" "}" => + relabel::Tree::For(v, r, Box::new(t)), +} + +AssertVariable: relabel::Variable = { + #[precedence(level="0")] + "label" => relabel::Variable::Special(relabel::Special::Label), + #[precedence(level="1")] + "edge" => relabel::Variable::Special(relabel::Special::Edge), + #[precedence(level="2")] + => relabel::Variable::Id(v), +} + + +AssertExpression: relabel::Expression = { + // Unary + #[precedence(level="0")] + => + relabel::Expression::Unary(unp, Box::new(e)), + #[precedence(level="2")] + => + relabel::Expression::Unary(uns, Box::new(e)), + + // binary + #[precedence(level="3")] #[assoc(side="left")] + => + relabel::Expression::Binary(b, Box::new(e1), Box::new(e2)), + #[precedence(level="1")] + + "(" "," ")" => + relabel::Expression::Binary(b, Box::new(e1), Box::new(e2)), + + #[precedence(level="4")] + "(" ")" => e, + "true" => relabel::Expression::True, + "false" => relabel::Expression::False, + + #[precedence(level="5")] + => relabel::Expression::Var(v), + + // If changing IntegerType in assert.rs, also change from Num to another + // similar parser with different return type + #[precedence(level="6")] + => relabel::Expression::Integer(i), + + #[precedence(level="7")] + => relabel::Expression::Label(Box::new(lab)), + => relabel::Expression::Set(set), + "'" "'" => relabel::Expression::Element(translator.encode(el)), + + // strings + #[precedence(level="8")] + PATH => relabel::Expression::String(<>.trim_end_matches("\"") + .trim_start_matches("\"") + .to_string()), +} + +AssertRange: relabel::Range = { + "{" "}" => relabel::Range::IterateOverSet(Box::new(e)), + "{" ".." "}" => + relabel::Range::IterateInRange(Box::new(e1), Box::new(e2)), +} + +AssertUnaryPrefix: relabel::Unary = { + "not" => relabel::Unary::Not, + "rand" => relabel::Unary::Rand, +} + +AssertUnarySuffix: relabel::Unary = { + #[precedence(level="0")] + "." "empty" => relabel::Unary::Empty, + "." "length" => relabel::Unary::Length, + "." "tostr" => relabel::Unary::ToStr, + "." "toel" => relabel::Unary::ToEl, + + #[precedence(level="1")] + "." => relabel::Unary::Qualifier(q), +} + +AssertQualifierRestricted: relabel::QualifierRestricted = { + "Entities" => relabel::QualifierRestricted::Entities, + "Context" => relabel::QualifierRestricted::Context, + "Reactants" => relabel::QualifierRestricted::Reactants, + "ReactantsAbsent" => relabel::QualifierRestricted::ReactantsAbsent, + "Inhibitors" => relabel::QualifierRestricted::Inhibitors, + "InhibitorsPresent" => relabel::QualifierRestricted::InhibitorsPresent, + "Products" => relabel::QualifierRestricted::Products, +} + +AssertQualifierLabel: relabel::QualifierLabel = { + "AvailableEntities" => relabel::QualifierLabel::AvailableEntities, + "AllReactants" => relabel::QualifierLabel::AllReactants, + "AllInhibitors" => relabel::QualifierLabel::AllInhibitors, +} + +AssertQualifierSystem: relabel::QualifierSystem = { + "SystemEntities" => relabel::QualifierSystem::Entities, + "SystemContext" => relabel::QualifierSystem::Context, +} + +AssertQualifierEdge: relabel::QualifierEdge = { + "source" => relabel::QualifierEdge::Source, + "target" => relabel::QualifierEdge::Target, +} + +AssertQualifierNode: relabel::QualifierNode = { + "neighbours" => relabel::QualifierNode::Neighbours, + "system" => relabel::QualifierNode::System, +} + +AssertQualifier: relabel::Qualifier = { + => relabel::Qualifier::System(q), + => relabel::Qualifier::Label(q), + => relabel::Qualifier::Restricted(q), + => relabel::Qualifier::Edge(q), + => relabel::Qualifier::Node(q), +} + + +AssertBinary: relabel::Binary = { + "&&" => relabel::Binary::And, + "||" => relabel::Binary::Or, + "^^" => relabel::Binary::Xor, + "<" => relabel::Binary::Less, + "<=" => relabel::Binary::LessEq, + ">" => relabel::Binary::More, + ">=" => relabel::Binary::MoreEq, + "==" => relabel::Binary::Eq, + "!=" => relabel::Binary::NotEq, + "+" => relabel::Binary::Plus, + "-" => relabel::Binary::Minus, + "*" => relabel::Binary::Times, + "^" => relabel::Binary::Exponential, + "/" => relabel::Binary::Quotient, + "%" => relabel::Binary::Reminder, + "::" => relabel::Binary::Concat, +} + +AssertBinaryPrefix: relabel::Binary = { + "substr" => relabel::Binary::SubStr, + "min" => relabel::Binary::Min, + "max" => relabel::Binary::Max, + "commonsubstr" => relabel::Binary::CommonSubStr, +} + +// ----------------------------------------------------------------------------- +// GroupingParser +// ----------------------------------------------------------------------------- +pub Group: Box = { + ">" "node" "{" "}" => + Box::new(grouping::Assert{tree: f}), +}; + +GroupTree: grouping::Tree = { + ";" => + grouping::Tree::Concat(Box::new(t1), Box::new(t2)), + => t, +} + +GroupTree2: grouping::Tree = { + #[precedence(level="1")] + "if" + "then" "{" "}" => + grouping::Tree::If(Box::new(e), Box::new(t)), + + #[precedence(level="0")] + "if" + "then" "{" "}" + "else" "{" "}" => + grouping::Tree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)), + + #[precedence(level="2")] + "let" "=" => + grouping::Tree::Assignment(v, q, Box::new(e)), + + #[precedence(level="3")] + "return" => + grouping::Tree::Return(Box::new(e)), + + #[precedence(level="4")] + "for" "in" "{" "}" => + grouping::Tree::For(v, r, Box::new(t)), +} + +GroupVariable: grouping::Variable = { + #[precedence(level="0")] + "entities" => grouping::Variable::Special(grouping::Special::Entities), + #[precedence(level="1")] + "node" => grouping::Variable::Special(grouping::Special::Node), + #[precedence(level="2")] + => grouping::Variable::Id(v), +} + +GroupExpression: grouping::Expression = { + #[precedence(level="100")] + "(" ")" => + grouping::Expression::Unary(unp, Box::new(e)), + + #[precedence(level="100")] + "." => + grouping::Expression::Unary(uns, Box::new(e)), + + #[precedence(level="100")] #[assoc(side="left")] + "(" ")" => + grouping::Expression::Binary(b, Box::new(e1), Box::new(e2)), + + #[precedence(level="100")] + + "(" "," ")" => + grouping::Expression::Binary(b, Box::new(e1), Box::new(e2)), + + #[precedence(level="50")] + "(" ")" => e, + + #[precedence(level="0")] + => t, +} + +GroupTerm: grouping::Expression = { + "true" => grouping::Expression::True, + "false" => grouping::Expression::False, + + => grouping::Expression::Var(v), + + // If changing IntegerType in assert.rs, also change from Num to another + // similar parser with different return type + => grouping::Expression::Integer(i), + + => grouping::Expression::Label(Box::new(lab)), + => grouping::Expression::Set(set), + "'" "'" => grouping::Expression::Element(translator.encode(el)), + + // strings + PATH => grouping::Expression::String(<>.trim_end_matches("\"") + .trim_start_matches("\"") + .to_string()), +} + +GroupRange: grouping::Range = { + "{" "}" => grouping::Range::IterateOverSet(Box::new(e)), + "{" ".." "}" => + grouping::Range::IterateInRange(Box::new(e1), Box::new(e2)), +} + +GroupUnaryPrefix: grouping::Unary = { + "not" => grouping::Unary::Not, + "rand" => grouping::Unary::Rand, +} + +GroupUnarySuffix: grouping::Unary = { + #[precedence(level="0")] + "empty" => grouping::Unary::Empty, + "length" => grouping::Unary::Length, + "tostr" => grouping::Unary::ToStr, + "toel" => grouping::Unary::ToEl, + + #[precedence(level="1")] + => grouping::Unary::Qualifier(q), +} + +GroupQualifierRestricted: grouping::QualifierRestricted = { + "Entities" => grouping::QualifierRestricted::Entities, + "Context" => grouping::QualifierRestricted::Context, + "Reactants" => grouping::QualifierRestricted::Reactants, + "ReactantsAbsent" => grouping::QualifierRestricted::ReactantsAbsent, + "Inhibitors" => grouping::QualifierRestricted::Inhibitors, + "InhibitorsPresent" => grouping::QualifierRestricted::InhibitorsPresent, + "Products" => grouping::QualifierRestricted::Products, +} + +GroupQualifierLabel: grouping::QualifierLabel = { + "AvailableEntities" => grouping::QualifierLabel::AvailableEntities, + "AllReactants" => grouping::QualifierLabel::AllReactants, + "AllInhibitors" => grouping::QualifierLabel::AllInhibitors, +} + +GroupQualifierSystem: grouping::QualifierSystem = { + "SystemEntities" => grouping::QualifierSystem::Entities, + "SystemContext" => grouping::QualifierSystem::Context, +} + +GroupQualifierEdge: grouping::QualifierEdge = { + "source" => grouping::QualifierEdge::Source, + "target" => grouping::QualifierEdge::Target, +} + +GroupQualifierNode: grouping::QualifierNode = { + "neighbours" => grouping::QualifierNode::Neighbours, + "system" => grouping::QualifierNode::System, +} + +GroupQualifier: grouping::Qualifier = { + => grouping::Qualifier::System(q), + => grouping::Qualifier::Label(q), + => grouping::Qualifier::Restricted(q), + => grouping::Qualifier::Edge(q), + => grouping::Qualifier::Node(q), +} + + +GroupBinary: grouping::Binary = { + "&&" => grouping::Binary::And, + "||" => grouping::Binary::Or, + "^^" => grouping::Binary::Xor, + "<" => grouping::Binary::Less, + "<=" => grouping::Binary::LessEq, + ">" => grouping::Binary::More, + ">=" => grouping::Binary::MoreEq, + "==" => grouping::Binary::Eq, + "!=" => grouping::Binary::NotEq, + "+" => grouping::Binary::Plus, + "-" => grouping::Binary::Minus, + "*" => grouping::Binary::Times, + "^" => grouping::Binary::Exponential, + "/" => grouping::Binary::Quotient, + "%" => grouping::Binary::Reminder, + "::" => grouping::Binary::Concat, +} + +GroupBinaryPrefix: grouping::Binary = { + "substr" => grouping::Binary::SubStr, + "min" => grouping::Binary::Min, + "max" => grouping::Binary::Max, + "commonsubstr" => grouping::Binary::CommonSubStr, +} + + + // ----------------------------------------------------------------------------- // BHMLParser // ----------------------------------------------------------------------------- @@ -473,9 +664,9 @@ AssertLabel: label::Label = { // "(" > ")" => RSBHML::Or(g), // "(" > ")" => RSBHML::And(g), // "<" ">" => -// RSBHML::Diamond(Box::new(f), Box::new(g)), +// RSBHML::Diamond(Box::new(f), Box::new(g)), // "[" "]" => -// RSBHML::Box(Box::new(f), Box::new(g)), +// RSBHML::Box(Box::new(f), Box::new(g)), // }; @@ -491,10 +682,10 @@ pub System: system::System = { "Initial Entities" ":" "Context" ":" "Reactions" ":" - => system::System::from(delta.into(), - available_entities, - context_process, - Rc::new(reaction_rules)) + => system::System::from(delta.into(), + available_entities, + context_process, + Rc::new(reaction_rules)) } // experiment @@ -503,7 +694,7 @@ pub System: system::System = { pub Experiment: (Vec, Vec) = { "Weights" ":" > "Sets" ":" > - => (w.into_iter().map(|x| x as u32).collect::>(), s), + => (w.into_iter().map(|x| x as u32).collect::>(), s), } @@ -514,202 +705,202 @@ pub Experiment: (Vec, Vec) = { /// Decides whetherer to print to stdout or to save to file Helper_SO: presets::SaveOptions = { "Print" => - presets::SaveOptions {print: true, save: None}, + presets::SaveOptions {print: true, save: None}, "Save" "(" ")" => - presets::SaveOptions {print: false, save: Some(vec![p])} + presets::SaveOptions {print: false, save: Some(vec![p])} } /// we could need to save to multiple files SaveOptions: presets::SaveOptions = { > => { - p.into_iter() - .reduce(|mut acc, mut e| {acc.combine(&mut e); acc}) - .unwrap_or_default() + p.into_iter() + .reduce(|mut acc, mut e| {acc.combine(&mut e); acc}) + .unwrap_or_default() } } /// Match for strings between nodes formatters LiteralSeparatorNode: graph::NodeDisplayBase = { PATH => - graph::NodeDisplayBase::String { - string: <>.trim_end_matches("\"") - .trim_start_matches("\"") - .to_string() - } + graph::NodeDisplayBase::String { + string: <>.trim_end_matches("\"") + .trim_start_matches("\"") + .to_string() + } }; /// Match for strings between edge formatters LiteralSeparatorEdge: graph::EdgeDisplayBase = { PATH => - graph::EdgeDisplayBase::String { - string: <>.trim_end_matches("\"") - .trim_start_matches("\"") - .to_string() - } + graph::EdgeDisplayBase::String { + string: <>.trim_end_matches("\"") + .trim_start_matches("\"") + .to_string() + } }; NodeDisplayBase: graph::NodeDisplayBase = { "Hide" => - graph::NodeDisplayBase::Hide, + graph::NodeDisplayBase::Hide, "Entities" => - graph::NodeDisplayBase::Entities, + graph::NodeDisplayBase::Entities, "MaskEntities" => - graph::NodeDisplayBase::MaskEntities{mask}, + graph::NodeDisplayBase::MaskEntities{mask}, "ExcludeEntities" => graph::NodeDisplayBase::ExcludeEntities{mask}, "Context" => - graph::NodeDisplayBase::Context, + graph::NodeDisplayBase::Context, "UncommonEntities" => - graph::NodeDisplayBase::UncommonEntities, + graph::NodeDisplayBase::UncommonEntities, "MaskUncommonentities" => - graph::NodeDisplayBase::MaskUncommonEntities{mask}, + graph::NodeDisplayBase::MaskUncommonEntities{mask}, } /// Node display formatters separated by arbitrary strings in quotes SeparatorNode: graph::NodeDisplay = { => graph::NodeDisplay {base: vec![v]}, )+> => - match e { - None => graph::NodeDisplay { - base: - v.iter().fold(vec![], - |mut acc, (a, b)| { - acc.push(a.clone()); - acc.push(b.clone()); - acc.clone() - }) - }, - Some(e) => { - let mut v = v.iter().fold(vec![], - |mut acc, (a, b)| { - acc.push(a.clone()); - acc.push(b.clone()); - acc.clone() - }); - v.push(e); - graph::NodeDisplay { base: v } - } - } + match e { + None => graph::NodeDisplay { + base: + v.iter().fold(vec![], + |mut acc, (a, b)| { + acc.push(a.clone()); + acc.push(b.clone()); + acc.clone() + }) + }, + Some(e) => { + let mut v = v.iter().fold(vec![], + |mut acc, (a, b)| { + acc.push(a.clone()); + acc.push(b.clone()); + acc.clone() + }); + v.push(e); + graph::NodeDisplay { base: v } + } + } } EdgeDisplay: graph::EdgeDisplayBase = { "Hide" => - graph::EdgeDisplayBase::Hide, + graph::EdgeDisplayBase::Hide, "Products" => - graph::EdgeDisplayBase::Products - { mask: None, filter_common: false }, + graph::EdgeDisplayBase::Products + { mask: None, filter_common: false }, "MaskProducts" => - graph::EdgeDisplayBase::Entities - { mask: Some(mask), filter_common: false }, + graph::EdgeDisplayBase::Entities + { mask: Some(mask), filter_common: false }, "UncommonProducts" => - graph::EdgeDisplayBase::Products - { mask: None, filter_common: true }, + graph::EdgeDisplayBase::Products + { mask: None, filter_common: true }, "UncommonMaskProducts" => - graph::EdgeDisplayBase::Entities - { mask: Some(mask), filter_common: true }, + graph::EdgeDisplayBase::Entities + { mask: Some(mask), filter_common: true }, "Entities" => - graph::EdgeDisplayBase::Entities - { mask: None, filter_common: false }, + graph::EdgeDisplayBase::Entities + { mask: None, filter_common: false }, "MaskEntities" => - graph::EdgeDisplayBase::Entities - { mask: Some(mask), filter_common: false }, + graph::EdgeDisplayBase::Entities + { mask: Some(mask), filter_common: false }, "UncommonEntities" => - graph::EdgeDisplayBase::Entities - { mask: None, filter_common: true }, + graph::EdgeDisplayBase::Entities + { mask: None, filter_common: true }, "UncommonMaskEntities" => - graph::EdgeDisplayBase::Entities - { mask: Some(mask), filter_common: true }, + graph::EdgeDisplayBase::Entities + { mask: Some(mask), filter_common: true }, "Context" => - graph::EdgeDisplayBase::Context - { mask: None, filter_common: false }, + graph::EdgeDisplayBase::Context + { mask: None, filter_common: false }, "MaskContext" => - graph::EdgeDisplayBase::Context - { mask: Some(mask), filter_common: false }, + graph::EdgeDisplayBase::Context + { mask: Some(mask), filter_common: false }, "UncommonContext" => - graph::EdgeDisplayBase::Context - { mask: None, filter_common: true }, + graph::EdgeDisplayBase::Context + { mask: None, filter_common: true }, "UncommonMaskContext" => - graph::EdgeDisplayBase::Context - { mask: Some(mask), filter_common: true }, + graph::EdgeDisplayBase::Context + { mask: Some(mask), filter_common: true }, "Union" => - graph::EdgeDisplayBase::Union - { mask: None, filter_common: false }, + graph::EdgeDisplayBase::Union + { mask: None, filter_common: false }, "MaskUnion" => - graph::EdgeDisplayBase::Union - { mask: Some(mask), filter_common: false }, + graph::EdgeDisplayBase::Union + { mask: Some(mask), filter_common: false }, "UncommonUnion" => - graph::EdgeDisplayBase::Union - { mask: None, filter_common: true }, + graph::EdgeDisplayBase::Union + { mask: None, filter_common: true }, "UncommonMaskUnion" => - graph::EdgeDisplayBase::Union - { mask: Some(mask), filter_common: true }, + graph::EdgeDisplayBase::Union + { mask: Some(mask), filter_common: true }, "Difference" => - graph::EdgeDisplayBase::Difference - { mask: None, filter_common: false }, + graph::EdgeDisplayBase::Difference + { mask: None, filter_common: false }, "MaskDifference" => - graph::EdgeDisplayBase::Difference - { mask: Some(mask), filter_common: false }, + graph::EdgeDisplayBase::Difference + { mask: Some(mask), filter_common: false }, "UncommonDifference" => - graph::EdgeDisplayBase::Difference - { mask: None, filter_common: true }, + graph::EdgeDisplayBase::Difference + { mask: None, filter_common: true }, "UncommonMaskDifference" => - graph::EdgeDisplayBase::Difference - { mask: Some(mask), filter_common: true }, + graph::EdgeDisplayBase::Difference + { mask: Some(mask), filter_common: true }, "EntitiesDeleted" => - graph::EdgeDisplayBase::EntitiesDeleted - { mask: None, filter_common: false }, + graph::EdgeDisplayBase::EntitiesDeleted + { mask: None, filter_common: false }, "MaskEntitiesDeleted" => - graph::EdgeDisplayBase::EntitiesDeleted - { mask: Some(mask), filter_common: false }, + graph::EdgeDisplayBase::EntitiesDeleted + { mask: Some(mask), filter_common: false }, "UncommonEntitiesDeleted" => - graph::EdgeDisplayBase::EntitiesDeleted - { mask: None, filter_common: true }, + graph::EdgeDisplayBase::EntitiesDeleted + { mask: None, filter_common: true }, "UncommonMaskEntitiesDeleted" => - graph::EdgeDisplayBase::EntitiesDeleted - { mask: Some(mask), filter_common: true }, + graph::EdgeDisplayBase::EntitiesDeleted + { mask: Some(mask), filter_common: true }, "EntitiesAdded" => - graph::EdgeDisplayBase::EntitiesAdded - { mask: None, filter_common: false }, + graph::EdgeDisplayBase::EntitiesAdded + { mask: None, filter_common: false }, "MaskEntitiesAdded" => - graph::EdgeDisplayBase::EntitiesAdded - { mask: Some(mask), filter_common: false }, + graph::EdgeDisplayBase::EntitiesAdded + { mask: Some(mask), filter_common: false }, "UncommonEntitiesAdded" => - graph::EdgeDisplayBase::EntitiesAdded - { mask: None, filter_common: true }, + graph::EdgeDisplayBase::EntitiesAdded + { mask: None, filter_common: true }, "UncommonMaskEntitiesAdded" => - graph::EdgeDisplayBase::EntitiesAdded - { mask: Some(mask), filter_common: true }, + graph::EdgeDisplayBase::EntitiesAdded + { mask: Some(mask), filter_common: true }, } /// Edge display formatters separated by arbitrary strings in quotes SeparatorEdge: graph::EdgeDisplay = { => graph::EdgeDisplay{ base: vec![v] }, )+> => - match e { - None => graph::EdgeDisplay{ base: v.iter().fold(vec![], - |mut acc, (a, b)| { - acc.push(a.clone()); - acc.push(b.clone()); - acc.clone() - }) }, - Some(e) => { - let mut v = v.iter().fold(vec![], - |mut acc, (a, b)| { - acc.push(a.clone()); - acc.push(b.clone()); - acc.clone() - }); - v.push(e); - graph::EdgeDisplay{ base: v } - } - } + match e { + None => graph::EdgeDisplay{ base: v.iter().fold(vec![], + |mut acc, (a, b)| { + acc.push(a.clone()); + acc.push(b.clone()); + acc.clone() + }) }, + Some(e) => { + let mut v = v.iter().fold(vec![], + |mut acc, (a, b)| { + acc.push(a.clone()); + acc.push(b.clone()); + acc.clone() + }); + v.push(e); + graph::EdgeDisplay{ base: v } + } + } } Operation: graph::OperationType = { @@ -727,34 +918,34 @@ Operation: graph::OperationType = { NodeColorConditional: (graph::NodeColorConditional, String) = { "Entities" "?" => - (graph::NodeColorConditional::EntitiesConditional(op, set), - color.to_string()), + (graph::NodeColorConditional::EntitiesConditional(op, set), + color.to_string()), "Context.Nill" "?" => - (graph::NodeColorConditional::ContextConditional( - graph::ContextColorConditional::Nill), - color.to_string()), + (graph::NodeColorConditional::ContextConditional( + graph::ContextColorConditional::Nill), + color.to_string()), "Context.RecursiveIdentifier" "(" ")" "?" => - (graph::NodeColorConditional::ContextConditional( - graph::ContextColorConditional::RecursiveIdentifier( - translator.encode(x) - )), - color.to_string()), + (graph::NodeColorConditional::ContextConditional( + graph::ContextColorConditional::RecursiveIdentifier( + translator.encode(x) + )), + color.to_string()), "Context.EntitySet" "?" => - (graph::NodeColorConditional::ContextConditional( - graph::ContextColorConditional::EntitySet(op, set)), - color.to_string()), + (graph::NodeColorConditional::ContextConditional( + graph::ContextColorConditional::EntitySet(op, set)), + color.to_string()), "Context.NonDeterministicChoice" "?" => - (graph::NodeColorConditional::ContextConditional( - graph::ContextColorConditional::NonDeterministicChoice), - color.to_string()), + (graph::NodeColorConditional::ContextConditional( + graph::ContextColorConditional::NonDeterministicChoice), + color.to_string()), "Context.Summation" "?" => - (graph::NodeColorConditional::ContextConditional( - graph::ContextColorConditional::Summation), - color.to_string()), + (graph::NodeColorConditional::ContextConditional( + graph::ContextColorConditional::Summation), + color.to_string()), "Context.WaitEntity" "?" => - (graph::NodeColorConditional::ContextConditional( - graph::ContextColorConditional::WaitEntity), - color.to_string()), + (graph::NodeColorConditional::ContextConditional( + graph::ContextColorConditional::WaitEntity), + color.to_string()), } @@ -762,112 +953,127 @@ NodeColorConditional: (graph::NodeColorConditional, String) = { ColorNode: graph::NodeColor = { > "!" => - graph::NodeColor { conditionals, - base_color: base_color.to_string() }, + graph::NodeColor { conditionals, + base_color: base_color.to_string() }, "!" => - graph::NodeColor { conditionals: vec![], - base_color: base_color.to_string() }, + graph::NodeColor { conditionals: vec![], + base_color: base_color.to_string() }, } EdgeColorConditional: (graph::EdgeColorConditional, String) = { "Entities" "?" => - (graph::EdgeColorConditional::Entities(op, set), - color.to_string()), + (graph::EdgeColorConditional::Entities(op, set), + color.to_string()), "Context" "?" => - (graph::EdgeColorConditional::Context(op, set), - color.to_string()), + (graph::EdgeColorConditional::Context(op, set), + color.to_string()), "T" "?" => - (graph::EdgeColorConditional::T(op, set), - color.to_string()), + (graph::EdgeColorConditional::T(op, set), + color.to_string()), "Reactants" "?" => - (graph::EdgeColorConditional::Reactants(op, set), - color.to_string()), + (graph::EdgeColorConditional::Reactants(op, set), + color.to_string()), "AbsentReactants" "?" => - (graph::EdgeColorConditional::ReactantsAbsent(op, set), - color.to_string()), + (graph::EdgeColorConditional::ReactantsAbsent(op, set), + color.to_string()), "Inhibitors" "?" => - (graph::EdgeColorConditional::Inhibitors(op, set), - color.to_string()), + (graph::EdgeColorConditional::Inhibitors(op, set), + color.to_string()), "PresentInhibitors" "?" => - (graph::EdgeColorConditional::InhibitorsPresent(op, set), - color.to_string()), + (graph::EdgeColorConditional::InhibitorsPresent(op, set), + color.to_string()), "Products" "?" => - (graph::EdgeColorConditional::Products(op, set), - color.to_string()), + (graph::EdgeColorConditional::Products(op, set), + color.to_string()), } ColorEdge: graph::EdgeColor = { > "!" => - graph::EdgeColor { conditionals, - base_color: base_color.to_string() }, + graph::EdgeColor { conditionals, + base_color: base_color.to_string() }, "!" => - graph::EdgeColor { conditionals: vec![], - base_color: base_color.to_string() }, + graph::EdgeColor { conditionals: vec![], + base_color: base_color.to_string() }, } GraphSaveOptions: presets::GraphSaveOptions = { - "Dot" "|"? "|" "|" - "|" ">" - => - presets::GraphSaveOptions::Dot { node_display: s_node, - edge_display: s_edge, - node_color: c_node, - edge_color: c_edge, - so }, - "GraphML" "|"? "|" ">" - => - presets::GraphSaveOptions::GraphML { node_display: s_node, - edge_display: s_edge, - so }, + "Dot" + "|"? + "|" + "|" + "|" + ">" => + presets::GraphSaveOptions::Dot { node_display: s_node, + edge_display: s_edge, + node_color: c_node, + edge_color: c_edge, + so }, + "GraphML" + "|"? + "|" + ">" => + presets::GraphSaveOptions::GraphML { node_display: s_node, + edge_display: s_edge, + so }, "Serialize" "(" ")" => - presets::GraphSaveOptions::Serialize { path }, + presets::GraphSaveOptions::Serialize { path }, } Instruction: presets::Instruction = { - "Stats" ">" => - presets::Instruction::Stats { so }, - "Target" ">" => - presets::Instruction::Target { so }, - "Run" ">" => - presets::Instruction::Run { so }, - "Loop" "(" ")" ">" => - presets::Instruction::Loop { symbol, so }, - "Frequency" ">" => - presets::Instruction::Frequency { so }, - "LimitFrequency" "(" ")" ">" => - presets::Instruction::LimitFrequency { experiment: p, so }, - "FastFrequency" "(" ")" ">" => - presets::Instruction::FastFrequency { experiment: p, so }, - "Digraph" ">" > => - presets::Instruction::Digraph { gso }, - "Bisimilarity" "(" ")" "relabel" - ">" => - presets::Instruction::Bisimilarity { - system_b: p, - edge_relabeler, - so - }, + "Stats" + ">" => + presets::Instruction::Stats { so }, + "Target" + ">" => + presets::Instruction::Target { so }, + "Run" + ">" => + presets::Instruction::Run { so }, + "Loop" "(" ")" + ">" => + presets::Instruction::Loop { symbol, so }, + "Frequency" + ">" => + presets::Instruction::Frequency { so }, + "LimitFrequency" "(" ")" + ">" => + presets::Instruction::LimitFrequency { experiment: p, so }, + "FastFrequency" "(" ")" + ">" => + presets::Instruction::FastFrequency { experiment: p, so }, + "Digraph" + + ">" > => + presets::Instruction::Digraph { group, gso }, + "Bisimilarity" "(" ")" + "relabel" + ">" => + presets::Instruction::Bisimilarity { + system_b: p, + edge_relabeler, + so + }, } pub Run: presets::Instructions = { #[precedence(level="0")] > => - presets::Instructions { system: presets::System::System { sys }, - instructions: instr }, + presets::Instructions { system: presets::System::System { sys }, + instructions: instr }, #[precedence(level="1")] => - presets::Instructions { system: presets::System::System { sys }, - instructions: vec![] }, + presets::Instructions { system: presets::System::System { sys }, + instructions: vec![] }, #[precedence(level="2")] "Deserialize" "(" ")" > => - presets::Instructions { system: presets::System::Deserialize { path }, - instructions: instr }, + presets::Instructions { system: presets::System::Deserialize { path }, + instructions: instr }, } diff --git a/src/rsprocess/graph.rs b/src/rsprocess/graph.rs index 4597e88..0750116 100644 --- a/src/rsprocess/graph.rs +++ b/src/rsprocess/graph.rs @@ -106,17 +106,23 @@ where { fn map_edges( &self, - edge_map: &super::assert::types::Assert, + edge_map: &super::assert::relabel::Assert, translator: &mut super::translator::Translator, - ) -> Result, String>; + ) -> Result< + Graph, + String, + >; } impl<'a> MapEdges<'a, System, Label, Directed, u32> for SystemGraph { fn map_edges( &self, - edge_map: &super::assert::types::Assert, + edge_map: &super::assert::relabel::Assert, translator: &mut super::translator::Translator, - ) -> Result, String> { + ) -> Result< + Graph, + String, + > { use petgraph::graph::EdgeIndex; let mut g = Graph::with_capacity(self.node_count(), self.edge_count()); @@ -126,12 +132,12 @@ impl<'a> MapEdges<'a, System, Label, Directed, u32> for SystemGraph { let edges = edges .iter() .enumerate() - .map( - |(i, edge)| match edge_map.execute(self, &EdgeIndex::new(i), translator) { + .map(|(i, edge)| { + match edge_map.execute(self, &EdgeIndex::new(i), translator) { Err(e) => Err(e), Ok(val) => Ok((edge.source(), edge.target(), val)), - }, - ) + } + }) .collect::, _>>()?; nodes.iter().for_each(|node| { g.add_node(node.weight.clone()); @@ -164,7 +170,8 @@ pub struct NodeDisplay { pub base: Vec, } -type GraphMapNodesFnTy<'a> = dyn Fn(petgraph::prelude::NodeIndex, &'a System) -> String + 'a; +type GraphMapNodesFnTy<'a> = + dyn Fn(petgraph::prelude::NodeIndex, &'a System) -> String + 'a; fn match_node_display<'a>( base: &NodeDisplayBase, @@ -179,12 +186,17 @@ fn match_node_display<'a>( Hide => format_hide(translator), Entities => format_entities(translator), MaskEntities { mask } => format_mask_entities(translator, mask.clone()), - ExcludeEntities { mask } => format_exclude_entities(translator, mask.clone()), - Context => format_context(translator), - UncommonEntities => format_exclude_entities(translator, (*common_entities).clone()), - MaskUncommonEntities { mask } => { - format_exclude_entities(translator, mask.intersection(&common_entities)) + ExcludeEntities { mask } => { + format_exclude_entities(translator, mask.clone()) } + Context => format_context(translator), + UncommonEntities => { + format_exclude_entities(translator, (*common_entities).clone()) + } + MaskUncommonEntities { mask } => format_exclude_entities( + translator, + mask.intersection(&common_entities), + ), } } @@ -213,7 +225,11 @@ impl NodeDisplay { Box::new(move |i, n| { let mut accumulator = String::new(); for b in &self.base { - let f = match_node_display(b, Rc::clone(&common_entities), Rc::clone(&translator)); + let f = match_node_display( + b, + Rc::clone(&common_entities), + Rc::clone(&translator), + ); accumulator.push_str(&(f)(i, n)); } @@ -264,7 +280,8 @@ pub struct EdgeDisplay { pub base: Vec, } -type GraphMapEdgesFnTy<'a> = dyn Fn(petgraph::prelude::EdgeIndex, &'a Label) -> String + 'a; +type GraphMapEdgesFnTy<'a> = + dyn Fn(petgraph::prelude::EdgeIndex, &'a Label) -> String + 'a; #[derive(Default, Clone)] struct CommonEntities { @@ -293,7 +310,11 @@ fn match_edge_display<'a>( filter_common, } => { if *filter_common { - format_products(translator, mask.clone(), Some(common.common_products)) + format_products( + translator, + mask.clone(), + Some(common.common_products), + ) } else { format_products(translator, mask.clone(), None) } @@ -303,7 +324,11 @@ fn match_edge_display<'a>( filter_common, } => { if *filter_common { - format_entities(translator, mask.clone(), Some(common.common_entities)) + format_entities( + translator, + mask.clone(), + Some(common.common_entities), + ) } else { format_entities(translator, mask.clone(), None) } @@ -313,7 +338,11 @@ fn match_edge_display<'a>( filter_common, } => { if *filter_common { - format_context(translator, mask.clone(), Some(common.common_context)) + format_context( + translator, + mask.clone(), + Some(common.common_context), + ) } else { format_context(translator, mask.clone(), None) } @@ -323,7 +352,11 @@ fn match_edge_display<'a>( filter_common, } => { if *filter_common { - format_union(translator, mask.clone(), Some(common.common_union)) + format_union( + translator, + mask.clone(), + Some(common.common_union), + ) } else { format_union(translator, mask.clone(), None) } @@ -333,7 +366,11 @@ fn match_edge_display<'a>( filter_common, } => { if *filter_common { - format_difference(translator, mask.clone(), Some(common.common_difference)) + format_difference( + translator, + mask.clone(), + Some(common.common_difference), + ) } else { format_difference(translator, mask.clone(), None) } @@ -357,7 +394,11 @@ fn match_edge_display<'a>( filter_common, } => { if *filter_common { - format_entities_added(translator, mask.clone(), Some(common.common_entities_added)) + format_entities_added( + translator, + mask.clone(), + Some(common.common_entities_added), + ) } else { format_entities_added(translator, mask.clone(), None) } @@ -461,10 +502,12 @@ impl EdgeDisplay { tmp.common_difference = common_label_difference(current_graph); } if self.common_entities_deleted() { - tmp.common_entities_deleted = common_label_entities_deleted(current_graph); + tmp.common_entities_deleted = + common_label_entities_deleted(current_graph); } if self.common_entities_added() { - tmp.common_entities_added = common_label_entities_added(current_graph); + tmp.common_entities_added = + common_label_entities_added(current_graph); } tmp }; @@ -472,7 +515,11 @@ impl EdgeDisplay { Box::new(move |i, n| { let mut accumulator = String::new(); for b in &self.base { - let f = match_edge_display(b, Rc::clone(&translator), common.clone()); + let f = match_edge_display( + b, + Rc::clone(&translator), + common.clone(), + ); accumulator.push_str(&(f)(i, n)); } accumulator @@ -486,10 +533,16 @@ impl EdgeDisplay { // Node ------------------------------------------------------------------------ type RSdotGraph = Graph; -type RSformatNodeTy<'a> = - dyn Fn(&'a RSdotGraph, <&'a RSdotGraph as IntoNodeReferences>::NodeRef) -> String + 'a; -type RSformatNodeTyOpt<'a> = - dyn Fn(&'a RSdotGraph, <&'a RSdotGraph as IntoNodeReferences>::NodeRef) -> Option + 'a; +type RSformatNodeTy<'a> = dyn Fn( + &'a RSdotGraph, + <&'a RSdotGraph as IntoNodeReferences>::NodeRef, + ) -> String + + 'a; +type RSformatNodeTyOpt<'a> = dyn Fn( + &'a RSdotGraph, + <&'a RSdotGraph as IntoNodeReferences>::NodeRef, + ) -> Option + + 'a; #[derive(Clone, Copy)] pub enum OperationType { @@ -553,7 +606,12 @@ fn match_node_color_conditional<'a>( format_nill(Rc::clone(&original_graph), color.to_string(), star) } ContextColorConditional::RecursiveIdentifier(s) => { - format_recursive_identifier(Rc::clone(&original_graph), color.to_string(), star, *s) + format_recursive_identifier( + Rc::clone(&original_graph), + color.to_string(), + star, + *s, + ) } ContextColorConditional::EntitySet(ot, set) => format_entity_set( Rc::clone(&original_graph), @@ -563,22 +621,32 @@ fn match_node_color_conditional<'a>( set.clone(), ), ContextColorConditional::NonDeterministicChoice => { - format_non_deterministic_choice(Rc::clone(&original_graph), color.to_string(), star) - } - ContextColorConditional::Summation => { - format_summation(Rc::clone(&original_graph), color.to_string(), star) - } - ContextColorConditional::WaitEntity => { - format_wait_entity(Rc::clone(&original_graph), color.to_string(), star) + format_non_deterministic_choice( + Rc::clone(&original_graph), + color.to_string(), + star, + ) } + ContextColorConditional::Summation => format_summation( + Rc::clone(&original_graph), + color.to_string(), + star, + ), + ContextColorConditional::WaitEntity => format_wait_entity( + Rc::clone(&original_graph), + color.to_string(), + star, + ), }, - NodeColorConditional::EntitiesConditional(ot, set) => format_entities_conditional( - Rc::clone(&original_graph), - color.to_string(), - star, - *ot, - set.clone(), - ), + NodeColorConditional::EntitiesConditional(ot, set) => { + format_entities_conditional( + Rc::clone(&original_graph), + color.to_string(), + star, + *ot, + set.clone(), + ) + } } } @@ -590,7 +658,12 @@ impl NodeColor { ) -> Box> { Box::new(move |i, n| { for (rule, color) in &self.conditionals { - let f = match_node_color_conditional(rule, color, Rc::clone(&original_graph), star); + let f = match_node_color_conditional( + rule, + color, + Rc::clone(&original_graph), + star, + ); if let Some(s) = (f)(i, n) { return s; @@ -603,10 +676,16 @@ impl NodeColor { // Edge ------------------------------------------------------------------------ -type RSformatEdgeTy<'a> = - dyn Fn(&'a RSdotGraph, <&'a RSdotGraph as IntoEdgeReferences>::EdgeRef) -> String + 'a; -type RSformatEdgeTyOpt<'a> = - dyn Fn(&'a RSdotGraph, <&'a RSdotGraph as IntoEdgeReferences>::EdgeRef) -> Option + 'a; +type RSformatEdgeTy<'a> = dyn Fn( + &'a RSdotGraph, + <&'a RSdotGraph as IntoEdgeReferences>::EdgeRef, + ) -> String + + 'a; +type RSformatEdgeTyOpt<'a> = dyn Fn( + &'a RSdotGraph, + <&'a RSdotGraph as IntoEdgeReferences>::EdgeRef, + ) -> Option + + 'a; #[derive(Clone)] pub enum EdgeColorConditional { @@ -661,24 +740,28 @@ fn match_edge_color_conditional<'a>( *ot, set.clone(), ), - EdgeColorConditional::ReactantsAbsent(ot, set) => format_reactants_absent( - Rc::clone(&original_graph), - color.to_string(), - *ot, - set.clone(), - ), + EdgeColorConditional::ReactantsAbsent(ot, set) => { + format_reactants_absent( + Rc::clone(&original_graph), + color.to_string(), + *ot, + set.clone(), + ) + } EdgeColorConditional::Inhibitors(ot, set) => format_inhibitors( Rc::clone(&original_graph), color.to_string(), *ot, set.clone(), ), - EdgeColorConditional::InhibitorsPresent(ot, set) => format_inhibitors_present( - Rc::clone(&original_graph), - color.to_string(), - *ot, - set.clone(), - ), + EdgeColorConditional::InhibitorsPresent(ot, set) => { + format_inhibitors_present( + Rc::clone(&original_graph), + color.to_string(), + *ot, + set.clone(), + ) + } EdgeColorConditional::Products(ot, set) => format_products( Rc::clone(&original_graph), color.to_string(), @@ -689,10 +772,17 @@ fn match_edge_color_conditional<'a>( } impl EdgeColor { - pub fn generate<'a>(self, original_graph: Rc) -> Box> { + pub fn generate<'a>( + self, + original_graph: Rc, + ) -> Box> { Box::new(move |i, n| { for (rule, color) in &self.conditionals { - let f = match_edge_color_conditional(rule, color, Rc::clone(&original_graph)); + let f = match_edge_color_conditional( + rule, + color, + Rc::clone(&original_graph), + ); if let Some(s) = (f)(i, n) { return s; diff --git a/src/rsprocess/label.rs b/src/rsprocess/label.rs index c58c1e7..e6f0471 100644 --- a/src/rsprocess/label.rs +++ b/src/rsprocess/label.rs @@ -7,7 +7,14 @@ use super::translator::{Formatter, PrintableWithTranslator, Translator}; pub trait BasicLabel where - Self: Default + Clone + Debug + Serialize + Eq + Ord + Hash + PrintableWithTranslator, + Self: Default + + Clone + + Debug + + Serialize + + Eq + + Ord + + Hash + + PrintableWithTranslator, for<'a> Self: Deserialize<'a>, { type Set: BasicSet; @@ -17,7 +24,9 @@ where // ----------------------------------------------------------------------------- -#[derive(Default, Clone, Debug, Serialize, Deserialize, Eq, PartialOrd, Ord)] +#[derive( + Default, Clone, Debug, Serialize, Deserialize, Eq, PartialOrd, Ord, +)] pub struct Label { pub available_entities: Set, pub context: Set, @@ -112,7 +121,11 @@ impl Hash for Label { } impl PrintableWithTranslator for Label { - fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator) -> std::fmt::Result { + fn print( + &self, + f: &mut std::fmt::Formatter, + translator: &Translator, + ) -> std::fmt::Result { write!( f, "{{available_entities: {}, \ @@ -137,7 +150,9 @@ impl PrintableWithTranslator for Label { // ----------------------------------------------------------------------------- -#[derive(Default, Clone, Debug, Serialize, Deserialize, Eq, PartialOrd, Ord)] +#[derive( + Default, Clone, Debug, Serialize, Deserialize, Eq, PartialOrd, Ord, +)] pub struct PositiveLabel { pub available_entities: PositiveSet, pub context: PositiveSet, @@ -185,7 +200,11 @@ impl Hash for PositiveLabel { } impl PrintableWithTranslator for PositiveLabel { - fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator) -> std::fmt::Result { + fn print( + &self, + f: &mut std::fmt::Formatter, + translator: &Translator, + ) -> std::fmt::Result { write!( f, "{{available_entities: {}, \ @@ -220,14 +239,15 @@ impl PositiveLabel { inhibitors_present: PositiveSet, products: PositiveSet, ) -> Self { - Self { available_entities, - context, - t, - reactants, - reactants_absent, - inhibitors, - inhibitors_present, - products + Self { + available_entities, + context, + t, + reactants, + reactants_absent, + inhibitors, + inhibitors_present, + products, } } diff --git a/src/rsprocess/presets.rs b/src/rsprocess/presets.rs index 1aca816..a7c6dfc 100644 --- a/src/rsprocess/presets.rs +++ b/src/rsprocess/presets.rs @@ -2,6 +2,7 @@ use lalrpop_util::ParseError; use petgraph::Graph; +use std::collections::HashMap; use std::env; use std::fmt::Display; use std::fs; @@ -103,16 +104,18 @@ pub enum Instruction { so: SaveOptions, }, Digraph { + group: Option>, gso: Vec, }, Bisimilarity { system_b: String, - edge_relabeler: Box, + edge_relabeler: Box, so: SaveOptions, }, } /// Describes a system or a graph. +#[derive(Clone)] pub enum System { Deserialize { path: String }, System { sys: system::System }, @@ -120,7 +123,10 @@ pub enum System { impl System { /// Deserialize the graph if applicable. - pub fn compute(&self, translator: Translator) -> Result { + pub fn compute( + &self, + translator: Translator, + ) -> Result { match self { Self::System { sys } => Ok(EvaluatedSystem::System { sys: sys.to_owned(), @@ -134,6 +140,7 @@ impl System { } } +#[derive(Clone)] pub enum EvaluatedSystem { Graph { graph: graph::SystemGraph, @@ -167,7 +174,11 @@ pub struct Instructions { // IO Helper Functions // ----------------------------------------------------------------------------- -fn read_file(translator: &mut Translator, path_string: String, parser: F) -> Result +fn read_file( + translator: &mut Translator, + path_string: String, + parser: F, +) -> Result where F: Fn(&mut Translator, String) -> Result, { @@ -196,14 +207,17 @@ where Ok(result) } -fn reformat_error(e: ParseError, input_str: &str) -> Result +fn reformat_error( + e: ParseError, + input_str: &str, +) -> Result where T: Display, { match e { ParseError::ExtraToken { token: (l, t, r) } => Err(format!( "Unexpected token \"{t}\" \ - between positions {l} and {r}." + between positions {l} and {r}." )), ParseError::UnrecognizedEof { location: _, @@ -214,30 +228,30 @@ where } ParseError::UnrecognizedToken { token: (l, t, r), - expected: _, + expected, } => { use colored::Colorize; let mut err = format!( "Unrecognized token {}{}{} \ - between positions {l} and {r}.", + between positions {l} and {r}.", "\"".red(), t.to_string().red(), "\"".red(), ); - // // Temporary debug. - // err.push_str("Expected: "); - // let mut it = expected.iter().peekable(); - // while let Some(s) = it.next() { - // err.push('('); - // err.push_str(&format!("{}", s.green())); - // err.push(')'); - // if it.peek().is_some() { - // err.push(','); - // err.push(' '); - // } - // } + // Temporary debug. + err.push_str("Expected: "); + let mut it = expected.iter().peekable(); + while let Some(s) = it.next() { + err.push('('); + err.push_str(&format!("{}", s.green())); + err.push(')'); + if it.peek().is_some() { + err.push(','); + err.push(' '); + } + } let right_new_line = input_str[l..] .find("\n") .map(|pos| pos + l) @@ -310,7 +324,12 @@ fn save_file(contents: &String, path_string: String) -> Result<(), String> { let mut f = match fs::File::create(&path) { Ok(f) => f, - Err(_) => return Err(format!("Error creating file {}.", path.to_str().unwrap())), + Err(_) => { + return Err(format!( + "Error creating file {}.", + path.to_str().unwrap() + )); + } }; match write!(f, "{contents}") { Ok(_) => {} @@ -327,7 +346,9 @@ fn save_file(contents: &String, path_string: String) -> Result<(), String> { /// Equivalent main_do(stat) or main_do(stat, MissingE) pub fn stats(system: &EvaluatedSystem) -> Result { match system { - EvaluatedSystem::System { sys, translator } => Ok(sys.statistics(translator)), + EvaluatedSystem::System { sys, translator } => { + Ok(sys.statistics(translator)) + } EvaluatedSystem::Graph { graph, translator } => { let Some(sys) = graph.node_weights().next() else { return Err("No node found in graph.".into()); @@ -342,7 +363,9 @@ pub fn stats(system: &EvaluatedSystem) -> Result { /// Equivalent to main_do(target, E) pub fn target(system: &EvaluatedSystem) -> Result { let (res, translator) = match system { - EvaluatedSystem::System { sys, translator } => (sys.target()?, translator), + EvaluatedSystem::System { sys, translator } => { + (sys.target()?, translator) + } EvaluatedSystem::Graph { graph, translator } => { let Some(sys) = graph.node_weights().next() else { return Err("No node found in graph.".into()); @@ -363,7 +386,9 @@ pub fn target(system: &EvaluatedSystem) -> Result { /// equivalent to main_do(run,Es) pub fn traversed(system: &EvaluatedSystem) -> Result { let (res, translator) = match system { - EvaluatedSystem::System { sys, translator } => (sys.run_separated()?, translator), + EvaluatedSystem::System { sys, translator } => { + (sys.run_separated()?, translator) + } EvaluatedSystem::Graph { graph, translator } => { let Some(sys) = graph.node_weights().next() else { return Err("No node found in graph.".into()); @@ -376,7 +401,10 @@ pub fn traversed(system: &EvaluatedSystem) -> Result { output.push_str("The trace is composed by the set of entities: "); for (e, _c, _t) in res { - output.push_str(&format!("{}", translator::Formatter::from(translator, &e))); + output.push_str(&format!( + "{}", + translator::Formatter::from(translator, &e) + )); } Ok(output) } @@ -385,7 +413,10 @@ pub fn traversed(system: &EvaluatedSystem) -> Result { /// context. IMPORTANT: for loops, we assume Delta defines the process constant /// x = Q.x and the context process is x . /// equivalent to main_do(loop,Es) -pub fn hoop(system: &EvaluatedSystem, symbol: String) -> Result { +pub fn hoop( + system: &EvaluatedSystem, + symbol: String, +) -> Result { use system::LoopSystem; let (res, translator) = match system { @@ -412,7 +443,10 @@ pub fn hoop(system: &EvaluatedSystem, symbol: String) -> Result output.push_str("The loop is composed by the sets: "); for e in res { - output.push_str(&format!("{}", translator::Formatter::from(translator, &e))); + output.push_str(&format!( + "{}", + translator::Formatter::from(translator, &e) + )); } Ok(output) @@ -445,7 +479,10 @@ pub fn freq(system: &EvaluatedSystem) -> Result { /// Finds the frequency of each entity in the limit loop of a nonterminating /// Reaction System whose context has the form Q1 ... Q1.Q2 ... Q2 ... Qn ... /// equivalent to main_do(limitfreq, PairList) -pub fn limit_freq(system: &mut EvaluatedSystem, experiment: String) -> Result { +pub fn limit_freq( + system: &mut EvaluatedSystem, + experiment: String, +) -> Result { use frequency::BasicFrequency; let (sys, translator): (&system::System, &mut Translator) = match system { @@ -482,7 +519,10 @@ pub fn limit_freq(system: &mut EvaluatedSystem, experiment: String) -> Result Result { +pub fn fast_freq( + system: &mut EvaluatedSystem, + experiment: String, +) -> Result { use frequency::BasicFrequency; let (sys, translator): (&system::System, &mut Translator) = match system { @@ -520,33 +560,91 @@ pub fn fast_freq(system: &mut EvaluatedSystem, experiment: String) -> Result Result<(), String> { if let EvaluatedSystem::System { sys, translator } = system { *system = EvaluatedSystem::Graph { - graph: sys.clone().digraph()?, + graph: sys.digraph()?, translator: translator.to_owned(), }; } Ok(()) } +pub fn grouping( + system: &mut EvaluatedSystem, + group: &assert::grouping::Assert, +) -> Result<(), String> { + let mut buckets = HashMap::new(); + let mut leader: HashMap = HashMap::new(); + + if let EvaluatedSystem::Graph { graph, translator } = system { + for node in graph.node_indices() { + let val = group.execute(graph, &node, translator)?; + buckets.entry(val.clone()).or_insert(vec![]).push(node); + let l = buckets.get(&val).unwrap().first().unwrap(); + leader.insert(node, (*l, val)); + } + + for node in graph.node_indices().rev() { + let (origin, val) = leader.get(&node).unwrap(); + if *origin == node { + continue; + } + if buckets.get(val).unwrap().len() <= 1 { + continue; + } + + let mut edges = + graph.neighbors_directed(node, petgraph::Outgoing).detach(); + while let Some(edge) = edges.next_edge(graph) { + graph.add_edge( + *origin, + graph.edge_endpoints(edge).unwrap().1, + graph.edge_weight(edge).unwrap().clone(), + ); + } + let mut edges = + graph.neighbors_directed(node, petgraph::Incoming).detach(); + while let Some(edge) = edges.next_edge(graph) { + graph.add_edge( + graph.edge_endpoints(edge).unwrap().0, + *origin, + graph.edge_weight(edge).unwrap().clone(), + ); + } + graph + .remove_node(node) + .ok_or(format!("Could not remove node {node:?}"))?; + } + + Ok(()) + } else { + Err("Grouping can be done only on graphs.".into()) + } +} + /// Computes bisimularity of two provided systems pub fn bisimilar( system_a: &mut EvaluatedSystem, - edge_relabeler: &super::assert::types::Assert, + edge_relabeler: &assert::relabel::Assert, system_b: String, ) -> Result { - use super::assert::types::AssertReturnValue; + use assert::relabel::AssertReturnValue; let system_b = read_file( system_a.get_translator(), system_b.to_string(), parser_instructions, )?; - let mut system_b = match system_b.system.compute(system_a.get_translator().clone())? { - EvaluatedSystem::System { sys, translator } => EvaluatedSystem::System { sys, translator }, + let mut system_b = match system_b + .system + .compute(system_a.get_translator().clone())? + { + EvaluatedSystem::System { sys, translator } => { + EvaluatedSystem::System { sys, translator } + } EvaluatedSystem::Graph { graph, translator } => { if translator != *system_a.get_translator() { return Err("Bisimilarity not implemented for systems with \ - different encodings. Serialize the systems \ - with the same translator." + different encodings. Serialize the systems \ + with the same translator." .into()); } EvaluatedSystem::Graph { graph, translator } @@ -574,9 +672,9 @@ pub fn bisimilar( b.map_edges(edge_relabeler, translator_b)?; Ok(format!( "{}", - // super::bisimilarity::bisimilarity_kanellakis_smolka::bisimilarity(&&a, &&b) - // super::bisimilarity::bisimilarity_paige_tarjan::bisimilarity_ignore_labels(&&a, &&b) - super::bisimilarity::bisimilarity_paige_tarkan::bisimilarity(&&a, &&b) + // bisimilarity::bisimilarity_kanellakis_smolka::bisimilarity(&&a, &&b) + // bisimilarity::bisimilarity_paige_tarjan::bisimilarity_ignore_labels(&&a, &&b) + bisimilarity::bisimilarity_paige_tarkan::bisimilarity(&&a, &&b) )) } _ => { @@ -611,12 +709,16 @@ pub fn dot( let graph = Rc::new(graph.to_owned()); - let node_formatter = - node_color.generate(Rc::clone(&graph), translator.encode_not_mut("*")); + let node_formatter = node_color + .generate(Rc::clone(&graph), translator.encode_not_mut("*")); let edge_formatter = edge_color.generate(Rc::clone(&graph)); - let dot = - dot::Dot::with_attr_getters(&modified_graph, &[], &edge_formatter, &node_formatter); + let dot = dot::Dot::with_attr_getters( + &modified_graph, + &[], + &edge_formatter, + &node_formatter, + ); Ok(format!("{dot}")) } @@ -670,7 +772,12 @@ pub fn serialize(system: &EvaluatedSystem, path: String) -> Result<(), String> { let f = match fs::File::create(&path) { Ok(f) => f, - Err(_) => return Err(format!("Error creating file {}.", path.to_str().unwrap())), + Err(_) => { + return Err(format!( + "Error creating file {}.", + path.to_str().unwrap() + )); + } }; match serialize::ser(f, graph, translator) { @@ -684,7 +791,9 @@ pub fn serialize(system: &EvaluatedSystem, path: String) -> Result<(), String> { /// Reads the specified serialized system from a file. /// N.B. graph size in memory might be much larger after serialization and /// deserialization -pub fn deserialize(input_path: String) -> Result<(graph::SystemGraph, Translator), String> { +pub fn deserialize( + input_path: String, +) -> Result<(graph::SystemGraph, Translator), String> { // relative path let mut path = match env::current_dir() { Ok(p) => p, @@ -695,7 +804,12 @@ pub fn deserialize(input_path: String) -> Result<(graph::SystemGraph, Translator let f = match fs::File::open(&path) { Ok(f) => f, - Err(_) => return Err(format!("Error opening file {}.", path.to_str().unwrap())), + Err(_) => { + return Err(format!( + "Error opening file {}.", + path.to_str().unwrap() + )); + } }; match serialize::de(f) { @@ -723,7 +837,10 @@ macro_rules! save_options { }; } -fn execute(instruction: Instruction, system: &mut EvaluatedSystem) -> Result<(), String> { +fn execute( + instruction: Instruction, + system: &mut EvaluatedSystem, +) -> Result<(), String> { match instruction { Instruction::Stats { so } => { save_options!(stats(system)?, so); @@ -746,9 +863,14 @@ fn execute(instruction: Instruction, system: &mut EvaluatedSystem) -> Result<(), Instruction::FastFrequency { experiment, so } => { save_options!(fast_freq(system, experiment)?, so); } - Instruction::Digraph { gso } => { + Instruction::Digraph { group, gso } => { + let mut graph = system.clone(); + digraph(&mut graph)?; + if let Some(group) = group { + group.typecheck()?; + grouping(&mut graph, &group)?; + } for save in gso { - digraph(system)?; match save { GraphSaveOptions::Dot { node_display: nd, @@ -757,17 +879,17 @@ fn execute(instruction: Instruction, system: &mut EvaluatedSystem) -> Result<(), edge_color: ec, so, } => { - save_options!(dot(system, nd, ed, nc, ec)?, so); + save_options!(dot(&graph, nd, ed, nc, ec)?, so); } GraphSaveOptions::GraphML { node_display: nd, edge_display: ed, so, } => { - save_options!(graphml(system, nd, ed)?, so); + save_options!(graphml(&graph, nd, ed)?, so); } GraphSaveOptions::Serialize { path } => { - serialize(system, path)?; + serialize(&graph, path)?; } } } diff --git a/src/rsprocess/process.rs b/src/rsprocess/process.rs index ad8a404..cd7f0df 100644 --- a/src/rsprocess/process.rs +++ b/src/rsprocess/process.rs @@ -11,7 +11,14 @@ use super::translator::{Formatter, PrintableWithTranslator, Translator}; pub trait BasicProcess where - Self: Clone + Debug + Default + PartialEq + Eq + Hash + Serialize + PrintableWithTranslator, + Self: Clone + + Debug + + Default + + PartialEq + + Eq + + Hash + + Serialize + + PrintableWithTranslator, for<'a> Self: Deserialize<'a>, { type Id; @@ -149,7 +156,11 @@ impl Default for Process { } impl PrintableWithTranslator for Process { - fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator) -> std::fmt::Result { + fn print( + &self, + f: &mut std::fmt::Formatter, + translator: &Translator, + ) -> std::fmt::Result { match self { Self::Nill => { write!(f, "Nill") @@ -202,7 +213,11 @@ impl PrintableWithTranslator for Process { if it.peek().is_none() { write!(f, "{}", Formatter::from(translator, &**child))?; } else { - write!(f, "{} + ", Formatter::from(translator, &**child))?; + write!( + f, + "{} + ", + Formatter::from(translator, &**child) + )?; } } write!(f, "]") @@ -214,7 +229,11 @@ impl PrintableWithTranslator for Process { if it.peek().is_none() { write!(f, "{}", Formatter::from(translator, &**child))?; } else { - write!(f, "{}, ", Formatter::from(translator, &**child))?; + write!( + f, + "{}, ", + Formatter::from(translator, &**child) + )?; } } write!(f, "]") @@ -349,7 +368,11 @@ impl Default for PositiveProcess { } impl PrintableWithTranslator for PositiveProcess { - fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator) -> std::fmt::Result { + fn print( + &self, + f: &mut std::fmt::Formatter, + translator: &Translator, + ) -> std::fmt::Result { match self { Self::Nill => { write!(f, "Nill") @@ -402,7 +425,11 @@ impl PrintableWithTranslator for PositiveProcess { if it.peek().is_none() { write!(f, "{}", Formatter::from(translator, &**child))?; } else { - write!(f, "{} + ", Formatter::from(translator, &**child))?; + write!( + f, + "{} + ", + Formatter::from(translator, &**child) + )?; } } write!(f, "]") @@ -414,7 +441,11 @@ impl PrintableWithTranslator for PositiveProcess { if it.peek().is_none() { write!(f, "{}", Formatter::from(translator, &**child))?; } else { - write!(f, "{}, ", Formatter::from(translator, &**child))?; + write!( + f, + "{}, ", + Formatter::from(translator, &**child) + )?; } } write!(f, "]") @@ -434,9 +465,11 @@ impl From<&Process> for PositiveProcess { entities: entities.to_positive_set(IdState::Positive), next_process: Rc::new((&**next_process).into()), }, - Process::RecursiveIdentifier { identifier } => Self::RecursiveIdentifier { - identifier: *identifier, - }, + Process::RecursiveIdentifier { identifier } => { + Self::RecursiveIdentifier { + identifier: *identifier, + } + } Process::Guarded { reaction, next_process, @@ -448,8 +481,14 @@ impl From<&Process> for PositiveProcess { reactants: reaction .reactants .to_positive_set(IdState::Positive) - .union(&reaction.inhibitors.to_positive_set(IdState::Negative)), - products: reaction.products.to_positive_set(IdState::Positive), + .union( + &reaction + .inhibitors + .to_positive_set(IdState::Negative), + ), + products: reaction + .products + .to_positive_set(IdState::Positive), }, next_process: Rc::new((&**next_process).into()), } @@ -464,11 +503,19 @@ impl From<&Process> for PositiveProcess { next_process: Rc::new((&**next_process).into()), }, Process::Summation { children } => Self::Summation { - children: children.iter().map(|c| Rc::new((&**c).into())).collect(), - }, - Process::NondeterministicChoice { children } => Self::NondeterministicChoice { - children: children.iter().map(|c| Rc::new((&**c).into())).collect(), + children: children + .iter() + .map(|c| Rc::new((&**c).into())) + .collect(), }, + Process::NondeterministicChoice { children } => { + Self::NondeterministicChoice { + children: children + .iter() + .map(|c| Rc::new((&**c).into())) + .collect(), + } + } } } } diff --git a/src/rsprocess/reaction.rs b/src/rsprocess/reaction.rs index 0cce695..c9def44 100644 --- a/src/rsprocess/reaction.rs +++ b/src/rsprocess/reaction.rs @@ -10,7 +10,8 @@ use super::element::{IdState, IdType}; use super::set::{BasicSet, ExtensionsSet, PositiveSet, Set}; use super::translator::{Formatter, PrintableWithTranslator, Translator}; -pub trait BasicReaction: Clone + Default + Eq + Hash + Serialize + PrintableWithTranslator +pub trait BasicReaction: + Clone + Default + Eq + Hash + Serialize + PrintableWithTranslator where for<'de> Self: Deserialize<'de>, { @@ -30,7 +31,11 @@ pub trait ExtensionReaction: Sized { q: &Self::Set, ) -> (Vec, Vec); - fn find_only_loop(reactions: &[Self], entities: &Self::Set, q: &Self::Set) -> Vec; + fn find_only_loop( + reactions: &[Self], + entities: &Self::Set, + q: &Self::Set, + ) -> Vec; fn find_prefix_len_loop( reactions: &[Self], @@ -63,7 +68,11 @@ impl, Set: BasicSet> ExtensionReaction for T { } /// Finds the loops by simulating the system. - fn find_loop(reactions: &[Self], entities: Set, q: &Set) -> (Vec, Vec) { + fn find_loop( + reactions: &[Self], + entities: Set, + q: &Set, + ) -> (Vec, Vec) { let mut entities = entities; let mut trace = vec![]; loop { @@ -95,7 +104,11 @@ impl, Set: BasicSet> ExtensionReaction for T { } /// Finds the loops and the length of the prefix by simulating the system. - fn find_prefix_len_loop(reactions: &[Self], entities: Set, q: &Set) -> (usize, Vec) { + fn find_prefix_len_loop( + reactions: &[Self], + entities: Set, + q: &Set, + ) -> (usize, Vec) { let mut entities = entities; let mut trace = vec![]; loop { @@ -111,7 +124,11 @@ impl, Set: BasicSet> ExtensionReaction for T { } /// see loop/5 - fn lollipops_only_loop_decomposed_q(reactions: &[Self], entities: &Set, q: &Set) -> Vec { + fn lollipops_only_loop_decomposed_q( + reactions: &[Self], + entities: &Set, + q: &Set, + ) -> Vec { let find_loop_fn = |q| Self::find_only_loop(reactions, entities, q); find_loop_fn(q) } @@ -120,7 +137,9 @@ impl, Set: BasicSet> ExtensionReaction for T { // ----------------------------------------------------------------------------- /// Basic structure for a reaction. -#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[derive( + Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Hash, +)] pub struct Reaction { pub reactants: Set, pub inhibitors: Set, @@ -133,7 +152,8 @@ impl BasicReaction for Reaction { /// returns true if ```current_state``` enables the reaction /// see enable fn enabled(&self, current_state: &Self::Set) -> bool { - self.reactants.is_subset(current_state) && self.inhibitors.is_disjoint(current_state) + self.reactants.is_subset(current_state) + && self.inhibitors.is_disjoint(current_state) } /// Computes the result of a single reaction (if enabled returns the @@ -149,7 +169,11 @@ impl BasicReaction for Reaction { } impl PrintableWithTranslator for Reaction { - fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator) -> std::fmt::Result { + fn print( + &self, + f: &mut std::fmt::Formatter, + translator: &Translator, + ) -> std::fmt::Result { write!( f, "(r: {}, i: {}, p: {})", @@ -175,7 +199,10 @@ impl Reaction { .fold(Set::default(), |acc, r| acc.union(&r.products)) } - pub fn all_reactions_with_product<'a>(reactions: &'a [Self], el: &IdType) -> Vec<&'a Self> { + pub fn all_reactions_with_product<'a>( + reactions: &'a [Self], + el: &IdType, + ) -> Vec<&'a Self> { reactions.iter().fold(vec![], |mut acc, r| { if r.products.contains(el) { acc.push(r); @@ -187,7 +214,9 @@ impl Reaction { // ----------------------------------------------------------------------------- -#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[derive( + Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Hash, +)] pub struct PositiveReaction { pub reactants: PositiveSet, pub products: PositiveSet, @@ -210,7 +239,11 @@ impl BasicReaction for PositiveReaction { } impl PrintableWithTranslator for PositiveReaction { - fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator) -> std::fmt::Result { + fn print( + &self, + f: &mut std::fmt::Formatter, + translator: &Translator, + ) -> std::fmt::Result { write!( f, "(r: {}, p: {})", @@ -240,7 +273,7 @@ impl PositiveReaction { /// returns the reactants that are equal pub fn differ_only_one_element(&self, other: &Self) -> Option { if self.products != other.products { - return None + return None; } let mut found = false; for el in self.reactants.iter() { @@ -248,11 +281,7 @@ impl PositiveReaction { None => return None, Some(s) => { if s != el.1 { - if found { - return None - } else { - found = true - } + if found { return None } else { found = true } } } } diff --git a/src/rsprocess/serialize.rs b/src/rsprocess/serialize.rs index 48d4dea..1c143f7 100644 --- a/src/rsprocess/serialize.rs +++ b/src/rsprocess/serialize.rs @@ -35,7 +35,9 @@ where } /// Deserializer for file that contains graph and translator. -pub fn de(reader: R) -> Result<(graph::SystemGraph, Translator), serde_cbor_2::Error> +pub fn de( + reader: R, +) -> Result<(graph::SystemGraph, Translator), serde_cbor_2::Error> where R: io::Read, { diff --git a/src/rsprocess/set.rs b/src/rsprocess/set.rs index 0260994..9f872ca 100644 --- a/src/rsprocess/set.rs +++ b/src/rsprocess/set.rs @@ -11,7 +11,13 @@ use super::translator::{Formatter, PrintableWithTranslator, Translator}; /// the trait). pub trait BasicSet where - Self: Clone + Eq + Ord + Default + Serialize + IntoIterator + PrintableWithTranslator, + Self: Clone + + Eq + + Ord + + Default + + Serialize + + IntoIterator + + PrintableWithTranslator, for<'de> Self: Deserialize<'de>, { type Element; @@ -33,7 +39,10 @@ pub trait ExtensionsSet { where for<'b> &'b Self: IntoIterator; - fn split<'a>(&'a self, trace: &'a [Self]) -> Option<(&'a [Self], &'a [Self])> + fn split<'a>( + &'a self, + trace: &'a [Self], + ) -> Option<(&'a [Self], &'a [Self])> where Self: Sized; } @@ -48,7 +57,10 @@ impl ExtensionsSet for T { } /// Returns the prefix and the loop from a trace. - fn split<'a>(&'a self, trace: &'a [Self]) -> Option<(&'a [Self], &'a [Self])> { + fn split<'a>( + &'a self, + trace: &'a [Self], + ) -> Option<(&'a [Self], &'a [Self])> { let position = trace.iter().rposition(|x| x == self); position.map(|pos| trace.split_at(pos)) } @@ -57,7 +69,9 @@ impl ExtensionsSet for T { // ----------------------------------------------------------------------------- /// Basic set of entities. -#[derive(Clone, Debug, Default, PartialOrd, Eq, Ord, Serialize, Deserialize)] +#[derive( + Clone, Debug, Default, PartialOrd, Eq, Ord, Serialize, Deserialize, +)] pub struct Set { pub identifiers: BTreeSet, } @@ -158,7 +172,11 @@ impl<'a> IntoIterator for &'a Set { } impl PrintableWithTranslator for Set { - fn print(&self, f: &mut fmt::Formatter, translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + translator: &Translator, + ) -> fmt::Result { write!(f, "{{")?; let mut it = self.iter().peekable(); while let Some(el) = it.next() { @@ -253,29 +271,29 @@ impl Set { }) .collect::>(); - let mut state = vec![0_usize; unions.len()]; let mut t = vec![]; loop { - let mut new_combination = - unions.iter().zip(state.iter()) + let mut new_combination = unions + .iter() + .zip(state.iter()) .map(|(els, pos)| els[*pos]) .collect::>(); - new_combination.sort_by( - |a, b| + new_combination.sort_by(|a, b| { a.id.cmp(&b.id).then(a.state.cmp(&b.state)) - ); + }); let mut error = false; - 'external: for i in 0..new_combination.len()-1 { + 'external: for i in 0..new_combination.len() - 1 { let mut j = i + 1; loop { if new_combination[i].id != new_combination[j].id { break; } else if new_combination[i].id == new_combination[j].id - && new_combination[i].state != new_combination[j].state + && new_combination[i].state + != new_combination[j].state { error = true; break 'external; @@ -292,17 +310,16 @@ impl Set { t.push(PositiveSet::from(new_combination)); } - let next = - unions.iter().zip(state.iter()).enumerate() - .rfind( - |(_, (els, pos))| - **pos < els.len() -1 - ); + let next = unions + .iter() + .zip(state.iter()) + .enumerate() + .rfind(|(_, (els, pos))| **pos < els.len() - 1); match next { None => break, Some((pos, _)) => { state[pos] += 1; - state.iter_mut().skip(pos+1).for_each(|el| *el = 0); + state.iter_mut().skip(pos + 1).for_each(|el| *el = 0); } } } @@ -340,17 +357,18 @@ impl Set { // replace pair of sets that have a common negative-positive element // with set without let mut removed = 0; - + for (pos_set1, set1) in t.clone().iter_mut().enumerate() { // we find another set that has at least one opposite element in // common - if let Some((pos_set2, set2)) = t.iter().enumerate().find( - |(_, set2)| - set1.equal_except_negated_elements(set2) - ) { + if let Some((pos_set2, set2)) = t + .iter() + .enumerate() + .find(|(_, set2)| set1.equal_except_negated_elements(set2)) + { let intersection = set1.opposite_intersection(set2); if intersection.len() != 1 { - continue + continue; } set1.remove_elements(intersection); @@ -366,7 +384,9 @@ impl Set { // ----------------------------------------------------------------------------- -#[derive(Clone, Debug, Default, PartialOrd, Eq, Ord, Serialize, Deserialize)] +#[derive( + Clone, Debug, Default, PartialOrd, Eq, Ord, Serialize, Deserialize, +)] pub struct PositiveSet { pub identifiers: BTreeMap, } @@ -476,7 +496,11 @@ impl BasicSet for PositiveSet { } impl PrintableWithTranslator for PositiveSet { - fn print(&self, f: &mut fmt::Formatter, translator: &Translator) -> fmt::Result { + fn print( + &self, + f: &mut fmt::Formatter, + translator: &Translator, + ) -> fmt::Result { write!(f, "{{")?; let mut it = self.iter().peekable(); while let Some((id, s)) = it.next() { @@ -484,13 +508,19 @@ impl PrintableWithTranslator for PositiveSet { write!( f, "{}", - Formatter::from(translator, &PositiveType { id: *id, state: *s }) + Formatter::from( + translator, + &PositiveType { id: *id, state: *s } + ) )?; } else { write!( f, "{}, ", - Formatter::from(translator, &PositiveType { id: *id, state: *s }) + Formatter::from( + translator, + &PositiveType { id: *id, state: *s } + ) )?; } } @@ -581,13 +611,17 @@ impl From> for PositiveSet { impl FromIterator for PositiveSet { fn from_iter>(iter: T) -> Self { - Self { identifiers: iter.into_iter().map(|el| (el.id, el.state)).collect() } + Self { + identifiers: iter.into_iter().map(|el| (el.id, el.state)).collect(), + } } } impl FromIterator<(IdType, IdState)> for PositiveSet { fn from_iter>(iter: T) -> Self { - Self { identifiers: iter.into_iter().collect() } + Self { + identifiers: iter.into_iter().collect(), + } } } @@ -628,13 +662,15 @@ impl PositiveSet { } pub fn positives(&self) -> Self { - self.iter().filter(|el| *el.1 == IdState::Positive) + self.iter() + .filter(|el| *el.1 == IdState::Positive) .map(|el| (*el.0, *el.1)) .collect::() } pub fn negatives(&self) -> Self { - self.iter().filter(|el| *el.1 == IdState::Negative) + self.iter() + .filter(|el| *el.1 == IdState::Negative) .map(|el| (*el.0, *el.1)) .collect::() } diff --git a/src/rsprocess/set_test.rs b/src/rsprocess/set_test.rs index a919922..f013ab5 100644 --- a/src/rsprocess/set_test.rs +++ b/src/rsprocess/set_test.rs @@ -123,10 +123,5 @@ fn prohibiting_set_5() { Set::prohibiting_set(&[r1r, r2r], &[r1i, r2i]).unwrap(); prohibiting_set.sort(); - assert_eq!( - prohibiting_set, - vec![ - PositiveSet::from([(1, Negative)]), - ] - ) + assert_eq!(prohibiting_set, vec![PositiveSet::from([(1, Negative)]),]) } diff --git a/src/rsprocess/system.rs b/src/rsprocess/system.rs index 1b39f21..ae60468 100644 --- a/src/rsprocess/system.rs +++ b/src/rsprocess/system.rs @@ -5,34 +5,47 @@ use std::fmt::Debug; use std::hash::Hash; use std::rc::Rc; +use super::choices::Choices; use super::choices::{BasicChoices, PositiveChoices}; use super::element::IdState; use super::environment::{ - BasicEnvironment, Environment, ExtensionsEnvironment, LoopEnvironment, PositiveEnvironment, + BasicEnvironment, Environment, ExtensionsEnvironment, LoopEnvironment, + PositiveEnvironment, }; use super::label::{BasicLabel, Label, PositiveLabel}; use super::process::{BasicProcess, PositiveProcess, Process}; -use super::reaction::{BasicReaction, ExtensionReaction, PositiveReaction, Reaction}; +use super::reaction::{ + BasicReaction, ExtensionReaction, PositiveReaction, Reaction, +}; use super::set::{BasicSet, PositiveSet, Set}; use super::transitions::TransitionsIterator; use super::translator::{Formatter, PrintableWithTranslator, Translator}; -use super::choices::Choices; pub trait BasicSystem where - Self: Clone + Debug + Serialize + Default + Eq + Hash + PrintableWithTranslator, + Self: Clone + + Debug + + Serialize + + Default + + Eq + + Hash + + PrintableWithTranslator, for<'de> Self: Deserialize<'de>, { type Set: BasicSet; type Reaction: BasicReaction; type Label: BasicLabel; type Process: BasicProcess; - type Environment: BasicEnvironment; + type Environment: BasicEnvironment< + Set = Self::Set, + Process = Self::Process, + Choices = Self::Choices, + >; type Choices: BasicChoices; - fn to_transitions_iterator(&self) -> Result, String>; + fn to_transitions_iterator( + &self, + ) -> Result, String>; fn environment(&self) -> &Self::Environment; fn available_entities(&self) -> &Self::Set; @@ -44,37 +57,46 @@ type Trace = Vec<(Option>, Rc)>; pub trait ExtensionsSystem: BasicSystem { fn unfold(&self) -> Result; - + fn one_transition(&self) -> Result, String>; - fn nth_transition(&self, n: usize) -> Result, String>; + fn nth_transition( + &self, + n: usize, + ) -> Result, String>; fn all_transitions(&self) -> Result, String>; fn run(&self) -> Result>, String>; - fn digraph(self) -> Result, String>; + fn digraph(&self) -> Result, String>; fn target(&self) -> Result<(i64, Self::Set), String>; #[allow(clippy::type_complexity)] - fn run_separated(&self) -> Result, String>; + fn run_separated( + &self, + ) -> Result, String>; fn traces(self, n: usize) -> Result>, String>; } impl ExtensionsSystem for T { fn unfold(&self) -> Result { - self.environment().unfold(self.context(), self.available_entities()) + self.environment() + .unfold(self.context(), self.available_entities()) } - + /// see oneTransition, transition, smartTransition, smartOneTransition fn one_transition(&self) -> Result, String> { let mut tr = self.to_transitions_iterator()?; Ok(tr.next()) } - fn nth_transition(&self, n: usize) -> Result, String> { + fn nth_transition( + &self, + n: usize, + ) -> Result, String> { let mut tr = self.to_transitions_iterator()?; Ok(tr.nth(n)) } @@ -95,16 +117,16 @@ impl ExtensionsSystem for T { } /// Creates a graph starting from a system as root node. - fn digraph(self) -> Result, String> { + fn digraph(&self) -> Result, String> { use petgraph::Graph; - let mut graph = Graph::default(); + let mut graph: DiGraph = Graph::default(); let node = graph.add_node(self.clone()); let mut association = HashMap::new(); association.insert(self.clone(), node); - let mut stack = vec![self]; + let mut stack = vec![self.clone()]; while let Some(current) = stack.pop() { // depth first @@ -112,10 +134,11 @@ impl ExtensionsSystem for T { for (label, next) in current.to_transitions_iterator()? { // if not already visited - let next_node = association.entry(next.clone()).or_insert_with(|| { - stack.push(next.clone()); - graph.add_node(next) - }); + let next_node = + association.entry(next.clone()).or_insert_with(|| { + stack.push(next.clone()); + graph.add_node(next) + }); graph.add_edge(current_node, *next_node, label); } } @@ -140,7 +163,9 @@ impl ExtensionsSystem for T { } /// see smartOneRunECT, smartRunECT - fn run_separated(&self) -> Result, String> { + fn run_separated( + &self, + ) -> Result, String> { let mut res = vec![]; let current = self.one_transition()?; if current.is_none() { @@ -167,22 +192,28 @@ impl ExtensionsSystem for T { } let mut n = n; let mut res: Vec> = vec![]; - let mut current_trace: Trace = vec![(None, Rc::new(self))]; + let mut current_trace: Trace = + vec![(None, Rc::new(self))]; let mut branch = vec![0]; let mut depth = 0; let mut new_branch = true; loop { - let next_sys = current_trace[depth].1.nth_transition(branch[depth])?; + let next_sys = + current_trace[depth].1.nth_transition(branch[depth])?; if let Some((current_label, next_sys)) = next_sys { depth += 1; if depth >= branch.len() { branch.push(0); - current_trace.push((Some(Rc::new(current_label)), Rc::new(next_sys))); + current_trace.push(( + Some(Rc::new(current_label)), + Rc::new(next_sys), + )); } else { branch[depth] = 0; - current_trace[depth] = (Some(Rc::new(current_label)), Rc::new(next_sys)); + current_trace[depth] = + (Some(Rc::new(current_label)), Rc::new(next_sys)); } new_branch = true; } else { @@ -234,8 +265,12 @@ pub trait LoopSystem: BasicSystem { ) -> Option>; } -impl, T: BasicSystem> - LoopSystem for T +impl< + S, + E, + R: ExtensionReaction, + T: BasicSystem, +> LoopSystem for T where E: BasicEnvironment + ExtensionsEnvironment, for<'a> &'a E: IntoIterator, @@ -266,7 +301,9 @@ where .iter() .filter_map(|l| l.1.filter_delta(l.0)); - let find_loop_fn = |q| R::find_only_loop(self.reactions(), self.available_entities(), q); + let find_loop_fn = |q| { + R::find_only_loop(self.reactions(), self.available_entities(), q) + }; filtered.map(find_loop_fn).collect::>() } @@ -280,7 +317,10 @@ where /// Under these assumptions, the predicate lollipop finds the Prefixes and /// the Loops sequences of entities. /// see lollipop - fn lollipops_named(&self, symb: E::Id) -> Option<(Vec, Vec)> { + fn lollipops_named( + &self, + symb: E::Id, + ) -> Option<(Vec, Vec)> { self.environment().lollipops_decomposed_named( self.reactions(), self.available_entities(), @@ -304,7 +344,9 @@ where }) .next(); - let find_loop_fn = |q| R::find_only_loop(self.reactions(), self.available_entities(), q); + let find_loop_fn = |q| { + R::find_only_loop(self.reactions(), self.available_entities(), q) + }; filtered.map(find_loop_fn) } @@ -328,7 +370,9 @@ impl BasicSystem for System { type Environment = Environment; type Choices = Choices; - fn to_transitions_iterator(&self) -> Result, String> { + fn to_transitions_iterator( + &self, + ) -> Result, String> { TransitionsIterator::::from(self) } @@ -385,7 +429,11 @@ impl Default for System { } impl PrintableWithTranslator for System { - fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator) -> std::fmt::Result { + fn print( + &self, + f: &mut std::fmt::Formatter, + translator: &Translator, + ) -> std::fmt::Result { write!( f, "[delta: {}, available_entities: {}, context_process: {}, \ @@ -434,7 +482,9 @@ impl System { use super::translator::Formatter; let mut result: String = "Statistics:\n".into(); - result.push_str("=============================================================\n"); + result.push_str( + "=============================================================\n", + ); result.push_str(&format!( "the initial state has {} entities:\n", self.available_entities.len() @@ -549,7 +599,9 @@ impl System { "- there are {} reactions that will never be enabled.\n", nonadmissible_reactions.len() )); - result.push_str("============================================================="); + result.push_str( + "=============================================================", + ); result } @@ -575,7 +627,9 @@ impl BasicSystem for PositiveSystem { type Environment = PositiveEnvironment; type Choices = PositiveChoices; - fn to_transitions_iterator(&self) -> Result, String> { + fn to_transitions_iterator( + &self, + ) -> Result, String> { TransitionsIterator::::from(self) } @@ -632,7 +686,11 @@ impl Default for PositiveSystem { } impl PrintableWithTranslator for PositiveSystem { - fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator) -> std::fmt::Result { + fn print( + &self, + f: &mut std::fmt::Formatter, + translator: &Translator, + ) -> std::fmt::Result { write!( f, "[delta: {}, available_entities: {}, context_process: {}, \ @@ -668,16 +726,14 @@ impl From for PositiveSystem { .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) - }), - ) + .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 new_available_entities = @@ -697,19 +753,19 @@ impl From for PositiveSystem { tmp.push(PositiveReaction::create( r.reactants.clone(), r.inhibitors.clone(), - Set::from([el]) + 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; + let mut pos = tmp.len() - 1; while pos > 0 { - if let Some(intersection) - = tmp[pos].differ_only_one_element(&tmp[pos-1]) + if let Some(intersection) = + tmp[pos].differ_only_one_element(&tmp[pos - 1]) { - tmp[pos-1].reactants = intersection; + tmp[pos - 1].reactants = intersection; tmp.remove(pos); } pos -= 1; @@ -719,7 +775,8 @@ impl From for PositiveSystem { let prohib_set = Set::prohibiting_set( &p.iter().map(|p| p.reactants.clone()).collect::>(), &p.iter().map(|p| p.inhibitors.clone()).collect::>(), - ).unwrap(); // since we have in input a valid system + ) + .unwrap(); // since we have in input a valid system for s in prohib_set { res.push(PositiveReaction { reactants: s, @@ -727,8 +784,7 @@ impl From for PositiveSystem { }) } } - - + Rc::new(res) }; diff --git a/src/rsprocess/system_test.rs b/src/rsprocess/system_test.rs index 6261861..ae931f6 100644 --- a/src/rsprocess/system_test.rs +++ b/src/rsprocess/system_test.rs @@ -16,13 +16,11 @@ fn one_transition() { entities: Set::from([]), next_process: Rc::new(Process::Nill), }, - Rc::new(vec![ - Reaction::from( - Set::from([1]), - Set::from([3]), - Set::from([3]), - ), - ]), + Rc::new(vec![Reaction::from( + Set::from([1]), + Set::from([3]), + Set::from([3]), + )]), ); match system.one_transition() { @@ -31,7 +29,9 @@ fn one_transition() { System { available_entities, .. }, - ))) => assert!(available_entities.len() == 1 && available_entities.contains(&3)), + ))) => assert!( + available_entities.len() == 1 && available_entities.contains(&3) + ), _ => panic!(), } } @@ -63,8 +63,10 @@ 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 { @@ -127,13 +129,11 @@ fn convertion() { entities: Set::from([]), next_process: Rc::new(Process::Nill), }, - Rc::new(vec![ - Reaction::from( - Set::from([1]), - Set::from([3]), - Set::from([3]), - ), - ]), + Rc::new(vec![Reaction::from( + Set::from([1]), + Set::from([3]), + Set::from([3]), + )]), ); let system: PositiveSystem = system.into(); @@ -192,15 +192,27 @@ fn traces_1() { children: vec![ Rc::new(Process::EntitySet { entities: Set::from([10]), - next_process: Rc::new(Process::RecursiveIdentifier { identifier: 100 }), + next_process: Rc::new( + Process::RecursiveIdentifier { + identifier: 100, + }, + ), }), Rc::new(Process::EntitySet { entities: Set::from([11]), - next_process: Rc::new(Process::RecursiveIdentifier { identifier: 102 }), + next_process: Rc::new( + Process::RecursiveIdentifier { + identifier: 102, + }, + ), }), Rc::new(Process::EntitySet { entities: Set::from([11]), - next_process: Rc::new(Process::RecursiveIdentifier { identifier: 103 }), + next_process: Rc::new( + Process::RecursiveIdentifier { + identifier: 103, + }, + ), }), ], }, @@ -209,21 +221,9 @@ fn traces_1() { available_entities: Set::from([1, 2]), context_process: Process::RecursiveIdentifier { identifier: 101 }, reaction_rules: Rc::new(vec![ - 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]), - ), + 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])), ]), }; @@ -268,21 +268,9 @@ fn traces_empty_env() { next_process: Rc::new(Process::Nill), }, reaction_rules: Rc::new(vec![ - 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]), - ), + 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])), ]), }; @@ -295,87 +283,79 @@ fn traces_empty_env() { 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::*; + 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 { 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]), - ), + 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))); + 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)]), - ), - ]); + 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::element::IdState::*; use super::environment::Environment; - use super::set::Set; use super::process::Process; use super::reaction::Reaction; - use super::element::IdState::*; + use super::set::Set; + use super::system::{PositiveSystem, System}; 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]), - ), + 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) - ])); + assert_eq!( + entities, + PositiveSet::from([ + (1, Positive), + (2, Positive), + (3, Negative), + (5, Negative) + ]) + ); } diff --git a/src/rsprocess/transitions.rs b/src/rsprocess/transitions.rs index 8b1a0ad..0274969 100644 --- a/src/rsprocess/transitions.rs +++ b/src/rsprocess/transitions.rs @@ -6,7 +6,7 @@ use super::label::{Label, PositiveLabel}; use super::process::{BasicProcess, PositiveProcess, Process}; use super::reaction::BasicReaction; use super::set::{BasicSet, PositiveSet, Set}; -use super::system::{BasicSystem, PositiveSystem, System, ExtensionsSystem}; +use super::system::{BasicSystem, ExtensionsSystem, PositiveSystem, System}; #[derive(Clone, Debug)] pub struct TransitionsIterator< @@ -38,35 +38,40 @@ impl<'a> Iterator for TransitionsIterator<'a, Set, System, Process> { fn next(&mut self) -> Option<(Label, System)> { let (c, k) = self.choices_iterator.next()?; let t = self.system.available_entities.union(c.as_ref()); - let (reactants, reactants_absent, inhibitors, inhibitors_present, products) = - self.system.reaction_rules.iter().fold( - ( - Set::default(), // reactants - Set::default(), // reactants_absent - Set::default(), // inhibitors - Set::default(), // inhibitors_present - Set::default(), // products - ), - |acc, reaction| { - if reaction.enabled(&t) { - ( - acc.0.union(&reaction.reactants), - acc.1, - acc.2.union(&reaction.inhibitors), - acc.3, - acc.4.union(&reaction.products), - ) - } else { - ( - acc.0, - acc.1.union(&reaction.inhibitors.intersection(&t)), - acc.2, - acc.3.union(&reaction.reactants.subtraction(&t)), - acc.4, - ) - } - }, - ); + let ( + reactants, + reactants_absent, + inhibitors, + inhibitors_present, + products, + ) = self.system.reaction_rules.iter().fold( + ( + Set::default(), // reactants + Set::default(), // reactants_absent + Set::default(), // inhibitors + Set::default(), // inhibitors_present + Set::default(), // products + ), + |acc, reaction| { + if reaction.enabled(&t) { + ( + acc.0.union(&reaction.reactants), + acc.1, + acc.2.union(&reaction.inhibitors), + acc.3, + acc.4.union(&reaction.products), + ) + } else { + ( + acc.0, + acc.1.union(&reaction.inhibitors.intersection(&t)), + acc.2, + acc.3.union(&reaction.reactants.subtraction(&t)), + acc.4, + ) + } + }, + ); let label = Label::from( self.system.available_entities.clone(), @@ -102,43 +107,53 @@ impl<'a> TransitionsIterator<'a, PositiveSet, PositiveSystem, PositiveProcess> { } } -impl<'a> Iterator for TransitionsIterator<'a, PositiveSet, PositiveSystem, PositiveProcess> { +impl<'a> Iterator + for TransitionsIterator<'a, PositiveSet, PositiveSystem, PositiveProcess> +{ type Item = (PositiveLabel, PositiveSystem); /// Creates the next arc from the current system. fn next(&mut self) -> Option { let (c, k) = self.choices_iterator.next()?; let t = self.system.available_entities.union(c.as_ref()); - let (reactants, reactants_absent, inhibitors, inhibitors_present, products) - = self.system.reaction_rules.iter() - .fold( - ( - PositiveSet::default(), // reactants - PositiveSet::default(), // reactants_absent - PositiveSet::default(), // inhibitors - PositiveSet::default(), // inhibitors_present - PositiveSet::default(), // products - ), - |acc, reaction| { - if reaction.enabled(&t) { - ( - acc.0.union(&reaction.reactants.positives()), - acc.1, - acc.2.union(&reaction.reactants.negatives()), - acc.3, - acc.4.union(&reaction.products), - ) - } else { - ( - acc.0, - acc.1.union(&reaction.reactants.negatives().intersection(&t)), - acc.2, - acc.3.union(&reaction.reactants.positives().subtraction(&t)), - acc.4, - ) - } - }, - ); + let ( + reactants, + reactants_absent, + inhibitors, + inhibitors_present, + products, + ) = self.system.reaction_rules.iter().fold( + ( + PositiveSet::default(), // reactants + PositiveSet::default(), // reactants_absent + PositiveSet::default(), // inhibitors + PositiveSet::default(), // inhibitors_present + PositiveSet::default(), // products + ), + |acc, reaction| { + if reaction.enabled(&t) { + ( + acc.0.union(&reaction.reactants.positives()), + acc.1, + acc.2.union(&reaction.reactants.negatives()), + acc.3, + acc.4.union(&reaction.products), + ) + } else { + ( + acc.0, + acc.1.union( + &reaction.reactants.negatives().intersection(&t), + ), + acc.2, + acc.3.union( + &reaction.reactants.positives().subtraction(&t), + ), + acc.4, + ) + } + }, + ); let label = PositiveLabel::from( self.system.available_entities.clone(), diff --git a/src/rsprocess/translator.rs b/src/rsprocess/translator.rs index 984369a..a7c94f3 100644 --- a/src/rsprocess/translator.rs +++ b/src/rsprocess/translator.rs @@ -72,7 +72,11 @@ impl PartialEq for Translator { // ----------------------------------------------------------------------------- pub trait PrintableWithTranslator { - fn print(&self, f: &mut fmt::Formatter, translator: &Translator) -> fmt::Result; + fn print( + &self, + f: &mut fmt::Formatter, + translator: &Translator, + ) -> fmt::Result; } pub struct Formatter<'a, T> { diff --git a/testing/examples/digraph.system b/testing/examples/digraph.system index 6fc27b9..4224838 100644 --- a/testing/examples/digraph.system +++ b/testing/examples/digraph.system @@ -4,7 +4,7 @@ Context: [({a,b}.{a}.{a,c}.x + {a,b}.{a}.{a}.nill)] Reactions: ([{a,b}, {c}, {b}]) Digraph > Dot - | Entities " - " Context " - entities masked: " MaskEntities {a} + | Entities | Entities | Entities < {a} ? "blue" ! "white" | ! "black" @@ -13,4 +13,23 @@ Digraph > Dot Digraph > GraphML | Entities | Entities - > Print + > Print, + +Digraph > node { if (entities == {a, b}) + then { return 0 } + else { return 2 } } + > Dot + | Entities + | Entities + | Entities < {a} ? "blue" ! "white" + | ! "black" + > Print, + +Digraph > node { return entities == {b} } + > Dot + | Entities + | Entities + | Entities < {a} ? "blue" ! "white" + | ! "black" + > Print, +