use petgraph::graph::Graph;
use crate::algorithms::vf2::find_mappings;
use crate::transformation::{Rule, Morphism};
use crate::transformation::util::{check_gluing, delete_part, add_part};
pub fn find_matches<N, E>(
rule: &Rule<N, E>,
host: &Graph<N, E>,
check_edge_labels: bool,
) -> Vec<Morphism>
where
N: Eq + Clone,
E: Eq + Clone,
{
assert!(rule.validate(), "DPO rule validation failed");
let node_maps = find_mappings(&rule.lhs, host, check_edge_labels);
node_maps
.into_iter()
.map(|node_map| {
let mut m = Morphism::new();
for (p_node, h_node) in node_map {
m.insert_node(p_node, h_node);
}
m
})
.collect()
}
pub fn apply_once<N, E>(
rule: &Rule<N, E>,
host: &Graph<N, E>,
m: &Morphism,
) -> Option<Graph<N, E>>
where
N: Clone,
E: Clone,
{
assert!(rule.validate(), "DPO rule validation failed");
let mut result = host.clone();
if !check_gluing(&result, m, rule) {
return None;
}
delete_part(&mut result, m, rule);
add_part(&mut result, m, rule);
Some(result)
}
pub fn apply<N, E>(
rule: &Rule<N, E>,
host: &Graph<N, E>,
check_edge_labels: bool,
) -> Vec<Graph<N, E>>
where
N: Eq + Clone,
E: Eq + Clone,
{
assert!(rule.validate(), "DPO rule validation failed");
fn recurse<N, E>(
rule: &Rule<N, E>,
current: Graph<N, E>,
check_edge_labels: bool,
results: &mut Vec<Graph<N, E>>,
)
where
N: Eq + Clone,
E: Eq + Clone,
{
let matches = find_matches(rule, ¤t, check_edge_labels);
if matches.is_empty() {
results.push(current);
} else {
for m in matches {
if let Some(next) = apply_once(rule, ¤t, &m) {
recurse(rule, next, check_edge_labels, results);
}
}
}
}
let mut finals = Vec::new();
recurse(rule, host.clone(), check_edge_labels, &mut finals);
finals
}