From 0efdd348f8380957c0020c7df66f43ef5477463e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Radek=20Hu=C5=A1ek?= <PitelVonSacek@gmail.com>
Date: Thu, 10 Dec 2015 10:41:27 +0100
Subject: [PATCH] Implement Python part of 2-cut optimization

---
 group-connectivity.h  |  6 +++---
 groupConnectivity.pyx | 37 +++++++++++++++++++++++++++++++++++--
 2 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/group-connectivity.h b/group-connectivity.h
index 280b07d..354328d 100644
--- a/group-connectivity.h
+++ b/group-connectivity.h
@@ -158,7 +158,7 @@ struct Tester : public AbstractTester {
 #endif
 
 
-  Mapping& cannonize(Mapping& map) {
+  Mapping& canonize(Mapping& map) {
     for (const auto &i : nonClassEdges) {
 #if OPTIMIZE_COMBINE
       if (map[i.first] != Ring::zero)
@@ -225,11 +225,11 @@ struct Tester : public AbstractTester {
 
       do {
         Mapping copy(forb);
-        INC(classes[pack(cannonize(copy))]);
+        INC(classes[pack(canonize(copy))]);
       } while (nextForb(forb));
 #   else
       for (size_t i = 0; i < numForb; i++)
-        INC(classes[pack(cannonize(unpack(i, forb)))]);
+        INC(classes[pack(canonize(unpack(i, forb)))]);
 #   endif
 
     for (const auto &c : classes) if (!c) return (isConnected = false);
diff --git a/groupConnectivity.pyx b/groupConnectivity.pyx
index 84a66e1..083bd12 100644
--- a/groupConnectivity.pyx
+++ b/groupConnectivity.pyx
@@ -25,6 +25,7 @@ cdef extern from "group-connectivity.h":
   cdef cppclass Tester[T](AbstractTester):
     pass
 
+
 def pathToEdges(G, path):
   ret = []
   u = path[0]
@@ -35,7 +36,9 @@ def pathToEdges(G, path):
     u = v
   return ret
 
-def testGroupConnectivity(G, group = "Z4", getClasses = False, debug = False):
+
+def testGroupConnectivity(G, group = "Z4", getClasses = False,
+                          useTwoCuts = False, debug = False):
   cdef AbstractTester* tester = NULL
   if group == "Z4":
     tester = new Tester[Z4[int]]()
@@ -46,6 +49,9 @@ def testGroupConnectivity(G, group = "Z4", getClasses = False, debug = False):
 
   assert(tester != NULL)
 
+  if useTwoCuts:
+    G.relabel()
+
   i = 1
   for (u, v, _) in G.edge_iterator():
     G.set_edge_label(u, v, i)
@@ -59,11 +65,37 @@ def testGroupConnectivity(G, group = "Z4", getClasses = False, debug = False):
 
   spanningTreeEdges = [ l for (_, _, l) in spanningTree.edge_iterator() ]
 
+  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]
+      fl = f[2]
+      if el not in availableEdges or fl not in availableEdges:
+        continue
+      availableEdges.remove(el)
+      availableEdges.remove(fl)
+
+      w1 = e[0] if e[0] != v else e[1]
+      w2 = f[0] if f[0] != v else f[1]
+
+      if w1 > v:
+        el *= -1
+      if w2 < v:
+        fl *= -1
+
+      if debug:
+        print "twoCut> ", v, w1, w2, el, fl, (w1 > v), (w2 < v)
+
+      twoCuts.append((el, fl))
+
   if debug:
     print "Spanning Tree: ", spanningTreeEdges
     print "Elementary cycles: ", elemCycles
+    print "Two cuts: ", twoCuts
 
-  tester.init(G.num_edges(), spanningTreeEdges, [], elemCycles)
+  tester.init(G.num_edges(), spanningTreeEdges, twoCuts, elemCycles)
   ret = tester.run()
 
   if getClasses:
@@ -74,6 +106,7 @@ def testGroupConnectivity(G, group = "Z4", getClasses = False, debug = False):
     del tester
     return ret
 
+
 def subdivisionIterator(G, edges = None):
   if edges is None:
     edges = G.edges()
-- 
GitLab