Enumerate colour/tread phase over the residue graphs
residue_phase_sweep.py exhaustively enumerates the two colouring control knobs
-- the per-annulus tread phase {0,1}^A and the root-DFS colour order perms(0,1,2)
-- on top of every insertion-site combo, for the graphs the random-phase site
sweep still fails. canonical_coloring_explicit makes this deterministic.
Result (residue_phase_sweep_results.txt): the two hub graphs are RESCUED once
phase is enumerated rather than sampled (so the random-phase fail count overstates
difficulty); the genuine obstructions that survive sites x phases x colour-orders
are exactly the face-leaf graphs (terminal-triangle leaf gadget). Smallest is
seed2 #26 [3,6,3] face (1 combo, 24 settings, all fail at gadget-removal) -- a
minimal obstruction target. Caveat: try_establish is a bounded local Kempe search,
so STILL FAILS means unreachable by the bounded search from canonical-even over
all knob settings, not that no Kempe path exists.
Findings note updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+46
@@ -85,6 +85,52 @@ knobs. Building this joint solver — and finding the smallest configuration, if
|
||||
forcing a self-loop or odd cycle — is the next step and the exact thing a proof
|
||||
would need to rule out.
|
||||
|
||||
## Exhausting the control knobs over the residue
|
||||
|
||||
The site sweep above counts a graph `ok` if some placement works over only **4
|
||||
random** colour phases per combo. `residue_phase_sweep.py` takes the graphs that
|
||||
sweep still fails (the residue) and **exhaustively enumerates the colour/tread
|
||||
phase and the root-DFS colour order** on top of every insertion site:
|
||||
|
||||
```
|
||||
phases in {0,1}^A (A = # non-root annuli; the tread phases)
|
||||
colorder in perms(0,1,2) (root-region DFS colour priority)
|
||||
```
|
||||
|
||||
over all site combos (cap 512). Result on the seed-1/seed-2 residue
|
||||
(`residue_phase_sweep_results.txt`):
|
||||
|
||||
```
|
||||
seed1 #16 [3,8,3,5] hub RESCUED (720 settings, 18 ok)
|
||||
seed1 #51 [3,7,3,3,7] hub RESCUED (42336 settings, 196 ok)
|
||||
seed1 #3 [3,7,4,6,3] face STILL FAILS (672 settings, 0 ok)
|
||||
seed1 #4 [3,4,5,5,3] face STILL FAILS (2400 settings, 0 ok)
|
||||
seed2 #26 [3,6,3] face STILL FAILS (24 settings, 0 ok)
|
||||
seed2 #30 [3,3,6,7,3] face STILL FAILS (2016 settings, 0 ok)
|
||||
seed2 #54 [3,3,5,3] face STILL FAILS (720 settings, 0 ok)
|
||||
```
|
||||
|
||||
Two things fall out:
|
||||
|
||||
1. **Phase reachability explains part of the residue.** The two `hub` graphs are
|
||||
*rescued* once the phase/colour-order is enumerated rather than sampled — they
|
||||
were never genuine obstructions, just unlucky random phases. So the
|
||||
random-phase `fail` count overstates the true difficulty.
|
||||
2. **The genuine obstructions are exactly the `face`-leaf graphs.** Every graph
|
||||
that survives exhausting sites × phases × colour-orders has `leaf='face'` —
|
||||
i.e. an inner terminal triangle carrying a leaf gadget. The smallest is
|
||||
`seed2 #26 [3,6,3]` (one site combo, 24 settings, all fail at
|
||||
`gadget-removal`): a minimal target for the joint solver / an obstruction
|
||||
hunt. (#26 fails at the gadget step; #3/#4/#30/#54 at `diamond-switch`.)
|
||||
|
||||
**Caveat on "STILL FAILS".** `try_establish` is a *bounded* local Kempe search
|
||||
(≤3 components anchored at the quad support). So `STILL FAILS` means *no (site,
|
||||
phase, colour-order) lets the bounded search from the canonical-even colouring
|
||||
reach a descendable one* — not that no Kempe path exists. A descendable colouring
|
||||
provably exists (M(G) is 3-colourable); whether it is reachable under a principled
|
||||
(joint, unbounded) switch is the open question, now sharply localised to the
|
||||
`face`-leaf family.
|
||||
|
||||
## Caveats / domain
|
||||
|
||||
- Real plantri triangulations mostly `skip:chord-level-edge` under BFS-from-outer
|
||||
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
"""Exhaustively enumerate the colour/tread-phase control knobs over the residue
|
||||
graphs -- the synthetic ring triangulations the SITE sweep still fails on while
|
||||
only *sampling* random phases (kempe_even_program_harness.run_graph draws 4
|
||||
random phase vectors + colour orders per site combo).
|
||||
|
||||
For each residue graph we sweep, per insertion-site combo:
|
||||
phases in {0,1}^A (A = number of non-root annuli; the tread phases)
|
||||
colorder in perms(0,1,2) (the root-region DFS colour priority)
|
||||
and ask whether SOME (combo, phases, colorder) yields a full reduction. This
|
||||
isolates how much of the residue is a phase-reachability artifact vs a genuine
|
||||
obstruction.
|
||||
|
||||
Usage: python3 residue_phase_sweep.py # the seed1/seed2 residue
|
||||
python3 residue_phase_sweep.py SEED IDX # one graph
|
||||
"""
|
||||
import sys
|
||||
import random
|
||||
import itertools as it
|
||||
import kempe_even_program_harness as H
|
||||
|
||||
# residue from the random-phase site sweep (seed, idx) -> reported failure
|
||||
RESIDUE = [(1, 3), (1, 4), (1, 16), (1, 51), (2, 26), (2, 30), (2, 54)]
|
||||
MAX_COMBOS = 512
|
||||
|
||||
|
||||
def reconstruct(seed, idx):
|
||||
"""Replay the synthetic loop to get graph #idx (rng state is sequential)."""
|
||||
rng = random.Random(seed)
|
||||
g = outer = sizes = leaf = None
|
||||
for _ in range(idx + 1):
|
||||
sizes, leaf = H.random_profile(rng)
|
||||
g, outer = H.ring_triangulation(sizes, leaf, rng)
|
||||
return g, outer, sizes, leaf
|
||||
|
||||
|
||||
def descend_explicit(template, outer, orig, gadgets, combo, phases, colorder):
|
||||
gg = template.copy()
|
||||
dia = [gg.insert_diamond(a, b) for (a, b) in combo]
|
||||
an = H.Analysis(gg, outer)
|
||||
if an.degenerate:
|
||||
return f"skip:post-diamond-{an.degenerate}"
|
||||
if any(len(c) % 2 for _, c in an.seams):
|
||||
return "fail:seam-evening"
|
||||
col, reason = H.canonical_coloring_explicit(gg, an.level, outer, phases, colorder)
|
||||
if col is None:
|
||||
return f"fail:canonical-{reason}"
|
||||
for (w, u, v, x, t) in dia:
|
||||
adj = H.medial_adj(gg)
|
||||
quad = H.quad_of(gg, w, u, v)
|
||||
if quad is None:
|
||||
return "fail:diamond-quad"
|
||||
support = [H.e(quad[i], quad[(i + 1) % 4]) for i in range(4)]
|
||||
if not H.try_establish(col, adj, support,
|
||||
lambda c: H.diamond_condition(c, quad) is not None):
|
||||
return "fail:diamond-switch"
|
||||
H.collapse_degree4(gg, col, w, u, v)
|
||||
if not H.verify_proper(gg, col):
|
||||
return "fail:improper-after-diamond"
|
||||
for (y, z, u, v, x, t) in gadgets:
|
||||
done = False
|
||||
for first, second, tri in ((z, y, (x, u, v)), (y, z, (u, v, t))):
|
||||
gt, ct = gg.copy(), dict(col)
|
||||
adj = H.medial_adj(gt)
|
||||
quad = H.quad_of(gt, first, u, v)
|
||||
if quad is None:
|
||||
continue
|
||||
support = [H.e(quad[i], quad[(i + 1) % 4]) for i in range(4)]
|
||||
if not H.try_establish(ct, adj, support,
|
||||
lambda c: H.diamond_condition(c, quad) is not None):
|
||||
continue
|
||||
H.collapse_degree4(gt, ct, first, u, v)
|
||||
if not H.verify_proper(gt, ct):
|
||||
continue
|
||||
adj2 = H.medial_adj(gt)
|
||||
a_, b_, c_ = tri
|
||||
support2 = [H.e(a_, b_), H.e(b_, c_), H.e(c_, a_)]
|
||||
if not H.try_establish(ct, adj2, support2,
|
||||
lambda c: H.rainbow_condition(c, tri)):
|
||||
continue
|
||||
H.collapse_degree3(gt, ct, second)
|
||||
if not H.verify_proper(gt, ct):
|
||||
continue
|
||||
gg, col = gt, ct
|
||||
done = True
|
||||
break
|
||||
if not done:
|
||||
return "fail:gadget-removal"
|
||||
if set(gg.rot) != orig:
|
||||
return "fail:vertex-mismatch"
|
||||
if not H.verify_proper(gg, col):
|
||||
return "fail:final-improper"
|
||||
return "ok"
|
||||
|
||||
|
||||
def phase_arity(template, outer, combo):
|
||||
gg = template.copy()
|
||||
for (a, b) in combo:
|
||||
gg.insert_diamond(a, b)
|
||||
an = H.Analysis(gg, outer)
|
||||
sk, _ = H.coloring_skeleton(gg, an.level, outer)
|
||||
return len(sk['nonroot']) if sk else None
|
||||
|
||||
|
||||
def sweep(seed, idx):
|
||||
g, outer, sizes, leaf = reconstruct(seed, idx)
|
||||
orig = set(g.rot)
|
||||
prep = H._prep_gadgets(g.copy(), outer)
|
||||
if isinstance(prep, str):
|
||||
print(f"seed{seed} #{idx} {sizes} {leaf}: prep -> {prep}")
|
||||
return
|
||||
template, an_g, gadgets = prep
|
||||
sites = H._candidate_sites(an_g)
|
||||
if sites is None:
|
||||
print(f"seed{seed} #{idx} {sizes} {leaf}: no diamond site")
|
||||
return
|
||||
combos = list(it.product(*sites))
|
||||
n_full = len(combos)
|
||||
truncated = n_full > MAX_COMBOS
|
||||
combos = combos[:MAX_COMBOS]
|
||||
tried = wins = 0
|
||||
first = None
|
||||
for combo in combos:
|
||||
nph = phase_arity(template, outer, combo)
|
||||
if nph is None:
|
||||
continue
|
||||
for phases in it.product((0, 1), repeat=nph):
|
||||
for colorder in it.permutations((0, 1, 2)):
|
||||
tried += 1
|
||||
res = descend_explicit(template, outer, orig, gadgets,
|
||||
combo, phases, list(colorder))
|
||||
if res == "ok":
|
||||
wins += 1
|
||||
if first is None:
|
||||
first = (combo, phases, colorder)
|
||||
verdict = "RESCUED" if wins else "STILL FAILS"
|
||||
msg = (f"seed{seed} #{idx} {sizes} {leaf}: {verdict} "
|
||||
f"(combos={n_full}{'[capped]' if truncated else ''}, "
|
||||
f"settings tried={tried}, ok={wins})")
|
||||
if first:
|
||||
msg += f"\n first ok: site={first[0]} phases={first[1]} colorder={first[2]}"
|
||||
print(msg)
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) == 3:
|
||||
sweep(int(sys.argv[1]), int(sys.argv[2]))
|
||||
else:
|
||||
for seed, idx in RESIDUE:
|
||||
sweep(seed, idx)
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
seed1 #3 [3, 7, 4, 6, 3] face: STILL FAILS (combos=7, settings tried=672, ok=0)
|
||||
seed1 #4 [3, 4, 5, 5, 3] face: STILL FAILS (combos=25, settings tried=2400, ok=0)
|
||||
seed1 #16 [3, 8, 3, 5] hub: RESCUED (combos=15, settings tried=720, ok=18)
|
||||
first ok: site=((11, 13), (14, 15)) phases=(0, 1, 0) colorder=(0, 1, 2)
|
||||
seed1 #51 [3, 7, 3, 3, 7] hub: RESCUED (combos=441, settings tried=42336, ok=196)
|
||||
first ok: site=((6, 7), (10, 11), (14, 15), (21, 22)) phases=(0, 0, 1, 0) colorder=(0, 1, 2)
|
||||
seed2 #26 [3, 6, 3] face: STILL FAILS (combos=1, settings tried=24, ok=0)
|
||||
seed2 #30 [3, 3, 6, 7, 3] face: STILL FAILS (combos=21, settings tried=2016, ok=0)
|
||||
seed2 #54 [3, 3, 5, 3] face: STILL FAILS (combos=15, settings tried=720, ok=0)
|
||||
Reference in New Issue
Block a user