Files
ReactionSystems/src/rsprocess/translator.rs

441 lines
11 KiB
Rust
Raw Normal View History

//! Module for translation and keeping track of strings.
2025-07-10 15:02:14 +02:00
use std::{cmp::max, collections::HashMap};
2025-07-09 21:44:04 +02:00
use serde::{Serialize, Deserialize};
/// precision for printing frequencies
static PRECISION: &usize = &2;
2025-06-16 14:46:04 +02:00
pub type IdType = u32;
2025-07-10 15:02:14 +02:00
/// Structure that keeps track of association string and id. Ids given
/// sequentially from 0.
2025-07-09 21:44:04 +02:00
#[derive(Clone, Debug, Serialize, Deserialize)]
2025-06-16 14:46:04 +02:00
pub struct Translator {
strings: HashMap<String, IdType>,
2025-06-18 11:28:04 +02:00
reverse: HashMap<IdType, String>,
last_id: IdType,
2025-06-16 14:46:04 +02:00
}
impl Translator {
pub fn new() -> Self {
2025-06-18 11:28:04 +02:00
Translator {
2025-07-13 17:28:13 +02:00
strings: HashMap::from([("*".into(), 0)]),
reverse: HashMap::from([(0, "*".into())]),
last_id: 1,
2025-06-18 11:28:04 +02:00
}
2025-06-16 14:46:04 +02:00
}
2025-06-18 11:28:04 +02:00
}
2025-06-16 14:46:04 +02:00
impl Default for Translator {
fn default() -> Self {
2025-07-01 19:22:50 +02:00
Translator::new()
}
}
impl PartialEq for Translator {
fn eq(&self, other: &Self) -> bool {
for (s, id) in self.strings.iter() {
match other.strings.get(s) {
None => return false,
Some(id2) if id != id2 => return false,
_ => {}
}
}
true
}
}
2025-06-18 11:28:04 +02:00
impl Translator {
/// converts a string into an id
2025-06-18 11:28:04 +02:00
pub fn encode(&mut self, s: impl Into<String>) -> IdType {
let s = s.into();
let id = *(self.strings.entry(s.clone()).or_insert({
2025-06-18 11:28:04 +02:00
self.last_id += 1;
self.last_id
}));
self.reverse.insert(id, s.clone());
id
2025-06-18 11:28:04 +02:00
}
2025-06-16 14:46:04 +02:00
2025-07-12 02:42:28 +02:00
pub fn encode_not_mut(&self, s: impl Into<String>) -> Option<IdType> {
self.strings.get(&s.into()).copied()
}
/// converts an id into the corresponding string
2025-07-02 07:30:05 +02:00
pub fn decode(&self, el: IdType) -> Option<String> {
self.reverse
.get(&el)
.map(|x| x.to_string())
2025-06-18 11:28:04 +02:00
}
2025-06-16 14:46:04 +02:00
}
// -----------------------------------------------------------------------------
// print structures
2025-06-18 11:28:04 +02:00
// -----------------------------------------------------------------------------
2025-07-01 19:22:50 +02:00
use super::{
frequency::Frequency,
structure::{
2025-07-29 19:35:25 +02:00
RSBHML, RSassert, RSchoices, RSenvironment, RSlabel,
2025-07-01 19:22:50 +02:00
RSprocess, RSreaction, RSset, RSsystem,
},
};
2025-06-18 11:28:04 +02:00
use std::fmt;
macro_rules! translator_structure {
($name:ident, $type:ty, $dataname:ident, $print_func:ident) => {
#[derive(Clone, Debug)]
#[allow(dead_code)]
pub struct $name<'a> {
translator: &'a Translator,
$dataname: &'a $type,
}
#[allow(dead_code)]
impl <'a>$name<'a> {
pub fn from(translator: &'a Translator, $dataname: &'a $type) -> Self {
$name { translator, $dataname }
}
}
impl<'a> fmt::Display for $name<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
$print_func(f, self.translator, self.$dataname)
}
}
2025-06-18 11:28:04 +02:00
};
}
// RSset
2025-06-18 11:28:04 +02:00
fn print_set(
f: &mut fmt::Formatter,
translator: &Translator,
set: &RSset
) -> fmt::Result {
2025-06-18 11:28:04 +02:00
write!(f, "{{")?;
let mut it = set.iter().peekable();
2025-06-18 11:28:04 +02:00
while let Some(el) = it.next() {
if it.peek().is_none() {
2025-07-02 07:30:05 +02:00
write!(f,
"{}",
translator.decode(*el).unwrap_or("Missing".into()))?;
} else {
2025-07-02 07:30:05 +02:00
write!(f,
"{}, ",
translator.decode(*el).unwrap_or("Missing".into()))?;
}
2025-06-18 11:28:04 +02:00
}
write!(f, "}}")
}
translator_structure!(RSsetDisplay, RSset, set, print_set);
// RSreaction
fn print_reaction(
f: &mut fmt::Formatter,
translator: &Translator,
reaction: &RSreaction,
) -> fmt::Result {
write!(
f,
"(r: {}, i: {}, p: {})",
RSsetDisplay::from(translator, &reaction.reactants),
2025-07-13 19:08:39 +02:00
RSsetDisplay::from(translator, &reaction.inhibitors),
RSsetDisplay::from(translator, &reaction.products)
)
2025-06-18 11:28:04 +02:00
}
translator_structure!(RSreactionDisplay, RSreaction, reaction, print_reaction);
// RSprocess
fn print_process(
f: &mut fmt::Formatter,
translator: &Translator,
process: &RSprocess,
) -> fmt::Result {
2025-06-18 11:28:04 +02:00
use super::structure::RSprocess::*;
match process {
Nill => {
2025-07-05 14:54:43 +02:00
write!(f, "Nill")
2025-08-20 13:51:48 +02:00
},
RecursiveIdentifier { identifier } => {
2025-07-02 07:30:05 +02:00
write!(f,
"[{}]",
translator.decode(*identifier).unwrap_or("Missing".into()))
2025-08-20 13:51:48 +02:00
},
EntitySet { entities, next_process, } => {
write!(
f,
2025-07-05 14:54:43 +02:00
"{}.{}",
RSsetDisplay::from(translator, entities),
RSprocessDisplay::from(translator, next_process)
)
2025-08-20 13:51:48 +02:00
},
Guarded { reaction, next_process } => {
write!(f,
"?{}?.{}",
RSreactionDisplay::from(translator, reaction),
RSprocessDisplay::from(translator, next_process))
},
WaitEntity { repeat, repeated_process, next_process, } => {
write!(
f,
2025-07-05 14:54:43 +02:00
"({})^{repeat}.{}",
RSprocessDisplay::from(translator, repeated_process),
RSprocessDisplay::from(translator, next_process)
)
}
Summation { children } => {
write!(f, "[")?;
let mut it = children.iter().peekable();
while let Some(child) = it.next() {
if it.peek().is_none() {
2025-07-01 19:22:50 +02:00
write!(
f,
"{}",
RSprocessDisplay::from(translator, child)
2025-07-01 19:22:50 +02:00
)?;
} else {
write!(
f,
"{} + ",
RSprocessDisplay::from(translator, child)
)?;
}
}
write!(f, "]")
}
NondeterministicChoice { children } => {
write!(f, "[")?;
let mut it = children.iter().peekable();
while let Some(child) = it.next() {
if it.peek().is_none() {
2025-07-01 19:22:50 +02:00
write!(
f,
"{}",
RSprocessDisplay::from(translator, child)
2025-07-01 19:22:50 +02:00
)?;
} else {
2025-07-01 19:22:50 +02:00
write!(
f,
"{}, ",
RSprocessDisplay::from(translator, child)
2025-07-01 19:22:50 +02:00
)?;
}
}
write!(f, "]")
}
2025-06-18 11:28:04 +02:00
}
}
translator_structure!(RSprocessDisplay, RSprocess, process, print_process);
// RSchoices
fn print_choices(
f: &mut fmt::Formatter,
translator: &Translator,
choices: &RSchoices,
) -> fmt::Result {
2025-06-18 11:28:04 +02:00
write!(f, "[")?;
let mut it = choices.iter().peekable();
while let Some(el) = it.next() {
if it.peek().is_none() {
write!(
f,
"[set: {}, process: {}]",
RSsetDisplay::from(translator, &el.0),
RSprocessDisplay::from(translator, &el.1)
)?;
} else {
write!(
f,
"[set: {}, process: {}], ",
RSsetDisplay::from(translator, &el.0),
RSprocessDisplay::from(translator, &el.1)
)?;
}
2025-06-16 14:46:04 +02:00
}
2025-06-18 11:28:04 +02:00
write!(f, "]")
2025-06-16 14:46:04 +02:00
}
2025-06-18 11:28:04 +02:00
translator_structure!(RSchoicesDisplay, RSchoices, choices, print_choices);
// RSenvironment
fn print_environment(
f: &mut fmt::Formatter,
translator: &Translator,
environment: &RSenvironment,
) -> fmt::Result {
2025-06-18 11:28:04 +02:00
write!(f, "{{env:")?;
let mut it = environment.iter().peekable();
while let Some(el) = it.next() {
if it.peek().is_none() {
write!(
f,
"({} -> {})",
2025-07-02 07:30:05 +02:00
translator.decode(*el.0).unwrap_or("Missing".into()),
RSprocessDisplay::from(translator, el.1)
)?;
} else {
write!(
f,
"({} -> {}), ",
2025-07-02 07:30:05 +02:00
translator.decode(*el.0).unwrap_or("Missing".into()),
RSprocessDisplay::from(translator, el.1)
)?;
}
2025-06-18 11:28:04 +02:00
}
write!(f, "}}")
}
translator_structure!(RSenvironmentDisplay, RSenvironment, environment, print_environment);
// RSsystem
fn print_system(
f: &mut fmt::Formatter,
translator: &Translator,
system: &RSsystem
) -> fmt::Result {
write!(
f,
"[delta: {}, available_entities: {}, context_process: {}, reaction_rules: [",
RSenvironmentDisplay::from(translator, &system.delta),
RSsetDisplay::from(translator, &system.available_entities),
RSprocessDisplay::from(translator, &system.context_process)
2025-06-18 11:28:04 +02:00
)?;
let mut it = system.reaction_rules.iter().peekable();
2025-06-18 11:28:04 +02:00
while let Some(el) = it.next() {
if it.peek().is_none() {
write!(f, "{}", RSreactionDisplay::from(translator, el))?;
} else {
write!(f, "{}, ", RSreactionDisplay::from(translator, el))?;
}
2025-06-18 11:28:04 +02:00
}
write!(f, "] ]")
}
translator_structure!(RSsystemDisplay, RSsystem, system, print_system);
// RSlabel
fn print_label(
f: &mut fmt::Formatter,
translator: &Translator,
label: &RSlabel
) -> fmt::Result {
2025-07-01 19:22:50 +02:00
write!(
f,
"{{available_entities: {}, context: {}, t: {}, reactants: {}, reactantsi: {}, inihibitors: {}, ireactants: {}, products: {}}}",
RSsetDisplay::from(translator, &label.available_entities),
RSsetDisplay::from(translator, &label.context),
RSsetDisplay::from(translator, &label.t),
RSsetDisplay::from(translator, &label.reactants),
RSsetDisplay::from(translator, &label.reactants_absent),
2025-07-13 19:08:39 +02:00
RSsetDisplay::from(translator, &label.inhibitors),
RSsetDisplay::from(translator, &label.inhibitors_present),
RSsetDisplay::from(translator, &label.products),
2025-06-18 11:28:04 +02:00
)
}
translator_structure!(RSlabelDisplay, RSlabel, label, print_label);
// RSassert
2025-06-18 11:28:04 +02:00
#[allow(unused_variables)]
fn print_assert(
f: &mut fmt::Formatter,
translator: &Translator,
assert: &RSassert
) -> fmt::Result {
2025-06-18 11:28:04 +02:00
todo!()
}
translator_structure!(RSassertDisplay, RSassert, assert, print_assert);
// RSBHML
2025-06-18 11:28:04 +02:00
#[allow(unused_variables)]
fn print_bhml(
f: &mut fmt::Formatter,
translator: &Translator,
bhml: &RSBHML
) -> fmt::Result {
2025-06-18 11:28:04 +02:00
todo!()
}
translator_structure!(RSBHMLDisplay, RSBHML, bhml, print_bhml);
// Frequency
fn print_frequency(
f: &mut fmt::Formatter,
translator: &Translator,
frequency: &Frequency,
) -> fmt::Result {
write!(f, "[")?;
2025-07-01 18:00:27 +02:00
let mut freq_it = frequency.frequency_map.iter().peekable();
let totals = &frequency.totals;
let weights = &frequency.weights;
2025-07-01 18:00:27 +02:00
while let Some((e, freq)) = freq_it.next() {
2025-07-02 07:30:05 +02:00
write!(f, "{} -> ", translator.decode(*e).unwrap_or("Missing".into()))?;
2025-07-01 18:00:27 +02:00
2025-07-01 19:22:50 +02:00
let mut total_freq = 0.;
2025-07-01 18:00:27 +02:00
let end = max(freq.len(), max(totals.len(), weights.len()));
2025-07-01 18:00:27 +02:00
for pos in 0..end {
let freq_e = freq.get(pos).copied().unwrap_or(0) as f32;
let weight = weights.get(pos).copied().unwrap_or(1) as f32;
let total = totals.get(pos).copied().unwrap_or(1) as f32;
let weighted_freq = (freq_e * weight * 100.) / (total);
if pos == end-1 {
#[allow(clippy::uninlined_format_args)]
write!(f, "{weighted_freq:.*}", PRECISION)?;
} else {
#[allow(clippy::uninlined_format_args)]
write!(f, "{weighted_freq:.*}, ", PRECISION)?;
}
total_freq += weighted_freq;
}
2025-07-01 19:22:50 +02:00
total_freq /= frequency.total_weights() as f32;
2025-07-01 18:00:27 +02:00
#[allow(clippy::uninlined_format_args)]
write!(f, " (total: {total_freq:.*})", PRECISION)?;
2025-07-01 18:00:27 +02:00
2025-07-01 19:22:50 +02:00
if freq_it.peek().is_some() {
writeln!(f, ",")?;
}
}
write!(f, "]")
}
translator_structure!(FrequencyDisplay, Frequency, frequency, print_frequency);