diff --git a/papers/coloring_nested_tire_graphs/experiments/draw_uniqueness_break.py b/papers/coloring_nested_tire_graphs/experiments/draw_uniqueness_break.py deleted file mode 100644 index eeb4547..0000000 --- a/papers/coloring_nested_tire_graphs/experiments/draw_uniqueness_break.py +++ /dev/null @@ -1,226 +0,0 @@ -"""Draw an empirical uniqueness-break case using TRUE planar -embedding coordinates (not spring layout). - -We need a LOW-SIDE face f of H_d such that f's interior contains -H_{d-1} edges from multiple H_{d-1} faces. - -The most reliable low-side face: the OUTER (unbounded) face of H_d. -For d >= 2, the outer face of H_d contains all of H_{d-1} (= depth- -(d-1) subgraph) plus pendants. - -Algorithm: - - For HM_0 cut #1 side 1 (a known interesting case), use the - primal planar embedding for vertex positions. - - Identify the outer face of H_2 (= largest face by area, or by - Sage's outer-face-of-embedding). - - Verify it contains H_1 edges from multiple H_1 faces in its - interior region. - - Draw. -""" -import os, sys -from collections import defaultdict - -import matplotlib.pyplot as plt -from sage.all import Graph - -HERE = os.path.dirname(os.path.abspath(__file__)) -sys.path.insert(0, HERE) -from cut_depth_label import ( - parse_planar_code, HM_FILE, - apply_procedure, compute_nice_layout, -) -from cut_tire_tree import compute_H_d_faces -from tree_structure_sweep import all_six_edge_cuts - - -def planar_layout_for_H(H): - """Return planar layout of H using Sage's planar embedding.""" - # Try planar layout - H2 = H.copy() - try: - H2.is_planar(set_embedding=True) - # Use Sage's planar layout - pos = H2.layout(layout='planar') - # pos values are (x, y) but Sage returns dict v -> (x,y) - return pos - except Exception as e: - print(f' Planar layout failed: {e}') - return None - - -def main(): - gs = parse_planar_code(HM_FILE) - G = gs[0] - G.is_planar(set_embedding=True) - base_pos = compute_nice_layout(G) - cuts = all_six_edge_cuts(G, max_cuts=5) - S, cut_edges = cuts[1] - S1 = frozenset(G.vertices()) - S - H, _, ed, _, _, _ = apply_procedure( - G, S1, cut_edges, base_pos, '1', - pendant_start_id=max(G.vertices()) + 501) - print(f'|V(H)|={H.order()}, |E(H)|={H.size()}') - print(f'Depths: {sorted(set(ed.values()))}') - - # Use Sage's planar layout for H - pos = planar_layout_for_H(H) - if pos is None: - pos = H.layout(layout='spring') - print(f'Got positions for {len(pos)} vertices') - - # Compute faces of H_1, H_2, H_3 - faces_1, _ = compute_H_d_faces(H, ed, 1) - faces_2, _ = compute_H_d_faces(H, ed, 2) - faces_3, _ = compute_H_d_faces(H, ed, 3) - print(f'H_1: {len(faces_1)} faces, lengths {[len(f) for f in faces_1]}') - print(f'H_2: {len(faces_2)} faces, lengths {[len(f) for f in faces_2]}') - print(f'H_3: {len(faces_3)} faces, lengths {[len(f) for f in faces_3]}') - - # Identify the LOW-side face of H_2. - # A low-side face contains depth-<2 edges (= pendants + H_1 edges). - # Equivalently: it's the face whose interior in the planar embedding - # contains the pendant vertices. - pendant_verts = {v for e, d in ed.items() if d == 0 for v in e} - # We pick the face whose boundary walk encloses the pendants. - # In Sage's planar embedding, this is the "outer" face often. - # Heuristic: the H_2 face NOT containing H_3 edges in its interior. - # Or: the largest face by vertex count. - # Most reliable: the face that, when removed from the plane, the - # pendants are in the remaining unbounded region. - # Use Sage's faces() — the first face is the outer face by default. - # For now, pick the face with the most vertices. - - target_face_idx = max(range(len(faces_2)), - key=lambda i: len(set(v for u, v in faces_2[i]) - | set(u for u, v in faces_2[i]))) - target_face = faces_2[target_face_idx] - target_verts = set() - for u, v in target_face: - target_verts.add(u); target_verts.add(v) - print(f'\nTarget face (H_2 face {target_face_idx}): {len(target_face)} ' - f'edges, {len(target_verts)} verts') - print(f' vertices: {sorted(target_verts)}') - - # Identify H_1 edges in the "interior" of the target face. - # Heuristic: H_1 edges whose endpoints are NOT on the target face - # boundary, OR endpoints on the boundary but the edge "points - # inward" by planar embedding. - # For simplicity, look at all H_1 edges with at least one endpoint - # on target_verts and the OTHER endpoint NOT on H_2's outer - # boundary. - h1_in_interior = [] - h1_face_of_edge = {} - for fi, walk in enumerate(faces_1): - for u, v in walk: - e = tuple(sorted((u, v))) - h1_face_of_edge.setdefault(e, []).append(fi) - - for e, d in ed.items(): - if d != 1: - continue - # An H_1 edge "in target face's interior" if at least one - # endpoint is in target_verts (= boundary of target face). - if e[0] in target_verts or e[1] in target_verts: - h1_in_interior.append(e) - - h1_in_int_by_face = defaultdict(list) - for e in h1_in_interior: - for fi in h1_face_of_edge.get(e, []): - h1_in_int_by_face[fi].append(e) - print(f'\nH_1 edges adjacent to target face boundary:') - for fi, eds in sorted(h1_in_int_by_face.items()): - print(f' H_1 face {fi}: {len(set(eds))} edges') - - # Draw - fig, ax = plt.subplots(figsize=(11, 10)) - # All H edges in light gray as background - for u, v in H.edges(labels=False): - e = tuple(sorted((u, v))) - x1, y1 = pos[u]; x2, y2 = pos[v] - de = ed.get(e, -1) - if de == 0: - color = '#888888'; lw = 0.8; alpha = 0.4 - elif de == 1: - color = '#4477CC'; lw = 2.0; alpha = 0.8 - elif de == 2: - color = '#DD7733'; lw = 3.5; alpha = 1.0 - elif de == 3: - color = '#999999'; lw = 0.8; alpha = 0.3 - else: - color = '#CCCCCC'; lw = 0.5; alpha = 0.2 - ax.plot([x1, x2], [y1, y2], color=color, linewidth=lw, - alpha=alpha, zorder=2) - - # Highlight target H_2 face boundary - for u, v in target_face: - x1, y1 = pos[u]; x2, y2 = pos[v] - ax.plot([x1, x2], [y1, y2], color='#DD7733', linewidth=5.5, - alpha=1.0, zorder=4, solid_capstyle='round') - - # H_1 edges colored by their H_1 face - h1_colors = {'face 0': '#22AA88', 'face 1': '#AA22AA', - 'face 2': '#225599'} - color_list = ['#22AA88', '#AA22AA', '#225599'] - for fi, eds in sorted(h1_in_int_by_face.items()): - col = color_list[fi % len(color_list)] - for e in set(eds): - u, v = e - x1, y1 = pos[u]; x2, y2 = pos[v] - ax.plot([x1, x2], [y1, y2], color=col, linewidth=4.0, - alpha=0.95, zorder=5, solid_capstyle='round') - - # Vertices - for v in H.vertices(): - x, y = pos[v] - in_target = v in target_verts - is_pendant = v in pendant_verts - if is_pendant: - ax.plot(x, y, 'o', color='#CC3333', markersize=6, zorder=6) - elif in_target: - ax.plot(x, y, 'o', color='#DD7733', markersize=7, zorder=6, - markeredgecolor='black', markeredgewidth=1) - ax.annotate(str(v), (x, y), textcoords='offset points', - xytext=(7, 7), fontsize=9, color='black', zorder=7) - else: - ax.plot(x, y, 'ko', markersize=4, zorder=6) - - from matplotlib.lines import Line2D - legend = [ - Line2D([0], [0], color='#DD7733', lw=5, - label=f'$H_2$ face {target_face_idx} boundary ' - f'({len(target_face)} edges)'), - Line2D([0], [0], color='#22AA88', lw=4, - label=f'$H_1$ edges in face 0'), - Line2D([0], [0], color='#AA22AA', lw=4, - label=f'$H_1$ edges in face 1'), - Line2D([0], [0], color='#225599', lw=4, - label=f'$H_1$ edges in face 2'), - Line2D([0], [0], color='#4477CC', lw=1.5, label='other $H_1$ edges'), - Line2D([0], [0], color='#888888', lw=0.8, label='pendants ($d=0$)'), - Line2D([0], [0], color='#999999', lw=0.8, label='$H_3+$ edges'), - Line2D([0], [0], marker='o', color='#CC3333', lw=0, - label='pendant vertex', markersize=8), - Line2D([0], [0], marker='o', color='#DD7733', lw=0, - label='$H_2$ face vertex', markersize=8, - markeredgecolor='black'), - ] - ax.legend(handles=legend, loc='upper left', fontsize=8, - framealpha=0.95) - - ax.set_aspect('equal') - ax.axis('off') - n_h1_faces = len(h1_in_int_by_face) - ax.set_title( - f'HM_0 cut #1 side 1, $d=2$: this $H_2$ face has $H_1$ edges ' - f'from {n_h1_faces} different $H_1$ faces adjacent\n' - f'(planar embedding from Sage; $H_2$ face shown in orange; ' - f'$H_1$ edges grouped by face)') - - out = os.path.join(os.path.dirname(HERE), 'notes', - 'uniqueness_break_example.pdf') - fig.savefig(out, bbox_inches='tight', dpi=120) - print(f'\nWrote {out}') - - -if __name__ == '__main__': - main() diff --git a/papers/coloring_nested_tire_graphs/experiments/find_uniqueness_break.py b/papers/coloring_nested_tire_graphs/experiments/find_uniqueness_break.py deleted file mode 100644 index 47d4039..0000000 --- a/papers/coloring_nested_tire_graphs/experiments/find_uniqueness_break.py +++ /dev/null @@ -1,171 +0,0 @@ -"""Find an empirical case where the low-side face of H_d spans -multiple faces of H_{d-1} (= the case high-side restriction is -needed for). - -For each (G, cut, side), iterate (d, face) and check: - - Is `face` the low-side face of H_d? - - Does face's interior contain H_{d-1} edges from multiple - H_{d-1} faces? - -Output: a clear description of the case + edges of H_d, H_{d-1}, -and their face structures, so we can draw it. -""" -import os, sys -from collections import defaultdict - -from sage.all import Graph, graphs - -HERE = os.path.dirname(os.path.abspath(__file__)) -sys.path.insert(0, HERE) -from cut_depth_label import ( - parse_planar_code, HM_FILE, - apply_procedure, compute_nice_layout, -) -from cut_tire_tree import build_tree, compute_H_d_faces -from tree_structure_sweep import all_six_edge_cuts - - -def classify_face(face, edge_depth, d): - """Returns 'low', 'high', or 'mixed' based on adjacency to non-Hd - edges by depth around the face vertices.""" - verts = set() - for u, v in face: - verts.add(u); verts.add(v) - seen_lower = False - seen_higher = False - # For each vertex in face, look at incident edges NOT on this face - face_e_set = {tuple(sorted(e)) for e in face} - # Approach: any incident edge with depth < d → "lower" hint; - # any with depth > d → "higher" hint. (The face's interior could - # contain stuff via vertex-adjacency.) - return None # not used, we'll classify differently - - -def find_face_of_edge(faces, e_norm): - """Find which face(s) of a graph have edge e_norm in their walk.""" - matches = [] - for fi, walk in enumerate(faces): - for u, v in walk: - if tuple(sorted((u, v))) == e_norm: - matches.append(fi) - break - return matches - - -def analyze_cut(G, cut_idx, cuts, base_pos): - S, cut_edges = cuts[cut_idx] - S0, S1 = S, frozenset(G.vertices()) - S - for side, S_side in [('0', S0), ('1', S1)]: - if len(S_side) < 6 or len(S_side) > G.order() - 6: - continue - try: - H, _, ed, _, _, _ = apply_procedure( - G, S_side, cut_edges, base_pos, side, - pendant_start_id=max(G.vertices()) + 1 + ( - 0 if side == '0' else 500)) - except Exception: - continue - if not ed: - continue - max_d = max(ed.values()) - for d in range(2, max_d + 1): - faces_d, H_d = compute_H_d_faces(H, ed, d) - faces_dm1, H_dm1 = compute_H_d_faces(H, ed, d - 1) - if not faces_d or not faces_dm1 or len(faces_dm1) < 2: - continue - # For each face of H_d, find which H_{d-1} edges are - # "inside" it (= H_{d-1} edges with both endpoints among - # face's vertex closure, intuitively). - # Simpler: a low-side face of H_d is one whose interior - # contains depth-= 2 and len(face) >= 6 and \ - len(unique_edges) >= 4: - print(f'\n=== FOUND: side {side}, d={d}, face {fi} of ' - f'H_d spans {len(faces_touched)} H_{{d-1}} ' - f'faces ===', flush=True) - print(f' Cut: |S0|={len(S0)}, |S1|={len(S1)}') - print(f' H_d face boundary edges ({len(face)}):', - flush=True) - for u, v in face[:8]: - print(f' ({u},{v})') - if len(face) > 8: - print(f' ... ({len(face)-8} more)') - print(f' H_{{d-1}} edges adjacent to face ' - f'(broken across H_{{d-1}} faces):') - for fjk in sorted(faces_touched): - print(f' H_{{d-1}} face {fjk}: ' - f'{[(min(e),max(e)) for e in edge_to_face[fjk][:5]]}') - return { - 'side': side, 'd': d, 'face_idx': fi, - 'face_walk': face, 'face_verts': face_verts, - 'H_d_edges': [(u,v) for u,v in face], - 'H_dm1_faces': {fjk: edge_to_face[fjk] - for fjk in faces_touched}, - 'all_H_d_faces': faces_d, - 'all_H_dm1_faces': faces_dm1, - 'edge_depth': ed, - } - return None - - -def main(): - gs = parse_planar_code(HM_FILE) - candidates = [('Dodecahedron', graphs.DodecahedralGraph())] - for i, g in enumerate(gs): - candidates.append((f'HM_{i}', g)) - for name, G in candidates: - G.is_planar(set_embedding=True) - base_pos = compute_nice_layout(G) - cuts = all_six_edge_cuts(G, max_cuts=30) - print(f'\n=== {name}: testing {len(cuts)} cuts ===', flush=True) - for ci in range(len(cuts)): - res = analyze_cut(G, ci, cuts, base_pos) - if res: - print(f'\nFOUND case in cut #{ci} of {name}', flush=True) - res['graph_name'] = name - res['cut_idx'] = ci - return res - print('No example found.') - return None - - -if __name__ == '__main__': - main() diff --git a/papers/coloring_nested_tire_graphs/notes/boundary_cut_tire.aux b/papers/coloring_nested_tire_graphs/notes/boundary_cut_tire.aux index 7cc3a1c..f712371 100644 --- a/papers/coloring_nested_tire_graphs/notes/boundary_cut_tire.aux +++ b/papers/coloring_nested_tire_graphs/notes/boundary_cut_tire.aux @@ -1,15 +1,14 @@ \relax \@writefile{toc}{\contentsline {paragraph}{Why low-side faces break uniqueness.}{1}{}\protected@file@percent } -\@writefile{toc}{\contentsline {paragraph}{An empirically observed case.}{2}{}\protected@file@percent } -\@writefile{toc}{\contentsline {paragraph}{The coverage gap.}{3}{}\protected@file@percent } -\@writefile{toc}{\contentsline {paragraph}{Resolution.}{3}{}\protected@file@percent } -\@writefile{toc}{\contentsline {paragraph}{Setup.}{3}{}\protected@file@percent } -\@writefile{toc}{\contentsline {paragraph}{The low-side face of $H_1$.}{3}{}\protected@file@percent } -\@writefile{toc}{\contentsline {paragraph}{Picture.}{3}{}\protected@file@percent } -\@writefile{toc}{\contentsline {paragraph}{What $T_\partial $ looks like in special cases.}{4}{}\protected@file@percent } -\@writefile{toc}{\contentsline {paragraph}{Role in the chain DP.}{5}{}\protected@file@percent } -\@writefile{toc}{\contentsline {paragraph}{What this closes.}{6}{}\protected@file@percent } -\@writefile{toc}{\contentsline {paragraph}{What it leaves open.}{6}{}\protected@file@percent } -\@writefile{toc}{\contentsline {paragraph}{Why the chain DP can still work.}{6}{}\protected@file@percent } -\@writefile{toc}{\contentsline {paragraph}{Logical status of the extended framework.}{6}{}\protected@file@percent } -\gdef \@abspage@last{6} +\@writefile{toc}{\contentsline {paragraph}{The coverage gap.}{2}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{Resolution.}{2}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{Setup.}{2}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{The low-side face of $H_1$.}{2}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{Picture.}{2}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{What $T_\partial $ looks like in special cases.}{3}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{Role in the chain DP.}{4}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{What this closes.}{5}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{What it leaves open.}{5}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{Why the chain DP can still work.}{5}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{Logical status of the extended framework.}{5}{}\protected@file@percent } +\gdef \@abspage@last{5} diff --git a/papers/coloring_nested_tire_graphs/notes/boundary_cut_tire.log b/papers/coloring_nested_tire_graphs/notes/boundary_cut_tire.log index 065bb24..3a3462d 100644 --- a/papers/coloring_nested_tire_graphs/notes/boundary_cut_tire.log +++ b/papers/coloring_nested_tire_graphs/notes/boundary_cut_tire.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) 26 MAY 2026 23:44 +This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 26 MAY 2026 23:36 entering extended mode restricted \write18 enabled. %&-line parsing enabled. @@ -583,49 +583,44 @@ LaTeX Font Info: Trying to load font information for U+msb on input line 20. File: umsb.fd 2013/01/14 v3.01 AMS symbols B ) [1 -{/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] - -File: uniqueness_break_example.pdf Graphic file (type pdf) - -Package pdftex.def Info: uniqueness_break_example.pdf used on input line 107. -(pdftex.def) Requested size: 446.26582pt x 470.60703pt. - [2 <./uniqueness_break_example.pdf>] [3] [4] [5] [6] (./boundary_cut_tire.aux) - ) +{/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] [2] [3] + [4] [5] +(./boundary_cut_tire.aux) ) Here is how much of TeX's memory you used: - 14747 strings out of 478268 - 301412 string characters out of 5846347 - 568832 words of memory out of 5000000 - 32701 multiletter control sequences out of 15000+600000 + 14740 strings out of 478268 + 301161 string characters out of 5846347 + 568755 words of memory out of 5000000 + 32695 multiletter control sequences out of 15000+600000 482413 words of font info for 79 fonts, out of 8000000 for 9000 1141 hyphenation exceptions out of 8191 84i,6n,89p,452b,713s stack positions out of 10000i,1000n,20000p,200000b,200000s -{/usr/local/texlive/2022/texmf-dist/fonts/enc/dvips/cm-super/cm-super-ts1.enc -} -< -/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb> -Output written on boundary_cut_tire.pdf (6 pages, 274500 bytes). +{/usr/local/texlive/2022/texmf-dist/fonts/enc/dvips/ +cm-super/cm-super-ts1.enc} + +Output written on boundary_cut_tire.pdf (5 pages, 251070 bytes). PDF statistics: - 193 PDF objects out of 1000 (max. 8388607) - 93 compressed objects within 1 object stream + 134 PDF objects out of 1000 (max. 8388607) + 82 compressed objects within 1 object stream 0 named destinations out of 1000 (max. 500000) - 18 words of extra memory for PDF output out of 10000 (max. 10000000) + 13 words of extra memory for PDF output out of 10000 (max. 10000000) diff --git a/papers/coloring_nested_tire_graphs/notes/boundary_cut_tire.pdf b/papers/coloring_nested_tire_graphs/notes/boundary_cut_tire.pdf index fd144ad..2c487e6 100644 Binary files a/papers/coloring_nested_tire_graphs/notes/boundary_cut_tire.pdf and b/papers/coloring_nested_tire_graphs/notes/boundary_cut_tire.pdf differ diff --git a/papers/coloring_nested_tire_graphs/notes/boundary_cut_tire.tex b/papers/coloring_nested_tire_graphs/notes/boundary_cut_tire.tex index 5b33880..28d6ee6 100644 --- a/papers/coloring_nested_tire_graphs/notes/boundary_cut_tire.tex +++ b/papers/coloring_nested_tire_graphs/notes/boundary_cut_tire.tex @@ -85,37 +85,6 @@ By contrast, face $A$ (high-side, inside the inner cycle) sits entirely inside face $X$ of $H_{d-1}$. Unique parent. This is why the forest proposition restricts to high-side faces. -\paragraph{An empirically observed case.} Holton--McKay graph -$\mathrm{HM}_0$, $6$-edge cut \#$1$, side $1$ (with $|S_1| = 28$). -At $d = 2$: $H_2$ has three faces of lengths $4, 4, 12$; $H_1$ also -has three faces of lengths $4, 4, 12$. The outer face of $H_2$ -(the length-$12$ one, $7$ vertices: $\{16,19,20,21,23,24,28\}$) is -low-side --- in its interior live the depth-$0$ pendants and all -of the depth-$1$ ($H_1$) edges. Those $H_1$ edges are spread -across all three faces of $H_1$: -\begin{itemize} -\item $H_1$ face $0$: contributes edge $(15,19)$. -\item $H_1$ face $1$: contributes edge $(17,21)$. -\item $H_1$ face $2$: contributes edges $(23, 27), (28, 33), (24, 29), - (28, 34)$. -\end{itemize} -So this single low-side face of $H_2$ has $H_1$ edges from -\emph{three} different $H_1$ faces adjacent to its boundary --- no -single $H_1$ face contains all of them, hence no unique parent. - -\begin{center} -\includegraphics[width=0.95\textwidth]{uniqueness_break_example.pdf} -\end{center} - -The orange ring is the boundary of the low-side $H_2$ face. The -three coloured edges (green, purple, blue) are $H_1$ edges -adjacent to the orange ring's vertices, coloured by which $H_1$ -face they belong to. The diagram is laid out using Sage's planar -embedding of $H$. If we tried to assign this $H_2$ face a single -``parent'' in $H_1$, none of the three $H_1$ faces would contain -it. $T_\partial$ exists precisely to handle this low-side -exception. - \paragraph{The coverage gap.} Empirically (\texttt{chain\_dp\_joint.py} on the dodecahedron, cut $\#0$, side $0$): when $|S_i|$ is small, $H_1$ on side $i$ can be a diff --git a/papers/coloring_nested_tire_graphs/notes/uniqueness_break_example.pdf b/papers/coloring_nested_tire_graphs/notes/uniqueness_break_example.pdf deleted file mode 100644 index c10d37d..0000000 Binary files a/papers/coloring_nested_tire_graphs/notes/uniqueness_break_example.pdf and /dev/null differ