Skip to content
Snippets Groups Projects
Commit ecb8f588 authored by Radek Hušek's avatar Radek Hušek
Browse files

Boundary -> BoundaryValue

parent b8e13c80
Branches
No related tags found
No related merge requests found
#!/usr/bin/python
DOC = """
Calculate that the number of CDCs of Flower snark $J_k$ is $16^{(1-o(1))k}$.
Calculate that the number of CDCs of Flower snark $J_k$ is $c16^k \pm O(15^k)$.
We calculate the step matrix $M$, show that 16 is its eigenvalue by finding
its eigenvector. The eigenvector is guessed for the ratios of coefficients
......@@ -15,6 +15,18 @@ sys.path.append(os.path.dirname(__file__) + "/..")
from graph_tools.all import *
from sage.all import identity_matrix, QQ, DiGraph, matrix
def make_P(u):
coords = [ r for r, c in u.dict().keys() ]
assert min(coords) == 1 and u[1, 0] == 1
P = matrix(QQ, u.nrows(), u.nrows(), sparse=True)
P[:, 0] = u
P[0, 1] = 1
for i in range(2, P.nrows()):
P[i, i] = 1
P[1, i] = -P[i, 0]
return P
def deflate_eigenvector(M, u):
coord = min(( r for r in range(u.nrows()) if u[r, 0] > 0 ), key=lambda r: u[r, 0])
......@@ -87,7 +99,8 @@ if __name__ == "__main__":
A = M * A
nu2 = fin * A
assert nu1 == nu2
print(" ν(J_%i) = %i" % (i, nu1))
c_approx = nu1 / 16**i
print(" ν(J_%i) = %i (c = %.3f)" % (i, nu1, c_approx))
print(" Done")
print("\nCalculating the eigenvector for eigenvalue 16")
......@@ -105,7 +118,7 @@ if __name__ == "__main__":
print(" Checking it...")
nex = to_dict(FlowerSnark._next_gadget(FakeGadget(6,
[ Boundary(b, v) for b, v in vec.items() ])).eval_gadget(CircuitDoubleCover))
[ BoundaryValue(b, v) for b, v in vec.items() ])).eval_gadget(CircuitDoubleCover))
assert nex.keys() == vec.keys()
for b in vec:
......
......@@ -11,16 +11,14 @@ share exactly one edge, and non-consecutive neighbour faces do not
share any edge.
"""
import sys, os
sys.path.append(os.path.dirname(__file__) + "/..")
import _experiment
from graph_tools.all import *
@GraphSequence
class Flower:
sequence_start = 2
SCV = FakeGadget(3, [ Boundary(((1,), (2,), (1, 2), None), 1) ])
SCV = FakeGadget(3, [ BoundaryValue(((1,), (2,), (1, 2), None), 1) ])
D = Gadget.join(
[ SCV, CUBIC_VERTEX ],
......
def _init_():
global \
Boundary, \
BoundaryValue, \
GraphParameterBase, SimpleParameterBase, \
Gadget, FakeGadget, CUBIC_VERTEX, FREE_EDGE, \
ParametrizedGraphSequence, GraphSequence
......@@ -11,13 +11,13 @@ def _init_():
from itertools import combinations, chain, product
from functools import reduce
Boundary = namedtuple("Boundary", ['boundary', 'value', 'origins'])
Boundary.with_origins = lambda s, o: Boundary(s.boundary, s.value, o)
BoundaryValue = namedtuple("BoundaryValue", ['boundary', 'value', 'origins'])
BoundaryValue.with_origins = lambda s, o: BoundaryValue(s.boundary, s.value, o)
OriginJoinEdge = namedtuple("OriginJoinEdge", ['boundary', 'e1', 'e2', 'info'])
OriginJoinBoundaries = namedtuple("OriginJoinBoundaries", ['boundaries', 'info'])
# hack compatible with Python < 3.7
Boundary.__new__.__defaults__ = (None, None, None)
BoundaryValue.__new__.__defaults__ = (None, None, None)
class GraphParameterBase:
......@@ -49,14 +49,14 @@ def _init_():
for e1, e2 in joins: it = join(it, e1, e2)
def project_and_canonize(b):
return Boundary(self.project_and_canonize(outs, b.boundary), b.value, b.origins)
return BoundaryValue(self.project_and_canonize(outs, b.boundary), b.value, b.origins)
it = ( project_and_canonize(b) for b in it )
ret = dict()
for b in it:
if b.boundary in ret:
ret[b.boundary] = Boundary(b.boundary,
ret[b.boundary] = BoundaryValue(b.boundary,
self.merge_values(ret[b.boundary].value, b.value),
ret[b.boundary].origins + b.origins if track_origins else None
)
......@@ -72,7 +72,7 @@ def _init_():
class SimpleParameterBase(GraphParameterBase):
def join_boundaries(self, x, _):
yield Boundary(
yield BoundaryValue(
tuple(chain.from_iterable( b.boundary for b in x )),
reduce(lambda acc, b: acc*b.value, x, 1)
)
......@@ -256,7 +256,7 @@ def _init_():
boundaries = new_boundaries
gadget = FakeGadget(
start_gadget.size(),
[ Boundary(k, 1) for k in boundaries ]
[ BoundaryValue(k, 1) for k in boundaries ]
)
out = self._next_gadget(gadget).eval_gadget(parameter, no_cache=True)
new_boundaries = set( b.boundary for b in out )
......@@ -272,7 +272,7 @@ def _init_():
(rename[b.boundary], rename[col]): b.value
for col in sorted_boundaries
for b in self._next_gadget(FakeGadget(start_gadget.size(),
[ Boundary(col, 1) ])).eval_gadget(parameter, no_cache=True)
[ BoundaryValue(col, 1) ])).eval_gadget(parameter, no_cache=True)
})
iv = matrix(QQ, size, 1, {
......@@ -282,7 +282,7 @@ def _init_():
fin = matrix(QQ, 1, size, {
(0, rename[col]): self._make_graph(FakeGadget(start_gadget.size(),
[ Boundary(col, 1) ])).eval(parameter, no_cache=True)
[ BoundaryValue(col, 1) ])).eval(parameter, no_cache=True)
for col in sorted_boundaries
})
......
......@@ -3,7 +3,7 @@ def _init_():
edge_model_join, edge_model_join_matrix, parameter_matrix, \
enumerate_diamond_matchings
from .base import Gadget, CUBIC_VERTEX, Boundary, FakeGadget
from .base import Gadget, CUBIC_VERTEX, BoundaryValue, FakeGadget
from .parameters import CircuitDoubleCover
from .sequences import Necklace
......@@ -177,7 +177,7 @@ def _init_():
def edge_model_join_matrix(P, k):
BG = [ FakeGadget(k, [ Boundary(b, 1) ]) for b in P.enumerate_boundaries(k) ]
BG = [ FakeGadget(k, [ BoundaryValue(b, 1) ]) for b in P.enumerate_boundaries(k) ]
return parameter_matrix(P, BG)
......
......@@ -13,7 +13,7 @@ def _init_():
UnionFind
from .base import \
Boundary, \
BoundaryValue as BV, \
SimpleParameterBase, GraphParameterBase
from fractions import Fraction
......@@ -27,9 +27,9 @@ def _init_():
def __init__(self, group, nowherezero):
self.group = group
self.nowherezero = nowherezero
self.FREE_EDGE = [ Boundary((i, i), 1) for i in group if not nowherezero or i != 0 ]
self.FREE_EDGE = [ BV((i, i), 1) for i in group if not nowherezero or i != 0 ]
self.CUBIC_VERTEX = [
Boundary((i, j, l), 1) for i in group for j in group
BV((i, j, l), 1) for i in group for j in group
for l in group if i + j + l == 0 and
(not nowherezero or i != 0 and j != 0 and l != 0)
]
......@@ -41,9 +41,9 @@ def _init_():
class CycleDoubleCover(SimpleParameterBase):
def __init__(self, k):
self.k = k
self.FREE_EDGE = [ Boundary(((i, j), (i, j)), 1) for i in range(k) for j in range(i+1, k) ]
self.FREE_EDGE = [ BV(((i, j), (i, j)), 1) for i in range(k) for j in range(i+1, k) ]
self.CUBIC_VERTEX = [
Boundary((tuple(sorted((i, j))), tuple(sorted((i, l))), tuple(sorted((j, l)))), 1)
BV((tuple(sorted((i, j))), tuple(sorted((i, l))), tuple(sorted((j, l)))), 1)
for i in range(k) for j in range(k) for l in range(k)
if i != j and j != l and i != l
]
......@@ -81,9 +81,9 @@ def _init_():
def __init__(self, k):
self.k = k
self.FREE_EDGE = [ Boundary((i, i), 1) for i in range(k) ]
self.FREE_EDGE = [ BV((i, i), 1) for i in range(k) ]
self.CUBIC_VERTEX = [
Boundary((i, j, l), 1) for i in range(k) for j in range(k)
BV((i, j, l), 1) for i in range(k) for j in range(k)
for l in range(k) if i != j and j != l and i != l
]
......@@ -95,7 +95,7 @@ def _init_():
class VertexColoring(SimpleParameterBase):
def __init__(self, k):
self.k = k
self.CUBIC_VERTEX = [ Boundary((i, i, i), 1) for i in range(k) ]
self.CUBIC_VERTEX = [ BV((i, i, i), 1) for i in range(k) ]
def is_compatible(self, boundary, e_a, e_b):
return boundary[e_a] != boundary[e_b]
......@@ -106,7 +106,7 @@ def _init_():
from sage.all import Graph
CUBIC_VERTEX = [
Boundary((0, 0, 0), Graph([[0], []], multiedges=True, loops=True, immutable=True))
BV((0, 0, 0), Graph([[0], []], multiedges=True, loops=True, immutable=True))
]
def join_boundaries(self, x, _):
......@@ -119,7 +119,7 @@ def _init_():
for i, b in enumerate(x)
)
yield Boundary(
yield BV(
tuple(chain.from_iterable(
[ v + offsets[i] for v in b.boundary ] for i, b in enumerate(x)
)),
......@@ -129,7 +129,7 @@ def _init_():
def join_edges(self, b, e1, e2):
g = b.value.copy(immutable=False)
g.add_edge(b.boundary[e1], b.boundary[e2])
yield Boundary(b.boundary, g.copy(immutable=True))
yield BV(b.boundary, g.copy(immutable=True))
def project_and_canonize(self, sel, b):
return select(sel, b)
......@@ -149,11 +149,11 @@ def _init_():
Same as `gadget.eval(UnderlayingGraph).num_verts()` but
also works for gadgets containing FREE_EDGE.
"""
CUBIC_VERTEX = [ Boundary(None, 1) ]
FREE_EDGE = [ Boundary(None, 0) ]
CUBIC_VERTEX = [ BV(None, 1) ]
FREE_EDGE = [ BV(None, 0) ]
def join_boundaries(self, x, _):
yield Boundary(None, sum( b.value for b in x ))
yield BV(None, sum( b.value for b in x ))
def join_edges(self, b, _, __): yield b
def project_and_canonize(self, _, b): return b
......@@ -162,11 +162,11 @@ def _init_():
@Singleton
class HamiltonianCycle(GraphParameterBase):
FREE_EDGE = [ Boundary((1, 1), 1), Boundary((None, None), 1) ]
FREE_EDGE = [ BV((1, 1), 1), BV((None, None), 1) ]
CUBIC_VERTEX = [
Boundary((1, 1, None), 1),
Boundary((1, None, 1), 1),
Boundary((None, 1, 1), 1)
BV((1, 1, None), 1),
BV((1, None, 1), 1),
BV((None, 1, 1), 1)
]
def join_boundaries(self, x, _):
......@@ -185,7 +185,7 @@ def _init_():
[ shift(x, offsets[i]) for x in b.boundary ] for i, b in enumerate(x)
]))
yield Boundary(ret_b, prod( b.value for b in x ))
yield BV(ret_b, prod( b.value for b in x ))
def join_edges(self, b, e1, e2):
# print("%s %s %s" % (b, e1, e2))
......@@ -198,7 +198,7 @@ def _init_():
if c1 != c2:
if c1 > c2: c1, c2 = c2, c1
boundary = tuple( v if v != c2 else c1 for v in b.boundary )
yield Boundary(boundary, b.value)
yield BV(boundary, b.value)
elif max_(b.boundary) == 1:
yield b
......@@ -223,8 +223,8 @@ def _init_():
@Singleton
class CircuitDoubleCover(GraphParameterBase):
FREE_EDGE = [ Boundary(((1,2), (1,2), None), Fraction(1, 2)) ]
CUBIC_VERTEX = [ Boundary(((1,2), (2,3), (1,3), None), 1) ]
FREE_EDGE = [ BV(((1,2), (1,2), None), Fraction(1, 2)) ]
CUBIC_VERTEX = [ BV(((1,2), (2,3), (1,3), None), 1) ]
def __init__(self):
super().__init__()
......@@ -242,19 +242,19 @@ def _init_():
]))
ret_b = tuple(chain(*tmp[0], (None,), *tmp[1]))
yield Boundary(ret_b, prod( b.value for b in x ))
yield BV(ret_b, prod( b.value for b in x ))
def join_edges(self, b, e1, e2):
"""
>>> from .base import Boundary as B
>>> from .base import BoundaryValue as BV
>>> def test(*args): return list(CircuitDoubleCover.join_edges(*args))
>>> test(B(((1,2), (2,3), (1,3), None), 1), 1, 2)
>>> test(BV(((1,2), (2,3), (1,3), None), 1), 1, 2)
[]
>>> assert test(B(((1,2), (2,3), (1,4), (3,4), None), 1), 1, 2) == \
[B(((3, 2), (2, 3), (3, 2), (3, 2), None), 1)]
>>> test(B(((1,2), (2,3), (1,4), (3,4), None, (1,3)), 1), 1, 2)
>>> assert test(BV(((1,2), (2,3), (1,4), (3,4), None), 1), 1, 2) == \
[BV(((3, 2), (2, 3), (3, 2), (3, 2), None), 1)]
>>> test(BV(((1,2), (2,3), (1,4), (3,4), None, (1,3)), 1), 1, 2)
[]
>>> len(test(B(((1,2), (2,3), (4,5), (1,3), (4,5), None), 1), 1, 2))
>>> len(test(BV(((1,2), (2,3), (4,5), (1,3), (4,5), None), 1), 1, 2))
2
"""
assert len(b.boundary[e1]) == len(b.boundary[e2])
......@@ -269,7 +269,7 @@ def _init_():
if len(t) == 2 and t[0] == t[1]: break
ret_b.append(t)
else:
yield Boundary(tuple(ret_b), b.value)
yield BV(tuple(ret_b), b.value)
if len(b.boundary[e1]) == 1:
uf = UnionFind(len(b.boundary))
......
......@@ -5,7 +5,6 @@ def _init_():
GeneralizedPetersen, Petersen
from .base import \
Boundary, \
Gadget, FakeGadget, CUBIC_VERTEX, FREE_EDGE, \
GraphSequence, ParametrizedGraphSequence
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment