Positive graph dot and graphml formatting functions

This commit is contained in:
elvis
2025-10-28 22:21:09 +01:00
parent f90308a11e
commit 0700b016eb
3 changed files with 1272 additions and 209 deletions

View File

@ -519,3 +519,584 @@ pub mod edge_formatter {
})
}
}
// -----------------------------------------------------------------------------
// Positive
// -----------------------------------------------------------------------------
pub mod positive_graph_map_nodes_ty_from {
use std::rc::Rc;
use super::super::element::IdState;
use super::super::set::{BasicSet, Set};
use super::super::system::PositiveSystem;
use super::super::translator;
type PositiveGraphMapNodesFnTy =
dyn Fn(petgraph::prelude::NodeIndex, &PositiveSystem) -> String;
pub fn format_string(s: String) -> Box<PositiveGraphMapNodesFnTy> {
Box::new(move |_, _| s.clone())
}
pub fn format_hide(
_translator: Rc<translator::Translator>,
) -> Box<PositiveGraphMapNodesFnTy> {
Box::new(|_, _| String::new())
}
pub fn format_entities(
translator: Rc<translator::Translator>,
) -> Box<PositiveGraphMapNodesFnTy> {
Box::new(move |_, node: &PositiveSystem| {
format!(
"{}",
translator::Formatter::from(
&translator,
&node.available_entities
)
)
})
}
pub fn format_mask_entities(
translator: Rc<translator::Translator>,
mask: Set,
) -> Box<PositiveGraphMapNodesFnTy> {
Box::new(move |_, node: &PositiveSystem| {
let masked_entities = node
.available_entities
.mask(&mask.to_positive_set(IdState::Positive));
format!(
"{}",
translator::Formatter::from(&translator, &masked_entities)
)
})
}
pub fn format_exclude_entities(
translator: Rc<translator::Translator>,
mask: Set,
) -> Box<PositiveGraphMapNodesFnTy> {
Box::new(move |_, node: &PositiveSystem| {
let masked_entities = node
.available_entities
.subtraction(&mask.to_positive_set(IdState::Negative))
.subtraction(&mask.to_positive_set(IdState::Negative));
format!(
"{}",
translator::Formatter::from(&translator, &masked_entities)
)
})
}
pub fn format_context(
translator: Rc<translator::Translator>,
) -> Box<PositiveGraphMapNodesFnTy> {
Box::new(move |_, node: &PositiveSystem| {
format!(
"{}",
translator::Formatter::from(&translator, &node.context_process)
)
})
}
}
pub mod positive_graph_map_edges_ty_from {
use std::rc::Rc;
use super::super::element::IdState;
use super::super::label::PositiveLabel;
use super::super::set::{BasicSet, Set};
use super::super::translator;
type PositiveGraphMapEdgesFnTy<'a> =
dyn Fn(petgraph::prelude::EdgeIndex, &'a PositiveLabel) -> String + 'a;
pub fn format_string<'a>(
_translator: Rc<translator::Translator>,
s: String,
) -> Box<PositiveGraphMapEdgesFnTy<'a>> {
Box::new(move |_, _| s.clone())
}
pub fn format_hide<'a>(
_translator: Rc<translator::Translator>,
) -> Box<PositiveGraphMapEdgesFnTy<'a>> {
Box::new(|_, _| String::new())
}
macro_rules! create_format_edge {
( $name:ident,
[$edge_name:ident, $mask_name:ident, $common_name:ident],
$mask_common:expr,
$mask:expr,
$common:expr,
$default:expr ) => {
pub fn $name<'a>(
translator: Rc<translator::Translator>,
$mask_name: Option<Set>,
$common_name: Option<Set>,
) -> Box<PositiveGraphMapEdgesFnTy<'a>> {
match ($mask_name, $common_name) {
| (Some($mask_name), Some($common_name)) =>
Box::new(move |_, $edge_name: &PositiveLabel| {
format!(
"{}",
translator::Formatter::from(
&translator,
$mask_common
)
)
}),
| (Some($mask_name), None) =>
Box::new(move |_, $edge_name: &PositiveLabel| {
format!(
"{}",
translator::Formatter::from(&translator, $mask)
)
}),
| (None, Some($common_name)) =>
Box::new(move |_, $edge_name: &PositiveLabel| {
format!(
"{}",
translator::Formatter::from(
&translator,
$common
)
)
}),
| (None, None) =>
Box::new(move |_, $edge_name: &PositiveLabel| {
format!(
"{}",
translator::Formatter::from(
&translator,
$default
)
)
}),
}
}
};
}
create_format_edge!(
format_products,
[edge, mask, common],
&edge
.products
.mask(&mask.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Negative)),
&edge.products.mask(&mask.to_positive_set(IdState::Positive)),
&edge
.products
.subtraction(&common.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Negative)),
&edge.products
);
create_format_edge!(
format_entities,
[edge, mask, common],
&edge
.available_entities
.mask(&mask.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Negative)),
&edge
.available_entities
.mask(&mask.to_positive_set(IdState::Positive)),
&edge
.available_entities
.subtraction(&common.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Negative)),
&edge.available_entities
);
create_format_edge!(
format_context,
[edge, mask, common],
&edge
.context
.mask(&mask.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Negative)),
&edge.context.mask(&mask.to_positive_set(IdState::Positive)),
&edge
.context
.subtraction(&common.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Negative)),
&edge.context
);
create_format_edge!(
format_union,
[edge, mask, common],
&edge
.t
.mask(&mask.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Negative)),
&edge.t.mask(&mask.to_positive_set(IdState::Positive)),
&edge
.t
.subtraction(&common.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Negative)),
&edge.t
);
create_format_edge!(
format_difference,
[edge, mask, common],
&edge
.context
.subtraction(&edge.available_entities)
.mask(&mask.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Negative)),
&edge
.context
.subtraction(&edge.available_entities)
.mask(&mask.to_positive_set(IdState::Positive)),
&edge
.context
.subtraction(&edge.available_entities)
.subtraction(&common.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Negative)),
&edge.context.subtraction(&edge.available_entities)
);
create_format_edge!(
format_entities_deleted,
[edge, mask, common],
&edge
.available_entities
.subtraction(&edge.products)
.mask(&mask.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Negative)),
&edge
.available_entities
.subtraction(&edge.products)
.mask(&mask.to_positive_set(IdState::Positive)),
&edge
.available_entities
.subtraction(&edge.products)
.subtraction(&common.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Negative)),
&edge.available_entities.subtraction(&edge.products)
);
create_format_edge!(
format_entities_added,
[edge, mask, common],
&edge
.products
.subtraction(&edge.available_entities)
.mask(&mask.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Negative)),
&edge
.products
.subtraction(&edge.available_entities)
.mask(&mask.to_positive_set(IdState::Positive)),
&edge
.products
.subtraction(&edge.available_entities)
.subtraction(&common.to_positive_set(IdState::Positive))
.subtraction(&common.to_positive_set(IdState::Negative)),
&edge.products.subtraction(&edge.available_entities)
);
}
pub mod positive_node_formatter {
use std::rc::Rc;
use petgraph::visit::IntoNodeReferences;
use petgraph::{Directed, Graph};
use super::super::element::IdType;
use super::super::graph::{OperationType, PositiveSystemGraph};
use super::super::process::PositiveProcess;
use super::super::set::Set;
type RSdotGraph = Graph<String, String, Directed, u32>;
type RSformatNodeTy = dyn Fn(
&RSdotGraph,
<&RSdotGraph as IntoNodeReferences>::NodeRef,
) -> Option<String>;
pub fn format_nill(
original_graph: Rc<PositiveSystemGraph>,
color: String,
_star: Option<IdType>,
) -> Box<RSformatNodeTy> {
Box::new(move |_, n| {
let rssystem = original_graph.node_weight(n.0).unwrap();
if rssystem.context_process == PositiveProcess::Nill {
Some(", fillcolor=".to_string() + &color)
} else {
None
}
})
}
pub fn format_recursive_identifier(
original_graph: Rc<PositiveSystemGraph>,
color: String,
star: Option<IdType>,
s: IdType,
) -> Box<RSformatNodeTy> {
Box::new(move |_, n| {
let rssystem = original_graph.node_weight(n.0).unwrap();
match (Some(s) == star, &rssystem.context_process) {
| (
true,
PositiveProcess::RecursiveIdentifier { identifier: _ },
) => Some(", fillcolor=".to_string() + &color),
| (
false,
PositiveProcess::RecursiveIdentifier { identifier: id },
) if id == &s => Some(", fillcolor=".to_string() + &color),
| _ => None,
}
})
}
pub fn format_entity_set(
original_graph: Rc<PositiveSystemGraph>,
color: String,
_star: Option<IdType>,
ot: OperationType,
set: Set,
) -> Box<RSformatNodeTy> {
Box::new(move |_, n| {
let rssystem = original_graph.node_weight(n.0).unwrap();
match &rssystem.context_process {
| PositiveProcess::EntitySet {
entities,
next_process: _,
} if ot.evaluate_positive(entities, &set) =>
Some(", fillcolor=".to_string() + &color),
| _ => None,
}
})
}
pub fn format_non_deterministic_choice(
original_graph: Rc<PositiveSystemGraph>,
color: String,
_star: Option<IdType>,
) -> Box<RSformatNodeTy> {
Box::new(move |_, n| {
let rssystem = original_graph.node_weight(n.0).unwrap();
if let PositiveProcess::NondeterministicChoice { children: _ } =
rssystem.context_process
{
Some(", fillcolor=".to_string() + &color)
} else {
None
}
})
}
pub fn format_summation(
original_graph: Rc<PositiveSystemGraph>,
color: String,
_star: Option<IdType>,
) -> Box<RSformatNodeTy> {
Box::new(move |_, n| {
let rssystem = original_graph.node_weight(n.0).unwrap();
if let PositiveProcess::Summation { children: _ } =
rssystem.context_process
{
Some(", fillcolor=".to_string() + &color)
} else {
None
}
})
}
pub fn format_wait_entity(
original_graph: Rc<PositiveSystemGraph>,
color: String,
_star: Option<IdType>,
) -> Box<RSformatNodeTy> {
Box::new(move |_, n| {
let rssystem = original_graph.node_weight(n.0).unwrap();
if let PositiveProcess::WaitEntity {
repeat: _,
repeated_process: _,
next_process: _,
} = &rssystem.context_process
{
Some(", fillcolor=".to_string() + &color)
} else {
None
}
})
}
pub fn format_entities_conditional(
original_graph: Rc<PositiveSystemGraph>,
color: String,
_star: Option<IdType>,
ot: OperationType,
set: Set,
) -> Box<RSformatNodeTy> {
Box::new(move |_, n| {
let rssystem = original_graph.node_weight(n.0).unwrap();
if ot.evaluate_positive(&rssystem.available_entities, &set) {
Some(", fillcolor=".to_string() + &color)
} else {
None
}
})
}
}
pub mod positive_edge_formatter {
use std::rc::Rc;
use petgraph::visit::{EdgeRef, IntoEdgeReferences};
use petgraph::{Directed, Graph};
use super::super::graph::{OperationType, PositiveSystemGraph};
use super::super::set::Set;
type RSdotGraph = Graph<String, String, Directed, u32>;
type RSformatEdgeTy = dyn Fn(
&RSdotGraph,
<&RSdotGraph as IntoEdgeReferences>::EdgeRef,
) -> Option<String>;
pub fn format_entities(
original_graph: Rc<PositiveSystemGraph>,
color: String,
ot: OperationType,
set: Set,
) -> Box<RSformatEdgeTy> {
Box::new(move |_, e| {
let rssystem = original_graph.edge_weight(e.id()).unwrap();
if ot.evaluate_positive(&rssystem.available_entities, &set) {
Some(", color=".to_string() + &color)
} else {
None
}
})
}
pub fn format_context(
original_graph: Rc<PositiveSystemGraph>,
color: String,
ot: OperationType,
set: Set,
) -> Box<RSformatEdgeTy> {
Box::new(move |_, e| {
let rssystem = original_graph.edge_weight(e.id()).unwrap();
if ot.evaluate_positive(&rssystem.context, &set) {
Some(", color=".to_string() + &color)
} else {
None
}
})
}
pub fn format_t(
original_graph: Rc<PositiveSystemGraph>,
color: String,
ot: OperationType,
set: Set,
) -> Box<RSformatEdgeTy> {
Box::new(move |_, e| {
let rssystem = original_graph.edge_weight(e.id()).unwrap();
if ot.evaluate_positive(&rssystem.t, &set) {
Some(", color=".to_string() + &color)
} else {
None
}
})
}
pub fn format_reactants(
original_graph: Rc<PositiveSystemGraph>,
color: String,
ot: OperationType,
set: Set,
) -> Box<RSformatEdgeTy> {
Box::new(move |_, e| {
let rssystem = original_graph.edge_weight(e.id()).unwrap();
if ot.evaluate_positive(&rssystem.reactants, &set) {
Some(", color=".to_string() + &color)
} else {
None
}
})
}
pub fn format_reactants_absent(
original_graph: Rc<PositiveSystemGraph>,
color: String,
ot: OperationType,
set: Set,
) -> Box<RSformatEdgeTy> {
Box::new(move |_, e| {
let rssystem = original_graph.edge_weight(e.id()).unwrap();
if ot.evaluate_positive(&rssystem.reactants_absent, &set) {
Some(", color=".to_string() + &color)
} else {
None
}
})
}
pub fn format_inhibitors(
original_graph: Rc<PositiveSystemGraph>,
color: String,
ot: OperationType,
set: Set,
) -> Box<RSformatEdgeTy> {
Box::new(move |_, e| {
let rssystem = original_graph.edge_weight(e.id()).unwrap();
if ot.evaluate_positive(&rssystem.inhibitors, &set) {
Some(", color=".to_string() + &color)
} else {
None
}
})
}
pub fn format_inhibitors_present(
original_graph: Rc<PositiveSystemGraph>,
color: String,
ot: OperationType,
set: Set,
) -> Box<RSformatEdgeTy> {
Box::new(move |_, e| {
let rssystem = original_graph.edge_weight(e.id()).unwrap();
if ot.evaluate_positive(&rssystem.inhibitors_present, &set) {
Some(", color=".to_string() + &color)
} else {
None
}
})
}
pub fn format_products(
original_graph: Rc<PositiveSystemGraph>,
color: String,
ot: OperationType,
set: Set,
) -> Box<RSformatEdgeTy> {
Box::new(move |_, e| {
let rssystem = original_graph.edge_weight(e.id()).unwrap();
if ot.evaluate_positive(&rssystem.products, &set) {
Some(", color=".to_string() + &color)
} else {
None
}
})
}
}

View File

@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
use super::element::IdType;
use super::label::{Label, PositiveLabel};
use super::set::{BasicSet, Set};
use super::set::{BasicSet, PositiveSet, Set};
use super::system::{PositiveSystem, System};
use super::translator;
@ -17,6 +17,10 @@ pub type SystemGraph = Graph<System, Label, Directed, u32>;
pub type PositiveSystemGraph =
Graph<PositiveSystem, PositiveLabel, Directed, u32>;
// -----------------------------------------------------------------------------
// Helpers
// -----------------------------------------------------------------------------
fn common_system_entities(graph: &SystemGraph) -> Set {
graph
.node_references()
@ -27,6 +31,17 @@ fn common_system_entities(graph: &SystemGraph) -> Set {
.unwrap_or(Set::default())
}
fn positive_common_system_entities(graph: &PositiveSystemGraph) -> Set {
graph
.node_references()
.fold(None, |acc, node| match acc {
| None => Some(node.1.available_entities.elements()),
| Some(acc) =>
Some(node.1.available_entities.elements().intersection(&acc)),
})
.unwrap_or(Set::default())
}
macro_rules! common_label {
(
$name:ident,
@ -98,6 +113,86 @@ common_label!(
.intersection(&acc)
);
macro_rules! common_positive_label {
(
$name:ident,
[$edge_name:ident, $acc_name:ident],
$empty_expr:expr,
$some_expr:expr
) => {
fn $name(graph: &PositiveSystemGraph) -> Set {
graph
.edge_references()
.fold(None, |$acc_name, $edge_name| {
let $edge_name = $edge_name.weight();
match $acc_name {
| None => Some($empty_expr),
| Some($acc_name) => Some($some_expr),
}
})
.unwrap_or(Set::default())
}
};
}
common_positive_label!(
common_positive_label_products,
[edge, acc],
edge.products.elements(),
edge.products.elements().intersection(&acc)
);
common_positive_label!(
common_positive_label_entities,
[edge, acc],
edge.available_entities.elements(),
edge.available_entities.elements().intersection(&acc)
);
common_positive_label!(
common_positive_label_context,
[edge, acc],
edge.context.elements(),
edge.context.elements().intersection(&acc)
);
common_positive_label!(
common_positive_label_union,
[edge, acc],
edge.t.elements(),
edge.t.elements().intersection(&acc)
);
common_positive_label!(
common_positive_label_difference,
[edge, acc],
edge.context
.elements()
.subtraction(&edge.available_entities.elements()),
edge.context
.elements()
.subtraction(&edge.available_entities.elements())
.intersection(&acc)
);
common_positive_label!(
common_positive_label_entities_deleted,
[edge, acc],
edge.available_entities
.elements()
.subtraction(&edge.products.elements()),
edge.available_entities
.elements()
.subtraction(&edge.products.elements())
.intersection(&acc)
);
common_positive_label!(
common_positive_label_entities_added,
[edge, acc],
edge.products
.elements()
.subtraction(&edge.available_entities.elements()),
edge.products
.elements()
.subtraction(&edge.available_entities.elements())
.intersection(&acc)
);
// Nodes -----------------------------------------------------------------------
/// Helper structure that specifies what information to display for nodes.
@ -121,33 +216,61 @@ pub struct NodeDisplay {
type GraphMapNodesFnTy<'a> =
dyn Fn(petgraph::prelude::NodeIndex, &'a System) -> String + 'a;
type PositiveGraphMapNodesFnTy<'a> =
dyn Fn(petgraph::prelude::NodeIndex, &'a PositiveSystem) -> String + 'a;
impl NodeDisplayBase {
fn match_node_display<'a>(
base: &NodeDisplayBase,
&self,
common_entities: Rc<Set>,
translator: Rc<translator::Translator>,
) -> Box<GraphMapNodesFnTy<'a>> {
use NodeDisplayBase::*;
use super::format_helpers::graph_map_nodes_ty_from::*;
match base {
| String { string } => format_string(string.clone()),
| Hide => format_hide(translator),
| Entities => format_entities(translator),
| MaskEntities { mask } =>
match self {
| Self::String { string } => format_string(string.clone()),
| Self::Hide => format_hide(translator),
| Self::Entities => format_entities(translator),
| Self::MaskEntities { mask } =>
format_mask_entities(translator, mask.clone()),
| ExcludeEntities { mask } =>
| Self::ExcludeEntities { mask } =>
format_exclude_entities(translator, mask.clone()),
| Context => format_context(translator),
| UncommonEntities =>
| Self::Context => format_context(translator),
| Self::UncommonEntities =>
format_exclude_entities(translator, (*common_entities).clone()),
| MaskUncommonEntities { mask } => format_exclude_entities(
| Self::MaskUncommonEntities { mask } => format_exclude_entities(
translator,
mask.intersection(&common_entities),
),
}
}
fn positive_match_node_display<'a>(
&self,
common_entities: Rc<Set>,
translator: Rc<translator::Translator>,
) -> Box<PositiveGraphMapNodesFnTy<'a>> {
use super::format_helpers::positive_graph_map_nodes_ty_from::*;
match self {
| Self::String { string } => format_string(string.clone()),
| Self::Hide => format_hide(translator),
| Self::Entities => format_entities(translator),
| Self::MaskEntities { mask } =>
format_mask_entities(translator, mask.clone()),
| Self::ExcludeEntities { mask } =>
format_exclude_entities(translator, mask.clone()),
| Self::Context => format_context(translator),
| Self::UncommonEntities =>
format_exclude_entities(translator, (*common_entities).clone()),
| Self::MaskUncommonEntities { mask } => format_exclude_entities(
translator,
mask.intersection(&common_entities),
),
}
}
}
impl NodeDisplay {
fn contains_uncommon(&self) -> bool {
self.base.iter().any(|b| {
@ -173,8 +296,32 @@ impl NodeDisplay {
Box::new(move |i, n| {
let mut accumulator = String::new();
for b in &self.base {
let f = match_node_display(
b,
let f = b.match_node_display(
Rc::clone(&common_entities),
Rc::clone(&translator),
);
accumulator.push_str(&(f)(i, n));
}
accumulator
})
}
pub fn generate_positive<'a>(
self,
translator: Rc<translator::Translator>,
current_graph: &PositiveSystemGraph,
) -> Box<PositiveGraphMapNodesFnTy<'a>> {
let common_entities = if self.contains_uncommon() {
Rc::new(positive_common_system_entities(current_graph))
} else {
Rc::new(Set::default())
};
Box::new(move |i, n| {
let mut accumulator = String::new();
for b in &self.base {
let f = b.positive_match_node_display(
Rc::clone(&common_entities),
Rc::clone(&translator),
);
@ -232,6 +379,9 @@ pub struct EdgeDisplay {
type GraphMapEdgesFnTy<'a> =
dyn Fn(petgraph::prelude::EdgeIndex, &'a Label) -> String + 'a;
type PositiveGraphMapEdgesFnTy<'a> =
dyn Fn(petgraph::prelude::EdgeIndex, &'a PositiveLabel) -> String + 'a;
#[derive(Default, Clone)]
struct CommonEntities {
common_products: Set,
@ -243,19 +393,19 @@ struct CommonEntities {
common_entities_added: Set,
}
impl EdgeDisplayBase {
fn match_edge_display<'a>(
base: &'a EdgeDisplayBase,
&'a self,
translator: Rc<translator::Translator>,
common: CommonEntities,
) -> Box<GraphMapEdgesFnTy<'a>> {
use EdgeDisplayBase::*;
use super::format_helpers::graph_map_edges_ty_from::*;
match base {
| String { string } => format_string(translator, string.clone()),
| Hide => format_hide(translator),
| Products {
match self {
| Self::String { string } =>
format_string(translator, string.clone()),
| Self::Hide => format_hide(translator),
| Self::Products {
mask,
filter_common,
} =>
@ -268,7 +418,7 @@ fn match_edge_display<'a>(
} else {
format_products(translator, mask.clone(), None)
},
| Entities {
| Self::Entities {
mask,
filter_common,
} =>
@ -281,7 +431,7 @@ fn match_edge_display<'a>(
} else {
format_entities(translator, mask.clone(), None)
},
| Context {
| Self::Context {
mask,
filter_common,
} =>
@ -294,7 +444,7 @@ fn match_edge_display<'a>(
} else {
format_context(translator, mask.clone(), None)
},
| Union {
| Self::Union {
mask,
filter_common,
} =>
@ -307,7 +457,7 @@ fn match_edge_display<'a>(
} else {
format_union(translator, mask.clone(), None)
},
| Difference {
| Self::Difference {
mask,
filter_common,
} =>
@ -320,7 +470,7 @@ fn match_edge_display<'a>(
} else {
format_difference(translator, mask.clone(), None)
},
| EntitiesDeleted {
| Self::EntitiesDeleted {
mask,
filter_common,
} =>
@ -333,7 +483,7 @@ fn match_edge_display<'a>(
} else {
format_entities_deleted(translator, mask.clone(), None)
},
| EntitiesAdded {
| Self::EntitiesAdded {
mask,
filter_common,
} =>
@ -349,6 +499,112 @@ fn match_edge_display<'a>(
}
}
fn positive_match_edge_display<'a>(
&'a self,
translator: Rc<translator::Translator>,
common: CommonEntities,
) -> Box<PositiveGraphMapEdgesFnTy<'a>> {
use super::format_helpers::positive_graph_map_edges_ty_from::*;
match self {
| Self::String { string } =>
format_string(translator, string.clone()),
| Self::Hide => format_hide(translator),
| Self::Products {
mask,
filter_common,
} =>
if *filter_common {
format_products(
translator,
mask.clone(),
Some(common.common_products),
)
} else {
format_products(translator, mask.clone(), None)
},
| Self::Entities {
mask,
filter_common,
} =>
if *filter_common {
format_entities(
translator,
mask.clone(),
Some(common.common_entities),
)
} else {
format_entities(translator, mask.clone(), None)
},
| Self::Context {
mask,
filter_common,
} =>
if *filter_common {
format_context(
translator,
mask.clone(),
Some(common.common_context),
)
} else {
format_context(translator, mask.clone(), None)
},
| Self::Union {
mask,
filter_common,
} =>
if *filter_common {
format_union(
translator,
mask.clone(),
Some(common.common_union),
)
} else {
format_union(translator, mask.clone(), None)
},
| Self::Difference {
mask,
filter_common,
} =>
if *filter_common {
format_difference(
translator,
mask.clone(),
Some(common.common_difference),
)
} else {
format_difference(translator, mask.clone(), None)
},
| Self::EntitiesDeleted {
mask,
filter_common,
} =>
if *filter_common {
format_entities_deleted(
translator,
mask.clone(),
Some(common.common_entities_deleted),
)
} else {
format_entities_deleted(translator, mask.clone(), None)
},
| Self::EntitiesAdded {
mask,
filter_common,
} =>
if *filter_common {
format_entities_added(
translator,
mask.clone(),
Some(common.common_entities_added),
)
} else {
format_entities_added(translator, mask.clone(), None)
},
}
}
}
macro_rules! common_entity {
($name:ident, $match:pat, $filter_common:ident) => {
fn $name(&self) -> bool {
@ -458,8 +714,56 @@ impl EdgeDisplay {
Box::new(move |i, n| {
let mut accumulator = String::new();
for b in &self.base {
let f = match_edge_display(
b,
let f = b
.match_edge_display(Rc::clone(&translator), common.clone());
accumulator.push_str(&(f)(i, n));
}
accumulator
})
}
pub fn generate_positive<'a>(
self,
translator: Rc<translator::Translator>,
current_graph: &PositiveSystemGraph,
) -> Box<PositiveGraphMapEdgesFnTy<'a>> {
// create the structure for common entities if required
let common = {
let mut tmp = CommonEntities::default();
if self.common_products() {
tmp.common_products =
common_positive_label_products(current_graph);
}
if self.common_entities() {
tmp.common_entities =
common_positive_label_entities(current_graph);
}
if self.common_context() {
tmp.common_context =
common_positive_label_context(current_graph);
}
if self.common_union() {
tmp.common_union = common_positive_label_union(current_graph);
}
if self.common_difference() {
tmp.common_difference =
common_positive_label_difference(current_graph);
}
if self.common_entities_deleted() {
tmp.common_entities_deleted =
common_positive_label_entities_deleted(current_graph);
}
if self.common_entities_added() {
tmp.common_entities_added =
common_positive_label_entities_added(current_graph);
}
tmp
};
Box::new(move |i, n| {
let mut accumulator = String::new();
for b in &self.base {
let f = b.positive_match_edge_display(
Rc::clone(&translator),
common.clone(),
);
@ -506,6 +810,19 @@ impl OperationType {
| Self::SupersetEqual => b.is_subset(a),
}
}
pub fn evaluate_positive(&self, a: &PositiveSet, b: &Set) -> bool {
match self {
| Self::Equals =>
a.elements().is_subset(b) && b.is_subset(&a.elements()),
| Self::Subset =>
a.elements().is_subset(b) && !b.is_subset(&a.elements()),
| Self::SubsetEqual => a.elements().is_subset(b),
| Self::Superset =>
b.is_subset(&a.elements()) && !a.elements().is_subset(b),
| Self::SupersetEqual => b.is_subset(&a.elements()),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize, Hash)]
@ -535,50 +852,55 @@ fn node_formatter_base_color(base_color: String) -> String {
", fillcolor=".to_string() + &base_color
}
#[inline(always)]
impl NodeColorConditional {
fn match_node_color_conditional<'a>(
rule: &'a NodeColorConditional,
&self,
color: &'a String,
original_graph: Rc<SystemGraph>,
star: Option<IdType>,
) -> Box<RSformatNodeTyOpt<'a>> {
use super::format_helpers::node_formatter::*;
match rule {
| NodeColorConditional::ContextConditional(ccc) => match ccc {
| ContextColorConditional::Nill =>
match self {
| Self::ContextConditional(ContextColorConditional::Nill) =>
format_nill(Rc::clone(&original_graph), color.to_string(), star),
| ContextColorConditional::RecursiveIdentifier(s) =>
format_recursive_identifier(
| Self::ContextConditional(
ContextColorConditional::RecursiveIdentifier(s),
) => format_recursive_identifier(
Rc::clone(&original_graph),
color.to_string(),
star,
*s,
),
| ContextColorConditional::EntitySet(ot, set) => format_entity_set(
| Self::ContextConditional(ContextColorConditional::EntitySet(
ot,
set,
)) => format_entity_set(
Rc::clone(&original_graph),
color.to_string(),
star,
*ot,
set.clone(),
),
| ContextColorConditional::NonDeterministicChoice =>
format_non_deterministic_choice(
| Self::ContextConditional(
ContextColorConditional::NonDeterministicChoice,
) => format_non_deterministic_choice(
Rc::clone(&original_graph),
color.to_string(),
star,
),
| ContextColorConditional::Summation => format_summation(
| Self::ContextConditional(ContextColorConditional::Summation) =>
format_summation(
Rc::clone(&original_graph),
color.to_string(),
star,
),
| ContextColorConditional::WaitEntity => format_wait_entity(
| Self::ContextConditional(ContextColorConditional::WaitEntity) =>
format_wait_entity(
Rc::clone(&original_graph),
color.to_string(),
star,
),
},
| NodeColorConditional::EntitiesConditional(ot, set) =>
| Self::EntitiesConditional(ot, set) =>
format_entities_conditional(
Rc::clone(&original_graph),
color.to_string(),
@ -589,6 +911,65 @@ fn match_node_color_conditional<'a>(
}
}
fn match_positive_node_color_conditional<'a>(
&self,
color: &'a String,
original_graph: Rc<PositiveSystemGraph>,
star: Option<IdType>,
) -> Box<RSformatNodeTyOpt<'a>> {
use super::format_helpers::positive_node_formatter::*;
match self {
| Self::ContextConditional(ContextColorConditional::Nill) =>
format_nill(Rc::clone(&original_graph), color.to_string(), star),
| Self::ContextConditional(
ContextColorConditional::RecursiveIdentifier(s),
) => format_recursive_identifier(
Rc::clone(&original_graph),
color.to_string(),
star,
*s,
),
| Self::ContextConditional(ContextColorConditional::EntitySet(
ot,
set,
)) => format_entity_set(
Rc::clone(&original_graph),
color.to_string(),
star,
*ot,
set.clone(),
),
| Self::ContextConditional(
ContextColorConditional::NonDeterministicChoice,
) => format_non_deterministic_choice(
Rc::clone(&original_graph),
color.to_string(),
star,
),
| Self::ContextConditional(ContextColorConditional::Summation) =>
format_summation(
Rc::clone(&original_graph),
color.to_string(),
star,
),
| Self::ContextConditional(ContextColorConditional::WaitEntity) =>
format_wait_entity(
Rc::clone(&original_graph),
color.to_string(),
star,
),
| Self::EntitiesConditional(ot, set) =>
format_entities_conditional(
Rc::clone(&original_graph),
color.to_string(),
star,
*ot,
set.clone(),
),
}
}
}
impl NodeColor {
pub fn generate<'a>(
self,
@ -597,8 +978,28 @@ impl NodeColor {
) -> Box<RSformatNodeTy<'a>> {
Box::new(move |i, n| {
for (rule, color) in &self.conditionals {
let f = match_node_color_conditional(
rule,
let f = rule.match_node_color_conditional(
color,
Rc::clone(&original_graph),
star,
);
if let Some(s) = (f)(i, n) {
return s;
}
}
node_formatter_base_color(self.base_color.clone())
})
}
pub fn generate_positive<'a>(
self,
original_graph: Rc<PositiveSystemGraph>,
star: Option<IdType>,
) -> Box<RSformatNodeTy<'a>> {
Box::new(move |i, n| {
for (rule, color) in &self.conditionals {
let f = rule.match_positive_node_color_conditional(
color,
Rc::clone(&original_graph),
star,
@ -648,58 +1049,57 @@ fn edge_formatter_base_color(base_color: String) -> String {
", color=".to_string() + &base_color
}
impl EdgeColorConditional {
fn match_edge_color_conditional<'a>(
rule: &'a EdgeColorConditional,
&'a self,
color: &'a String,
original_graph: Rc<SystemGraph>,
) -> Box<RSformatEdgeTyOpt<'a>> {
use super::format_helpers::edge_formatter::*;
match rule {
| EdgeColorConditional::Entities(ot, set) => format_entities(
match self {
| Self::Entities(ot, set) => format_entities(
Rc::clone(&original_graph),
color.to_string(),
*ot,
set.clone(),
),
| EdgeColorConditional::Context(ot, set) => format_context(
| Self::Context(ot, set) => format_context(
Rc::clone(&original_graph),
color.to_string(),
*ot,
set.clone(),
),
| EdgeColorConditional::T(ot, set) => format_t(
| Self::T(ot, set) => format_t(
Rc::clone(&original_graph),
color.to_string(),
*ot,
set.clone(),
),
| EdgeColorConditional::Reactants(ot, set) => format_reactants(
| Self::Reactants(ot, set) => format_reactants(
Rc::clone(&original_graph),
color.to_string(),
*ot,
set.clone(),
),
| EdgeColorConditional::ReactantsAbsent(ot, set) =>
format_reactants_absent(
| Self::ReactantsAbsent(ot, set) => format_reactants_absent(
Rc::clone(&original_graph),
color.to_string(),
*ot,
set.clone(),
),
| EdgeColorConditional::Inhibitors(ot, set) => format_inhibitors(
| Self::Inhibitors(ot, set) => format_inhibitors(
Rc::clone(&original_graph),
color.to_string(),
*ot,
set.clone(),
),
| EdgeColorConditional::InhibitorsPresent(ot, set) =>
format_inhibitors_present(
| Self::InhibitorsPresent(ot, set) => format_inhibitors_present(
Rc::clone(&original_graph),
color.to_string(),
*ot,
set.clone(),
),
| EdgeColorConditional::Products(ot, set) => format_products(
| Self::Products(ot, set) => format_products(
Rc::clone(&original_graph),
color.to_string(),
*ot,
@ -708,6 +1108,66 @@ fn match_edge_color_conditional<'a>(
}
}
fn match_positive_edge_color_conditional<'a>(
&'a self,
color: &'a String,
original_graph: Rc<PositiveSystemGraph>,
) -> Box<RSformatEdgeTyOpt<'a>> {
use super::format_helpers::positive_edge_formatter::*;
match self {
| Self::Entities(ot, set) => format_entities(
Rc::clone(&original_graph),
color.to_string(),
*ot,
set.clone(),
),
| Self::Context(ot, set) => format_context(
Rc::clone(&original_graph),
color.to_string(),
*ot,
set.clone(),
),
| Self::T(ot, set) => format_t(
Rc::clone(&original_graph),
color.to_string(),
*ot,
set.clone(),
),
| Self::Reactants(ot, set) => format_reactants(
Rc::clone(&original_graph),
color.to_string(),
*ot,
set.clone(),
),
| Self::ReactantsAbsent(ot, set) => format_reactants_absent(
Rc::clone(&original_graph),
color.to_string(),
*ot,
set.clone(),
),
| Self::Inhibitors(ot, set) => format_inhibitors(
Rc::clone(&original_graph),
color.to_string(),
*ot,
set.clone(),
),
| Self::InhibitorsPresent(ot, set) => format_inhibitors_present(
Rc::clone(&original_graph),
color.to_string(),
*ot,
set.clone(),
),
| Self::Products(ot, set) => format_products(
Rc::clone(&original_graph),
color.to_string(),
*ot,
set.clone(),
),
}
}
}
impl EdgeColor {
pub fn generate<'a>(
self,
@ -715,8 +1175,26 @@ impl EdgeColor {
) -> Box<RSformatEdgeTy<'a>> {
Box::new(move |i, n| {
for (rule, color) in &self.conditionals {
let f = match_edge_color_conditional(
rule,
let f = rule.match_edge_color_conditional(
color,
Rc::clone(&original_graph),
);
if let Some(s) = (f)(i, n) {
return s;
}
}
edge_formatter_base_color(self.base_color.clone())
})
}
pub fn generate_positive<'a>(
self,
original_graph: Rc<PositiveSystemGraph>,
) -> Box<RSformatEdgeTy<'a>> {
Box::new(move |i, n| {
for (rule, color) in &self.conditionals {
let f = rule.match_positive_edge_color_conditional(
color,
Rc::clone(&original_graph),
);

View File

@ -704,4 +704,8 @@ impl PositiveSet {
.collect::<PositiveSet>()
.union(self)
}
pub fn elements(&self) -> Set {
self.iter().map(|el| *el.0).collect::<Vec<_>>().into()
}
}