package org.eclipse.emf.henshin.model.staticanalysis;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.henshin.model.Graph;
import org.eclipse.emf.henshin.model.Node;
/**
* A <i>node equivalence</i> is a set <i>E</i> of at least 2 nodes in a graph <i>G</i>
* satisfying the following property:
* <ul>
* <li><i>for all nodes x≠y ∈ E there exists a bijective graph morphism m:G→G such that m(x)=y and m(y)=x (i.e. a non-trivial automorphism).</i></li>
* </ul>
* @author Christian Krause
*/
public class NodeEquivalence extends ArrayList<Node> {
private static final long serialVersionUID = 1L;
/**
* Compute the require node equivalences for a given rule.
* Every node equivalence has at least two nodes.
* @param rule The rule.
* @return The list of require node equivalences.
*/
public static List<NodeEquivalence> computeEquivalences(Graph graph) {
List<NodeEquivalence> equivalences = new ArrayList<NodeEquivalence>();
Set<Node> usedNodes = new HashSet<Node>();
for (Node x : graph.getNodes()) {
if (usedNodes.contains(x)) {
continue;
}
NodeEquivalence equivalence = new NodeEquivalence();
equivalence.add(x);
for (Node y : graph.getNodes()) {
if (x==y || usedNodes.contains(y) || x.getType()!=y.getType()) {
continue;
}
NodeMap map = new NodeMap(graph, graph);
for (Node z : graph.getNodes()) {
if (z==x) {
map.put(z, y);
} else if (z==y) {
map.put(z, x);
} else {
map.put(z, z);
}
}
if (map.isGraphMorphism()) {
try {
if (map.getInverse().isGraphMorphism()) {
equivalence.add(y);
usedNodes.add(x);
usedNodes.add(y);
}
} catch (Exception e) {
// do nothing
}
}
}
if (equivalence.size()>1) {
equivalences.add(equivalence);
}
}
return equivalences;
}
}