Source-dual cut is a spanning tree of the dual (38 faces, 37 edges,
connected and acyclic) after 20 cut edges removed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A tread's annular frontier can split into several disjoint cycles; each
is now recognised as a separate full medial tire graph instead of
disqualifying the whole tread.
- recognise() returns a list of (g, bij), one per annular cycle
component; add annular_cycle_components() and _recognise_one(), and
iterate components in iter_pieces().
- Key tires/results by (depth, component) throughout both experiment
drivers: _label_treads chains each tire to a parent-depth down tooth
sharing its apex; _cap_cut/_assemble_cut_graph/to_json/summary and the
dual-cut collectors/draws follow suit.
Source vertex selection for the dual-cut experiment now deep-embeds a
random face and roots at the outer-cap vertex. The source-dual figure
labels the source-graph vertices, highlights the entry medial vertex,
and uses a cap-rooted concentric layout.
For seed 7 / face (14,15,19) this recognises treads 3 and 4 as two
tires each (3.0,3.1,4.0,4.1), so every dual face is now cut.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add draw_cap_png and a --cap-png flag: render tread 0 as a wheel (source
hub, link-cycle rim, cap triangles filled, cap cut marked) from the
extract_tread roles, since tread 0 is skipped by tire recognition (a wheel
has no up teeth). Render funcD seed7's cap.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reflects cutting up-tooth apexes (except entry teeth): seed7 removes 17
source-dual edges, so its dual retains cycles (not a tree).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Duplicate the apex medial vertex of every singleton up tooth across all
recognised treads -- except each tread's entry tooth, whose apex is left
intact -- in addition to the closing annular-vertex cuts.
For seed59 (source 5) this removes 19 = n-1 source-dual edges and the
remaining dual is a tree (verified for every source/entry choice). The
tree property holds exactly when n-1 distinct edges are cut; some graphs
(e.g. seed7, cutting 17) fall short and retain cycles.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add draw_tire_cuts_png (and a --tire-png flag): one panel per recognised
tread showing the annular cycle, up/down/bite teeth, walk-depth labels, and
cut slits, ported from medial_tire_cut_labelling.to_tikz. Render the
function-D (seed 7) graph's tire cuts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reads the chained medial tire cut off as a source-dual cut (planar dual of
G with the cut edges removed), as in seed59_min5_dual_cut_1.png, and counts
the missing dual edges around each dual face (vertex of G).
Four chained entry points, broad to narrow control:
- random_dual_cut: random min-degree-5 maximal planar graph -> ...
- dual_cut_random_source: random level source -> ...
- dual_cut_random_entry: random root entry tooth -> ...
- medial_tire_dual_cut: worker chaining the walk-depth labelling/cut.
Refactor _label_treads to accept an optional root_entry_edge (default
preserves the arbitrary-up-tooth behaviour) so the worker can pin the entry.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a --whole mode to draw_medial_tire_cut.py that renders the entire
medial graph M(G) (the assembled cut graph), on a Kamada-Kawai layout,
with the recognised tires highlighted (black annular vertices, blue/red
teeth carrying walk depths, larger red bite apex) and the rest of M(G)
in grey. Add the resulting figure (Figure 3) and a describing paragraph
to the paper for the n=20 seed-72 example, via an \input-ed .tikz file.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add experiments/draw_medial_tire_cut.py, the paper-graphics companion
that imports run_experiment and emits a TikZ panel (walk-depth labels +
cut slits) per recognised tread via to_tikz. Add the resulting figure
(Example 3.2, Figure 2): the single recognised tread T_2 of the medial
tire decomposition of a random maximal planar graph on 20 vertices
(seed 72), an 8-cycle piece with a bite, labelled and cut.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New experiments/run_medial_tire_cut_experiment.py: generates a random
maximal planar graph (stacked seed + random diagonal flips), builds the
medial graph, takes the tire decomposition at a random vertex level
source, walk-depth labels and cuts each full medial tire graph chained
down the tire tree, and assembles one final cut graph of M(G) with a
global label map (data only; graphics go in a separate script).
Fix label_and_cut: the root face is None, which collided with the
next(..., None) sentinel, leaving teeth unlabelled when the entry up
tooth lay inside a bite gap; use a distinct sentinel so the ascent to
the root face runs.
Add a "Chaining across the tire tree" section to the paper, clarifying
that the candidate parent down teeth are the boundary (singleton) down
teeth only -- bite teeth are interior to the parent and shared with no
child, so a lower-walk bite is skipped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New experiments/medial_tire_cut_labelling.py: takes a full medial tire
graph and an entry up tooth and runs the walk-depth labelling-and-cut
procedure, reusing the full medial tire generator's model and emitting
TikZ. Add a generator-produced 8-tooth example to the paper (Figure 1,
Example 2.3) showing the labelling and the two cuts, plus a remark
fixing the cut's closing tooth for descended faces.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New paper "Medial Tire Cuts" citing the medial tire decompositions
paper. States the goal of decomposing the medial graph into a tree of
3-faces, and gives the walk-depth labelling-and-cut procedure for a
single full medial tire graph: a cut duplicates the annular vertex
where a face's tooth traversal closes (planar unzip), reducing the
inner faces to teeth.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop the faint base-graph (G') edges and the dotted restored base edge from the
medial panels, leaving just the medial graph (medial vertices at edge midpoints,
medial edges, colours, halos, and the restored-diagonal medial square). Panels A
and B still show the triangulation.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The walkthrough previously used a concentric layout whose outer-triangle->ring
spokes can cross -- not a valid plane embedding. Rebuild draw_walkthrough.py on
networkx planar_layout with an explicit crossing check: G, G', and the medial
M(G') drawn at edge midpoints are each verified crossing-free before rendering.
G' is embedded once and reused for panels B/C/D; G reuses it when still planar.
The medial-at-midpoints drawing is planar except for the medial triangle of the
geometric outer face (its midpoint-chords would cut across the unbounded region),
so those three edges are detected via the convex hull and omitted; the remainder
is verified crossing-free. Note updated to describe the embedding.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
draw_failing_graph.py renders seed2 #26 (ring [3,6,3]+face leaf, 12 vertices),
the smallest graph the programme fails on after exhausting sites x tread-phases x
root colour-orders. Uses networkx planar_layout for a straight-line embedding and
verifies no two non-incident edges cross before drawing. Panel A: plain embedding;
panel B: BFS levels with the odd level-2 seam (the inner triangle 9-11-10) bold,
the terminal leaf face shaded -- the face-leaf/gadget spot where removal fails.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
Refactor canonical_coloring into coloring_skeleton (phase-independent parts) +
canonical_coloring_explicit (explicit phases + DFS colour order) + a random-phase
wrapper for back-compat. This exposes the two control knobs deterministically so
they can be enumerated rather than only sampled.
Add a fully worked example on the smallest clean graph (ring [3,5]+hub, 9
vertices, one odd seam, no gadgets): even_program_walkthrough.md traces all six
stages -- generate G with embedding, pick source + BFS levels, choose the diamond
site that evens the level-5 seam, build M(G'), the canonical colouring (seam
mono-3, hub annulus alternates, root by DFS), and a real {1,2}-Kempe switch that
makes the diamond quad reducible. dump_walkthrough.py reproduces every number;
draw_walkthrough.py renders the 4-panel figure even_program_walkthrough.png.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
run_graph no longer takes the first admissible seam edge per odd seam. It now
enumerates every valid diamond site per odd seam (_candidate_sites), sweeps the
full Cartesian product (capped by --max-combos), runs <=4 colour phases per
combination, and counts a graph ok iff SOME placement fully descends. Reports
both the old first-match tally and the swept tally, plus design-space stats and
how many graphs the sweep rescued.
Finding: most "fail:diamond-switch" cases were heuristic, not intrinsic. The
old 39/60 was the first-match heuristic (one point in the design space, and
seed-sensitive 31-39). Sweeping insertion sites rescues ~20 of ~24 first-match
failures:
seed 1: first-match 31 ok / 29 fail -> sweep 54 ok / 6 fail (rescued 23)
seed 2: first-match 36 ok / 24 fail -> sweep 57 ok / 3 fail (rescued 21)
Only ~3-6 fail:diamond-switch survive the full site sweep -- those are the real
obstruction targets for the joint {1,3}-cycle bipartiteness solver. The colour/
tread phase is still only randomized over 4 attempts, not enumerated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Constructive route: surger G so every level cycle is even (two-vertex leaf gadget
on terminal triangles -> 4-wheel, no defect; diamond on odd internal seams), take
the canonical even colouring of M(G') (no 4CT used), Kempe-remove the planted
degree-4/3 vertices to reach a proper 3-colouring of M(G).
Pipeline runs end to end on synthetic ring triangulations: surgery, canonical
colouring, and gadget removal all work; the program lands on the CYCLE LAYER
(39/60 ok, rest fail:diamond-switch). Diagnostic: a descendable colouring always
EXISTS (M(G) is 3-colourable), so failures are Kempe-reachability from the
canonical even colouring, not non-existence -- the entire difficulty is localised
there. Greedy per-diamond switching is insufficient because diamonds share vertical
{1,3}-Kempe cycles; the principled solve is joint (bipartiteness of the diamond /
side-cycle constraint graph), which is the identified next step. Includes the leaf
gadget figure and a findings note.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add kempe_rt_composition_probe.py: Ext(T) = boundary necklaces realisable on a
subtree's outer seam by a compatible Kempe-balanced selection; monotone maps over
minimal-antichain families decide whether empty Ext is reachable. Modeling facts
established: the seam is exactly the singleton down apexes (bite apexes have parent
faces on both sides, hence parent-internal); necklace states are exact because a
child attaches with free dihedral placement (dihedral-closed sequence sets).
Result over all no-length-3-boundary tiles n<=14 (7750 tiles, 1966 distinct
relations, 149 leaf, 27 branching): empty Ext is NOT reachable — every assemblable
tree admits a compatible selection, verifying the chain-pigeonhole conjecture
exhaustively for tire trees with treads n<=14 and no separating triangles. The
fixpoint saturates in 2 rounds: restriction does not accumulate along chains.
Tightest subtree pins a size-5 seam to the single necklace 00012; every smallest
minimal Ext contains the blocky/regular state. Relations cached (~6MB) for cheap
extension to larger n. Caveat: terminal facial-triangle leaves not yet modeled.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add kempe_regular_family_test.py (fixed family, per-tile early-exit, --branch-only).
Threads 614/614 at n=12 but FAILS at n=15 on two classes of no-separating-triangle
tiles: non-branching large-even-outer + odd inner (UUUUUUDUDUDUDUD, p=10, face 5) and
branching odd-outer + two even inner faces (UDUDUDDUDUDDDDD bite=(5,12), p=5, [4,4];
11/1022 branching fail). This is the R_T coupling (not a product) biting at scale: the
uniform family sets outer/inner states independently per size. The shortcut was
stronger than the chain-pigeonhole conjecture (which allows per-interface freedom), so
its failure costs a constructive route, not the conjecture; pairwise overlap still
holds. Next line: per-interface R_T composition respecting coupling.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Full uniform-family CSP at n=14 --no-tri (4403 tiles, 193 branching) is FEASIBLE:
one family threads every tile incl. branching nodes (outer rim + both inner faces
at once). Independent candidate test threads 193/193 branching tiles. Witness is
fully regular: sigma_m = 0^m if m even (monochromatic), 0^(m-2)12 if m odd. So on
the 4CT-relevant class the chained pigeonhole is constructively resolved throughout
the tested range (n=9,12,14, incl. branching).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add kempe_branching_min_probe.py (structural: >=2 inner faces with singletons).
Unrestricted branching first appears at n=11; no-separating-triangle branching
(>=2 inner faces each >=4 singletons, p>=4) first appears at n=14 (193 tiles).
Smallest example: word=UUUUDDDDDDDDDD bite=(8,13), p=4, faces root{4,5,6,7} and
bite{9,10,11,12}. n=14 is the smallest place to test the uniform family / R_T
composition on a genuine branching no-separating-triangle tile.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add --no-tri filter (exclude tiles with a length-3 boundary = separating/non-facial
triangle in G: outer rim of 3 up teeth, or an inner face of exactly 3 singleton
downs) to the trend and uniform-family probes.
The n=12 breaker UUUDUDUDUDUD bite=(3,11) has a size-3 inner face (encloses d5,d7,d9)
and is excluded. With the restriction the size-7 universal at n=12 is restored
(|D[7]| 0->2), every |D[m]|>=1 across n=6..13, and the uniform-family CSP becomes
FEASIBLE at n=12 with the simplest family (monochromatic on even sizes, min-cut on
odd). So the only universal failure was an artifact of admitting non-4-connected
configs; on the 4CT-relevant class gluing is constructively trivial in range.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add plot_breaker_tile.py and figure for word=UUUDUDUDUDUD bite=(3,11): structure
(7 up teeth = size-7 outer rim, bite (3,11), singleton downs d5,d7,d9) plus a
Kempe-balanced colouring. Reconfirms the outer rim realises 9/10 admissible size-7
necklaces, never 0001112 -- the lone tile that empties the size-7 universal at n=12.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add kempe_universal_trend_probe.py (|D[m]| per size across n). Across n=6..13 and
all sizes, the ONLY empty per-size universal is (n=12, m=7): at n=13 size 7 is back
to |D|=2 with more boundaries (579), so the vanishing is sporadic, not monotone.
The lone n=12 breaker is the outer rim of word=UUUDUDUDUDUD bite=(3,11) (most-
alternating 7-up word, antipodal bite), realising 9/10 size-7 necklaces and missing
only 0001112. Correct the earlier "doomed at scale" reading in the findings note:
the uniform shortcut almost always works (near-total coverage) but is fragile to a
single exceptional tile; pairwise gluability still always holds.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Write up the R_T coupling, the uniform-family result (feasible n=9, infeasible
n=12 via empty size-7 universal, 0001112 blocked 210/211), and the open threads.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pursue the paper's medial pigeonhole programme (R_T restriction relation,
chain-pigeonhole conjecture) at the data level.
Findings: R_T (outer<->inner boundary necklace, one Kempe-balanced colouring)
is genuinely coupled, not a product of its projections. A uniform per-size
boundary-state family threading every tile EXISTS at n=9 (unique per size, the
balanced-block necklaces 0011/000011/012/00012 -- not monochromatic), but FAILS
at n=12: size-7 seams admit no universal state (|D[7]|=0; near-universal 0001112
realised on 210/211 boundaries, blocked by one tile). So the uniform "same state
everywhere" shortcut breaks once large odd seams appear and universals vanish as
the tile population grows; the per-interface pigeonhole choice is genuinely
needed. Pairwise gluability still holds, so this locates the conjecture's
difficulty rather than obstructing gluing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Each tile realises only a subset of the parity-admissible alphabet on its rim,
and tiles genuinely omit interfaces (n=12 m=8: max 273/274, min 43). But any
two tiles always glue: interface subsets always overlap (n=9 m=3-6, n=12 m=3-8)
-- usually via a global universal seam present on every inner+outer rim, and
where none exists (n=12 m=7) the worst pair still shares 14 seams. The universal
seams are the low-complexity ones (<=2 colours, single contiguous block). No
local gluing obstruction; any obstruction must be global across a nested stack.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
For each interface size m, compare the realized census vocabulary (outer
up-tooth apexes and inner singleton-down apexes) against the full
parity-admissible set. At n=12, m=3..8 every parity-admissible sequence is
realized on both faces (counts 1,4,10,31,91,274; none missing), and up==down
throughout -- the n=9 result is n-independent and scales to m=8. Validated
against the known n=9 answer before running n=12.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The anchored single-representative reading interacted with dihedral graph
dedup to record an arbitrary orientation of each necklace, producing a
spurious up-vs-down split at n=9,m=6 (001212 only up, 010122 only down --
the same necklace). Add dihedral_reading_sequences(), which unions the
canonical reading over all 2n dihedral anchors and exactly reproduces the
brute un-deduped census; make it the default for both experiments, with
--anchored to recover the old behaviour. Document the artifact and fix in
kempe_sequence_orientation_note.md.
Regenerate up + down for n=9, m=3..6. Up and down now agree on sequences
and groupings at every m (m=6: identical 31 sequences, 6 groups; the
001212/010122 pair appears on both sides). Groupings coarsen vs anchored
(m=4: 3 groups; m=5: 2 groups) since the orientation-honest vocabulary
merges previously split sequence-sets.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mirror of the up-tooth experiment with the distinguished valid face moved
from the outer face to an inner non-tooth face (root or bite inner-gap).
For each (M(T), inner face) config holding m singleton down-tooth apexes,
record the apex colour sequence (cyclic order, mod colour permutation) over
Kempe-balanced colourings and group configs by their sequence-set. Runs for
m=3,4,5,6 with per-sequence notes, figures, and a config atlas.
Finding: inner faces realise the same parity-admissible sequence vocabulary
and the same distinct-sequence counts (1/4/10/28) as the outer face, i.e.
the Kempe-parity law acts uniformly on every valid face. At m=6 the configs
are the U<->D embedding mirror of the up-m=6 graphs (matching 7 configs,
28 sequences, 127 colourings).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Enumerate Kempe-balanced 3-colourings of every M(T) with |A(T)|=9 and a
fixed number m of up teeth, record the up-tooth apex colour sequence
(cyclic order, mod colour permutation only), and group the M(T) by their
set of unique sequences. Runs for m=3,4,5,6 with per-sequence notes and
figures plus a summary atlas.
Finding: realised sequences obey outer-face Kempe parity (all three
colour-counts share m's parity). Distinct sequences grow 1/4/10/28 while
M(T) count falls 23/29/18/7 across m=3..6.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add draw_tire_realization.py: for each full medial tire graph from the seed-1
analysis, draw every proper 3-colouring (mod colour permutation) in a grid,
each panel coloured by its three colour classes and banner-labelled Realized /
Unrealized / Invalid, and write one standalone note per graph (plus a README
index). Refactor tire_realization_analysis to expose iter_pieces() yielding
per-piece coloured colourings.
Output: tire_realization_seed1/ with 17 piece notes + figures.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
For a random 12-vertex maximal planar graph (sphere convex hull), enumerate
all proper 3-colourings of M(G), take the BFS-level (tire-tree) decomposition
from every source vertex, and build each full medial tire graph M(T) in the
ambient tread-face model (cycle + teeth + bites). Recognise each M(T) as a
FullMedialTireGraph and label every proper 3-colouring Realized (Kempe-balanced
and a restriction of a global colouring), Unrealized (balanced but not a
restriction), or Invalid (not balanced).
Findings on seed 1 (17 pieces, M(G) with 90 colourings): zero realized-but-
invalid colourings (confirms Remark 5.8 on a real triangulation), and 12 of 17
pieces carry Unrealized colourings -- Kempe-balance is necessary but not
sufficient for realization; it is sufficient only on cap-like all-up/shallow
treads.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bites arise when the inner outerplanar graph O has a bridge: the bridge
edge is traversed twice by the outer-face walk, so its medial vertex is
adjacent to four annular vertices.
- check_remark58_bite.py: a minimal bite tread (outer 4-cycle + interior
bridge u-w) restricts to Kempe-balanced on all colourings (outer face).
- check_remark58_bite_rich.py: O = triangle abc + pendant bridge a-d gives
one bite plus three singleton down teeth in the bite's inner-gap face;
every restriction is Kempe-balanced (the three gap singletons are a
rainbow in every global colouring).
Update Remark 5.8's verification note: the bite case, including singletons
in the bite-gap face, is now confirmed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Computational checks of the necessity of Kempe-balance (Remark 5.8):
- check_medial_face_parity.py shows the naive "even P-coloured vertices
per medial face" claim is false (odd vertex-faces on the octahedron and
stacked triangulations), so the original face-parity justification was
wrong.
- check_remark58_bitefree.py builds genuine bite-free tire pieces (capped
triangulated annuli) and confirms every proper 3-colouring of M(G)
restricts to a Kempe-balanced colouring (|A(T)|=6,8,10,12, all
colourings, zero failures).
Rewrite Remark 5.8 to cite the correct mechanism: the up/down apexes lie
on level cycles, and a P-Kempe cycle meets each level cycle in an even
number of P-coloured incidences (Lemma 5.6). Note the bite case is not
yet checked end to end.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>