Slicing for traces, both normal and positive
This commit is contained in:
@ -14,5 +14,10 @@ fn main() {
|
||||
| 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.
|
||||
/// equivalent to main_do(digraph, Arcs) or to main_do(advdigraph, Arcs)
|
||||
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()?;
|
||||
system.graph = Some(graph);
|
||||
} else if let (Some(positive), true) =
|
||||
|
||||
@ -11,6 +11,7 @@ pub mod process;
|
||||
pub mod reaction;
|
||||
pub mod set;
|
||||
pub mod system;
|
||||
pub mod trace;
|
||||
|
||||
pub mod dot;
|
||||
pub mod frequency;
|
||||
@ -23,3 +24,6 @@ mod system_test;
|
||||
|
||||
#[cfg(test)]
|
||||
mod set_test;
|
||||
|
||||
#[cfg(test)]
|
||||
mod trace_test;
|
||||
|
||||
@ -19,6 +19,9 @@ where
|
||||
type Set: BasicSet;
|
||||
fn enabled(&self, state: &Self::Set) -> bool;
|
||||
fn compute_step(&self, state: &Self::Set) -> Option<&Self::Set>;
|
||||
|
||||
fn reactants(&self) -> &Self::Set;
|
||||
fn products(&self) -> &Self::Set;
|
||||
}
|
||||
|
||||
pub trait ExtensionReaction: Sized {
|
||||
@ -167,6 +170,14 @@ impl BasicReaction for Reaction {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn reactants(&self) -> &Self::Set {
|
||||
&self.reactants
|
||||
}
|
||||
|
||||
fn products(&self) -> &Self::Set {
|
||||
&self.products
|
||||
}
|
||||
}
|
||||
|
||||
impl PrintableWithTranslator for Reaction {
|
||||
@ -237,6 +248,14 @@ impl BasicReaction for PositiveReaction {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn reactants(&self) -> &Self::Set {
|
||||
&self.reactants
|
||||
}
|
||||
|
||||
fn products(&self) -> &Self::Set {
|
||||
&self.products
|
||||
}
|
||||
}
|
||||
|
||||
impl PrintableWithTranslator for PositiveReaction {
|
||||
|
||||
@ -636,6 +636,13 @@ impl PositiveSet {
|
||||
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>) {
|
||||
for element in other {
|
||||
self.identifiers.remove(&element);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::rc::Rc;
|
||||
@ -18,6 +18,7 @@ use super::reaction::{
|
||||
BasicReaction, ExtensionReaction, PositiveReaction, Reaction,
|
||||
};
|
||||
use super::set::{BasicSet, PositiveSet, Set};
|
||||
use super::trace::Trace;
|
||||
use super::transitions::TransitionsIterator;
|
||||
use super::translator::{Formatter, PrintableWithTranslator, Translator};
|
||||
|
||||
@ -51,9 +52,10 @@ where
|
||||
fn available_entities(&self) -> &Self::Set;
|
||||
fn context(&self) -> &Self::Process;
|
||||
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 {
|
||||
fn unfold(&self) -> Result<Self::Choices, String>;
|
||||
@ -134,9 +136,10 @@ impl<T: BasicSystem> ExtensionsSystem for T {
|
||||
let mut association = HashMap::new();
|
||||
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
|
||||
let current_node = *association.get(¤t).unwrap();
|
||||
|
||||
@ -144,7 +147,7 @@ impl<T: BasicSystem> ExtensionsSystem for T {
|
||||
// if not already visited
|
||||
let next_node =
|
||||
association.entry(next.clone()).or_insert_with(|| {
|
||||
stack.push(next.clone());
|
||||
stack.push_back(next.clone());
|
||||
graph.add_node(next)
|
||||
});
|
||||
graph.add_edge(current_node, *next_node, label);
|
||||
@ -244,8 +247,8 @@ impl<T: BasicSystem> ExtensionsSystem for T {
|
||||
}
|
||||
let mut n = n;
|
||||
let mut res: Vec<Trace<Self::Label, Self>> = vec![];
|
||||
let mut current_trace: Trace<Self::Label, Self> =
|
||||
vec![(None, Rc::new(self))];
|
||||
let mut current_trace: Trace<Self::Label, Self> = Trace::default();
|
||||
current_trace.push((None, Rc::new(self)));
|
||||
let mut branch = vec![0];
|
||||
let mut depth = 0;
|
||||
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
|
||||
// until we find another possible path.
|
||||
if new_branch {
|
||||
res.push(current_trace[0..depth].to_vec());
|
||||
res.push(Trace::from(current_trace[0..depth].to_vec()));
|
||||
new_branch = false;
|
||||
n -= 1;
|
||||
}
|
||||
if n == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
if depth == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
depth -= 1;
|
||||
branch[depth] += 1;
|
||||
}
|
||||
@ -412,6 +413,9 @@ pub struct System {
|
||||
pub available_entities: Set,
|
||||
pub context_process: Process,
|
||||
pub reaction_rules: Rc<Vec<Reaction>>,
|
||||
|
||||
context_elements: Rc<Set>,
|
||||
products_elements: Rc<Set>,
|
||||
}
|
||||
|
||||
impl BasicSystem for System {
|
||||
@ -425,7 +429,7 @@ impl BasicSystem for System {
|
||||
fn to_transitions_iterator(
|
||||
&self,
|
||||
) -> 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 {
|
||||
@ -443,6 +447,14 @@ impl BasicSystem for System {
|
||||
fn reactions(&self) -> &Vec<Self::Reaction> {
|
||||
&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
|
||||
@ -476,6 +488,9 @@ impl Default for System {
|
||||
available_entities: Set::default(),
|
||||
context_process: Process::Nill,
|
||||
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,
|
||||
reaction_rules: Rc<Vec<Reaction>>,
|
||||
) -> 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 {
|
||||
delta: Rc::clone(&delta),
|
||||
available_entities,
|
||||
context_process,
|
||||
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 context_process: PositiveProcess,
|
||||
pub reaction_rules: Rc<Vec<PositiveReaction>>,
|
||||
|
||||
context_elements: Rc<PositiveSet>,
|
||||
products_elements: Rc<PositiveSet>,
|
||||
}
|
||||
|
||||
impl BasicSystem for PositiveSystem {
|
||||
@ -682,7 +711,7 @@ impl BasicSystem for PositiveSystem {
|
||||
fn to_transitions_iterator(
|
||||
&self,
|
||||
) -> 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 {
|
||||
@ -700,6 +729,14 @@ impl BasicSystem for PositiveSystem {
|
||||
fn reactions(&self) -> &Vec<Self::Reaction> {
|
||||
&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
|
||||
@ -733,6 +770,9 @@ impl Default for PositiveSystem {
|
||||
available_entities: PositiveSet::default(),
|
||||
context_process: PositiveProcess::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)
|
||||
};
|
||||
|
||||
Self {
|
||||
delta: new_env,
|
||||
available_entities: new_available_entities,
|
||||
context_process: new_context,
|
||||
reaction_rules: new_reactions,
|
||||
}
|
||||
Self::from(new_env, new_available_entities, new_context, new_reactions)
|
||||
}
|
||||
}
|
||||
|
||||
@ -856,11 +891,24 @@ impl PositiveSystem {
|
||||
context_process: PositiveProcess,
|
||||
reaction_rules: Rc<Vec<PositiveReaction>>,
|
||||
) -> 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 {
|
||||
delta: Rc::clone(&delta),
|
||||
available_entities,
|
||||
context_process,
|
||||
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::system::{ExtensionsSystem, System};
|
||||
|
||||
let system = System {
|
||||
delta: Rc::new(Environment::from([
|
||||
let system = System::from(
|
||||
Rc::new(Environment::from([
|
||||
(100, Process::WaitEntity {
|
||||
repeat: 2,
|
||||
repeated_process: Rc::new(Process::EntitySet {
|
||||
@ -205,14 +205,14 @@ fn traces_1() {
|
||||
],
|
||||
}),
|
||||
])),
|
||||
available_entities: Set::from([1, 2]),
|
||||
context_process: Process::RecursiveIdentifier { identifier: 101 },
|
||||
reaction_rules: Rc::new(vec![
|
||||
Set::from([1, 2]),
|
||||
Process::RecursiveIdentifier { identifier: 101 },
|
||||
Rc::new(vec![
|
||||
Reaction::from(Set::from([1]), Set::from([3]), Set::from([3])),
|
||||
Reaction::from(Set::from([3]), Set::from([1]), Set::from([1])),
|
||||
Reaction::from(Set::from([2]), Set::default(), Set::from([4])),
|
||||
]),
|
||||
};
|
||||
);
|
||||
|
||||
let res = system.clone().traces(1).unwrap();
|
||||
assert_eq!(res.len(), 1);
|
||||
@ -244,10 +244,10 @@ fn traces_empty_env() {
|
||||
use super::set::Set;
|
||||
use super::system::{ExtensionsSystem, System};
|
||||
|
||||
let system = System {
|
||||
delta: Rc::new(Environment::from([])),
|
||||
available_entities: Set::from([1, 2]),
|
||||
context_process: Process::WaitEntity {
|
||||
let system = System::from(
|
||||
Rc::new(Environment::from([])),
|
||||
Set::from([1, 2]),
|
||||
Process::WaitEntity {
|
||||
repeat: 10,
|
||||
repeated_process: Rc::new(Process::EntitySet {
|
||||
entities: Set::from([1, 2]),
|
||||
@ -255,12 +255,12 @@ fn traces_empty_env() {
|
||||
}),
|
||||
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([3]), Set::from([1]), Set::from([1])),
|
||||
Reaction::from(Set::from([2]), Set::default(), Set::from([4])),
|
||||
]),
|
||||
};
|
||||
);
|
||||
|
||||
let res = system.clone().traces(10).unwrap();
|
||||
assert_eq!(res.len(), 1);
|
||||
@ -278,15 +278,15 @@ fn conversion_reactions() {
|
||||
use super::set::Set;
|
||||
use super::system::{PositiveSystem, System};
|
||||
|
||||
let system = System {
|
||||
delta: Rc::new(Environment::from([])),
|
||||
available_entities: Set::from([1, 2]),
|
||||
context_process: Process::Nill,
|
||||
reaction_rules: Rc::new(vec![
|
||||
let system = System::from(
|
||||
Rc::new(Environment::from([])),
|
||||
Set::from([1, 2]),
|
||||
Process::Nill,
|
||||
Rc::new(vec![
|
||||
Reaction::from(Set::from([2]), Set::from([1, 3]), Set::from([5])),
|
||||
Reaction::from(Set::from([1, 2]), Set::from([3]), Set::from([5])),
|
||||
]),
|
||||
};
|
||||
);
|
||||
let converted_system: PositiveSystem = system.into();
|
||||
let mut reactions = converted_system.reactions().clone();
|
||||
reactions.sort_by(|a, b| {
|
||||
@ -322,15 +322,15 @@ fn conversion_entities() {
|
||||
use super::set::Set;
|
||||
use super::system::{PositiveSystem, System};
|
||||
|
||||
let system = System {
|
||||
delta: Rc::new(Environment::from([])),
|
||||
available_entities: Set::from([1, 2]),
|
||||
context_process: Process::Nill,
|
||||
reaction_rules: Rc::new(vec![
|
||||
let system = System::from(
|
||||
Rc::new(Environment::from([])),
|
||||
Set::from([1, 2]),
|
||||
Process::Nill,
|
||||
Rc::new(vec![
|
||||
Reaction::from(Set::from([2]), Set::from([1, 3]), Set::from([5])),
|
||||
Reaction::from(Set::from([1, 2]), Set::from([3]), Set::from([5])),
|
||||
]),
|
||||
};
|
||||
);
|
||||
let converted_system: PositiveSystem = system.into();
|
||||
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
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::label::{Label, PositiveLabel};
|
||||
@ -8,6 +9,12 @@ use super::reaction::BasicReaction;
|
||||
use super::set::{BasicSet, PositiveSet, Set};
|
||||
use super::system::{BasicSystem, ExtensionsSystem, PositiveSystem, System};
|
||||
|
||||
pub trait BasicTransition
|
||||
where
|
||||
Self: Clone + Debug + Iterator,
|
||||
{
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TransitionsIterator<
|
||||
'a,
|
||||
@ -19,12 +26,16 @@ pub struct TransitionsIterator<
|
||||
system: &'a Sys,
|
||||
}
|
||||
|
||||
impl<'a> TransitionsIterator<'a, Set, System, Process> {
|
||||
pub fn from(system: &'a System) -> Result<Self, String> {
|
||||
match system.unfold() {
|
||||
| Ok(o) => Ok(TransitionsIterator {
|
||||
impl<'a> BasicTransition for TransitionsIterator<'a, Set, System, Process> {}
|
||||
|
||||
impl<'a> TryFrom<&'a System> for TransitionsIterator<'a, Set, System, Process> {
|
||||
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(),
|
||||
system,
|
||||
system: value,
|
||||
}),
|
||||
| Err(e) => Err(e),
|
||||
}
|
||||
@ -35,7 +46,7 @@ impl<'a> Iterator for TransitionsIterator<'a, Set, System, Process> {
|
||||
type Item = (Label, 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 t = self.system.available_entities.union(c.as_ref());
|
||||
let (
|
||||
@ -44,7 +55,7 @@ impl<'a> Iterator for TransitionsIterator<'a, Set, System, Process> {
|
||||
inhibitors,
|
||||
inhibitors_present,
|
||||
products,
|
||||
) = self.system.reaction_rules.iter().fold(
|
||||
) = self.system.reactions().iter().fold(
|
||||
(
|
||||
Set::default(), // reactants
|
||||
Set::default(), // reactants_absent
|
||||
@ -95,12 +106,21 @@ impl<'a> Iterator for TransitionsIterator<'a, Set, System, Process> {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
impl<'a> TransitionsIterator<'a, PositiveSet, PositiveSystem, PositiveProcess> {
|
||||
pub fn from(system: &'a PositiveSystem) -> Result<Self, String> {
|
||||
match system.unfold() {
|
||||
| Ok(o) => Ok(TransitionsIterator {
|
||||
impl<'a> BasicTransition
|
||||
for TransitionsIterator<'a, PositiveSet, PositiveSystem, PositiveProcess>
|
||||
{
|
||||
}
|
||||
|
||||
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(),
|
||||
system,
|
||||
system: value,
|
||||
}),
|
||||
| Err(e) => Err(e),
|
||||
}
|
||||
@ -174,3 +194,71 @@ impl<'a> Iterator
|
||||
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