diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/experiments/check_remark58_bite.py b/papers/medial_tire_decompositions_of_plane_triangulations/experiments/check_remark58_bite.py new file mode 100644 index 0000000..371d896 --- /dev/null +++ b/papers/medial_tire_decompositions_of_plane_triangulations/experiments/check_remark58_bite.py @@ -0,0 +1,116 @@ +"""Directly test Remark 5.8 on a genuine tire piece that contains a BITE. + +A bite arises when the inner outerplanar graph O has a bridge: the bridge edge +is traversed twice by the outer-face walk, so it borders two tread triangles and +its medial vertex is adjacent to four annular medial vertices. + +Minimal construction. Outer 4-cycle o0,o1,o2,o3; two interior vertices u,w +joined by a bridge u-w (V_in = {u,w}). Triangulate the disk so that u-w lies in +two tread triangles: + + (o0,o1,u) (o0,u,o3) (o1,w,u) (o1,o2,w) (o2,o3,w) (o3,u,w) + +Cap the outer cycle with an apex N (the bridge bounds no inner hole, so no inner +cap is needed). The result G is a closed plane triangulation; M(G) is 4-regular. + +Edge classification (by endpoints): annular = one endpoint outer & one inner; +up tooth = both endpoints outer (outer-cycle edge); down tooth = both endpoints +inner (here only the bridge u-w). The bridge's medial vertex is the bite apex. + +Remark 5.8 predicts every proper 3-colouring of M(G) restricts to a +Kempe-balanced colouring. Here the only non-trivial condition is the outer face +(the four up apexes), since the single bite contributes no singleton down teeth. +""" + +from __future__ import annotations + +import networkx as nx + +from check_remark58_bitefree import ekey, medial_graph, proper_3_colorings + +PAIRS = ((0, 1), (0, 2), (1, 2)) + +OUTER = ["o0", "o1", "o2", "o3"] +INNER = ["u", "w"] + +TREAD_TRIANGLES = [ + ("o0", "o1", "u"), + ("o0", "u", "o3"), + ("o1", "w", "u"), + ("o1", "o2", "w"), + ("o2", "o3", "w"), + ("o3", "u", "w"), +] + + +def build(): + g = nx.Graph() + for tri in TREAD_TRIANGLES: + a, b, c = tri + g.add_edges_from([(a, b), (b, c), (a, c)]) + # outer cap + for i in range(4): + g.add_edges_from([("N", OUTER[i]), ("N", OUTER[(i + 1) % 4])]) + return g + + +def classify_tread_edges(g): + out = set(OUTER) + inn = set(INNER) + tread_edges = set() + for tri in TREAD_TRIANGLES: + a, b, c = tri + tread_edges |= {ekey(a, b), ekey(b, c), ekey(a, c)} + annular, up, down = [], [], [] + for e in tread_edges: + a, b = e + ao, bo = a in out, b in out + ai, bi = a in inn, b in inn + if (ao and bi) or (ai and bo): + annular.append(e) + elif ao and bo: + up.append(e) + elif ai and bi: + down.append(e) + return annular, up, down + + +def run(): + g = build() + assert nx.check_planarity(g)[0] + M = medial_graph(g) + annular, up, down = classify_tread_edges(g) + annular_set = set(annular) + + # confirm there is a bite: a down edge whose medial vertex has 4 annular nbrs + bites = [e for e in down if sum(1 for nb in M.neighbors(e) if nb in annular_set) == 4] + print(f"tread: annular={len(annular)} up={len(up)} down={len(down)} " + f"bite apexes={len(bites)} (bite edge: {bites})") + + colorings = proper_3_colorings(M, limit=20000) + balanced = 0 + bad = [] + for col in colorings: + ok = all( + sum(1 for e in up if col[e] in pair) % 2 == 0 + for pair in PAIRS + ) + if ok: + balanced += 1 + else: + bad.append(col) + + print(f"|V(G)|={g.number_of_nodes()} |M(G)|={M.number_of_nodes()} " + f"colourings tested={len(colorings)}") + print(f" outer-face (up-apex) balanced={balanced} UNBALANCED={len(bad)}") + if bad: + print(f" first unbalanced up colours: {[bad[0][e] for e in up]}") + print() + print("Remark 5.8 holds on this bite tread" + if not bad else + "Remark 5.8 FAILS on this bite tread") + return len(bad) + + +if __name__ == "__main__": + run() diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/experiments/check_remark58_bite_rich.py b/papers/medial_tire_decompositions_of_plane_triangulations/experiments/check_remark58_bite_rich.py new file mode 100644 index 0000000..8d605bd --- /dev/null +++ b/papers/medial_tire_decompositions_of_plane_triangulations/experiments/check_remark58_bite_rich.py @@ -0,0 +1,132 @@ +"""Test Remark 5.8 on a bite tread that also has singleton down teeth in the +bite's inner-gap face -- the subtle case of the condition. + +Inner outerplanar graph O = triangle (a,b,c) plus a pendant bridge a-d. Its +outer-face walk is the cyclic sequence W = [d, a, b, c, a]: the bridge a-d is +traversed twice (-> a bite), the triangle edges a-b, b-c, c-a once each (-> three +singleton down teeth, all sitting in the bite's inner-gap face). + +We triangulate the annulus between an outer m-cycle and W by the lattice-path +method, searching interleavings for one giving a simple closed triangulation +after capping the outer cycle with an apex N. Then we test Remark 5.8: every +proper 3-colouring of M(G) restricts to a Kempe-balanced colouring, i.e. + + * the up apexes (outer edges) are even per colour pair, and + * the three singleton down apexes (a-b, b-c, c-a), which share the bite-gap + face, are even per colour pair (equivalently: a rainbow). +""" + +from __future__ import annotations + +import itertools + +import networkx as nx + +from check_remark58_bitefree import ekey, medial_graph, proper_3_colorings + +PAIRS = ((0, 1), (0, 2), (1, 2)) +INNER_WALK = ["d", "a", "b", "c", "a"] # bridge a-d traversed twice +SINGLETON_DOWN = [ekey("a", "b"), ekey("b", "c"), ekey("c", "a")] +BITE_EDGE = ekey("a", "d") + + +def build_tread(m: int, path: str): + """Build the annular triangulation for a given lattice path (m 'O', L 'I').""" + outer = [f"o{t}" for t in range(m)] + W = INNER_WALK + L = len(W) + g = nx.Graph() + g.add_edge(outer[0], W[0]) # anchor + i = j = 0 + tread_triangles = [] + for mv in path: + if mv == "O": + tri = (outer[i % m], W[j % L], outer[(i + 1) % m]) + i += 1 + else: + tri = (outer[i % m], W[j % L], W[(j + 1) % L]) + j += 1 + a, b, c = tri + g.add_edges_from([(a, b), (b, c), (a, c)]) + tread_triangles.append(tri) + if (i, j) != (m, L): + return None + return g, outer, tread_triangles + + +def cap_and_validate(g, outer): + """Cap the outer cycle with apex N; require a simple closed triangulation.""" + h = g.copy() + for t in range(len(outer)): + h.add_edges_from([("N", outer[t]), ("N", outer[(t + 1) % len(outer)])]) + if not nx.check_planarity(h)[0]: + return None + V, E = h.number_of_nodes(), h.number_of_edges() + if E != 3 * V - 6: # maximal planar == triangulation + return None + return h + + +def find_construction(m: int): + L = len(INNER_WALK) + for combo in itertools.combinations(range(m + L), L): + path = "".join("I" if t in combo else "O" for t in range(m + L)) + built = build_tread(m, path) + if built is None: + continue + g, outer, tris = built + h = cap_and_validate(g, outer) + if h is not None: + return h, outer, tris, path + return None + + +def run(): + for m in (4, 5, 6, 7): + found = find_construction(m) + if found: + break + if not found: + print("no valid bite-with-singletons triangulation found") + return 1 + h, outer, tris, path = found + M = medial_graph(h) + + annular = set() + for tri in tris: + a, b, c = tri + for e in (ekey(a, b), ekey(b, c), ekey(a, c)): + x, y = e + xo, yo = x in outer, y in outer + if (xo and not yo) or (yo and not xo): + annular.add(e) + + n_bite_nbrs = sum(1 for nb in M.neighbors(BITE_EDGE) if nb in annular) + up = [ekey(outer[t], outer[(t + 1) % len(outer)]) for t in range(len(outer))] + up = [e for e in up if e in M] + + print(f"m={len(outer)} path={path} |V(G)|={h.number_of_nodes()} " + f"|M(G)|={M.number_of_nodes()}") + print(f"bite edge {BITE_EDGE}: annular neighbours={n_bite_nbrs} (4 => bite)") + print(f"up apexes={len(up)} singleton down apexes={SINGLETON_DOWN}") + + colorings = proper_3_colorings(M, limit=50000) + bad_outer = bad_bitegap = 0 + for col in colorings: + if any(sum(1 for e in up if col[e] in p) % 2 for p in PAIRS): + bad_outer += 1 + if any(sum(1 for e in SINGLETON_DOWN if col[e] in p) % 2 for p in PAIRS): + bad_bitegap += 1 + + print(f"colourings tested={len(colorings)}") + print(f" outer face unbalanced: {bad_outer}") + print(f" bite-gap face (3 singletons) unbalanced: {bad_bitegap}") + print() + ok = (bad_outer == 0 and bad_bitegap == 0) + print("Remark 5.8 holds on this bite-with-singletons tread" + if ok else "Remark 5.8 FAILS on this bite-with-singletons tread") + return 0 if ok else 1 + + +if __name__ == "__main__": + run() diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/paper.aux b/papers/medial_tire_decompositions_of_plane_triangulations/paper.aux index 2a1025b..08b9e87 100644 --- a/papers/medial_tire_decompositions_of_plane_triangulations/paper.aux +++ b/papers/medial_tire_decompositions_of_plane_triangulations/paper.aux @@ -46,5 +46,5 @@ \newlabel{tocindent1}{17.77782pt} \newlabel{tocindent2}{29.38873pt} \newlabel{tocindent3}{0pt} -\@writefile{toc}{\contentsline {section}{\tocsection {}{}{References}}{10}{}\protected@file@percent } -\gdef \@abspage@last{10} +\@writefile{toc}{\contentsline {section}{\tocsection {}{}{References}}{11}{}\protected@file@percent } +\gdef \@abspage@last{11} diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/paper.fdb_latexmk b/papers/medial_tire_decompositions_of_plane_triangulations/paper.fdb_latexmk index 03043cf..09ca62f 100644 --- a/papers/medial_tire_decompositions_of_plane_triangulations/paper.fdb_latexmk +++ b/papers/medial_tire_decompositions_of_plane_triangulations/paper.fdb_latexmk @@ -1,5 +1,5 @@ # Fdb version 3 -["pdflatex"] 1781209574 "paper.tex" "paper.pdf" "paper" 1781209575 +["pdflatex"] 1781210675 "paper.tex" "paper.pdf" "paper" 1781210676 "/usr/local/texlive/2022/texmf-dist/fonts/map/fontname/texfonts.map" 1577235249 3524 cb3e574dea2d1052e39280babc910dc8 "" "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm" 1246382020 1004 54797486969f23fa377b128694d548df "" "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex8.tfm" 1246382020 988 bdf658c3bfc2d96d3c8b02cfc1c94c20 "" @@ -132,8 +132,8 @@ "/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map" 1647878959 4410336 7d30a02e9fa9a16d7d1f8d037ba69641 "" "/usr/local/texlive/2022/texmf-var/web2c/pdftex/pdflatex.fmt" 1665017617 2826443 7e98410c533054b636c6470db83a27bc "" "/usr/local/texlive/2022/texmf.cnf" 1647878952 577 209b46be99c9075fd74d4c0369380e8c "" - "paper.aux" 1781209575 4206 a817291c83280f23be785ea9b9789717 "pdflatex" - "paper.tex" 1781209541 40737 e5d86b8964b20788119dc708cc9cd8ef "" + "paper.aux" 1781210676 4206 870862ca1c6762f39fd7ed9def109a09 "pdflatex" + "paper.tex" 1781210650 40922 403b0b9df57192dbf02362b0b06705c3 "" (generated) "paper.aux" "paper.log" diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/paper.log b/papers/medial_tire_decompositions_of_plane_triangulations/paper.log index d5a7d5c..cecc7f4 100644 --- a/papers/medial_tire_decompositions_of_plane_triangulations/paper.log +++ b/papers/medial_tire_decompositions_of_plane_triangulations/paper.log @@ -1,4 +1,4 @@ -This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 11 JUN 2026 16:26 +This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 11 JUN 2026 16:44 entering extended mode restricted \write18 enabled. %&-line parsing enabled. @@ -506,7 +506,7 @@ LaTeX Warning: `h' float specifier changed to `ht'. LaTeX Warning: `h' float specifier changed to `ht'. -[4] [5] [6] [7] [8] [9] [10] (./paper.aux) ) +[4] [5] [6] [7] [8] [9] [10] [11] (./paper.aux) ) Here is how much of TeX's memory you used: 14419 strings out of 478268 283755 string characters out of 5846347 @@ -515,30 +515,30 @@ Here is how much of TeX's memory you used: 477048 words of font info for 58 fonts, out of 8000000 for 9000 1302 hyphenation exceptions out of 8191 84i,8n,89p,736b,838s stack positions out of 10000i,1000n,20000p,200000b,200000s - -Output written on paper.pdf (10 pages, 277087 bytes). + +Output written on paper.pdf (11 pages, 277538 bytes). PDF statistics: - 135 PDF objects out of 1000 (max. 8388607) - 84 compressed objects within 1 object stream + 138 PDF objects out of 1000 (max. 8388607) + 86 compressed objects within 1 object stream 0 named destinations out of 1000 (max. 500000) 13 words of extra memory for PDF output out of 10000 (max. 10000000) diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/paper.pdf b/papers/medial_tire_decompositions_of_plane_triangulations/paper.pdf index 772bc32..61e577f 100644 Binary files a/papers/medial_tire_decompositions_of_plane_triangulations/paper.pdf and b/papers/medial_tire_decompositions_of_plane_triangulations/paper.pdf differ diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/paper.tex b/papers/medial_tire_decompositions_of_plane_triangulations/paper.tex index b23f78b..1e50816 100644 --- a/papers/medial_tire_decompositions_of_plane_triangulations/paper.tex +++ b/papers/medial_tire_decompositions_of_plane_triangulations/paper.tex @@ -841,12 +841,14 @@ meets each level cycle in an even number of $P$-coloured incidences; for a given valid face these incidences are exactly its incident tooth apexes coloured $a$ or $b$, whence $\nu_P(F)$ is even. -This argument is verified computationally for bite-free pieces: across -all proper $3$-colourings of the capped triangulated annuli on annular -cycles of length $6,8,10,12$, every restriction to the tire piece is -Kempe-balanced. The case with bites, where the inner level cycle splits -into several child level cycles, is consistent with the same mechanism -but is not yet checked end to end. +This argument is verified computationally. For bite-free pieces---capped +triangulated annuli on annular cycles of length $6,8,10,12$---every proper +$3$-colouring of $M(G)$ restricts to a Kempe-balanced colouring. The same +holds for pieces carrying a bite, including the case where singleton down +teeth lie in the bite's inner-gap face: there the inner level cycle splits +into a child level cycle per gap, and conservation across each child cycle +supplies the parity (in the checked example the three singleton down apexes +of a bite gap are a rainbow in every restriction). \end{remark} More generally, let $T$ be a medial tire region with boundary