Working formatting of weights for nodes and edges
This commit is contained in:
@ -1,11 +1,12 @@
|
|||||||
use reactionsystems::rsprocess::presets;
|
use reactionsystems::rsprocess::presets;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// let now = std::time::Instant::now();
|
let now = std::time::Instant::now();
|
||||||
// println!("{}", now.elapsed().as_micros());
|
|
||||||
|
|
||||||
match presets::run("testing/first.system".into()) {
|
match presets::run("testing/first.system".into()) {
|
||||||
Ok(_) => {},
|
Ok(_) => {},
|
||||||
Err(e) => {println!("{e}")}
|
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::translator::{Translator, IdType};
|
||||||
use crate::rsprocess::presets::Instructions;
|
use crate::rsprocess::presets::Instructions;
|
||||||
use crate::rsprocess::presets;
|
use crate::rsprocess::presets;
|
||||||
|
use crate::rsprocess::graph;
|
||||||
|
|
||||||
grammar(translator: &mut Translator);
|
grammar(translator: &mut Translator);
|
||||||
|
|
||||||
@ -37,12 +38,17 @@ match {
|
|||||||
"Dot", "GraphML", "Serialize",
|
"Dot", "GraphML", "Serialize",
|
||||||
"Stats", "Target", "Run", "Loop", "Frequency", "LimitFrequency",
|
"Stats", "Target", "Run", "Loop", "Frequency", "LimitFrequency",
|
||||||
"FastFrequency", "Digraph",
|
"FastFrequency", "Digraph",
|
||||||
"Deserialize"
|
"Deserialize",
|
||||||
|
"Hide", "Entities", "MaskEntities", "MaskContext",
|
||||||
|
"Products", "MaskProducts", "Union", "MaskUnion",
|
||||||
|
"Difference", "MaskDifference",
|
||||||
|
"EntitiesDeleted", "MaskEntitiesDeleted",
|
||||||
|
"EntitiesAdded", "MaskEntitiesAdded"
|
||||||
} else {
|
} else {
|
||||||
r"[0-9]+" => NUMBER
|
r"[0-9]+" => NUMBER
|
||||||
} else {
|
} else {
|
||||||
// r"([[:alpha:]]|\p{Emoji})([[:word:]]|\p{Emoji})*" => WORD
|
r"([[:alpha:]])([[:word:]])*" => WORD
|
||||||
r"(\p{L}|\p{Emoji})(\p{L}|\p{Emoji}|\p{Dash}|\p{N})*" => WORD,
|
// r"(\p{L}|\p{Emoji})(\p{L}|\p{Emoji}|\p{Dash}|\p{N})*" => WORD,
|
||||||
} else {
|
} else {
|
||||||
r#"".*""# => PATH,
|
r#"".*""# => PATH,
|
||||||
} else {
|
} 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 = {
|
GraphSaveOptions: presets::GraphSaveOptions = {
|
||||||
"Dot" ">" <so: SaveOptions> =>
|
"Dot" <s_node: SeparatorNode> "|" <s_edge: SeparatorEdge> ">"
|
||||||
presets::GraphSaveOptions::Dot { so },
|
<so: SaveOptions> =>
|
||||||
"GraphML" ">" <so: SaveOptions> =>
|
presets::GraphSaveOptions::Dot { node_display: s_node,
|
||||||
presets::GraphSaveOptions::GraphML { so },
|
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> ")" =>
|
"Serialize" "(" <path: Path> ")" =>
|
||||||
presets::GraphSaveOptions::Serialize { path },
|
presets::GraphSaveOptions::Serialize { path },
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,6 +48,7 @@ pub fn digraph(
|
|||||||
// Nodes -----------------------------------------------------------------------
|
// Nodes -----------------------------------------------------------------------
|
||||||
|
|
||||||
/// Helper structure that specifies what information to display for nodes.
|
/// Helper structure that specifies what information to display for nodes.
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum GraphMapNodes {
|
pub enum GraphMapNodes {
|
||||||
Hide,
|
Hide,
|
||||||
Entities,
|
Entities,
|
||||||
@ -55,7 +56,8 @@ pub enum GraphMapNodes {
|
|||||||
Context,
|
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
|
/// Helper structure that holds a formatting function from node as RSsystem to
|
||||||
/// string
|
/// string
|
||||||
pub struct GraphMapNodesTy {
|
pub struct GraphMapNodesTy {
|
||||||
@ -133,6 +135,7 @@ impl From<GraphMapNodesTy> for Box<GraphMapNodesFnTy> {
|
|||||||
// Edges -----------------------------------------------------------------------
|
// Edges -----------------------------------------------------------------------
|
||||||
|
|
||||||
/// Helper structure that specifies what information to display for edges
|
/// Helper structure that specifies what information to display for edges
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum GraphMapEdges {
|
pub enum GraphMapEdges {
|
||||||
Hide,
|
Hide,
|
||||||
Products,
|
Products,
|
||||||
|
|||||||
@ -24,7 +24,6 @@ use super::*;
|
|||||||
// Structures
|
// Structures
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct SaveOptions {
|
pub struct SaveOptions {
|
||||||
pub print: bool,
|
pub print: bool,
|
||||||
pub save: Option<Vec<String>>
|
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 {
|
pub enum GraphSaveOptions {
|
||||||
Dot { so: SaveOptions },
|
Dot { node_display: Vec<NodeDisplay>,
|
||||||
GraphML { so: SaveOptions },
|
edge_display: Vec<EdgeDisplay>,
|
||||||
|
so: SaveOptions },
|
||||||
|
GraphML { node_display: Vec<NodeDisplay>,
|
||||||
|
edge_display: Vec<EdgeDisplay>,
|
||||||
|
so: SaveOptions },
|
||||||
Serialize { path: String }
|
Serialize { path: String }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
Stats { so: SaveOptions },
|
Stats { so: SaveOptions },
|
||||||
Target { so: SaveOptions },
|
Target { so: SaveOptions },
|
||||||
@ -76,13 +89,11 @@ pub enum Instruction {
|
|||||||
Digraph { gso: Vec<GraphSaveOptions> },
|
Digraph { gso: Vec<GraphSaveOptions> },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum System {
|
pub enum System {
|
||||||
Deserialize { path: String },
|
Deserialize { path: String },
|
||||||
RSsystem { sys: RSsystem }
|
RSsystem { sys: RSsystem }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum EvaluatedSystem {
|
pub enum EvaluatedSystem {
|
||||||
Graph { graph: Graph<RSsystem, RSlabel>,
|
Graph { graph: Graph<RSsystem, RSlabel>,
|
||||||
translator: Translator },
|
translator: Translator },
|
||||||
@ -93,22 +104,24 @@ pub enum EvaluatedSystem {
|
|||||||
|
|
||||||
impl System {
|
impl System {
|
||||||
pub fn compute(
|
pub fn compute(
|
||||||
&self, translator: Translator
|
&self,
|
||||||
|
translator: Translator
|
||||||
) -> Result<EvaluatedSystem, String>
|
) -> Result<EvaluatedSystem, String>
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Self::RSsystem { sys } => {
|
Self::RSsystem { sys } => {
|
||||||
Ok(EvaluatedSystem::System { sys: sys.to_owned(), translator })
|
Ok(EvaluatedSystem::System { sys: sys.to_owned(),
|
||||||
|
translator })
|
||||||
},
|
},
|
||||||
Self::Deserialize { path } => {
|
Self::Deserialize { path } => {
|
||||||
let (graph, translator) = deserialize(path.into())?;
|
let (graph, translator) = deserialize(path.into())?;
|
||||||
Ok(EvaluatedSystem::Graph { graph, translator })
|
Ok(EvaluatedSystem::Graph { graph,
|
||||||
|
translator })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Instructions {
|
pub struct Instructions {
|
||||||
pub system: System,
|
pub system: System,
|
||||||
pub instructions: Vec<Instruction>
|
pub instructions: Vec<Instruction>
|
||||||
@ -489,29 +502,96 @@ pub fn digraph(
|
|||||||
// Output Functions
|
// 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.
|
/// 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 {
|
match system {
|
||||||
EvaluatedSystem::System { sys:_, translator:_ } =>
|
EvaluatedSystem::System { sys:_, translator:_ } =>
|
||||||
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.to_owned());
|
let rc_translator = Rc::new(translator.clone());
|
||||||
// map each value to the corresponding value we want to display
|
// 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(
|
||||||
|id, node|
|
generate_node_pringting_fn(&node_display, Rc::clone(&rc_translator)),
|
||||||
graph::GraphMapNodesTy::from(
|
generate_edge_pringting_fn(&edge_display, rc_translator)
|
||||||
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()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let graph = Rc::new(graph.to_owned());
|
let graph = Rc::new(graph.to_owned());
|
||||||
@ -677,10 +757,10 @@ fn execute(
|
|||||||
for save in gso {
|
for save in gso {
|
||||||
digraph(system)?;
|
digraph(system)?;
|
||||||
match save {
|
match save {
|
||||||
GraphSaveOptions::Dot { so } => {
|
GraphSaveOptions::Dot { node_display, edge_display, so } => {
|
||||||
save_options!(dot(system)?, 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);
|
save_options!(graphml(system)?, so);
|
||||||
},
|
},
|
||||||
GraphSaveOptions::Serialize { path } => {
|
GraphSaveOptions::Serialize { path } => {
|
||||||
|
|||||||
@ -4,4 +4,4 @@ Context: [({a,b}.{a}.{a,c}.x + {a,b}.{a}.{a}.nill)]
|
|||||||
Reactions: ([{a,b}, {c}, {b}])
|
Reactions: ([{a,b}, {c}, {b}])
|
||||||
|
|
||||||
|
|
||||||
Digraph > Dot > Print
|
Digraph > Dot Entities | Context "; " MaskDifference {a, b} > Print
|
||||||
Reference in New Issue
Block a user