Positive version of assert and group functions w/ parsers
Grouping function in execution::data
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
use petgraph::{Directed, Graph};
|
||||
use rsprocess::graph::SystemGraph;
|
||||
use rsprocess::label::Label;
|
||||
use rsprocess::system::System;
|
||||
use rsprocess::graph::{PositiveSystemGraph, SystemGraph};
|
||||
use rsprocess::label::{Label, PositiveLabel};
|
||||
use rsprocess::system::{PositiveSystem, System};
|
||||
use rsprocess::translator;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -58,3 +58,158 @@ impl<'a> MapEdges<'a, System, Label, Directed, u32> for SystemGraph {
|
||||
Ok(g)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Very inelegant way to provide our graph with a map method where the edges
|
||||
/// are mapped until the first error.
|
||||
pub trait PositiveMapEdges<'a, N: 'a, E, Ty, Ix>
|
||||
where
|
||||
Ty: petgraph::EdgeType,
|
||||
Ix: petgraph::graph::IndexType,
|
||||
{
|
||||
fn map_edges(
|
||||
&self,
|
||||
edge_map: &assert::positive_relabel::PositiveAssert,
|
||||
translator: &mut translator::Translator,
|
||||
) -> Result<Graph<PositiveSystem, assert::positive_relabel::PositiveAssertReturnValue, Ty, Ix>, String>;
|
||||
}
|
||||
|
||||
impl<'a> PositiveMapEdges<'a, PositiveSystem, PositiveLabel, Directed, u32> for PositiveSystemGraph {
|
||||
fn map_edges(
|
||||
&self,
|
||||
edge_map: &assert::positive_relabel::PositiveAssert,
|
||||
translator: &mut translator::Translator,
|
||||
) -> Result<Graph<PositiveSystem, assert::positive_relabel::PositiveAssertReturnValue, Directed, u32>, String>
|
||||
{
|
||||
use petgraph::graph::EdgeIndex;
|
||||
|
||||
let mut g = Graph::with_capacity(self.node_count(), self.edge_count());
|
||||
let nodes = self.raw_nodes();
|
||||
let edges = self.raw_edges();
|
||||
|
||||
let edges = edges
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, edge)| {
|
||||
match edge_map.execute(self, &EdgeIndex::new(i), translator) {
|
||||
| Err(e) => Err(e),
|
||||
| Ok(val) => Ok((edge.source(), edge.target(), val)),
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
nodes.iter().for_each(|node| {
|
||||
g.add_node(node.weight.clone());
|
||||
});
|
||||
|
||||
edges.into_iter().for_each(|(source, target, v)| {
|
||||
g.add_edge(source, target, v);
|
||||
});
|
||||
|
||||
Ok(g)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Given a graph and a function that identifies nodes of the graph, merges
|
||||
/// nodes with the same identifier.
|
||||
pub fn grouping(
|
||||
graph: &mut Graph<System, Label>,
|
||||
group: &assert::grouping::Assert,
|
||||
translator: &mut rsprocess::translator::Translator
|
||||
) -> Result<(), String> {
|
||||
let mut buckets = std::collections::HashMap::new();
|
||||
let mut leader: std::collections::HashMap<petgraph::prelude::NodeIndex, _> = std::collections::HashMap::new();
|
||||
|
||||
for node in graph.node_indices() {
|
||||
let val = group.execute(graph, &node, translator)?;
|
||||
buckets.entry(val.clone()).or_insert(vec![]).push(node);
|
||||
let l = buckets.get(&val).unwrap().first().unwrap();
|
||||
leader.insert(node, (*l, val));
|
||||
}
|
||||
|
||||
for node in graph.node_indices().rev() {
|
||||
let (origin, val) = leader.get(&node).unwrap();
|
||||
if *origin == node {
|
||||
continue;
|
||||
}
|
||||
if buckets.get(val).unwrap().len() <= 1 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut edges =
|
||||
graph.neighbors_directed(node, petgraph::Outgoing).detach();
|
||||
while let Some(edge) = edges.next_edge(graph) {
|
||||
graph.add_edge(
|
||||
*origin,
|
||||
graph.edge_endpoints(edge).unwrap().1,
|
||||
graph.edge_weight(edge).unwrap().clone(),
|
||||
);
|
||||
}
|
||||
let mut edges =
|
||||
graph.neighbors_directed(node, petgraph::Incoming).detach();
|
||||
while let Some(edge) = edges.next_edge(graph) {
|
||||
graph.add_edge(
|
||||
graph.edge_endpoints(edge).unwrap().0,
|
||||
*origin,
|
||||
graph.edge_weight(edge).unwrap().clone(),
|
||||
);
|
||||
}
|
||||
graph
|
||||
.remove_node(node)
|
||||
.ok_or(format!("Could not remove node {node:?}"))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Given a graph and a function that identifies nodes of the graph, merges
|
||||
/// nodes with the same identifier.
|
||||
pub fn positive_grouping(
|
||||
graph: &mut Graph<PositiveSystem, PositiveLabel>,
|
||||
group: &assert::positive_grouping::PositiveAssert,
|
||||
translator: &mut rsprocess::translator::Translator
|
||||
) -> Result<(), String> {
|
||||
let mut buckets = std::collections::HashMap::new();
|
||||
let mut leader: std::collections::HashMap<petgraph::prelude::NodeIndex, _> = std::collections::HashMap::new();
|
||||
|
||||
for node in graph.node_indices() {
|
||||
let val = group.execute(graph, &node, translator)?;
|
||||
buckets.entry(val.clone()).or_insert(vec![]).push(node);
|
||||
let l = buckets.get(&val).unwrap().first().unwrap();
|
||||
leader.insert(node, (*l, val));
|
||||
}
|
||||
|
||||
for node in graph.node_indices().rev() {
|
||||
let (origin, val) = leader.get(&node).unwrap();
|
||||
if *origin == node {
|
||||
continue;
|
||||
}
|
||||
if buckets.get(val).unwrap().len() <= 1 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut edges =
|
||||
graph.neighbors_directed(node, petgraph::Outgoing).detach();
|
||||
while let Some(edge) = edges.next_edge(graph) {
|
||||
graph.add_edge(
|
||||
*origin,
|
||||
graph.edge_endpoints(edge).unwrap().1,
|
||||
graph.edge_weight(edge).unwrap().clone(),
|
||||
);
|
||||
}
|
||||
let mut edges =
|
||||
graph.neighbors_directed(node, petgraph::Incoming).detach();
|
||||
while let Some(edge) = edges.next_edge(graph) {
|
||||
graph.add_edge(
|
||||
graph.edge_endpoints(edge).unwrap().0,
|
||||
*origin,
|
||||
graph.edge_weight(edge).unwrap().clone(),
|
||||
);
|
||||
}
|
||||
graph
|
||||
.remove_node(node)
|
||||
.ok_or(format!("Could not remove node {node:?}"))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
//! Module that holds useful presets for interacting with other modules.
|
||||
use std::collections::HashMap;
|
||||
use std::io::prelude::*;
|
||||
use std::rc::Rc;
|
||||
use std::{env, fs, io};
|
||||
@ -629,7 +628,9 @@ where
|
||||
|
||||
/// Computes the LTS.
|
||||
/// equivalent to main_do(digraph, Arcs) or to main_do(advdigraph, Arcs)
|
||||
pub fn digraph(system: &mut EvaluatedSystem) -> Result<(), String> {
|
||||
pub fn digraph(
|
||||
system: &mut EvaluatedSystem,
|
||||
) -> Result<(), String> {
|
||||
if let (Some(sys), true) = (&system.sys, system.graph.is_none()) {
|
||||
let graph = sys.digraph()?;
|
||||
system.graph = Some(graph);
|
||||
@ -642,57 +643,16 @@ pub fn digraph(system: &mut EvaluatedSystem) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Given a graph and a function that identifies nodes of the graph, merges
|
||||
/// nodes with the same identifier.
|
||||
pub fn grouping(
|
||||
system: &mut EvaluatedSystem,
|
||||
group: &assert::grouping::Assert,
|
||||
) -> Result<(), String> {
|
||||
let mut buckets = HashMap::new();
|
||||
let mut leader: HashMap<petgraph::prelude::NodeIndex, _> = HashMap::new();
|
||||
|
||||
if let Some(graph) = &mut system.graph {
|
||||
for node in graph.node_indices() {
|
||||
let val = group.execute(graph, &node, &mut system.translator)?;
|
||||
println!("node: {node:?} -> val: {val:?}");
|
||||
buckets.entry(val.clone()).or_insert(vec![]).push(node);
|
||||
let l = buckets.get(&val).unwrap().first().unwrap();
|
||||
leader.insert(node, (*l, val));
|
||||
}
|
||||
|
||||
for node in graph.node_indices().rev() {
|
||||
let (origin, val) = leader.get(&node).unwrap();
|
||||
if *origin == node {
|
||||
continue;
|
||||
}
|
||||
if buckets.get(val).unwrap().len() <= 1 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut edges =
|
||||
graph.neighbors_directed(node, petgraph::Outgoing).detach();
|
||||
while let Some(edge) = edges.next_edge(graph) {
|
||||
graph.add_edge(
|
||||
*origin,
|
||||
graph.edge_endpoints(edge).unwrap().1,
|
||||
graph.edge_weight(edge).unwrap().clone(),
|
||||
);
|
||||
}
|
||||
let mut edges =
|
||||
graph.neighbors_directed(node, petgraph::Incoming).detach();
|
||||
while let Some(edge) = edges.next_edge(graph) {
|
||||
graph.add_edge(
|
||||
graph.edge_endpoints(edge).unwrap().0,
|
||||
*origin,
|
||||
graph.edge_weight(edge).unwrap().clone(),
|
||||
);
|
||||
}
|
||||
graph
|
||||
.remove_node(node)
|
||||
.ok_or(format!("Could not remove node {node:?}"))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
if system.graph.is_some() {
|
||||
super::data::grouping(
|
||||
system.graph.as_mut().unwrap(),
|
||||
group,
|
||||
&mut system.translator
|
||||
)
|
||||
} else {
|
||||
Err("Grouping can be done only on graphs.".into())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user