Slicing for traces, both normal and positive
This commit is contained in:
@ -14,5 +14,10 @@ fn main() {
|
|||||||
| Err(e) => println!("{e}"),
|
| Err(e) => println!("{e}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{} milliseconds elapsed", now.elapsed().as_millis());
|
let now = now.elapsed();
|
||||||
|
println!(
|
||||||
|
"{}.{:0>3} milliseconds elapsed",
|
||||||
|
now.as_millis(),
|
||||||
|
now.as_micros() - now.as_millis() * 1000
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -630,8 +630,7 @@ where
|
|||||||
/// Computes the LTS.
|
/// Computes the LTS.
|
||||||
/// equivalent to main_do(digraph, Arcs) or to main_do(advdigraph, Arcs)
|
/// equivalent to main_do(digraph, Arcs) or to main_do(advdigraph, Arcs)
|
||||||
pub fn digraph(system: &mut EvaluatedSystem) -> Result<(), String> {
|
pub fn digraph(system: &mut EvaluatedSystem) -> Result<(), String> {
|
||||||
if let (Some(sys), true) = (&system.sys, system.graph.is_none())
|
if let (Some(sys), true) = (&system.sys, system.graph.is_none()) {
|
||||||
{
|
|
||||||
let graph = sys.digraph()?;
|
let graph = sys.digraph()?;
|
||||||
system.graph = Some(graph);
|
system.graph = Some(graph);
|
||||||
} else if let (Some(positive), true) =
|
} else if let (Some(positive), true) =
|
||||||
|
|||||||
@ -11,6 +11,7 @@ pub mod process;
|
|||||||
pub mod reaction;
|
pub mod reaction;
|
||||||
pub mod set;
|
pub mod set;
|
||||||
pub mod system;
|
pub mod system;
|
||||||
|
pub mod trace;
|
||||||
|
|
||||||
pub mod dot;
|
pub mod dot;
|
||||||
pub mod frequency;
|
pub mod frequency;
|
||||||
@ -23,3 +24,6 @@ mod system_test;
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod set_test;
|
mod set_test;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod trace_test;
|
||||||
|
|||||||
@ -19,6 +19,9 @@ where
|
|||||||
type Set: BasicSet;
|
type Set: BasicSet;
|
||||||
fn enabled(&self, state: &Self::Set) -> bool;
|
fn enabled(&self, state: &Self::Set) -> bool;
|
||||||
fn compute_step(&self, state: &Self::Set) -> Option<&Self::Set>;
|
fn compute_step(&self, state: &Self::Set) -> Option<&Self::Set>;
|
||||||
|
|
||||||
|
fn reactants(&self) -> &Self::Set;
|
||||||
|
fn products(&self) -> &Self::Set;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ExtensionReaction: Sized {
|
pub trait ExtensionReaction: Sized {
|
||||||
@ -167,6 +170,14 @@ impl BasicReaction for Reaction {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reactants(&self) -> &Self::Set {
|
||||||
|
&self.reactants
|
||||||
|
}
|
||||||
|
|
||||||
|
fn products(&self) -> &Self::Set {
|
||||||
|
&self.products
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrintableWithTranslator for Reaction {
|
impl PrintableWithTranslator for Reaction {
|
||||||
@ -237,6 +248,14 @@ impl BasicReaction for PositiveReaction {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reactants(&self) -> &Self::Set {
|
||||||
|
&self.reactants
|
||||||
|
}
|
||||||
|
|
||||||
|
fn products(&self) -> &Self::Set {
|
||||||
|
&self.products
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrintableWithTranslator for PositiveReaction {
|
impl PrintableWithTranslator for PositiveReaction {
|
||||||
|
|||||||
@ -636,6 +636,13 @@ impl PositiveSet {
|
|||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns all elements that are present in self and are positive in other.
|
||||||
|
pub fn mask(&self, other: &Self) -> Self {
|
||||||
|
Self::from_iter(self.iter().filter(|el| {
|
||||||
|
other.contains(&PositiveType::from((*el.0, IdState::Positive)))
|
||||||
|
}).map(|el| (*el.0, *el.1)))
|
||||||
|
}
|
||||||
|
|
||||||
fn remove_elements(&mut self, other: Vec<IdType>) {
|
fn remove_elements(&mut self, other: Vec<IdType>) {
|
||||||
for element in other {
|
for element in other {
|
||||||
self.identifiers.remove(&element);
|
self.identifiers.remove(&element);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, VecDeque};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -18,6 +18,7 @@ use super::reaction::{
|
|||||||
BasicReaction, ExtensionReaction, PositiveReaction, Reaction,
|
BasicReaction, ExtensionReaction, PositiveReaction, Reaction,
|
||||||
};
|
};
|
||||||
use super::set::{BasicSet, PositiveSet, Set};
|
use super::set::{BasicSet, PositiveSet, Set};
|
||||||
|
use super::trace::Trace;
|
||||||
use super::transitions::TransitionsIterator;
|
use super::transitions::TransitionsIterator;
|
||||||
use super::translator::{Formatter, PrintableWithTranslator, Translator};
|
use super::translator::{Formatter, PrintableWithTranslator, Translator};
|
||||||
|
|
||||||
@ -51,9 +52,10 @@ where
|
|||||||
fn available_entities(&self) -> &Self::Set;
|
fn available_entities(&self) -> &Self::Set;
|
||||||
fn context(&self) -> &Self::Process;
|
fn context(&self) -> &Self::Process;
|
||||||
fn reactions(&self) -> &Vec<Self::Reaction>;
|
fn reactions(&self) -> &Vec<Self::Reaction>;
|
||||||
}
|
|
||||||
|
|
||||||
type Trace<L, S> = Vec<(Option<Rc<L>>, Rc<S>)>;
|
fn context_elements(&self) -> &Self::Set;
|
||||||
|
fn products_elements(&self) -> &Self::Set;
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ExtensionsSystem: BasicSystem {
|
pub trait ExtensionsSystem: BasicSystem {
|
||||||
fn unfold(&self) -> Result<Self::Choices, String>;
|
fn unfold(&self) -> Result<Self::Choices, String>;
|
||||||
@ -134,9 +136,10 @@ impl<T: BasicSystem> ExtensionsSystem for T {
|
|||||||
let mut association = HashMap::new();
|
let mut association = HashMap::new();
|
||||||
association.insert(self.clone(), node);
|
association.insert(self.clone(), node);
|
||||||
|
|
||||||
let mut stack = vec![self.clone()];
|
let mut stack = VecDeque::new();
|
||||||
|
stack.push_back(self.clone());
|
||||||
|
|
||||||
while let Some(current) = stack.pop() {
|
while let Some(current) = stack.pop_front() {
|
||||||
// depth first
|
// depth first
|
||||||
let current_node = *association.get(¤t).unwrap();
|
let current_node = *association.get(¤t).unwrap();
|
||||||
|
|
||||||
@ -144,7 +147,7 @@ impl<T: BasicSystem> ExtensionsSystem for T {
|
|||||||
// if not already visited
|
// if not already visited
|
||||||
let next_node =
|
let next_node =
|
||||||
association.entry(next.clone()).or_insert_with(|| {
|
association.entry(next.clone()).or_insert_with(|| {
|
||||||
stack.push(next.clone());
|
stack.push_back(next.clone());
|
||||||
graph.add_node(next)
|
graph.add_node(next)
|
||||||
});
|
});
|
||||||
graph.add_edge(current_node, *next_node, label);
|
graph.add_edge(current_node, *next_node, label);
|
||||||
@ -244,8 +247,8 @@ impl<T: BasicSystem> ExtensionsSystem for T {
|
|||||||
}
|
}
|
||||||
let mut n = n;
|
let mut n = n;
|
||||||
let mut res: Vec<Trace<Self::Label, Self>> = vec![];
|
let mut res: Vec<Trace<Self::Label, Self>> = vec![];
|
||||||
let mut current_trace: Trace<Self::Label, Self> =
|
let mut current_trace: Trace<Self::Label, Self> = Trace::default();
|
||||||
vec![(None, Rc::new(self))];
|
current_trace.push((None, Rc::new(self)));
|
||||||
let mut branch = vec![0];
|
let mut branch = vec![0];
|
||||||
let mut depth = 0;
|
let mut depth = 0;
|
||||||
let mut new_branch = true;
|
let mut new_branch = true;
|
||||||
@ -272,18 +275,16 @@ impl<T: BasicSystem> ExtensionsSystem for T {
|
|||||||
// at the bottom of a trace, we save to res, then backtrack
|
// at the bottom of a trace, we save to res, then backtrack
|
||||||
// until we find another possible path.
|
// until we find another possible path.
|
||||||
if new_branch {
|
if new_branch {
|
||||||
res.push(current_trace[0..depth].to_vec());
|
res.push(Trace::from(current_trace[0..depth].to_vec()));
|
||||||
new_branch = false;
|
new_branch = false;
|
||||||
n -= 1;
|
n -= 1;
|
||||||
}
|
}
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if depth == 0 {
|
if depth == 0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
depth -= 1;
|
depth -= 1;
|
||||||
branch[depth] += 1;
|
branch[depth] += 1;
|
||||||
}
|
}
|
||||||
@ -412,6 +413,9 @@ pub struct System {
|
|||||||
pub available_entities: Set,
|
pub available_entities: Set,
|
||||||
pub context_process: Process,
|
pub context_process: Process,
|
||||||
pub reaction_rules: Rc<Vec<Reaction>>,
|
pub reaction_rules: Rc<Vec<Reaction>>,
|
||||||
|
|
||||||
|
context_elements: Rc<Set>,
|
||||||
|
products_elements: Rc<Set>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BasicSystem for System {
|
impl BasicSystem for System {
|
||||||
@ -425,7 +429,7 @@ impl BasicSystem for System {
|
|||||||
fn to_transitions_iterator(
|
fn to_transitions_iterator(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<impl Iterator<Item = (Self::Label, Self)>, String> {
|
) -> Result<impl Iterator<Item = (Self::Label, Self)>, String> {
|
||||||
TransitionsIterator::<Self::Set, Self, Self::Process>::from(self)
|
TransitionsIterator::<Self::Set, Self, Self::Process>::try_from(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn environment(&self) -> &Self::Environment {
|
fn environment(&self) -> &Self::Environment {
|
||||||
@ -443,6 +447,14 @@ impl BasicSystem for System {
|
|||||||
fn reactions(&self) -> &Vec<Self::Reaction> {
|
fn reactions(&self) -> &Vec<Self::Reaction> {
|
||||||
&self.reaction_rules
|
&self.reaction_rules
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn context_elements(&self) -> &Self::Set {
|
||||||
|
&self.context_elements
|
||||||
|
}
|
||||||
|
|
||||||
|
fn products_elements(&self) -> &Self::Set {
|
||||||
|
&self.products_elements
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Equality does not care about delta or reaction rules. Only entities and
|
/// Equality does not care about delta or reaction rules. Only entities and
|
||||||
@ -476,6 +488,9 @@ impl Default for System {
|
|||||||
available_entities: Set::default(),
|
available_entities: Set::default(),
|
||||||
context_process: Process::Nill,
|
context_process: Process::Nill,
|
||||||
reaction_rules: Rc::new(Vec::default()),
|
reaction_rules: Rc::new(Vec::default()),
|
||||||
|
|
||||||
|
context_elements: Rc::new(Set::default()),
|
||||||
|
products_elements: Rc::new(Set::default()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -513,11 +528,22 @@ impl System {
|
|||||||
context_process: Process,
|
context_process: Process,
|
||||||
reaction_rules: Rc<Vec<Reaction>>,
|
reaction_rules: Rc<Vec<Reaction>>,
|
||||||
) -> System {
|
) -> System {
|
||||||
|
let products_elements = reaction_rules
|
||||||
|
.iter()
|
||||||
|
.fold(Set::default(), |acc: Set, r| acc.union(&r.products));
|
||||||
|
let all_elements_context = delta
|
||||||
|
.all_elements()
|
||||||
|
.union(&context_process.all_elements())
|
||||||
|
.subtraction(&products_elements);
|
||||||
|
|
||||||
System {
|
System {
|
||||||
delta: Rc::clone(&delta),
|
delta: Rc::clone(&delta),
|
||||||
available_entities,
|
available_entities,
|
||||||
context_process,
|
context_process,
|
||||||
reaction_rules: Rc::clone(&reaction_rules),
|
reaction_rules: Rc::clone(&reaction_rules),
|
||||||
|
|
||||||
|
context_elements: Rc::new(all_elements_context),
|
||||||
|
products_elements: Rc::new(products_elements),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -669,6 +695,9 @@ pub struct PositiveSystem {
|
|||||||
pub available_entities: PositiveSet,
|
pub available_entities: PositiveSet,
|
||||||
pub context_process: PositiveProcess,
|
pub context_process: PositiveProcess,
|
||||||
pub reaction_rules: Rc<Vec<PositiveReaction>>,
|
pub reaction_rules: Rc<Vec<PositiveReaction>>,
|
||||||
|
|
||||||
|
context_elements: Rc<PositiveSet>,
|
||||||
|
products_elements: Rc<PositiveSet>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BasicSystem for PositiveSystem {
|
impl BasicSystem for PositiveSystem {
|
||||||
@ -682,7 +711,7 @@ impl BasicSystem for PositiveSystem {
|
|||||||
fn to_transitions_iterator(
|
fn to_transitions_iterator(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<impl Iterator<Item = (Self::Label, Self)>, String> {
|
) -> Result<impl Iterator<Item = (Self::Label, Self)>, String> {
|
||||||
TransitionsIterator::<Self::Set, Self, Self::Process>::from(self)
|
TransitionsIterator::<Self::Set, Self, Self::Process>::try_from(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn environment(&self) -> &Self::Environment {
|
fn environment(&self) -> &Self::Environment {
|
||||||
@ -700,6 +729,14 @@ impl BasicSystem for PositiveSystem {
|
|||||||
fn reactions(&self) -> &Vec<Self::Reaction> {
|
fn reactions(&self) -> &Vec<Self::Reaction> {
|
||||||
&self.reaction_rules
|
&self.reaction_rules
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn context_elements(&self) -> &Self::Set {
|
||||||
|
&self.context_elements
|
||||||
|
}
|
||||||
|
|
||||||
|
fn products_elements(&self) -> &Self::Set {
|
||||||
|
&self.products_elements
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Equality does not care about delta or reaction rules. Only entities and
|
/// Equality does not care about delta or reaction rules. Only entities and
|
||||||
@ -733,6 +770,9 @@ impl Default for PositiveSystem {
|
|||||||
available_entities: PositiveSet::default(),
|
available_entities: PositiveSet::default(),
|
||||||
context_process: PositiveProcess::default(),
|
context_process: PositiveProcess::default(),
|
||||||
reaction_rules: Rc::new(Vec::default()),
|
reaction_rules: Rc::new(Vec::default()),
|
||||||
|
|
||||||
|
context_elements: Rc::new(PositiveSet::default()),
|
||||||
|
products_elements: Rc::new(PositiveSet::default()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -840,12 +880,7 @@ impl From<System> for PositiveSystem {
|
|||||||
Rc::new(res)
|
Rc::new(res)
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Self::from(new_env, new_available_entities, new_context, new_reactions)
|
||||||
delta: new_env,
|
|
||||||
available_entities: new_available_entities,
|
|
||||||
context_process: new_context,
|
|
||||||
reaction_rules: new_reactions,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -856,11 +891,24 @@ impl PositiveSystem {
|
|||||||
context_process: PositiveProcess,
|
context_process: PositiveProcess,
|
||||||
reaction_rules: Rc<Vec<PositiveReaction>>,
|
reaction_rules: Rc<Vec<PositiveReaction>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let products_elements = reaction_rules
|
||||||
|
.iter()
|
||||||
|
.fold(PositiveSet::default(), |acc: PositiveSet, r| {
|
||||||
|
acc.union(&r.products)
|
||||||
|
});
|
||||||
|
let all_elements_context = delta
|
||||||
|
.all_elements()
|
||||||
|
.union(&context_process.all_elements())
|
||||||
|
.subtraction(&products_elements);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
delta: Rc::clone(&delta),
|
delta: Rc::clone(&delta),
|
||||||
available_entities,
|
available_entities,
|
||||||
context_process,
|
context_process,
|
||||||
reaction_rules: Rc::clone(&reaction_rules),
|
reaction_rules: Rc::clone(&reaction_rules),
|
||||||
|
|
||||||
|
context_elements: Rc::new(all_elements_context),
|
||||||
|
products_elements: Rc::new(products_elements),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -156,8 +156,8 @@ fn traces_1() {
|
|||||||
use super::set::Set;
|
use super::set::Set;
|
||||||
use super::system::{ExtensionsSystem, System};
|
use super::system::{ExtensionsSystem, System};
|
||||||
|
|
||||||
let system = System {
|
let system = System::from(
|
||||||
delta: Rc::new(Environment::from([
|
Rc::new(Environment::from([
|
||||||
(100, Process::WaitEntity {
|
(100, Process::WaitEntity {
|
||||||
repeat: 2,
|
repeat: 2,
|
||||||
repeated_process: Rc::new(Process::EntitySet {
|
repeated_process: Rc::new(Process::EntitySet {
|
||||||
@ -205,14 +205,14 @@ fn traces_1() {
|
|||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
])),
|
])),
|
||||||
available_entities: Set::from([1, 2]),
|
Set::from([1, 2]),
|
||||||
context_process: Process::RecursiveIdentifier { identifier: 101 },
|
Process::RecursiveIdentifier { identifier: 101 },
|
||||||
reaction_rules: Rc::new(vec![
|
Rc::new(vec![
|
||||||
Reaction::from(Set::from([1]), Set::from([3]), Set::from([3])),
|
Reaction::from(Set::from([1]), Set::from([3]), Set::from([3])),
|
||||||
Reaction::from(Set::from([3]), Set::from([1]), Set::from([1])),
|
Reaction::from(Set::from([3]), Set::from([1]), Set::from([1])),
|
||||||
Reaction::from(Set::from([2]), Set::default(), Set::from([4])),
|
Reaction::from(Set::from([2]), Set::default(), Set::from([4])),
|
||||||
]),
|
]),
|
||||||
};
|
);
|
||||||
|
|
||||||
let res = system.clone().traces(1).unwrap();
|
let res = system.clone().traces(1).unwrap();
|
||||||
assert_eq!(res.len(), 1);
|
assert_eq!(res.len(), 1);
|
||||||
@ -244,10 +244,10 @@ fn traces_empty_env() {
|
|||||||
use super::set::Set;
|
use super::set::Set;
|
||||||
use super::system::{ExtensionsSystem, System};
|
use super::system::{ExtensionsSystem, System};
|
||||||
|
|
||||||
let system = System {
|
let system = System::from(
|
||||||
delta: Rc::new(Environment::from([])),
|
Rc::new(Environment::from([])),
|
||||||
available_entities: Set::from([1, 2]),
|
Set::from([1, 2]),
|
||||||
context_process: Process::WaitEntity {
|
Process::WaitEntity {
|
||||||
repeat: 10,
|
repeat: 10,
|
||||||
repeated_process: Rc::new(Process::EntitySet {
|
repeated_process: Rc::new(Process::EntitySet {
|
||||||
entities: Set::from([1, 2]),
|
entities: Set::from([1, 2]),
|
||||||
@ -255,12 +255,12 @@ fn traces_empty_env() {
|
|||||||
}),
|
}),
|
||||||
next_process: Rc::new(Process::Nill),
|
next_process: Rc::new(Process::Nill),
|
||||||
},
|
},
|
||||||
reaction_rules: Rc::new(vec![
|
Rc::new(vec![
|
||||||
Reaction::from(Set::from([1]), Set::from([3]), Set::from([3])),
|
Reaction::from(Set::from([1]), Set::from([3]), Set::from([3])),
|
||||||
Reaction::from(Set::from([3]), Set::from([1]), Set::from([1])),
|
Reaction::from(Set::from([3]), Set::from([1]), Set::from([1])),
|
||||||
Reaction::from(Set::from([2]), Set::default(), Set::from([4])),
|
Reaction::from(Set::from([2]), Set::default(), Set::from([4])),
|
||||||
]),
|
]),
|
||||||
};
|
);
|
||||||
|
|
||||||
let res = system.clone().traces(10).unwrap();
|
let res = system.clone().traces(10).unwrap();
|
||||||
assert_eq!(res.len(), 1);
|
assert_eq!(res.len(), 1);
|
||||||
@ -278,15 +278,15 @@ fn conversion_reactions() {
|
|||||||
use super::set::Set;
|
use super::set::Set;
|
||||||
use super::system::{PositiveSystem, System};
|
use super::system::{PositiveSystem, System};
|
||||||
|
|
||||||
let system = System {
|
let system = System::from(
|
||||||
delta: Rc::new(Environment::from([])),
|
Rc::new(Environment::from([])),
|
||||||
available_entities: Set::from([1, 2]),
|
Set::from([1, 2]),
|
||||||
context_process: Process::Nill,
|
Process::Nill,
|
||||||
reaction_rules: Rc::new(vec![
|
Rc::new(vec![
|
||||||
Reaction::from(Set::from([2]), Set::from([1, 3]), Set::from([5])),
|
Reaction::from(Set::from([2]), Set::from([1, 3]), Set::from([5])),
|
||||||
Reaction::from(Set::from([1, 2]), Set::from([3]), Set::from([5])),
|
Reaction::from(Set::from([1, 2]), Set::from([3]), Set::from([5])),
|
||||||
]),
|
]),
|
||||||
};
|
);
|
||||||
let converted_system: PositiveSystem = system.into();
|
let converted_system: PositiveSystem = system.into();
|
||||||
let mut reactions = converted_system.reactions().clone();
|
let mut reactions = converted_system.reactions().clone();
|
||||||
reactions.sort_by(|a, b| {
|
reactions.sort_by(|a, b| {
|
||||||
@ -322,15 +322,15 @@ fn conversion_entities() {
|
|||||||
use super::set::Set;
|
use super::set::Set;
|
||||||
use super::system::{PositiveSystem, System};
|
use super::system::{PositiveSystem, System};
|
||||||
|
|
||||||
let system = System {
|
let system = System::from(
|
||||||
delta: Rc::new(Environment::from([])),
|
Rc::new(Environment::from([])),
|
||||||
available_entities: Set::from([1, 2]),
|
Set::from([1, 2]),
|
||||||
context_process: Process::Nill,
|
Process::Nill,
|
||||||
reaction_rules: Rc::new(vec![
|
Rc::new(vec![
|
||||||
Reaction::from(Set::from([2]), Set::from([1, 3]), Set::from([5])),
|
Reaction::from(Set::from([2]), Set::from([1, 3]), Set::from([5])),
|
||||||
Reaction::from(Set::from([1, 2]), Set::from([3]), Set::from([5])),
|
Reaction::from(Set::from([1, 2]), Set::from([3]), Set::from([5])),
|
||||||
]),
|
]),
|
||||||
};
|
);
|
||||||
let converted_system: PositiveSystem = system.into();
|
let converted_system: PositiveSystem = system.into();
|
||||||
let entities = converted_system.available_entities().clone();
|
let entities = converted_system.available_entities().clone();
|
||||||
|
|
||||||
|
|||||||
415
rsprocess/src/trace.rs
Normal file
415
rsprocess/src/trace.rs
Normal file
@ -0,0 +1,415 @@
|
|||||||
|
use std::fmt::Debug;
|
||||||
|
use std::ops::{Index, IndexMut};
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::slice::SliceIndex;
|
||||||
|
|
||||||
|
use crate::reaction::{BasicReaction, PositiveReaction, Reaction};
|
||||||
|
use crate::set::{BasicSet, PositiveSet, Set};
|
||||||
|
use crate::system::{BasicSystem, PositiveSystem, System};
|
||||||
|
use crate::translator::{Formatter, PrintableWithTranslator};
|
||||||
|
|
||||||
|
type TraceElement<L, Sys> = (Option<Rc<L>>, Rc<Sys>);
|
||||||
|
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub struct Trace<L, Sys> {
|
||||||
|
pub values: Vec<TraceElement<L, Sys>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L, Sys> Trace<L, Sys> {
|
||||||
|
pub fn push(&mut self, val: TraceElement<L, Sys>) {
|
||||||
|
self.values.push(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.values.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.values.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L, Sys> From<&[TraceElement<L, Sys>]> for Trace<L, Sys> {
|
||||||
|
fn from(value: &[TraceElement<L, Sys>]) -> Self {
|
||||||
|
Self {
|
||||||
|
values: value.to_vec(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L, Sys, const N: usize> From<&[TraceElement<L, Sys>; N]>
|
||||||
|
for Trace<L, Sys>
|
||||||
|
{
|
||||||
|
fn from(value: &[TraceElement<L, Sys>; N]) -> Self {
|
||||||
|
Self {
|
||||||
|
values: value.to_vec(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, L, Sys> From<&'a Vec<TraceElement<L, Sys>>> for Trace<L, Sys> {
|
||||||
|
fn from(value: &'a Vec<TraceElement<L, Sys>>) -> Self {
|
||||||
|
Self {
|
||||||
|
values: value.to_vec(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L, Sys> From<Vec<TraceElement<L, Sys>>> for Trace<L, Sys> {
|
||||||
|
fn from(value: Vec<TraceElement<L, Sys>>) -> Self {
|
||||||
|
Self { values: value }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L, Sys, I: SliceIndex<[TraceElement<L, Sys>]>> Index<I> for Trace<L, Sys> {
|
||||||
|
type Output = I::Output;
|
||||||
|
|
||||||
|
fn index(&self, index: I) -> &Self::Output {
|
||||||
|
&self.values[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L, Sys, I: SliceIndex<[TraceElement<L, Sys>]>> IndexMut<I>
|
||||||
|
for Trace<L, Sys>
|
||||||
|
{
|
||||||
|
fn index_mut(&mut self, index: I) -> &mut Self::Output {
|
||||||
|
&mut self.values[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Slicing Trace
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub struct SlicingElement<S> {
|
||||||
|
pub context: S,
|
||||||
|
pub reaction_products: S,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> Debug for SlicingElement<S>
|
||||||
|
where
|
||||||
|
S: Debug,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{{context: {:?} - reaction_products: {:?}}}",
|
||||||
|
self.context, self.reaction_products
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> PrintableWithTranslator for SlicingElement<S>
|
||||||
|
where
|
||||||
|
S: PrintableWithTranslator,
|
||||||
|
{
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut std::fmt::Formatter,
|
||||||
|
translator: &crate::translator::Translator,
|
||||||
|
) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{{context: {}, ",
|
||||||
|
Formatter::from(translator, &self.context)
|
||||||
|
)?;
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"reaction products: {}}}",
|
||||||
|
Formatter::from(translator, &self.reaction_products)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug)]
|
||||||
|
pub struct EnabledReactions {
|
||||||
|
pub data: Vec<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrintableWithTranslator for EnabledReactions {
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut std::fmt::Formatter,
|
||||||
|
_translator: &crate::translator::Translator,
|
||||||
|
) -> std::fmt::Result {
|
||||||
|
let mut elements = self.data.iter().peekable();
|
||||||
|
while let Some(e) = elements.next() {
|
||||||
|
if elements.peek().is_some() {
|
||||||
|
write!(f, "{e}, ")?;
|
||||||
|
} else {
|
||||||
|
write!(f, "{e}")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a EnabledReactions {
|
||||||
|
type Item = &'a usize;
|
||||||
|
type IntoIter = std::slice::Iter<'a, usize>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.data.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnabledReactions {
|
||||||
|
pub fn iter(&self) -> std::slice::Iter<'_, usize> {
|
||||||
|
self.into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SlicingTrace<S: BasicSet,
|
||||||
|
R: BasicReaction<Set = S>,
|
||||||
|
Sys: BasicSystem<Set = S, Reaction = R>>
|
||||||
|
{
|
||||||
|
pub elements: Vec<SlicingElement<S>>,
|
||||||
|
pub enabled_reactions: Vec<EnabledReactions>,
|
||||||
|
|
||||||
|
pub reactions: Rc<Vec<R>>,
|
||||||
|
pub systems: Vec<Rc<Sys>>,
|
||||||
|
|
||||||
|
pub context_elements: Rc<S>,
|
||||||
|
pub products_elements: Rc<S>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: BasicSet,
|
||||||
|
R: BasicReaction<Set = S>,
|
||||||
|
Sys: BasicSystem<Set = S, Reaction = R>>
|
||||||
|
Default for SlicingTrace<S, R, Sys>
|
||||||
|
{
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
elements: Vec::default(),
|
||||||
|
enabled_reactions: Vec::default(),
|
||||||
|
reactions: Rc::new(Vec::default()),
|
||||||
|
systems: Vec::default(),
|
||||||
|
context_elements: Rc::new(S::default()),
|
||||||
|
products_elements: Rc::new(S::default()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: BasicSet + Debug,
|
||||||
|
R: BasicReaction<Set = S>,
|
||||||
|
Sys: BasicSystem<Set = S, Reaction = R>>
|
||||||
|
SlicingTrace<S, R, Sys>
|
||||||
|
{
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.elements.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.elements.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl SlicingTrace<Set, Reaction, System> {
|
||||||
|
pub fn slice(&self, marking: Set) -> Result<Self, String> {
|
||||||
|
let mut reversed_elements = Vec::with_capacity(self.elements.len());
|
||||||
|
reversed_elements.push(SlicingElement {
|
||||||
|
context: self
|
||||||
|
.elements
|
||||||
|
.last()
|
||||||
|
.ok_or("Trace with length zero.")?
|
||||||
|
.context
|
||||||
|
.clone(),
|
||||||
|
reaction_products: marking,
|
||||||
|
});
|
||||||
|
let mut reversed_enabled_reactions: Vec<EnabledReactions> =
|
||||||
|
Vec::with_capacity(self.enabled_reactions.len());
|
||||||
|
|
||||||
|
for i in (1..(self.len())).rev() {
|
||||||
|
let reverse_i: usize = self.len() - i;
|
||||||
|
let i = i - 1;
|
||||||
|
if reversed_elements.len() <= reverse_i {
|
||||||
|
reversed_elements.push(SlicingElement::default());
|
||||||
|
}
|
||||||
|
if reversed_enabled_reactions.len() <= reverse_i {
|
||||||
|
reversed_enabled_reactions.push(EnabledReactions::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
for r in self.enabled_reactions[i].iter() {
|
||||||
|
if !reversed_elements[reverse_i - 1]
|
||||||
|
.reaction_products
|
||||||
|
.is_disjoint(self.reactions[*r].products())
|
||||||
|
{
|
||||||
|
reversed_enabled_reactions[reverse_i - 1].data.push(*r);
|
||||||
|
reversed_elements[reverse_i].context.push(
|
||||||
|
&self.reactions[*r]
|
||||||
|
.reactants()
|
||||||
|
.intersection(&self.context_elements),
|
||||||
|
);
|
||||||
|
reversed_elements[reverse_i].reaction_products.push(
|
||||||
|
&self.reactions[*r]
|
||||||
|
.reactants()
|
||||||
|
.intersection(&self.products_elements),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reversed_elements.reverse();
|
||||||
|
reversed_enabled_reactions.reverse();
|
||||||
|
|
||||||
|
let new_trace = Self {
|
||||||
|
elements: reversed_elements,
|
||||||
|
enabled_reactions: reversed_enabled_reactions,
|
||||||
|
reactions: Rc::clone(&self.reactions),
|
||||||
|
systems: self.systems.to_vec(),
|
||||||
|
context_elements: Rc::clone(&self.context_elements),
|
||||||
|
products_elements: Rc::clone(&self.products_elements),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(new_trace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SlicingTrace<PositiveSet, PositiveReaction, PositiveSystem> {
|
||||||
|
pub fn slice(&self, marking: PositiveSet) -> Result<Self, String> {
|
||||||
|
let mut reversed_elements = Vec::with_capacity(self.elements.len());
|
||||||
|
reversed_elements.push(SlicingElement {
|
||||||
|
context: self
|
||||||
|
.elements
|
||||||
|
.last()
|
||||||
|
.ok_or("Trace with length zero.")?
|
||||||
|
.context
|
||||||
|
.clone(),
|
||||||
|
reaction_products: marking,
|
||||||
|
});
|
||||||
|
let mut reversed_enabled_reactions: Vec<EnabledReactions> =
|
||||||
|
Vec::with_capacity(self.enabled_reactions.len());
|
||||||
|
|
||||||
|
for i in (1..(self.len())).rev() {
|
||||||
|
let reverse_i: usize = self.len() - i;
|
||||||
|
let i = i - 1;
|
||||||
|
if reversed_elements.len() <= reverse_i {
|
||||||
|
reversed_elements.push(SlicingElement::default());
|
||||||
|
}
|
||||||
|
if reversed_enabled_reactions.len() <= reverse_i {
|
||||||
|
reversed_enabled_reactions.push(EnabledReactions::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
for r in self.enabled_reactions[i].iter() {
|
||||||
|
if !reversed_elements[reverse_i - 1]
|
||||||
|
.reaction_products
|
||||||
|
.intersection(self.reactions[*r].products()).is_empty()
|
||||||
|
{
|
||||||
|
reversed_enabled_reactions[reverse_i - 1].data.push(*r);
|
||||||
|
reversed_elements[reverse_i].context.push(
|
||||||
|
&self.reactions[*r]
|
||||||
|
.reactants()
|
||||||
|
.mask(&self.context_elements),
|
||||||
|
);
|
||||||
|
reversed_elements[reverse_i].reaction_products.push(
|
||||||
|
&self.reactions[*r]
|
||||||
|
.reactants()
|
||||||
|
.mask(&self.products_elements),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reversed_elements.reverse();
|
||||||
|
reversed_enabled_reactions.reverse();
|
||||||
|
|
||||||
|
let new_trace = Self {
|
||||||
|
elements: reversed_elements,
|
||||||
|
enabled_reactions: reversed_enabled_reactions,
|
||||||
|
reactions: Rc::clone(&self.reactions),
|
||||||
|
systems: self.systems.to_vec(),
|
||||||
|
context_elements: Rc::clone(&self.context_elements),
|
||||||
|
products_elements: Rc::clone(&self.products_elements),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(new_trace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<S: BasicSet,
|
||||||
|
R: BasicReaction<Set = S>,
|
||||||
|
Sys: BasicSystem<Set = S, Reaction = R>,>
|
||||||
|
PrintableWithTranslator for SlicingTrace<S, R, Sys>
|
||||||
|
{
|
||||||
|
fn print(
|
||||||
|
&self,
|
||||||
|
f: &mut std::fmt::Formatter,
|
||||||
|
translator: &crate::translator::Translator,
|
||||||
|
) -> std::fmt::Result {
|
||||||
|
// let mut systems = self.systems.iter().peekable();
|
||||||
|
// writeln!(f, "Systems:")?;
|
||||||
|
// while let Some(system) = systems.next() {
|
||||||
|
// if systems.peek().is_some() {
|
||||||
|
// write!(f, "{} --> ", Formatter::from(translator,
|
||||||
|
// &**system))?; } else {
|
||||||
|
// writeln!(f, "{}", Formatter::from(translator, &**system))?;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
let mut reactions = self.reactions.iter().enumerate().peekable();
|
||||||
|
writeln!(f, "Reactions:")?;
|
||||||
|
while let Some((pos, reaction)) = reactions.next() {
|
||||||
|
if reactions.peek().is_some() {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"\t({pos}) {},",
|
||||||
|
Formatter::from(translator, reaction)
|
||||||
|
)?;
|
||||||
|
} else {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"\t({pos}) {}.",
|
||||||
|
Formatter::from(translator, reaction)
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"Context Elements: {}",
|
||||||
|
Formatter::from(translator, &*self.context_elements)
|
||||||
|
)?;
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"Product Elements: {}",
|
||||||
|
Formatter::from(translator, &*self.products_elements)
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut elements = self.elements.iter().peekable();
|
||||||
|
let mut enabled_reactions = self.enabled_reactions.iter();
|
||||||
|
|
||||||
|
writeln!(f, "Trace:")?;
|
||||||
|
while let Some(el) = elements.next() {
|
||||||
|
if let Some(r) = enabled_reactions.next() {
|
||||||
|
if elements.peek().is_some() {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"{}\n\t|\n{: ^17}\n\t|\n\t▼",
|
||||||
|
Formatter::from(translator, el),
|
||||||
|
format!("({})", Formatter::from(translator, r)),
|
||||||
|
)?;
|
||||||
|
} else {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"{}\n\t|\n{: ^17}\n\t|\n\t?",
|
||||||
|
Formatter::from(translator, el),
|
||||||
|
format!("({})", Formatter::from(translator, r)),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
} else if elements.peek().is_some() {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"{}\n\t|\n\t|\n\t|\n\t▼",
|
||||||
|
Formatter::from(translator, el)
|
||||||
|
)?;
|
||||||
|
} else {
|
||||||
|
writeln!(f, "{}", Formatter::from(translator, el))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
382
rsprocess/src/trace_test.rs
Normal file
382
rsprocess/src/trace_test.rs
Normal file
@ -0,0 +1,382 @@
|
|||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use crate::element::IdState;
|
||||||
|
use crate::reaction::{BasicReaction, PositiveReaction, Reaction};
|
||||||
|
use crate::set::{ExtensionsSet, PositiveSet, Set, BasicSet};
|
||||||
|
use crate::system::{PositiveSystem, System};
|
||||||
|
use crate::trace::*;
|
||||||
|
use crate::translator::Translator;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn slice_atoi() {
|
||||||
|
let mut translator = Translator::new();
|
||||||
|
|
||||||
|
let reactions = vec![
|
||||||
|
(
|
||||||
|
vec!["tgfbr", "stat3", "il6r"],
|
||||||
|
vec!["tbet", "gata3", "foxp3"],
|
||||||
|
vec!["rorgt"],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
vec!["tgfbr", "stat3", "il21r"],
|
||||||
|
vec!["tbet", "gata3", "foxp3"],
|
||||||
|
vec!["rorgt"],
|
||||||
|
),
|
||||||
|
(vec!["il23r"], vec![], vec!["stat3"]),
|
||||||
|
(vec!["il21"], vec![], vec!["il21r"]),
|
||||||
|
(vec!["il6"], vec![], vec!["il6r"]),
|
||||||
|
(vec!["tcr"], vec!["foxp3"], vec!["nfat"]),
|
||||||
|
(vec!["il27", "nfat"], vec![], vec!["stat1"]),
|
||||||
|
(vec!["stat1"], vec!["rorgt", "foxp3"], vec!["tbet"]),
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.map(|r| {
|
||||||
|
Reaction::from(
|
||||||
|
r.0.iter()
|
||||||
|
.map(|el| translator.encode(*el))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into(),
|
||||||
|
r.1.iter()
|
||||||
|
.map(|el| translator.encode(*el))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into(),
|
||||||
|
r.2.iter()
|
||||||
|
.map(|el| translator.encode(*el))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let elements = [
|
||||||
|
(vec!["il23r", "il21"], vec!["tcr"]),
|
||||||
|
(vec!["il21r", "stat3", "nfat"], vec!["il27"]),
|
||||||
|
(vec!["stat1"], vec![]),
|
||||||
|
(vec!["tbet"], vec![]),
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.map(|elements| SlicingElement {
|
||||||
|
context: elements
|
||||||
|
.1
|
||||||
|
.iter()
|
||||||
|
.map(|el| translator.encode(*el))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into(),
|
||||||
|
reaction_products: elements
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.map(|el| translator.encode(*el))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into(),
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let enabled_reactions = vec![vec![3, 4, 6], vec![7], vec![8]]
|
||||||
|
.into_iter()
|
||||||
|
.map(|r| EnabledReactions {
|
||||||
|
data: r.iter().map(|i| i - 1).collect::<Vec<_>>(),
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let context_elements = ["tgfb", "il6", "tcr", "il27"]
|
||||||
|
.iter()
|
||||||
|
.map(|el| translator.encode(*el))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into();
|
||||||
|
let products_elements =
|
||||||
|
["rorgt", "stat3", "il21r", "il6r", "nfat", "stat1", "tbet", "il21",
|
||||||
|
"il23r"]
|
||||||
|
.iter()
|
||||||
|
.map(|el| translator.encode(*el))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into();
|
||||||
|
|
||||||
|
let trace: SlicingTrace<Set, Reaction, System> = SlicingTrace {
|
||||||
|
elements,
|
||||||
|
enabled_reactions,
|
||||||
|
|
||||||
|
reactions: Rc::new(reactions),
|
||||||
|
systems: vec![],
|
||||||
|
context_elements: Rc::new(context_elements),
|
||||||
|
products_elements: Rc::new(products_elements),
|
||||||
|
};
|
||||||
|
|
||||||
|
let marking = ["tbet"]
|
||||||
|
.iter()
|
||||||
|
.map(|el| translator.encode(*el))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into();
|
||||||
|
|
||||||
|
let sliced = trace.slice(marking).unwrap();
|
||||||
|
|
||||||
|
let mut reaction_products = sliced
|
||||||
|
.elements
|
||||||
|
.iter()
|
||||||
|
.map(|elements| {
|
||||||
|
elements
|
||||||
|
.reaction_products
|
||||||
|
.iter()
|
||||||
|
.map(|el| translator.decode(*el).unwrap())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
reaction_products.iter_mut().for_each(|x| x.sort());
|
||||||
|
let mut correct_reaction_products =
|
||||||
|
vec![vec![], vec!["nfat"], vec!["stat1"], vec!["tbet"]];
|
||||||
|
correct_reaction_products.iter_mut().for_each(|x| x.sort());
|
||||||
|
|
||||||
|
assert_eq!(reaction_products, correct_reaction_products);
|
||||||
|
|
||||||
|
let mut context = sliced
|
||||||
|
.elements
|
||||||
|
.iter()
|
||||||
|
.map(|elements| {
|
||||||
|
elements
|
||||||
|
.context
|
||||||
|
.iter()
|
||||||
|
.map(|el| translator.decode(*el).unwrap())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
context.iter_mut().for_each(|x| x.sort());
|
||||||
|
let mut correct_context = vec![vec!["tcr"], vec!["il27"], vec![], vec![]];
|
||||||
|
correct_context.iter_mut().for_each(|x| x.sort());
|
||||||
|
|
||||||
|
assert_eq!(context, correct_context);
|
||||||
|
|
||||||
|
let mut enabled_reactions = sliced
|
||||||
|
.enabled_reactions
|
||||||
|
.iter()
|
||||||
|
.map(|elements| elements.data.clone())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
enabled_reactions.iter_mut().for_each(|x| x.sort());
|
||||||
|
let mut correct_enabled_reactions = vec![vec![5], vec![6], vec![7]];
|
||||||
|
correct_enabled_reactions.iter_mut().for_each(|x| x.sort());
|
||||||
|
|
||||||
|
assert_eq!(enabled_reactions, correct_enabled_reactions);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn slice_positive_atoi() {
|
||||||
|
let mut translator = Translator::new();
|
||||||
|
|
||||||
|
let reactions = {
|
||||||
|
let reactions = vec![
|
||||||
|
(
|
||||||
|
vec!["tgfbr", "stat3", "il6r"],
|
||||||
|
vec!["tbet", "gata3", "foxp3"],
|
||||||
|
vec!["rorgt"],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
vec!["tgfbr", "stat3", "il21r"],
|
||||||
|
vec!["tbet", "gata3", "foxp3"],
|
||||||
|
vec!["rorgt"],
|
||||||
|
),
|
||||||
|
(vec!["il23r"], vec![], vec!["stat3"]),
|
||||||
|
(vec!["il21"], vec![], vec!["il21r"]),
|
||||||
|
(vec!["il6"], vec![], vec!["il6r"]),
|
||||||
|
(vec!["tcr"], vec!["foxp3"], vec!["nfat"]),
|
||||||
|
(vec!["il27", "nfat"], vec![], vec!["stat1"]),
|
||||||
|
(vec!["stat1"], vec!["rorgt", "foxp3"], vec!["tbet"]),
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.map(|r| {
|
||||||
|
Reaction::from(
|
||||||
|
r.0.iter()
|
||||||
|
.map(|el| translator.encode(*el))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into(),
|
||||||
|
r.1.iter()
|
||||||
|
.map(|el| translator.encode(*el))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into(),
|
||||||
|
r.2.iter()
|
||||||
|
.map(|el| translator.encode(*el))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let system = System::from(
|
||||||
|
Rc::new(crate::environment::Environment::from([])),
|
||||||
|
Set::from([]),
|
||||||
|
crate::process::Process::Nill,
|
||||||
|
Rc::new(reactions),
|
||||||
|
);
|
||||||
|
|
||||||
|
let converted_system: PositiveSystem = system.into();
|
||||||
|
let mut reactions = Rc::try_unwrap(converted_system.reaction_rules).unwrap();
|
||||||
|
reactions.sort_by(|a, b| a.reactants.cmp(&b.reactants)
|
||||||
|
.then(a.products.cmp(&b.products)));
|
||||||
|
|
||||||
|
println!("Computed Reactions:");
|
||||||
|
for (pos, r) in reactions.iter().enumerate() {
|
||||||
|
println!("\t({pos}) {},", crate::translator::Formatter::from(&translator, r));
|
||||||
|
}
|
||||||
|
reactions
|
||||||
|
};
|
||||||
|
|
||||||
|
let elements = [
|
||||||
|
(vec![("il23r", IdState::Positive), ("il21", IdState::Positive),
|
||||||
|
("rorgt", IdState::Negative), ("stat3", IdState::Negative),
|
||||||
|
("il21r", IdState::Negative), ("il6r", IdState::Negative),
|
||||||
|
("nfat", IdState::Negative), ("stat1", IdState::Negative),
|
||||||
|
("tbet", IdState::Negative), ("tgfbr", IdState::Negative),
|
||||||
|
("foxp3", IdState::Negative)],
|
||||||
|
vec![("tcr", IdState::Positive), ("tgfb", IdState::Negative),
|
||||||
|
("il6", IdState::Negative), ("il27", IdState::Negative)]),
|
||||||
|
(vec![("il21r", IdState::Positive), ("stat3", IdState::Positive),
|
||||||
|
("nfat", IdState::Positive), ("rorgt", IdState::Negative),
|
||||||
|
("il6r", IdState::Negative), ("stat1", IdState::Negative),
|
||||||
|
("tbet", IdState::Negative), ("il21", IdState::Negative),
|
||||||
|
("il23r", IdState::Negative), ("tgfbr", IdState::Negative),
|
||||||
|
("foxp3", IdState::Negative)],
|
||||||
|
vec![("il27", IdState::Positive), ("tgfb", IdState::Negative),
|
||||||
|
("il6", IdState::Negative), ("tcr", IdState::Negative)]),
|
||||||
|
(vec![("stat1", IdState::Positive), ("rorgt", IdState::Negative),
|
||||||
|
("stat3", IdState::Negative), ("il21r", IdState::Negative),
|
||||||
|
("il6r", IdState::Negative), ("nfat", IdState::Negative),
|
||||||
|
("tbet", IdState::Negative), ("il21", IdState::Negative),
|
||||||
|
("il23r", IdState::Negative), ("tgfbr", IdState::Negative),
|
||||||
|
("foxp3", IdState::Negative)],
|
||||||
|
vec![("il27", IdState::Negative), ("tgfb", IdState::Negative),
|
||||||
|
("il6", IdState::Negative), ("tcr", IdState::Negative)]),
|
||||||
|
(vec![("tbet", IdState::Positive), ("rorgt", IdState::Negative),
|
||||||
|
("stat3", IdState::Negative), ("il21r", IdState::Negative),
|
||||||
|
("il6r", IdState::Negative), ("nfat", IdState::Negative),
|
||||||
|
("stat1", IdState::Negative), ("il21", IdState::Negative),
|
||||||
|
("il23r", IdState::Negative), ("tgfbr", IdState::Negative),
|
||||||
|
("foxp3", IdState::Negative)],
|
||||||
|
vec![]),
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.map(|elements| SlicingElement {
|
||||||
|
context: Into::<PositiveSet>::into(
|
||||||
|
elements
|
||||||
|
.1
|
||||||
|
.iter()
|
||||||
|
.map(|el| (translator.encode(el.0), el.1))
|
||||||
|
.collect::<Vec<_>>()),
|
||||||
|
reaction_products: Into::<PositiveSet>::into(
|
||||||
|
elements
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.map(|el| (translator.encode(el.0), el.1))
|
||||||
|
.collect::<Vec<_>>()),
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
|
||||||
|
let enabled_reactions = {
|
||||||
|
let mut enabled_reactions = vec![];
|
||||||
|
for slice_el in elements.iter().rev().skip(1).rev() {
|
||||||
|
let available_enteties = slice_el.context.union(&slice_el.reaction_products);
|
||||||
|
enabled_reactions.push(vec![]);
|
||||||
|
for (pos, r) in reactions.iter().enumerate() {
|
||||||
|
if r.enabled(&available_enteties) {
|
||||||
|
enabled_reactions.last_mut().unwrap().push(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enabled_reactions.into_iter()
|
||||||
|
.map(|r| EnabledReactions {
|
||||||
|
data: r,
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
};
|
||||||
|
|
||||||
|
let context_elements =
|
||||||
|
Into::<Set>::into(
|
||||||
|
["tgfb", "il6", "tcr", "il27"]
|
||||||
|
.iter()
|
||||||
|
.map(|el| translator.encode(*el))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
).to_positive_set(IdState::Positive);
|
||||||
|
let products_elements =
|
||||||
|
Into::<Set>::into(
|
||||||
|
["rorgt", "stat3", "il21r", "il6r", "nfat", "stat1", "tbet", "il21",
|
||||||
|
"il23r", "tgfbr", "foxp3"]
|
||||||
|
.iter()
|
||||||
|
.map(|el| translator.encode(*el))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
).to_positive_set(IdState::Positive);
|
||||||
|
|
||||||
|
let trace: SlicingTrace<PositiveSet, PositiveReaction, PositiveSystem> =
|
||||||
|
SlicingTrace {
|
||||||
|
elements,
|
||||||
|
enabled_reactions,
|
||||||
|
|
||||||
|
reactions: Rc::new(reactions),
|
||||||
|
systems: vec![],
|
||||||
|
context_elements: Rc::new(context_elements),
|
||||||
|
products_elements: Rc::new(products_elements),
|
||||||
|
};
|
||||||
|
|
||||||
|
let marking =
|
||||||
|
Into::<Set>::into(
|
||||||
|
["tbet"]
|
||||||
|
.iter()
|
||||||
|
.map(|el| translator.encode(*el))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
).to_positive_set(IdState::Positive);
|
||||||
|
|
||||||
|
let sliced = trace.slice(marking).unwrap();
|
||||||
|
|
||||||
|
let mut reaction_products = sliced
|
||||||
|
.elements
|
||||||
|
.iter()
|
||||||
|
.map(|elements| {
|
||||||
|
elements
|
||||||
|
.reaction_products
|
||||||
|
.iter()
|
||||||
|
.map(|el| (translator.decode(*el.0).unwrap(), *el.1))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
reaction_products.iter_mut().for_each(|x| x.sort());
|
||||||
|
let mut correct_reaction_products: Vec<Vec<(String, IdState)>> =
|
||||||
|
[vec![("foxp3", IdState::Negative)],
|
||||||
|
vec![("nfat", IdState::Positive), ("tgfbr", IdState::Negative)],
|
||||||
|
vec![("stat1", IdState::Positive), ("foxp3", IdState::Negative),
|
||||||
|
("rorgt", IdState::Negative)],
|
||||||
|
vec![("tbet", IdState::Positive)]]
|
||||||
|
.iter().map(|x| x.iter().map(|y| (y.0.to_string(), y.1))
|
||||||
|
.collect::<Vec<_>>()).collect::<Vec<_>>();
|
||||||
|
correct_reaction_products.iter_mut().for_each(|x| x.sort());
|
||||||
|
|
||||||
|
assert_eq!(reaction_products, correct_reaction_products);
|
||||||
|
|
||||||
|
let mut context = sliced
|
||||||
|
.elements
|
||||||
|
.iter()
|
||||||
|
.map(|elements| {
|
||||||
|
elements
|
||||||
|
.context
|
||||||
|
.iter()
|
||||||
|
.map(|el| (translator.decode(*el.0).unwrap(), *el.1))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
context.iter_mut().for_each(|x| x.sort());
|
||||||
|
let mut correct_context =
|
||||||
|
[vec![("tcr", IdState::Positive)],
|
||||||
|
vec![("il27", IdState::Positive)],
|
||||||
|
vec![],
|
||||||
|
vec![]]
|
||||||
|
.iter().map(|x| x.iter().map(|y| (y.0.to_string(), y.1))
|
||||||
|
.collect::<Vec<_>>()).collect::<Vec<_>>();
|
||||||
|
correct_context.iter_mut().for_each(|x| x.sort());
|
||||||
|
|
||||||
|
assert_eq!(context, correct_context);
|
||||||
|
|
||||||
|
let mut enabled_reactions = sliced
|
||||||
|
.enabled_reactions
|
||||||
|
.iter()
|
||||||
|
.map(|elements| elements.data.clone())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
enabled_reactions.iter_mut().for_each(|x| x.sort());
|
||||||
|
let mut correct_enabled_reactions = vec![vec![11], vec![2, 20], vec![10]];
|
||||||
|
correct_enabled_reactions.iter_mut().for_each(|x| x.sort());
|
||||||
|
|
||||||
|
assert_eq!(enabled_reactions, correct_enabled_reactions);
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
//! Module for helper structure for simulation
|
//! Module for helper structure for simulation
|
||||||
|
|
||||||
|
use std::fmt::Debug;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use super::label::{Label, PositiveLabel};
|
use super::label::{Label, PositiveLabel};
|
||||||
@ -8,6 +9,12 @@ use super::reaction::BasicReaction;
|
|||||||
use super::set::{BasicSet, PositiveSet, Set};
|
use super::set::{BasicSet, PositiveSet, Set};
|
||||||
use super::system::{BasicSystem, ExtensionsSystem, PositiveSystem, System};
|
use super::system::{BasicSystem, ExtensionsSystem, PositiveSystem, System};
|
||||||
|
|
||||||
|
pub trait BasicTransition
|
||||||
|
where
|
||||||
|
Self: Clone + Debug + Iterator,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct TransitionsIterator<
|
pub struct TransitionsIterator<
|
||||||
'a,
|
'a,
|
||||||
@ -19,12 +26,16 @@ pub struct TransitionsIterator<
|
|||||||
system: &'a Sys,
|
system: &'a Sys,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TransitionsIterator<'a, Set, System, Process> {
|
impl<'a> BasicTransition for TransitionsIterator<'a, Set, System, Process> {}
|
||||||
pub fn from(system: &'a System) -> Result<Self, String> {
|
|
||||||
match system.unfold() {
|
impl<'a> TryFrom<&'a System> for TransitionsIterator<'a, Set, System, Process> {
|
||||||
| Ok(o) => Ok(TransitionsIterator {
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(value: &'a System) -> Result<Self, Self::Error> {
|
||||||
|
match value.unfold() {
|
||||||
|
| Ok(o) => Ok(Self {
|
||||||
choices_iterator: o.into_iter(),
|
choices_iterator: o.into_iter(),
|
||||||
system,
|
system: value,
|
||||||
}),
|
}),
|
||||||
| Err(e) => Err(e),
|
| Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
@ -35,7 +46,7 @@ impl<'a> Iterator for TransitionsIterator<'a, Set, System, Process> {
|
|||||||
type Item = (Label, System);
|
type Item = (Label, System);
|
||||||
|
|
||||||
/// Creates the next arc from the current system.
|
/// Creates the next arc from the current system.
|
||||||
fn next(&mut self) -> Option<(Label, System)> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let (c, k) = self.choices_iterator.next()?;
|
let (c, k) = self.choices_iterator.next()?;
|
||||||
let t = self.system.available_entities.union(c.as_ref());
|
let t = self.system.available_entities.union(c.as_ref());
|
||||||
let (
|
let (
|
||||||
@ -44,7 +55,7 @@ impl<'a> Iterator for TransitionsIterator<'a, Set, System, Process> {
|
|||||||
inhibitors,
|
inhibitors,
|
||||||
inhibitors_present,
|
inhibitors_present,
|
||||||
products,
|
products,
|
||||||
) = self.system.reaction_rules.iter().fold(
|
) = self.system.reactions().iter().fold(
|
||||||
(
|
(
|
||||||
Set::default(), // reactants
|
Set::default(), // reactants
|
||||||
Set::default(), // reactants_absent
|
Set::default(), // reactants_absent
|
||||||
@ -95,12 +106,21 @@ impl<'a> Iterator for TransitionsIterator<'a, Set, System, Process> {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
impl<'a> TransitionsIterator<'a, PositiveSet, PositiveSystem, PositiveProcess> {
|
impl<'a> BasicTransition
|
||||||
pub fn from(system: &'a PositiveSystem) -> Result<Self, String> {
|
for TransitionsIterator<'a, PositiveSet, PositiveSystem, PositiveProcess>
|
||||||
match system.unfold() {
|
{
|
||||||
| Ok(o) => Ok(TransitionsIterator {
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<&'a PositiveSystem>
|
||||||
|
for TransitionsIterator<'a, PositiveSet, PositiveSystem, PositiveProcess>
|
||||||
|
{
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(value: &'a PositiveSystem) -> Result<Self, Self::Error> {
|
||||||
|
match value.unfold() {
|
||||||
|
| Ok(o) => Ok(Self {
|
||||||
choices_iterator: o.into_iter(),
|
choices_iterator: o.into_iter(),
|
||||||
system,
|
system: value,
|
||||||
}),
|
}),
|
||||||
| Err(e) => Err(e),
|
| Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
@ -174,3 +194,71 @@ impl<'a> Iterator
|
|||||||
Some((label, new_system))
|
Some((label, new_system))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
pub struct TraceIterator<
|
||||||
|
'a,
|
||||||
|
S: BasicSet,
|
||||||
|
Sys: BasicSystem<Set = S, Process = Proc>,
|
||||||
|
Proc: BasicProcess<Set = S>,
|
||||||
|
> {
|
||||||
|
choices_iterator:
|
||||||
|
<<Sys as BasicSystem>::Choices as std::iter::IntoIterator>::IntoIter,
|
||||||
|
system: &'a Sys,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<&'a PositiveSystem>
|
||||||
|
for TraceIterator<'a, PositiveSet, PositiveSystem, PositiveProcess>
|
||||||
|
{
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(value: &'a PositiveSystem) -> Result<Self, Self::Error> {
|
||||||
|
match value.unfold() {
|
||||||
|
| Ok(o) => Ok(Self {
|
||||||
|
choices_iterator: o.into_iter(),
|
||||||
|
system: value,
|
||||||
|
}),
|
||||||
|
| Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator
|
||||||
|
for TraceIterator<'a, PositiveSet, PositiveSystem, PositiveProcess>
|
||||||
|
{
|
||||||
|
type Item = (PositiveSet, PositiveSet, Vec<usize>, PositiveSystem);
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let (context, k) = self.choices_iterator.next()?;
|
||||||
|
let total_entities =
|
||||||
|
self.system.available_entities().union(context.as_ref());
|
||||||
|
|
||||||
|
let (enabled_reaction_positions, all_products) =
|
||||||
|
self.system.reactions().iter().enumerate().fold(
|
||||||
|
(vec![], PositiveSet::default()),
|
||||||
|
|mut acc, (pos, reaction)| {
|
||||||
|
if reaction.enabled(&total_entities) {
|
||||||
|
acc.0.push(pos);
|
||||||
|
(acc.0, acc.1.union(&reaction.products))
|
||||||
|
} else {
|
||||||
|
acc
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let new_system = PositiveSystem::from(
|
||||||
|
Rc::clone(&self.system.delta),
|
||||||
|
all_products,
|
||||||
|
(*k).clone(),
|
||||||
|
Rc::clone(&self.system.reaction_rules),
|
||||||
|
);
|
||||||
|
|
||||||
|
Some((
|
||||||
|
context.as_ref().clone(),
|
||||||
|
self.system.available_entities().clone(),
|
||||||
|
enabled_reaction_positions,
|
||||||
|
new_system,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user