Edge color working

This commit is contained in:
elvis
2025-07-13 19:08:39 +02:00
parent 6fd606d75d
commit 75028fbf38
8 changed files with 232 additions and 51 deletions

View File

@ -440,7 +440,7 @@ NodeColorConditional: (graph::NodeColorConditional, String) = {
ColorNode: graph::NodeColor = {
<conditionals: Separated_Or<NodeColorConditional, "||">>
"!" <base_color: PATH> =>
graph::NodeColor { conditionals: conditionals,
graph::NodeColor { conditionals,
base_color: base_color.to_string() },
"!" <base_color: PATH> =>
@ -448,15 +448,53 @@ ColorNode: graph::NodeColor = {
base_color: base_color.to_string() },
}
EdgeColorConditional: (graph::EdgeColorConditional, String) = {
"Entities" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::EdgeColorConditional::Entities(op, set),
color.to_string()),
"Context" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::EdgeColorConditional::Context(op, set),
color.to_string()),
"T" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::EdgeColorConditional::T(op, set),
color.to_string()),
"Reactants" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::EdgeColorConditional::Reactants(op, set),
color.to_string()),
"AbsentReactants" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::EdgeColorConditional::ReactantsAbsent(op, set),
color.to_string()),
"Inhibitors" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::EdgeColorConditional::Inhibitors(op, set),
color.to_string()),
"PresentInhibitors" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::EdgeColorConditional::InhibitorsPresent(op, set),
color.to_string()),
"Products" <op: Operation> <set: Set> "?" <color: PATH> =>
(graph::EdgeColorConditional::Products(op, set),
color.to_string()),
}
ColorEdge: graph::EdgeColor = {
<conditionals: Separated_Or<EdgeColorConditional, "||">>
"!" <base_color: PATH> =>
graph::EdgeColor { conditionals,
base_color: base_color.to_string() },
"!" <base_color: PATH> =>
graph::EdgeColor { conditionals: vec![],
base_color: base_color.to_string() },
}
GraphSaveOptions: presets::GraphSaveOptions = {
"Dot" <s_node: SeparatorNode> "|" <s_edge: SeparatorEdge> "|"
<c_node: ColorNode> ">"
<c_node: ColorNode> "|" <c_edge: ColorEdge> ">"
<so: SaveOptions> =>
presets::GraphSaveOptions::Dot { node_display: s_node,
edge_display: s_edge,
node_color: c_node,
edge_color: c_edge,
so },
"GraphML" <s_node: SeparatorNode> "|" <s_edge: SeparatorEdge> ">"
<so: SaveOptions> =>

View File

@ -373,12 +373,6 @@ type RSformatNodeTy =
<&RSdotGraph as IntoNodeReferences>::NodeRef
) -> Option<String>;
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<String>;
#[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<RSgraph>
original_graph: Rc<RSgraph>,
rule: EdgeColorConditional,
color: String,
) -> Box<RSformatEdgeTy>
{
match rule {
EdgeColorConditional::Entities(ot, set) => {
Box::new(
move |_g, e| String::from(
if original_graph.edge_weight(e.id()).unwrap().products.is_empty() {
"color=black, fontcolor=black"
move |_, e| {
let rssystem = original_graph.edge_weight(e.id()).unwrap();
if ot.evaluate(&rssystem.available_entities, &set) {
Some(", fillcolor=".to_string() + &color)
} else {
"color=blue, fontcolor=blue"
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
}
}
)
},
}
))
}

View File

@ -76,6 +76,7 @@ pub enum GraphSaveOptions {
node_display: Vec<NodeDisplay>,
edge_display: Vec<EdgeDisplay>,
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<Graph<RSsystem, RSlabel>>,
) -> Box<dyn Fn(&Graph<String, String>, <&Graph<String, String, petgraph::Directed, u32> 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<NodeDisplay>,
edge_display: Vec<EdgeDisplay>,
node_color: &graph::NodeColor
node_color: &graph::NodeColor,
edge_color: &graph::EdgeColor
) -> Result<String, String> {
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,

View File

@ -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(),

View File

@ -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,
}
}

View File

@ -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(

View File

@ -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),
)
}

View File

@ -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