From 203b0053365fc51cf68474b9668c691399207136 Mon Sep 17 00:00:00 2001 From: didericis Date: Tue, 26 May 2026 22:49:20 -0400 Subject: [PATCH] coloring_nested_tire_graphs: chain half analysis + tree DP empirical test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NEW NOTE: chain_half_analysis.tex (4 pages). Formulates the chain half of the loose conjecture as a tree DP over the cut tire forest, identifies what's proven vs. open: PROVEN - Tree structure (high-side forest): from cut_tire_tree_structure.tex - S_3-equivariance of the DP: trivial Lemma in this note - Per-tire half for spoke-only cut tires (n ≥ 3): Prop 1.13 OPEN / GAPS DISCOVERED 1. Cut tires are NOT in general spoke-only. H_d can have degree-3 vertices (= branch points), making face boundaries non-simple cycles. Dodecahedron 6-edge cut yields H_1 with one face of length 20 over only 11 distinct vertices. Prop 1.13's count 2^n + 2(-1)^n applies only to spoke-only tires. 2. OUT-only projection loses S_3 orbit info. The per-tire half guarantees a full S_3 orbit on the JOINT (in + out) projection, but restricting to OUT spokes can collapse to |A|=3 (constant tuples). Empirically observed ~20% of the time on test cases. Correct DP must track joint projection (analog of tire_fiber_step2.tex's joint-support tracking). 3. Non-emptiness preservation through the DP is the genuine open piece (Conj. in this note + Strong per-tire extendibility). EMPIRICAL TESTS - chain_dp_test.py: simple cycle DP (assumes spoke-only). - chain_dp_general.py: handles branched faces via brute-force 3-edge-coloring enumeration (cut off at 12 edges/tire for tractability). - chain_dp_debug.py: diagnostic for inspecting H_d face structure. The general test reveals all three gaps above when run on Dodecahedron + HM #0. Cross-cut R_0 ∩ R_1 should be non-empty for both (they are 3-edge-colorable), but the heuristic parent-finding plus OUT-only projection produce false negatives. Status table at end of note summarizes what's needed to close. Co-Authored-By: Claude Opus 4.7 --- .../experiments/chain_dp_debug.py | 79 ++++ .../experiments/chain_dp_general.py | 358 +++++++++++++++++ .../experiments/chain_dp_test.py | 363 ++++++++++++++++++ .../notes/chain_half_analysis.aux | 18 + .../notes/chain_half_analysis.log | 317 +++++++++++++++ .../notes/chain_half_analysis.pdf | Bin 0 -> 216066 bytes .../notes/chain_half_analysis.tex | 279 ++++++++++++++ 7 files changed, 1414 insertions(+) create mode 100644 papers/coloring_nested_tire_graphs/experiments/chain_dp_debug.py create mode 100644 papers/coloring_nested_tire_graphs/experiments/chain_dp_general.py create mode 100644 papers/coloring_nested_tire_graphs/experiments/chain_dp_test.py create mode 100644 papers/coloring_nested_tire_graphs/notes/chain_half_analysis.aux create mode 100644 papers/coloring_nested_tire_graphs/notes/chain_half_analysis.log create mode 100644 papers/coloring_nested_tire_graphs/notes/chain_half_analysis.pdf create mode 100644 papers/coloring_nested_tire_graphs/notes/chain_half_analysis.tex diff --git a/papers/coloring_nested_tire_graphs/experiments/chain_dp_debug.py b/papers/coloring_nested_tire_graphs/experiments/chain_dp_debug.py new file mode 100644 index 0000000..6084331 --- /dev/null +++ b/papers/coloring_nested_tire_graphs/experiments/chain_dp_debug.py @@ -0,0 +1,79 @@ +"""Debug the chain DP: examine the structure of cut tires on a small +example to understand why R_i is empty. +""" +import os +import sys +import itertools +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, find_six_edge_cut, + apply_procedure, compute_nice_layout, +) +from cut_tire_tree import build_tree +from tree_structure_sweep import all_six_edge_cuts + + +def examine_cut(G, cut_idx, max_cuts=10): + cuts = all_six_edge_cuts(G, max_cuts=max_cuts) + if cut_idx >= len(cuts): + return + S, cut_edges = cuts[cut_idx] + base_pos = compute_nice_layout(G) + S0 = S + S1 = frozenset(G.vertices()) - S + print(f'=== Cut #{cut_idx}: |S0|={len(S0)}, |S1|={len(S1)} ===') + + for side, S_side in [('0', S0), ('1', S1)]: + print(f'\n--- Side {side} ---') + try: + H, pos, ed, _, _, _ = apply_procedure( + G, S_side, cut_edges, base_pos, side, + pendant_start_id=max(G.vertices()) + 1 + + (0 if side == '0' else 200)) + except Exception as e: + print(f' apply failed: {e}') + continue + + # Depth distribution + from collections import Counter + depth_count = Counter(ed.values()) + print(f' edge depths: {dict(depth_count)}') + print(f' |H| = {H.order()} vertices, {H.size()} edges') + print(f' max depth: {max(ed.values()) if ed else "N/A"}') + + if not ed: + continue + faces_by_depth, parent_of, _ = build_tree(H, ed) + for d in sorted(faces_by_depth.keys()): + faces = faces_by_depth[d] + print(f' H_{d}: {len(faces)} faces') + for f_idx, face in enumerate(faces[:3]): + verts = set() + for u, v in face: + verts.add(u) + verts.add(v) + # For each vertex, count incident H edges + bdry_v_data = [] + for v in verts: + incident = list(H.neighbors(v)) + incident_depths = [ed[tuple(sorted((v, nb)))] + for nb in incident] + bdry_v_data.append((v, incident_depths)) + # Show first few + print(f' face {f_idx}: |bdry|={len(face)}, ' + f'verts={len(verts)}, sample: {bdry_v_data[:3]}') + + +def main(): + G = graphs.DodecahedralGraph() + G.is_planar(set_embedding=True) + examine_cut(G, cut_idx=2, max_cuts=5) + + +if __name__ == '__main__': + main() diff --git a/papers/coloring_nested_tire_graphs/experiments/chain_dp_general.py b/papers/coloring_nested_tire_graphs/experiments/chain_dp_general.py new file mode 100644 index 0000000..3e7e7f6 --- /dev/null +++ b/papers/coloring_nested_tire_graphs/experiments/chain_dp_general.py @@ -0,0 +1,358 @@ +"""Generalized chain DP for cut tires (handles branched H_d faces). + +A cut tire T_d^{(f)} is treated as: + - Edge set E_f = edges in the boundary walk of face f of H_d. + - Vertex set V_f = vertices incident to E_f. + - For each v in V_f with deg_{H_d}(v) = 2: one labeled pendant + (in or out depending on the depth of the non-H_d edge at v). + - For each v in V_f with deg_{H_d}(v) = 3: no pendant. + +Proper 3-edge-coloring of T = (E_f ∪ pendants) such that all edges +incident at every v in V_f have distinct colors. (The "underlying" +graph treats E_f and pendants as edges in a planar multigraph; a +branch vertex has 3 incident E_f edges all distinct.) + +Out-spokes projection: tuple of colors on labeled-OUT pendants +(depth d-1 edges). + +Chain DP bottom-up: + - At each tire, enumerate proper 3-edge-colorings. + - Restrict to those compatible with at least one combination + of out-spoke colorings from each child. + - Project onto own out spokes. + +Verify: + (a) At each tire: |A(T)| > 0, contains full S_3 orbit. + (b) R_0 ∩ R_1 non-empty at the cut. +""" +import os +import sys +import itertools +from collections import defaultdict, Counter + +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 +from tree_structure_sweep import all_six_edge_cuts + + +def cut_tire_structure(H, edge_depth, d, face): + """Extract structure of cut tire T_d^{(face)}. + + Returns dict: + 'edges_indexed': list of (e_id, edge_tuple) for cycle edges. + Order: by appearance in face walk (so duplicates + can happen for branch points, but we use each + edge once). + 'pendants_in': dict v -> (pendant_id, depth=d+1 edge) + 'pendants_out': dict v -> (pendant_id, depth=d-1 edge) + 'edges_at_v': dict v -> list of edge_ids incident to v + (each appearance of v in walk = 1 cycle edge) + 'cycle_edges': list of (cycle_edge_id, edge_tuple) + """ + # First normalize: count each unique cycle edge once + cycle_e_set = set() + cycle_edges = [] + for u, v in face: + e = tuple(sorted((u, v))) + if e not in cycle_e_set: + cycle_e_set.add(e) + cycle_edges.append(e) + # Vertices on this face boundary + verts_set = set() + for u, v in cycle_edges: + verts_set.add(u) + verts_set.add(v) + # Edges incident to each vertex (cycle edges only) + edges_at_v = defaultdict(list) + for ce_id, (a, b) in enumerate(cycle_edges): + edges_at_v[a].append(ce_id) + edges_at_v[b].append(ce_id) + # Pendants: at each degree-2 vertex of H, identify the third edge + pendants_in = {} + pendants_out = {} + pendant_counter = [len(cycle_edges)] # next available edge id + for v in verts_set: + H_deg = sum(1 for nb in H.neighbors(v) + if tuple(sorted((v, nb))) in cycle_e_set) + # Wait — that's just degree restricted to face cycle edges. + # But pendant attaches to the H-edge of different depth. + # Look at ALL edges of H incident to v: + for nb in H.neighbors(v): + e_full = tuple(sorted((v, nb))) + d_e = edge_depth.get(e_full) + if d_e is None: + continue + if d_e == d: + continue # skip cycle edges + elif d_e == d + 1: + pid = pendant_counter[0] + pendant_counter[0] += 1 + pendants_in[v] = (pid, e_full) + edges_at_v[v].append(pid) + elif d_e == d - 1: + pid = pendant_counter[0] + pendant_counter[0] += 1 + pendants_out[v] = (pid, e_full) + edges_at_v[v].append(pid) + return { + 'cycle_edges': cycle_edges, + 'pendants_in': pendants_in, + 'pendants_out': pendants_out, + 'edges_at_v': dict(edges_at_v), + 'n_edges': pendant_counter[0], + } + + +def proper_3_colorings_general(struct): + """Enumerate all proper 3-edge-colorings of cut tire. + Edge ids 0..n_cycle_edges-1 are cycle edges; n_cycle...n_edges-1 are + pendants. Constraint: at each vertex v, the colors of edges in + edges_at_v[v] are all distinct.""" + n_e = struct['n_edges'] + edges_at_v = struct['edges_at_v'] + # Edge-coloring constraint reduces to: per vertex, colors distinct. + # Since vertex can have ≤ 3 incident edges in cubic (since each + # vertex in original G' is cubic), and our cut tire is subgraph, + # each v has at most 3 incident edges in the cut tire. + # We need all colors at each v distinct. + out = [] + # Naive enumeration: 3^n_e then filter. n_e is small (~10-50) + # for our test cases, so doable. + if n_e > 12: + return None # too big + for assign in itertools.product([0, 1, 2], repeat=n_e): + ok = True + for v, eids in edges_at_v.items(): + colors = [assign[eid] for eid in eids] + if len(set(colors)) != len(colors): + ok = False + break + if ok: + out.append(assign) + return out + + +def s3_orbit(tup): + """S_3 orbit of color tuple under permutations of {0,1,2}.""" + orbit = set() + for perm in itertools.permutations([0, 1, 2]): + orbit.add(tuple(perm[c] for c in tup)) + return orbit + + +def has_full_s3_orbit(s): + """Does set s of tuples contain a 6-element S_3 orbit?""" + if not s: + return False + for tup in s: + orb = s3_orbit(tup) + if len(orb) == 6 and orb <= s: + return True + return False + + +def chain_dp_general(faces_by_depth, parent_of, H, edge_depth): + """Run chain DP, returns dict node -> A(T) (set of out-spoke + color tuples).""" + # Build structures for each tire + structs = {} + for d, faces in faces_by_depth.items(): + for f_idx, face in enumerate(faces): + structs[(d, f_idx)] = cut_tire_structure(H, edge_depth, d, face) + + # Build children list + children = defaultdict(list) + for node, p in parent_of.items(): + if p is not None and p != ('cut', None): + children[p].append(node) + + # Order by depth (process leaves first) + max_d = max(d for (d, _) in structs) + A = {} + for d in range(max_d, 0, -1): + for (dd, f_idx), struct in list(structs.items()): + if dd != d: + continue + node = (d, f_idx) + cs = proper_3_colorings_general(struct) + if cs is None: + A[node] = None # too big + continue + # Pendant-IN edge ids: those whose pendant_id is in pendants_in + in_pids = {v: pid for v, (pid, _) in struct['pendants_in'].items()} + out_pids = {v: pid for v, (pid, _) in struct['pendants_out'].items()} + in_v_sorted = sorted(in_pids.keys()) + out_v_sorted = sorted(out_pids.keys()) + + # Find correspondence: each pendant-IN edge of this tire + # = full edge in G'_i. We need to find which child cycle + # edge it corresponds to. + # The pendant-IN at v has full edge e (in struct). + # Among children, find child c whose cycle_edges contains e. + child_links = [] # (child_node, parent_v -> child_edge_id) + for ch in children.get(node, []): + if ch not in A: + continue + if A[ch] is None: + child_links.append((ch, None)) # too big, skip + continue + ch_struct = structs[ch] + ch_out_v = sorted(ch_struct['pendants_out'].keys()) + ch_out_full = {v: ch_struct['pendants_out'][v][1] + for v in ch_out_v} + # Match: parent's pendant-IN edge = child's pendant-OUT edge? + # No wait — parent's pendant-IN is a depth-(d+1) edge. + # Child T_{d+1}^{(f')} has cycle edges of depth d+1. + # So parent's pendant-IN edge = a cycle edge of child. + p_v_to_child_cycle_eid = {} + for v_p, (pid_p, e_full_p) in struct['pendants_in'].items(): + # Find edge in child's cycle_edges with same e_full + for ce_id, e_c in enumerate(ch_struct['cycle_edges']): + if e_c == e_full_p: + p_v_to_child_cycle_eid[v_p] = ce_id + break + child_links.append((ch, p_v_to_child_cycle_eid)) + + # For each coloring, check compatibility with each child + achievable = set() + for assign in cs: + # Determine parent's pendant-IN colors + p_in_colors = {v: assign[in_pids[v]] for v in in_pids} + # For each child, check if there's a child-coloring with + # the same colors at the corresponding cycle edges. + # We use child's A in terms of OUT-SPOKE colors, but we + # need to constrain CYCLE colors. So we need to recompute + # per-child compatibility from child's allowed colorings. + # ALTERNATE: instead of using A(ch) (out-spoke restriction), + # track full child colorings. This blows up but is correct. + # Simpler: track child's set of valid (cycle, out) colorings. + # For now we use the WEAKER check: out-spoke compatibility + # via "any child coloring at all", since A(ch) doesn't + # carry cycle-edge info. + # Since the chain compatibility is on PARENT'S IN spokes = + # CHILD'S CYCLE EDGES (not out spokes), we actually need + # the child's projection on cycle edges, not out spokes. + # For this test, let's use child's full coloring set. + ok = True + for ch, link in child_links: + if link is None: + # child too big — skip compatibility check + continue + ch_full_colorings = proper_3_colorings_general(structs[ch]) + if ch_full_colorings is None: + continue + # Find a ch_coloring with matching cycle-edge colors + found = False + for ch_assign in ch_full_colorings: + match = True + for v_p, ce_id_c in link.items(): + if ch_assign[ce_id_c] != p_in_colors[v_p]: + match = False + break + if match: + found = True + break + if not found: + ok = False + break + if ok: + # Project to out spokes + if out_v_sorted: + tup = tuple(assign[out_pids[v]] for v in out_v_sorted) + else: + tup = () + achievable.add(tup) + A[node] = achievable + return A, structs + + +def test_on_graph(G, name, max_cuts=3): + cuts = all_six_edge_cuts(G, max_cuts=max_cuts) + print(f'\n=== {name}: V={G.order()}, {len(cuts)} cuts tested ===', + flush=True) + base_pos = compute_nice_layout(G) + n_tests, n_pertire_orbit_ok, n_root_ok, n_cross_ok = 0, 0, 0, 0 + per_tire_failures = [] + cross_failures = [] + for cut_idx, (S, cut_edges) in enumerate(cuts): + S0, S1 = S, frozenset(G.vertices()) - S + if len(S0) < 4 or len(S1) < 4: + continue + Rs = {} + for side, S_side in [('0', S0), ('1', S1)]: + try: + H, pos, ed, _, _, _ = apply_procedure( + G, S_side, cut_edges, base_pos, side, + pendant_start_id=max(G.vertices()) + 1 + + (0 if side == '0' else 200)) + except Exception: + continue + if not ed: + continue + faces_by_depth, parent_of, _ = build_tree(H, ed) + try: + A, structs = chain_dp_general( + faces_by_depth, parent_of, H, ed) + except Exception as e: + print(f' cut #{cut_idx}/{side}: DP failed: {e}', flush=True) + continue + # Per-tire check + for node, a in A.items(): + if a is None: + continue + n_tests += 1 + if a and has_full_s3_orbit(a): + n_pertire_orbit_ok += 1 + else: + per_tire_failures.append({ + 'cut': cut_idx, 'side': side, 'node': node, + 'n_edges': structs[node]['n_edges'], + '|A|': len(a), + 'has_orbit': has_full_s3_orbit(a) if a else False, + }) + # Roots + R_i = set() + for node in A: + if node[0] == 1 and A[node]: + R_i |= A[node] + if R_i and has_full_s3_orbit(R_i): + n_root_ok += 1 + Rs[side] = R_i + if '0' in Rs and '1' in Rs: + if Rs['0'] & Rs['1']: + n_cross_ok += 1 + else: + cross_failures.append({ + 'cut': cut_idx, + '|R0|': len(Rs['0']), + '|R1|': len(Rs['1']), + }) + print(f' Per-tire A(T) full-orbit count: {n_pertire_orbit_ok}/{n_tests}', + flush=True) + if per_tire_failures: + print(f' First per-tire failures:') + for f in per_tire_failures[:5]: + print(f' {f}') + print(f' R_i has full orbit (root sides): {n_root_ok}', flush=True) + print(f' Cross-cut R_0 ∩ R_1 != empty: {n_cross_ok}', flush=True) + if cross_failures: + print(f' Cross failures: {cross_failures[:3]}') + + +def main(): + G = graphs.DodecahedralGraph() + G.is_planar(set_embedding=True) + test_on_graph(G, 'Dodecahedron', max_cuts=3) + gs = parse_planar_code(HM_FILE) + test_on_graph(gs[0], 'HM_0', max_cuts=3) + + +if __name__ == '__main__': + main() diff --git a/papers/coloring_nested_tire_graphs/experiments/chain_dp_test.py b/papers/coloring_nested_tire_graphs/experiments/chain_dp_test.py new file mode 100644 index 0000000..aa7296f --- /dev/null +++ b/papers/coloring_nested_tire_graphs/experiments/chain_dp_test.py @@ -0,0 +1,363 @@ +"""Empirical test of the chain DP for the loose conjecture. + +For each (G, cut, side), build the cut tire forest. For each cut tire +T = D(T) (cycle + pendants), enumerate proper 3-edge-colorings of T. +Tree DP bottom-up: at each node, compute the set of out-spoke +colorings compatible with at least one valid child combination. + +Verify at roots: R_i != empty, contains a full S_3 orbit. +Verify across cut: R_0 ∩ R_1 != empty, contains a full S_3 orbit. + +Per the chain_half_analysis.tex note, this directly tests: + - Conjecture (non-emptiness preservation): A(T_p) non-empty if + children's A's are non-empty. + - Bottom-line: R_0 ∩ R_1 non-empty. +""" +import os +import sys +import itertools +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, find_six_edge_cut, + apply_procedure, compute_nice_layout, +) +from cut_tire_tree import build_tree + + +def order_cycle(cycle_edges): + """Order edges into a cyclic walk. Returns (verts_in_order, + edges_in_order) or (None, None) if not a simple cycle. + edges_in_order[i] connects verts_in_order[i] and verts_in_order[i+1].""" + n = len(cycle_edges) + if n < 2: + return None, None + e_set = {tuple(sorted(e)) for e in cycle_edges} + adj = defaultdict(list) + for u, v in e_set: + adj[u].append(v) + adj[v].append(u) + # Every vertex must have exactly 2 neighbors for a simple cycle + if any(len(adj[v]) != 2 for v in adj): + return None, None + start = next(iter(adj)) + walk = [start] + prev = None + cur = start + while True: + nxt = [w for w in adj[cur] if w != prev] + if not nxt: + return None, None + nxt = nxt[0] + if nxt == start and len(walk) == n: + break + walk.append(nxt) + prev = cur + cur = nxt + if len(walk) > n: + return None, None + if len(walk) != n: + return None, None + edges_in_order = [tuple(sorted((walk[i], walk[(i + 1) % n]))) + for i in range(n)] + return walk, edges_in_order + + +def get_tire_data(H, edge_depth, d, face): + """For cut tire T_d^{(face)}, return (verts_in_order, cycle_edges, + in_spokes, out_spokes) or None if face is not a simple cycle. + + in_spokes: dict {v: spoke_edge} for depth d+1 spokes + out_spokes: dict {v: spoke_edge} for depth d-1 spokes + """ + cycle_e = [tuple(sorted(e)) for e in face] + walk, edges_ord = order_cycle(cycle_e) + if walk is None: + return None + in_sp, out_sp = {}, {} + cycle_e_set = set(edges_ord) + for v in walk: + for nb in H.neighbors(v): + e = tuple(sorted((v, nb))) + if e in cycle_e_set: + continue + d_e = edge_depth.get(e) + if d_e is None: + continue + if d_e == d + 1: + in_sp[v] = e + elif d_e == d - 1: + out_sp[v] = e + return walk, edges_ord, in_sp, out_sp + + +def proper_3_colorings(verts, cycle_edges, in_sp, out_sp): + """Enumerate proper 3-edge-colorings of D(T): cycle + spokes. + Returns list of dicts {edge: color}. + + For each cycle coloring c[i] (i = 0..n-1) with c[i] != c[i+1]: + At vertex v_i, the two cycle edges adjacent are c[i-1] and c[i]. + Spoke at v_i (if present) gets the third color. + """ + n = len(cycle_edges) + out = [] + for assign in itertools.product([0, 1, 2], repeat=n): + # Proper cycle + bad = False + for i in range(n): + if assign[i] == assign[(i + 1) % n]: + bad = True + break + if bad: + continue + col = {cycle_edges[i]: assign[i] for i in range(n)} + # Determine spoke colors + for i, v in enumerate(verts): + c_left = assign[(i - 1) % n] + c_right = assign[i] + third = ({0, 1, 2} - {c_left, c_right}) + if len(third) != 1: + # Degenerate (n=2 case) + bad = True + break + third_c = third.pop() + if v in in_sp: + col[in_sp[v]] = third_c + if v in out_sp: + col[out_sp[v]] = third_c + if not bad: + out.append(col) + return out + + +def s3_orbit(tup): + """Generate S_3 orbit of a color tuple under permutations of {0,1,2}.""" + orbit = set() + for perm in itertools.permutations([0, 1, 2]): + orbit.add(tuple(perm[c] for c in tup)) + return orbit + + +def has_full_s3_orbit(s): + """Does set s (of tuples) contain a 6-element S_3 orbit?""" + for tup in s: + if len(s3_orbit(tup)) == 6 and s3_orbit(tup) <= s: + return True + return False + + +def chain_dp(faces_by_depth, parent_of, H, edge_depth, side_label): + """Run the chain DP on the cut tire forest. + + For each tire T_d^{(f)}, compute: + - tire_data: (verts, cycle_e, in_sp, out_sp) + - colorings: all proper 3-edge-colorings + - A(T): set of (out-spoke-color-tuples), restricted by + compatibility with all children. + + Returns: {node: A(T)}, where each A(T) is a set of tuples. + Also returns dict of issues found. + """ + tire_data = {} + for d, faces in faces_by_depth.items(): + for f_idx, face in enumerate(faces): + td = get_tire_data(H, edge_depth, d, face) + if td is not None: + tire_data[(d, f_idx)] = td + + # Build children list + children = defaultdict(list) + for node, p in parent_of.items(): + if p is not None and p != ('cut', None): + children[p].append(node) + + # Process bottom-up: order nodes by depth descending + nodes_by_depth = defaultdict(list) + for node in tire_data: + nodes_by_depth[node[0]].append(node) + max_d = max(nodes_by_depth) if nodes_by_depth else 0 + + A = {} # node -> set of out-spoke-color tuples + fully_S3 = {} # node -> bool: A(T) contains full S_3 orbit + issues = [] + + for d in range(max_d, 0, -1): + for node in nodes_by_depth[d]: + verts, cycle_e, in_sp, out_sp = tire_data[node] + if not out_sp and d > 1: + # Internal/leaf without out spokes — degenerate + A[node] = set() + continue + cs = proper_3_colorings(verts, cycle_e, in_sp, out_sp) + # Order out-spoke positions (by vertex) + out_sp_verts = sorted(out_sp.keys()) + in_sp_verts = sorted(in_sp.keys()) + + # For each child, build map: parent-in-spoke-vertex (= parent + # boundary vertex with in spoke) -> child-out-spoke-vertex. + # Equivalent: the in-spoke edge of parent = an out-spoke edge + # of one of its children. The shared endpoint is the parent's + # boundary vertex. + child_outsp_maps = [] + for ch in children.get(node, []): + if ch not in tire_data: + continue + ch_verts, ch_cycle, ch_in, ch_out = tire_data[ch] + # Match: parent's in-spoke edge == child's out-spoke edge + p_in_to_ch_out_v = {} + for v_p, e_p in in_sp.items(): + # Find the vertex w of child with out-spoke e_p + for v_c, e_c in ch_out.items(): + if e_p == e_c: + p_in_to_ch_out_v[v_p] = (ch, v_c) + break + child_outsp_maps.append((ch, p_in_to_ch_out_v)) + + # For each coloring, check compatibility with each child's A + achievable_out = set() + for col in cs: + # Extract parent's in-spoke colors + p_in_colors_by_v = {v: col[in_sp[v]] for v in in_sp} + # For each child, verify the corresponding out-spoke + # color (= our in-spoke color) is in A(child) + ok = True + for ch, mapping in child_outsp_maps: + if ch not in A: + ok = False # child has no achievable (shouldn't happen) + break + ch_verts, ch_cycle, ch_in, ch_out = tire_data[ch] + ch_out_verts_ordered = sorted(ch_out.keys()) + # Build the child's out-spoke tuple as we'd need + required_ch_out = {} + for v_p, (ch_id, v_c) in mapping.items(): + if ch_id != ch: + continue + required_ch_out[v_c] = p_in_colors_by_v[v_p] + # If some out-spoke vertex of child isn't covered by + # any parent in spoke, the value is FREE in A. + # So we check: exists tup in A(ch) with tup[i] = + # required_ch_out[v] for each i where v is constrained. + found_any = False + for tup in A[ch]: + match = True + for i, v in enumerate(ch_out_verts_ordered): + if v in required_ch_out and tup[i] != required_ch_out[v]: + match = False + break + if match: + found_any = True + break + if not found_any: + ok = False + break + if ok: + # Extract parent's out-spoke colors as a tuple + if out_sp_verts: + tup = tuple(col[out_sp[v]] for v in out_sp_verts) + achievable_out.add(tup) + else: + # No out spokes (root with empty out projection) — + # represent as singleton empty tuple + achievable_out.add(()) + A[node] = achievable_out + fully_S3[node] = has_full_s3_orbit(achievable_out) + if not achievable_out: + issues.append({ + 'type': 'empty_after_chain', + 'node': node, + 'side': side_label, + 'n_children': len(children.get(node, [])), + }) + + return A, fully_S3, issues, tire_data + + +def run_test(G, name, max_cuts=5): + """Run chain DP test on G across several 6-edge cuts.""" + from tree_structure_sweep import all_six_edge_cuts + cuts = all_six_edge_cuts(G, max_cuts=max_cuts) + print(f'\n=== {name}: V={G.order()}, E={G.size()}, ' + f'{len(cuts)} cuts tested ===', flush=True) + base_pos = compute_nice_layout(G) + n_cuts = 0 + n_empty = 0 + n_no_orbit = 0 + n_crossok = 0 + total_issues = [] + for cut_idx, (S, cut_edges) in enumerate(cuts): + S0 = S + S1 = frozenset(G.vertices()) - S + if len(S0) < 4 or len(S1) < 4: + continue + A_per_side = {} + for side, S_side in [('0', S0), ('1', S1)]: + try: + H, pos, ed, _, _, _ = apply_procedure( + G, S_side, cut_edges, base_pos, side, + pendant_start_id=max(G.vertices()) + 1 + + (0 if side == '0' else 200)) + except Exception as e: + print(f' cut #{cut_idx} side {side}: apply_procedure ' + f'failed: {e}', flush=True) + continue + faces_by_depth, parent_of, _ = build_tree(H, ed) + A, fully_S3, issues, tire_data = chain_dp( + faces_by_depth, parent_of, H, ed, side) + total_issues.extend(issues) + # Look at root tires (depth-1) + root_A = [] + for node in A: + if node[0] == 1: + root_A.append((node, A[node])) + # Combine root A's into R_i: union over roots + R_i = set() + for node, a in root_A: + R_i |= a + A_per_side[side] = R_i + if not R_i: + n_empty += 1 + print(f' cut #{cut_idx} side {side}: R_i empty!', flush=True) + elif not any(len(s3_orbit(t)) == 6 and s3_orbit(t) <= R_i + for t in R_i): + n_no_orbit += 1 + print(f' cut #{cut_idx} side {side}: R_i lacks full S_3 ' + f'orbit (|R_i|={len(R_i)})', flush=True) + if '0' in A_per_side and '1' in A_per_side: + n_cuts += 1 + # Cross-cut check: R_0 and R_1 are on the same 6 cut edges, + # but indexed by which side's roots. Need bijection. + # For now, compare structurally: do they share orbits? + R0, R1 = A_per_side['0'], A_per_side['1'] + common = R0 & R1 + if common: + n_crossok += 1 + else: + print(f' cut #{cut_idx}: R_0 ∩ R_1 = empty ' + f'(|R_0|={len(R0)}, |R_1|={len(R1)})', flush=True) + print(f' cuts tested: {n_cuts}, R_i empty: {n_empty}, ' + f'R_i no full orbit: {n_no_orbit}, R_0 ∩ R_1 non-empty: ' + f'{n_crossok}/{n_cuts}', flush=True) + return total_issues + + +def main(): + # Small test: Dodecahedron + G = graphs.DodecahedralGraph() + G.is_planar(set_embedding=True) + issues_dodec = run_test(G, 'Dodecahedron', max_cuts=5) + + # HM #0 + gs = parse_planar_code(HM_FILE) + issues_hm0 = run_test(gs[0], 'HM_0', max_cuts=5) + + print('\n=== Summary of issues ===', flush=True) + print(f'Dodecahedron: {len(issues_dodec)} issues') + print(f'HM_0: {len(issues_hm0)} issues') + + +if __name__ == '__main__': + main() diff --git a/papers/coloring_nested_tire_graphs/notes/chain_half_analysis.aux b/papers/coloring_nested_tire_graphs/notes/chain_half_analysis.aux new file mode 100644 index 0000000..7b0c427 --- /dev/null +++ b/papers/coloring_nested_tire_graphs/notes/chain_half_analysis.aux @@ -0,0 +1,18 @@ +\relax +\@writefile{toc}{\contentsline {paragraph}{Per-tire half.}{1}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{Chain half.}{1}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{(1) Leaves.}{1}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{(2) Internal nodes.}{1}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{(3) Roots and the cut.}{2}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{(4) Cross-cut.}{2}{}\protected@file@percent } +\newlabel{conj:non-empty-prop}{{}{2}} +\@writefile{toc}{\contentsline {paragraph}{Why it isn't trivial.}{2}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{Why it's plausible.}{2}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{What would close the proof.}{2}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{What goes wrong.}{3}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{Consequence for Prop 1.13.}{3}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{Two ways forward.}{3}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{What this changes in the chain DP.}{4}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{Second issue: out-spoke projection loses S$_3$ orbit.}{4}{}\protected@file@percent } +\@writefile{toc}{\contentsline {paragraph}{Third issue: heuristic parent-finding.}{4}{}\protected@file@percent } +\gdef \@abspage@last{4} diff --git a/papers/coloring_nested_tire_graphs/notes/chain_half_analysis.log b/papers/coloring_nested_tire_graphs/notes/chain_half_analysis.log new file mode 100644 index 0000000..12ddebc --- /dev/null +++ b/papers/coloring_nested_tire_graphs/notes/chain_half_analysis.log @@ -0,0 +1,317 @@ +This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 26 MAY 2026 22:49 +entering extended mode + restricted \write18 enabled. + %&-line parsing enabled. +**chain_half_analysis.tex +(./chain_half_analysis.tex +LaTeX2e <2021-11-15> patch level 1 +L3 programming layer <2022-02-24> +(/usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +Document Class: article 2021/10/04 v1.4n Standard LaTeX document class +(/usr/local/texlive/2022/texmf-dist/tex/latex/base/size11.clo +File: size11.clo 2021/10/04 v1.4n Standard LaTeX file (size option) +) +\c@part=\count185 +\c@section=\count186 +\c@subsection=\count187 +\c@subsubsection=\count188 +\c@paragraph=\count189 +\c@subparagraph=\count190 +\c@figure=\count191 +\c@table=\count192 +\abovecaptionskip=\skip47 +\belowcaptionskip=\skip48 +\bibindent=\dimen138 +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +Package: amsmath 2021/10/15 v2.17l AMS math features +\@mathmargin=\skip49 + +For additional information on amsmath, use the `?' option. +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +Package: amstext 2021/08/26 v2.01 AMS text + +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +File: amsgen.sty 1999/11/30 v2.0 generic functions +\@emptytoks=\toks16 +\ex@=\dimen139 +)) +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +Package: amsbsy 1999/11/29 v1.2d Bold Symbols +\pmbraise@=\dimen140 +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +Package: amsopn 2021/08/26 v2.02 operator names +) +\inf@bad=\count193 +LaTeX Info: Redefining \frac on input line 234. +\uproot@=\count194 +\leftroot@=\count195 +LaTeX Info: Redefining \overline on input line 399. +\classnum@=\count196 +\DOTSCASE@=\count197 +LaTeX Info: Redefining \ldots on input line 496. +LaTeX Info: Redefining \dots on input line 499. +LaTeX Info: Redefining \cdots on input line 620. +\Mathstrutbox@=\box50 +\strutbox@=\box51 +\big@size=\dimen141 +LaTeX Font Info: Redeclaring font encoding OML on input line 743. +LaTeX Font Info: Redeclaring font encoding OMS on input line 744. +\macc@depth=\count198 +\c@MaxMatrixCols=\count199 +\dotsspace@=\muskip16 +\c@parentequation=\count266 +\dspbrk@lvl=\count267 +\tag@help=\toks17 +\row@=\count268 +\column@=\count269 +\maxfields@=\count270 +\andhelp@=\toks18 +\eqnshift@=\dimen142 +\alignsep@=\dimen143 +\tagshift@=\dimen144 +\tagwidth@=\dimen145 +\totwidth@=\dimen146 +\lineht@=\dimen147 +\@envbody=\toks19 +\multlinegap=\skip50 +\multlinetaggap=\skip51 +\mathdisplay@stack=\toks20 +LaTeX Info: Redefining \[ on input line 2938. +LaTeX Info: Redefining \] on input line 2939. +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amssymb.sty +Package: amssymb 2013/01/14 v3.01 AMS font symbols + +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support +\symAMSa=\mathgroup4 +\symAMSb=\mathgroup5 +LaTeX Font Info: Redeclaring math symbol \hbar on input line 98. +LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold' +(Font) U/euf/m/n --> U/euf/b/n on input line 106. +)) +(/usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +Package: amsthm 2020/05/29 v2.20.6 +\thm@style=\toks21 +\thm@bodyfont=\toks22 +\thm@headfont=\toks23 +\thm@notefont=\toks24 +\thm@headpunct=\toks25 +\thm@preskip=\skip52 +\thm@postskip=\skip53 +\thm@headsep=\skip54 +\dth@everypar=\toks26 +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +Package: graphicx 2021/09/16 v1.2d Enhanced LaTeX Graphics (DPC,SPQR) + +(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +Package: keyval 2014/10/28 v1.15 key=value parser (DPC) +\KV@toks@=\toks27 +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +Package: graphics 2021/03/04 v1.4d Standard LaTeX Graphics (DPC,SPQR) + +(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +Package: trig 2021/08/11 v1.11 sin cos tan (DPC) +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +File: graphics.cfg 2016/06/04 v1.11 sample graphics configuration +) +Package graphics Info: Driver file: pdftex.def on input line 107. + +(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-def/pdftex.def +File: pdftex.def 2020/10/05 v1.2a Graphics/color driver for pdftex +)) +\Gin@req@height=\dimen148 +\Gin@req@width=\dimen149 +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/geometry/geometry.sty +Package: geometry 2020/01/02 v5.9 Page Geometry + +(/usr/local/texlive/2022/texmf-dist/tex/generic/iftex/ifvtex.sty +Package: ifvtex 2019/10/25 v1.7 ifvtex legacy package. Use iftex instead. + +(/usr/local/texlive/2022/texmf-dist/tex/generic/iftex/iftex.sty +Package: iftex 2022/02/03 v1.0f TeX engine tests +)) +\Gm@cnth=\count271 +\Gm@cntv=\count272 +\c@Gm@tempcnt=\count273 +\Gm@bindingoffset=\dimen150 +\Gm@wd@mp=\dimen151 +\Gm@odd@mp=\dimen152 +\Gm@even@mp=\dimen153 +\Gm@layoutwidth=\dimen154 +\Gm@layoutheight=\dimen155 +\Gm@layouthoffset=\dimen156 +\Gm@layoutvoffset=\dimen157 +\Gm@dimlist=\toks28 +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/booktabs/booktabs.sty +Package: booktabs 2020/01/12 v1.61803398 Publication quality tables +\heavyrulewidth=\dimen158 +\lightrulewidth=\dimen159 +\cmidrulewidth=\dimen160 +\belowrulesep=\dimen161 +\belowbottomsep=\dimen162 +\aboverulesep=\dimen163 +\abovetopsep=\dimen164 +\cmidrulesep=\dimen165 +\cmidrulekern=\dimen166 +\defaultaddspace=\dimen167 +\@cmidla=\count274 +\@cmidlb=\count275 +\@aboverulesep=\dimen168 +\@belowrulesep=\dimen169 +\@thisruleclass=\count276 +\@lastruleclass=\count277 +\@thisrulewidth=\dimen170 +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +File: l3backend-pdftex.def 2022-02-07 L3 backend support: PDF output (pdfTeX) +\l__color_backend_stack_int=\count278 +\l__pdf_internal_box=\box52 +) +(./chain_half_analysis.aux) +\openout1 = `chain_half_analysis.aux'. + +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 17. +LaTeX Font Info: ... okay on input line 17. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 17. +LaTeX Font Info: ... okay on input line 17. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 17. +LaTeX Font Info: ... okay on input line 17. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 17. +LaTeX Font Info: ... okay on input line 17. +LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 17. +LaTeX Font Info: ... okay on input line 17. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 17. +LaTeX Font Info: ... okay on input line 17. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 17. +LaTeX Font Info: ... okay on input line 17. + +(/usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +\scratchcounter=\count279 +\scratchdimen=\dimen171 +\scratchbox=\box53 +\nofMPsegments=\count280 +\nofMParguments=\count281 +\everyMPshowfont=\toks29 +\MPscratchCnt=\count282 +\MPscratchDim=\dimen172 +\MPnumerator=\count283 +\makeMPintoPDFobject=\count284 +\everyMPtoPDFconversion=\toks30 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +Package: epstopdf-base 2020-01-24 v2.11 Base part for package epstopdf +Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 4 +85. + +(/usr/local/texlive/2022/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Liv +e +)) +*geometry* driver: auto-detecting +*geometry* detected driver: pdftex +*geometry* verbose mode - [ preamble ] result: +* driver: pdftex +* paper: +* layout: +* layoutoffset:(h,v)=(0.0pt,0.0pt) +* modes: +* h-part:(L,W,R)=(72.26999pt, 469.75502pt, 72.26999pt) +* v-part:(T,H,B)=(72.26999pt, 650.43001pt, 72.26999pt) +* \paperwidth=614.295pt +* \paperheight=794.96999pt +* \textwidth=469.75502pt +* \textheight=650.43001pt +* \oddsidemargin=0.0pt +* \evensidemargin=0.0pt +* \topmargin=-37.0pt +* \headheight=12.0pt +* \headsep=25.0pt +* \topskip=11.0pt +* \footskip=30.0pt +* \marginparwidth=59.0pt +* \marginparsep=10.0pt +* \columnsep=10.0pt +* \skip\footins=10.0pt plus 4.0pt minus 2.0pt +* \hoffset=0.0pt +* \voffset=0.0pt +* \mag=1000 +* \@twocolumnfalse +* \@twosidefalse +* \@mparswitchfalse +* \@reversemarginfalse +* (1in=72.27pt=25.4mm, 1cm=28.453pt) + +LaTeX Font Info: Trying to load font information for U+msa on input line 18. + +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd +File: umsa.fd 2013/01/14 v3.01 AMS symbols A +) +LaTeX Font Info: Trying to load font information for U+msb on input line 18. + + +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd +File: umsb.fd 2013/01/14 v3.01 AMS symbols B +) +Overfull \hbox (31.8519pt too wide) in paragraph at lines 32--37 + \OT1/cmr/bx/n/10.95 Chain half.[] \OT1/cmr/m/n/10.95 Com-pos-ing per-tire pro- +jec-tions through the cut-tire for-est (\OT1/cmtt/m/n/10.95 cut[]tire[]tree[]st +ructure.tex\OT1/cmr/m/n/10.95 , + [] + + +Package amsmath Warning: Foreign command \atop; +(amsmath) \frac or \genfrac should be used instead +(amsmath) on input line 58. + +[1 + +{/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] +Overfull \hbox (41.57079pt too wide) in paragraph at lines 134--142 + \OT1/cmr/bx/n/10.95 Why it's plau-si-ble.[] \OT1/cmr/m/n/10.95 Em-pir-i-cal da +ta from the partial- tire-dual chain pi-geon-hole (\OT1/cmtt/m/n/10.95 tire[]fi +ber[]step2.tex\OT1/cmr/m/n/10.95 ): + [] + +[2] [3] [4] (./chain_half_analysis.aux) ) +Here is how much of TeX's memory you used: + 3256 strings out of 478268 + 48448 string characters out of 5846347 + 348617 words of memory out of 5000000 + 21443 multiletter control sequences out of 15000+600000 + 479693 words of font info for 69 fonts, out of 8000000 for 9000 + 1141 hyphenation exceptions out of 8191 + 55i,8n,62p,236b,241s stack positions out of 10000i,1000n,20000p,200000b,200000s +{/usr/local/texlive/2022/texmf-dist/fo +nts/enc/dvips/cm-super/cm-super-ts1.enc} +Output written on chain_half_analysis.pdf (4 pages, 216066 bytes). +PDF statistics: + 103 PDF objects out of 1000 (max. 8388607) + 62 compressed objects within 1 object stream + 0 named destinations out of 1000 (max. 500000) + 1 words of extra memory for PDF output out of 10000 (max. 10000000) + diff --git a/papers/coloring_nested_tire_graphs/notes/chain_half_analysis.pdf b/papers/coloring_nested_tire_graphs/notes/chain_half_analysis.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f037a3b5f2fa042786a0aab47c90340ae25b9d69 GIT binary patch literal 216066 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

Abk_+uLHIt`+5mAyIw@n%tt>D< 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