Add Heawood boundary-restriction experiments and findings note
Experiments probing the cluster restriction set R_K / Phi: R_K is a Z/3 zonotope (not a GF(3) subspace), the "richness" invariant is an artifact of non-shrinking annuli, the interface gluing always works on interior cycles (forced by 4CT), and the maximal constraint achievable on an n-cycle is a floor of 2^(n-2) -- already reached by the trivial tire. Note boundary_restriction_structure.tex writes these up. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+182
@@ -0,0 +1,182 @@
|
|||||||
|
"""
|
||||||
|
Does the richness invariant survive BRANCHING?
|
||||||
|
|
||||||
|
For a separating cycle C bounding a disk G_C (away from the source), the achievable
|
||||||
|
outer-interface set is
|
||||||
|
|
||||||
|
Phi(C) = { (lambda*(v))_{v in C} : lambda in {+1,-1}^{F(G_C)},
|
||||||
|
sum_{f ∋ w} lambda(f) ≡ 0 for every
|
||||||
|
truly-interior vertex w of G_C }.
|
||||||
|
|
||||||
|
This is the exact value the recursive transfer operator produces at C (interior
|
||||||
|
consistency = all the descendant gluings already performed; seam/boundary vertices
|
||||||
|
are deferred, exactly as in the recursion). We compute Phi(C) by constrained
|
||||||
|
enumeration over real triangulations and test the candidate self-similar invariant
|
||||||
|
|
||||||
|
non-empty & closed under sign flip & full single-position marginals
|
||||||
|
|
||||||
|
separately at BRANCH nodes (region encloses >=2 disjoint deeper sub-tires) and at
|
||||||
|
LINEAR nodes (one child), to see whether branching breaks it.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from collections import defaultdict, deque
|
||||||
|
from itertools import product
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from scipy.spatial import Delaunay
|
||||||
|
|
||||||
|
|
||||||
|
def delaunay(n, rng):
|
||||||
|
pts = rng.random((n, 2))
|
||||||
|
tri = Delaunay(pts)
|
||||||
|
faces = [tuple(int(x) for x in s) for s in tri.simplices]
|
||||||
|
hull = set(int(v) for e in tri.convex_hull for v in e)
|
||||||
|
return faces, hull
|
||||||
|
|
||||||
|
|
||||||
|
def build(faces):
|
||||||
|
adj = defaultdict(set)
|
||||||
|
efaces = defaultdict(list)
|
||||||
|
vfaces = defaultdict(list)
|
||||||
|
for fi, (a, b, c) in enumerate(faces):
|
||||||
|
adj[a] |= {b, c}; adj[b] |= {a, c}; adj[c] |= {a, b}
|
||||||
|
for e in ((a, b), (b, c), (a, c)):
|
||||||
|
efaces[frozenset(e)].append(fi)
|
||||||
|
for v in (a, b, c):
|
||||||
|
vfaces[v].append(fi)
|
||||||
|
fadj = [set() for _ in faces]
|
||||||
|
for fl in efaces.values():
|
||||||
|
for i in fl:
|
||||||
|
for j in fl:
|
||||||
|
if i != j:
|
||||||
|
fadj[i].add(j)
|
||||||
|
return adj, fadj, vfaces
|
||||||
|
|
||||||
|
|
||||||
|
def bfs(adj, src):
|
||||||
|
lev = {src: 0}; q = deque([src])
|
||||||
|
while q:
|
||||||
|
u = q.popleft()
|
||||||
|
for w in adj[u]:
|
||||||
|
if w not in lev:
|
||||||
|
lev[w] = lev[u] + 1; q.append(w)
|
||||||
|
return lev
|
||||||
|
|
||||||
|
|
||||||
|
def components(face_ids, fadj):
|
||||||
|
idset = set(face_ids)
|
||||||
|
seen = set(); comps = []
|
||||||
|
for s in face_ids:
|
||||||
|
if s in seen:
|
||||||
|
continue
|
||||||
|
comp = []; stack = [s]; seen.add(s)
|
||||||
|
while stack:
|
||||||
|
u = stack.pop(); comp.append(u)
|
||||||
|
for w in fadj[u]:
|
||||||
|
if w in idset and w not in seen:
|
||||||
|
seen.add(w); stack.append(w)
|
||||||
|
comps.append(comp)
|
||||||
|
return comps
|
||||||
|
|
||||||
|
|
||||||
|
def sign_closed(S):
|
||||||
|
return all(tuple((3 - x) % 3 for x in s) in S for s in S)
|
||||||
|
|
||||||
|
|
||||||
|
def marginals_full(S, k):
|
||||||
|
return all({s[i] for s in S} == {0, 1, 2} for i in range(k))
|
||||||
|
|
||||||
|
|
||||||
|
def phi_of_region(comp_faces, faces, vfaces, lev, d, cap):
|
||||||
|
"""Constrained-enumeration Phi on the outer (level-d) cycle of a region."""
|
||||||
|
Gc = comp_faces
|
||||||
|
if not (1 <= len(Gc) <= cap):
|
||||||
|
return None
|
||||||
|
Gcset = set(Gc)
|
||||||
|
verts = sorted(set(v for fi in Gc for v in faces[fi]))
|
||||||
|
# truly-interior: every global incident face is inside G_C (=> level > d)
|
||||||
|
interior = [v for v in verts if all(f in Gcset for f in vfaces[v])]
|
||||||
|
boundary_C = [v for v in verts if lev[v] == d and v not in interior]
|
||||||
|
if not boundary_C:
|
||||||
|
return None
|
||||||
|
F = len(Gc)
|
||||||
|
fidx = {fi: j for j, fi in enumerate(Gc)}
|
||||||
|
# incidence rows
|
||||||
|
Bint = np.zeros((len(interior), F), dtype=np.int64)
|
||||||
|
for r, w in enumerate(interior):
|
||||||
|
for fi in vfaces[w]:
|
||||||
|
if fi in Gcset:
|
||||||
|
Bint[r, fidx[fi]] = 1
|
||||||
|
Cinc = np.zeros((len(boundary_C), F), dtype=np.int64)
|
||||||
|
for r, v in enumerate(boundary_C):
|
||||||
|
for fi in vfaces[v]:
|
||||||
|
if fi in Gcset:
|
||||||
|
Cinc[r, fidx[fi]] = 1
|
||||||
|
labs = np.array(list(product((1, 2), repeat=F)), dtype=np.int64)
|
||||||
|
if len(interior):
|
||||||
|
ok = np.all((labs @ Bint.T) % 3 == 0, axis=1)
|
||||||
|
labs = labs[ok]
|
||||||
|
if labs.shape[0] == 0:
|
||||||
|
return set(), len(boundary_C)
|
||||||
|
outer = (labs @ Cinc.T) % 3
|
||||||
|
return set(map(tuple, np.unique(outer, axis=0))), len(boundary_C)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
seed = int(sys.argv[1]) if len(sys.argv) > 1 else 0
|
||||||
|
nprng = np.random.default_rng(seed)
|
||||||
|
CAP = 18
|
||||||
|
|
||||||
|
stats = {True: [0, 0, 0, 0], False: [0, 0, 0, 0]} # branch: [n, nonempty, sign, marg]
|
||||||
|
examples_fail = []
|
||||||
|
|
||||||
|
for _ in range(300):
|
||||||
|
faces, hull = delaunay(int(nprng.integers(14, 34)), nprng)
|
||||||
|
adj, fadj, vfaces = build(faces)
|
||||||
|
lev = bfs(adj, min(hull))
|
||||||
|
if len(lev) != len(adj):
|
||||||
|
continue
|
||||||
|
depth = [min(lev[v] for v in faces[fi]) for fi in range(len(faces))]
|
||||||
|
maxd = max(depth)
|
||||||
|
for d in range(1, maxd + 1):
|
||||||
|
fge = [fi for fi in range(len(faces)) if depth[fi] >= d]
|
||||||
|
for comp in components(fge, fadj):
|
||||||
|
if not (1 <= len(comp) <= CAP):
|
||||||
|
continue
|
||||||
|
deeper = [fi for fi in comp if depth[fi] >= d + 1]
|
||||||
|
n_children = len(components(deeper, fadj))
|
||||||
|
is_branch = n_children >= 2
|
||||||
|
res = phi_of_region(comp, faces, vfaces, lev, d, CAP)
|
||||||
|
if res is None:
|
||||||
|
continue
|
||||||
|
S, k = res
|
||||||
|
rec = stats[is_branch]
|
||||||
|
rec[0] += 1
|
||||||
|
rec[1] += bool(S)
|
||||||
|
rec[2] += (bool(S) and sign_closed(S))
|
||||||
|
rec[3] += (bool(S) and marginals_full(S, k))
|
||||||
|
if S and not marginals_full(S, k) and len(examples_fail) < 6:
|
||||||
|
examples_fail.append((is_branch, n_children, len(comp), k,
|
||||||
|
len(S)))
|
||||||
|
|
||||||
|
for branch in (False, True):
|
||||||
|
n, ne, sg, mg = stats[branch]
|
||||||
|
tag = "BRANCH (>=2 children)" if branch else "LINEAR (1 child)"
|
||||||
|
if n:
|
||||||
|
print(f"{tag}: {n} regions")
|
||||||
|
print(f" non-empty : {ne}/{n} ({100*ne/n:.1f}%)")
|
||||||
|
print(f" sign-closed : {sg}/{n} ({100*sg/n:.1f}%)")
|
||||||
|
print(f" marginals-full : {mg}/{n} ({100*mg/n:.1f}%)")
|
||||||
|
else:
|
||||||
|
print(f"{tag}: 0 regions")
|
||||||
|
if examples_fail:
|
||||||
|
print("\n marginals-NOT-full examples (branch?,n_children,|G_C|,|C|,|Phi|):")
|
||||||
|
for e in examples_fail:
|
||||||
|
print(f" {e}")
|
||||||
|
else:
|
||||||
|
print("\n richness (incl. full marginals) held on every region tested.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
+167
@@ -0,0 +1,167 @@
|
|||||||
|
"""
|
||||||
|
Construct the triangulated disk (= nested tire substructure) that MAXIMALLY
|
||||||
|
constrains its outer cycle.
|
||||||
|
|
||||||
|
For a triangulated disk D with boundary cycle C = (0..n-1), the achievable outer
|
||||||
|
Heawood set is
|
||||||
|
|
||||||
|
Phi(D) = { (lambda*(v))_{v in C} : lambda in {+1,-1}^{faces},
|
||||||
|
sum_{f ∋ w} lambda(f) ≡ 0 for every interior vertex w } .
|
||||||
|
|
||||||
|
Phi depends only on the disk triangulation (no BFS/tree needed). We want the disk
|
||||||
|
minimising |Phi| -- the worst case for the pigeonhole. Note Phi is always
|
||||||
|
sign-closed and non-empty, so |Phi| >= 1, and |Phi| = 1 forces Phi = { all-zeros }.
|
||||||
|
|
||||||
|
Key local fact: a degree-3 interior vertex (one Apollonian stack) has incident
|
||||||
|
faces f1,f2,f3 with lambda(f1)+lambda(f2)+lambda(f3) ≡ 0 mod 3 over +/-1 values,
|
||||||
|
which forces f1=f2=f3. So stacking chains equalities and collapses Phi.
|
||||||
|
|
||||||
|
We (a) randomly search disks built by Apollonian stacking, and (b) try a
|
||||||
|
deterministic deep-stack construction, reporting the smallest Phi found.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import random
|
||||||
|
import sys
|
||||||
|
from itertools import product
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
def fan_triangulation(n):
|
||||||
|
"""n-gon (0..n-1) triangulated as a fan from vertex 0. No interior vertex."""
|
||||||
|
return [(0, i, i + 1) for i in range(1, n - 1)]
|
||||||
|
|
||||||
|
|
||||||
|
def stack(faces, idx, v):
|
||||||
|
a, b, c = faces[idx]
|
||||||
|
faces[idx] = (a, b, v)
|
||||||
|
faces.append((b, c, v))
|
||||||
|
faces.append((a, c, v))
|
||||||
|
|
||||||
|
|
||||||
|
def phi(faces, n, cap):
|
||||||
|
"""Phi on boundary 0..n-1; interior = vertices >= n."""
|
||||||
|
verts = set(v for f in faces for v in f)
|
||||||
|
interior = sorted(v for v in verts if v >= n)
|
||||||
|
F = len(faces)
|
||||||
|
if F > cap:
|
||||||
|
return None
|
||||||
|
# incidence
|
||||||
|
Bint = np.zeros((len(interior), F), dtype=np.int64)
|
||||||
|
iindex = {w: r for r, w in enumerate(interior)}
|
||||||
|
Cinc = np.zeros((n, F), dtype=np.int64)
|
||||||
|
for j, (a, b, c) in enumerate(faces):
|
||||||
|
for v in (a, b, c):
|
||||||
|
if v >= n:
|
||||||
|
Bint[iindex[v], j] = 1
|
||||||
|
else:
|
||||||
|
Cinc[v, j] = 1
|
||||||
|
labs = np.array(list(product((1, 2), repeat=F)), dtype=np.int64)
|
||||||
|
if len(interior):
|
||||||
|
keep = np.all((labs @ Bint.T) % 3 == 0, axis=1)
|
||||||
|
labs = labs[keep]
|
||||||
|
if labs.shape[0] == 0:
|
||||||
|
return set()
|
||||||
|
outer = (labs @ Cinc.T) % 3
|
||||||
|
return set(map(tuple, np.unique(outer, axis=0)))
|
||||||
|
|
||||||
|
|
||||||
|
def disp(s):
|
||||||
|
return tuple(-1 if int(x) == 2 else int(x) for x in s)
|
||||||
|
|
||||||
|
|
||||||
|
def gf3_rank(rows):
|
||||||
|
M = [[int(x) % 3 for x in r] for r in rows]
|
||||||
|
if not M:
|
||||||
|
return 0
|
||||||
|
nc = len(M[0]); r = 0
|
||||||
|
for c in range(nc):
|
||||||
|
piv = next((i for i in range(r, len(M)) if M[i][c] % 3), None)
|
||||||
|
if piv is None:
|
||||||
|
continue
|
||||||
|
M[r], M[piv] = M[piv], M[r]
|
||||||
|
inv = M[r][c] % 3
|
||||||
|
M[r] = [(x * inv) % 3 for x in M[r]]
|
||||||
|
for i in range(len(M)):
|
||||||
|
if i != r and M[i][c] % 3:
|
||||||
|
fct = M[i][c] % 3
|
||||||
|
M[i] = [(M[i][k] - fct * M[r][k]) % 3 for k in range(nc)]
|
||||||
|
r += 1
|
||||||
|
if r == len(M):
|
||||||
|
break
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def describe(P):
|
||||||
|
P = list(P)
|
||||||
|
sign_closed = all(tuple((3 - x) % 3 for x in s) in set(P) for s in P)
|
||||||
|
s0 = P[0]
|
||||||
|
D = [tuple((np.array(s) - np.array(s0)) % 3) for s in P]
|
||||||
|
rank = gf3_rank(D)
|
||||||
|
affine = (len(P) == 3 ** rank)
|
||||||
|
pow2 = (len(P) & (len(P) - 1)) == 0
|
||||||
|
return (f"sign-closed={sign_closed} affine-GF3={affine} "
|
||||||
|
f"|Phi|={len(P)} (power-of-2={pow2}) hull-dim={rank}")
|
||||||
|
|
||||||
|
|
||||||
|
def random_disk(n, n_stacks, rng):
|
||||||
|
faces = fan_triangulation(n)
|
||||||
|
nxt = n
|
||||||
|
for _ in range(n_stacks):
|
||||||
|
stack(faces, rng.randrange(len(faces)), nxt)
|
||||||
|
nxt += 1
|
||||||
|
return faces
|
||||||
|
|
||||||
|
|
||||||
|
def deep_stack_disk(n, n_stacks):
|
||||||
|
"""Always stack into the most-recently created face -> deep equality chain."""
|
||||||
|
faces = fan_triangulation(n)
|
||||||
|
nxt = n
|
||||||
|
for _ in range(n_stacks):
|
||||||
|
stack(faces, len(faces) - 1, nxt)
|
||||||
|
nxt += 1
|
||||||
|
return faces
|
||||||
|
|
||||||
|
|
||||||
|
def search(n, cap=18, trials=400, seed=0):
|
||||||
|
rng = random.Random(seed)
|
||||||
|
best = (10 ** 9, None, None)
|
||||||
|
max_stacks = (cap - (n - 2)) // 2
|
||||||
|
# random search
|
||||||
|
for _ in range(trials):
|
||||||
|
k = rng.randint(0, max_stacks)
|
||||||
|
faces = random_disk(n, k, rng)
|
||||||
|
P = phi(faces, n, cap)
|
||||||
|
if P is None:
|
||||||
|
continue
|
||||||
|
if len(P) < best[0]:
|
||||||
|
best = (len(P), k, P)
|
||||||
|
# deterministic deep stack at max depth
|
||||||
|
for k in range(max_stacks + 1):
|
||||||
|
faces = deep_stack_disk(n, k)
|
||||||
|
P = phi(faces, n, cap)
|
||||||
|
if P is not None and len(P) < best[0]:
|
||||||
|
best = (len(P), k, P)
|
||||||
|
size, k, P = best
|
||||||
|
print(f"n={n}: min |Phi| = {size} (= 2^(n-2) = {2**(n-2)}?) "
|
||||||
|
f"interior vertices = {k}, max stacks at cap {cap} = {max_stacks}")
|
||||||
|
print(f" {describe(P)}")
|
||||||
|
for s in sorted(P)[:6]:
|
||||||
|
print(f" {disp(s)}")
|
||||||
|
if len(P) > 6:
|
||||||
|
print(f" ... (+{len(P)-6} more)")
|
||||||
|
return size
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
ns = [int(x) for x in sys.argv[1:]] or [4, 5, 6, 7]
|
||||||
|
print("Searching for maximally-constraining disks (min |Phi|)\n")
|
||||||
|
for n in ns:
|
||||||
|
# bigger cap for small n
|
||||||
|
cap = 18 if n <= 6 else 16
|
||||||
|
search(n, cap=cap)
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
+129
@@ -0,0 +1,129 @@
|
|||||||
|
"""
|
||||||
|
Search for a UNIVERSAL Heawood boundary sequence for a tire graph.
|
||||||
|
|
||||||
|
Fix an outer boundary cycle B_out of length n (the interface at which a tire
|
||||||
|
glues to its parent). Each way of filling the annulus -- an inner boundary of
|
||||||
|
size m together with a spoke triangulation ("inner graph") -- gives a tire whose
|
||||||
|
annular faces induce a set of realisable outer Heawood sequences
|
||||||
|
|
||||||
|
R_out(tire) = { (lambda*(v0), ..., lambda*(v_{n-1})) : lambda in {+1,-1}^F }
|
||||||
|
⊆ {0,1,-1}^n .
|
||||||
|
|
||||||
|
A *universal sequence* for B_out is one realisable for EVERY inner graph, i.e. a
|
||||||
|
member of the intersection ∩_tire R_out(tire). If a universal sequence existed,
|
||||||
|
a parent could always present its negation and glue to any child regardless of
|
||||||
|
the child's interior.
|
||||||
|
|
||||||
|
Note: chords of the inner outerplanar graph O lie inside B_in and bound no
|
||||||
|
annular face, so they do not change R_out -- only (n, m, spoke-path) do. And
|
||||||
|
intersecting over a SUBFAMILY of inner graphs can only OVERestimate the true
|
||||||
|
intersection, so finding the intersection empty over simple-cycle inner fills is
|
||||||
|
already conclusive that NO universal sequence exists.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from itertools import combinations, product
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
def lattice_paths(n_outer, m_inner):
|
||||||
|
"""All spoke triangulations: strings with n_outer 'O' moves, m_inner 'I'."""
|
||||||
|
N = n_outer + m_inner
|
||||||
|
for opos in combinations(range(N), n_outer):
|
||||||
|
opos = set(opos)
|
||||||
|
yield "".join("O" if i in opos else "I" for i in range(N))
|
||||||
|
|
||||||
|
|
||||||
|
def annular_faces(n, m, path):
|
||||||
|
"""Faces (triangles) of the annulus between outer n-cycle (0..n-1) and inner
|
||||||
|
m-cycle (n..n+m-1) under the spoke path. Starts at spoke (outer0, inner0)."""
|
||||||
|
faces = []
|
||||||
|
i = j = 0
|
||||||
|
for mv in path:
|
||||||
|
if mv == "O":
|
||||||
|
faces.append((i % n, (i + 1) % n, n + (j % m)))
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
faces.append((i % n, n + (j % m), n + ((j + 1) % m)))
|
||||||
|
j += 1
|
||||||
|
return faces
|
||||||
|
|
||||||
|
|
||||||
|
def fan_faces(n):
|
||||||
|
"""m = 1 degenerate inner boundary: a wheel/fan, center = vertex n."""
|
||||||
|
return [(i, (i + 1) % n, n) for i in range(n)]
|
||||||
|
|
||||||
|
|
||||||
|
def realisable_outer(n, faces):
|
||||||
|
"""Set of outer Heawood sequences over all +/-1 face labellings."""
|
||||||
|
F = len(faces)
|
||||||
|
A = np.zeros((n, F), dtype=np.int64) # outer-vertex x face incidence
|
||||||
|
for f, tri in enumerate(faces):
|
||||||
|
for v in tri:
|
||||||
|
if v < n:
|
||||||
|
A[v, f] = 1
|
||||||
|
labs = np.array(list(product((1, 2), repeat=F)), dtype=np.int64)
|
||||||
|
vals = (labs @ A.T) % 3
|
||||||
|
# display residues in {0, 1, -1}: 2 -> -1
|
||||||
|
vals = np.where(vals == 2, -1, vals)
|
||||||
|
return set(tuple(int(x) for x in row) for row in np.unique(vals, axis=0))
|
||||||
|
|
||||||
|
|
||||||
|
def tires_for(n, m_max, fcap):
|
||||||
|
"""Yield (label, faces) for inner fills of an n-outer tire."""
|
||||||
|
yield (f"m=1 fan", fan_faces(n))
|
||||||
|
for m in range(2, m_max + 1):
|
||||||
|
if n + m > fcap:
|
||||||
|
continue
|
||||||
|
for path in lattice_paths(n, m):
|
||||||
|
yield (f"m={m} {path}", annular_faces(n, m, path))
|
||||||
|
|
||||||
|
|
||||||
|
def run(n, m_max=7, fcap=13):
|
||||||
|
inter = None
|
||||||
|
n_tires = 0
|
||||||
|
min_set = (10**9, None)
|
||||||
|
shrink_trace = []
|
||||||
|
for label, faces in tires_for(n, m_max, fcap):
|
||||||
|
R = realisable_outer(n, faces)
|
||||||
|
n_tires += 1
|
||||||
|
if len(R) < min_set[0]:
|
||||||
|
min_set = (len(R), label)
|
||||||
|
if inter is None:
|
||||||
|
inter = set(R)
|
||||||
|
else:
|
||||||
|
before = len(inter)
|
||||||
|
inter &= R
|
||||||
|
if len(inter) < before:
|
||||||
|
shrink_trace.append((n_tires, label, len(inter)))
|
||||||
|
if not inter:
|
||||||
|
break
|
||||||
|
print(f"n={n}: {n_tires} tires tried, "
|
||||||
|
f"smallest single R_out = {min_set[0]} ({min_set[1]})")
|
||||||
|
if inter:
|
||||||
|
print(f" UNIVERSAL sequences found: {len(inter)}")
|
||||||
|
for s in sorted(inter)[:12]:
|
||||||
|
print(f" {s}")
|
||||||
|
else:
|
||||||
|
print(f" NO universal sequence: intersection emptied after "
|
||||||
|
f"{n_tires} tires")
|
||||||
|
print(" intersection size as tires were added (last few shrinks):")
|
||||||
|
for t in shrink_trace[-6:]:
|
||||||
|
print(f" after tire {t[0]:4d} ({t[1]}): |∩| = {t[2]}")
|
||||||
|
return bool(inter)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
ns = [int(sys.argv[1])]
|
||||||
|
else:
|
||||||
|
ns = [3, 4, 5, 6]
|
||||||
|
print("Searching for universal Heawood boundary sequences\n")
|
||||||
|
for n in ns:
|
||||||
|
run(n)
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
+172
@@ -0,0 +1,172 @@
|
|||||||
|
"""
|
||||||
|
Transfer operator for the Heawood program, in the cleanest self-similar setting:
|
||||||
|
a chain of annular tires with n_out = n_in = n. Each tire's labelling map sends
|
||||||
|
+/-1 face labels to (outer sequence, inner sequence). Gluing a child below means
|
||||||
|
the parent's inner sequence must negate (mod 3) the child's achievable outer
|
||||||
|
sequence. So the achievable outer-interface set propagates UP the chain by
|
||||||
|
|
||||||
|
Phi(parent) = { outer(lambda) : lambda in {+-1}^F,
|
||||||
|
inner(lambda) in -Phi(child) }.
|
||||||
|
|
||||||
|
This is a monotone set-operator on subsets of (Z/3)^n. Iterating it models a
|
||||||
|
deepening nested chain; we look for a FIXED POINT (absorbing set) and test which
|
||||||
|
candidate self-similar invariants the limit satisfies:
|
||||||
|
* non-empty
|
||||||
|
* closed under the global sign flip s -> -s
|
||||||
|
* local marginals: does every position attain all of {0,1,-1}?
|
||||||
|
* is it an affine GF(3) subspace? (we expect NO -- R_T is a zonotope)
|
||||||
|
* does a linear/parity constraint cut it out?
|
||||||
|
Sequences are stored mod 3 in {0,1,2}; printed in {0,1,-1} (2 -> -1).
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from itertools import product
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
def annular_tire(n_out, n_in, path):
|
||||||
|
"""Faces between outer cycle 0..n_out-1 and inner cycle n_out..n_out+n_in-1."""
|
||||||
|
faces = []
|
||||||
|
i = j = 0
|
||||||
|
for mv in path:
|
||||||
|
if mv == "O":
|
||||||
|
faces.append((i % n_out, (i + 1) % n_out, n_out + (j % n_in)))
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
faces.append((i % n_out, n_out + (j % n_in), n_out + ((j + 1) % n_in)))
|
||||||
|
j += 1
|
||||||
|
return faces
|
||||||
|
|
||||||
|
|
||||||
|
def labelling_pairs(n_out, n_in, faces):
|
||||||
|
"""All (outer_seq, inner_seq) over lambda in {+1,-1}^F, as Z/3 tuples."""
|
||||||
|
F = len(faces)
|
||||||
|
Ao = np.zeros((n_out, F), dtype=np.int64)
|
||||||
|
Ai = np.zeros((n_in, F), dtype=np.int64)
|
||||||
|
for f, (a, b, c) in enumerate(faces):
|
||||||
|
for v in (a, b, c):
|
||||||
|
if v < n_out:
|
||||||
|
Ao[v, f] = 1
|
||||||
|
else:
|
||||||
|
Ai[v - n_out, f] = 1
|
||||||
|
labs = np.array(list(product((1, 2), repeat=F)), dtype=np.int64)
|
||||||
|
outer = (labs @ Ao.T) % 3
|
||||||
|
inner = (labs @ Ai.T) % 3
|
||||||
|
return [(tuple(o), tuple(i)) for o, i in zip(outer.tolist(), inner.tolist())]
|
||||||
|
|
||||||
|
|
||||||
|
def make_operator(pairs):
|
||||||
|
def op(phi_child):
|
||||||
|
neg = {tuple((3 - x) % 3 for x in s) for s in phi_child}
|
||||||
|
return {o for (o, inn) in pairs if inn in neg}
|
||||||
|
return op
|
||||||
|
|
||||||
|
|
||||||
|
def iterate_to_fixed(op, start, max_iter=50):
|
||||||
|
phi = frozenset(start)
|
||||||
|
seen = [phi]
|
||||||
|
for _ in range(max_iter):
|
||||||
|
nxt = frozenset(op(phi))
|
||||||
|
if nxt == phi:
|
||||||
|
return phi, "fixed", len(seen)
|
||||||
|
if nxt in seen:
|
||||||
|
return nxt, "cycle", len(seen)
|
||||||
|
phi = nxt
|
||||||
|
seen.append(phi)
|
||||||
|
return phi, "no-converge", len(seen)
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------- invariant tests -------------------------------------------
|
||||||
|
def disp(s):
|
||||||
|
return tuple(-1 if x == 2 else x for x in s)
|
||||||
|
|
||||||
|
|
||||||
|
def gf3_rank(rows):
|
||||||
|
M = [[x % 3 for x in r] for r in rows]
|
||||||
|
if not M:
|
||||||
|
return 0
|
||||||
|
nc = len(M[0]); r = 0
|
||||||
|
for c in range(nc):
|
||||||
|
piv = next((i for i in range(r, len(M)) if M[i][c] % 3), None)
|
||||||
|
if piv is None:
|
||||||
|
continue
|
||||||
|
M[r], M[piv] = M[piv], M[r]
|
||||||
|
inv = M[r][c] % 3 # 1->1, 2->2 are self-inverse mod 3
|
||||||
|
M[r] = [(x * inv) % 3 for x in M[r]]
|
||||||
|
for i in range(len(M)):
|
||||||
|
if i != r and M[i][c] % 3:
|
||||||
|
f = M[i][c] % 3
|
||||||
|
M[i] = [(M[i][k] - f * M[r][k]) % 3 for k in range(nc)]
|
||||||
|
r += 1
|
||||||
|
if r == len(M):
|
||||||
|
break
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def is_affine(S):
|
||||||
|
S = list(S)
|
||||||
|
if len(S) <= 1:
|
||||||
|
return True
|
||||||
|
s0 = S[0]
|
||||||
|
D = [tuple((np.array(s) - np.array(s0)) % 3) for s in S]
|
||||||
|
return len(S) == 3 ** gf3_rank(D)
|
||||||
|
|
||||||
|
|
||||||
|
def marginals_full(S, n):
|
||||||
|
return all({s[i] for s in S} == {0, 1, 2} for i in range(n))
|
||||||
|
|
||||||
|
|
||||||
|
def sign_closed(S):
|
||||||
|
return all(tuple((3 - x) % 3 for x in s) in S for s in S)
|
||||||
|
|
||||||
|
|
||||||
|
def linear_constraints(S, n):
|
||||||
|
"""Dimension of the space of linear forms vanishing on S-s0 (codim of hull)."""
|
||||||
|
S = list(S)
|
||||||
|
if len(S) <= 1:
|
||||||
|
return n
|
||||||
|
s0 = S[0]
|
||||||
|
D = [tuple((np.array(s) - np.array(s0)) % 3) for s in S]
|
||||||
|
return n - gf3_rank(D)
|
||||||
|
|
||||||
|
|
||||||
|
def analyse(tag, S, n):
|
||||||
|
print(f" [{tag}] |Phi|={len(S)} of 3^{n}={3**n} "
|
||||||
|
f"sign-closed={sign_closed(S)} marginals-full={marginals_full(S,n)} "
|
||||||
|
f"affine={is_affine(S)} hull-codim={linear_constraints(S,n)}")
|
||||||
|
|
||||||
|
|
||||||
|
def run(n, paths=None):
|
||||||
|
if paths is None:
|
||||||
|
# a few distinct same-n annular triangulations
|
||||||
|
paths = ["OI" * n, "O" * n + "I" * n, ("OOI" * n)[:2 * n]]
|
||||||
|
paths = [p for p in paths if p.count("O") == n and p.count("I") == n]
|
||||||
|
print(f"=== n={n} ===")
|
||||||
|
full = set(product((0, 1, 2), repeat=n))
|
||||||
|
for path in paths:
|
||||||
|
faces = annular_tire(n, n, path)
|
||||||
|
pairs = labelling_pairs(n, n, faces)
|
||||||
|
op = make_operator(pairs)
|
||||||
|
single = set(o for (o, _) in pairs) # leaf: full single-tire outer set
|
||||||
|
fixed, how, steps = iterate_to_fixed(op, single)
|
||||||
|
# also iterate from the universal start (all sequences allowed below)
|
||||||
|
fixed2, how2, _ = iterate_to_fixed(op, full)
|
||||||
|
print(f" path={path}: single-tire |outer|={len(single)}; "
|
||||||
|
f"iterate->{how} in {steps} steps; "
|
||||||
|
f"same-limit-from-full={fixed==fixed2}")
|
||||||
|
analyse("limit", fixed, n)
|
||||||
|
sample = sorted(disp(s) for s in fixed)[:8]
|
||||||
|
print(f" sample of limit set: {sample}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
ns = [int(x) for x in sys.argv[1:]] or [4, 5, 6]
|
||||||
|
print("Transfer-operator fixed points on same-n annular tire chains\n")
|
||||||
|
for n in ns:
|
||||||
|
run(n)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
\relax
|
||||||
|
\gdef \@abspage@last{2}
|
||||||
+296
@@ -0,0 +1,296 @@
|
|||||||
|
This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 17 JUN 2026 02:12
|
||||||
|
entering extended mode
|
||||||
|
restricted \write18 enabled.
|
||||||
|
%&-line parsing enabled.
|
||||||
|
**boundary_restriction_structure.tex
|
||||||
|
(./boundary_restriction_structure.tex
|
||||||
|
LaTeX2e <2021-11-15> patch level 1
|
||||||
|
L3 programming layer <2022-02-24>
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls
|
||||||
|
Document Class: article 2021/10/04 v1.4n Standard LaTeX document class
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/base/size11.clo
|
||||||
|
File: size11.clo 2021/10/04 v1.4n Standard LaTeX file (size option)
|
||||||
|
)
|
||||||
|
\c@part=\count185
|
||||||
|
\c@section=\count186
|
||||||
|
\c@subsection=\count187
|
||||||
|
\c@subsubsection=\count188
|
||||||
|
\c@paragraph=\count189
|
||||||
|
\c@subparagraph=\count190
|
||||||
|
\c@figure=\count191
|
||||||
|
\c@table=\count192
|
||||||
|
\abovecaptionskip=\skip47
|
||||||
|
\belowcaptionskip=\skip48
|
||||||
|
\bibindent=\dimen138
|
||||||
|
)
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty
|
||||||
|
Package: amsmath 2021/10/15 v2.17l AMS math features
|
||||||
|
\@mathmargin=\skip49
|
||||||
|
|
||||||
|
For additional information on amsmath, use the `?' option.
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty
|
||||||
|
Package: amstext 2021/08/26 v2.01 AMS text
|
||||||
|
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty
|
||||||
|
File: amsgen.sty 1999/11/30 v2.0 generic functions
|
||||||
|
\@emptytoks=\toks16
|
||||||
|
\ex@=\dimen139
|
||||||
|
))
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty
|
||||||
|
Package: amsbsy 1999/11/29 v1.2d Bold Symbols
|
||||||
|
\pmbraise@=\dimen140
|
||||||
|
)
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty
|
||||||
|
Package: amsopn 2021/08/26 v2.02 operator names
|
||||||
|
)
|
||||||
|
\inf@bad=\count193
|
||||||
|
LaTeX Info: Redefining \frac on input line 234.
|
||||||
|
\uproot@=\count194
|
||||||
|
\leftroot@=\count195
|
||||||
|
LaTeX Info: Redefining \overline on input line 399.
|
||||||
|
\classnum@=\count196
|
||||||
|
\DOTSCASE@=\count197
|
||||||
|
LaTeX Info: Redefining \ldots on input line 496.
|
||||||
|
LaTeX Info: Redefining \dots on input line 499.
|
||||||
|
LaTeX Info: Redefining \cdots on input line 620.
|
||||||
|
\Mathstrutbox@=\box50
|
||||||
|
\strutbox@=\box51
|
||||||
|
\big@size=\dimen141
|
||||||
|
LaTeX Font Info: Redeclaring font encoding OML on input line 743.
|
||||||
|
LaTeX Font Info: Redeclaring font encoding OMS on input line 744.
|
||||||
|
\macc@depth=\count198
|
||||||
|
\c@MaxMatrixCols=\count199
|
||||||
|
\dotsspace@=\muskip16
|
||||||
|
\c@parentequation=\count266
|
||||||
|
\dspbrk@lvl=\count267
|
||||||
|
\tag@help=\toks17
|
||||||
|
\row@=\count268
|
||||||
|
\column@=\count269
|
||||||
|
\maxfields@=\count270
|
||||||
|
\andhelp@=\toks18
|
||||||
|
\eqnshift@=\dimen142
|
||||||
|
\alignsep@=\dimen143
|
||||||
|
\tagshift@=\dimen144
|
||||||
|
\tagwidth@=\dimen145
|
||||||
|
\totwidth@=\dimen146
|
||||||
|
\lineht@=\dimen147
|
||||||
|
\@envbody=\toks19
|
||||||
|
\multlinegap=\skip50
|
||||||
|
\multlinetaggap=\skip51
|
||||||
|
\mathdisplay@stack=\toks20
|
||||||
|
LaTeX Info: Redefining \[ on input line 2938.
|
||||||
|
LaTeX Info: Redefining \] on input line 2939.
|
||||||
|
)
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amssymb.sty
|
||||||
|
Package: amssymb 2013/01/14 v3.01 AMS font symbols
|
||||||
|
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty
|
||||||
|
Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support
|
||||||
|
\symAMSa=\mathgroup4
|
||||||
|
\symAMSb=\mathgroup5
|
||||||
|
LaTeX Font Info: Redeclaring math symbol \hbar on input line 98.
|
||||||
|
LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold'
|
||||||
|
(Font) U/euf/m/n --> U/euf/b/n on input line 106.
|
||||||
|
))
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty
|
||||||
|
Package: amsthm 2020/05/29 v2.20.6
|
||||||
|
\thm@style=\toks21
|
||||||
|
\thm@bodyfont=\toks22
|
||||||
|
\thm@headfont=\toks23
|
||||||
|
\thm@notefont=\toks24
|
||||||
|
\thm@headpunct=\toks25
|
||||||
|
\thm@preskip=\skip52
|
||||||
|
\thm@postskip=\skip53
|
||||||
|
\thm@headsep=\skip54
|
||||||
|
\dth@everypar=\toks26
|
||||||
|
)
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty
|
||||||
|
Package: graphicx 2021/09/16 v1.2d Enhanced LaTeX Graphics (DPC,SPQR)
|
||||||
|
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty
|
||||||
|
Package: keyval 2014/10/28 v1.15 key=value parser (DPC)
|
||||||
|
\KV@toks@=\toks27
|
||||||
|
)
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty
|
||||||
|
Package: graphics 2021/03/04 v1.4d Standard LaTeX Graphics (DPC,SPQR)
|
||||||
|
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty
|
||||||
|
Package: trig 2021/08/11 v1.11 sin cos tan (DPC)
|
||||||
|
)
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/graphics.cfg
|
||||||
|
File: graphics.cfg 2016/06/04 v1.11 sample graphics configuration
|
||||||
|
)
|
||||||
|
Package graphics Info: Driver file: pdftex.def on input line 107.
|
||||||
|
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-def/pdftex.def
|
||||||
|
File: pdftex.def 2020/10/05 v1.2a Graphics/color driver for pdftex
|
||||||
|
))
|
||||||
|
\Gin@req@height=\dimen148
|
||||||
|
\Gin@req@width=\dimen149
|
||||||
|
)
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/geometry/geometry.sty
|
||||||
|
Package: geometry 2020/01/02 v5.9 Page Geometry
|
||||||
|
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/generic/iftex/ifvtex.sty
|
||||||
|
Package: ifvtex 2019/10/25 v1.7 ifvtex legacy package. Use iftex instead.
|
||||||
|
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/generic/iftex/iftex.sty
|
||||||
|
Package: iftex 2022/02/03 v1.0f TeX engine tests
|
||||||
|
))
|
||||||
|
\Gm@cnth=\count271
|
||||||
|
\Gm@cntv=\count272
|
||||||
|
\c@Gm@tempcnt=\count273
|
||||||
|
\Gm@bindingoffset=\dimen150
|
||||||
|
\Gm@wd@mp=\dimen151
|
||||||
|
\Gm@odd@mp=\dimen152
|
||||||
|
\Gm@even@mp=\dimen153
|
||||||
|
\Gm@layoutwidth=\dimen154
|
||||||
|
\Gm@layoutheight=\dimen155
|
||||||
|
\Gm@layouthoffset=\dimen156
|
||||||
|
\Gm@layoutvoffset=\dimen157
|
||||||
|
\Gm@dimlist=\toks28
|
||||||
|
)
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/booktabs/booktabs.sty
|
||||||
|
Package: booktabs 2020/01/12 v1.61803398 Publication quality tables
|
||||||
|
\heavyrulewidth=\dimen158
|
||||||
|
\lightrulewidth=\dimen159
|
||||||
|
\cmidrulewidth=\dimen160
|
||||||
|
\belowrulesep=\dimen161
|
||||||
|
\belowbottomsep=\dimen162
|
||||||
|
\aboverulesep=\dimen163
|
||||||
|
\abovetopsep=\dimen164
|
||||||
|
\cmidrulesep=\dimen165
|
||||||
|
\cmidrulekern=\dimen166
|
||||||
|
\defaultaddspace=\dimen167
|
||||||
|
\@cmidla=\count274
|
||||||
|
\@cmidlb=\count275
|
||||||
|
\@aboverulesep=\dimen168
|
||||||
|
\@belowrulesep=\dimen169
|
||||||
|
\@thisruleclass=\count276
|
||||||
|
\@lastruleclass=\count277
|
||||||
|
\@thisrulewidth=\dimen170
|
||||||
|
)
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def
|
||||||
|
File: l3backend-pdftex.def 2022-02-07 L3 backend support: PDF output (pdfTeX)
|
||||||
|
\l__color_backend_stack_int=\count278
|
||||||
|
\l__pdf_internal_box=\box52
|
||||||
|
)
|
||||||
|
No file boundary_restriction_structure.aux.
|
||||||
|
\openout1 = `boundary_restriction_structure.aux'.
|
||||||
|
|
||||||
|
LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 18.
|
||||||
|
LaTeX Font Info: ... okay on input line 18.
|
||||||
|
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 18.
|
||||||
|
LaTeX Font Info: ... okay on input line 18.
|
||||||
|
LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 18.
|
||||||
|
LaTeX Font Info: ... okay on input line 18.
|
||||||
|
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 18.
|
||||||
|
LaTeX Font Info: ... okay on input line 18.
|
||||||
|
LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 18.
|
||||||
|
LaTeX Font Info: ... okay on input line 18.
|
||||||
|
LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 18.
|
||||||
|
LaTeX Font Info: ... okay on input line 18.
|
||||||
|
LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 18.
|
||||||
|
LaTeX Font Info: ... okay on input line 18.
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii
|
||||||
|
[Loading MPS to PDF converter (version 2006.09.02).]
|
||||||
|
\scratchcounter=\count279
|
||||||
|
\scratchdimen=\dimen171
|
||||||
|
\scratchbox=\box53
|
||||||
|
\nofMPsegments=\count280
|
||||||
|
\nofMParguments=\count281
|
||||||
|
\everyMPshowfont=\toks29
|
||||||
|
\MPscratchCnt=\count282
|
||||||
|
\MPscratchDim=\dimen172
|
||||||
|
\MPnumerator=\count283
|
||||||
|
\makeMPintoPDFobject=\count284
|
||||||
|
\everyMPtoPDFconversion=\toks30
|
||||||
|
) (/usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty
|
||||||
|
Package: epstopdf-base 2020-01-24 v2.11 Base part for package epstopdf
|
||||||
|
Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 4
|
||||||
|
85.
|
||||||
|
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg
|
||||||
|
File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Liv
|
||||||
|
e
|
||||||
|
))
|
||||||
|
*geometry* driver: auto-detecting
|
||||||
|
*geometry* detected driver: pdftex
|
||||||
|
*geometry* verbose mode - [ preamble ] result:
|
||||||
|
* driver: pdftex
|
||||||
|
* paper: <default>
|
||||||
|
* layout: <same size as paper>
|
||||||
|
* layoutoffset:(h,v)=(0.0pt,0.0pt)
|
||||||
|
* modes:
|
||||||
|
* h-part:(L,W,R)=(72.26999pt, 469.75502pt, 72.26999pt)
|
||||||
|
* v-part:(T,H,B)=(72.26999pt, 650.43001pt, 72.26999pt)
|
||||||
|
* \paperwidth=614.295pt
|
||||||
|
* \paperheight=794.96999pt
|
||||||
|
* \textwidth=469.75502pt
|
||||||
|
* \textheight=650.43001pt
|
||||||
|
* \oddsidemargin=0.0pt
|
||||||
|
* \evensidemargin=0.0pt
|
||||||
|
* \topmargin=-37.0pt
|
||||||
|
* \headheight=12.0pt
|
||||||
|
* \headsep=25.0pt
|
||||||
|
* \topskip=11.0pt
|
||||||
|
* \footskip=30.0pt
|
||||||
|
* \marginparwidth=59.0pt
|
||||||
|
* \marginparsep=10.0pt
|
||||||
|
* \columnsep=10.0pt
|
||||||
|
* \skip\footins=10.0pt plus 4.0pt minus 2.0pt
|
||||||
|
* \hoffset=0.0pt
|
||||||
|
* \voffset=0.0pt
|
||||||
|
* \mag=1000
|
||||||
|
* \@twocolumnfalse
|
||||||
|
* \@twosidefalse
|
||||||
|
* \@mparswitchfalse
|
||||||
|
* \@reversemarginfalse
|
||||||
|
* (1in=72.27pt=25.4mm, 1cm=28.453pt)
|
||||||
|
|
||||||
|
LaTeX Font Info: Trying to load font information for U+msa on input line 19.
|
||||||
|
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd
|
||||||
|
File: umsa.fd 2013/01/14 v3.01 AMS symbols A
|
||||||
|
)
|
||||||
|
LaTeX Font Info: Trying to load font information for U+msb on input line 19.
|
||||||
|
|
||||||
|
|
||||||
|
(/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd
|
||||||
|
File: umsb.fd 2013/01/14 v3.01 AMS symbols B
|
||||||
|
) [1
|
||||||
|
|
||||||
|
{/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] [2]
|
||||||
|
(./boundary_restriction_structure.aux) )
|
||||||
|
Here is how much of TeX's memory you used:
|
||||||
|
3254 strings out of 478268
|
||||||
|
48506 string characters out of 5846347
|
||||||
|
347668 words of memory out of 5000000
|
||||||
|
21442 multiletter control sequences out of 15000+600000
|
||||||
|
480359 words of font info for 70 fonts, out of 8000000 for 9000
|
||||||
|
1141 hyphenation exceptions out of 8191
|
||||||
|
55i,8n,62p,247b,208s stack positions out of 10000i,1000n,20000p,200000b,200000s
|
||||||
|
</usr/local/texlive/2022/texmf-dist/fon
|
||||||
|
ts/type1/public/amsfonts/cm/cmbx10.pfb></usr/local/texlive/2022/texmf-dist/font
|
||||||
|
s/type1/public/amsfonts/cm/cmbx12.pfb></usr/local/texlive/2022/texmf-dist/fonts
|
||||||
|
/type1/public/amsfonts/cm/cmex10.pfb></usr/local/texlive/2022/texmf-dist/fonts/
|
||||||
|
type1/public/amsfonts/cm/cmmi10.pfb></usr/local/texlive/2022/texmf-dist/fonts/t
|
||||||
|
ype1/public/amsfonts/cm/cmmi12.pfb></usr/local/texlive/2022/texmf-dist/fonts/ty
|
||||||
|
pe1/public/amsfonts/cm/cmmi8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type
|
||||||
|
1/public/amsfonts/cm/cmr10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/
|
||||||
|
public/amsfonts/cm/cmr12.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/pu
|
||||||
|
blic/amsfonts/cm/cmr17.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/publ
|
||||||
|
ic/amsfonts/cm/cmr8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/
|
||||||
|
amsfonts/cm/cmss8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/am
|
||||||
|
sfonts/cm/cmsy10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/ams
|
||||||
|
fonts/cm/cmsy8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfo
|
||||||
|
nts/cm/cmti10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfon
|
||||||
|
ts/cm/cmtt10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfont
|
||||||
|
s/symbols/msbm10.pfb>
|
||||||
|
Output written on boundary_restriction_structure.pdf (2 pages, 184212 bytes).
|
||||||
|
PDF statistics:
|
||||||
|
91 PDF objects out of 1000 (max. 8388607)
|
||||||
|
54 compressed objects within 1 object stream
|
||||||
|
0 named destinations out of 1000 (max. 500000)
|
||||||
|
1 words of extra memory for PDF output out of 10000 (max. 10000000)
|
||||||
|
|
||||||
BIN
Binary file not shown.
+139
@@ -0,0 +1,139 @@
|
|||||||
|
\documentclass[11pt]{article}
|
||||||
|
\usepackage{amsmath,amssymb,amsthm}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\usepackage{geometry}
|
||||||
|
\usepackage{booktabs}
|
||||||
|
\geometry{margin=1in}
|
||||||
|
|
||||||
|
\title{Heawood boundary restriction sets:\\
|
||||||
|
zonotope structure and the $2^{n-2}$ constraint floor}
|
||||||
|
\author{}
|
||||||
|
\date{}
|
||||||
|
|
||||||
|
\newtheorem*{obs}{Observation}
|
||||||
|
\newtheorem*{prop}{Proposition}
|
||||||
|
\newtheorem*{conj}{Conjecture}
|
||||||
|
\newtheorem*{lem}{Lemma}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
|
||||||
|
This note records the empirical structure of the Heawood boundary
|
||||||
|
restriction sets studied in \texttt{paper.tex}, and a clean
|
||||||
|
\emph{maximal-constraint} result. All claims below are backed by the
|
||||||
|
experiments in \texttt{experiments/} (filenames given inline). Sequences
|
||||||
|
live in $(\mathbb{Z}/3)^{\,\cdot}$, displayed in $\{0,1,-1\}$.
|
||||||
|
|
||||||
|
\section*{Setup}
|
||||||
|
|
||||||
|
Fix a triangulated disk $D$ with boundary cycle $C = (v_0,\dots,v_{n-1})$.
|
||||||
|
A Heawood face-labelling is $\lambda : \{\text{faces of }D\} \to \{+1,-1\}$,
|
||||||
|
with induced vertex value $\lambda^{*}(v) = \sum_{f \ni v}\lambda(f) \bmod 3$.
|
||||||
|
The achievable outer set is
|
||||||
|
\[
|
||||||
|
\Phi(D) \;=\; \bigl\{\, (\lambda^{*}(v_0),\dots,\lambda^{*}(v_{n-1}))
|
||||||
|
\;:\; \lambda \in \{+1,-1\}^{F(D)},\;
|
||||||
|
\lambda^{*}(w) \equiv 0 \ \forall\ \text{interior } w \,\bigr\}.
|
||||||
|
\]
|
||||||
|
This is exactly the value the recursive transfer operator produces at
|
||||||
|
$C$ (interior consistency $=$ all descendant gluings performed; boundary
|
||||||
|
deferred). Crucially $\Phi(D)$ depends \emph{only} on the disk
|
||||||
|
triangulation, not on any BFS/tire-tree labelling.
|
||||||
|
|
||||||
|
\section*{1. The restriction sets are zonotopes, not subspaces}
|
||||||
|
|
||||||
|
(\texttt{probe\_RK\_structure.py}.) Writing $\lambda = \mathbf{1}+b$ with
|
||||||
|
$b \in \{0,1\}^F$, the labelling map is $\lambda \mapsto M\mathbf{1}+Mb
|
||||||
|
\pmod 3$, a linear image of the Boolean cube ($M$ the face/vertex
|
||||||
|
incidence matrix). Over $3655$ cluster restriction sets $R_{\mathsf K}$:
|
||||||
|
none was an affine $\mathrm{GF}(3)$ subspace; the map is usually
|
||||||
|
injective, so $|R_{\mathsf K}| = 2^{|F|}$ (a power of $2$ inside the
|
||||||
|
column space of size $3^{\operatorname{rank} M}$); the nowhere-zero
|
||||||
|
constraint $\lambda \neq 0$ shrank the set below the full linear image in
|
||||||
|
\emph{every} case. The only surviving linear structure is
|
||||||
|
$R_{\mathsf K} \subseteq \operatorname{col}(M)$ (cokernel relations such
|
||||||
|
as $\sum_v \lambda^{*}(v) \equiv 0$). So $\Phi$ is a $\mathbb{Z}/3$
|
||||||
|
zonotope: a projected cube, sign-closed but not closed under addition.
|
||||||
|
|
||||||
|
\section*{2. ``Richness'' is not a self-similar invariant}
|
||||||
|
|
||||||
|
(\texttt{transfer\_operator.py}, \texttt{branch\_invariant.py}.) In a
|
||||||
|
homogeneous same-$n$ spoke-only chain the operator saturates: $\Phi$ has
|
||||||
|
full single-position marginals (every interface vertex independently
|
||||||
|
attains all of $\{0,1,-1\}$), and the alternating tire reaches the
|
||||||
|
\emph{entire} space $3^n$. This is an artifact of non-shrinking annuli
|
||||||
|
with no interior constraints. On genuine triangulations the marginal
|
||||||
|
fullness holds for only ${\sim}8\%$ of regions: depth (not branching)
|
||||||
|
shrinks $\Phi$, e.g.\ a region with $|C|=10$ realised only $|\Phi|=400$
|
||||||
|
of $3^{10}\approx 59000$. Only non-emptiness and sign-closure survive,
|
||||||
|
both of which are automatic / equivalent to $4$CT. Hence no abundance
|
||||||
|
(counting) pigeonhole: a working invariant must tolerate \emph{small}
|
||||||
|
$\Phi$.
|
||||||
|
|
||||||
|
\section*{3. The maximal-constraint floor}
|
||||||
|
|
||||||
|
(\texttt{maximally\_constrain.py}.) Minimising $|\Phi(D)|$ over disks with
|
||||||
|
a fixed boundary $n$-cycle:
|
||||||
|
|
||||||
|
\begin{center}
|
||||||
|
\begin{tabular}{ccccc}
|
||||||
|
\toprule
|
||||||
|
$n$ & $4$ & $5$ & $6$ & $7$\\
|
||||||
|
\midrule
|
||||||
|
$\min |\Phi|$ (search) & $4$ & $8$ & $16$ & $32$\\
|
||||||
|
fan, $0$ interior vertices & $4$ & $8$ & $16$ & $32$\\
|
||||||
|
$2^{\,n-2}$ & $4$ & $8$ & $16$ & $32$\\
|
||||||
|
\bottomrule
|
||||||
|
\end{tabular}
|
||||||
|
\end{center}
|
||||||
|
|
||||||
|
A search over random and deep-stacked disks (up to $8$ interior vertices)
|
||||||
|
never beat $2^{n-2}$, and the interior-free triangulation already
|
||||||
|
attains it. Thus:
|
||||||
|
|
||||||
|
\begin{obs}
|
||||||
|
The outer $n$-cycle cannot be constrained below $2^{n-2}$ achievable
|
||||||
|
sequences, and no nested structure is needed to reach the floor: a single
|
||||||
|
trivial tire is already maximal. Deep nesting only approaches the floor
|
||||||
|
from above.
|
||||||
|
\end{obs}
|
||||||
|
|
||||||
|
The achievability is transparent: in a fan from $v_0$,
|
||||||
|
\[
|
||||||
|
\sigma_1 = \lambda_1,\quad
|
||||||
|
\sigma_i = \lambda_{i-1}+\lambda_i \ (1<i<n-1),\quad
|
||||||
|
\sigma_{n-1} = \lambda_{n-2},\quad
|
||||||
|
\sigma_0 = \textstyle\sum_j \lambda_j ,
|
||||||
|
\]
|
||||||
|
so $(\lambda_1,\dots,\lambda_{n-2})$ is recoverable from $\sigma$ and the
|
||||||
|
map is injective onto $2^{n-2}$ sequences. The lower bound over
|
||||||
|
\emph{all} disks is the substance:
|
||||||
|
|
||||||
|
\begin{conj}[Boundary degrees of freedom]
|
||||||
|
For every triangulated disk $D$ with boundary $n$-cycle,
|
||||||
|
$|\Phi(D)| \ge 2^{n-2}$. Equivalently, the $n-2$ binary degrees of
|
||||||
|
freedom carried by the boundary-incident faces survive every interior
|
||||||
|
Heawood constraint (which relates only interior-incident faces).
|
||||||
|
\end{conj}
|
||||||
|
|
||||||
|
The minimal set is itself a sign-closed zonotope of size $2^{n-2}$, hull
|
||||||
|
dimension $n-2$, not a $\mathrm{GF}(3)$ subspace --- the same fingerprint
|
||||||
|
as $\S1$.
|
||||||
|
|
||||||
|
\section*{Consequence for the pigeonhole}
|
||||||
|
|
||||||
|
Even a maximally-constraining child still presents $2^{n-2}$ outer
|
||||||
|
options --- exponential in the interface length $n$. So the gluing
|
||||||
|
problem has the least slack at \emph{short} interfaces ($n=4$ leaves $4$
|
||||||
|
options, $n=3$ leaves $2$), and is easy at long ones. The crux of the
|
||||||
|
Heawood programme therefore lives entirely at short level cycles, exactly
|
||||||
|
where the medial programme's $N(k)$ bound concentrates.
|
||||||
|
|
||||||
|
\medskip
|
||||||
|
\noindent\emph{Meta-remark.} Because $4$CT holds, every actual
|
||||||
|
triangulation glues, so no experiment can exhibit an obstruction (pair or
|
||||||
|
chain). The experiments measure \emph{structure} (zonotope type,
|
||||||
|
constraint floor), not proof difficulty; the difficulty is localised, not
|
||||||
|
removed.
|
||||||
|
|
||||||
|
\end{document}
|
||||||
Reference in New Issue
Block a user