From cdf3d23243098f79cfea51a79aea4773e37bb128 Mon Sep 17 00:00:00 2001 From: elvis Date: Mon, 7 Jul 2025 01:25:38 +0200 Subject: [PATCH] Useful graph presets --- src/examples.rs | 16 +- src/rsprocess/graph.rs | 316 ++++++++++++++++++++++++++++++++++++- src/rsprocess/structure.rs | 2 + 3 files changed, 329 insertions(+), 5 deletions(-) diff --git a/src/examples.rs b/src/examples.rs index 642dbf5..48c9595 100644 --- a/src/examples.rs +++ b/src/examples.rs @@ -11,6 +11,7 @@ use std::env; use std::fs; use std::io; use std::io::prelude::*; +use std::rc::Rc; // grammar is defined in main.rs, calling lalrpop_mod! twice, generates twice // the code @@ -252,10 +253,17 @@ pub fn digraph() -> std::io::Result<()> { println!("Generated graph in dot notation:\n{:?}\n", Dot::new(&res)); - let res = res.map(|_, node| format!("{}; {}", - translator::RSsetDisplay::from(&translator, node.get_available_entities()), - translator::RSprocessDisplay::from(&translator, node.get_context_process())), - |_, edge| translator::RSsetDisplay::from(&translator, &edge.context)); + let rc_translator = Rc::new(translator); + + let res = res.map( + |id, node| + graph::GraphMapNodesTy::from(graph::GraphMapNodes::Entities, + Rc::clone(&rc_translator)).get()(id, node) + + "; " + + &graph::GraphMapNodesTy::from(graph::GraphMapNodes::Context, + Rc::clone(&rc_translator)).get()(id, node), + graph::GraphMapEdgesTy::from(graph::GraphMapEdges::EntitiesAdded, + Rc::clone(&rc_translator)).get()); println!("Generated graph in dot notation:\n{}", Dot::new(&res)); diff --git a/src/rsprocess/graph.rs b/src/rsprocess/graph.rs index 52ca3ef..d4a9f30 100644 --- a/src/rsprocess/graph.rs +++ b/src/rsprocess/graph.rs @@ -2,8 +2,10 @@ use petgraph::Graph; use std::collections::HashMap; -use super::structure::{RSlabel, RSsystem}; +use super::structure::{RSlabel, RSsystem, RSset}; use super::support_structures::TransitionsIterator; +use super::translator; +use std::rc::Rc; pub fn digraph( system: RSsystem @@ -37,3 +39,315 @@ pub fn digraph( } Ok(graph) } + +// ----------------------------------------------------------------------------- +// helper functions +// ----------------------------------------------------------------------------- + + +// Nodes ----------------------------------------------------------------------- + +pub enum GraphMapNodes { + Hide, + Entities, + MaskEntities { mask: RSset }, + Context, +} + +type GraphMapNodesFnTy = dyn Fn(petgraph::prelude::NodeIndex, &RSsystem) -> String; +pub struct GraphMapNodesTy { + function: Box +} + +impl GraphMapNodesTy { + pub fn from( + f: GraphMapNodes, + translator: Rc + ) -> Self { + use GraphMapNodes::*; + let function: Box = + // rust cant unify closures (they all have different types) so box needs + // to happen inside the match + // we use move because translator is from the env, so we transfer the + // borrow to the struct, also translator needs to be in box, a reference + // is not enough + match f { + Hide => { + Box::new( + |_, _| + String::new() + ) + }, + Entities => { + Box::new( + move |_, node: &RSsystem| + format!("{}", + translator::RSsetDisplay::from( + &translator, + node.get_available_entities()) + ) + ) + }, + MaskEntities { mask } => { + Box::new( + move |_, node: &RSsystem| { + let masked_entities = + node.get_available_entities() + .intersection(&mask); + format!("{}", + translator::RSsetDisplay::from( + &translator, + &masked_entities) + ) + } + ) + }, + Context => { + Box::new( + move |_, node: &RSsystem| + format!("{}", + translator::RSprocessDisplay::from( + &translator, + node.get_context_process()) + ) + ) + }, + }; + GraphMapNodesTy { function } + } + + pub fn get(&self) -> &GraphMapNodesFnTy { + &self.function + } +} + +impl From for Box { + fn from(g: GraphMapNodesTy) -> Self { + g.function + } +} + +// Edges ----------------------------------------------------------------------- + +pub enum GraphMapEdges { + Hide, + Products, + MaskProducts { mask: RSset }, + Entities, + MaskEntities { mask: RSset }, + Context, + MaskContext { mask: RSset }, + Union, + MaskUnion { mask: RSset }, + Difference, + MaskDifference { mask: RSset }, + EntitiesDeleted, + MaskEntitiesDeleted { mask: RSset }, + EntitiesAdded, + MaskEntitiesAdded { mask: RSset }, +} + +type GraphMapEdgesFnTy = dyn Fn(petgraph::prelude::EdgeIndex, &RSlabel) -> String; +pub struct GraphMapEdgesTy { + function: Box +} + +impl GraphMapEdgesTy { + pub fn from( + f: GraphMapEdges, + translator: Rc + ) -> Self { + use GraphMapEdges::*; + let function: Box = + // rust cant unify closures (they all have different types) so box needs + // to happen inside the match + // we use move because translator is from the env, so we transfer the + // borrow to the struct, also translator needs to be in box, a reference + // is not enough + match f { + Hide => { + Box::new( + |_, _| + String::new() + ) + }, + Products => { + Box::new( + move |_, edge: &RSlabel| + format!("{}", + translator::RSsetDisplay::from( + &translator, + &edge.products + ) + ) + ) + }, + MaskProducts { mask } => { + Box::new( + move |_, edge: &RSlabel| + format!("{}", + translator::RSsetDisplay::from( + &translator, + &mask.intersection(&edge.products) + ) + ) + ) + }, + Entities => { + Box::new( + move |_, edge: &RSlabel| + format!("{}", + translator::RSsetDisplay::from( + &translator, + &edge.available_entities + ) + ) + ) + }, + MaskEntities { mask } => { + Box::new( + move |_, edge: &RSlabel| + format!("{}", + translator::RSsetDisplay::from( + &translator, + &mask.intersection(&edge.available_entities) + ) + ) + ) + }, + Context => { + Box::new( + move |_, edge: &RSlabel| + format!("{}", + translator::RSsetDisplay::from( + &translator, + &edge.context + ) + ) + ) + }, + MaskContext { mask } => { + Box::new( + move |_, edge: &RSlabel| + format!("{}", + translator::RSsetDisplay::from( + &translator, + &mask.intersection(&edge.context) + ) + ) + ) + }, + Union => { + Box::new( + move |_, edge: &RSlabel| + format!("{}", + translator::RSsetDisplay::from( + &translator, + &edge.t + ) + ) + ) + }, + MaskUnion { mask } => { + Box::new( + move |_, edge: &RSlabel| + format!("{}", + translator::RSsetDisplay::from( + &translator, + &mask.intersection(&edge.t) + ) + ) + ) + }, + Difference => { + Box::new( + move |_, edge: &RSlabel| + format!("{}", + translator::RSsetDisplay::from( + &translator, + &edge.context.subtraction( + &edge.available_entities + ) + ) + ) + ) + }, + MaskDifference { mask } => { + Box::new( + move |_, edge: &RSlabel| + format!("{}", + translator::RSsetDisplay::from( + &translator, + &mask.intersection( + &edge.context.subtraction( + &edge.available_entities + ) + ) + ) + ) + ) + }, + EntitiesDeleted => { + Box::new( + move |_, edge: &RSlabel| + format!("{}", + translator::RSsetDisplay::from( + &translator, + &edge.available_entities.subtraction( + &edge.products + ) + ) + ) + ) + }, + MaskEntitiesDeleted { mask } => { + Box::new( + move |_, edge: &RSlabel| + format!("{}", + translator::RSsetDisplay::from( + &translator, + &mask.intersection( + &edge.available_entities.subtraction( + &edge.products + ) + ) + ) + ) + ) + }, + EntitiesAdded => { + Box::new( + move |_, edge: &RSlabel| + format!("{}", + translator::RSsetDisplay::from( + &translator, + &edge.products.subtraction( + &edge.available_entities + ) + ) + ) + ) + }, + MaskEntitiesAdded { mask } => { + Box::new( + move |_, edge: &RSlabel| + format!("{}", + translator::RSsetDisplay::from( + &translator, + &mask.intersection( + &edge.products.subtraction( + &edge.available_entities + ) + ) + ) + ) + ) + }, + }; + GraphMapEdgesTy { function } + } + + pub fn get(&self) -> &GraphMapEdgesFnTy { + &self.function + } +} diff --git a/src/rsprocess/structure.rs b/src/rsprocess/structure.rs index 077dde1..88b0817 100644 --- a/src/rsprocess/structure.rs +++ b/src/rsprocess/structure.rs @@ -67,6 +67,7 @@ impl RSset { } } + /// returns the new set a \cap b pub fn intersection(&self, b: &RSset) -> RSset { // TODO maybe find more efficient way without copy/clone let res: BTreeSet<_> = b @@ -77,6 +78,7 @@ impl RSset { RSset { identifiers: res } } + /// returns the new set a - b pub fn subtraction(&self, b: &RSset) -> RSset { // TODO maybe find more efficient way without copy/clone let res: BTreeSet<_> = self