Support for excluding common entities and excluding custom ones

This commit is contained in:
elvis
2025-07-16 16:20:29 +02:00
parent 0ef51200e5
commit 23ce9c3488
4 changed files with 90 additions and 8 deletions

View File

@ -272,11 +272,20 @@ LiteralSeparatorEdge: presets::EdgeDisplay = {
};
NodeDisplay: presets::NodeDisplay = {
"Hide" => presets::NodeDisplay::Display(graph::GraphMapNodes::Hide),
"Entities" => presets::NodeDisplay::Display(graph::GraphMapNodes::Entities),
"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)
"Context" =>
presets::NodeDisplay::Display(graph::GraphMapNodes::Context),
"UncommonEntities" =>
presets::NodeDisplay::UncommonEntities,
"MaskUncommonentities" <mask: Set> =>
presets::NodeDisplay::MaskUncommonEntities(mask),
"ExcludeEntities" <mask: Set> =>
presets::NodeDisplay::Display(graph::GraphMapNodes::ExcludeEntities{mask})
}
/// Node display formatters separated by arbitrary strings in quotes

View File

@ -41,6 +41,20 @@ pub fn digraph(
Ok(graph)
}
pub fn common_entities(
graph: &RSgraph
) -> RSset {
graph.node_references().fold(
None,
|acc, node|
match acc {
None => Some(node.1.available_entities.clone()),
Some(acc) => Some(node.1.available_entities.intersection(&acc))
}
).unwrap_or(RSset::new())
}
// -----------------------------------------------------------------------------
// helper functions
// -----------------------------------------------------------------------------
@ -54,6 +68,7 @@ pub enum GraphMapNodes {
Hide,
Entities,
MaskEntities { mask: RSset },
ExcludeEntities { mask: RSset },
Context,
}
@ -108,6 +123,20 @@ impl GraphMapNodesTy {
}
)
},
ExcludeEntities { mask } => {
Box::new(
move |_, node: &RSsystem| {
let masked_entities =
node.available_entities
.subtraction(&mask);
format!("{}",
translator::RSsetDisplay::from(
&translator,
&masked_entities)
)
}
)
}
Context => {
Box::new(
move |_, node: &RSsystem|

View File

@ -62,6 +62,8 @@ impl Default for SaveOptions {
pub enum NodeDisplay {
Separator(String),
Display(graph::GraphMapNodes),
UncommonEntities,
MaskUncommonEntities(RSset)
}
@ -539,6 +541,7 @@ pub fn bisimilar(
#[allow(clippy::type_complexity)]
fn generate_node_pringting_fn<'a>(
node_display: &'a Vec<NodeDisplay>,
graph: &graph::RSgraph,
translator: Rc<Translator>,
) -> Box<dyn Fn(petgraph::prelude::NodeIndex, &'a RSsystem) -> String + 'a> {
// The type cannot be aliased since rust doesnt like generics.
@ -557,11 +560,43 @@ fn generate_node_pringting_fn<'a>(
(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)
},
// ad hoc since graph information is not available in the graph
// function generation
NodeDisplay::UncommonEntities => {
let common_entities = graph::common_entities(graph);
let val = translator.clone();
Box::new(move |i, n| {
(accumulator)(i, n)
+ &graph::GraphMapNodesTy::from(
graph::GraphMapNodes::ExcludeEntities {
mask: common_entities.clone()
},
val.clone()
).get()(i, n)
}
)
},
// ad hoc since graph information is not available in the graph
// function generation
NodeDisplay::MaskUncommonEntities(mask) => {
let common_entities = graph::common_entities(graph);
let val = translator.clone();
Box::new(move |i, n| {
(accumulator)(i, n)
+ &graph::GraphMapNodesTy::from(
graph::GraphMapNodes::ExcludeEntities {
mask: common_entities.union(mask)
},
val.clone()
).get()(i, n)
}
)
},
};
}
accumulator
@ -666,6 +701,7 @@ pub fn dot(
// fine...
let modified_graph = graph.map(
generate_node_pringting_fn(&node_display,
graph,
Rc::clone(&rc_translator)),
generate_edge_pringting_fn(&edge_display,
Rc::clone(&rc_translator)),
@ -707,6 +743,7 @@ pub fn graphml(
// map each value to the corresponding value we want to display
let modified_graph = graph.map(
generate_node_pringting_fn(&node_display,
graph,
Rc::clone(&rc_translator)),
generate_edge_pringting_fn(&edge_display,
rc_translator),

View File

@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize};
// -----------------------------------------------------------------------------
/// Basic set of entities.
#[derive(Clone, Debug, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialOrd, Eq, Ord, Serialize, Deserialize)]
pub struct RSset {
pub identifiers: BTreeSet<IdType>,
}
@ -79,7 +79,7 @@ impl RSset {
RSset { identifiers: res }
}
/// returns the new set a \ b
/// returns the new set a b
pub fn subtraction(&self, b: &RSset) -> RSset {
// TODO maybe find more efficient way without copy/clone
let res: BTreeSet<_> = self
@ -123,6 +123,12 @@ impl PartialEq for RSset {
}
}
impl Hash for RSset {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.identifiers.hash(state)
}
}
impl IntoIterator for RSset {
type Item = IdType;
type IntoIter = std::collections::btree_set::IntoIter<Self::Item>;
@ -564,7 +570,8 @@ impl PartialEq for RSlabel {
fn eq(&self, other: &Self) -> bool {
self.available_entities == other.available_entities &&
self.context == other.context &&
self.t == other.t &&
// self.t == other.t && // no need since its the union of the above
// // elements
self.reactants == other.reactants &&
self.reactants_absent == other.reactants_absent &&
self.inhibitors == other.inhibitors &&