Introducing traits for sets and reactions

This commit is contained in:
elvis
2025-08-26 16:56:08 +02:00
parent a46ab3833d
commit bf2403cdcf
14 changed files with 376 additions and 311 deletions

View File

@ -1,6 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use super::super::{translator, graph, set, process, system, label}; use super::super::{translator, graph, set, process, system, label};
use super::super::set::BasicSet;
/// If changing IntegerType in assert.rs, also change from Num to another /// If changing IntegerType in assert.rs, also change from Num to another
/// similar parser with different return type in grammar.lalrpop in /// similar parser with different return type in grammar.lalrpop in

View File

@ -890,12 +890,12 @@ fn for_1() {
Box::new(Tree::Assignment( Box::new(Tree::Assignment(
Variable::Id("a".into()), Variable::Id("a".into()),
None, None,
Box::new(Expression::Set(Set::new())) Box::new(Expression::Set(Set::default()))
)), )),
Box::new(Tree::Assignment( Box::new(Tree::Assignment(
Variable::Id("b".into()), Variable::Id("b".into()),
None, None,
Box::new(Expression::Set(Set::new())) Box::new(Expression::Set(Set::default()))
)), )),
)), )),
Box::new(Tree::For( Box::new(Tree::For(
@ -945,7 +945,7 @@ fn for_2() {
Box::new(Tree::Assignment( Box::new(Tree::Assignment(
Variable::Id("b".into()), Variable::Id("b".into()),
None, None,
Box::new(Expression::Set(Set::new())) Box::new(Expression::Set(Set::default()))
)), )),
)), )),
Box::new(Tree::For( Box::new(Tree::For(
@ -996,19 +996,19 @@ fn for_3() {
None, None,
Box::new(Expression::Label( Box::new(Expression::Label(
Box::new(Label::from(Set::from([1, 2]), Box::new(Label::from(Set::from([1, 2]),
Set::new(), Set::default(),
Set::from([1, 2]), Set::from([1, 2]),
Set::new(), Set::default(),
Set::new(), Set::default(),
Set::new(), Set::default(),
Set::new(), Set::default(),
Set::new())) Set::default()))
)) ))
)), )),
Box::new(Tree::Assignment( Box::new(Tree::Assignment(
Variable::Id("b".into()), Variable::Id("b".into()),
None, None,
Box::new(Expression::Set(Set::new())) Box::new(Expression::Set(Set::default()))
)), )),
)), )),
Box::new(Tree::For( Box::new(Tree::For(
@ -1066,17 +1066,17 @@ fn for_4() {
Box::new(Label::from(Set::from([1, 2]), Box::new(Label::from(Set::from([1, 2]),
Set::from([3]), Set::from([3]),
Set::from([1, 2, 3]), Set::from([1, 2, 3]),
Set::new(), Set::default(),
Set::new(), Set::default(),
Set::new(), Set::default(),
Set::new(), Set::default(),
Set::new())) Set::default()))
)) ))
)), )),
Box::new(Tree::Assignment( Box::new(Tree::Assignment(
Variable::Id("b".into()), Variable::Id("b".into()),
None, None,
Box::new(Expression::Set(Set::new())) Box::new(Expression::Set(Set::default()))
)), )),
)), )),
Box::new(Tree::For( Box::new(Tree::For(
@ -1133,13 +1133,13 @@ fn for_5() {
None, None,
Box::new(Expression::Label( Box::new(Expression::Label(
Box::new(Label::from(Set::from([1, 2]), Box::new(Label::from(Set::from([1, 2]),
Set::from([3]), Set::from([3]),
Set::from([1, 2, 3]), Set::from([1, 2, 3]),
Set::new(), Set::default(),
Set::new(), Set::default(),
Set::new(), Set::default(),
Set::new(), Set::default(),
Set::new())) Set::default()))
)) ))
)), )),
Box::new(Tree::Assignment( Box::new(Tree::Assignment(
@ -1217,11 +1217,11 @@ fn for_6() {
Box::new(Label::from(Set::from([1, 2]), Box::new(Label::from(Set::from([1, 2]),
Set::from([3]), Set::from([3]),
Set::from([1, 2, 3]), Set::from([1, 2, 3]),
Set::new(), Set::default(),
Set::new(), Set::default(),
Set::new(), Set::default(),
Set::new(), Set::default(),
Set::new())) Set::default()))
)) ))
)), )),
Box::new(Tree::Concat( Box::new(Tree::Concat(

View File

@ -1,7 +1,7 @@
use std::rc::Rc; use std::rc::Rc;
use super::process::Process; use super::process::Process;
use super::set::Set; use super::set::{BasicSet, Set};
use super::translator::{Translator, PrintableWithTranslator, Formatter}; use super::translator::{Translator, PrintableWithTranslator, Formatter};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -18,7 +18,7 @@ impl Choices {
pub fn new_not_empty() -> Self { pub fn new_not_empty() -> Self {
Choices { Choices {
context_moves: vec![(Rc::new(Set::new()), context_moves: vec![(Rc::new(Set::default()),
Rc::new(Process::Nill))], Rc::new(Process::Nill))],
} }
} }

View File

@ -5,8 +5,8 @@ use std::rc::Rc;
use super::choices::Choices; use super::choices::Choices;
use super::process::Process; use super::process::Process;
use super::reaction::Reaction; use super::reaction::{Reaction, BasicReaction, ExtensionReaction};
use super::set::Set; use super::set::{BasicSet, Set};
use super::translator::{IdType, Translator, PrintableWithTranslator, Formatter}; use super::translator::{IdType, Translator, PrintableWithTranslator, Formatter};
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
@ -30,7 +30,7 @@ impl Environment {
} }
pub fn all_elements(&self) -> Set { pub fn all_elements(&self) -> Set {
let mut acc = Set::new(); let mut acc = Set::default();
for (_, process) in self.definitions.iter() { for (_, process) in self.definitions.iter() {
acc.push(&process.all_elements()); acc.push(&process.all_elements());
} }
@ -110,7 +110,7 @@ impl Environment {
// short-circuits with try_fold. // short-circuits with try_fold.
if children.is_empty() { if children.is_empty() {
Ok(Choices::from(vec![( Ok(Choices::from(vec![(
Rc::new(Set::new()), Rc::new(Set::default()),
Rc::new(Process::Nill), Rc::new(Process::Nill),
)])) )]))
} else { } else {

View File

@ -1,5 +1,5 @@
pub mod graph_map_nodes_ty_from { pub mod graph_map_nodes_ty_from {
use super::super::set::Set; use super::super::set::{BasicSet, Set};
use super::super::system::System; use super::super::system::System;
use super::super::translator; use super::super::translator;
use std::rc::Rc; use std::rc::Rc;
@ -74,7 +74,7 @@ pub mod graph_map_nodes_ty_from {
pub mod graph_map_edges_ty_from { pub mod graph_map_edges_ty_from {
use super::super::set::Set; use super::super::set::{BasicSet, Set};
use super::super::label::Label; use super::super::label::Label;
use super::super::translator; use super::super::translator;
use std::rc::Rc; use std::rc::Rc;

View File

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

View File

@ -5,7 +5,7 @@ use petgraph::{Graph, Directed};
use std::rc::Rc; use std::rc::Rc;
use super::label::Label; use super::label::Label;
use super::set::Set; use super::set::{BasicSet, Set};
use super::system::System; use super::system::System;
use super::translator::{self, IdType}; use super::translator::{self, IdType};
@ -19,7 +19,7 @@ fn common_system_entities(graph: &SystemGraph) -> Set {
None => Some(node.1.available_entities.clone()), None => Some(node.1.available_entities.clone()),
Some(acc) => Some(node.1.available_entities.intersection(&acc)) Some(acc) => Some(node.1.available_entities.intersection(&acc))
} }
).unwrap_or(Set::new()) ).unwrap_or(Set::default())
} }
macro_rules! common_label { macro_rules! common_label {
@ -39,7 +39,7 @@ macro_rules! common_label {
Some($acc_name) => Some($some_expr) Some($acc_name) => Some($some_expr)
} }
} }
).unwrap_or(Set::new()) ).unwrap_or(Set::default())
} }
}; };
} }
@ -218,7 +218,7 @@ impl NodeDisplay {
if self.contains_uncommon() { if self.contains_uncommon() {
Rc::new(common_system_entities(current_graph)) Rc::new(common_system_entities(current_graph))
} else { } else {
Rc::new(Set::new()) Rc::new(Set::default())
}; };
Box::new( Box::new(

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::hash::Hash; use std::hash::Hash;
use super::set::Set; use super::set::{BasicSet, Set};
use super::translator::{Translator, PrintableWithTranslator, Formatter}; use super::translator::{Translator, PrintableWithTranslator, Formatter};
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialOrd)] #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialOrd)]
@ -19,14 +19,14 @@ pub struct Label {
impl Label { impl Label {
pub fn new() -> Self { pub fn new() -> Self {
Label { Label {
available_entities: Set::new(), available_entities: Set::default(),
context: Set::new(), context: Set::default(),
t: Set::new(), t: Set::default(),
reactants: Set::new(), reactants: Set::default(),
reactants_absent: Set::new(), reactants_absent: Set::default(),
inhibitors: Set::new(), inhibitors: Set::default(),
inhibitors_present: Set::new(), inhibitors_present: Set::default(),
products: Set::new(), products: Set::default(),
} }
} }

View File

@ -4,7 +4,7 @@ use std::hash::Hash;
use std::rc::Rc; use std::rc::Rc;
use super::reaction::Reaction; use super::reaction::Reaction;
use super::set::Set; use super::set::{Set, BasicSet};
use super::translator::{IdType, Translator, PrintableWithTranslator, Formatter}; use super::translator::{IdType, Translator, PrintableWithTranslator, Formatter};
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
@ -61,7 +61,7 @@ impl Process {
/// returns all elements used /// returns all elements used
pub fn all_elements(&self) -> Set { pub fn all_elements(&self) -> Set {
let mut queue = VecDeque::from([self]); let mut queue = VecDeque::from([self]);
let mut elements = Set::new(); let mut elements = Set::default();
while let Some(el) = queue.pop_front() { while let Some(el) = queue.pop_front() {
match el { match el {

View File

@ -6,161 +6,190 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::hash::Hash; use std::hash::Hash;
use super::set::Set; use super::set::{BasicSet, ExtensionsSet, Set};
use super::translator::{Translator, PrintableWithTranslator, Formatter}; use super::translator::{Translator, PrintableWithTranslator, Formatter};
pub trait BasicReaction<S: BasicSet>:
Clone + Default + Eq + Hash + Serialize + PrintableWithTranslator
where for<'de> Self: Deserialize<'de>,
{
fn enabled(&self, state: &S) -> bool;
fn compute_step(&self, state: &S) -> Option<&S>;
}
pub trait ExtensionReaction<S: BasicSet> {
fn compute_all(reactions: &[Self], state: &S) -> S
where Self: Sized;
fn find_loop(reactions: &[Self], entities: S, q: &S) -> (Vec<S>, Vec<S>)
where Self: Sized;
fn find_only_loop(reactions: &[Self], entities: S, q: &S) -> Vec<S>
where Self: Sized;
fn find_prefix_len_loop(
reactions: &[Self],
entities: S,
q: &S
) -> (usize, Vec<S>)
where Self: Sized;
fn lollipops_only_loop_decomposed_q(
reactions: &[Self],
entities: &S,
q: &S
) -> Vec<S>
where Self: Sized;
}
impl<T: BasicReaction<S>, S: BasicSet> ExtensionReaction<S> for T {
/// Computes the result of a series of reactions. Returns the union of all
/// products.
/// see result
fn compute_all(
reactions: &[Self],
state: &S
) -> S
where Self: Sized {
reactions.iter().fold(S::default(), |mut acc: S, r| {
acc.extend(r.compute_step(state));
acc
})
}
/// Finds the loops by simulating the system.
fn find_loop(
reactions: &[Self],
entities: S,
q: &S
) -> (Vec<S>, Vec<S>) {
let mut entities = entities;
let mut trace = vec![];
loop {
if let Some((prefix, hoop)) = entities.split(&trace) {
return (prefix.to_vec(), hoop.to_vec());
} else {
let t = entities.union(q);
let products = Self::compute_all(reactions, &t);
trace.push(entities.clone());
entities = products;
}
}
}
/// Finds the loops by simulating the system.
fn find_only_loop(
reactions: &[Self],
entities: S,
q: &S
) -> Vec<S> {
let mut entities = entities;
let mut trace = vec![];
loop {
if let Some((_prefix, hoop)) = entities.split(&trace) {
return hoop.to_vec();
} else {
let t = entities.union(q);
let products = Self::compute_all(reactions, &t);
trace.push(entities.clone());
entities = products;
}
}
}
/// Finds the loops and the length of the prefix by simulating the system.
fn find_prefix_len_loop(
reactions: &[Self],
entities: S,
q: &S
) -> (usize, Vec<S>) {
let mut entities = entities;
let mut trace = vec![];
loop {
if let Some((prefix, hoop)) = entities.split(&trace) {
return (prefix.len(), hoop.to_vec());
} else {
let t = entities.union(q);
let products = Self::compute_all(reactions, &t);
trace.push(entities.clone());
entities = products;
}
}
}
/// see loop/5
fn lollipops_only_loop_decomposed_q(
reactions: &[Self],
entities: &S,
q: &S,
) -> Vec<S> {
let find_loop_fn =
|q| Self::find_only_loop(reactions,
entities.clone(),
q);
find_loop_fn(q)
}
}
// -----------------------------------------------------------------------------
/// Basic structure for a reaction. /// Basic structure for a reaction.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] #[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct Reaction { pub struct Reaction {
pub reactants: Set, pub reactants: Set,
pub inhibitors: Set, pub inhibitors: Set,
pub products: Set, pub products: Set,
}
impl BasicReaction<Set> for Reaction {
/// returns true if ```current_state``` enables the reaction
/// see enable
fn enabled(&self, current_state: &Set) -> bool {
self.reactants.is_subset(current_state)
&& self.inhibitors.is_disjoint(current_state)
}
/// Computes the result of a single reaction (if enabled returns the
/// products) otherwise returns None.
/// see result
fn compute_step(
&self,
state: &Set,
) -> Option<&Set> {
if self.enabled(state) {
Some(&self.products)
} else {
None
}
}
} }
impl Reaction { impl Reaction {
pub fn new() -> Self { pub fn from(reactants: Set, inhibitors: Set, products: Set) -> Self {
Reaction { Reaction {
reactants: Set::new(), reactants,
inhibitors: Set::new(), inhibitors,
products: Set::new(), products,
}
} }
}
pub fn from(reactants: Set, inhibitors: Set, products: Set) -> Self {
Reaction {
reactants,
inhibitors,
products,
}
}
/// returns true if ```current_state``` enables the reaction
/// see enable
pub fn enabled(&self, current_state: &Set) -> bool {
self.reactants.is_subset(current_state)
&& self.inhibitors.is_disjoint(current_state)
}
/// Computes the result of a single reaction (if enabled returns the products)
/// otherwise returns None.
/// see result
pub fn compute_step<'a>(
&'a self,
current_state: &'a Set,
) -> Option<&'a Set> {
if self.enabled(current_state) {
Some(&self.products)
} else {
None
}
}
/// Computes the result of a series of reactions. Returns the union of all
/// products.
/// see result
pub fn compute_all<'a>(
current_state: &'a Set,
reactions: &'a [Self]
) -> Set {
reactions.iter().fold(Set::new(), |mut acc, r| {
acc.union_option(r.compute_step(current_state));
acc
})
}
/// Finds the loops by simulating the system.
pub fn find_loop(
rs: &[Self],
entities: Set,
q: &Set
) -> (Vec<Set>, Vec<Set>) {
let mut entities = entities;
let mut trace = vec![];
loop {
if let Some((prefix, hoop)) = entities.split(&trace) {
return (prefix.to_vec(), hoop.to_vec());
} else {
let t = entities.union(q);
let products = Self::compute_all(&t, rs);
trace.push(entities.clone());
entities = products;
}
}
}
/// Finds the loops by simulating the system.
pub fn find_only_loop(
rs: &[Self],
entities: Set,
q: &Set
) -> Vec<Set> {
let mut entities = entities;
let mut trace = vec![];
loop {
if let Some((_prefix, hoop)) = entities.split(&trace) {
return hoop.to_vec();
} else {
let t = entities.union(q);
let products = Self::compute_all(&t, rs);
trace.push(entities.clone());
entities = products;
}
}
}
/// Finds the loops and the length of the prefix by simulating the system.
pub fn find_prefix_len_loop(
rs: &[Self],
entities: Set,
q: &Set
) -> (usize, Vec<Set>) {
let mut entities = entities;
let mut trace = vec![];
loop {
if let Some((prefix, hoop)) = entities.split(&trace) {
return (prefix.len(), hoop.to_vec());
} else {
let t = entities.union(q);
let products = Self::compute_all(&t, rs);
trace.push(entities.clone());
entities = products;
}
}
}
/// see loop/5
pub fn lollipops_only_loop_decomposed_q(
reaction_rules: &[Self],
q: &Set,
available_entities: &Set,
) -> Vec<Set> {
let find_loop_fn =
|q| Reaction::find_only_loop(reaction_rules,
available_entities.clone(),
q);
find_loop_fn(q)
}
}
impl Default for Reaction {
fn default() -> Self {
Reaction::new()
}
} }
impl PrintableWithTranslator for Reaction { impl PrintableWithTranslator for Reaction {
fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator) fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator)
-> std::fmt::Result { -> std::fmt::Result {
write!( write!(
f, f,
"(r: {}, i: {}, p: {})", "(r: {}, i: {}, p: {})",
Formatter::from(translator, &self.reactants), Formatter::from(translator, &self.reactants),
Formatter::from(translator, &self.inhibitors), Formatter::from(translator, &self.inhibitors),
Formatter::from(translator, &self.products) Formatter::from(translator, &self.products)
) )
} }
} }

View File

@ -5,108 +5,48 @@ use std::fmt;
use super::translator::{IdType, Translator, PrintableWithTranslator}; use super::translator::{IdType, Translator, PrintableWithTranslator};
/// Basic set of entities.
#[derive(Clone, Debug, PartialOrd, Eq, Ord, Serialize, Deserialize)] /// Basic trait for all Set implementations.
pub struct Set { /// Implement IntoIterator for &Self to have .iter() (not required directly by
pub identifiers: BTreeSet<IdType>, /// the trait).
pub trait BasicSet
where Self: Clone + Eq + Ord + Default + Serialize + IntoIterator
+ PrintableWithTranslator,
for<'de> Self: Deserialize<'de>
{
fn is_subset(&self, other: &Self) -> bool;
fn is_disjoint(&self, other: &Self) -> bool;
fn union(&self, other: &Self) -> Self;
fn push(&mut self, other: &Self);
fn extend(&mut self, other: Option<&Self>);
fn intersection(&self, other: &Self) -> Self;
fn subtraction(&self, other: &Self) -> Self;
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
} }
impl<const N: usize> From<[IdType; N]> for Set { pub trait ExtensionsSet {
fn from(arr: [IdType; N]) -> Self { fn iter(
Set { &self
identifiers: BTreeSet::from(arr), ) -> <&Self as IntoIterator>::IntoIter
} where for<'b> &'b Self: IntoIterator;
}
fn split<'a>(
&'a self,
trace: &'a [Self]
) -> Option<(&'a [Self], &'a [Self])>
where Self: Sized;
} }
impl From<&[IdType]> for Set { /// Implementations for all sets.
fn from(arr: &[IdType]) -> Self { impl<T: BasicSet> ExtensionsSet for T {
Set { fn iter(&self) -> <&T as IntoIterator>::IntoIter
identifiers: BTreeSet::from_iter(arr.to_vec()), where for<'b> &'b T: IntoIterator {
} self.into_iter()
}
}
impl From<Vec<IdType>> for Set {
fn from(arr: Vec<IdType>) -> Self {
Set {
identifiers: BTreeSet::from_iter(arr),
}
}
}
impl Set {
pub const fn new() -> Self {
Set {
identifiers: BTreeSet::new(),
}
}
pub fn is_subset(&self, b: &Set) -> bool {
self.identifiers.is_subset(&b.identifiers)
}
pub fn is_disjoint(&self, b: &Set) -> bool {
self.identifiers.is_disjoint(&b.identifiers)
}
// returns the new set a \cup b
pub fn union(&self, b: &Set) -> Set {
let mut ret: Set = b.clone();
ret.identifiers.extend(self.identifiers.iter());
ret
}
pub fn union_option(&mut self, b: Option<&Set>) {
if let Some(b) = b {
self.identifiers.extend(b.iter());
}
}
/// returns the new set a \cap b
pub fn intersection(&self, b: &Set) -> Set {
// TODO maybe find more efficient way without copy/clone
let res: BTreeSet<_> = b
.identifiers
.intersection(&self.identifiers)
.copied()
.collect();
Set { identifiers: res }
}
/// returns the new set a b
pub fn subtraction(&self, b: &Set) -> Set {
// TODO maybe find more efficient way without copy/clone
let res: BTreeSet<_> = self
.identifiers
.difference(&b.identifiers)
.copied()
.collect();
Set { identifiers: res }
}
pub fn iter(&self) -> std::collections::btree_set::Iter<'_, IdType> {
self.identifiers.iter()
}
pub fn len(&self) -> usize {
self.identifiers.len()
}
pub fn insert(&mut self, el: IdType) -> bool {
self.identifiers.insert(el)
}
pub fn push(&mut self, b: &Set) {
self.identifiers.extend(b.iter())
}
pub fn is_empty(&self) -> bool {
self.identifiers.is_empty()
} }
/// Returns the prefix and the loop from a trace. /// Returns the prefix and the loop from a trace.
pub fn split<'a>( fn split<'a>(
&'a self, &'a self,
trace: &'a [Self] trace: &'a [Self]
) -> Option<(&'a [Self], &'a [Self])> { ) -> Option<(&'a [Self], &'a [Self])> {
@ -115,9 +55,69 @@ impl Set {
} }
} }
impl Default for Set {
fn default() -> Self { // -----------------------------------------------------------------------------
Set::new()
/// Basic set of entities.
#[derive(Clone, Debug, Default, PartialOrd, Eq, Ord, Serialize, Deserialize)]
pub struct Set {
pub identifiers: BTreeSet<IdType>,
}
impl BasicSet for Set {
fn is_subset(&self, other: &Self) -> bool {
self.identifiers.is_subset(&other.identifiers)
}
fn is_disjoint(&self, other: &Self) -> bool {
self.identifiers.is_disjoint(&other.identifiers)
}
// returns the new set a \cup b
fn union(&self, other: &Self) -> Self {
let mut ret: Set = other.clone();
ret.identifiers.extend(self.identifiers.iter());
ret
}
fn push(&mut self, b: &Self) {
self.identifiers.extend(b.iter())
}
fn extend(&mut self, other: Option<&Self>) {
if let Some(other) = other {
self.identifiers.extend(other);
}
}
/// returns the new set a \cap b
fn intersection(&self, other: &Self) -> Self {
// TODO maybe find more efficient way without copy/clone
let res: BTreeSet<_> = other
.identifiers
.intersection(&self.identifiers)
.copied()
.collect();
Set { identifiers: res }
}
/// returns the new set a b
fn subtraction(&self, other: &Self) -> Self {
// TODO maybe find more efficient way without copy/clone
let res: BTreeSet<_> = self
.identifiers
.difference(&other.identifiers)
.copied()
.collect();
Set { identifiers: res }
}
fn len(&self) -> usize {
self.identifiers.len()
}
fn is_empty(&self) -> bool {
self.identifiers.is_empty()
} }
} }
@ -142,6 +142,15 @@ impl IntoIterator for Set {
} }
} }
impl<'a> IntoIterator for &'a Set {
type Item = &'a IdType;
type IntoIter = std::collections::btree_set::Iter<'a, IdType>;
fn into_iter(self) -> Self::IntoIter {
self.identifiers.iter()
}
}
impl PrintableWithTranslator for Set { impl PrintableWithTranslator for Set {
fn print( fn print(
&self, &self,
@ -164,3 +173,28 @@ impl PrintableWithTranslator for Set {
write!(f, "}}") write!(f, "}}")
} }
} }
impl<const N: usize> From<[IdType; N]> for Set {
fn from(arr: [IdType; N]) -> Self {
Set {
identifiers: BTreeSet::from(arr),
}
}
}
impl From<&[IdType]> for Set {
fn from(arr: &[IdType]) -> Self {
Set {
identifiers: BTreeSet::from_iter(arr.to_vec()),
}
}
}
impl From<Vec<IdType>> for Set {
fn from(arr: Vec<IdType>) -> Self {
Set {
identifiers: BTreeSet::from_iter(arr),
}
}
}

View File

@ -7,8 +7,8 @@ use super::environment::Environment;
use super::graph::SystemGraph; use super::graph::SystemGraph;
use super::label::Label; use super::label::Label;
use super::process::Process; use super::process::Process;
use super::reaction::Reaction; use super::reaction::{Reaction, ExtensionReaction};
use super::set::Set; use super::set::{BasicSet, Set};
use super::transitions::TransitionsIterator; use super::transitions::TransitionsIterator;
use super::translator::{IdType, Translator, PrintableWithTranslator, Formatter}; use super::translator::{IdType, Translator, PrintableWithTranslator, Formatter};
@ -27,7 +27,7 @@ impl System {
pub fn new() -> System { pub fn new() -> System {
System { System {
delta: Rc::new(Environment::new()), delta: Rc::new(Environment::new()),
available_entities: Set::new(), available_entities: Set::default(),
context_process: Process::Nill, context_process: Process::Nill,
reaction_rules: Rc::new(vec![]), reaction_rules: Rc::new(vec![]),
} }
@ -405,7 +405,7 @@ impl System {
let reactants = self let reactants = self
.reaction_rules .reaction_rules
.iter() .iter()
.fold(Set::new(), |acc, new| acc.union(&new.reactants)); .fold(Set::default(), |acc, new| acc.union(&new.reactants));
result.push_str(&format!( result.push_str(&format!(
"The reactants are {}:\n{}\n", "The reactants are {}:\n{}\n",
reactants.len(), reactants.len(),
@ -415,7 +415,7 @@ impl System {
let inhibitors = self let inhibitors = self
.reaction_rules .reaction_rules
.iter() .iter()
.fold(Set::new(), |acc, new| acc.union(&new.inhibitors)); .fold(Set::default(), |acc, new| acc.union(&new.inhibitors));
result.push_str(&format!( result.push_str(&format!(
"The inhibitors are {}:\n{}\n", "The inhibitors are {}:\n{}\n",
inhibitors.len(), inhibitors.len(),
@ -425,7 +425,7 @@ impl System {
let products = self let products = self
.reaction_rules .reaction_rules
.iter() .iter()
.fold(Set::new(), |acc, new| acc.union(&new.products)); .fold(Set::default(), |acc, new| acc.union(&new.products));
result.push_str(&format!( result.push_str(&format!(
"The products are {}:\n{}\n", "The products are {}:\n{}\n",
products.len(), products.len(),

View File

@ -53,7 +53,7 @@ fn traces_1() {
inhibitors: Set::from([1]), inhibitors: Set::from([1]),
products: Set::from([1]), }, products: Set::from([1]), },
Reaction { reactants: Set::from([2]), Reaction { reactants: Set::from([2]),
inhibitors: Set::new(), inhibitors: Set::default(),
products: Set::from([4]), }, products: Set::from([4]), },
]) ])
}; };
@ -113,7 +113,7 @@ fn traces_empty_env() {
inhibitors: Set::from([1]), inhibitors: Set::from([1]),
products: Set::from([1]), }, products: Set::from([1]), },
Reaction { reactants: Set::from([2]), Reaction { reactants: Set::from([2]),
inhibitors: Set::new(), inhibitors: Set::default(),
products: Set::from([4]), }, products: Set::from([4]), },
]) ])
}; };

View File

@ -4,8 +4,9 @@ use std::rc::Rc;
use super::label::Label; use super::label::Label;
use super::process::Process; use super::process::Process;
use super::set::Set; use super::set::{BasicSet, Set};
use super::system::System; use super::system::System;
use super::reaction::BasicReaction;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct TransitionsIterator<'a> { pub struct TransitionsIterator<'a> {
@ -44,11 +45,11 @@ impl<'a> Iterator for TransitionsIterator<'a> {
) = ) =
self.system.reaction_rules.iter().fold( self.system.reaction_rules.iter().fold(
( (
Set::new(), // reactants Set::default(), // reactants
Set::new(), // reactants_absent Set::default(), // reactants_absent
Set::new(), // inhibitors Set::default(), // inhibitors
Set::new(), // inhibitors_present Set::default(), // inhibitors_present
Set::new(), // products Set::default(), // products
), ),
|acc, reaction| { |acc, reaction| {
if reaction.enabled(&t) { if reaction.enabled(&t) {