Working positive rs
This commit is contained in:
@ -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));
|
||||
|
||||
|
||||
@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@ -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};
|
||||
|
||||
|
||||
@ -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))
|
||||
};
|
||||
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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(¤t).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(¤t).unwrap();
|
||||
|
||||
for (label, next) in TransitionsIterator::from(¤t)? {
|
||||
// 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user