Files
ReactionSystems/src/rsprocess/frequency.rs

127 lines
3.6 KiB
Rust
Raw Normal View History

#![allow(dead_code)]
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;
#[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() {
self.frequency_map.entry(el).or_insert(vec![0; run + 1])[run] += 1
}
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()
}
}
// -----------------------------------------------------------------------------
2025-07-01 18:00:27 +02:00
// see naiveFreq, assume the system is finite, calculate the frequency of
// each symbol in all traversed states
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)
}
2025-07-01 18:00:27 +02:00
// see loopFreq, assume the system stabilizes in a loop, calculate the frequency
// of each symbol in all states of the loop
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
}
2025-07-01 18:00:27 +02:00
// see limitFreq, 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
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)
}
2025-07-01 18:00:27 +02:00
// see fastFreq, 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.
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)
}