Files
ReactionSystems/src/rsprocess/frequency.rs

153 lines
4.0 KiB
Rust
Raw Normal View History

2025-07-10 15:02:14 +02:00
//! Definitions and structure for frequency of elements in a simulation
2025-07-01 19:22:50 +02:00
use std::collections::HashMap;
use super::reaction::Reaction;
use super::set::Set;
use super::system::System;
use super::translator::IdType;
/// structure that holds the frequency of elements of a run or multiple runs,
2025-07-10 15:02:14 +02:00
/// weighted. To print use ```translator::FrequencyDisplay```.
#[derive(Debug, Clone)]
pub struct Frequency {
2025-07-01 18:00:27 +02:00
pub frequency_map: HashMap<IdType, Vec<u32>>,
pub totals: Vec<usize>,
2025-07-01 19:22:50 +02:00
pub weights: Vec<u32>,
}
impl Frequency {
2025-07-01 18:00:27 +02:00
pub fn new() -> Self {
2025-07-01 19:22:50 +02:00
Frequency {
frequency_map: HashMap::new(),
totals: vec![],
weights: vec![],
}
}
pub fn add(&mut self, e: &Set, run: usize) {
2025-07-01 19:22:50 +02:00
for &el in e.iter() {
2025-07-12 02:42:28 +02:00
let entry =
self.frequency_map.entry(el).or_insert(vec![0; run + 1]);
2025-07-02 17:27:36 +02:00
if entry.len() < run +1 {
entry.resize(run + 1, 0);
}
entry[run] += 1
2025-07-01 19:22:50 +02:00
}
2025-07-02 07:30:05 +02:00
// TODO resize clones all prev values, replace with in place method
if self.totals.len() < run + 1 {
self.totals.resize(run + 1, 0);
}
2025-07-01 19:22:50 +02:00
self.totals[run] += 1
}
2025-07-01 18:00:27 +02:00
pub fn append_weight(&mut self, new_weight: u32) {
2025-07-01 19:22:50 +02:00
self.weights.push(new_weight)
2025-07-01 18:00:27 +02:00
}
pub fn total_weights(&self) -> u32 {
2025-07-01 19:22:50 +02:00
self.weights.iter().sum()
2025-07-01 18:00:27 +02:00
}
}
impl Default for Frequency {
fn default() -> Self {
2025-07-01 19:22:50 +02:00
Frequency::new()
}
}
// -----------------------------------------------------------------------------
impl Frequency {
/// Assuming the system is finite, calculates the frequency of each symbol
/// in all traversed states.
/// see naiveFreq
pub fn naive_frequency(
system: &System
) -> Result<Self, String> {
let ect = system.run_separated()?;
let es = ect.iter().map(|(e, _, _)| e).collect::<Vec<_>>();
let mut freq = Frequency::new();
freq.append_weight(1);
es.iter().for_each(|e| freq.add(e, 0));
Ok(freq)
}
/// Assume the system stabilizes in a loop, calculates the frequency of each
/// symbol in all states of the loop.
/// see loopFreq
pub fn loop_frequency(
system: &System,
symb: IdType
) -> Self {
let mut freq = Frequency::new();
freq.append_weight(1);
if let Some(hoop) = system.lollipops_only_loop_named(symb) {
hoop.iter().for_each(|e| freq.add(e, 0));
}
freq
}
/// Assuming ```q[i]``` is given enough times such that the system
/// stabilizes in a loop, calculates the frequency of the symbols in any
/// state in the last loop.
/// see limitFreq
pub fn limit_frequency(
q: &[Set],
reaction_rules: &[Reaction],
available_entities: &Set,
) -> Option<Self> {
let mut available_entities = available_entities.clone();
for q in q.iter().rev().skip(1).rev() {
let res =
Reaction::lollipops_only_loop_decomposed_q(reaction_rules,
q,
&available_entities);
available_entities = res.into_iter().next()?;
}
let mut freq = Frequency::new();
freq.append_weight(1);
Reaction::lollipops_only_loop_decomposed_q(reaction_rules,
q.last().unwrap(),
&available_entities)
.iter()
.for_each(|e| freq.add(e, 0));
Some(freq)
}
/// Assuming ```q[i]``` is given enough times such that the system
/// stabilizes in a loop, calculates the frequency of the symbols in any
/// state in any loop, weighted.
/// see fastFreq
pub fn fast_frequency(
q: &[Set],
reaction_rules: &[Reaction],
available_entities: &Set,
weights: &[u32],
) -> Option<Self> {
// FIXME: we return the empty frequency or do we not return anything?
let mut available_entities = available_entities.clone();
let mut freq = Frequency::new();
for (pos, (q, &w)) in q.iter().zip(weights).enumerate() {
freq.append_weight(w);
let hoop =
Reaction::lollipops_only_loop_decomposed_q(reaction_rules,
q,
&available_entities);
hoop.iter().for_each(|e| freq.add(e, pos));
available_entities = hoop.into_iter().next()?;
}
Some(freq)
}
}