package org.simantics.graph.matching; import gnu.trove.list.array.TIntArrayList; import gnu.trove.map.hash.THashMap; import gnu.trove.map.hash.TIntIntHashMap; import gnu.trove.map.hash.TIntObjectHashMap; import gnu.trove.procedure.TObjectProcedure; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; /** * Matches isomorphic components of the not yet matched graphs together. * * @author Hannu Niemistö */ public enum ComponentMatchingStrategy implements GraphMatchingStrategy { INSTANCE; static class UnionFind { int[] canonical; public UnionFind(int size) { canonical = new int[size]; for(int i=0;i components = new TIntObjectHashMap(); for(int i=0;i() { int i = 0; @Override public boolean execute(TIntArrayList els) { result[i++] = els.toArray(); return true; } }); return result; } public static Stat[][] neighbors(int[] map, Stat[][] statements) { int resourceCount = map.length; Stat[][] neighbors = new Stat[resourceCount][]; ArrayList stats = new ArrayList(); for(int s=0;s= 0) { neighbors[s] = Stat.NO_STATS; continue; } for(Stat stat : statements[s]) { int pp = map[stat.p] >= 0 ? stat.p : -1; int oo = map[stat.o] >= 0 ? stat.o : -1; stats.add(new Stat(pp, oo)); } if(stats.isEmpty()) neighbors[s] = Stat.NO_STATS; else { neighbors[s] = stats.toArray(new Stat[stats.size()]); stats.clear(); } } return neighbors; } static class Component { int[] elements; Stat[][] neighbors; public Component(int[] elements, Stat[][] neighbors) { this.elements = elements; this.neighbors = new Stat[elements.length][]; for(int i=0;i PP_COMPARATOR = new Comparator() { @Override public int compare(PP o1, PP o2) { Stat[] stats1 = o1.stats; Stat[] stats2 = o2.stats; int l1 = stats1.length; int l2 = stats2.length; if(l1 < l2) return -1; else if(l1 > l2) return 1; for(int i=0;i s2.p) return 1; else if(s1.o < s2.o) return -1; else if(s1.o > s2.o) return 1; } return 0; } }; public void canonicalize(String[] elNames, String[] statNames) { PP[] pps = new PP[elements.length]; for(int i=0;i "); else System.out.print(" "); System.out.println(elNames[pps[i].element]); for(Stat stat : pps[i].stats) System.out.println(" " + stat.toString(statNames)); } break; } for(int i=0;i 0) return false; return true; } } static class TNeighbourObjectHashMap extends THashMap { @Override protected boolean equals(Object one, Object two) { Stat[][] o1 = (Stat[][])one; Stat[][] o2 = (Stat[][])two; if(o1.length != o2.length) return false; for(int i=0;i> aComponents = new TNeighbourObjectHashMap>(); { Stat[][] neighbors = neighbors(matching.aToB, matching.aGraph.statements); //TIntIntHashMap componentSizes = new TIntIntHashMap(); for(int[] els : findComponents(matching.aToB, matching.aGraph.statements, matching.aGraph.inverses)) { /*for(int el : els) System.out.print(matching.aGraph.names[el] + " "); System.out.println(); componentSizes.adjustOrPutValue(els.length, 1, 1);*/ Component component = new Component(els, neighbors); if(component.isIsolated()) continue; component.map(matching.aToB); component.canonicalize(matching.aGraph.names, matching.bGraph.names); ArrayList values = aComponents.get(component.neighbors); if(values == null) { values = new ArrayList(1); aComponents.put(component.neighbors, values); } values.add(component.elements); } /*componentSizes.forEachEntry(new TIntIntProcedure() { @Override public boolean execute(int a, int b) { System.out.println("Components of size " + a + ": " + b); return true; } });*/ } ArrayList bComponents = new ArrayList(); { Stat[][] neighbors = neighbors(matching.bToA, matching.bGraph.statements); for(int[] els : findComponents(matching.bToA, matching.bGraph.statements, matching.bGraph.inverses)) { Component component = new Component(els, neighbors); if(component.isIsolated()) continue; component.canonicalize(matching.bGraph.names, matching.bGraph.names); bComponents.add(component); } } for(Component c : bComponents) { ArrayList candidates = aComponents.get(c.neighbors); if(candidates != null) for(int i=0;i