Useful graph presets

This commit is contained in:
elvis
2025-07-07 01:25:38 +02:00
parent ad1ef6f6a6
commit cdf3d23243
3 changed files with 329 additions and 5 deletions

View File

@ -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<GraphMapNodesFnTy>
}
impl GraphMapNodesTy {
pub fn from(
f: GraphMapNodes,
translator: Rc<translator::Translator>
) -> Self {
use GraphMapNodes::*;
let function: Box<GraphMapNodesFnTy> =
// 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<GraphMapNodesTy> for Box<GraphMapNodesFnTy> {
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<GraphMapEdgesFnTy>
}
impl GraphMapEdgesTy {
pub fn from(
f: GraphMapEdges,
translator: Rc<translator::Translator>
) -> Self {
use GraphMapEdges::*;
let function: Box<GraphMapEdgesFnTy> =
// 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
}
}

View File

@ -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