Converting to library and commenting code

refactoring and removing useless functions
This commit is contained in:
elvis
2025-07-09 19:34:15 +02:00
parent 1b9c0ce44b
commit ed49d6fa52
14 changed files with 170 additions and 121 deletions

View File

@ -11,7 +11,7 @@ use std::io;
use std::io::prelude::*; use std::io::prelude::*;
use std::rc::Rc; use std::rc::Rc;
// grammar is defined in main.rs, calling lalrpop_mod! twice, generates twice // grammar is defined in lib.rs, calling lalrpop_mod! twice, generates twice
// the code // the code
use super::grammar; use super::grammar;

7
src/lib.rs Normal file
View File

@ -0,0 +1,7 @@
pub mod rsprocess;
pub mod examples;
lalrpop_util::lalrpop_mod!(
#[allow(clippy::uninlined_format_args)] pub grammar, // name of module
"/rsprocess/grammar.rs" // location of parser
);

View File

@ -1,33 +1,10 @@
mod examples;
mod rsprocess;
lalrpop_util::lalrpop_mod!(
#[allow(clippy::uninlined_format_args)] pub grammar, // name of module
"/rsprocess/grammar.rs" // location of parser
);
fn main() -> std::io::Result<()> { fn main() -> std::io::Result<()> {
// let now = std::time::Instant::now(); // let now = std::time::Instant::now();
// std::thread::sleep(std::time::Duration::new(2, 0));
// println!("{}", now.elapsed().as_micros()); // println!("{}", now.elapsed().as_micros());
// examples::stats()?; reactionsystems::examples::digraph()?;
// examples::freq()?; reactionsystems::examples::adversarial()?;
// examples::hoop()?;
// examples::target()?;
// examples::run()?;
// examples::limit_freq()?;
// examples::fast_freq()?;
examples::digraph()?;
examples::adversarial()?;
Ok(()) Ok(())
} }

View File

@ -4,13 +4,11 @@
//! Reaction System (RS) Framework. //! Reaction System (RS) Framework.
//! The data is held in RSset or RSreaction, in the latter the reagents, //! The data is held in RSset or RSreaction, in the latter the reagents,
//! inhibitors and products are held. //! inhibitors and products are held.
#![allow(dead_code)]
use super::structure::{RSreaction, RSset}; use super::structure::{RSreaction, RSset};
/// Computes the result of a single reaction (if enabled returns the products) /// Computes the result of a single reaction (if enabled returns the products)
/// otherwise returns None. /// otherwise returns None.
// see result /// see result
pub fn compute_step<'a>( pub fn compute_step<'a>(
current_state: &'a RSset, current_state: &'a RSset,
reaction: &'a RSreaction reaction: &'a RSreaction
@ -24,21 +22,13 @@ pub fn compute_step<'a>(
/// Computes the result of a series of reactions. Returns the union of all /// Computes the result of a series of reactions. Returns the union of all
/// products. /// products.
// see result /// see result
pub fn compute_all<'a>( pub fn compute_all<'a>(
current_state: &'a RSset,
reactions: Vec<&'a RSreaction>
) -> RSset {
reactions.iter().fold(RSset::new(), |acc, r| {
acc.union_option(compute_step(current_state, r))
})
}
pub fn compute_all_owned<'a>(
current_state: &'a RSset, current_state: &'a RSset,
reactions: &'a [RSreaction] reactions: &'a [RSreaction]
) -> RSset { ) -> RSset {
reactions.iter().fold(RSset::new(), |acc, r| { reactions.iter().fold(RSset::new(), |mut acc, r| {
acc.union_option(compute_step(current_state, r)) acc.union_option(compute_step(current_state, r));
acc
}) })
} }

View File

@ -1,5 +1,3 @@
#![allow(dead_code)]
use super::perpetual::{ use super::perpetual::{
lollipops_decomposed_named, lollipops_prefix_len_loop_decomposed, lollipops_decomposed_named, lollipops_prefix_len_loop_decomposed,
lollipops_prefix_len_loop_decomposed_named, lollipops_prefix_len_loop_decomposed_named,
@ -9,7 +7,13 @@ use super::translator::IdType;
use std::cmp; use std::cmp;
use std::collections::HashSet; use std::collections::HashSet;
// see confluent, confluents
/// Two set of entities E1 and E2 are confluent w.r.t. the perpetual context
/// delta iff they reach the same loop.
/// confluent checks if all the sets of entities in ```entities``` are confluent
/// and if so returns the maximal length of prefixes traversed to reached the
/// loop, its dimension (length) and the loop.
/// see confluent, confluents
pub fn confluent( pub fn confluent(
delta: &RSenvironment, delta: &RSenvironment,
reaction_rules: &[RSreaction], reaction_rules: &[RSreaction],
@ -27,7 +31,6 @@ pub fn confluent(
lollipops_prefix_len_loop_decomposed(delta, lollipops_prefix_len_loop_decomposed(delta,
reaction_rules, reaction_rules,
available_entities); available_entities);
// FIXME we take just the first? do we compare all?
let (prefix_len, new_hoop) = all_loops.first()?; let (prefix_len, new_hoop) = all_loops.first()?;
if new_hoop.len() != dimension || !hoop.contains(new_hoop.first()?) { if new_hoop.len() != dimension || !hoop.contains(new_hoop.first()?) {
@ -38,7 +41,12 @@ pub fn confluent(
Some((max_distance, dimension, hoop)) Some((max_distance, dimension, hoop))
} }
// see confluent, confluents /// Two set of entities E1 and E2 are confluent w.r.t. the perpetual context Q
/// iff they reach the same loop.
/// The predicate confluent(Rs,Q,Es,Loop,Distance,Dimension) checks if all the
/// sets of entities in Es are confluent and if so returns the Loop, the maximal
/// length of prefixes traversed to reached the loop and its dimension (length).
/// see confluent, confluents
pub fn confluent_named( pub fn confluent_named(
delta: &RSenvironment, delta: &RSenvironment,
reaction_rules: &[RSreaction], reaction_rules: &[RSreaction],
@ -72,7 +80,9 @@ pub fn confluent_named(
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// see invariant /// invariant_named checks if all the sets of entities in ```entities``` are
/// confluent and if so returns the set of all traversed states, together with the loop.
/// see invariant
pub fn invariant_named( pub fn invariant_named(
delta: &RSenvironment, delta: &RSenvironment,
reaction_rules: &[RSreaction], reaction_rules: &[RSreaction],
@ -113,7 +123,18 @@ pub fn invariant_named(
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// see loop_confluent /// Suppose the context has the form
/// Q1. ... Q1.Q2. ... Q2. ... Qn. ... Qn. ...
/// and that each context Q1, Q2, ... , Q(n-1) is provided for a large number
/// of times, enough to stabilize the system in a loop (while Qn is provided
/// infinitely many times). Then it can be the case that when the context
/// switches from Qi to Q(i+1), no matter what is the current state of the loop
/// for Qi at the moment of the switching, the system will stabilize in the same
/// loop for Q(i+1): if this is the case the system is called "loop confluent".
/// loop_confluent_named checks this property over the list of contexts
/// [Q1,Q2,...,Qn] and returns the lists of Loops, Distances and Dimensions for
/// all Qi's.
/// see loop_confluent
pub fn loop_confluent_named( pub fn loop_confluent_named(
deltas: &[RSenvironment], deltas: &[RSenvironment],
reaction_rules: &[RSreaction], reaction_rules: &[RSreaction],
@ -126,7 +147,12 @@ pub fn loop_confluent_named(
.collect::<Option<Vec<_>>>() .collect::<Option<Vec<_>>>()
} }
// see strong_confluent /// "strong confluence" requires loop confluence and additionally check
/// that even if the context is switched BEFORE REACHING THE LOOP for Qi
/// the traversed states are still confluent for Q(i+1)
/// IMPORTANT: this notion of confluence assumes each context can be executed 0
/// or more times
/// see strong_confluent
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
pub fn strong_confluent_named( pub fn strong_confluent_named(
deltas: &[RSenvironment], deltas: &[RSenvironment],
@ -146,3 +172,5 @@ pub fn strong_confluent_named(
}) })
.collect::<Option<Vec<_>>>() .collect::<Option<Vec<_>>>()
} }
// TODO: weak confluence

View File

@ -1,5 +1,3 @@
#![allow(dead_code)]
use crate::rsprocess::perpetual::lollipops_only_loop_decomposed_q; use crate::rsprocess::perpetual::lollipops_only_loop_decomposed_q;
use std::collections::HashMap; use std::collections::HashMap;
@ -8,6 +6,8 @@ use super::structure::{RSreaction, RSset, RSsystem};
use super::transitions::run_separated; use super::transitions::run_separated;
use super::translator::IdType; use super::translator::IdType;
/// structure that holds the frequency of elements of a run or multiple runs,
/// weighted
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Frequency { pub struct Frequency {
pub frequency_map: HashMap<IdType, Vec<u32>>, pub frequency_map: HashMap<IdType, Vec<u32>>,
@ -56,8 +56,9 @@ impl Default for Frequency {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// see naiveFreq, assume the system is finite, calculate the frequency of /// assume the system is finite, calculate the frequency of each symbol in all
// each symbol in all traversed states /// traversed states
/// see naiveFreq
pub fn naive_frequency(system: &RSsystem) -> Result<Frequency, String> { pub fn naive_frequency(system: &RSsystem) -> Result<Frequency, String> {
let ect = run_separated(system)?; let ect = run_separated(system)?;
let es = ect.iter().map(|(e, _, _)| e).collect::<Vec<_>>(); let es = ect.iter().map(|(e, _, _)| e).collect::<Vec<_>>();
@ -70,8 +71,9 @@ pub fn naive_frequency(system: &RSsystem) -> Result<Frequency, String> {
Ok(freq) Ok(freq)
} }
// see loopFreq, assume the system stabilizes in a loop, calculate the frequency /// assume the system stabilizes in a loop, calculate the frequency of each
// of each symbol in all states of the loop /// symbol in all states of the loop
/// see loopFreq
pub fn loop_frequency(system: &RSsystem, symb: IdType) -> Frequency { pub fn loop_frequency(system: &RSsystem, symb: IdType) -> Frequency {
let mut freq = Frequency::new(); let mut freq = Frequency::new();
freq.append_weight(1); freq.append_weight(1);
@ -82,8 +84,9 @@ pub fn loop_frequency(system: &RSsystem, symb: IdType) -> Frequency {
freq freq
} }
// see limitFreq, q[i] is given enough times such that the stabilizes in a loop, /// ```q[i]``` is given enough times such that the stabilizes in a loop, calculate the
// calculate the frequency of the symbols in any state in the last loop /// frequency of the symbols in any state in the last loop
/// see limitFreq
pub fn limit_frequency( pub fn limit_frequency(
q: &[RSset], q: &[RSset],
reaction_rules: &[RSreaction], reaction_rules: &[RSreaction],
@ -109,8 +112,9 @@ pub fn limit_frequency(
Some(freq) Some(freq)
} }
// see fastFreq, q[i] is given enough times such that the stabilizes in a loop, /// ```q[i]``` is given enough times such that the stabilizes in a loop, calculate the
// calculate the frequency of the symbols in any state in any loop, weighted. /// frequency of the symbols in any state in any loop, weighted.
/// see fastFreq
pub fn fast_frequency( pub fn fast_frequency(
q: &[RSset], q: &[RSset],
reaction_rules: &[RSreaction], reaction_rules: &[RSreaction],

View File

@ -1,5 +1,3 @@
#![allow(dead_code)]
use petgraph::{Graph, Directed}; use petgraph::{Graph, Directed};
use std::collections::HashMap; use std::collections::HashMap;
use super::structure::{RSlabel, RSsystem, RSset, RSprocess}; use super::structure::{RSlabel, RSsystem, RSset, RSprocess};
@ -9,6 +7,7 @@ use std::rc::Rc;
type RSgraph = Graph<RSsystem, RSlabel, Directed, u32>; type RSgraph = Graph<RSsystem, RSlabel, Directed, u32>;
/// creates a graph starting from a system as root node
pub fn digraph( pub fn digraph(
system: RSsystem system: RSsystem
) -> Result<RSgraph, String> { ) -> Result<RSgraph, String> {
@ -27,10 +26,7 @@ pub fn digraph(
current = stack.pop().unwrap(); current = stack.pop().unwrap();
let current_node = *association.get(&current).unwrap(); let current_node = *association.get(&current).unwrap();
// cycle through all next nodes for (label, next) in TransitionsIterator::from(&current)? {
let tr = TransitionsIterator::from(&current)?;
for (label, next) in tr {
// if not already visited // if not already visited
let next_node = association.entry(next.clone()).or_insert_with(|| { let next_node = association.entry(next.clone()).or_insert_with(|| {
stack.push(next.clone()); stack.push(next.clone());
@ -49,6 +45,7 @@ pub fn digraph(
// Nodes ----------------------------------------------------------------------- // Nodes -----------------------------------------------------------------------
/// Helper structure that specifies what information to display for nodes.
pub enum GraphMapNodes { pub enum GraphMapNodes {
Hide, Hide,
Entities, Entities,
@ -57,6 +54,8 @@ pub enum GraphMapNodes {
} }
type GraphMapNodesFnTy = dyn Fn(petgraph::prelude::NodeIndex, &RSsystem) -> String; type GraphMapNodesFnTy = dyn Fn(petgraph::prelude::NodeIndex, &RSsystem) -> String;
/// Helper structure that holds a formatting function from node as RSsystem to
/// string
pub struct GraphMapNodesTy { pub struct GraphMapNodesTy {
function: Box<GraphMapNodesFnTy> function: Box<GraphMapNodesFnTy>
} }
@ -131,6 +130,7 @@ impl From<GraphMapNodesTy> for Box<GraphMapNodesFnTy> {
// Edges ----------------------------------------------------------------------- // Edges -----------------------------------------------------------------------
/// Helper structure that specifies what information to display for edges
pub enum GraphMapEdges { pub enum GraphMapEdges {
Hide, Hide,
Products, Products,
@ -150,6 +150,8 @@ pub enum GraphMapEdges {
} }
type GraphMapEdgesFnTy = dyn Fn(petgraph::prelude::EdgeIndex, &RSlabel) -> String; type GraphMapEdgesFnTy = dyn Fn(petgraph::prelude::EdgeIndex, &RSlabel) -> String;
/// Helper structure that holds a formatting function from node as RSsystem to
/// string
pub struct GraphMapEdgesTy { pub struct GraphMapEdgesTy {
function: Box<GraphMapEdgesFnTy> function: Box<GraphMapEdgesFnTy>
} }

View File

@ -1,10 +1,8 @@
#![allow(dead_code)] use super::classical::compute_all;
use super::classical::compute_all_owned;
use super::structure::{RSenvironment, RSprocess, RSreaction, RSset, RSsystem}; use super::structure::{RSenvironment, RSprocess, RSreaction, RSset, RSsystem};
use super::translator::IdType; use super::translator::IdType;
// returns the prefix and the loop from a trace /// returns the prefix and the loop from a trace
fn split<'a>( fn split<'a>(
set: &'a RSset, set: &'a RSset,
trace: &'a [RSset] trace: &'a [RSset]
@ -13,7 +11,7 @@ fn split<'a>(
position.map(|pos| trace.split_at(pos)) position.map(|pos| trace.split_at(pos))
} }
// finds the loops by simulating the system /// finds the loops by simulating the system
fn find_loop( fn find_loop(
rs: &[RSreaction], rs: &[RSreaction],
entities: RSset, entities: RSset,
@ -26,14 +24,14 @@ fn find_loop(
return (prefix.to_vec(), hoop.to_vec()); return (prefix.to_vec(), hoop.to_vec());
} else { } else {
let t = entities.union(q); let t = entities.union(q);
let products = compute_all_owned(&t, rs); let products = compute_all(&t, rs);
trace.push(entities.clone()); trace.push(entities.clone());
entities = products; entities = products;
} }
} }
} }
// finds the loops by simulating the system /// finds the loops by simulating the system
fn find_only_loop( fn find_only_loop(
rs: &[RSreaction], rs: &[RSreaction],
entities: RSset, entities: RSset,
@ -46,14 +44,14 @@ fn find_only_loop(
return hoop.to_vec(); return hoop.to_vec();
} else { } else {
let t = entities.union(q); let t = entities.union(q);
let products = compute_all_owned(&t, rs); let products = compute_all(&t, rs);
trace.push(entities.clone()); trace.push(entities.clone());
entities = products; entities = products;
} }
} }
} }
// finds the loops and the length of the prefix by simulating the system /// finds the loops and the length of the prefix by simulating the system
fn find_prefix_len_loop( fn find_prefix_len_loop(
rs: &[RSreaction], rs: &[RSreaction],
entities: RSset, entities: RSset,
@ -66,7 +64,7 @@ fn find_prefix_len_loop(
return (prefix.len(), hoop.to_vec()); return (prefix.len(), hoop.to_vec());
} else { } else {
let t = entities.union(q); let t = entities.union(q);
let products = compute_all_owned(&t, rs); let products = compute_all(&t, rs);
trace.push(entities.clone()); trace.push(entities.clone());
entities = products; entities = products;
} }
@ -75,8 +73,8 @@ fn find_prefix_len_loop(
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// finds only the rules X = pre(Q, rec(X)), but not only x = pre(Q, rec(x)) /// finds only the rules X = pre(Q, rec(X)), but not only x = pre(Q, rec(x))
// to use in filter_map /// to use in filter_map
fn filter_delta<'a>(x: (&IdType, &'a RSprocess)) -> Option<&'a RSset> { fn filter_delta<'a>(x: (&IdType, &'a RSprocess)) -> Option<&'a RSset> {
use super::structure::RSprocess::*; use super::structure::RSprocess::*;
let (id, rest) = x; let (id, rest) = x;
@ -95,7 +93,14 @@ fn filter_delta<'a>(x: (&IdType, &'a RSprocess)) -> Option<&'a RSset> {
None None
} }
// see lollipop /// A special case of systems is when the context recursively provides always
/// the same set of entities. The corresponding computation is infinite. It
/// consists of a finite sequence of states followed by a looping sequence.
/// IMPORTANT: We return all loops for all X = Q.X, by varing X. The set of
/// reactions Rs and the context x are constant. Each state of the computation
/// is distinguished by the current entities E. Under these assumptions, the
/// predicate lollipop finds the Prefixes and the Loops sequences of entities.
/// see lollipop
pub fn lollipops_decomposed( pub fn lollipops_decomposed(
delta: &RSenvironment, delta: &RSenvironment,
reaction_rules: &[RSreaction], reaction_rules: &[RSreaction],
@ -112,7 +117,14 @@ pub fn lollipops_decomposed(
filtered.map(find_loop_fn).collect::<Vec<_>>() filtered.map(find_loop_fn).collect::<Vec<_>>()
} }
// see lollipop /// A special case of systems is when the context recursively provides always
/// the same set of entities. The corresponding computation is infinite. It
/// consists of a finite sequence of states followed by a looping sequence.
/// IMPORTANT: We return all loops for all X = Q.X, by varing X. The set of
/// reactions Rs and the context x are constant. Each state of the computation
/// is distinguished by the current entities E. Under these assumptions, the
/// predicate lollipop finds the Prefixes and the Loops sequences of entities.
/// see lollipop
pub fn lollipops(system: RSsystem) -> Vec<(Vec<RSset>, Vec<RSset>)> { pub fn lollipops(system: RSsystem) -> Vec<(Vec<RSset>, Vec<RSset>)> {
lollipops_decomposed( lollipops_decomposed(
&system.delta, &system.delta,
@ -121,10 +133,9 @@ pub fn lollipops(system: RSsystem) -> Vec<(Vec<RSset>, Vec<RSset>)> {
) )
} }
// see loop /// Only returns the loop part of the lollipop, returns for all X, where X = Q.X
/// see loop
pub fn lollipops_only_loop(system: RSsystem) -> Vec<Vec<RSset>> { pub fn lollipops_only_loop(system: RSsystem) -> Vec<Vec<RSset>> {
// FIXME: i think we are only interested in "x", not all symbols that
// satisfy X = pre(Q, rec(X))
let filtered = system.delta.iter().filter_map(filter_delta); let filtered = system.delta.iter().filter_map(filter_delta);
let find_loop_fn = |q| { let find_loop_fn = |q| {
@ -143,8 +154,6 @@ pub fn lollipops_prefix_len_loop_decomposed(
reaction_rules: &[RSreaction], reaction_rules: &[RSreaction],
available_entities: &RSset, available_entities: &RSset,
) -> Vec<(usize, Vec<RSset>)> { ) -> Vec<(usize, Vec<RSset>)> {
// FIXME: i think we are only interested in "x", not all symbols that
// satisfy X = pre(Q, rec(X))
let filtered = delta.iter().filter_map(filter_delta); let filtered = delta.iter().filter_map(filter_delta);
let find_loop_fn = |q| find_prefix_len_loop(reaction_rules, let find_loop_fn = |q| find_prefix_len_loop(reaction_rules,
@ -154,14 +163,12 @@ pub fn lollipops_prefix_len_loop_decomposed(
filtered.map(find_loop_fn).collect::<Vec<_>>() filtered.map(find_loop_fn).collect::<Vec<_>>()
} }
// see loop /// see loop
pub fn lollipops_only_loop_decomposed( pub fn lollipops_only_loop_decomposed(
delta: &RSenvironment, delta: &RSenvironment,
reaction_rules: &[RSreaction], reaction_rules: &[RSreaction],
available_entities: &RSset, available_entities: &RSset,
) -> Vec<Vec<RSset>> { ) -> Vec<Vec<RSset>> {
// FIXME: i think we are only interested in "x", not all symbols that
// satisfy X = pre(Q, rec(X))
let filtered = delta.iter().filter_map(filter_delta); let filtered = delta.iter().filter_map(filter_delta);
let find_loop_fn = |q| find_only_loop(reaction_rules, let find_loop_fn = |q| find_only_loop(reaction_rules,
@ -175,8 +182,8 @@ pub fn lollipops_only_loop_decomposed(
// Named versions // Named versions
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// finds only the rules symb = pre(Q, rec(symb)), get symb from a translator /// finds only the rules symb = pre(Q, rec(symb)), get symb from a translator
// to use in filter_map /// to use in filter_map
fn filter_delta_named<'a>( fn filter_delta_named<'a>(
x: (&IdType, &'a RSprocess), x: (&IdType, &'a RSprocess),
symb: &IdType symb: &IdType
@ -201,7 +208,14 @@ fn filter_delta_named<'a>(
None None
} }
// see lollipop /// A special case of systems is when the context recursively provides always
/// the same set of entities. The corresponding computation is infinite. It
/// consists of a finite sequence of states followed by a looping sequence.
/// IMPORTANT: We return all loops for all X = Q.X, by varing X. The set of
/// reactions Rs and the context x are constant. Each state of the computation
/// is distinguished by the current entities E. Under these assumptions, the
/// predicate lollipop finds the Prefixes and the Loops sequences of entities.
/// see lollipop
pub fn lollipops_decomposed_named( pub fn lollipops_decomposed_named(
delta: &RSenvironment, delta: &RSenvironment,
reaction_rules: &[RSreaction], reaction_rules: &[RSreaction],
@ -220,7 +234,14 @@ pub fn lollipops_decomposed_named(
filtered.map(find_loop_fn) filtered.map(find_loop_fn)
} }
// see lollipop /// A special case of systems is when the context recursively provides always
/// the same set of entities. The corresponding computation is infinite. It
/// consists of a finite sequence of states followed by a looping sequence.
/// IMPORTANT: We return all loops for all X = Q.X, by varing X. The set of
/// reactions Rs and the context x are constant. Each state of the computation
/// is distinguished by the current entities E. Under these assumptions, the
/// predicate lollipop finds the Prefixes and the Loops sequences of entities.
/// see lollipop
pub fn lollipops_named( pub fn lollipops_named(
system: RSsystem, system: RSsystem,
symb: IdType symb: IdType
@ -233,7 +254,8 @@ pub fn lollipops_named(
) )
} }
// see loop /// Only returns the loop part of the lollipop, returns for all X, where X = Q.X
/// see loop
pub fn lollipops_only_loop_named( pub fn lollipops_only_loop_named(
system: RSsystem, system: RSsystem,
symb: IdType symb: IdType
@ -273,7 +295,7 @@ pub fn lollipops_prefix_len_loop_decomposed_named(
filtered.map(find_loop_fn) filtered.map(find_loop_fn)
} }
// see loop /// see loop
pub fn lollipops_only_loop_decomposed_named( pub fn lollipops_only_loop_decomposed_named(
delta: &RSenvironment, delta: &RSenvironment,
reaction_rules: &[RSreaction], reaction_rules: &[RSreaction],
@ -292,7 +314,7 @@ pub fn lollipops_only_loop_decomposed_named(
filtered.map(find_loop_fn) filtered.map(find_loop_fn)
} }
// see loop/5 /// see loop/5
pub fn lollipops_only_loop_decomposed_q( pub fn lollipops_only_loop_decomposed_q(
q: &RSset, q: &RSset,
reaction_rules: &[RSreaction], reaction_rules: &[RSreaction],

View File

@ -1,6 +1,5 @@
//! Slightly modified Simple graphviz dot file format output. //! Slightly modified Simple graphviz dot file format output.
//! See petgraph::dot::mod. //! See petgraph::dot::mod.
#![allow(dead_code)]
// use alloc::string::String; // use alloc::string::String;
use core::fmt::{self, Display, Write}; use core::fmt::{self, Display, Write};

View File

@ -1,10 +1,10 @@
#![allow(dead_code)]
use super::structure::RSset; use super::structure::RSset;
use super::structure::RSsystem; use super::structure::RSsystem;
use super::translator; use super::translator;
use super::translator::Translator; use super::translator::Translator;
/// Returns statistics about the system
/// see main_do(stat,MissingE)
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn of_RSsystem<'a>(translator: &'a Translator, system: &'a RSsystem) -> String { pub fn of_RSsystem<'a>(translator: &'a Translator, system: &'a RSsystem) -> String {
let mut result: String = "Statistics:\n".into(); let mut result: String = "Statistics:\n".into();

View File

@ -1,5 +1,3 @@
#![allow(dead_code)]
use super::translator::IdType; use super::translator::IdType;
use std::collections::{BTreeSet, HashMap, VecDeque}; use std::collections::{BTreeSet, HashMap, VecDeque};
use std::hash::Hash; use std::hash::Hash;
@ -8,6 +6,7 @@ use std::rc::Rc;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// RSset // RSset
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RSset { pub struct RSset {
pub identifiers: BTreeSet<IdType>, pub identifiers: BTreeSet<IdType>,
@ -52,18 +51,16 @@ impl RSset {
self.identifiers.is_disjoint(&b.identifiers) self.identifiers.is_disjoint(&b.identifiers)
} }
// returns the new set a \cup b
pub fn union(&self, b: &RSset) -> RSset { pub fn union(&self, b: &RSset) -> RSset {
// TODO maybe find more efficient way without copy/clone
let mut ret: RSset = b.clone(); let mut ret: RSset = b.clone();
ret.identifiers.extend(self.identifiers.iter()); ret.identifiers.extend(self.identifiers.iter());
ret ret
} }
pub fn union_option(&self, b: Option<&RSset>) -> RSset { pub fn union_option(&mut self, b: Option<&RSset>) {
if let Some(b) = b { if let Some(b) = b {
self.union(b) self.identifiers.extend(b.iter());
} else {
self.clone()
} }
} }
@ -78,7 +75,7 @@ impl RSset {
RSset { identifiers: res } RSset { identifiers: res }
} }
/// returns the new set a - b /// returns the new set a \ b
pub fn subtraction(&self, b: &RSset) -> RSset { pub fn subtraction(&self, b: &RSset) -> RSset {
// TODO maybe find more efficient way without copy/clone // TODO maybe find more efficient way without copy/clone
let res: BTreeSet<_> = self let res: BTreeSet<_> = self
@ -152,7 +149,8 @@ impl RSreaction {
} }
} }
// see enable /// returns true if ```current_state``` enables the reaction
/// see enable
pub fn enabled(&self, current_state: &RSset) -> bool { pub fn enabled(&self, current_state: &RSset) -> bool {
self.reactants.is_subset(current_state) self.reactants.is_subset(current_state)
&& self.inihibitors.is_disjoint(current_state) && self.inihibitors.is_disjoint(current_state)
@ -215,6 +213,7 @@ impl RSprocess {
} }
} }
/// returns all elements used
pub fn all_elements(&self) -> RSset { pub fn all_elements(&self) -> RSset {
let mut queue = VecDeque::from([self]); let mut queue = VecDeque::from([self]);
let mut elements = RSset::new(); let mut elements = RSset::new();
@ -316,6 +315,12 @@ impl RSchoices {
} }
} }
impl Default for RSchoices {
fn default() -> Self {
Self::new()
}
}
impl IntoIterator for RSchoices { impl IntoIterator for RSchoices {
type Item = (Rc<RSset>, Rc<RSprocess>); type Item = (Rc<RSset>, Rc<RSprocess>);
type IntoIter = std::vec::IntoIter<Self::Item>; type IntoIter = std::vec::IntoIter<Self::Item>;
@ -536,6 +541,12 @@ impl RSlabel {
} }
} }
impl Default for RSlabel {
fn default() -> Self {
Self::new()
}
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// RSassertOp // RSassertOp
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -1,4 +1,3 @@
#![allow(dead_code)]
use super::structure::{RSlabel, RSprocess, RSset, RSsystem}; use super::structure::{RSlabel, RSprocess, RSset, RSsystem};
use super::transitions::unfold; use super::transitions::unfold;
use std::rc::Rc; use std::rc::Rc;
@ -29,13 +28,19 @@ impl<'a> Iterator for TransitionsIterator<'a> {
fn next(&mut self) -> Option<(RSlabel, RSsystem)> { fn next(&mut self) -> Option<(RSlabel, RSsystem)> {
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 (reactants, reactantsi, inihibitors, ireactants, products) = let (
reactants,
reactants_absent,
inihibitors,
inihibitors_present,
products
) =
self.system.reaction_rules.iter().fold( self.system.reaction_rules.iter().fold(
( (
RSset::new(), // reactants RSset::new(), // reactants
RSset::new(), // reactantsi RSset::new(), // reactants_absent
RSset::new(), // inihibitors RSset::new(), // inihibitors
RSset::new(), // ireactants RSset::new(), // inihibitors_present
RSset::new(), // products RSset::new(), // products
), ),
|acc, reaction| { |acc, reaction| {
@ -64,9 +69,9 @@ impl<'a> Iterator for TransitionsIterator<'a> {
(*c).clone(), (*c).clone(),
t, t,
reactants, reactants,
reactantsi, reactants_absent,
inihibitors, inihibitors,
ireactants, inihibitors_present,
products.clone(), products.clone(),
); );
let new_system = RSsystem::from( let new_system = RSsystem::from(

View File

@ -1,5 +1,3 @@
#![allow(dead_code)]
use super::structure::{RSchoices, use super::structure::{RSchoices,
RSenvironment, RSenvironment,
RSlabel, RSlabel,
@ -9,7 +7,10 @@ use super::structure::{RSchoices,
use super::support_structures::TransitionsIterator; use super::support_structures::TransitionsIterator;
use std::rc::Rc; use std::rc::Rc;
// see unfold /// unfold returns the list of choices for the context given the process
/// definitions environment. RSchoices is a list of context moves mapping a set
/// of entities and the continuation
/// see unfold
pub fn unfold( pub fn unfold(
environment: &RSenvironment, environment: &RSenvironment,
context_process: &RSprocess, context_process: &RSprocess,
@ -93,7 +94,7 @@ pub fn iterator_transitions<'a>(
TransitionsIterator::from(system) TransitionsIterator::from(system)
} }
// see oneTransition, transition, smartTransition, smartOneTransition /// see oneTransition, transition, smartTransition, smartOneTransition
pub fn one_transition( pub fn one_transition(
system: &RSsystem system: &RSsystem
) -> Result<Option<(RSlabel, RSsystem)>, String> { ) -> Result<Option<(RSlabel, RSsystem)>, String> {
@ -101,7 +102,7 @@ pub fn one_transition(
Ok(tr.next()) Ok(tr.next())
} }
// see allTransitions, smartAllTransitions /// see allTransitions, smartAllTransitions
pub fn all_transitions( pub fn all_transitions(
system: &RSsystem system: &RSsystem
) -> Result<Vec<(RSlabel, RSsystem)>, String> { ) -> Result<Vec<(RSlabel, RSsystem)>, String> {
@ -109,7 +110,7 @@ pub fn all_transitions(
Ok(tr.collect::<Vec<_>>()) Ok(tr.collect::<Vec<_>>())
} }
// see oneTarget, smartOneTarget, target, smartTarget /// see oneTarget, smartOneTarget, target, smartTarget
pub fn target( pub fn target(
system: &RSsystem system: &RSsystem
) -> Result<(i64, RSset), String> { ) -> Result<(i64, RSset), String> {
@ -126,7 +127,7 @@ pub fn target(
Ok((n, current.available_entities.clone())) Ok((n, current.available_entities.clone()))
} }
// see oneRun, run, smartOneRunEK, smartRunEK /// see oneRun, run, smartOneRunEK, smartRunEK
pub fn run(system: RSsystem) -> Result<Vec<Rc<RSsystem>>, String> { pub fn run(system: RSsystem) -> Result<Vec<Rc<RSsystem>>, String> {
let mut res = vec![Rc::new(system)]; let mut res = vec![Rc::new(system)];
while let Some((_, next_sys)) = one_transition(res.last().unwrap())? { while let Some((_, next_sys)) = one_transition(res.last().unwrap())? {
@ -135,7 +136,7 @@ pub fn run(system: RSsystem) -> Result<Vec<Rc<RSsystem>>, String> {
Ok(res) Ok(res)
} }
// see smartOneRunECT, smartRunECT /// see smartOneRunECT, smartRunECT
pub fn run_separated( pub fn run_separated(
system: &RSsystem system: &RSsystem
) -> Result<Vec<(RSset, RSset, RSset)>, String> { ) -> Result<Vec<(RSset, RSset, RSset)>, String> {

View File

@ -1,6 +1,7 @@
// translate and keeps track of strings //! Module for translation and keeping track of strings.
use std::{cmp::max, collections::HashMap}; use std::{cmp::max, collections::HashMap};
/// precision for printing frequencies
static PRECISION: &usize = &2; static PRECISION: &usize = &2;
pub type IdType = u32; pub type IdType = u32;
@ -29,6 +30,7 @@ impl Default for Translator {
} }
impl Translator { impl Translator {
/// converts a string into an id
pub fn encode(&mut self, s: impl Into<String>) -> IdType { pub fn encode(&mut self, s: impl Into<String>) -> IdType {
let s = s.into(); let s = s.into();
let id = *(self.strings.entry(s.clone()).or_insert({ let id = *(self.strings.entry(s.clone()).or_insert({
@ -39,6 +41,7 @@ impl Translator {
id id
} }
/// converts an id into the corresponding string
pub fn decode(&self, el: IdType) -> Option<String> { pub fn decode(&self, el: IdType) -> Option<String> {
self.reverse self.reverse
.get(&el) .get(&el)