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

parameters.CircuitDoubleCover: rework project_and_canonize

parent 994bc084
No related branches found
No related tags found
No related merge requests found
...@@ -17,7 +17,7 @@ def _init_(): ...@@ -17,7 +17,7 @@ def _init_():
SimpleParameterBase, GraphParameterBase SimpleParameterBase, GraphParameterBase
from fractions import Fraction from fractions import Fraction
from itertools import chain, combinations, product from itertools import chain, combinations, product, permutations
from functools import reduce from functools import reduce
from collections import defaultdict from collections import defaultdict
...@@ -226,6 +226,10 @@ def _init_(): ...@@ -226,6 +226,10 @@ def _init_():
FREE_EDGE = [ Boundary(((1,2), (1,2), None), Fraction(1, 2)) ] FREE_EDGE = [ Boundary(((1,2), (1,2), None), Fraction(1, 2)) ]
CUBIC_VERTEX = [ Boundary(((1,2), (2,3), (1,3), None), 1) ] CUBIC_VERTEX = [ Boundary(((1,2), (2,3), (1,3), None), 1) ]
def __init__(self):
super().__init__()
self._canonize_cache = {}
def join_boundaries(self, x, offsets): def join_boundaries(self, x, offsets):
def shift(k, off): def shift(k, off):
if k is None: return None if k is None: return None
...@@ -283,28 +287,49 @@ def _init_(): ...@@ -283,28 +287,49 @@ def _init_():
yield from do_join(uf) yield from do_join(uf)
c3, c4 = c4, c3 c3, c4 = c4, c3
def project_and_canonize(self, p, x): def project_and_canonize(self, p, x, no_cache=False):
ret = self._canonize_cache.get((tuple(p), tuple(x)), None)
if ret is not None: return ret
l, r = split_on_none(x) l, r = split_on_none(x)
r = set(r).union(l) r = set(r).union(l)
l = select(p, l) l = select(p, l)
r = r.difference(l) r = r.difference(l)
r = { x for x in r if len(x) == 2 } r = { y for y in r if len(y) == 2 }
def do_rename(p):
perm = { v: i+1 for i, v in enumerate(p) }
l_ = [ tuple(sorted([ perm[a] for a in y ])) for y in l ]
r_ = { tuple(sorted([ perm[a], perm[b] ])) for a, b in r \
if a in perm and b in perm }
r_.difference_update(set(l_))
return tuple(l_ + [None] + sorted(r_))
rename = defaultdict(list) rename = defaultdict(list)
for i, y in enumerate(l):
for a in y: rename[a].append(i)
positions = defaultdict(list)
for k, pos in rename.items():
positions[tuple(pos)].append(k)
positions = sorted(positions.items())
for i, x in enumerate(l): def perms(pos):
for a in x: rename[a].append(i) if pos == []:
yield tuple()
return
rename = sorted( (v, k) for k, v in rename.items() ) for p in permutations(pos[0][1]):
rename = { x[1]: i + 1 for i, x in enumerate(rename) } for tail in perms(pos[1:]):
yield p + tail
l = [ tuple(sorted([ rename[a] for a in x ])) for x in l ] ret = min( do_rename(perm) for perm in perms(positions) )
r = { tuple(sorted([rename[a], rename[b]])) for a, b in r \
if a in rename and b in rename }
r.difference_update(set(l)) if not no_cache: self._canonize_cache[(tuple(p), tuple(x))] = ret
return ret
return tuple(l + [None] + sorted(r))
def finalize(self, b): def finalize(self, b):
assert len(b) <= 1 assert len(b) <= 1
...@@ -324,9 +349,9 @@ def _init_(): ...@@ -324,9 +349,9 @@ def _init_():
>>> list(CircuitDoubleCover.enumerate_boundaries(3)) >>> list(CircuitDoubleCover.enumerate_boundaries(3))
[((1, 2), (1, 3), (2, 3), None)] [((1, 2), (1, 3), (2, 3), None)]
>>> sum( 1 for _ in CircuitDoubleCover.enumerate_boundaries(4) ) >>> sum( 1 for _ in CircuitDoubleCover.enumerate_boundaries(4) )
60 33
>>> sum( 1 for _ in CircuitDoubleCover.enumerate_boundaries(5) ) >>> sum( 1 for _ in CircuitDoubleCover.enumerate_boundaries(5) )
1024 744
""" """
if n == 0: yield (None,) if n == 0: yield (None,)
if n <= 1: return if n <= 1: return
...@@ -340,7 +365,7 @@ def _init_(): ...@@ -340,7 +365,7 @@ def _init_():
b = tuple(b + [None]) b = tuple(b + [None])
for x in powerset(X): for x in powerset(X):
ret = b + tuple(sorted(x)) ret = b + tuple(sorted(x))
if self.project_and_canonize(rng, ret) == ret: if self.project_and_canonize(rng, ret, no_cache=True) == ret:
yield ret yield ret
def add_edge(b, used, fu): def add_edge(b, used, fu):
... ...
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment