Commit 4470b2bd authored by Radek Hušek's avatar Radek Hušek
Browse files

implementation of naive algorithm for group connectivity testing

parent b2d95f55
default: groupConnectivity.so clean_obj
groupConnectivity.so: groupConnectivity.pyx group-connectivity.h setup.py compileTimeOptions.h generateCompileTimeOptions.sh rings.h fast-array.h twoCuts.h parmap.py
groupConnectivity.so: groupConnectivity.pyx group-connectivity.h setup.py compileTimeOptions.h generateCompileTimeOptions.sh rings.h fast-array.h twoCuts.h parmap.py groupConnectivityNaive.py
./generateCompileTimeOptions.sh > options.h
python setup.py build_ext
cp build/lib*/groupConnectivity.so .
......
from libcpp.vector cimport vector
from libcpp cimport bool
from libcpp.utility cimport pair
from sage.graphs.graph import Graph
from sage.graphs.graph import Graph, DiGraph
# include because we don't want it to became external dependecy
include "parmap.py"
include "groupConnectivityNaive.py"
cdef extern from "group-connectivity.h" namespace "Ring":
cdef cppclass Z4[T]:
......@@ -28,6 +31,7 @@ cdef extern from "group-connectivity.h":
def pathToEdges(G, path):
"""Transform list of vertices into list of edges."""
ret = []
u = path[0]
for v in path[1:]:
......@@ -39,10 +43,7 @@ def pathToEdges(G, path):
def theOtherNeighbour(G, v, w):
"""
Given vertex v of degree 2 returns neighbour
of v not equal to w.
"""
"""Return neighbour of v in G not equal to w given v has degree 2."""
N = G.neighbors(v)
if N[0] == w:
return N[1]
......
def flowEnumerator(G, group):
"""Enumerate all flows of given graph.
Graph G must be directed and it edges labeled with numbers 0 to |E(G)|.
"""
m = G.num_edges()
assert(G.is_directed())
assert(set(x for _, _, x in G.edges()) == set(range(m)))
def to_elem_vector(cycle):
vec = [ group.zero() ] * m
for (u, v, x) in cycle:
if u > v:
vec[x] = -group.one()
else:
vec[x] = group.one()
return vec
elemVecs = map(to_elem_vector, Graph(G).cycle_basis(output = "edge"))
def combine(vec, i):
if i >= len(elemVecs):
yield vec
return
for e in group:
for v in combine(map(lambda x: x[0] + e * x[1], zip(vec, elemVecs[i])), i + 1):
yield v
for v in combine([group.zero()] * m, 0):
yield v
def testGroupConnectivityNaive(G_, group, forb_spanning_tree = False, list_all = False):
E = [ (u, v, i) for i, (u, v, _) in enumerate(G_.edges()) ]
G = DiGraph([G_.vertices(), E], format='vertices_and_edges')
m = G.num_edges()
info = { 'graph': G, 'edges': E }
if forb_spanning_tree:
T = G.min_spanning_tree()
else:
T = G.edges()
info['span_tree'] = T
T = [ x for _, _, x in T ]
flows = list(flowEnumerator(G, group))
info['all_flows'] = flows
mask = [group.zero()] * m
for e in T:
mask[e] = None
def is_compatible(f, x):
for i in range(m):
if f[i] == x[i]:
return False
return True
flows = [ f for f in flows if is_compatible(f, mask) ]
info['compatible_flows'] = flows
Elems = [ x for x in group ]
forb = [ group.zero() ] * m
def forb_iter(e):
if e >= len(T):
yield True
return
for v in Elems:
forb[T[e]] = v
for r in forb_iter(e + 1):
yield r
def find_flow():
for f in flows:
if is_compatible(f, forb):
return True
return False
ret = []
for _ in forb_iter(0):
if not find_flow():
if not list_all:
return (False, info, [forb])
ret.append(list(forb))
return (len(ret) == 0, info, ret)
def labelsFromArray(G, E, labels):
for (u, v, i) in E:
G.set_edge_label(u, v, labels[i])
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment