use petgraph::graph::{Graph, NodeIndex};
use petgraph::visit::EdgeRef;
use crate::transformation::rule::Rule;
use crate::transformation::morphism::Morphism;
pub fn delete_part<N, E>(host: &mut Graph<N, E>, m: &Morphism, rule: &Rule<N, E>) {
let inv_l2k = rule.l2k.invert();
for l_edge in rule.lhs.edge_indices() {
if inv_l2k.map_edge(&l_edge).is_none() {
let (l_src, l_dst) = rule.lhs.edge_endpoints(l_edge).unwrap();
if let (Some(&h_src), Some(&h_dst)) = (m.map_node(&l_src), m.map_node(&l_dst)) {
if let Some(e_idx) = host.find_edge(h_src, h_dst) {
host.remove_edge(e_idx);
}
}
}
}
let mut to_delete = Vec::new();
for l_node in rule.lhs.node_indices() {
if inv_l2k.map_node(&l_node).is_none() {
if let Some(&h_node) = m.map_node(&l_node) {
to_delete.push(h_node);
}
}
}
for node in to_delete {
host.remove_node(node);
}
}
pub fn add_part<N: Clone, E: Clone>(host: &mut Graph<N, E>, m: &Morphism, rule: &Rule<N, E>) {
let inv_k2r = rule.k2r.invert();
let inv_l2k = rule.l2k.invert();
let mut k_to_new: Vec<(NodeIndex, NodeIndex)> = Vec::new();
for r_node in rule.rhs.node_indices() {
if inv_k2r.map_node(&r_node).is_none() {
let weight = rule.rhs.node_weight(r_node).unwrap().clone();
let new_node = host.add_node(weight);
k_to_new.push((r_node, new_node));
}
}
for r_edge in rule.rhs.edge_indices() {
if inv_k2r.map_edge(&r_edge).is_none() {
let (r_src, r_dst) = rule.rhs.edge_endpoints(r_edge).unwrap();
let h_src = if let Some(&k_src) = inv_k2r.map_node(&r_src) {
let via_l = inv_l2k.map_node(&k_src).unwrap();
*m.map_node(via_l).unwrap()
} else {
k_to_new.iter().find(|&&(r,_)| r == r_src).unwrap().1
};
let h_dst = if let Some(&k_dst) = inv_k2r.map_node(&r_dst) {
let via_l = inv_l2k.map_node(&k_dst).unwrap();
*m.map_node(via_l).unwrap()
} else {
k_to_new.iter().find(|&&(r,_)| r == r_dst).unwrap().1
};
let e_weight = rule.rhs.edge_weight(r_edge).unwrap().clone();
host.add_edge(h_src, h_dst, e_weight);
}
}
}
pub fn check_gluing<N, E>(host: &Graph<N, E>, m: &Morphism, rule: &Rule<N, E>) -> bool {
for l_node in rule.lhs.node_indices() {
if rule.l2k.map_node(&l_node).is_none() {
if let Some(&h_node) = m.map_node(&l_node) {
for edge in host.edges(h_node) {
let other = if edge.source() == h_node {
edge.target()
} else {
edge.source()
};
let valid = rule.lhs.node_indices().any(|l2|
m.map_node(&l2).map(|&n| n == other).unwrap_or(false)
);
if !valid {
return false;
}
}
}
}
}
true
}