Working positive rs

This commit is contained in:
elvis
2025-08-29 17:59:49 +02:00
parent 5812c75e37
commit 7dcdc3a727
13 changed files with 1489 additions and 372 deletions

View File

@ -22,9 +22,9 @@ fn return_true() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Boolean(true))));
@ -51,9 +51,9 @@ fn concat_1() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Boolean(true))));
@ -80,9 +80,9 @@ fn concat_2() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Boolean(true))));
@ -106,9 +106,9 @@ fn return_1() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Boolean(true))));
@ -172,9 +172,9 @@ fn return_2() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Boolean(true))));
@ -208,9 +208,9 @@ fn return_3() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Boolean(false))));
@ -245,9 +245,9 @@ fn if_1() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Boolean(true))));
@ -281,9 +281,9 @@ fn if_2() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Boolean(false))));
@ -318,9 +318,9 @@ fn if_3() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Boolean(true))));
@ -380,9 +380,9 @@ fn if_else_1() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Boolean(true))));
@ -420,9 +420,9 @@ fn if_else_2() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Boolean(false))));
@ -520,9 +520,9 @@ fn assignment_2() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Boolean(true))));
@ -560,9 +560,9 @@ fn assignment_3() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Boolean(false))));
@ -626,9 +626,9 @@ fn assignment_5() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Integer(10))));
@ -674,9 +674,9 @@ fn assignment_6() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Integer(10))));
@ -720,9 +720,9 @@ fn assignment_7() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Boolean(true))));
@ -770,9 +770,9 @@ fn assignment_8() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Integer(10))));
@ -818,9 +818,9 @@ fn assignment_9() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Integer(10))));
@ -868,9 +868,9 @@ fn assignment_10() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Integer(10))));
@ -919,9 +919,9 @@ fn for_1() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(tree.execute(&graph, &edge, &mut tr).is_err());
}
@ -973,9 +973,9 @@ fn for_2() {
tr.encode("two");
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Set(_))));
@ -1041,9 +1041,9 @@ fn for_3() {
tr.encode("two");
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Set(_))));
@ -1110,9 +1110,9 @@ fn for_4() {
tr.encode("three");
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Element(_))));
@ -1192,9 +1192,9 @@ fn for_5() {
tr.encode("three");
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Integer(3))));
@ -1284,9 +1284,9 @@ fn for_6() {
tr.encode("three");
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
@ -1337,9 +1337,9 @@ fn for_7() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
@ -1406,9 +1406,9 @@ fn for_8() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Integer(1))));
@ -1417,11 +1417,11 @@ fn for_8() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_2 = graph.add_node(System::new());
let edge = graph.add_edge(node_1, node_2, Label::new());
let node_3 = graph.add_node(System::new());
graph.add_edge(node_1, node_3, Label::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(System::default());
let edge = graph.add_edge(node_1, node_2, Label::default());
let node_3 = graph.add_node(System::default());
graph.add_edge(node_1, node_3, Label::default());
assert!(matches!(tree.execute(&graph, &edge, &mut tr),
Ok(AssertReturnValue::Integer(2))));
@ -1476,16 +1476,16 @@ fn nodes() {
let mut tr = Translator::new();
let mut graph = petgraph::Graph::new();
let node_1 = graph.add_node(System::new());
let node_1 = graph.add_node(System::default());
let node_2 = graph.add_node(
System::from(
Rc::new(Environment::new()),
Rc::new(Environment::default()),
Set::from([2]),
Process::Nill,
Rc::new(vec![])
)
);
let edge = graph.add_edge(node_1, node_2, Label::new());
let edge = graph.add_edge(node_1, node_2, Label::default());
println!("{:?}", tree.execute(&graph, &edge, &mut tr));

View File

@ -1,33 +1,34 @@
use std::fmt::Debug;
use std::rc::Rc;
use super::process::Process;
use super::set::{BasicSet, Set};
use super::process::{BasicProcess, PositiveProcess, Process};
use super::set::{BasicSet, PositiveSet, Set};
use super::translator::{Translator, PrintableWithTranslator, Formatter};
#[derive(Clone, Debug)]
pub trait BasicChoices
where Self: Clone + Debug + Default + IntoIterator + PrintableWithTranslator {
type Process: BasicProcess;
fn append(&mut self, other: &mut Self);
fn replace(&mut self, other: Rc<Self::Process>);
fn shuffle(&mut self, choices: Self);
}
// -----------------------------------------------------------------------------
#[derive(Clone, Debug, Default)]
pub struct Choices {
context_moves: Vec<(Rc<Set>, Rc<Process>)>,
}
impl Choices {
pub fn new() -> Self {
Choices {
context_moves: vec![],
}
}
impl BasicChoices for Choices {
type Process = Process;
pub fn new_not_empty() -> Self {
Choices {
context_moves: vec![(Rc::new(Set::default()),
Rc::new(Process::Nill))],
}
}
pub fn append(&mut self, a: &mut Choices) {
fn append(&mut self, a: &mut Self) {
self.context_moves.append(&mut a.context_moves);
}
pub fn replace(&mut self, a: Rc<Process>) {
fn replace(&mut self, a: Rc<Self::Process>) {
self.context_moves = self
.context_moves
.iter_mut()
@ -35,7 +36,7 @@ impl Choices {
.collect::<Vec<_>>();
}
pub fn shuffle(&mut self, choices: Choices) {
fn shuffle(&mut self, choices: Self) {
match (
self.context_moves.is_empty(),
choices.context_moves.is_empty(),
@ -57,15 +58,11 @@ impl Choices {
}
}
}
pub fn iter(&self) -> std::slice::Iter<'_, (Rc<Set>, Rc<Process>)> {
self.context_moves.iter()
}
}
impl Default for Choices {
fn default() -> Self {
Self::new()
impl Choices {
fn iter(&self) -> std::slice::Iter<'_, (Rc<Set>, Rc<Process>)> {
self.context_moves.iter()
}
}
@ -125,3 +122,109 @@ impl PrintableWithTranslator for Choices {
write!(f, "]")
}
}
// -----------------------------------------------------------------------------
#[derive(Clone, Debug, Default)]
pub struct PositiveChoices {
context_moves: Vec<(Rc<PositiveSet>, Rc<PositiveProcess>)>,
}
impl BasicChoices for PositiveChoices {
type Process = PositiveProcess;
fn append(&mut self, a: &mut Self) {
self.context_moves.append(&mut a.context_moves);
}
fn replace(&mut self, a: Rc<Self::Process>) {
self.context_moves = self
.context_moves
.iter_mut()
.map(|(c1, _)| (Rc::clone(c1), Rc::clone(&a)))
.collect::<Vec<_>>();
}
fn shuffle(&mut self, choices: Self) {
match (
self.context_moves.is_empty(),
choices.context_moves.is_empty(),
) {
(true, true) => {}
(true, false) => self.context_moves = choices.context_moves,
(false, true) => {}
(false, false) => {
let mut new_self = vec![];
for item_self in &self.context_moves {
for item_choices in &choices.context_moves {
new_self.push((
Rc::new(item_self.0.union(&item_choices.0)),
Rc::new(item_self.1.concat(&item_choices.1)),
));
}
}
self.context_moves = new_self;
}
}
}
}
impl IntoIterator for PositiveChoices {
type Item = (Rc<PositiveSet>, Rc<PositiveProcess>);
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.context_moves.into_iter()
}
}
impl PrintableWithTranslator for PositiveChoices {
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() {
if it.peek().is_none() {
write!(
f,
"[set: {}, process: {}]",
Formatter::from(translator, &*el.0),
Formatter::from(translator, &*el.1)
)?;
} else {
write!(
f,
"[set: {}, process: {}], ",
Formatter::from(translator, &*el.0),
Formatter::from(translator, &*el.1)
)?;
}
}
write!(f, "]")
}
}
impl PositiveChoices {
fn iter(&self)
-> std::slice::Iter<'_, (Rc<PositiveSet>, Rc<PositiveProcess>)> {
self.context_moves.iter()
}
}
impl<const N: usize> From<[(Rc<PositiveSet>, Rc<PositiveProcess>); N]> for PositiveChoices {
fn from(arr: [(Rc<PositiveSet>, Rc<PositiveProcess>); N]) -> Self {
Self { context_moves: arr.to_vec() }
}
}
impl From<&[(Rc<PositiveSet>, Rc<PositiveProcess>)]> for PositiveChoices {
fn from(arr: &[(Rc<PositiveSet>, Rc<PositiveProcess>)]) -> Self {
Self { context_moves: arr.to_vec() }
}
}
impl From<Vec<(Rc<PositiveSet>, Rc<PositiveProcess>)>> for PositiveChoices {
fn from(arr: Vec<(Rc<PositiveSet>, Rc<PositiveProcess>)>) -> Self {
Self { context_moves: arr }
}
}

View File

@ -1,36 +1,49 @@
use serde::{Deserialize, Serialize};
use std::cmp;
use std::collections::{HashMap, HashSet};
use std::fmt::Debug;
use std::rc::Rc;
use super::choices::Choices;
use super::process::Process;
use super::choices::{BasicChoices, Choices, PositiveChoices};
use super::process::{BasicProcess, PositiveProcess, Process};
use super::reaction::{Reaction, BasicReaction, ExtensionReaction};
use super::set::{BasicSet, Set};
use super::set::{BasicSet, PositiveSet, Set};
use super::element::IdType;
use super::translator::{Translator, PrintableWithTranslator, Formatter};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub trait BasicEnvironment
where Self: Clone + Debug + Default + Serialize + PrintableWithTranslator,
for<'a> Self: Deserialize<'a> {
type Id;
type Set: BasicSet;
type Choices: BasicChoices;
type Process: BasicProcess<Set = Self::Set, Id = Self::Id>;
fn get(&self, k: Self::Id) -> Option<&Self::Process>;
fn all_elements(&self) -> Self::Set;
fn unfold(
&self,
context: &Self::Process,
entities: &Self::Set,
) -> Result<Self::Choices, String>;
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct Environment {
definitions: HashMap<IdType, Process>,
}
impl Environment {
pub fn new() -> Environment {
Environment {
definitions: HashMap::new(),
}
}
impl BasicEnvironment for Environment {
type Process = Process;
type Set = Set;
type Choices = Choices;
type Id = IdType;
pub fn get(&self, k: IdType) -> Option<&Process> {
fn get(&self, k: IdType) -> Option<&Process> {
self.definitions.get(&k)
}
pub fn iter(&self) -> std::collections::hash_map::Iter<'_, u32, Process> {
self.definitions.iter()
}
pub fn all_elements(&self) -> Set {
fn all_elements(&self) -> Set {
let mut acc = Set::default();
for (_, process) in self.definitions.iter() {
acc.push(&process.all_elements());
@ -42,14 +55,14 @@ impl Environment {
/// definitions environment. choices::Choices is a list of context moves
/// mapping a set of entities and the continuation.
/// see unfold
pub fn unfold(
fn unfold(
&self,
context_process: &Process,
current_entities: &Set,
) -> Result<Choices, String> {
match context_process {
Process::Nill => {
Ok(Choices::new())
Ok(Choices::default())
},
Process::RecursiveIdentifier { identifier } => {
let newprocess = self.get(*identifier);
@ -70,7 +83,7 @@ impl Environment {
Ok(Choices::from([(Rc::new(reaction.products.clone()),
Rc::clone(next_process))]))
} else {
Ok(Choices::new())
Ok(Choices::default())
}
}
Process::WaitEntity { repeat, repeated_process: _, next_process, }
@ -97,7 +110,7 @@ impl Environment {
}
Process::Summation { children } => {
// short-circuits with try_fold.
children.iter().try_fold(Choices::new(), |mut acc, x| {
children.iter().try_fold(Choices::default(), |mut acc, x| {
match self.unfold(x, current_entities) {
Ok(mut choices) => {
acc.append(&mut choices);
@ -115,7 +128,7 @@ impl Environment {
Rc::new(Process::Nill),
)]))
} else {
children.iter().try_fold(Choices::new(), |mut acc, x| {
children.iter().try_fold(Choices::default(), |mut acc, x| {
acc.shuffle(self.unfold(x, current_entities)?);
Ok(acc)
})
@ -125,36 +138,6 @@ impl Environment {
}
}
impl Default for Environment {
fn default() -> Self {
Environment::new()
}
}
impl<const N: usize> From<[(IdType, Process); N]> for Environment {
fn from(arr: [(IdType, Process); N]) -> Self {
Environment {
definitions: HashMap::from(arr),
}
}
}
impl From<&[(IdType, Process)]> for Environment {
fn from(arr: &[(IdType, Process)]) -> Self {
Environment {
definitions: HashMap::from_iter(arr.to_vec()),
}
}
}
impl From<Vec<(IdType, Process)>> for Environment {
fn from(arr: Vec<(IdType, Process)>) -> Self {
Environment {
definitions: HashMap::from_iter(arr),
}
}
}
impl PrintableWithTranslator for Environment {
fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator)
-> std::fmt::Result {
@ -181,6 +164,36 @@ impl PrintableWithTranslator for Environment {
}
}
impl Environment {
pub fn iter(&self) -> std::collections::hash_map::Iter<'_, u32, Process> {
self.definitions.iter()
}
}
impl<const N: usize> From<[(IdType, Process); N]> for Environment {
fn from(arr: [(IdType, Process); N]) -> Self {
Environment {
definitions: HashMap::from(arr),
}
}
}
impl From<&[(IdType, Process)]> for Environment {
fn from(arr: &[(IdType, Process)]) -> Self {
Environment {
definitions: HashMap::from_iter(arr.to_vec()),
}
}
}
impl From<Vec<(IdType, Process)>> for Environment {
fn from(arr: Vec<(IdType, Process)>) -> Self {
Environment {
definitions: HashMap::from_iter(arr),
}
}
}
// -----------------------------------------------------------------------------
// Loops
@ -510,3 +523,167 @@ impl Environment {
// TODO: weak confluence
}
// -----------------------------------------------------------------------------
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct PositiveEnvironment {
definitions: HashMap<IdType, PositiveProcess>,
}
impl BasicEnvironment for PositiveEnvironment {
type Id = IdType;
type Set = PositiveSet;
type Choices = PositiveChoices;
type Process = PositiveProcess;
fn get(&self, k: Self::Id) -> Option<&Self::Process> {
self.definitions.get(&k)
}
fn all_elements(&self) -> Self::Set {
let mut acc = Self::Set::default();
for (_, process) in self.definitions.iter() {
acc.push(&process.all_elements());
}
acc
}
fn unfold(
&self,
context: &Self::Process,
entities: &Self::Set,
) -> Result<Self::Choices, String> {
match context {
PositiveProcess::Nill => {
Ok(Self::Choices::default())
},
PositiveProcess::RecursiveIdentifier { identifier } => {
let newprocess = self.get(*identifier);
if let Some(newprocess) = newprocess {
self.unfold(newprocess, entities)
} else {
Err(format!("Missing symbol in context: {identifier}"))
}
}
PositiveProcess::EntitySet { entities, next_process, } => {
Ok(Self::Choices::from([(
Rc::new(entities.clone()),
Rc::clone(next_process),
)]))
},
PositiveProcess::Guarded { reaction, next_process } => {
if reaction.enabled(entities) {
Ok(Self::Choices::from([(Rc::new(reaction.products.clone()),
Rc::clone(next_process))]))
} else {
Ok(Self::Choices::default())
}
}
PositiveProcess::WaitEntity { repeat, repeated_process: _, next_process, }
if *repeat <= 0 => {
self.unfold(next_process, entities)
},
PositiveProcess::WaitEntity { repeat, repeated_process, next_process, }
if *repeat == 1 => {
let mut choices1 = self.unfold(repeated_process,
entities)?;
choices1.replace(Rc::clone(next_process));
Ok(choices1)
}
PositiveProcess::WaitEntity { repeat, repeated_process, next_process, } =>
{
let mut choices1 = self.unfold(repeated_process,
entities)?;
choices1.replace(Rc::new(PositiveProcess::WaitEntity {
repeat: (*repeat - 1),
repeated_process: Rc::clone(repeated_process),
next_process: Rc::clone(next_process),
}));
Ok(choices1)
}
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),
}
})
}
PositiveProcess::NondeterministicChoice { children } => {
// short-circuits with try_fold.
if children.is_empty() {
Ok(Self::Choices::from(vec![(
Rc::new(Self::Set::default()),
Rc::new(Self::Process::default()),
)]))
} else {
children.iter().try_fold(
Self::Choices::default(),
|mut acc, x| {
acc.shuffle(self.unfold(x, entities)?);
Ok(acc)
})
}
}
}
}
}
impl PrintableWithTranslator for PositiveEnvironment {
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() {
if it.peek().is_none() {
write!(
f,
"({} -> {})",
translator.decode(*el.0).unwrap_or("Missing".into()),
Formatter::from(translator, el.1)
)?;
} else {
write!(
f,
"({} -> {}), ",
translator.decode(*el.0).unwrap_or("Missing".into()),
Formatter::from(translator, el.1)
)?;
}
}
write!(f, "}}")
}
}
impl PositiveEnvironment {
pub fn iter(
&self
) -> impl std::iter::Iterator<Item = (&u32, &PositiveProcess)> {
self.definitions.iter()
}
}
impl From<&Environment> for PositiveEnvironment {
fn from(value: &Environment) -> Self {
PositiveEnvironment {
definitions: value
.definitions
.iter()
.map(|(id, proc)| (*id, proc.into()))
.collect::<HashMap<_, _>>()
}
}
}
impl From<Environment> for PositiveEnvironment {
fn from(value: Environment) -> Self {
(&value).into()
}
}

View File

@ -4,7 +4,7 @@ use std::collections::HashMap;
use super::reaction::{Reaction, ExtensionReaction};
use super::set::{Set, ExtensionsSet};
use super::system::System;
use super::system::{System, ExtensionsSystem};
use super::element::IdType;
use super::translator::{Translator, PrintableWithTranslator, PRECISION};

View File

@ -256,7 +256,7 @@ CTX_process: process::Process = {
// -----------------------------------------------------------------------------
pub Environment: Box<environment::Environment> = {
"[" "]" =>
Box::new(environment::Environment::new()),
Box::new(environment::Environment::default()),
"[" <t: Separated_Or<Env_term, ",">> "]" =>
Box::new(environment::Environment::from(t))
};

View File

@ -1,10 +1,22 @@
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::hash::Hash;
use super::set::{BasicSet, Set};
use super::set::{BasicSet, PositiveSet, Set};
use super::translator::{Translator, PrintableWithTranslator, Formatter};
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialOrd)]
pub trait BasicLabel
where Self: Default + Clone + Debug + Serialize + Eq + Ord + Hash +
PrintableWithTranslator,
for<'a> Self: Deserialize<'a> {
type Set: BasicSet;
fn get_context(&self) -> (&Self::Set, &Self::Set, &Self::Set);
}
// -----------------------------------------------------------------------------
#[derive(Default, Clone, Debug, Serialize, Deserialize, Eq, PartialOrd, Ord)]
pub struct Label {
pub available_entities: Set,
pub context: Set,
@ -16,20 +28,19 @@ pub struct Label {
pub products: Set,
}
impl Label {
pub fn new() -> Self {
Label {
available_entities: Set::default(),
context: Set::default(),
t: Set::default(),
reactants: Set::default(),
reactants_absent: Set::default(),
inhibitors: Set::default(),
inhibitors_present: Set::default(),
products: Set::default(),
}
}
impl BasicLabel for Label {
type Set = Set;
fn get_context(&self) -> (&Set, &Set, &Set) {
(
&self.available_entities,
&self.context,
&self.t,
)
}
}
impl Label {
#[allow(clippy::too_many_arguments)]
pub fn from(
available_entities: Set,
@ -74,20 +85,6 @@ impl Label {
products,
}
}
pub fn get_context(&self) -> (&Set, &Set, &Set) {
(
&self.available_entities,
&self.context,
&self.t,
)
}
}
impl Default for Label {
fn default() -> Self {
Self::new()
}
}
impl PartialEq for Label {
@ -122,7 +119,14 @@ impl PrintableWithTranslator for Label {
-> std::fmt::Result {
write!(
f,
"{{available_entities: {}, context: {}, t: {}, reactants: {}, reactantsi: {}, inihibitors: {}, ireactants: {}, products: {}}}",
"{{available_entities: {}, \
context: {}, \
t: {}, \
reactants: {}, \
reactantsi: {}, \
inihibitors: {}, \
ireactants: {}, \
products: {}}}",
Formatter::from(translator, &self.available_entities),
Formatter::from(translator, &self.context),
Formatter::from(translator, &self.t),
@ -134,3 +138,110 @@ impl PrintableWithTranslator for Label {
)
}
}
// -----------------------------------------------------------------------------
#[derive(Default, Clone, Debug, Serialize, Deserialize, Eq, PartialOrd, Ord)]
pub struct PositiveLabel {
pub available_entities: PositiveSet,
pub context: PositiveSet,
pub t: PositiveSet,
pub reactants: PositiveSet,
pub reactants_absent: PositiveSet,
pub products: PositiveSet,
}
impl BasicLabel for PositiveLabel {
type Set = PositiveSet;
fn get_context(&self) -> (&PositiveSet, &PositiveSet, &PositiveSet) {
(
&self.available_entities,
&self.context,
&self.t,
)
}
}
impl PartialEq for PositiveLabel {
fn eq(&self, other: &Self) -> bool {
self.available_entities == other.available_entities &&
self.context == other.context &&
// self.t == other.t && // no need since its the union of the above
// // elements
self.reactants == other.reactants &&
self.reactants_absent == other.reactants_absent &&
self.products == other.products
}
}
impl Hash for PositiveLabel {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.available_entities.hash(state);
self.context.hash(state);
// self.t.hash(state);
self.reactants.hash(state);
self.reactants_absent.hash(state);
self.products.hash(state);
}
}
impl PrintableWithTranslator for PositiveLabel {
fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator)
-> std::fmt::Result {
write!(
f,
"{{available_entities: {}, \
context: {}, \
t: {}, \
reactants: {}, \
reactantsi: {}, \
products: {}}}",
Formatter::from(translator, &self.available_entities),
Formatter::from(translator, &self.context),
Formatter::from(translator, &self.t),
Formatter::from(translator, &self.reactants),
Formatter::from(translator, &self.reactants_absent),
Formatter::from(translator, &self.products),
)
}
}
impl PositiveLabel {
#[allow(clippy::too_many_arguments)]
pub fn from(
available_entities: PositiveSet,
context: PositiveSet,
t: PositiveSet,
reactants: PositiveSet,
reactants_absent: PositiveSet,
products: PositiveSet,
) -> Self {
Self {
available_entities,
context,
t,
reactants,
reactants_absent,
products,
}
}
#[allow(clippy::too_many_arguments)]
pub fn create(
available_entities: PositiveSet,
context: PositiveSet,
reactants: PositiveSet,
reactants_absent: PositiveSet,
products: PositiveSet,
) -> Self {
Self {
available_entities: available_entities.clone(),
context: context.clone(),
t: available_entities.union(&context),
reactants,
reactants_absent,
products,
}
}
}

View File

@ -12,6 +12,7 @@ use std::rc::Rc;
use super::*;
use super::graph::MapEdges;
use super::set::Set;
use super::system::{ExtensionsSystem};
use super::translator::Translator;
use super::super::grammar;

View File

@ -1,13 +1,28 @@
use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;
use super::reaction::Reaction;
use super::set::{Set, BasicSet};
use super::element::IdType;
use super::reaction::{PositiveReaction, Reaction};
use super::set::{BasicSet, PositiveSet, Set};
use super::element::{IdState, IdType};
use super::translator::{Translator, PrintableWithTranslator, Formatter};
pub trait BasicProcess
where Self: Clone + Debug + Default + PartialEq + Eq + Hash + Serialize +
PrintableWithTranslator,
for<'a> Self: Deserialize<'a> {
type Id;
type Set: BasicSet;
fn concat(&self, new: &Self) -> Self;
fn all_elements(&self) -> Self::Set;
fn filter_delta(&self, id: &Self::Id) -> Option<&Self::Set>;
}
// -----------------------------------------------------------------------------
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Process {
Nill,
@ -35,34 +50,36 @@ pub enum Process {
},
}
impl Process {
// TODO: remove all the clone()
pub fn concat(&self, new: &Process) -> Process {
impl BasicProcess for Process {
type Id = IdType;
type Set = Set;
fn concat(&self, new: &Self) -> Self {
match (self, new) {
(
Process::NondeterministicChoice { children: c1 },
Process::NondeterministicChoice { children: c2 },
) => Process::NondeterministicChoice {
Self::NondeterministicChoice { children: c1 },
Self::NondeterministicChoice { children: c2 },
) => Self::NondeterministicChoice {
children: [c1.clone(), c2.clone()].concat(),
},
(Process::NondeterministicChoice { children }, new)
| (new, Process::NondeterministicChoice { children }) => {
(Self::NondeterministicChoice { children }, new)
| (new, Self::NondeterministicChoice { children }) => {
let mut new_children = children.clone();
new_children.push(Rc::new(new.clone()));
Process::NondeterministicChoice {
Self::NondeterministicChoice {
children: new_children,
}
}
(_, _) => Process::NondeterministicChoice {
(_, _) => Self::NondeterministicChoice {
children: vec![Rc::new(self.clone()), Rc::new(new.clone())],
},
}
}
/// returns all elements used
pub fn all_elements(&self) -> Set {
fn all_elements(&self) -> Self::Set {
let mut queue = VecDeque::from([self]);
let mut elements = Set::default();
let mut elements = Self::Set::default();
while let Some(el) = queue.pop_front() {
match el {
@ -104,13 +121,12 @@ impl Process {
elements
}
/// Finds only the rules X = pre(Q, rec(X)), but not only x = pre(Q, rec(x))
/// to use in filter_map.
pub fn filter_delta<'a>(
fn filter_delta<'a>(
&'a self,
id: &IdType
) -> Option<&'a Set> {
id: &Self::Id
) -> Option<&'a Self::Set> {
if let Self::EntitySet { entities, next_process } = self
&& let Self::RecursiveIdentifier { identifier } = &**next_process
&& identifier == id
@ -122,6 +138,12 @@ impl Process {
}
}
impl Default for Process {
fn default() -> Self {
Self::Nill
}
}
impl PrintableWithTranslator for Process {
fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator)
-> std::fmt::Result {
@ -201,3 +223,246 @@ impl PrintableWithTranslator for Process {
}
}
}
// -----------------------------------------------------------------------------
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum PositiveProcess {
Nill,
RecursiveIdentifier {
identifier: IdType,
},
EntitySet {
entities: PositiveSet,
next_process: Rc<PositiveProcess>,
},
Guarded {
reaction: PositiveReaction,
next_process: Rc<PositiveProcess>,
},
WaitEntity {
repeat: i64,
repeated_process: Rc<PositiveProcess>,
next_process: Rc<PositiveProcess>,
},
Summation {
children: Vec<Rc<PositiveProcess>>,
},
NondeterministicChoice {
children: Vec<Rc<PositiveProcess>>,
},
}
impl BasicProcess for PositiveProcess {
type Id = IdType;
type Set = PositiveSet;
fn concat(&self, new: &Self) -> Self {
match (self, new) {
(
Self::NondeterministicChoice { children: c1 },
Self::NondeterministicChoice { children: c2 },
) => Self::NondeterministicChoice {
children: [c1.clone(), c2.clone()].concat(),
},
(Self::NondeterministicChoice { children }, new)
| (new, Self::NondeterministicChoice { children }) => {
let mut new_children = children.clone();
new_children.push(Rc::new(new.clone()));
Self::NondeterministicChoice {
children: new_children,
}
}
(_, _) => Self::NondeterministicChoice {
children: vec![Rc::new(self.clone()), Rc::new(new.clone())],
},
}
}
/// returns all elements used
fn all_elements(&self) -> Self::Set {
let mut queue = VecDeque::from([self]);
let mut elements = Self::Set::default();
while let Some(el) = queue.pop_front() {
match el {
Self::Nill => {}
Self::RecursiveIdentifier { identifier: _ } => {}
Self::EntitySet {
entities,
next_process,
} => {
elements.push(entities);
queue.push_back(next_process);
}
Self::Guarded { reaction, next_process } => {
elements.push(&reaction.reactants);
elements.push(&reaction.products);
queue.push_back(next_process);
}
Self::WaitEntity {
repeat: _,
repeated_process,
next_process,
} => {
queue.push_back(repeated_process);
queue.push_back(next_process);
}
Self::Summation { children } => {
for c in children {
queue.push_back(c);
}
}
Self::NondeterministicChoice { children } => {
for c in children {
queue.push_back(c);
}
}
}
}
elements
}
/// Finds only the rules X = pre(Q, rec(X)), but not only x = pre(Q, rec(x))
/// to use in filter_map.
fn filter_delta(&self, id: &Self::Id) -> Option<&Self::Set> {
if let Self::EntitySet { entities, next_process } = self
&& let Self::RecursiveIdentifier { identifier } = &**next_process
&& identifier == id
{
return Some(entities);
}
None
}
}
impl Default for PositiveProcess {
fn default() -> Self {
Self::Nill
}
}
impl PrintableWithTranslator for PositiveProcess {
fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator)
-> std::fmt::Result {
match self {
Self::Nill => {
write!(f, "Nill")
},
Self::RecursiveIdentifier { identifier } => {
write!(f,
"[{}]",
translator
.decode(*identifier)
.unwrap_or("Missing".into()))
},
Self::EntitySet { entities, next_process, } => {
write!(
f,
"{}.{}",
Formatter::from(translator, entities),
Formatter::from(translator, &**next_process)
)
},
Self::Guarded { reaction, next_process } => {
write!(f,
"?{}?.{}",
Formatter::from(translator, reaction),
Formatter::from(translator, &**next_process))
},
Self::WaitEntity { repeat, repeated_process, next_process, } => {
write!(
f,
"({})^{repeat}.{}",
Formatter::from(translator, &**repeated_process),
Formatter::from(translator, &**next_process)
)
}
Self::Summation { children } => {
write!(f, "[")?;
let mut it = children.iter().peekable();
while let Some(child) = it.next() {
if it.peek().is_none() {
write!(
f,
"{}",
Formatter::from(translator, &**child)
)?;
} else {
write!(
f,
"{} + ",
Formatter::from(translator, &**child)
)?;
}
}
write!(f, "]")
}
Self::NondeterministicChoice { children } => {
write!(f, "[")?;
let mut it = children.iter().peekable();
while let Some(child) = it.next() {
if it.peek().is_none() {
write!(
f,
"{}",
Formatter::from(translator, &**child)
)?;
} else {
write!(
f,
"{}, ",
Formatter::from(translator, &**child)
)?;
}
}
write!(f, "]")
}
}
}
}
impl From<&Process> for PositiveProcess {
fn from(value: &Process) -> Self {
match value {
Process::Nill => Self::Nill,
Process::EntitySet { entities, next_process } =>
Self::EntitySet {
entities: entities.to_positive_set(IdState::Positive),
next_process: Rc::new((&**next_process).into()) },
Process::RecursiveIdentifier { identifier } =>
Self::RecursiveIdentifier { identifier: *identifier },
Process::Guarded { reaction, next_process } => // TODO: is this right?
Self::Guarded {
reaction: PositiveReaction {
reactants: reaction.reactants
.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())},
Process::WaitEntity { repeat, repeated_process, next_process } =>
Self::WaitEntity {
repeat: *repeat,
repeated_process: Rc::new((&**repeated_process).into()),
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() }
}
}
}
impl From<Process>for PositiveProcess {
fn from(value: Process) -> Self {
(&value).into()
}
}

View File

@ -6,6 +6,7 @@
use serde::{Deserialize, Serialize};
use std::hash::Hash;
use super::element::{IdState, IdType};
use super::set::{BasicSet, ExtensionsSet, Set, PositiveSet};
use super::translator::{Translator, PrintableWithTranslator, Formatter};
@ -161,7 +162,7 @@ impl BasicReaction for Reaction {
/// returns true if ```current_state``` enables the reaction
/// see enable
fn enabled(&self, current_state: &Set) -> bool {
fn enabled(&self, current_state: &Self::Set) -> bool {
self.reactants.is_subset(current_state)
&& self.inhibitors.is_disjoint(current_state)
}
@ -169,7 +170,7 @@ impl BasicReaction for Reaction {
/// Computes the result of a single reaction (if enabled returns the
/// products) otherwise returns None.
/// see result
fn compute_step(&self, state: &Set) -> Option<&Set> {
fn compute_step(&self, state: &Self::Set) -> Option<&Self::Set> {
if self.enabled(state) {
Some(&self.products)
} else {
@ -195,6 +196,29 @@ impl Reaction {
pub fn from(reactants: Set, inhibitors: Set, products: Set) -> Self {
Reaction { reactants, inhibitors, products }
}
pub fn all_products(reactions: &[Self]) -> Set {
reactions.iter().fold(
Set::default(),
|acc, r|
acc.union(&r.products)
)
}
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);
}
acc
}
)
}
}
// -----------------------------------------------------------------------------
@ -208,11 +232,11 @@ pub struct PositiveReaction {
impl BasicReaction for PositiveReaction {
type Set = PositiveSet;
fn enabled(&self, state: &PositiveSet) -> bool {
fn enabled(&self, state: &Self::Set) -> bool {
self.reactants.is_subset(state)
}
fn compute_step(&self, state: &PositiveSet) -> Option<&PositiveSet> {
fn compute_step(&self, state: &Self::Set) -> Option<&Self::Set> {
if self.enabled(state) {
Some(&self.products)
} else {
@ -235,6 +259,14 @@ impl PrintableWithTranslator for PositiveReaction {
impl PositiveReaction {
pub fn from(reactants: PositiveSet, products: PositiveSet) -> Self {
PositiveReaction { reactants, products }
Self { reactants, products }
}
pub fn create(reactants: Set, inhibitors: Set, products: Set) -> Self {
Self { reactants:
reactants.to_positive_set(IdState::Positive).union(
&inhibitors.to_positive_set(IdState::Negative)
),
products: products.to_positive_set(IdState::Positive) }
}
}

View File

@ -14,6 +14,8 @@ where Self: Clone + Eq + Ord + Default + Serialize + IntoIterator
+ PrintableWithTranslator,
for<'de> Self: Deserialize<'de>
{
type Element;
fn is_subset(&self, other: &Self) -> bool;
fn is_disjoint(&self, other: &Self) -> bool;
fn union(&self, other: &Self) -> Self;
@ -23,6 +25,7 @@ for<'de> Self: Deserialize<'de>
fn subtraction(&self, other: &Self) -> Self;
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
fn contains(&self, el: &Self::Element) -> bool;
}
pub trait ExtensionsSet {
@ -65,6 +68,8 @@ pub struct Set {
}
impl BasicSet for Set {
type Element = IdType;
fn is_subset(&self, other: &Self) -> bool {
self.identifiers.is_subset(&other.identifiers)
}
@ -119,6 +124,10 @@ impl BasicSet for Set {
fn is_empty(&self) -> bool {
self.identifiers.is_empty()
}
fn contains(&self, el: &Self::Element) -> bool {
self.identifiers.contains(el)
}
}
impl PartialEq for Set {
@ -323,6 +332,8 @@ pub struct PositiveSet {
}
impl BasicSet for PositiveSet {
type Element = PositiveType;
fn is_subset(&self, other: &Self) -> bool {
for (id, s) in self.iter() {
if let Some(s1) = other.identifiers.get(id) {
@ -406,6 +417,14 @@ impl BasicSet for PositiveSet {
fn is_empty(&self) -> bool {
self.identifiers.is_empty()
}
fn contains(&self, el: &Self::Element) -> bool {
if let Some(e) = self.identifiers.get(&el.id) && *e == el.state {
true
} else {
false
}
}
}
impl PrintableWithTranslator for PositiveSet {

View File

@ -1,94 +1,147 @@
use petgraph::graph::DiGraph;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;
use super::environment::Environment;
use super::graph::SystemGraph;
use super::label::Label;
use super::process::Process;
use super::reaction::{Reaction, ExtensionReaction};
use super::set::{BasicSet, Set};
use super::element::IdType;
use super::environment::{Environment, BasicEnvironment, PositiveEnvironment};
use super::label::{BasicLabel, Label, PositiveLabel};
use super::process::{BasicProcess, PositiveProcess, Process};
use super::reaction::{BasicReaction, ExtensionReaction, PositiveReaction, Reaction};
use super::set::{BasicSet, PositiveSet, Set};
use super::element::{IdState, IdType};
use super::transitions::TransitionsIterator;
use super::translator::{Translator, PrintableWithTranslator, Formatter};
pub trait BasicSystem
where Self: Clone + Debug + Serialize + Default + Eq + Hash
+ PrintableWithTranslator,
for<'de> Self: Deserialize<'de> {
type Set: BasicSet;
type Reaction: BasicReaction<Set = Self::Set>;
type Label: BasicLabel<Set = Self::Set>;
type Process: BasicProcess<Set = Self::Set>;
type Environment: BasicEnvironment<Set = Self::Set, Process = Self::Process>;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct System {
pub delta: Rc<Environment>,
pub available_entities: Set,
pub context_process: Process,
pub reaction_rules: Rc<Vec<Reaction>>,
fn to_transitions_iterator(
&self
) -> Result<impl Iterator<Item = (Self::Label, Self)>, String>;
fn environment(&self) -> &Self::Environment;
fn available_entities(&self) -> &Self::Set;
fn context(&self) -> &Self::Process;
fn reactions(&self) -> &Vec<Self::Reaction>;
}
type Trace = Vec<(Option<Rc<Label>>, Rc<System>)>;
type Trace<L, S> = Vec<(Option<Rc<L>>, Rc<S>)>;
impl System {
pub fn new() -> System {
System {
delta: Rc::new(Environment::new()),
available_entities: Set::default(),
context_process: Process::Nill,
reaction_rules: Rc::new(vec![]),
}
}
pub fn from(
delta: Rc<Environment>,
available_entities: Set,
context_process: Process,
reaction_rules: Rc<Vec<Reaction>>,
) -> System {
System {
delta: Rc::clone(&delta),
available_entities,
context_process,
reaction_rules: Rc::clone(&reaction_rules),
}
}
pub fn to_transitions_iterator<'a>(
&'a self
) -> Result<TransitionsIterator<'a>, String> {
TransitionsIterator::from(self)
}
/// see oneTransition, transition, smartTransition, smartOneTransition
pub fn one_transition(
pub trait ExtensionsSystem: BasicSystem {
fn one_transition(
&self
) -> Result<Option<(Label, System)>, String> {
) -> Result<Option<(Self::Label, Self)>, String>;
fn nth_transition(
&self,
n: usize,
) -> Result<Option<(Self::Label, Self)>, String>;
fn all_transitions(
&self
) -> Result<Vec<(Self::Label, Self)>, String>;
fn run(
&self
) -> Result<Vec<Rc<Self>>, String>;
fn digraph(self) -> Result<DiGraph<Self, Self::Label>, String>;
fn target(&self) -> Result<(i64, Self::Set), String>;
#[allow(clippy::type_complexity)]
fn run_separated(
&self
) -> Result<Vec<(Self::Set, Self::Set, Self::Set)>, String>;
fn traces(
self,
n: usize,
) -> Result<Vec<Trace<Self::Label, Self>>, String>;
}
impl<T: BasicSystem> ExtensionsSystem for T {
/// see oneTransition, transition, smartTransition, smartOneTransition
fn one_transition(
&self
) -> Result<Option<(Self::Label, Self)>, String> {
let mut tr = self.to_transitions_iterator()?;
Ok(tr.next())
}
pub fn nth_transition(
fn nth_transition(
&self,
n: usize,
) -> Result<Option<(Label, System)>, String> {
) -> Result<Option<(Self::Label, Self)>, String> {
let mut tr = self.to_transitions_iterator()?;
Ok(tr.nth(n))
}
/// see allTransitions, smartAllTransitions
pub fn all_transitions(
fn all_transitions(
&self
) -> Result<Vec<(Label, System)>, String> {
) -> Result<Vec<(Self::Label, Self)>, String> {
let tr = self.to_transitions_iterator()?;
Ok(tr.collect::<Vec<_>>())
}
/// see oneTarget, smartOneTarget, target, smartTarget
pub fn target(
/// see oneRun, run, smartOneRunEK, smartRunEK
fn run(
&self
) -> Result<(i64, Set), String> {
) -> Result<Vec<Rc<Self>>, String> {
let mut res = vec![Rc::new(self.clone())];
while let Some((_, next_sys)) = res.last().unwrap().one_transition()? {
res.push(Rc::new(next_sys));
}
Ok(res)
}
/// Creates a graph starting from a system as root node.
fn digraph(self) -> Result<DiGraph<Self, Self::Label>, String> {
use petgraph::Graph;
let mut graph = Graph::default();
let node = graph.add_node(self.clone());
let mut association = HashMap::new();
association.insert(self.clone(), node);
let mut stack = vec![self];
while let Some(current) = stack.pop() {
// depth first
let current_node = *association.get(&current).unwrap();
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)
});
graph.add_edge(current_node, *next_node, label);
}
}
Ok(graph)
}
/// Returns the state in one of the terminal states and the number of steps
/// to arrive at the last state.
/// see oneTarget, smartOneTarget, target, smartTarget
fn target(
&self
) -> Result<(i64, Self::Set), String> {
let current = self.one_transition()?;
if current.is_none() {
return Ok((0, self.available_entities.clone()));
return Ok((0, self.available_entities().clone()));
}
let mut n = 1;
let mut current = current.unwrap().1;
@ -96,25 +149,13 @@ impl System {
current = next;
n += 1;
}
Ok((n, current.available_entities.clone()))
Ok((n, current.available_entities().clone()))
}
/// see oneRun, run, smartOneRunEK, smartRunEK
pub fn run(
self
) -> Result<Vec<Rc<Self>>, String> {
let mut res = vec![Rc::new(self)];
while let Some((_, next_sys)) = res.last().unwrap().one_transition()? {
res.push(Rc::new(next_sys));
}
Ok(res)
}
/// see smartOneRunECT, smartRunECT
pub fn run_separated(
fn run_separated(
&self
) -> Result<Vec<(Set, Set, Set)>, String> {
) -> Result<Vec<(Self::Set, Self::Set, Self::Set)>, String> {
let mut res = vec![];
let current = self.one_transition()?;
if current.is_none() {
@ -132,16 +173,21 @@ impl System {
Ok(res)
}
pub fn traces(
/// Return the first n traces. Equivalent to visiting the execution tree
/// depth first and returning the first n leaf nodes and their path to the
/// root.
fn traces(
self,
n: usize,
) -> Result<Vec<Trace>, String> {
) -> Result<Vec<Trace<Self::Label, Self>>, String> {
if n == 0 {
return Ok(vec![])
}
let mut n = n;
let mut res : Vec<Trace> = vec![];
let mut current_trace: Trace = vec![(None, Rc::new(self))];
let mut res : Vec<Trace<Self::Label, Self>>
= vec![];
let mut current_trace: Trace<Self::Label, Self>
= vec![(None, Rc::new(self))];
let mut branch = vec![0];
let mut depth = 0;
let mut new_branch = true;
@ -187,6 +233,46 @@ impl System {
}
}
// -----------------------------------------------------------------------------
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct System {
pub delta: Rc<Environment>,
pub available_entities: Set,
pub context_process: Process,
pub reaction_rules: Rc<Vec<Reaction>>,
}
impl BasicSystem for System {
type Set = Set;
type Reaction = Reaction;
type Label = Label;
type Process = Process;
type Environment = Environment;
fn to_transitions_iterator(
&self
) -> Result<impl Iterator<Item = (Self::Label, Self)>, String> {
TransitionsIterator::<Self::Set, Self, Self::Process>::from(self)
}
fn environment(&self) -> &Self::Environment {
&self.delta
}
fn available_entities(&self) -> &Self::Set {
&self.available_entities
}
fn context(&self) -> &Self::Process {
&self.context_process
}
fn reactions(&self) -> &Vec<Self::Reaction> {
&self.reaction_rules
}
}
/// Equality does not care about delta or reaction rules. Only entities and
/// context is compared
impl PartialEq for System {
@ -214,7 +300,10 @@ impl Hash for System {
impl Default for System {
fn default() -> Self {
System::new()
Self { delta: Rc::new(Environment::default()),
available_entities: Set::default(),
context_process: Process::Nill,
reaction_rules: Rc::new(Vec::default()) }
}
}
@ -242,6 +331,23 @@ impl PrintableWithTranslator for System {
}
impl System {
pub fn from(
delta: Rc<Environment>,
available_entities: Set,
context_process: Process,
reaction_rules: Rc<Vec<Reaction>>,
) -> System {
System {
delta: Rc::clone(&delta),
available_entities,
context_process,
reaction_rules: Rc::clone(&reaction_rules),
}
}
}
// -----------------------------------------------------------------------------
// Loops
// -----------------------------------------------------------------------------
@ -339,43 +445,6 @@ impl System {
}
}
// -----------------------------------------------------------------------------
// Graph
// -----------------------------------------------------------------------------
impl System {
/// Creates a graph starting from a system as root node
pub fn digraph(
self
) -> Result<SystemGraph, String> {
use petgraph::Graph;
let mut graph = Graph::default();
let node = graph.add_node(self.clone());
let mut association = HashMap::new();
association.insert(self.clone(), node);
let mut stack = vec![self];
while let Some(current) = stack.pop() {
// depth first
let current_node = *association.get(&current).unwrap();
for (label, next) in TransitionsIterator::from(&current)? {
// if not already visited
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);
}
}
Ok(graph)
}
}
// -----------------------------------------------------------------------------
// Statistics
// -----------------------------------------------------------------------------
@ -388,7 +457,7 @@ impl System {
&self,
translator: &Translator,
) -> String {
use super::translator;
use super::translator::Formatter;
let mut result: String = "Statistics:\n".into();
result.push_str(
@ -400,7 +469,7 @@ impl System {
));
result.push_str(&format!(
"{}\n",
translator::Formatter::from(translator, &self.available_entities)
Formatter::from(translator, &self.available_entities)
));
let reactants = self
@ -410,7 +479,7 @@ impl System {
result.push_str(&format!(
"The reactants are {}:\n{}\n",
reactants.len(),
translator::Formatter::from(translator, &reactants)
Formatter::from(translator, &reactants)
));
let inhibitors = self
@ -420,7 +489,7 @@ impl System {
result.push_str(&format!(
"The inhibitors are {}:\n{}\n",
inhibitors.len(),
translator::Formatter::from(translator, &inhibitors)
Formatter::from(translator, &inhibitors)
));
let products = self
@ -430,28 +499,28 @@ impl System {
result.push_str(&format!(
"The products are {}:\n{}\n",
products.len(),
translator::Formatter::from(translator, &products)
Formatter::from(translator, &products)
));
let total = reactants.union(&inhibitors.union(&products));
result.push_str(&format!(
"The reactions involve {} entities:\n{}\n",
total.len(),
translator::Formatter::from(translator, &total)
Formatter::from(translator, &total)
));
let entities_env = self.delta.all_elements();
result.push_str(&format!(
"The environment involves {} entities:\n{}\n",
entities_env.len(),
translator::Formatter::from(translator, &entities_env)
Formatter::from(translator, &entities_env)
));
let entities_context = self.context_process.all_elements();
result.push_str(&format!(
"The context involves {} entities:\n{}\n",
entities_context.len(),
translator::Formatter::from(translator, &entities_context)
Formatter::from(translator, &entities_context)
));
let entities_all = total
@ -462,7 +531,7 @@ impl System {
result.push_str(&format!(
"The whole RS involves {} entities:\n{}\n",
entities_all.len(),
translator::Formatter::from(translator, &entities_all)
Formatter::from(translator, &entities_all)
));
let possible_e = products
@ -472,7 +541,7 @@ impl System {
result.push_str(&format!(
"There are {} reactants that will never be available:\n{}\n",
missing_e.len(),
translator::Formatter::from(translator, &missing_e)
Formatter::from(translator, &missing_e)
));
let entities_not_needed = entities_context.subtraction(&total);
@ -480,7 +549,7 @@ impl System {
"The context can provide {} entities that will never be used:\
\n{}\n",
entities_not_needed.len(),
translator::Formatter::from(translator, &entities_not_needed)
Formatter::from(translator, &entities_not_needed)
));
result.push_str(&format!(
@ -515,3 +584,165 @@ impl System {
result
}
}
// -----------------------------------------------------------------------------
// Positive System
// -----------------------------------------------------------------------------
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct PositiveSystem {
pub delta: Rc<PositiveEnvironment>,
pub available_entities: PositiveSet,
pub context_process: PositiveProcess,
pub reaction_rules: Rc<Vec<PositiveReaction>>,
}
impl BasicSystem for PositiveSystem {
type Set = PositiveSet;
type Reaction = PositiveReaction;
type Label = PositiveLabel;
type Process = PositiveProcess;
type Environment = PositiveEnvironment;
fn to_transitions_iterator(
&self
) -> Result<impl Iterator<Item = (Self::Label, Self)>, String> {
TransitionsIterator::<Self::Set, Self, Self::Process>::from(self)
}
fn environment(&self) -> &Self::Environment {
&self.delta
}
fn available_entities(&self) -> &Self::Set {
&self.available_entities
}
fn context(&self) -> &Self::Process {
&self.context_process
}
fn reactions(&self) -> &Vec<Self::Reaction> {
&self.reaction_rules
}
}
/// Equality does not care about delta or reaction rules. Only entities and
/// context is compared
impl PartialEq for PositiveSystem {
// we ignore delta and reaction rules
fn eq(&self, other: &PositiveSystem) -> bool {
self.available_entities == other.available_entities &&
self.context_process == other.context_process
}
}
/// Equality does not care about delta or reaction rules. Only entities and
/// context is compared
impl Eq for PositiveSystem {}
/// Hash does not care about delta or reaction rules. Only entities and
/// context is hashed
impl Hash for PositiveSystem {
// ignores delta and reaction rules
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.available_entities.hash(state);
self.context_process.hash(state);
}
}
impl Default for PositiveSystem {
fn default() -> Self {
Self { delta: Rc::new(PositiveEnvironment::default()),
available_entities: PositiveSet::default(),
context_process: PositiveProcess::default(),
reaction_rules: Rc::new(Vec::default()) }
}
}
impl PrintableWithTranslator for PositiveSystem {
fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator)
-> std::fmt::Result {
write!(
f,
"[delta: {}, available_entities: {}, context_process: {}, \
reaction_rules: [",
Formatter::from(translator, &*self.delta),
Formatter::from(translator, &self.available_entities),
Formatter::from(translator, &self.context_process)
)?;
let mut it = self.reaction_rules.iter().peekable();
while let Some(el) = it.next() {
if it.peek().is_none() {
write!(f, "{}", Formatter::from(translator, el))?;
} else {
write!(f, "{}, ", Formatter::from(translator, el))?;
}
}
write!(f, "] ]")
}
}
impl From<System> for PositiveSystem {
/// Converts from a normal system to a positive one, replaces every reaction
/// {r, i, p} with a positive reaction {r ¬i, p} and with {t, el} for each
/// el ∈ p for p in some reaction and t ∈ prohibiting set of a with respect
/// all reactions that contains el in the products.
/// Should never fail.
fn from(value: System) -> Self {
let new_env = Rc::new((&*value.delta).into());
let new_available_entities =
value.available_entities.to_positive_set(IdState::Positive);
let new_context = value.context_process.into();
let new_reactions = {
let mut res = vec![];
let old_reactions = &value.reaction_rules;
old_reactions.iter()
.for_each(
|r| res.push(PositiveReaction::create(r.reactants.clone(),
r.inhibitors.clone(),
r.products.clone())));
let all_products = Reaction::all_products(old_reactions);
for el in all_products {
let p =
Reaction::all_reactions_with_product(old_reactions, &el);
let prohib_set =
Set::prohibiting_set(
&p.iter().map(|p| p.reactants.clone())
.collect::<Vec<_>>(),
&p.iter().map(|p| p.inhibitors.clone())
.collect::<Vec<_>>())
.unwrap();
for s in prohib_set {
res.push(PositiveReaction {
reactants: s,
products: PositiveSet::from([(el, IdState::Negative)])
})
}
}
Rc::new(res)
};
Self { delta: new_env,
available_entities: new_available_entities,
context_process: new_context,
reaction_rules: new_reactions }
}
}
impl PositiveSystem {
pub fn from(
delta: Rc<PositiveEnvironment>,
available_entities: PositiveSet,
context_process: PositiveProcess,
reaction_rules: Rc<Vec<PositiveReaction>>,
) -> Self {
Self {
delta: Rc::clone(&delta),
available_entities,
context_process,
reaction_rules: Rc::clone(&reaction_rules),
}
}
}

View File

@ -1,6 +1,118 @@
#[test]
fn one_transition() {
use super::system::{System, ExtensionsSystem};
use super::reaction::Reaction;
use super::process::Process;
use super::environment::Environment;
use super::set::{Set, BasicSet};
use std::rc::Rc;
let system = System::from(
Rc::new(Environment::default()),
Set::from([1, 2]),
Process::EntitySet { entities: Set::from([]),
next_process: Rc::new(Process::Nill) },
Rc::new(vec![Reaction { reactants: Set::from([1]),
inhibitors: Set::from([3]),
products: Set::from([3]), }, ])
);
match system.one_transition() {
Ok(Some((_, System { available_entities, .. }))) =>
assert!(available_entities.len() == 1 &&
available_entities.contains(&3)),
_ => panic!()
}
}
#[test]
fn one_transition_2() {
use super::system::{PositiveSystem, ExtensionsSystem};
use super::reaction::PositiveReaction;
use super::process::PositiveProcess;
use super::environment::PositiveEnvironment;
use super::set::{PositiveSet, BasicSet};
use super::element::{IdState, PositiveType};
use std::rc::Rc;
let system = PositiveSystem::from(
Rc::new(PositiveEnvironment::default()),
PositiveSet::from([(1, IdState::Positive),
(2, IdState::Positive),
(3, IdState::Negative)]),
PositiveProcess::WaitEntity { repeat: 2,
repeated_process: Rc::new(
PositiveProcess::EntitySet {
entities: PositiveSet::default(),
next_process: Rc::new(
PositiveProcess::Nill) }
),
next_process: Rc::new(PositiveProcess::Nill) },
Rc::new(vec![
PositiveReaction {
reactants: PositiveSet::from([(1, IdState::Positive),
(3, IdState::Negative)]),
products: PositiveSet::from([(3, IdState::Positive)]), },
PositiveReaction {
reactants: PositiveSet::from([(3, IdState::Positive)]),
products: PositiveSet::from([(3, IdState::Negative)]), },
PositiveReaction {
reactants: PositiveSet::from([(1, IdState::Negative)]),
products: PositiveSet::from([(3, IdState::Negative)]), }, ])
);
let system = system.one_transition();
let system =
match system {
Ok(Some((_, system))) => {
assert!(system.available_entities.len() == 1 &&
system.available_entities.contains(
&PositiveType { id: 3,
state: IdState::Positive }));
system
},
_ => panic!()
};
match system.one_transition() {
Ok(Some((_, PositiveSystem { available_entities, .. }))) =>
assert!(available_entities.len() == 1 &&
available_entities.contains(
&PositiveType { id: 3,
state: IdState::Negative })),
_ => panic!()
}
}
#[test]
fn convertion() {
use super::system::{System, PositiveSystem};
use super::reaction::Reaction;
use super::process::Process;
use super::environment::Environment;
use super::set::{Set, BasicSet};
use std::rc::Rc;
let system = System::from(
Rc::new(Environment::default()),
Set::from([1, 2]),
Process::EntitySet { entities: Set::from([]),
next_process: Rc::new(Process::Nill) },
Rc::new(vec![Reaction { reactants: Set::from([1]),
inhibitors: Set::from([3]),
products: Set::from([3]), }, ])
);
let system: PositiveSystem = system.into();
assert_eq!(system.available_entities.len(), 2);
assert_eq!(system.reaction_rules.len(), 3);
}
#[test]
fn traces_1() {
use super::system::System;
use super::system::{System, ExtensionsSystem};
use super::reaction::Reaction;
use super::process::Process;
use super::environment::Environment;
@ -58,15 +170,6 @@ fn traces_1() {
])
};
// for (pos, trace) in res.iter().enumerate() {
// println!("trace {}:", pos);
// for (_, sy) in trace {
// let ent = format!("{:?}", sy.available_entities);
// let con = format!("{:?}", sy.context_process);
// println!("\t({}, {})", ent, con);
// }
// }
let res = system.clone().traces(1).unwrap();
assert_eq!(res.len(), 1);
@ -89,7 +192,7 @@ fn traces_1() {
#[test]
fn traces_empty_env() {
use super::system::System;
use super::system::{System, ExtensionsSystem};
use super::reaction::Reaction;
use super::process::Process;
use super::environment::Environment;

View File

@ -2,24 +2,27 @@
use std::rc::Rc;
use super::label::Label;
use super::process::Process;
use super::set::{BasicSet, Set};
use super::system::System;
use super::label::{Label, PositiveLabel};
use super::process::{BasicProcess, PositiveProcess, Process};
use super::set::{BasicSet, PositiveSet, Set};
use super::system::{BasicSystem, PositiveSystem, System};
use super::reaction::BasicReaction;
use super::environment::BasicEnvironment;
#[derive(Clone, Debug)]
pub struct TransitionsIterator<'a> {
choices_iterator: std::vec::IntoIter<(Rc<Set>, Rc<Process>)>,
system: &'a System,
pub struct TransitionsIterator<'a, S: BasicSet,
Sys: BasicSystem<Set = S>,
Proc: BasicProcess<Set = S>> {
choices_iterator: std::vec::IntoIter<(Rc<S>, Rc<Proc>)>,
system: &'a Sys,
}
impl<'a> TransitionsIterator<'a> {
impl<'a> TransitionsIterator<'a, Set, System, Process> {
pub fn from(
system: &'a System
) -> Result<TransitionsIterator<'a>, String> {
match system.delta.unfold(&system.context_process,
&system.available_entities) {
) -> Result<Self, String> {
match system.environment().unfold(system.context(),
system.available_entities()) {
Ok(o) => Ok(TransitionsIterator {
choices_iterator: o.into_iter(),
system,
@ -29,7 +32,7 @@ impl<'a> TransitionsIterator<'a> {
}
}
impl<'a> Iterator for TransitionsIterator<'a> {
impl<'a> Iterator for TransitionsIterator<'a, Set, System, Process> {
type Item = (Label, System);
/// Creates the next arc from the current system.
@ -91,3 +94,75 @@ impl<'a> Iterator for TransitionsIterator<'a> {
Some((label, new_system))
}
}
// -----------------------------------------------------------------------------
impl<'a> TransitionsIterator<'a, PositiveSet, PositiveSystem, PositiveProcess> {
pub fn from(
system: &'a PositiveSystem
) -> Result<Self, String> {
match system.environment().unfold(system.context(),
system.available_entities()) {
Ok(o) => Ok(TransitionsIterator {
choices_iterator: o.into_iter(),
system,
}),
Err(e) => Err(e),
}
}
}
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<Self::Item> {
let (c, k) = self.choices_iterator.next()?;
let t = self.system.available_entities.union(c.as_ref());
let (
reactants,
reactants_absent,
products
) =
self.system.reaction_rules.iter().fold(
(
PositiveSet::default(), // reactants
PositiveSet::default(), // reactants_absent
PositiveSet::default(), // products
),
|acc, reaction| {
if reaction.enabled(&t) {
(
acc.0.union(&reaction.reactants),
acc.1,
acc.2.union(&reaction.products),
)
} else {
(
acc.0,
// TODO is this right?
acc.1.union(&reaction.reactants.intersection(&t)),
acc.2,
)
}
},
);
let label = PositiveLabel::from(
self.system.available_entities.clone(),
(*c).clone(),
t,
reactants,
reactants_absent,
products.clone(),
);
let new_system = PositiveSystem::from(
Rc::clone(&self.system.delta),
products,
(*k).clone(),
Rc::clone(&self.system.reaction_rules),
);
Some((label, new_system))
}
}