--- /dev/null
+package org.simantics.graph.matching;\r
+\r
+import gnu.trove.list.array.TIntArrayList;\r
+import gnu.trove.map.hash.TIntDoubleHashMap;\r
+import gnu.trove.map.hash.TIntIntHashMap;\r
+import gnu.trove.map.hash.TIntObjectHashMap;\r
+import gnu.trove.procedure.TIntDoubleProcedure;\r
+import gnu.trove.procedure.TIntObjectProcedure;\r
+\r
+public enum VotingMatchingStrategy implements GraphMatchingStrategy {\r
+ INSTANCE;\r
+\r
+ public static void vote(\r
+ final TIntDoubleHashMap[] voting, \r
+ int[] aToB,\r
+ int[] bToA,\r
+ Stat[] aStat,\r
+ Stat[] bStat,\r
+ final String[] bNames) {\r
+ final TIntObjectHashMap<TIntArrayList> aMap =\r
+ new TIntObjectHashMap<TIntArrayList>(); \r
+ for(Stat stat : aStat) {\r
+ int mp = aToB[stat.p];\r
+ if(mp >= 0 && aToB[stat.o] < 0) {\r
+ TIntArrayList l = aMap.get(mp);\r
+ if(l == null) {\r
+ l = new TIntArrayList(2);\r
+ aMap.put(mp, l);\r
+ }\r
+ l.add(stat.o);\r
+ }\r
+ }\r
+ TIntObjectHashMap<TIntArrayList> bMap =\r
+ new TIntObjectHashMap<TIntArrayList>();\r
+ for(Stat stat : bStat) {\r
+ int p = stat.p;\r
+ int o = stat.o;\r
+ if(bToA[p] >= 0 && bToA[o] < 0) {\r
+ TIntArrayList l = bMap.get(p);\r
+ if(l == null) {\r
+ l = new TIntArrayList(2);\r
+ bMap.put(p, l);\r
+ }\r
+ l.add(o);\r
+ }\r
+ }\r
+ /*System.out.println("---------------------------------------");\r
+ aMap.forEachEntry(new TIntObjectProcedure<TIntArrayList>() {\r
+ @Override\r
+ public boolean execute(int a, TIntArrayList b) {\r
+ System.out.println("a " + bNames[a] + " -> " + b);\r
+ return true;\r
+ }\r
+ });\r
+ bMap.forEachEntry(new TIntObjectProcedure<TIntArrayList>() {\r
+ @Override\r
+ public boolean execute(int a, TIntArrayList b) {\r
+ System.out.println("b " + bNames[a] + " -> " + b);\r
+ return true;\r
+ }\r
+ });*/\r
+ bMap.forEachEntry(new TIntObjectProcedure<TIntArrayList>() { \r
+ @Override\r
+ public boolean execute(int p, TIntArrayList bos) {\r
+ TIntArrayList aos = aMap.get(p);\r
+ if(aos != null && aos.size() <= 4 && bos.size() <= 4) {\r
+ final double weight = 1.0 / bos.size();\r
+ for(int i=0;i<aos.size();++i)\r
+ for(int j=0;j<bos.size();++j)\r
+ voting[aos.get(i)].adjustOrPutValue(bos.get(j), weight, weight);\r
+ }\r
+ return true;\r
+ }\r
+ });\r
+ }\r
+ \r
+ @Override\r
+ public void applyTo(GraphMatching matching) {\r
+ int[] aToB = matching.aToB;\r
+ final int[] bToA = matching.bToA;\r
+ int resourceCount = aToB.length;\r
+ Stat[][] aStatements = matching.aGraph.statements;\r
+ Stat[][] bStatements = matching.bGraph.statements;\r
+ TIntIntHashMap aInv = matching.aGraph.inverses;\r
+ TIntIntHashMap bInv = matching.bGraph.inverses;\r
+ \r
+ TIntDoubleHashMap[] voting = new TIntDoubleHashMap[resourceCount];\r
+ for(int i=0;i<resourceCount;++i)\r
+ if(aToB[i] < 0)\r
+ voting[i] = new TIntDoubleHashMap();\r
+ for(int s=0;s<resourceCount;++s) {\r
+ int ms = aToB[s];\r
+ if(ms >= 0 && ms < bStatements.length)\r
+ vote(voting, aToB, bToA, aStatements[s], bStatements[ms], matching.bGraph.names);\r
+ }\r
+ \r
+ for(int a=0;a<resourceCount;++a) {\r
+ TIntDoubleHashMap votes = voting[a];\r
+ if(votes != null && !votes.isEmpty()) {\r
+ final int[] best = new int[] { -1 };\r
+ votes.forEachEntry(new TIntDoubleProcedure() {\r
+ double bestWeight = 0.9;\r
+ @Override\r
+ public boolean execute(int b, double weight) {\r
+ if(weight > bestWeight && bToA[b] < 0) {\r
+ bestWeight = weight;\r
+ best[0] = b;\r
+ }\r
+ return true;\r
+ }\r
+ });\r
+ if(best[0] >= 0) {\r
+ int b = best[0];\r
+ matching.map(a, b);\r
+ if(aInv.contains(a) && bInv.contains(b) && aInv.get(a) != a)\r
+ matching.map(aInv.get(a), bInv.get(b));\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+}\r