Working formatting of weights for nodes and edges
This commit is contained in:
@ -1,11 +1,12 @@
|
||||
use reactionsystems::rsprocess::presets;
|
||||
|
||||
fn main() {
|
||||
// let now = std::time::Instant::now();
|
||||
// println!("{}", now.elapsed().as_micros());
|
||||
let now = std::time::Instant::now();
|
||||
|
||||
match presets::run("testing/first.system".into()) {
|
||||
Ok(_) => {},
|
||||
Err(e) => {println!("{e}")}
|
||||
}
|
||||
|
||||
println!("{} milliseconds elapsed", now.elapsed().as_millis());
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ use crate::rsprocess::structure::{RSset,
|
||||
use crate::rsprocess::translator::{Translator, IdType};
|
||||
use crate::rsprocess::presets::Instructions;
|
||||
use crate::rsprocess::presets;
|
||||
use crate::rsprocess::graph;
|
||||
|
||||
grammar(translator: &mut Translator);
|
||||
|
||||
@ -37,12 +38,17 @@ match {
|
||||
"Dot", "GraphML", "Serialize",
|
||||
"Stats", "Target", "Run", "Loop", "Frequency", "LimitFrequency",
|
||||
"FastFrequency", "Digraph",
|
||||
"Deserialize"
|
||||
"Deserialize",
|
||||
"Hide", "Entities", "MaskEntities", "MaskContext",
|
||||
"Products", "MaskProducts", "Union", "MaskUnion",
|
||||
"Difference", "MaskDifference",
|
||||
"EntitiesDeleted", "MaskEntitiesDeleted",
|
||||
"EntitiesAdded", "MaskEntitiesAdded"
|
||||
} else {
|
||||
r"[0-9]+" => NUMBER
|
||||
} else {
|
||||
// r"([[:alpha:]]|\p{Emoji})([[:word:]]|\p{Emoji})*" => WORD
|
||||
r"(\p{L}|\p{Emoji})(\p{L}|\p{Emoji}|\p{Dash}|\p{N})*" => WORD,
|
||||
r"([[:alpha:]])([[:word:]])*" => WORD
|
||||
// r"(\p{L}|\p{Emoji})(\p{L}|\p{Emoji}|\p{Dash}|\p{N})*" => WORD,
|
||||
} else {
|
||||
r#"".*""# => PATH,
|
||||
} else {
|
||||
@ -245,11 +251,86 @@ SaveOptions: presets::SaveOptions = {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LiteralSeparatorNode: presets::NodeDisplay = {
|
||||
PATH =>
|
||||
presets::NodeDisplay::Separator(
|
||||
<>.trim_end_matches("\"").trim_start_matches("\"").to_string()
|
||||
)
|
||||
};
|
||||
|
||||
LiteralSeparatorEdge: presets::EdgeDisplay = {
|
||||
PATH =>
|
||||
presets::EdgeDisplay::Separator(
|
||||
<>.trim_end_matches("\"").trim_start_matches("\"").to_string()
|
||||
)
|
||||
};
|
||||
|
||||
NodeDisplay: presets::NodeDisplay = {
|
||||
"Hide" => presets::NodeDisplay::Display(graph::GraphMapNodes::Hide),
|
||||
"Entities" => presets::NodeDisplay::Display(graph::GraphMapNodes::Entities),
|
||||
"MaskEntities" <mask: Set> =>
|
||||
presets::NodeDisplay::Display(graph::GraphMapNodes::MaskEntities{ mask }),
|
||||
"Context" => presets::NodeDisplay::Display(graph::GraphMapNodes::Context)
|
||||
}
|
||||
|
||||
SeparatorNode: Vec<presets::NodeDisplay> = {
|
||||
<v: NodeDisplay> => vec![v],
|
||||
<v:(<NodeDisplay> <LiteralSeparatorNode>)+> <e: NodeDisplay?> =>
|
||||
match e {
|
||||
None => 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)| {acc.push(a.clone()); acc.push(b.clone()); acc.clone()});
|
||||
v.push(e);
|
||||
v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EdgeDisplay: presets::EdgeDisplay = {
|
||||
"Hide" => presets::EdgeDisplay::Display(graph::GraphMapEdges::Hide),
|
||||
"Products" => presets::EdgeDisplay::Display(graph::GraphMapEdges::Products),
|
||||
"MaskProducts" <mask: Set> =>
|
||||
presets::EdgeDisplay::Display(graph::GraphMapEdges::MaskEntities{ mask }),
|
||||
"Entities" => presets::EdgeDisplay::Display(graph::GraphMapEdges::Entities),
|
||||
"MaskEntities" <mask: Set> => presets::EdgeDisplay::Display(graph::GraphMapEdges::MaskEntities{ mask }),
|
||||
"Context" => presets::EdgeDisplay::Display(graph::GraphMapEdges::Context),
|
||||
"MaskContext" <mask: Set> => presets::EdgeDisplay::Display(graph::GraphMapEdges::MaskContext{ mask }),
|
||||
"Union" => presets::EdgeDisplay::Display(graph::GraphMapEdges::Union),
|
||||
"MaskUnion" <mask: Set> => presets::EdgeDisplay::Display(graph::GraphMapEdges::MaskUnion{ mask }),
|
||||
"Difference" => presets::EdgeDisplay::Display(graph::GraphMapEdges::Difference),
|
||||
"MaskDifference" <mask: Set> => presets::EdgeDisplay::Display(graph::GraphMapEdges::MaskDifference{ mask }),
|
||||
"EntitiesDeleted" => presets::EdgeDisplay::Display(graph::GraphMapEdges::EntitiesDeleted),
|
||||
"MaskEntitiesDeleted" <mask: Set> => presets::EdgeDisplay::Display(graph::GraphMapEdges::MaskEntitiesDeleted{ mask }),
|
||||
"EntitiesAdded" => presets::EdgeDisplay::Display(graph::GraphMapEdges::EntitiesAdded),
|
||||
"MaskEntitiesAdded" <mask: Set> => presets::EdgeDisplay::Display(graph::GraphMapEdges::MaskEntitiesAdded{ mask }),
|
||||
}
|
||||
|
||||
SeparatorEdge: Vec<presets::EdgeDisplay> = {
|
||||
<v: EdgeDisplay> => vec![v],
|
||||
<v:(<EdgeDisplay> <LiteralSeparatorEdge>)+> <e: EdgeDisplay?> =>
|
||||
match e {
|
||||
None => 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)| {acc.push(a.clone()); acc.push(b.clone()); acc.clone()});
|
||||
v.push(e);
|
||||
v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GraphSaveOptions: presets::GraphSaveOptions = {
|
||||
"Dot" ">" <so: SaveOptions> =>
|
||||
presets::GraphSaveOptions::Dot { so },
|
||||
"GraphML" ">" <so: SaveOptions> =>
|
||||
presets::GraphSaveOptions::GraphML { so },
|
||||
"Dot" <s_node: SeparatorNode> "|" <s_edge: SeparatorEdge> ">"
|
||||
<so: SaveOptions> =>
|
||||
presets::GraphSaveOptions::Dot { node_display: s_node,
|
||||
edge_display: s_edge,
|
||||
so },
|
||||
"GraphML" <s_node: SeparatorNode> "|" <s_edge: SeparatorEdge> ">"
|
||||
<so: SaveOptions> =>
|
||||
presets::GraphSaveOptions::GraphML { node_display: s_node,
|
||||
edge_display: s_edge,
|
||||
so },
|
||||
"Serialize" "(" <path: Path> ")" =>
|
||||
presets::GraphSaveOptions::Serialize { path },
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ pub fn digraph(
|
||||
// Nodes -----------------------------------------------------------------------
|
||||
|
||||
/// Helper structure that specifies what information to display for nodes.
|
||||
#[derive(Clone)]
|
||||
pub enum GraphMapNodes {
|
||||
Hide,
|
||||
Entities,
|
||||
@ -55,7 +56,8 @@ pub enum GraphMapNodes {
|
||||
Context,
|
||||
}
|
||||
|
||||
type GraphMapNodesFnTy = dyn Fn(petgraph::prelude::NodeIndex, &RSsystem) -> String;
|
||||
type GraphMapNodesFnTy =
|
||||
dyn Fn(petgraph::prelude::NodeIndex, &RSsystem) -> String;
|
||||
/// Helper structure that holds a formatting function from node as RSsystem to
|
||||
/// string
|
||||
pub struct GraphMapNodesTy {
|
||||
@ -133,6 +135,7 @@ impl From<GraphMapNodesTy> for Box<GraphMapNodesFnTy> {
|
||||
// Edges -----------------------------------------------------------------------
|
||||
|
||||
/// Helper structure that specifies what information to display for edges
|
||||
#[derive(Clone)]
|
||||
pub enum GraphMapEdges {
|
||||
Hide,
|
||||
Products,
|
||||
|
||||
@ -24,7 +24,6 @@ use super::*;
|
||||
// Structures
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SaveOptions {
|
||||
pub print: bool,
|
||||
pub save: Option<Vec<String>>
|
||||
@ -57,14 +56,28 @@ impl Default for SaveOptions {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone)]
|
||||
pub enum NodeDisplay {
|
||||
Separator(String),
|
||||
Display(graph::GraphMapNodes)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum EdgeDisplay {
|
||||
Separator(String),
|
||||
Display(graph::GraphMapEdges)
|
||||
}
|
||||
|
||||
pub enum GraphSaveOptions {
|
||||
Dot { so: SaveOptions },
|
||||
GraphML { so: SaveOptions },
|
||||
Dot { node_display: Vec<NodeDisplay>,
|
||||
edge_display: Vec<EdgeDisplay>,
|
||||
so: SaveOptions },
|
||||
GraphML { node_display: Vec<NodeDisplay>,
|
||||
edge_display: Vec<EdgeDisplay>,
|
||||
so: SaveOptions },
|
||||
Serialize { path: String }
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Instruction {
|
||||
Stats { so: SaveOptions },
|
||||
Target { so: SaveOptions },
|
||||
@ -76,13 +89,11 @@ pub enum Instruction {
|
||||
Digraph { gso: Vec<GraphSaveOptions> },
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum System {
|
||||
Deserialize { path: String },
|
||||
RSsystem { sys: RSsystem }
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum EvaluatedSystem {
|
||||
Graph { graph: Graph<RSsystem, RSlabel>,
|
||||
translator: Translator },
|
||||
@ -93,22 +104,24 @@ pub enum EvaluatedSystem {
|
||||
|
||||
impl System {
|
||||
pub fn compute(
|
||||
&self, translator: Translator
|
||||
&self,
|
||||
translator: Translator
|
||||
) -> Result<EvaluatedSystem, String>
|
||||
{
|
||||
match self {
|
||||
Self::RSsystem { sys } => {
|
||||
Ok(EvaluatedSystem::System { sys: sys.to_owned(), translator })
|
||||
Ok(EvaluatedSystem::System { sys: sys.to_owned(),
|
||||
translator })
|
||||
},
|
||||
Self::Deserialize { path } => {
|
||||
let (graph, translator) = deserialize(path.into())?;
|
||||
Ok(EvaluatedSystem::Graph { graph, translator })
|
||||
Ok(EvaluatedSystem::Graph { graph,
|
||||
translator })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Instructions {
|
||||
pub system: System,
|
||||
pub instructions: Vec<Instruction>
|
||||
@ -489,29 +502,96 @@ pub fn digraph(
|
||||
// Output Functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn generate_node_pringting_fn<'a>(
|
||||
node_display: &'a Vec<NodeDisplay>,
|
||||
translator: Rc<Translator>
|
||||
) -> Box<dyn Fn(petgraph::prelude::NodeIndex, &'a RSsystem) -> String + '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 mut accumulator:
|
||||
Box<dyn Fn(petgraph::prelude::NodeIndex, &RSsystem) -> String>
|
||||
= Box::new(|_, _| String::new());
|
||||
for nd in node_display {
|
||||
accumulator =
|
||||
match nd {
|
||||
NodeDisplay::Display(d) => { // retrieve from the graph module
|
||||
// the correct formatting function
|
||||
let val = translator.clone();
|
||||
Box::new(
|
||||
move |i, n| (accumulator)(i, n) +
|
||||
&graph::GraphMapNodesTy::from(
|
||||
d.clone(),
|
||||
val.clone()
|
||||
).get()(i, n))
|
||||
},
|
||||
NodeDisplay::Separator(s) => { // we have a string so simply
|
||||
// add it at the end
|
||||
Box::new(
|
||||
move |i, n| (accumulator)(i, n) + s
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
accumulator
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn generate_edge_pringting_fn<'a>(
|
||||
edge_display: &'a Vec<EdgeDisplay>,
|
||||
translator: Rc<Translator>
|
||||
) -> Box<dyn Fn(petgraph::prelude::EdgeIndex, &'a RSlabel) -> String + '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 mut accumulator:
|
||||
Box<dyn Fn(petgraph::prelude::EdgeIndex, &RSlabel) -> String>
|
||||
= Box::new(|_, _| String::new());
|
||||
for nd in edge_display {
|
||||
accumulator =
|
||||
match nd {
|
||||
EdgeDisplay::Display(d) => { // retrieve from the graph module
|
||||
// the correct formatting function
|
||||
let val = translator.clone();
|
||||
Box::new(
|
||||
move |i, n| (accumulator)(i, n) +
|
||||
&graph::GraphMapEdgesTy::from(
|
||||
d.clone(),
|
||||
val.clone()
|
||||
).get()(i, n))
|
||||
},
|
||||
EdgeDisplay::Separator(s) => { // we have a string so simply
|
||||
// add it at the end
|
||||
Box::new(
|
||||
move |i, n| (accumulator)(i, n) + s
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
accumulator
|
||||
}
|
||||
|
||||
/// Writes the specified graph to a file in .dot format.
|
||||
pub fn dot(system: &EvaluatedSystem) -> Result<String, String> {
|
||||
pub fn dot(
|
||||
system: &EvaluatedSystem,
|
||||
node_display: Vec<NodeDisplay>,
|
||||
edge_display: Vec<EdgeDisplay>
|
||||
) -> Result<String, String>
|
||||
{
|
||||
match system {
|
||||
EvaluatedSystem::System { sys:_, translator:_ } =>
|
||||
Err("Supplied system is not a graph".into()),
|
||||
EvaluatedSystem::Graph { graph, translator } => {
|
||||
let rc_translator = Rc::new(translator.to_owned());
|
||||
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(
|
||||
|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()
|
||||
generate_node_pringting_fn(&node_display, Rc::clone(&rc_translator)),
|
||||
generate_edge_pringting_fn(&edge_display, rc_translator)
|
||||
);
|
||||
|
||||
let graph = Rc::new(graph.to_owned());
|
||||
@ -677,10 +757,10 @@ fn execute(
|
||||
for save in gso {
|
||||
digraph(system)?;
|
||||
match save {
|
||||
GraphSaveOptions::Dot { so } => {
|
||||
save_options!(dot(system)?, so);
|
||||
GraphSaveOptions::Dot { node_display, edge_display, so } => {
|
||||
save_options!(dot(system, node_display, edge_display)?, so);
|
||||
},
|
||||
GraphSaveOptions::GraphML { so } => {
|
||||
GraphSaveOptions::GraphML { node_display:_, edge_display:_, so } => {
|
||||
save_options!(graphml(system)?, so);
|
||||
},
|
||||
GraphSaveOptions::Serialize { path } => {
|
||||
|
||||
Reference in New Issue
Block a user