Removed unnecessary middle struct for node formatting
This commit is contained in:
@ -256,11 +256,13 @@ SaveOptions: presets::SaveOptions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Match for strings between nodes formatters
|
/// Match for strings between nodes formatters
|
||||||
LiteralSeparatorNode: presets::NodeDisplay = {
|
LiteralSeparatorNode: graph::NodeDisplayBase = {
|
||||||
PATH =>
|
PATH =>
|
||||||
presets::NodeDisplay::Separator(
|
graph::NodeDisplayBase::String {
|
||||||
<>.trim_end_matches("\"").trim_start_matches("\"").to_string()
|
string: <>.trim_end_matches("\"")
|
||||||
)
|
.trim_start_matches("\"")
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Match for strings between edge formatters
|
/// Match for strings between edge formatters
|
||||||
@ -271,34 +273,37 @@ LiteralSeparatorEdge: presets::EdgeDisplay = {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
NodeDisplay: presets::NodeDisplay = {
|
NodeDisplayBase: graph::NodeDisplayBase = {
|
||||||
"Hide" =>
|
"Hide" =>
|
||||||
presets::NodeDisplay::Display(graph::GraphMapNodes::Hide),
|
graph::NodeDisplayBase::Hide,
|
||||||
"Entities" =>
|
"Entities" =>
|
||||||
presets::NodeDisplay::Display(graph::GraphMapNodes::Entities),
|
graph::NodeDisplayBase::Entities,
|
||||||
"MaskEntities" <mask: Set> =>
|
"MaskEntities" <mask: Set> =>
|
||||||
presets::NodeDisplay::Display(graph::GraphMapNodes::MaskEntities{mask}),
|
graph::NodeDisplayBase::MaskEntities{mask},
|
||||||
"Context" =>
|
|
||||||
presets::NodeDisplay::Display(graph::GraphMapNodes::Context),
|
|
||||||
"UncommonEntities" =>
|
|
||||||
presets::NodeDisplay::UncommonEntities,
|
|
||||||
"MaskUncommonentities" <mask: Set> =>
|
|
||||||
presets::NodeDisplay::MaskUncommonEntities(mask),
|
|
||||||
"ExcludeEntities" <mask: Set> =>
|
"ExcludeEntities" <mask: Set> =>
|
||||||
presets::NodeDisplay::Display(graph::GraphMapNodes::ExcludeEntities{mask})
|
graph::NodeDisplayBase::ExcludeEntities{mask},
|
||||||
|
"Context" =>
|
||||||
|
graph::NodeDisplayBase::Context,
|
||||||
|
"UncommonEntities" =>
|
||||||
|
graph::NodeDisplayBase::UncommonEntities,
|
||||||
|
"MaskUncommonentities" <mask: Set> =>
|
||||||
|
graph::NodeDisplayBase::MaskUncommonEntities{mask},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Node display formatters separated by arbitrary strings in quotes
|
/// Node display formatters separated by arbitrary strings in quotes
|
||||||
SeparatorNode: Vec<presets::NodeDisplay> = {
|
SeparatorNode: graph::NodeDisplay = {
|
||||||
<v: NodeDisplay> => vec![v],
|
<v: NodeDisplayBase> => graph::NodeDisplay {base: vec![v]},
|
||||||
<v:(<NodeDisplay> <LiteralSeparatorNode>)+> <e: NodeDisplay?> =>
|
<v:(<NodeDisplayBase> <LiteralSeparatorNode>)+> <e: NodeDisplayBase?> =>
|
||||||
match e {
|
match e {
|
||||||
None => v.iter().fold(vec![],
|
None => graph::NodeDisplay {
|
||||||
|
base:
|
||||||
|
v.iter().fold(vec![],
|
||||||
|mut acc, (a, b)| {
|
|mut acc, (a, b)| {
|
||||||
acc.push(a.clone());
|
acc.push(a.clone());
|
||||||
acc.push(b.clone());
|
acc.push(b.clone());
|
||||||
acc.clone()
|
acc.clone()
|
||||||
}),
|
})
|
||||||
|
},
|
||||||
Some(e) => {
|
Some(e) => {
|
||||||
let mut v = v.iter().fold(vec![],
|
let mut v = v.iter().fold(vec![],
|
||||||
|mut acc, (a, b)| {
|
|mut acc, (a, b)| {
|
||||||
@ -307,7 +312,7 @@ SeparatorNode: Vec<presets::NodeDisplay> = {
|
|||||||
acc.clone()
|
acc.clone()
|
||||||
});
|
});
|
||||||
v.push(e);
|
v.push(e);
|
||||||
v
|
graph::NodeDisplay { base: v }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,12 +21,9 @@ pub fn digraph(
|
|||||||
association.insert(system.clone(), node);
|
association.insert(system.clone(), node);
|
||||||
|
|
||||||
let mut stack = vec![system];
|
let mut stack = vec![system];
|
||||||
let mut current;
|
|
||||||
|
|
||||||
|
while let Some(current) = stack.pop() {
|
||||||
while !stack.is_empty() {
|
|
||||||
// depth first
|
// depth first
|
||||||
current = stack.pop().unwrap();
|
|
||||||
let current_node = *association.get(¤t).unwrap();
|
let current_node = *association.get(¤t).unwrap();
|
||||||
|
|
||||||
for (label, next) in TransitionsIterator::from(¤t)? {
|
for (label, next) in TransitionsIterator::from(¤t)? {
|
||||||
@ -62,97 +59,97 @@ pub fn common_entities(graph: &RSgraph) -> RSset {
|
|||||||
|
|
||||||
/// Helper structure that specifies what information to display for nodes.
|
/// Helper structure that specifies what information to display for nodes.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum GraphMapNodes {
|
pub enum NodeDisplayBase {
|
||||||
String { string: String },
|
String { string: String },
|
||||||
Hide,
|
Hide,
|
||||||
Entities,
|
Entities,
|
||||||
MaskEntities { mask: RSset },
|
MaskEntities { mask: RSset },
|
||||||
ExcludeEntities { mask: RSset },
|
ExcludeEntities { mask: RSset },
|
||||||
Context,
|
Context,
|
||||||
|
UncommonEntities,
|
||||||
|
MaskUncommonEntities { mask: RSset }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NodeDisplay {
|
||||||
|
pub base: Vec<NodeDisplayBase>
|
||||||
}
|
}
|
||||||
|
|
||||||
type GraphMapNodesFnTy<'a> =
|
type GraphMapNodesFnTy<'a> =
|
||||||
dyn Fn(petgraph::prelude::NodeIndex, &'a RSsystem) -> String + 'a;
|
dyn Fn(petgraph::prelude::NodeIndex, &'a RSsystem) -> String + 'a;
|
||||||
/// Helper structure that holds a formatting function from node as RSsystem to
|
|
||||||
/// string
|
|
||||||
pub struct GraphMapNodesTy<'a> {
|
fn match_node_display<'a>(
|
||||||
functions: Vec<Box<GraphMapNodesFnTy<'a>>>,
|
base: &NodeDisplayBase,
|
||||||
|
common_entities: Rc<RSset>,
|
||||||
translator: Rc<translator::Translator>
|
translator: Rc<translator::Translator>
|
||||||
}
|
) -> Box<GraphMapNodesFnTy<'a>> {
|
||||||
|
use NodeDisplayBase::*;
|
||||||
impl<'a, const N: usize> From<([GraphMapNodes; N], Rc<translator::Translator>)> for GraphMapNodesTy<'a> {
|
|
||||||
fn from(value: ([GraphMapNodes; N], Rc<translator::Translator>)) -> Self {
|
|
||||||
Self::from((value.0.to_vec(), value.1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<(&[GraphMapNodes], Rc<translator::Translator>)> for GraphMapNodesTy<'a> {
|
|
||||||
fn from(value: (&[GraphMapNodes], Rc<translator::Translator>)) -> Self {
|
|
||||||
Self::from((value.0.to_vec(), value.1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<(Vec<GraphMapNodes>, Rc<translator::Translator>)> for GraphMapNodesTy<'a> {
|
|
||||||
fn from(value: (Vec<GraphMapNodes>, Rc<translator::Translator>)) -> Self {
|
|
||||||
use GraphMapNodes::*;
|
|
||||||
use super::format_helpers::graph_map_nodes_ty_from::*;
|
use super::format_helpers::graph_map_nodes_ty_from::*;
|
||||||
|
|
||||||
let mut new = GraphMapNodesTy {functions: vec![], translator: value.1};
|
match base {
|
||||||
|
|
||||||
for f in value.0 {
|
|
||||||
match f {
|
|
||||||
String { string } => {
|
String { string } => {
|
||||||
new.functions.push(format_string(string.clone()));
|
format_string(string.clone())
|
||||||
}
|
},
|
||||||
Hide => {
|
Hide => {
|
||||||
new.functions.push(format_hide(
|
format_hide(translator)
|
||||||
Rc::clone(&new.translator)
|
|
||||||
));
|
|
||||||
},
|
},
|
||||||
Entities => {
|
Entities => {
|
||||||
new.functions.push(format_entities(
|
format_entities(translator)
|
||||||
Rc::clone(&new.translator)
|
|
||||||
));
|
|
||||||
},
|
},
|
||||||
MaskEntities { mask } => {
|
MaskEntities { mask } => {
|
||||||
new.functions.push(format_mask_entities(
|
format_mask_entities(translator, mask.clone())
|
||||||
Rc::clone(&new.translator),
|
|
||||||
mask.clone()
|
|
||||||
));
|
|
||||||
},
|
},
|
||||||
ExcludeEntities { mask } => {
|
ExcludeEntities { mask } => {
|
||||||
new.functions.push(format_exclude_entities(
|
format_exclude_entities(translator, mask.clone())
|
||||||
Rc::clone(&new.translator),
|
|
||||||
mask.clone()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
Context => {
|
|
||||||
new.functions.push(format_context(
|
|
||||||
Rc::clone(&new.translator)
|
|
||||||
));
|
|
||||||
},
|
},
|
||||||
|
Context => {
|
||||||
|
format_context(translator)
|
||||||
|
},
|
||||||
|
UncommonEntities => {
|
||||||
|
format_exclude_entities(translator, (*common_entities).clone())
|
||||||
|
},
|
||||||
|
MaskUncommonEntities { mask } => {
|
||||||
|
format_exclude_entities(translator,
|
||||||
|
mask.intersection(&common_entities))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl NodeDisplay {
|
||||||
|
fn contains_uncommon(&self) -> bool {
|
||||||
|
self.base.iter().any(
|
||||||
|
|b|
|
||||||
|
matches!(b, NodeDisplayBase::UncommonEntities |
|
||||||
|
NodeDisplayBase::MaskUncommonEntities { mask: _ }))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate<'a>(
|
||||||
|
self,
|
||||||
|
translator: Rc<translator::Translator>,
|
||||||
|
current_graph: &RSgraph
|
||||||
|
) -> Box<GraphMapNodesFnTy<'a>> {
|
||||||
|
let common_entities =
|
||||||
|
if self.contains_uncommon() {
|
||||||
|
Rc::new(common_entities(current_graph))
|
||||||
|
} else {
|
||||||
|
Rc::new(RSset::new())
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
new
|
Box::new(
|
||||||
}
|
move |i, n| {
|
||||||
}
|
let mut accumulator = String::new();
|
||||||
|
for b in &self.base {
|
||||||
|
let f = match_node_display(b,
|
||||||
|
Rc::clone(&common_entities),
|
||||||
|
Rc::clone(&translator));
|
||||||
|
|
||||||
impl<'a> GraphMapNodesTy<'a> {
|
accumulator.push_str(&(f)(i, n));
|
||||||
pub fn generate(self) -> Box<GraphMapNodesFnTy<'a>> {
|
|
||||||
let mut accumulator: Box<GraphMapNodesFnTy<'a>> =
|
|
||||||
super::format_helpers::graph_map_nodes_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)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
accumulator
|
accumulator
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -188,19 +185,25 @@ pub struct GraphMapEdgesTy<'a> {
|
|||||||
translator: Rc<translator::Translator>
|
translator: Rc<translator::Translator>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, const N: usize> From<([GraphMapEdges; N], Rc<translator::Translator>)> for GraphMapEdgesTy<'a> {
|
impl<'a, const N: usize> From<([GraphMapEdges; N], Rc<translator::Translator>)>
|
||||||
|
for GraphMapEdgesTy<'a>
|
||||||
|
{
|
||||||
fn from(value: ([GraphMapEdges; N], Rc<translator::Translator>)) -> Self {
|
fn from(value: ([GraphMapEdges; N], Rc<translator::Translator>)) -> Self {
|
||||||
Self::from((value.0.to_vec(), value.1))
|
Self::from((value.0.to_vec(), value.1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<(&[GraphMapEdges], Rc<translator::Translator>)> for GraphMapEdgesTy<'a> {
|
impl<'a> From<(&[GraphMapEdges], Rc<translator::Translator>)>
|
||||||
|
for GraphMapEdgesTy<'a>
|
||||||
|
{
|
||||||
fn from(value: (&[GraphMapEdges], Rc<translator::Translator>)) -> Self {
|
fn from(value: (&[GraphMapEdges], Rc<translator::Translator>)) -> Self {
|
||||||
Self::from((value.0.to_vec(), value.1))
|
Self::from((value.0.to_vec(), value.1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<(Vec<GraphMapEdges>, Rc<translator::Translator>)> for GraphMapEdgesTy<'a> {
|
impl<'a> From<(Vec<GraphMapEdges>, Rc<translator::Translator>)>
|
||||||
|
for GraphMapEdgesTy<'a>
|
||||||
|
{
|
||||||
fn from(value: (Vec<GraphMapEdges>, Rc<translator::Translator>)) -> Self {
|
fn from(value: (Vec<GraphMapEdges>, Rc<translator::Translator>)) -> Self {
|
||||||
use GraphMapEdges::*;
|
use GraphMapEdges::*;
|
||||||
use super::format_helpers::graph_map_edges_ty_from::*;
|
use super::format_helpers::graph_map_edges_ty_from::*;
|
||||||
|
|||||||
@ -58,15 +58,6 @@ impl Default for SaveOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Describes display options for nodes (RSsystem).
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum NodeDisplay {
|
|
||||||
Separator(String),
|
|
||||||
Display(graph::GraphMapNodes),
|
|
||||||
UncommonEntities,
|
|
||||||
MaskUncommonEntities(RSset)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Describes display options for edges (RSlabels).
|
// Describes display options for edges (RSlabels).
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum EdgeDisplay {
|
pub enum EdgeDisplay {
|
||||||
@ -77,14 +68,14 @@ pub enum EdgeDisplay {
|
|||||||
// Describes output options for a graph.
|
// Describes output options for a graph.
|
||||||
pub enum GraphSaveOptions {
|
pub enum GraphSaveOptions {
|
||||||
Dot {
|
Dot {
|
||||||
node_display: Vec<NodeDisplay>,
|
node_display: graph::NodeDisplay,
|
||||||
edge_display: Vec<EdgeDisplay>,
|
edge_display: Vec<EdgeDisplay>,
|
||||||
node_color: graph::NodeColor,
|
node_color: graph::NodeColor,
|
||||||
edge_color: graph::EdgeColor,
|
edge_color: graph::EdgeColor,
|
||||||
so: SaveOptions,
|
so: SaveOptions,
|
||||||
},
|
},
|
||||||
GraphML {
|
GraphML {
|
||||||
node_display: Vec<NodeDisplay>,
|
node_display: graph::NodeDisplay,
|
||||||
edge_display: Vec<EdgeDisplay>,
|
edge_display: Vec<EdgeDisplay>,
|
||||||
so: SaveOptions,
|
so: SaveOptions,
|
||||||
},
|
},
|
||||||
@ -563,49 +554,6 @@ pub fn bisimilar(
|
|||||||
// Output Functions
|
// Output Functions
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
type GraphMapNodesFnTy<'a> =
|
|
||||||
dyn Fn(petgraph::prelude::NodeIndex, &'a RSsystem) -> String + 'a;
|
|
||||||
fn generate_node_printing_fn<'a>(
|
|
||||||
node_display: &[NodeDisplay],
|
|
||||||
graph: &graph::RSgraph,
|
|
||||||
translator: Rc<Translator>,
|
|
||||||
) -> Box<GraphMapNodesFnTy<'a>> {
|
|
||||||
// The type cannot be aliased since rust doesnt like generics.
|
|
||||||
// We are iterating over the node_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 node_display = node_display.iter().map(
|
|
||||||
|e|
|
|
||||||
match e {
|
|
||||||
NodeDisplay::Display(d) => d.clone(),
|
|
||||||
NodeDisplay::Separator(s) => {
|
|
||||||
graph::GraphMapNodes::String {
|
|
||||||
string: s.clone()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
NodeDisplay::UncommonEntities => {
|
|
||||||
let common_entities = graph::common_entities(graph);
|
|
||||||
graph::GraphMapNodes::ExcludeEntities {
|
|
||||||
mask: common_entities.clone()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
NodeDisplay::MaskUncommonEntities(mask) => {
|
|
||||||
let common_entities = graph::common_entities(graph);
|
|
||||||
graph::GraphMapNodes::ExcludeEntities {
|
|
||||||
mask: common_entities.union(mask)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
).collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let gmnt = graph::GraphMapNodesTy::from(
|
|
||||||
(node_display, Rc::clone(&translator))
|
|
||||||
);
|
|
||||||
|
|
||||||
gmnt.generate()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
type GraphMapEdgesFnTy<'a> =
|
type GraphMapEdgesFnTy<'a> =
|
||||||
dyn Fn(petgraph::prelude::EdgeIndex, &'a RSlabel) -> String + 'a;
|
dyn Fn(petgraph::prelude::EdgeIndex, &'a RSlabel) -> String + 'a;
|
||||||
fn generate_edge_printing_fn<'a>(
|
fn generate_edge_printing_fn<'a>(
|
||||||
@ -639,7 +587,7 @@ fn generate_edge_printing_fn<'a>(
|
|||||||
/// Writes the specified graph to a file in .dot format.
|
/// Writes the specified graph to a file in .dot format.
|
||||||
pub fn dot(
|
pub fn dot(
|
||||||
system: &EvaluatedSystem,
|
system: &EvaluatedSystem,
|
||||||
node_display: Vec<NodeDisplay>,
|
node_display: graph::NodeDisplay,
|
||||||
edge_display: Vec<EdgeDisplay>,
|
edge_display: Vec<EdgeDisplay>,
|
||||||
node_color: graph::NodeColor,
|
node_color: graph::NodeColor,
|
||||||
edge_color: graph::EdgeColor
|
edge_color: graph::EdgeColor
|
||||||
@ -651,13 +599,8 @@ pub fn dot(
|
|||||||
} => Err("Supplied system is not a graph".into()),
|
} => Err("Supplied system is not a graph".into()),
|
||||||
EvaluatedSystem::Graph { graph, translator } => {
|
EvaluatedSystem::Graph { graph, translator } => {
|
||||||
let rc_translator = Rc::new(translator.clone());
|
let rc_translator = Rc::new(translator.clone());
|
||||||
// map each value to the corresponding value we want to display
|
|
||||||
// this is awful but rust is not a functional language so its all
|
|
||||||
// fine...
|
|
||||||
let modified_graph = graph.map(
|
let modified_graph = graph.map(
|
||||||
generate_node_printing_fn(&node_display,
|
node_display.generate(Rc::clone(&rc_translator), graph),
|
||||||
graph,
|
|
||||||
Rc::clone(&rc_translator)),
|
|
||||||
generate_edge_printing_fn(&edge_display,
|
generate_edge_printing_fn(&edge_display,
|
||||||
Rc::clone(&rc_translator)),
|
Rc::clone(&rc_translator)),
|
||||||
);
|
);
|
||||||
@ -685,7 +628,7 @@ pub fn dot(
|
|||||||
/// Writes the specified graph to a file in .graphml format.
|
/// Writes the specified graph to a file in .graphml format.
|
||||||
pub fn graphml(
|
pub fn graphml(
|
||||||
system: &EvaluatedSystem,
|
system: &EvaluatedSystem,
|
||||||
node_display: Vec<NodeDisplay>,
|
node_display: graph::NodeDisplay,
|
||||||
edge_display: Vec<EdgeDisplay>,
|
edge_display: Vec<EdgeDisplay>,
|
||||||
) -> Result<String, String> {
|
) -> Result<String, String> {
|
||||||
match system {
|
match system {
|
||||||
@ -698,9 +641,8 @@ pub fn graphml(
|
|||||||
|
|
||||||
// map each value to the corresponding value we want to display
|
// map each value to the corresponding value we want to display
|
||||||
let modified_graph = graph.map(
|
let modified_graph = graph.map(
|
||||||
generate_node_printing_fn(&node_display,
|
node_display.generate(Rc::clone(&rc_translator),
|
||||||
graph,
|
graph),
|
||||||
Rc::clone(&rc_translator)),
|
|
||||||
generate_edge_printing_fn(&edge_display,
|
generate_edge_printing_fn(&edge_display,
|
||||||
rc_translator),
|
rc_translator),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user