From 0a393087c737811ce1ae5b13449248d29d68d1da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20Hu=C5=A1ek?= <husek@iuuk.mff.cuni.cz> Date: Thu, 8 Jul 2021 21:03:02 +0200 Subject: [PATCH] Add basic voltage graphs support --- graph_tools/__main__.py | 1 + graph_tools/all.py | 1 + graph_tools/voltage_graphs.py | 118 ++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 graph_tools/voltage_graphs.py diff --git a/graph_tools/__main__.py b/graph_tools/__main__.py index d2d94eb..15264be 100644 --- a/graph_tools/__main__.py +++ b/graph_tools/__main__.py @@ -8,6 +8,7 @@ to_test = [ "sequences", "parameters", "misc", + "voltage_graphs", "tests" ] diff --git a/graph_tools/all.py b/graph_tools/all.py index cc664bb..631ae0c 100644 --- a/graph_tools/all.py +++ b/graph_tools/all.py @@ -2,4 +2,5 @@ from .base import * from .sequences import * from .parameters import * from .misc import * +from .voltage_graphs import * diff --git a/graph_tools/voltage_graphs.py b/graph_tools/voltage_graphs.py new file mode 100644 index 0000000..d021796 --- /dev/null +++ b/graph_tools/voltage_graphs.py @@ -0,0 +1,118 @@ +def _init_(): + global voltage_graph_zn_to_sequence + + from .base import Gadget, CUBIC_VERTEX, FREE_EDGE, GraphSequence + import itertools + + def flatten(x): return list(itertools.chain.from_iterable(x)) + + class GadgetBuilder: + def __init__(self, subgadgets): + self._subgadgets = subgadgets + self._degree = { i: g.size() for i, g in enumerate(subgadgets) } + self._joins = [] + self._outs = [] + + def _get_out(self, v): + ret = self._degree[v] + assert ret > 0 + self._degree[v] = ret - 1 + return ret + + def extend(self, gadget): + i = len(self._subgadgets) + self._degree[i] = gadget.size() + self._subgadgets.append(gadget) + return i + + def join(self, u, v): + ui = self._get_out(u) + vi = self._get_out(v) + self._joins.append(((u+1, ui), (v+1, vi))) + return self + + def out(self, u): + ui = self._get_out(u) + self._outs.append((u+1, ui)) + return self + + def finish(self): + assert all( d == 0 for d in self._degree.values() ) + return Gadget.join( + self._subgadgets, + self._joins, + self._outs + ) + + + def voltage_graph_zn_to_sequence(template, assignment): + """Transform a voltage graph template into a graph sequence. + + EXAMPLES: + >>> gs = voltage_graph_zn_to_sequence([2, [(0,0), (0,1), (1,1)]], [1,0,2]) + >>> from sage.all import graphs + >>> from .parameters import UnderlyingGraph, EdgeColoring, CircuitDoubleCover + >>> gs.graph(5).eval(EdgeColoring(3)) + 0 + >>> gs.graph(5).eval(CircuitDoubleCover) + 52 + >>> P = gs.graph(5).eval(UnderlyingGraph) + >>> P.is_isomorphic(graphs.PetersenGraph()) + True + + >>> gs = voltage_graph_zn_to_sequence([4, [(0,1), (0,2), (0,3), (1,1), (2,2), (3,3)]], [0,0,0, 1,2,3]) + >>> C = gs.graph(7).eval(UnderlyingGraph) + >>> C.is_isomorphic(graphs.CoxeterGraph()) + True + + >>> gs = voltage_graph_zn_to_sequence([4, [(0,0), (0,1), (1,2), (1,3), (2,3), (2,3)]], [1, 0,0,0, 1,-1]) + >>> gs.graph(5).eval(EdgeColoring(3)) + 0 + >>> F = gs.graph(5).eval(UnderlyingGraph) + >>> F.is_isomorphic(graphs.FlowerSnark()) + True + """ + + n, E = template + m = max(map(abs, assignment)) + s = 2*sum(map(abs, assignment)) + + E_zero = [ (u, v) for i, (u, v) in enumerate(E) if assignment[i] == 0 ] + E_nonzero = [ (u, v, assignment[i]) for i, (u, v) in enumerate(E) if assignment[i] != 0 ] + + assert len(assignment) == len(E) + assert sorted(flatten(E)) == flatten( [i]*3 for i in range(n) ) + + gadget = GadgetBuilder([ CUBIC_VERTEX ] * n) + + for u, v in E_zero: + gadget.join(u, v) + + for u, v, a in E_nonzero: + free_edges = [ gadget.extend(FREE_EDGE) for _ in range(abs(a) - 1) ] + if a > 0: + for i in range(a): + gadget.out(free_edges[i] if i < a - 1 else u) + gadget.out(v if i == 0 else free_edges[i-1]) + else: + for i in range(-a): + gadget.out(v if i == 0 else free_edges[i-1]) + gadget.out(free_edges[i] if i < a - 1 else u) + + gadget = gadget.finish() + + @GraphSequence + class Sequence: + sequence_start = 1 + + base_gadget = gadget + step_gadget = gadget + + step_join = [ ((1, 2*i-1), (2, 2*i)) for i in range(1, 1 + gadget.size() // 2) ] + step_out = [ (1 + (i % 2), i) for i in range(1, 1 + gadget.size()) ] + final_join = [ ((1, 2*i-1), (1, 2*i)) for i in range(1, 1 + gadget.size() // 2) ] + + return Sequence + +_init_() + -- GitLab