Useful graph presets
This commit is contained in:
@ -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));
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user