Verify Remark 5.8 on genuine bite treads
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>
This commit is contained in:
+116
@@ -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()
|
||||
+132
@@ -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()
|
||||
@@ -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}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
</usr/local/texlive/2022/texmf-dist
|
||||
/fonts/type1/public/amsfonts/cm/cmbx10.pfb></usr/local/texlive/2022/texmf-dist/
|
||||
fonts/type1/public/amsfonts/cm/cmbx8.pfb></usr/local/texlive/2022/texmf-dist/fo
|
||||
nts/type1/public/amsfonts/cm/cmcsc10.pfb></usr/local/texlive/2022/texmf-dist/fo
|
||||
nts/type1/public/amsfonts/cm/cmmi10.pfb></usr/local/texlive/2022/texmf-dist/fon
|
||||
ts/type1/public/amsfonts/cm/cmmi5.pfb></usr/local/texlive/2022/texmf-dist/fonts
|
||||
/type1/public/amsfonts/cm/cmmi7.pfb></usr/local/texlive/2022/texmf-dist/fonts/t
|
||||
ype1/public/amsfonts/cm/cmmi8.pfb></usr/local/texlive/2022/texmf-dist/fonts/typ
|
||||
e1/public/amsfonts/cm/cmr10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1
|
||||
/public/amsfonts/cm/cmr7.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/pu
|
||||
blic/amsfonts/cm/cmr8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/publi
|
||||
c/amsfonts/cm/cmss10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public
|
||||
/amsfonts/cm/cmsy10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/
|
||||
amsfonts/cm/cmsy5.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/am
|
||||
sfonts/cm/cmsy6.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsf
|
||||
onts/cm/cmsy7.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfon
|
||||
ts/cm/cmti10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfont
|
||||
s/cm/cmti8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/
|
||||
cm/cmtt8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/sy
|
||||
mbols/msam10.pfb>
|
||||
Output written on paper.pdf (10 pages, 277087 bytes).
|
||||
</usr/local/texlive/2022/texmf
|
||||
-dist/fonts/type1/public/amsfonts/cm/cmbx10.pfb></usr/local/texlive/2022/texmf-
|
||||
dist/fonts/type1/public/amsfonts/cm/cmbx8.pfb></usr/local/texlive/2022/texmf-di
|
||||
st/fonts/type1/public/amsfonts/cm/cmcsc10.pfb></usr/local/texlive/2022/texmf-di
|
||||
st/fonts/type1/public/amsfonts/cm/cmmi10.pfb></usr/local/texlive/2022/texmf-dis
|
||||
t/fonts/type1/public/amsfonts/cm/cmmi5.pfb></usr/local/texlive/2022/texmf-dist/
|
||||
fonts/type1/public/amsfonts/cm/cmmi7.pfb></usr/local/texlive/2022/texmf-dist/fo
|
||||
nts/type1/public/amsfonts/cm/cmmi8.pfb></usr/local/texlive/2022/texmf-dist/font
|
||||
s/type1/public/amsfonts/cm/cmr10.pfb></usr/local/texlive/2022/texmf-dist/fonts/
|
||||
type1/public/amsfonts/cm/cmr7.pfb></usr/local/texlive/2022/texmf-dist/fonts/typ
|
||||
e1/public/amsfonts/cm/cmr8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/
|
||||
public/amsfonts/cm/cmss10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/p
|
||||
ublic/amsfonts/cm/cmsy10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/pu
|
||||
blic/amsfonts/cm/cmsy5.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/publ
|
||||
ic/amsfonts/cm/cmsy6.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public
|
||||
/amsfonts/cm/cmsy7.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/a
|
||||
msfonts/cm/cmti10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/am
|
||||
sfonts/cm/cmti8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsf
|
||||
onts/cm/cmtt8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfon
|
||||
ts/symbols/msam10.pfb>
|
||||
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)
|
||||
|
||||
|
||||
Binary file not shown.
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user