Removing Unnecessary structures for edge display in dot and graphml

This commit is contained in:
elvis
2025-07-27 14:59:35 +02:00
parent 9ee0c94e28
commit 7fcaa5c13b
3 changed files with 140 additions and 222 deletions

View File

@ -266,11 +266,11 @@ LiteralSeparatorNode: graph::NodeDisplayBase = {
};
/// Match for strings between edge formatters
LiteralSeparatorEdge: presets::EdgeDisplay = {
LiteralSeparatorEdge: graph::EdgeDisplayBase = {
PATH =>
presets::EdgeDisplay::Separator(
<>.trim_end_matches("\"").trim_start_matches("\"").to_string()
)
graph::EdgeDisplayBase::String {
string: <>.trim_end_matches("\"").trim_start_matches("\"").to_string()
}
};
NodeDisplayBase: graph::NodeDisplayBase = {
@ -317,80 +317,50 @@ SeparatorNode: graph::NodeDisplay = {
}
}
EdgeDisplay: presets::EdgeDisplay = {
EdgeDisplay: graph::EdgeDisplayBase = {
"Hide" =>
presets::EdgeDisplay::Display(
graph::GraphMapEdges::Hide
),
graph::EdgeDisplayBase::Hide,
"Products" =>
presets::EdgeDisplay::Display(
graph::GraphMapEdges::Products
),
graph::EdgeDisplayBase::Products,
"MaskProducts" <mask: Set> =>
presets::EdgeDisplay::Display(
graph::GraphMapEdges::MaskEntities{ mask }
),
graph::EdgeDisplayBase::MaskEntities{ mask },
"Entities" =>
presets::EdgeDisplay::Display(
graph::GraphMapEdges::Entities
),
graph::EdgeDisplayBase::Entities,
"MaskEntities" <mask: Set> =>
presets::EdgeDisplay::Display(
graph::GraphMapEdges::MaskEntities{ mask }
),
graph::EdgeDisplayBase::MaskEntities{ mask },
"Context" =>
presets::EdgeDisplay::Display(
graph::GraphMapEdges::Context
),
graph::EdgeDisplayBase::Context,
"MaskContext" <mask: Set> =>
presets::EdgeDisplay::Display(
graph::GraphMapEdges::MaskContext{ mask }
),
graph::EdgeDisplayBase::MaskContext{ mask },
"Union" =>
presets::EdgeDisplay::Display(
graph::GraphMapEdges::Union
),
graph::EdgeDisplayBase::Union,
"MaskUnion" <mask: Set> =>
presets::EdgeDisplay::Display(
graph::GraphMapEdges::MaskUnion{ mask }
),
graph::EdgeDisplayBase::MaskUnion{ mask },
"Difference" =>
presets::EdgeDisplay::Display(
graph::GraphMapEdges::Difference
),
graph::EdgeDisplayBase::Difference,
"MaskDifference" <mask: Set> =>
presets::EdgeDisplay::Display(
graph::GraphMapEdges::MaskDifference{ mask }
),
graph::EdgeDisplayBase::MaskDifference{ mask },
"EntitiesDeleted" =>
presets::EdgeDisplay::Display(
graph::GraphMapEdges::EntitiesDeleted
),
graph::EdgeDisplayBase::EntitiesDeleted,
"MaskEntitiesDeleted" <mask: Set> =>
presets::EdgeDisplay::Display(
graph::GraphMapEdges::MaskEntitiesDeleted{ mask }
),
graph::EdgeDisplayBase::MaskEntitiesDeleted{ mask },
"EntitiesAdded" =>
presets::EdgeDisplay::Display(
graph::GraphMapEdges::EntitiesAdded
),
graph::EdgeDisplayBase::EntitiesAdded,
"MaskEntitiesAdded" <mask: Set> =>
presets::EdgeDisplay::Display(
graph::GraphMapEdges::MaskEntitiesAdded{ mask }
),
graph::EdgeDisplayBase::MaskEntitiesAdded{ mask },
}
/// Edge display formatters separated by arbitrary strings in quotes
SeparatorEdge: Vec<presets::EdgeDisplay> = {
<v: EdgeDisplay> => vec![v],
SeparatorEdge: graph::EdgeDisplay = {
<v: EdgeDisplay> => graph::EdgeDisplay{ base: vec![v] },
<v:(<EdgeDisplay> <LiteralSeparatorEdge>)+> <e: EdgeDisplay?> =>
match e {
None => v.iter().fold(vec![],
None => graph::EdgeDisplay{ base: v.iter().fold(vec![],
|mut acc, (a, b)| {
acc.push(a.clone());
acc.push(b.clone());
acc.clone()
}),
}) },
Some(e) => {
let mut v = v.iter().fold(vec![],
|mut acc, (a, b)| {
@ -399,7 +369,7 @@ SeparatorEdge: Vec<presets::EdgeDisplay> = {
acc.clone()
});
v.push(e);
v
graph::EdgeDisplay{ base: v }
}
}
}

View File

@ -157,7 +157,7 @@ impl NodeDisplay {
/// Helper structure that specifies what information to display for edges
#[derive(Clone)]
pub enum GraphMapEdges {
pub enum EdgeDisplayBase {
String { string: String },
Hide,
Products,
@ -176,136 +176,93 @@ pub enum GraphMapEdges {
MaskEntitiesAdded { mask: RSset },
}
pub struct EdgeDisplay {
pub base: Vec<EdgeDisplayBase>
}
type GraphMapEdgesFnTy<'a> =
dyn Fn(petgraph::prelude::EdgeIndex, &'a RSlabel) -> String + 'a;
/// Helper structure that holds a formatting function from node as RSsystem to
/// string
pub struct GraphMapEdgesTy<'a> {
functions: Vec<Box<GraphMapEdgesFnTy<'a>>>,
fn match_edge_display<'a>(
base: &'a EdgeDisplayBase,
translator: Rc<translator::Translator>
}
impl<'a, const N: usize> From<([GraphMapEdges; N], Rc<translator::Translator>)>
for GraphMapEdgesTy<'a>
{
fn from(value: ([GraphMapEdges; N], Rc<translator::Translator>)) -> Self {
Self::from((value.0.to_vec(), value.1))
}
}
impl<'a> From<(&[GraphMapEdges], Rc<translator::Translator>)>
for GraphMapEdgesTy<'a>
{
fn from(value: (&[GraphMapEdges], Rc<translator::Translator>)) -> Self {
Self::from((value.0.to_vec(), value.1))
}
}
impl<'a> From<(Vec<GraphMapEdges>, Rc<translator::Translator>)>
for GraphMapEdgesTy<'a>
{
fn from(value: (Vec<GraphMapEdges>, Rc<translator::Translator>)) -> Self {
use GraphMapEdges::*;
) -> Box<GraphMapEdgesFnTy<'a>> {
use EdgeDisplayBase::*;
use super::format_helpers::graph_map_edges_ty_from::*;
let mut new = GraphMapEdgesTy {functions: vec![], translator: value.1};
for f in value.0 {
match f {
match base {
String { string } => {
new.functions.push(format_string(
Rc::clone(&new.translator), string))
format_string(translator, string.clone())
}
Hide => {
new.functions.push(format_hide(
Rc::clone(&new.translator)
))
format_hide(translator)
},
Products => {
new.functions.push(format_products(
Rc::clone(&new.translator)
))
format_products(translator)
},
MaskProducts { mask } => {
new.functions.push(format_mask_products(
Rc::clone(&new.translator), mask))
format_mask_products(translator, mask.clone())
},
Entities => {
new.functions.push(format_entities(
Rc::clone(&new.translator)
))
format_entities(translator)
},
MaskEntities { mask } => {
new.functions.push(format_mask_entities(
Rc::clone(&new.translator), mask))
format_mask_entities(translator, mask.clone())
},
Context => {
new.functions.push(format_context(
Rc::clone(&new.translator)
))
format_context(translator)
},
MaskContext { mask } => {
new.functions.push(format_mask_context(
Rc::clone(&new.translator), mask))
format_mask_context(translator, mask.clone())
},
Union => {
new.functions.push(format_union(
Rc::clone(&new.translator)
))
format_union(translator)
},
MaskUnion { mask } => {
new.functions.push(format_mask_union(
Rc::clone(&new.translator), mask))
format_mask_union(translator, mask.clone())
},
Difference => {
new.functions.push(format_difference(
Rc::clone(&new.translator)
))
format_difference(translator)
},
MaskDifference { mask } => {
new.functions.push(format_mask_difference(
Rc::clone(&new.translator), mask))
format_mask_difference(translator, mask.clone())
},
EntitiesDeleted => {
new.functions.push(format_entities_deleted(
Rc::clone(&new.translator)
))
format_entities_deleted(translator)
},
MaskEntitiesDeleted { mask } => {
new.functions.push(format_mask_entities_deleted(
Rc::clone(&new.translator), mask))
format_mask_entities_deleted(translator, mask.clone())
},
EntitiesAdded => {
new.functions.push(format_entities_added(
Rc::clone(&new.translator)
))
format_entities_added(translator)
},
MaskEntitiesAdded { mask } => {
new.functions.push(format_mask_entities_added(
Rc::clone(&new.translator), mask))
format_mask_entities_added(translator, mask.clone())
},
};
}
new
}
}
impl<'a> GraphMapEdgesTy<'a> {
pub fn generate(self) -> Box<GraphMapEdgesFnTy<'a>> {
let mut accumulator: Box<GraphMapEdgesFnTy<'a>> =
super::format_helpers::graph_map_edges_ty_from::format_hide(
Rc::clone(&self.translator)
);
for f in self.functions {
accumulator = Box::new(move |i, n| {
(accumulator)(i, n)
+ &f(i, n)
})
}
impl EdgeDisplay {
pub fn generate<'a>(
self,
translator: Rc<translator::Translator>,
_current_graph: &RSgraph
) -> Box<GraphMapEdgesFnTy<'a>> {
Box::new(
move |i, n| {
let mut accumulator = String::new();
for b in &self.base {
let f = match_edge_display(b,
Rc::clone(&translator));
accumulator.push_str(&(f)(i, n));
}
accumulator
}
)
}
}
// -----------------------------------------------------------------------------

View File

@ -13,7 +13,6 @@ use lalrpop_util::ParseError;
// the code
use crate::grammar;
use super::structure::RSlabel;
use super::structure::{RSset, RSsystem};
use super::translator::Translator;
use super::*;
@ -58,25 +57,18 @@ impl Default for SaveOptions {
}
}
// Describes display options for edges (RSlabels).
#[derive(Clone)]
pub enum EdgeDisplay {
Separator(String),
Display(graph::GraphMapEdges),
}
// Describes output options for a graph.
pub enum GraphSaveOptions {
Dot {
node_display: graph::NodeDisplay,
edge_display: Vec<EdgeDisplay>,
edge_display: graph::EdgeDisplay,
node_color: graph::NodeColor,
edge_color: graph::EdgeColor,
so: SaveOptions,
},
GraphML {
node_display: graph::NodeDisplay,
edge_display: Vec<EdgeDisplay>,
edge_display: graph::EdgeDisplay,
so: SaveOptions,
},
Serialize {
@ -554,41 +546,41 @@ pub fn bisimilar(
// Output Functions
// -----------------------------------------------------------------------------
type GraphMapEdgesFnTy<'a> =
dyn Fn(petgraph::prelude::EdgeIndex, &'a RSlabel) -> String + 'a;
fn generate_edge_printing_fn<'a>(
edge_display: &[EdgeDisplay],
translator: Rc<Translator>,
) -> Box<GraphMapEdgesFnTy<'a>> {
// The type cannot be aliased since rust doesnt like generics.
// We are iterating over the edge_display and constructing a function
// (accumulator) that prints out our formatted nodes. So at each step we
// call the previous function and add the next string or function.
let edge_display = edge_display.iter().map(
|e| {
match e {
EdgeDisplay::Display(d) => {
d.clone()
},
EdgeDisplay::Separator(s) => {
graph::GraphMapEdges::String { string: s.clone() }
}
}
}
).collect::<Vec<_>>();
// type GraphMapEdgesFnTy<'a> =
// dyn Fn(petgraph::prelude::EdgeIndex, &'a RSlabel) -> String + 'a;
// fn generate_edge_printing_fn<'a>(
// edge_display: graph::EdgeDisplay,
// translator: Rc<Translator>,
// ) -> Box<GraphMapEdgesFnTy<'a>> {
// // The type cannot be aliased since rust doesnt like generics.
// // We are iterating over the edge_display and constructing a function
// // (accumulator) that prints out our formatted nodes. So at each step we
// // call the previous function and add the next string or function.
// let edge_display = edge_display.iter().map(
// |e| {
// match e {
// EdgeDisplay::Display(d) => {
// d.clone()
// },
// EdgeDisplay::Separator(s) => {
// graph::EdgeDisplayBase::String { string: s.clone() }
// }
// }
// }
// ).collect::<Vec<_>>();
let gmet = graph::GraphMapEdgesTy::from(
(edge_display, Rc::clone(&translator))
);
// let gmet = graph::GraphMapEdgesTy::from(
// (edge_display, Rc::clone(&translator))
// );
gmet.generate()
}
// gmet.generate()
// }
/// Writes the specified graph to a file in .dot format.
pub fn dot(
system: &EvaluatedSystem,
node_display: graph::NodeDisplay,
edge_display: Vec<EdgeDisplay>,
edge_display: graph::EdgeDisplay,
node_color: graph::NodeColor,
edge_color: graph::EdgeColor
) -> Result<String, String> {
@ -601,8 +593,7 @@ pub fn dot(
let rc_translator = Rc::new(translator.clone());
let modified_graph = graph.map(
node_display.generate(Rc::clone(&rc_translator), graph),
generate_edge_printing_fn(&edge_display,
Rc::clone(&rc_translator)),
edge_display.generate(Rc::clone(&rc_translator), graph),
);
let graph = Rc::new(graph.to_owned());
@ -629,7 +620,7 @@ pub fn dot(
pub fn graphml(
system: &EvaluatedSystem,
node_display: graph::NodeDisplay,
edge_display: Vec<EdgeDisplay>,
edge_display: graph::EdgeDisplay,
) -> Result<String, String> {
match system {
EvaluatedSystem::System {
@ -643,8 +634,8 @@ pub fn graphml(
let modified_graph = graph.map(
node_display.generate(Rc::clone(&rc_translator),
graph),
generate_edge_printing_fn(&edge_display,
rc_translator),
edge_display.generate(rc_translator,
graph),
);
use petgraph_graphml::GraphMl;