From 08ad2cb3054568874311631702a99d76d16e02df Mon Sep 17 00:00:00 2001 From: elvis Date: Fri, 20 Jun 2025 17:11:00 +0200 Subject: [PATCH] lollipop operator without prefix --- src/main.rs | 13 +++++- src/rsprocess/perpetual.rs | 90 ++++++++++++++++++++++++++------------ 2 files changed, 73 insertions(+), 30 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4e8c65e..fbd5677 100644 --- a/src/main.rs +++ b/src/main.rs @@ -170,7 +170,7 @@ fn main() -> Result<(), Box> { ) ])); - let res = rsprocess::perpetual::lollipops(sys); + let res = rsprocess::perpetual::lollipops(sys.clone()); println!("res:"); for (prefix, hoop) in res { @@ -184,5 +184,16 @@ fn main() -> Result<(), Box> { } println!(); } + + let res = rsprocess::perpetual::lollipops_only_loop(sys); + + println!("res:"); + for hoop in res { + print!("hoop: "); + for l in hoop { + print!("{}, ", WithTranslator::from_RSset(&translator, &l)); + } + println!(); + } Ok(()) } diff --git a/src/rsprocess/perpetual.rs b/src/rsprocess/perpetual.rs index 8cb9055..4e3d051 100644 --- a/src/rsprocess/perpetual.rs +++ b/src/rsprocess/perpetual.rs @@ -1,55 +1,87 @@ #![allow(dead_code)] use std::rc::Rc; - use super::classical::compute_all_owned; use super::translator::IdType; use super::structure::{RSsystem, RSprocess, RSset, RSreaction}; +// finds only the rules X = pre(Q, rec(X)), but not only x = pre(Q, rec(x)) +// to use in filter_map +fn filter_delta<'a>(x: (&IdType, &'a RSprocess)) -> Option<&'a RSset> { + use super::structure::RSprocess::*; + let (id, rest) = x; + match rest { + EntitySet{ entities, next_process} => { + match &**next_process { + RecursiveIdentifier{ identifier } if identifier == id => { + Some(entities) + }, + _ => None + } + }, + _ => None + } +} + +// returns the prefix and the loop from a trace fn split<'a>(set: &'a RSset, trace: &'a [RSset]) -> Option<(&'a[RSset], &'a[RSset])> { let position = trace.iter().rposition(|x| x == set); position.map(|pos| trace.split_at(pos)) } -fn find_loop(rs: &Rc>, e: RSset, q: &RSset) -> (Vec, Vec) { - let mut e = e; +// finds the loops by simulating the system +fn find_loop(rs: &Rc>, entities: RSset, q: &RSset) -> (Vec, Vec) { + let mut entities = entities; let mut trace = vec![]; loop { - if let Some((prefix, hoop)) = split(&e, &trace) { + if let Some((prefix, hoop)) = split(&entities, &trace) { return (prefix.to_vec(), hoop.to_vec()); } else { - let t = e.union(q); - let p = compute_all_owned(&t, rs); - trace.push(e.clone()); - e = p; + let t = entities.union(q); + let products = compute_all_owned(&t, rs); + trace.push(entities.clone()); + entities = products; + } + } +} + +// finds the loops by simulating the system +fn find_only_loop(rs: &Rc>, entities: RSset, q: &RSset) -> Vec { + let mut entities = entities; + let mut trace = vec![]; + loop { + if let Some((_prefix, hoop)) = split(&entities, &trace) { + return hoop.to_vec(); + } else { + let t = entities.union(q); + let products = compute_all_owned(&t, rs); + trace.push(entities.clone()); + entities = products; } } } // see lollipop pub fn lollipops(system: RSsystem) -> Vec<(Vec, Vec)> { - fn filter_delta<'a>(x: (&IdType, &'a RSprocess)) -> Option<&'a RSset> { - use super::structure::RSprocess::*; - let (id, rest) = x; - match rest { - EntitySet{ entities, next_process} => { - match &**next_process { - RecursiveIdentifier{ identifier } if identifier == id => { - Some(entities) - }, - _ => None - } - }, - _ => None - } - } - - // FIXME: what? i think we are only interested in "x", not all symbols that + // FIXME: i think we are only interested in "x", not all symbols that // satisfy X = pre(Q, rec(X)) let filtered = system.get_delta().iter().filter_map(filter_delta); - filtered.map(|q| find_loop(system.get_reaction_rules(), - system.get_available_entities().clone(), - q) - ).collect::>() + let find_loop_fn = |q| find_loop(system.get_reaction_rules(), + system.get_available_entities().clone(), + q); + + filtered.map(find_loop_fn).collect::>() +} + +pub fn lollipops_only_loop(system: RSsystem) -> Vec> { + // FIXME: i think we are only interested in "x", not all symbols that + // satisfy X = pre(Q, rec(X)) + let filtered = system.get_delta().iter().filter_map(filter_delta); + + let find_loop_fn = |q| find_only_loop(system.get_reaction_rules(), + system.get_available_entities().clone(), + q); + + filtered.map(find_loop_fn).collect::>() }