Adding traces

This commit is contained in:
elvis
2025-08-21 21:43:54 +02:00
parent c58597389d
commit 064bddbddc
2 changed files with 177 additions and 110 deletions

View File

@ -41,7 +41,7 @@ impl From<Vec<IdType>> for RSset {
} }
impl RSset { impl RSset {
pub fn new() -> Self { pub const fn new() -> Self {
RSset { RSset {
identifiers: BTreeSet::new(), identifiers: BTreeSet::new(),
} }

View File

@ -1,11 +1,11 @@
//! Definitions for simple simulation steps. //! Definitions for simple simulation steps.
use super::structure::{RSchoices, use super::structure::{RSchoices,
RSenvironment, RSenvironment,
RSlabel, RSlabel,
RSprocess, RSprocess,
RSset, RSset,
RSsystem}; RSsystem};
use super::support_structures::TransitionsIterator; use super::support_structures::TransitionsIterator;
use std::rc::Rc; use std::rc::Rc;
@ -14,149 +14,216 @@ use std::rc::Rc;
/// of entities and the continuation. /// of entities and the continuation.
/// see unfold /// see unfold
pub fn unfold( pub fn unfold(
environment: &RSenvironment, environment: &RSenvironment,
context_process: &RSprocess, context_process: &RSprocess,
current_entities: &RSset, current_entities: &RSset,
) -> Result<RSchoices, String> { ) -> Result<RSchoices, String> {
match context_process { match context_process {
RSprocess::Nill => { RSprocess::Nill => {
Ok(RSchoices::new()) Ok(RSchoices::new())
}, },
RSprocess::RecursiveIdentifier { identifier } => { RSprocess::RecursiveIdentifier { identifier } => {
let newprocess = environment.get(*identifier); let newprocess = environment.get(*identifier);
if let Some(newprocess) = newprocess { if let Some(newprocess) = newprocess {
unfold(environment, newprocess, current_entities) unfold(environment, newprocess, current_entities)
} else { } else {
Err(format!("Missing symbol in context: {identifier}")) Err(format!("Missing symbol in context: {identifier}"))
} }
} }
RSprocess::EntitySet { entities, next_process, } => { RSprocess::EntitySet { entities, next_process, } => {
Ok(RSchoices::from([( Ok(RSchoices::from([(
Rc::new(entities.clone()), Rc::new(entities.clone()),
Rc::clone(next_process), Rc::clone(next_process),
)])) )]))
}, },
RSprocess::Guarded { reaction, next_process } => { RSprocess::Guarded { reaction, next_process } => {
if reaction.enabled(current_entities) { if reaction.enabled(current_entities) {
Ok(RSchoices::from([(Rc::new(reaction.products.clone()), Ok(RSchoices::from([(Rc::new(reaction.products.clone()),
Rc::clone(next_process))])) Rc::clone(next_process))]))
} else { } else {
Ok(RSchoices::new()) Ok(RSchoices::new())
} }
} }
RSprocess::WaitEntity { repeat, repeated_process: _, next_process, } RSprocess::WaitEntity { repeat, repeated_process: _, next_process, }
if *repeat <= 0 => { if *repeat <= 0 => {
unfold(environment, next_process, current_entities) unfold(environment, next_process, current_entities)
}, },
RSprocess::WaitEntity { repeat, repeated_process, next_process, } RSprocess::WaitEntity { repeat, repeated_process, next_process, }
if *repeat == 1 => { if *repeat == 1 => {
let mut choices1 = unfold(environment, repeated_process, current_entities)?; let mut choices1 = unfold(environment, repeated_process, current_entities)?;
choices1.replace(Rc::clone(next_process)); choices1.replace(Rc::clone(next_process));
Ok(choices1) Ok(choices1)
} }
RSprocess::WaitEntity { repeat, repeated_process, next_process, } => { RSprocess::WaitEntity { repeat, repeated_process, next_process, } => {
let mut choices1 = unfold(environment, repeated_process, current_entities)?; let mut choices1 = unfold(environment, repeated_process, current_entities)?;
choices1.replace(Rc::new(RSprocess::WaitEntity { choices1.replace(Rc::new(RSprocess::WaitEntity {
repeat: (*repeat - 1), repeat: (*repeat - 1),
repeated_process: Rc::clone(repeated_process), repeated_process: Rc::clone(repeated_process),
next_process: Rc::clone(next_process), next_process: Rc::clone(next_process),
})); }));
Ok(choices1) Ok(choices1)
} }
RSprocess::Summation { children } => { RSprocess::Summation { children } => {
// short-circuits with try_fold. // short-circuits with try_fold.
children.iter().try_fold(RSchoices::new(), |mut acc, x| { children.iter().try_fold(RSchoices::new(), |mut acc, x| {
match unfold(environment, x, current_entities) { match unfold(environment, x, current_entities) {
Ok(mut choices) => { Ok(mut choices) => {
acc.append(&mut choices); acc.append(&mut choices);
Ok(acc) Ok(acc)
} }
Err(e) => Err(e), Err(e) => Err(e),
} }
}) })
} }
RSprocess::NondeterministicChoice { children } => { RSprocess::NondeterministicChoice { children } => {
// short-circuits with try_fold. // short-circuits with try_fold.
if children.is_empty() { if children.is_empty() {
Ok(RSchoices::from(vec![( Ok(RSchoices::from(vec![(
Rc::new(RSset::new()), Rc::new(RSset::new()),
Rc::new(RSprocess::Nill), Rc::new(RSprocess::Nill),
)])) )]))
} else { } else {
children.iter().try_fold(RSchoices::new(), |mut acc, x| { children.iter().try_fold(RSchoices::new(), |mut acc, x| {
acc.shuffle(unfold(environment, x, current_entities)?); acc.shuffle(unfold(environment, x, current_entities)?);
Ok(acc) Ok(acc)
}) })
} }
} }
} }
} }
pub fn iterator_transitions<'a>( pub fn iterator_transitions<'a>(
system: &'a RSsystem system: &'a RSsystem
) -> Result<TransitionsIterator<'a>, String> { ) -> Result<TransitionsIterator<'a>, String> {
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> {
let mut tr = TransitionsIterator::from(system)?; let mut tr = TransitionsIterator::from(system)?;
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> {
let tr = TransitionsIterator::from(system)?; let tr = TransitionsIterator::from(system)?;
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> {
let current = one_transition(system)?; let current = one_transition(system)?;
if current.is_none() { if current.is_none() {
return Ok((0, system.available_entities.clone())); return Ok((0, system.available_entities.clone()));
} }
let mut n = 1; let mut n = 1;
let mut current = current.unwrap().1; let mut current = current.unwrap().1;
while let Some((_, next)) = one_transition(&current)? { while let Some((_, next)) = one_transition(&current)? {
current = next; current = next;
n += 1; n += 1;
} }
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())? {
res.push(Rc::new(next_sys)); res.push(Rc::new(next_sys));
} }
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> {
let mut res = vec![]; let mut res = vec![];
let current = one_transition(system)?; let current = one_transition(system)?;
if current.is_none() { if current.is_none() {
return Ok(res); return Ok(res);
} }
let current = current.unwrap(); let current = current.unwrap();
let (available_entities, context, t) = current.0.get_context(); let (available_entities, context, t) = current.0.get_context();
res.push((available_entities.clone(), context.clone(), t.clone())); res.push((available_entities.clone(), context.clone(), t.clone()));
let mut current = current.1; let mut current = current.1;
while let Some((label, next)) = one_transition(&current)? { while let Some((label, next)) = one_transition(&current)? {
current = next; current = next;
let (available_entities, context, t) = label.get_context(); let (available_entities, context, t) = label.get_context();
res.push((available_entities.clone(), context.clone(), t.clone())); res.push((available_entities.clone(), context.clone(), t.clone()));
} }
Ok(res) Ok(res)
}
fn nth_transition(
system: &RSsystem,
n: usize,
) -> Result<Option<(RSlabel, RSsystem)>, String> {
let mut tr = TransitionsIterator::from(system)?;
Ok(tr.nth(n))
}
type Trace = Vec<(Option<Rc<RSlabel>>, Rc<RSsystem>)>;
pub fn traces(
system: RSsystem,
n: usize,
) -> Result<Vec<Trace>, String> {
if n == 0 {
return Ok(vec![])
}
let mut n = n;
let mut res : Vec<Trace> = vec![];
let mut current_trace: Trace = vec![(None, Rc::new(system))];
let mut branch = vec![0];
let mut depth = 0;
let mut new_branch = true;
loop {
let next_sys = nth_transition(&current_trace[depth].1,
branch[depth])?;
if let Some((current_label, next_sys)) = next_sys {
depth += 1;
if depth >= branch.len() {
branch.push(0);
current_trace.push((Some(Rc::new(current_label)),
Rc::new(next_sys)));
} else {
branch[depth] = 0;
current_trace[depth] = (Some(Rc::new(current_label)),
Rc::new(next_sys));
}
new_branch = true;
} else {
// at the bottom of a trace, we save to res, then backtrack until
// we find another possible path.
if new_branch {
res.push(current_trace[0..depth].to_vec());
new_branch = false;
n -= 1;
}
if n == 0 {
break;
}
if depth == 0 {
break;
}
depth -= 1;
branch[depth] += 1;
}
}
Ok(res)
} }