From 75028fbf3883dc06e46efe30918709637c23b1fd Mon Sep 17 00:00:00 2001 From: elvis Date: Sun, 13 Jul 2025 19:08:39 +0200 Subject: [PATCH] Edge color working --- src/rsprocess/grammar.lalrpop | 42 +++++++- src/rsprocess/graph.rs | 149 +++++++++++++++++++++++++--- src/rsprocess/presets.rs | 40 ++++++-- src/rsprocess/statistics.rs | 2 +- src/rsprocess/structure.rs | 26 ++--- src/rsprocess/support_structures.rs | 16 +-- src/rsprocess/translator.rs | 6 +- testing/first.system | 2 +- 8 files changed, 232 insertions(+), 51 deletions(-) diff --git a/src/rsprocess/grammar.lalrpop b/src/rsprocess/grammar.lalrpop index 1c22c54..ce53229 100644 --- a/src/rsprocess/grammar.lalrpop +++ b/src/rsprocess/grammar.lalrpop @@ -440,7 +440,7 @@ NodeColorConditional: (graph::NodeColorConditional, String) = { ColorNode: graph::NodeColor = { > "!" => - graph::NodeColor { conditionals: conditionals, + graph::NodeColor { conditionals, base_color: base_color.to_string() }, "!" => @@ -448,15 +448,53 @@ ColorNode: graph::NodeColor = { base_color: base_color.to_string() }, } +EdgeColorConditional: (graph::EdgeColorConditional, String) = { + "Entities" "?" => + (graph::EdgeColorConditional::Entities(op, set), + color.to_string()), + "Context" "?" => + (graph::EdgeColorConditional::Context(op, set), + color.to_string()), + "T" "?" => + (graph::EdgeColorConditional::T(op, set), + color.to_string()), + "Reactants" "?" => + (graph::EdgeColorConditional::Reactants(op, set), + color.to_string()), + "AbsentReactants" "?" => + (graph::EdgeColorConditional::ReactantsAbsent(op, set), + color.to_string()), + "Inhibitors" "?" => + (graph::EdgeColorConditional::Inhibitors(op, set), + color.to_string()), + "PresentInhibitors" "?" => + (graph::EdgeColorConditional::InhibitorsPresent(op, set), + color.to_string()), + "Products" "?" => + (graph::EdgeColorConditional::Products(op, set), + color.to_string()), +} + +ColorEdge: graph::EdgeColor = { + > + "!" => + graph::EdgeColor { conditionals, + base_color: base_color.to_string() }, + + "!" => + graph::EdgeColor { conditionals: vec![], + base_color: base_color.to_string() }, +} GraphSaveOptions: presets::GraphSaveOptions = { "Dot" "|" "|" - ">" + "|" ">" => presets::GraphSaveOptions::Dot { node_display: s_node, edge_display: s_edge, node_color: c_node, + edge_color: c_edge, so }, "GraphML" "|" ">" => diff --git a/src/rsprocess/graph.rs b/src/rsprocess/graph.rs index 39a4a15..faf152c 100644 --- a/src/rsprocess/graph.rs +++ b/src/rsprocess/graph.rs @@ -373,12 +373,6 @@ type RSformatNodeTy = <&RSdotGraph as IntoNodeReferences>::NodeRef ) -> Option; -type RSformatEdgeTy = - dyn Fn( - &RSdotGraph, - <&RSdotGraph as IntoEdgeReferences>::EdgeRef - ) -> String; - #[derive(Clone, Copy)] pub enum OperationType { Equals, @@ -420,7 +414,6 @@ pub enum ContextColorConditional { WaitEntity } - #[derive(Clone)] pub enum NodeColorConditional { ContextConditional(ContextColorConditional), @@ -544,16 +537,140 @@ pub fn node_formatter( } } +type RSformatEdgeTy = + dyn Fn( + &RSdotGraph, + <&RSdotGraph as IntoEdgeReferences>::EdgeRef + ) -> Option; + +#[derive(Clone)] +pub enum EdgeColorConditional { + Entities(OperationType, RSset), + Context(OperationType, RSset), + T(OperationType, RSset), + Reactants(OperationType, RSset), + ReactantsAbsent(OperationType, RSset), + Inhibitors(OperationType, RSset), + InhibitorsPresent(OperationType, RSset), + Products(OperationType, RSset), +} + +#[derive(Clone)] +pub struct EdgeColor { + pub conditionals: Vec<(EdgeColorConditional, String)>, + pub base_color: String +} + + +pub fn edge_formatter_base_color( + base_color: String +) -> String +{ + ", fillcolor=".to_string() + &base_color +} + pub fn edge_formatter( - original_graph: Rc + original_graph: Rc, + rule: EdgeColorConditional, + color: String, ) -> Box { - Box::new( - move |_g, e| String::from( - if original_graph.edge_weight(e.id()).unwrap().products.is_empty() { - "color=black, fontcolor=black" - } else { - "color=blue, fontcolor=blue" - } - )) + match rule { + EdgeColorConditional::Entities(ot, set) => { + Box::new( + move |_, e| { + let rssystem = original_graph.edge_weight(e.id()).unwrap(); + if ot.evaluate(&rssystem.available_entities, &set) { + Some(", fillcolor=".to_string() + &color) + } else { + None + } + } + ) + }, + EdgeColorConditional::Context(ot, set) => { + Box::new( + move |_, e| { + let rssystem = original_graph.edge_weight(e.id()).unwrap(); + if ot.evaluate(&rssystem.context, &set) { + Some(", fillcolor=".to_string() + &color) + } else { + None + } + } + ) + }, + EdgeColorConditional::T(ot, set) => { + Box::new( + move |_, e| { + let rssystem = original_graph.edge_weight(e.id()).unwrap(); + if ot.evaluate(&rssystem.t, &set) { + Some(", fillcolor=".to_string() + &color) + } else { + None + } + } + ) + }, + EdgeColorConditional::Reactants(ot, set) => { + Box::new( + move |_, e| { + let rssystem = original_graph.edge_weight(e.id()).unwrap(); + if ot.evaluate(&rssystem.reactants, &set) { + Some(", fillcolor=".to_string() + &color) + } else { + None + } + } + ) + }, + EdgeColorConditional::ReactantsAbsent(ot, set) => { + Box::new( + move |_, e| { + let rssystem = original_graph.edge_weight(e.id()).unwrap(); + if ot.evaluate(&rssystem.reactants_absent, &set) { + Some(", fillcolor=".to_string() + &color) + } else { + None + } + } + ) + }, + EdgeColorConditional::Inhibitors(ot, set) => { + Box::new( + move |_, e| { + let rssystem = original_graph.edge_weight(e.id()).unwrap(); + if ot.evaluate(&rssystem.inhibitors, &set) { + Some(", fillcolor=".to_string() + &color) + } else { + None + } + } + ) + }, + EdgeColorConditional::InhibitorsPresent(ot, set) => { + Box::new( + move |_, e| { + let rssystem = original_graph.edge_weight(e.id()).unwrap(); + if ot.evaluate(&rssystem.inhibitors_present, &set) { + Some(", fillcolor=".to_string() + &color) + } else { + None + } + } + ) + }, + EdgeColorConditional::Products(ot, set) => { + Box::new( + move |_, e| { + let rssystem = original_graph.edge_weight(e.id()).unwrap(); + if ot.evaluate(&rssystem.products, &set) { + Some(", fillcolor=".to_string() + &color) + } else { + None + } + } + ) + }, + } } diff --git a/src/rsprocess/presets.rs b/src/rsprocess/presets.rs index 24e5567..eb02b73 100644 --- a/src/rsprocess/presets.rs +++ b/src/rsprocess/presets.rs @@ -76,6 +76,7 @@ pub enum GraphSaveOptions { node_display: Vec, edge_display: Vec, node_color: graph::NodeColor, + edge_color: graph::EdgeColor, so: SaveOptions, }, GraphML { @@ -205,7 +206,7 @@ where let mut it = expected.iter().peekable(); while let Some(s) = it.next() { err.push('('); - err.push_str(&s); + err.push_str(s); err.push(')'); if it.peek().is_some() { err.push(','); @@ -575,12 +576,36 @@ fn generate_node_color_fn<'a>( ) } +use petgraph::visit::IntoEdgeReferences; +#[allow(clippy::type_complexity)] +fn generate_edge_color_fn<'a>( + edge_color: &'a graph::EdgeColor, + original_graph: Rc>, +) -> Box, <&Graph as IntoEdgeReferences>::EdgeRef) -> String + 'a> { + Box::new( + move |i, n| { + let cloned_edge_color = edge_color.clone(); + for (rule, color) in cloned_edge_color.conditionals { + if let Some(s) = graph::edge_formatter( + original_graph.clone(), + rule, + color + )(i, n) { + return s + } + } + graph::edge_formatter_base_color(edge_color.base_color.to_string()) + } + ) +} + /// Writes the specified graph to a file in .dot format. pub fn dot( system: &EvaluatedSystem, node_display: Vec, edge_display: Vec, - node_color: &graph::NodeColor + node_color: &graph::NodeColor, + edge_color: &graph::EdgeColor ) -> Result { match system { EvaluatedSystem::System { @@ -601,15 +626,15 @@ pub fn dot( let graph = Rc::new(graph.to_owned()); - // let edge_formatter = - // graph::default_edge_formatter(Rc::clone(&graph)); let node_formatter = - generate_node_color_fn(node_color, graph, rc_translator); + generate_node_color_fn(node_color, Rc::clone(&graph), rc_translator); + let edge_formatter = + generate_edge_color_fn(edge_color, graph); let dot = rsdot::RSDot::with_attr_getters( &modified_graph, &[], - &|_, _| String::new(), // &edge_formatter, + &edge_formatter, &node_formatter, ); @@ -759,9 +784,10 @@ fn execute( node_display: nd, edge_display: ed, node_color: nc, + edge_color: ec, so, } => { - save_options!(dot(system, nd, ed, &nc)?, so); + save_options!(dot(system, nd, ed, &nc, &ec)?, so); } GraphSaveOptions::GraphML { node_display: nd, diff --git a/src/rsprocess/statistics.rs b/src/rsprocess/statistics.rs index 74fc754..b12ddcf 100644 --- a/src/rsprocess/statistics.rs +++ b/src/rsprocess/statistics.rs @@ -35,7 +35,7 @@ pub fn of_RSsystem<'a>(translator: &'a Translator, system: &'a RSsystem) -> Stri let inhibitors = system .reaction_rules .iter() - .fold(RSset::new(), |acc, new| acc.union(&new.inihibitors)); + .fold(RSset::new(), |acc, new| acc.union(&new.inhibitors)); result.push_str(&format!( "The inhibitors are {}:\n{}\n", inhibitors.len(), diff --git a/src/rsprocess/structure.rs b/src/rsprocess/structure.rs index c366b50..1cc4777 100644 --- a/src/rsprocess/structure.rs +++ b/src/rsprocess/structure.rs @@ -135,7 +135,7 @@ impl IntoIterator for RSset { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct RSreaction { pub reactants: RSset, - pub inihibitors: RSset, + pub inhibitors: RSset, pub products: RSset, } @@ -143,15 +143,15 @@ impl RSreaction { pub fn new() -> Self { RSreaction { reactants: RSset::new(), - inihibitors: RSset::new(), + inhibitors: RSset::new(), products: RSset::new(), } } - pub fn from(reactants: RSset, inihibitors: RSset, products: RSset) -> Self { + pub fn from(reactants: RSset, inhibitors: RSset, products: RSset) -> Self { RSreaction { reactants, - inihibitors, + inhibitors, products, } } @@ -160,7 +160,7 @@ impl RSreaction { /// see enable pub fn enabled(&self, current_state: &RSset) -> bool { self.reactants.is_subset(current_state) - && self.inihibitors.is_disjoint(current_state) + && self.inhibitors.is_disjoint(current_state) } } @@ -498,8 +498,8 @@ pub struct RSlabel { pub t: RSset, pub reactants: RSset, pub reactants_absent: RSset, - pub inihibitors: RSset, - pub inihibitors_present: RSset, + pub inhibitors: RSset, + pub inhibitors_present: RSset, pub products: RSset, } @@ -511,8 +511,8 @@ impl RSlabel { t: RSset::new(), reactants: RSset::new(), reactants_absent: RSset::new(), - inihibitors: RSset::new(), - inihibitors_present: RSset::new(), + inhibitors: RSset::new(), + inhibitors_present: RSset::new(), products: RSset::new(), } } @@ -524,8 +524,8 @@ impl RSlabel { t: RSset, reactants: RSset, reactants_absent: RSset, - inihibitors: RSset, - inihibitors_present: RSset, + inhibitors: RSset, + inhibitors_present: RSset, products: RSset, ) -> Self { RSlabel { @@ -534,8 +534,8 @@ impl RSlabel { t, reactants, reactants_absent, - inihibitors, - inihibitors_present, + inhibitors, + inhibitors_present, products, } } diff --git a/src/rsprocess/support_structures.rs b/src/rsprocess/support_structures.rs index 731557e..289688b 100644 --- a/src/rsprocess/support_structures.rs +++ b/src/rsprocess/support_structures.rs @@ -34,16 +34,16 @@ impl<'a> Iterator for TransitionsIterator<'a> { let ( reactants, reactants_absent, - inihibitors, - inihibitors_present, + inhibitors, + inhibitors_present, products ) = self.system.reaction_rules.iter().fold( ( RSset::new(), // reactants RSset::new(), // reactants_absent - RSset::new(), // inihibitors - RSset::new(), // inihibitors_present + RSset::new(), // inhibitors + RSset::new(), // inhibitors_present RSset::new(), // products ), |acc, reaction| { @@ -51,14 +51,14 @@ impl<'a> Iterator for TransitionsIterator<'a> { ( acc.0.union(&reaction.reactants), acc.1, - acc.2.union(&reaction.inihibitors), + acc.2.union(&reaction.inhibitors), acc.3, acc.4.union(&reaction.products), ) } else { ( acc.0, - acc.1.union(&reaction.inihibitors.intersection(&t)), + acc.1.union(&reaction.inhibitors.intersection(&t)), acc.2, acc.3.union(&reaction.reactants.subtraction(&t)), acc.4, @@ -73,8 +73,8 @@ impl<'a> Iterator for TransitionsIterator<'a> { t, reactants, reactants_absent, - inihibitors, - inihibitors_present, + inhibitors, + inhibitors_present, products.clone(), ); let new_system = RSsystem::from( diff --git a/src/rsprocess/translator.rs b/src/rsprocess/translator.rs index 972c569..71f643f 100644 --- a/src/rsprocess/translator.rs +++ b/src/rsprocess/translator.rs @@ -133,7 +133,7 @@ fn print_reaction( f, "(r: {}, i: {}, p: {})", RSsetDisplay::from(translator, &reaction.reactants), - RSsetDisplay::from(translator, &reaction.inihibitors), + RSsetDisplay::from(translator, &reaction.inhibitors), RSsetDisplay::from(translator, &reaction.products) ) } @@ -339,8 +339,8 @@ fn print_label( RSsetDisplay::from(translator, &label.t), RSsetDisplay::from(translator, &label.reactants), RSsetDisplay::from(translator, &label.reactants_absent), - RSsetDisplay::from(translator, &label.inihibitors), - RSsetDisplay::from(translator, &label.inihibitors_present), + RSsetDisplay::from(translator, &label.inhibitors), + RSsetDisplay::from(translator, &label.inhibitors_present), RSsetDisplay::from(translator, &label.products), ) } diff --git a/testing/first.system b/testing/first.system index e020aa9..3063fa6 100644 --- a/testing/first.system +++ b/testing/first.system @@ -4,4 +4,4 @@ Context: [({a,b}.{a}.{a,c}.x + {a,b}.{a}.{a}.nill)] Reactions: ([{a,b}, {c}, {b}]) -Digraph > Dot Context | Hide | Context.EntitySet ⊆ {a, c} ? "HERE" || Context.NonDeterministicChoice ? "ASDASDSAD" ! "#123" > Print +Digraph > Dot Context | Hide | Context.EntitySet ⊆ {a, c} ? "HERE" || Context.NonDeterministicChoice ? "ASDASDSAD" ! "#123" | ! "#987" > Print