Files
ReactionSystems/src/rsprocess/frequency.rs

139 lines
3.9 KiB
Rust
Raw Normal View History

use crate::rsprocess::perpetual::lollipops_only_loop_decomposed_q;
2025-07-01 19:22:50 +02:00
use std::collections::HashMap;
2025-07-01 18:00:27 +02:00
use super::perpetual::lollipops_only_loop_named;
use super::structure::{RSreaction, RSset, RSsystem};
use super::transitions::run_separated;
use super::translator::IdType;
/// structure that holds the frequency of elements of a run or multiple runs,
/// weighted
#[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![],
}
}
2025-07-01 18:00:27 +02:00
pub fn add(&mut self, e: &RSset, run: usize) {
2025-07-01 19:22:50 +02:00
for &el in e.iter() {
2025-07-02 17:27:36 +02:00
let entry = self.frequency_map.entry(el).or_insert(vec![0; run + 1]);
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()
}
}
// -----------------------------------------------------------------------------
/// assume the system is finite, calculate the frequency of each symbol in all
/// traversed states
/// see naiveFreq
pub fn naive_frequency(system: &RSsystem) -> Result<Frequency, String> {
let ect = run_separated(system)?;
let es = ect.iter().map(|(e, _, _)| e).collect::<Vec<_>>();
2025-07-01 18:00:27 +02:00
let mut freq = Frequency::new();
freq.append_weight(1);
2025-07-01 18:00:27 +02:00
es.iter().for_each(|e| freq.add(e, 0));
Ok(freq)
}
/// assume the system stabilizes in a loop, calculate the frequency of each
/// symbol in all states of the loop
/// see loopFreq
2025-07-01 18:00:27 +02:00
pub fn loop_frequency(system: &RSsystem, symb: IdType) -> Frequency {
let mut freq = Frequency::new();
freq.append_weight(1);
if let Some(hoop) = lollipops_only_loop_named(system.clone(), symb) {
2025-07-01 19:22:50 +02:00
hoop.iter().for_each(|e| freq.add(e, 0));
}
freq
}
/// ```q[i]``` is given enough times such that the stabilizes in a loop, calculate the
/// frequency of the symbols in any state in the last loop
/// see limitFreq
pub fn limit_frequency(
q: &[RSset],
reaction_rules: &[RSreaction],
2025-07-01 19:22:50 +02:00
available_entities: &RSset,
) -> Option<Frequency> {
let mut available_entities = available_entities.clone();
2025-07-01 18:00:27 +02:00
for q in q.iter().rev().skip(1).rev() {
2025-07-01 19:22:50 +02:00
let res = lollipops_only_loop_decomposed_q(q,
reaction_rules,
&available_entities);
2025-07-01 19:22:50 +02:00
available_entities = res.into_iter().next()?;
}
2025-07-01 18:00:27 +02:00
let mut freq = Frequency::new();
freq.append_weight(1);
lollipops_only_loop_decomposed_q(q.last().unwrap(),
reaction_rules,
&available_entities)
2025-07-01 19:22:50 +02:00
.iter()
.for_each(|e| freq.add(e, 0));
Some(freq)
}
/// ```q[i]``` is given enough times such that the stabilizes in a loop, calculate the
/// frequency of the symbols in any state in any loop, weighted.
/// see fastFreq
pub fn fast_frequency(
2025-07-01 18:00:27 +02:00
q: &[RSset],
reaction_rules: &[RSreaction],
available_entities: &RSset,
2025-07-01 19:22:50 +02:00
weights: &[u32],
) -> Option<Frequency> {
// FIXME: we return the empty frequency or do we not return anything?
let mut available_entities = available_entities.clone();
2025-07-01 18:00:27 +02:00
let mut freq = Frequency::new();
2025-07-01 18:00:27 +02:00
for (pos, (q, &w)) in q.iter().zip(weights).enumerate() {
2025-07-01 19:22:50 +02:00
freq.append_weight(w);
let hoop = lollipops_only_loop_decomposed_q(q,
2025-07-01 18:00:27 +02:00
reaction_rules,
&available_entities);
2025-07-01 19:22:50 +02:00
hoop.iter().for_each(|e| freq.add(e, pos));
available_entities = hoop.into_iter().next()?;
}
Some(freq)
}