From f20caa717a684bf3ad7f4c038c3ea975be138e0c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Radek=20Hu=C5=A1ek?= <PitelVonSacek@gmail.com>
Date: Thu, 10 Dec 2015 14:51:07 +0100
Subject: [PATCH] Implement and enable double subdivision optimization

---
 compileTimeOptions.h  |  2 +-
 group-connectivity.h  | 16 ++++++++++++++++
 groupConnectivity.pyx | 21 ++++++++++++++++-----
 3 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/compileTimeOptions.h b/compileTimeOptions.h
index 526e6ec..ee4aee3 100644
--- a/compileTimeOptions.h
+++ b/compileTimeOptions.h
@@ -20,6 +20,6 @@ REQUIRES(EXPLICIT_NORMAL_EDGES, USE_NEXT_FORB)
 BOOL_OPTION(USE_TWO_CUTS, 1)
 REQUIRES(USE_TWO_CUTS, USE_NEXT_FORB && EXPLICIT_NORMAL_EDGES)
 
-BOOL_OPTION(USE_DOUBLE_SUBDIVISIONS, 0)
+BOOL_OPTION(USE_DOUBLE_SUBDIVISIONS, 1)
 REQUIRES(USE_DOUBLE_SUBDIVISIONS, USE_NEXT_FORB && EXPLICIT_NORMAL_EDGES)
 
diff --git a/group-connectivity.h b/group-connectivity.h
index ec326fb..0199836 100644
--- a/group-connectivity.h
+++ b/group-connectivity.h
@@ -57,6 +57,9 @@ struct Tester : public AbstractTester {
 # if USE_TWO_CUTS
   std::vector< TwoCutInt > twoCuts;
 # endif
+# if USE_DOUBLE_SUBDIVISIONS
+  std::vector< EdgeId > doubleSubdividedEdges;
+# endif
 
   virtual void init(
     int edges_,
@@ -87,6 +90,16 @@ struct Tester : public AbstractTester {
       }
     }
 
+#   if USE_DOUBLE_SUBDIVISIONS
+    if (Ring::size == 4) {
+      for (const auto& i : dSub) {
+        for (auto e : i) edgeList[e - 1] = false;
+        classEdges.push_back(i[0] - 1);
+        doubleSubdividedEdges.push_back(i[0] - 1);
+      }
+    }
+#   endif
+
 #   if USE_TWO_CUTS
     for (auto cut : twoCuts_) {
       if (cut.first < 0) {
@@ -227,6 +240,9 @@ struct Tester : public AbstractTester {
 #     if USE_TWO_CUTS
       for (const auto& cut : twoCuts) cut.encode(forb, 0);
 #     endif
+#     if USE_DOUBLE_SUBDIVISIONS
+      for (const auto& e : doubleSubdividedEdges) forb.assign(e, 0);
+#     endif
 
       do {
         Mapping copy(forb);
diff --git a/groupConnectivity.pyx b/groupConnectivity.pyx
index b70b9ed..007c5de 100644
--- a/groupConnectivity.pyx
+++ b/groupConnectivity.pyx
@@ -39,7 +39,7 @@ def pathToEdges(G, path):
 
 
 def testGroupConnectivity(G, group = "Z4", getClasses = False,
-                          useTwoCuts = True, useDoubleSubdivisions = False,
+                          useTwoCuts = True, useDoubleSubdivisions = True,
                           debug = False):
   cdef AbstractTester* tester = NULL
   if group == "Z4":
@@ -59,19 +59,29 @@ def testGroupConnectivity(G, group = "Z4", getClasses = False,
     G.set_edge_label(u, v, i)
     i += 1
 
-  spanningTree = Graph(G.min_spanning_tree())
+  spanningTree = Graph(G.min_spanning_tree(
+    weight_function = lambda e: min(G.degree([e[0], e[1]]))
+  ))
   elemCycles = [
     [ l ] + pathToEdges(G, spanningTree.shortest_path(u, v))
     for (u, v, l) in set(G.edge_iterator()) - set(spanningTree.edge_iterator())
   ]
 
   spanningTreeEdges = [ l for (_, _, l) in spanningTree.edge_iterator() ]
+  availableEdges = set(spanningTreeEdges)
 
-
+  doubleSubdivisions = []
+  if useDoubleSubdivisions:
+    for (u, v, l) in G.edges():
+      if G.degree([u, v]) != [2, 2]:
+        continue
+      edges = set([ l for (_, _, l) in G.edges_incident([u, v]) ])
+      if edges.issubset(availableEdges):
+        doubleSubdivisions.append(edges)
+        availableEdges -= edges
 
   twoCuts = []
   if useTwoCuts:
-    availableEdges = set(spanningTreeEdges)
     for v in [ v for v in G.vertices() if G.degree(v) == 2 ]:
       e, f = G.edges_incident(v)
       el = e[2]
@@ -98,8 +108,9 @@ def testGroupConnectivity(G, group = "Z4", getClasses = False,
     print "Spanning Tree: ", spanningTreeEdges
     print "Elementary cycles: ", elemCycles
     print "Two cuts: ", twoCuts
+    print "Double subdivided edges: ", doubleSubdivisions
 
-  tester.init(G.num_edges(), spanningTreeEdges, twoCuts, [], elemCycles)
+  tester.init(G.num_edges(), spanningTreeEdges, twoCuts, doubleSubdivisions, elemCycles)
   ret = tester.run()
 
   if getClasses:
-- 
GitLab