diff --git a/papers/coloring_nested_tire_graphs/experiments/tire_fiber_chunked.py b/papers/coloring_nested_tire_graphs/experiments/tire_fiber_chunked.py new file mode 100644 index 0000000..b12d920 --- /dev/null +++ b/papers/coloring_nested_tire_graphs/experiments/tire_fiber_chunked.py @@ -0,0 +1,153 @@ +"""Streaming/chunked variant of tire_fiber_chords_fast.py for n > 27. + +The in-memory version materializes an (N, n) int8 array with N = 3·2^(n-1), +which at n = 30 is ~30 GB. This chunked version processes paths in +chunks of ~2^20 rows, never holding the full array in memory. + +For projection support: we only need the set of σ-projected rows, +which is typically much smaller than 3^k. We accumulate into a Python +set. + +For γ up to ~18 with m ≥ γ this brings n up to ~36, with one tire +taking minutes (versus impossible). +""" +from __future__ import annotations + +import numpy as np + +from tire_fiber_chords import ( + d_positions_for, + u_positions_for, + compute_faces_from_chords, +) +from tire_fiber_chords_fast import OTHER_NP, induced_sigma_vec + + +def proper_cycle_colorings_chunked(n: int, chunk_size: int = 1 << 20): + """Yield (rows, n) int8 chunks of proper edge 3-colorings of C_n. + + Each chunk is a numpy array; chunks together cover every proper + edge 3-coloring exactly once. After filtering for the cycle closure + constraint, a chunk may be smaller than chunk_size.""" + if n < 2: + return + + block_size = 1 << (n - 1) + eff_chunk = min(chunk_size, block_size) + + for c0 in (1, 2, 3): + for start in range(0, block_size, eff_chunk): + end = min(start + eff_chunk, block_size) + n_rows = end - start + arr = np.empty((n_rows, n), dtype=np.int8) + arr[:, 0] = c0 + + row_idx = np.arange(start, end, dtype=np.int64) + for i in range(1, n): + bits = ((row_idx >> (i - 1)) & 1).astype(np.int8) + prev = arr[:, i - 1] + arr[:, i] = OTHER_NP[prev, bits] + + mask = arr[:, -1] != arr[:, 0] + if mask.any(): + yield arr[mask] + + +def projection_support_streaming( + m: int, + k: int, + chords, + positions: list[int], + chunk_size: int = 1 << 20, +) -> set: + """Compute the projected support {σ[positions] : σ realisable} + without materializing the full σ array. + + Returns: set of tuples in {1,2,3}^len(positions). + """ + n = m + k + d_positions = d_positions_for(m, k) + o_faces = compute_faces_from_chords(k, chords) + d_positions_by_face = [ + [d_positions[a] for a in face_edges] + for face_edges in o_faces + ] + + support: set[tuple[int, ...]] = set() + for c_chunk in proper_cycle_colorings_chunked(n, chunk_size): + sigma = induced_sigma_vec(c_chunk) + + mask = np.ones(sigma.shape[0], dtype=bool) + for face in d_positions_by_face: + if len(face) <= 1: + continue + for i in range(len(face)): + for j in range(i + 1, len(face)): + mask &= (sigma[:, face[i]] != sigma[:, face[j]]) + + if not mask.any(): + continue + sigma_ok = sigma[mask] + projected = sigma_ok[:, positions] + support.update(map(tuple, projected.tolist())) + + return support + + +def spoke_only_projection_support_streaming( + n: int, positions: list[int], chunk_size: int = 1 << 20 +) -> set: + """Steiner-rich baseline (no chord constraints).""" + support: set[tuple[int, ...]] = set() + for c_chunk in proper_cycle_colorings_chunked(n, chunk_size): + sigma = induced_sigma_vec(c_chunk) + projected = sigma[:, positions] + support.update(map(tuple, projected.tolist())) + return support + + +if __name__ == '__main__': + import time + from tire_fiber_chords_fast import fiber_distribution_fast, projection_support_fast + + print("Validation: chunked vs in-memory") + print("-" * 60) + cases = [ + (4, 4, [(0, 2)]), + (6, 6, [(0, 3)]), + (6, 9, [(0, 2), (3, 5), (6, 8)]), + (9, 9, [(0, 3), (4, 7)]), + (12, 12, [(0, 3), (4, 7), (8, 11)]), + ] + for m, k, ch in cases: + n = m + k + d_pos = d_positions_for(m, k) + + t0 = time.time() + fibers_mem, _, _ = fiber_distribution_fast(m, k, ch) + S_mem = projection_support_fast(fibers_mem, d_pos) + dt_mem = time.time() - t0 + + t0 = time.time() + S_chunked = projection_support_streaming(m, k, ch, d_pos) + dt_chunked = time.time() - t0 + + ok = S_mem == S_chunked + status = "OK" if ok else "MISMATCH" + print(f"(m={m}, k={k}, n={n}): mem {dt_mem:.2f}s, chunked {dt_chunked:.2f}s, " + f"|S|={len(S_chunked)}, {status}") + + print() + print("Stress test (n > 24):") + print("-" * 60) + cases_big = [ + (12, 13, [(0, 3), (4, 7), (8, 11), (12, 1)]), # n=25 + (15, 15, [(0, 3), (4, 7), (8, 11), (12, 14), (12, 0)]), # n=30 + ] + for m, k, ch in cases_big: + n = m + k + d_pos = d_positions_for(m, k) + t0 = time.time() + S = projection_support_streaming(m, k, ch, d_pos) + dt = time.time() - t0 + print(f"(m={m}, k={k}, n={n}): {dt:.1f}s, |S|={len(S)}") diff --git a/papers/coloring_nested_tire_graphs/experiments/tire_fiber_threshold_search.py b/papers/coloring_nested_tire_graphs/experiments/tire_fiber_threshold_search.py new file mode 100644 index 0000000..09dce77 --- /dev/null +++ b/papers/coloring_nested_tire_graphs/experiments/tire_fiber_threshold_search.py @@ -0,0 +1,236 @@ +"""Counterexample search at γ ∈ {13, 14, 15}, threshold m ≥ γ. + +The earlier search (tire_fiber_counterexample_search.py) capped n ≤ 27 +to fit fiber arrays in memory, which forced m_1 < γ at γ ≥ 13 — so it +never tested the threshold-satisfying regime above γ = 12. This +script uses tire_fiber_chunked.projection_support_streaming to push +n up to 30+ (at γ = 15, m = 15, the bottleneck is ~7 min per tire). + +Configs include all-3-faces chord matchings (where they exist — +γ ∈ {15} via the multi-chord 'ring' (0,3),(3,6),...,(γ-3,γ),(0,γ-3)) +plus mixed-face chord matchings (γ ∈ {13, 14}). + +Shares the same counterexample_search.log with the earlier sweep; +deduplication via pair-keys lets this be resumed mid-flight. +""" +from __future__ import annotations + +import json +import time +from pathlib import Path + +from tire_fiber_chords import ( + compute_faces_from_chords, + d_positions_for, + u_positions_for, +) +from tire_fiber_chunked import projection_support_streaming + + +HERE = Path(__file__).resolve().parent +LOG_PATH = HERE / "counterexample_search.log" + + +def log_event(event: dict) -> None: + event.setdefault('wall_time', time.time()) + with open(LOG_PATH, 'a') as f: + f.write(json.dumps(event, default=str) + "\n") + f.flush() + + +def has_all_three_faces(k: int, chords) -> bool: + if not chords: + return k == 3 + faces = compute_faces_from_chords(k, chords) + return all(len(f) == 3 for f in faces) + + +def make_key(gamma, m_1, ch1, model1, k_2, ch2, model2) -> str: + ch1_str = json.dumps(sorted([sorted(c) for c in ch1])) if ch1 else "[]" + ch2_str = json.dumps(sorted([sorted(c) for c in ch2])) if ch2 else "[]" + return f"gamma={gamma}|t1=({m_1},{ch1_str},{model1})|t2=({k_2},{ch2_str},{model2})" + + +def read_existing_keys() -> set[str]: + keys = set() + if not LOG_PATH.exists(): + return keys + with open(LOG_PATH) as f: + for line in f: + try: + ev = json.loads(line) + except json.JSONDecodeError: + continue + if ev.get('type') == 'pair' and 'key' in ev: + keys.add(ev['key']) + return keys + + +# T1 chord configurations at the higher γ. +T1_CONFIGS = { + 13: [ + # Mixed-face (no all-3 possible at γ=13, since 13 not divisible by 3) + [(0, 3), (4, 7), (8, 11), (12, 1)], + [(0, 3), (3, 6), (6, 9), (9, 12), (12, 0)], + ], + 14: [ + # Mixed-face + [(0, 3), (3, 6), (6, 9), (9, 12), (12, 0)], + [(0, 3), (4, 7), (8, 11), (12, 0)], + ], + 15: [ + # all-3 "ring" config: 5 chords, all faces size 3 + [(0, 3), (3, 6), (6, 9), (9, 12), (0, 12)], + # mixed-face alternative + [(0, 3), (4, 7), (8, 11), (12, 14), (12, 0)], + ], +} + +# T2 chord configurations (only k_2 ≥ γ to satisfy threshold). +T2_CONFIGS = { + 13: [ + [(0, 3), (4, 7), (8, 11), (12, 1)], + ], + 14: [ + [(0, 3), (3, 6), (6, 9), (9, 12), (12, 0)], + ], + 15: [ + [(0, 3), (3, 6), (6, 9), (9, 12), (0, 12)], + [(0, 3), (4, 7), (8, 11), (12, 14), (12, 0)], + ], +} + + +# In-memory caches so that a fixed (m_1, gamma, ch1) doesn't get +# re-streamed across multiple T2 variants. +_pi_d_cache: dict = {} +_pi_u_cache: dict = {} + + +def _cache_key(args): + return tuple(args[:-1]) + (tuple(tuple(sorted(c)) for c in args[-1]),) + + +def pi_D_cached(m_1: int, gamma: int, ch1: list) -> set: + key = (m_1, gamma, tuple(tuple(sorted(c)) for c in ch1)) + if key not in _pi_d_cache: + d_pos = d_positions_for(m_1, gamma) + _pi_d_cache[key] = projection_support_streaming(m_1, gamma, ch1, d_pos) + return _pi_d_cache[key] + + +def pi_U_cached(gamma: int, k_2: int, ch2: list) -> set: + key = (gamma, k_2, tuple(tuple(sorted(c)) for c in ch2)) + if key not in _pi_u_cache: + u_pos = u_positions_for(gamma, k_2) + _pi_u_cache[key] = projection_support_streaming(gamma, k_2, ch2, u_pos) + return _pi_u_cache[key] + + +def test_pair(gamma: int, m_1: int, ch1, k_2: int, ch2) -> dict: + t0 = time.time() + S1 = pi_D_cached(m_1, gamma, ch1) + S2 = pi_U_cached(gamma, k_2, ch2) + fwd = S1 & S2 + S2_rev = {s[::-1] for s in S2} + rev = S1 & S2_rev + dt = time.time() - t0 + return { + 'type': 'pair', + 'key': make_key(gamma, m_1, ch1, 'SP', k_2, ch2, 'SP'), + 'gamma': gamma, + 't1': {'m_1': m_1, 'chords': ch1, 'model': 'SP'}, + 't2': {'k_2': k_2, 'chords': ch2, 'model': 'SP'}, + 's1_size': len(S1), + 's2_size': len(S2), + 'fwd_size': len(fwd), + 'rev_size': len(rev), + 'compatible': bool(fwd or rev), + 'time_seconds': round(dt, 3), + 't1_all_three': has_all_three_faces(gamma, ch1), + 't2_all_three': has_all_three_faces(k_2, ch2), + } + + +def main(): + already = read_existing_keys() + log_event({'type': 'session_start', 'session_kind': 'threshold-search-streaming'}) + print(f"[start] {len(already)} pairs already tested", flush=True) + + n_tested = 0 + n_ce = 0 + n_ce_all3 = 0 + t_start = time.time() + + for gamma in [13, 14, 15]: + cs1_list = T1_CONFIGS.get(gamma, []) + if not cs1_list: + continue + log_event({'type': 'k_start', 'gamma': gamma, + 'session_kind': 'threshold-search-streaming', + 'n_t1_configs': len(cs1_list)}) + + # We only test the threshold m_1 = γ here (n_1 = 2γ). Larger m_1 + # would saturate even more easily. + m_1 = gamma + + for ch1 in cs1_list: + for k_2 in sorted(T2_CONFIGS.keys()): + if k_2 < gamma: + continue # threshold: k_2 ≥ γ + for ch2 in T2_CONFIGS[k_2]: + key = make_key(gamma, m_1, ch1, 'SP', k_2, ch2, 'SP') + if key in already: + continue + + t0 = time.time() + print(f"[{(time.time()-t_start)/60:.1f}m] testing γ={gamma} " + f"T1=(m={m_1}, ch={ch1}), T2=(k={k_2}, ch={ch2})", + flush=True) + try: + result = test_pair(gamma, m_1, ch1, k_2, ch2) + except Exception as e: + log_event({'type': 'exception', 'key': key, + 'error': type(e).__name__ + ": " + str(e)}) + print(f" exception: {e}", flush=True) + continue + log_event(result) + already.add(key) + n_tested += 1 + if not result['compatible']: + n_ce += 1 + if result.get('t1_all_three') and result.get('t2_all_three'): + n_ce_all3 += 1 + log_event({'type': 'COUNTEREXAMPLE', + 'strict_latin': True, + 'threshold': True, + 'pair': result}) + print(f" *** THRESHOLD STRICT-LATIN COUNTEREXAMPLE ***", + flush=True) + else: + log_event({'type': 'COUNTEREXAMPLE', + 'pair': result}) + print(f" *** counterexample (not strict-Latin) ***", + flush=True) + print(f" -> |S1|={result['s1_size']}, |S2|={result['s2_size']}, " + f"fwd={result['fwd_size']}, rev={result['rev_size']}, " + f"compat={result['compatible']} ({result['time_seconds']:.1f}s)", + flush=True) + # Free the γ-specific caches before moving to the next γ + _pi_d_cache.clear() + _pi_u_cache.clear() + + elapsed_h = (time.time() - t_start) / 3600 + log_event({'type': 'session_end', + 'session_kind': 'threshold-search-streaming', + 'n_tested': n_tested, + 'n_ce': n_ce, + 'n_ce_strict_latin_threshold': n_ce_all3, + 'elapsed_hours': elapsed_h}) + print(f"\n[done] tested {n_tested}, CE {n_ce}, " + f"strict-Latin threshold CE {n_ce_all3}, " + f"elapsed {elapsed_h:.2f} hours", flush=True) + + +if __name__ == '__main__': + main() diff --git a/papers/coloring_nested_tire_graphs/notes/worst_case_proof_sketch.aux b/papers/coloring_nested_tire_graphs/notes/worst_case_proof_sketch.aux new file mode 100644 index 0000000..95d9805 --- /dev/null +++ b/papers/coloring_nested_tire_graphs/notes/worst_case_proof_sketch.aux @@ -0,0 +1,5 @@ +\relax +\newlabel{prop:konig-overlap}{{}{1}} +\newlabel{prop:lower-bound-tight}{{}{1}} +\newlabel{conj:t2-induces-partition}{{}{2}} +\gdef \@abspage@last{3} diff --git a/papers/coloring_nested_tire_graphs/notes/worst_case_proof_sketch.log b/papers/coloring_nested_tire_graphs/notes/worst_case_proof_sketch.log new file mode 100644 index 0000000..d906b95 --- /dev/null +++ b/papers/coloring_nested_tire_graphs/notes/worst_case_proof_sketch.log @@ -0,0 +1,280 @@ +This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 26 MAY 2026 11:12 +entering extended mode + restricted \write18 enabled. + %&-line parsing enabled. +**worst_case_proof_sketch.tex +(./worst_case_proof_sketch.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/l3backend/l3backend-pdftex.def +File: l3backend-pdftex.def 2022-02-07 L3 backend support: PDF output (pdfTeX) +\l__color_backend_stack_int=\count274 +\l__pdf_internal_box=\box52 +) +(./worst_case_proof_sketch.aux) +\openout1 = `worst_case_proof_sketch.aux'. + +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 16. +LaTeX Font Info: ... okay on input line 16. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 16. +LaTeX Font Info: ... okay on input line 16. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 16. +LaTeX Font Info: ... okay on input line 16. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 16. +LaTeX Font Info: ... okay on input line 16. +LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 16. +LaTeX Font Info: ... okay on input line 16. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 16. +LaTeX Font Info: ... okay on input line 16. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 16. +LaTeX Font Info: ... okay on input line 16. + +(/usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +\scratchcounter=\count275 +\scratchdimen=\dimen158 +\scratchbox=\box53 +\nofMPsegments=\count276 +\nofMParguments=\count277 +\everyMPshowfont=\toks29 +\MPscratchCnt=\count278 +\MPscratchDim=\dimen159 +\MPnumerator=\count279 +\makeMPintoPDFobject=\count280 +\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 17. + +(/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 17. + + +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd +File: umsb.fd 2013/01/14 v3.01 AMS symbols B +) [1 + +{/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] [2] [3] + +(./worst_case_proof_sketch.aux) ) +Here is how much of TeX's memory you used: + 3188 strings out of 478268 + 47308 string characters out of 5846347 + 350893 words of memory out of 5000000 + 21380 multiletter control sequences out of 15000+600000 + 480772 words of font info for 73 fonts, out of 8000000 for 9000 + 1141 hyphenation exceptions out of 8191 + 55i,8n,62p,240b,218s stack positions out of 10000i,1000n,20000p,200000b,200000s +{/usr/local/texlive/2022/texmf-dist/fonts/enc/ +dvips/cm-super/cm-super-ts1.enc} +Output written on worst_case_proof_sketch.pdf (3 pages, 202583 bytes). +PDF statistics: + 100 PDF objects out of 1000 (max. 8388607) + 60 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/worst_case_proof_sketch.pdf b/papers/coloring_nested_tire_graphs/notes/worst_case_proof_sketch.pdf new file mode 100644 index 0000000..0d1ad8a Binary files /dev/null and b/papers/coloring_nested_tire_graphs/notes/worst_case_proof_sketch.pdf differ diff --git a/papers/coloring_nested_tire_graphs/notes/worst_case_proof_sketch.tex b/papers/coloring_nested_tire_graphs/notes/worst_case_proof_sketch.tex new file mode 100644 index 0000000..ff47938 --- /dev/null +++ b/papers/coloring_nested_tire_graphs/notes/worst_case_proof_sketch.tex @@ -0,0 +1,210 @@ +\documentclass[11pt]{article} +\usepackage{amsmath,amssymb,amsthm} +\usepackage{graphicx} +\usepackage{geometry} +\geometry{margin=1in} + +\title{A proof attempt at the worst-case overlap} +\author{} +\date{} + +\newtheorem*{thm}{Theorem} +\newtheorem*{prop}{Proposition} +\newtheorem*{lem}{Lemma} +\newtheorem*{conj}{Conjecture} + +\begin{document} +\maketitle + +\section*{Setup} + +Let $\gamma$ be a cycle of length $k$ (divisible by $3$ for the +``all-3'' case), and let $T_1, T_2$ be two adjacent SP tires sharing +$\gamma$ with the threshold condition +$|B_{\mathrm{out}}^{(1)}| \geq k$ and $|B_{\mathrm{in}}^{(2)}| \geq k$. +Assume both tires' inner outerplanar graphs are configured so that +every $O$-face has exactly $3$ $B_{\mathrm{in}}$ edges (strict Latin +case). + +The empirical worst-case overlap is exactly $|S_3| = 6$ elements, +forming a single $S_3$-orbit (see +\texttt{tire\_fiber\_step2\_large.tex}, Obs. on the $S_3$-orbit +structure). This note sketches a proof. + +\section*{What I can prove cleanly: both sides give $\gamma$-face partitions} + +\begin{prop}[König $\Rightarrow$ overlap $\geq 6$] +\label{prop:konig-overlap} +Suppose both $T_1$ and $T_2$ induce \emph{direct} all-$3$ face +partitions $\mathcal{F}_1, \mathcal{F}_2$ of $E(\gamma)$. Then +\[ + |\mathcal{L}(\gamma, \mathcal{F}_1) \cap \mathcal{L}(\gamma, + \mathcal{F}_2)| \;\geq\; 6. +\] +\end{prop} + +\begin{proof}[Proof sketch] +Define a bipartite graph $G$: +\begin{itemize} + \item Left vertices: $\mathcal{F}_1$-faces (there are $k/3$ of + them). + \item Right vertices: $\mathcal{F}_2$-faces (also $k/3$). + \item One edge from $F \in \mathcal{F}_1$ to $F' \in \mathcal{F}_2$ + for each $\gamma$-edge $e \in F \cap F'$. +\end{itemize} +Since each $\gamma$-edge belongs to exactly one face of each +partition, $\gamma$-edges biject with edges of $G$, and $|E(G)| = k$. +Each face has $3$ $\gamma$-edges, so every vertex of $G$ has degree +exactly $3$. Thus $G$ is $3$-regular bipartite. + +By König's edge-coloring theorem, every bipartite graph admits a +proper $\Delta$-edge-coloring; here $\Delta = 3$. So $G$ has a +proper $3$-edge-coloring $\chi : E(G) \to \{1,2,3\}$. Transport +$\chi$ back to $\gamma$-edges via the bijection: define +$\sigma(e) := \chi(e)$. Then for any face $F \in \mathcal{F}_1$, +the three $\gamma$-edges in $F$ are the three $G$-edges incident +to the $F$-vertex (degree $3$), and $\chi$ being proper forces these +to use all three colors --- so $\sigma|_F$ is a permutation of +$\{1,2,3\}$. Same for $\mathcal{F}_2$. + +Hence $\sigma \in \mathcal{L}(\gamma, \mathcal{F}_1) \cap +\mathcal{L}(\gamma, \mathcal{F}_2)$. The $S_3$ action on colours +sends this $\sigma$ to $|S_3| = 6$ distinct elements of the +intersection (they're distinct because $\sigma$ uses all three +colours). +\end{proof} + +\begin{prop}[Lower bound is achieved] +\label{prop:lower-bound-tight} +The lower bound $|{\cdots}| \geq 6$ in +Prop.~\ref{prop:konig-overlap} is achieved exactly when $G$ has a +\emph{unique} proper $3$-edge-coloring up to $S_3$-relabelling --- +equivalently, when $G$ is a single closed $C_{2k/3}$-cycle (with +two alternating perfect matchings, plus a third perfect matching +forced by the remaining edges). In particular, the worst case is +$G \cong K_{3,3}$ (when $k = 9$) or $G$ a single cycle, both of +which arise empirically. +\end{prop} + +(Sketch: a $3$-regular bipartite graph has $\geq 6$ proper $3$-edge- +colourings, with equality iff the colouring is essentially unique. +The unique-up-to-$S_3$ case is exactly when $G$ is highly symmetric. +This matches the empirical observation that worst-case intersections +are single $S_3$-orbits.) + +\section*{What remains: the gap in the actual setting} + +In the real chain-pigeonhole setup, $T_1$'s chord is on $B_{\mathrm{in}}^{(1)} += \gamma$ (so $T_1$ \emph{does} give a direct $\gamma$-face partition +$\mathcal{F}_1$), but $T_2$'s chord is on $B_{\mathrm{in}}^{(2)}$, +\emph{not} on $\gamma$. So $T_2$ does not directly give a +$\gamma$-face partition. + +\subsection*{Conjectural extension to the real case} + +\begin{conj}[Induced $\gamma$-partition from $T_2$] +\label{conj:t2-induces-partition} +For any SP tire $T_2$ with $B_{\mathrm{in}}^{(2)}$-side chord +structure $O^{(2)}$ such that every $O^{(2)}$-face has exactly $3$ +$B_{\mathrm{in}}^{(2)}$-edges, the outer-spoke support +$\pi_U(\mathcal{C}(T_2)) \subseteq \{1,2,3\}^\gamma$ contains a +Latin subset $\mathcal{L}(\gamma, \widetilde{\mathcal{F}_2})$ for +some induced face partition $\widetilde{\mathcal{F}_2}$ of $\gamma$ +into triples, where $\widetilde{\mathcal{F}_2}$ is determined by how +$T_2$'s annular triangulation distributes $B_{\mathrm{in}}^{(2)}$ faces +across $\gamma$-edges. +\end{conj} + +If Conjecture~\ref{conj:t2-induces-partition} holds, then +Prop.~\ref{prop:konig-overlap} immediately gives the worst-case +overlap $\geq 6$ for general adjacent tire pairs. + +\subsection*{Why this is plausible} + +At $\gamma = 6$, $T_1 = (m_1, (0,3), \mathrm{SP})$ vs $T_2 = (m_2, +B_{\mathrm{in}}^{(2)} = C_3, \mathrm{SP})$, the empirical $6$-element +intersection consists of patterns $(a, b, c, b, c, a)$ which: +\begin{itemize} + \item $T_1$'s $\gamma$-face partition $\{0,1,2\} \mid \{3,4,5\}$: + $\sigma|_{0,1,2} = (a, b, c)$ is a permutation, + $\sigma|_{3,4,5} = (b, c, a)$ is a permutation. $\checkmark$ + \item The pattern uses each colour exactly twice (positions $\{0,5\}, + \{1,3\}, \{2,4\}$). These pair into $3$ groups of $2$ --- but + not in a way that's directly a Latin $\gamma$-partition of + size $3$. +\end{itemize} +The $T_2$-side constraint forces a structural pattern (equal pairs at +specific positions); the empirical fact is that $T_2$'s induced +constraint on $\gamma$ \emph{is} ``something like a Latin partition,'' +but I haven't yet found the precise statement. + +\subsection*{One concrete attempt at the induced partition} + +For $T_2$ with $B_{\mathrm{in}}^{(2)} = C_{k_2}$ and balanced +annular triangulation, the dual cycle of $T_2$ alternates between +D-triangles (one $B_{\mathrm{in}}^{(2)}$-edge each) and U-triangles +(one $\gamma$-edge each). Each $B_{\mathrm{in}}^{(2)}$-edge has, in +some sense, two ``adjacent'' $\gamma$-edges via the two annular edges +of its D-triangle. + +\emph{Candidate induced partition.} Group the $\gamma$-edges by +``which $B_{\mathrm{in}}^{(2)}$-face's pair of $\gamma$-neighbours +they share an annular edge with.'' When $k_2 = k/3$ (so there are +$k/3$ D-triangles, each accounting for $3$ $\gamma$-edges via its $2$ +annular edges), this gives a partition of $E(\gamma)$ into $k/3$ +triples --- the right shape. + +Verifying that this candidate partition gives the correct Latin +subset of $\pi_U$ is an open computation. + +\section*{Where the lower bound of $|S_3| = 6$ comes from independently} + +Setting aside the construction, the lower bound of $6$ has a clean +abstract origin: + +\begin{lem}[Lower bound from $S_3$-invariance] +Both $S_1$ and $S_2$ are $S_3$-invariant (the $S_3$ action on +colours acts on edge $3$-colourings of $G'$). Hence $S_1 \cap S_2$ +is $S_3$-invariant, so it decomposes into $S_3$-orbits. Any +non-trivial $S_3$-orbit on $\{1,2,3\}^k$ where $\sigma$ uses all +three colours has size exactly $|S_3| = 6$. Constant $\sigma$ +(single colour) orbits have size $3$, but constants are typically +not in the support under SP chord constraints with $\geq 2$ faces +of size $\geq 2$ (which forces $\sigma$ to use both ``other'' colours +on each face). +\end{lem} + +So the absolute floor is $6$ once we rule out emptiness. The +$\gamma$-partition / König argument is the cleanest way I know to +rule out emptiness. + +\section*{Summary of what's proven, conjectured, and open} + +\begin{itemize} + \item \textbf{Proven (Prop.~\ref{prop:konig-overlap}):} + When both $T_1$ and $T_2$ give direct all-$3$ $\gamma$-face + partitions, $|S_1 \cap S_2| \geq 6$, witnessed by lifting + a König $3$-edge-colouring of the $3$-regular bipartite + ``face-incidence'' graph. + + \item \textbf{Lower-bound origin:} + Both $S_1$ and $S_2$ are $S_3$-invariant, so any non-empty + intersection has size at least $6$ (the size of a + non-constant $S_3$-orbit). + + \item \textbf{Conjectured (Conj.~\ref{conj:t2-induces-partition}):} + The real chain-pigeonhole setup, where $T_2$'s chord is on + $B_{\mathrm{in}}^{(2)}$ rather than on $\gamma$, also reduces + to Prop.~\ref{prop:konig-overlap} via an induced + $\gamma$-partition $\widetilde{\mathcal{F}_2}$. Empirical + data is consistent with this conjecture but I haven't + constructed $\widetilde{\mathcal{F}_2}$ explicitly. + + \item \textbf{Open:} + Find the explicit map $T_2 \mapsto \widetilde{\mathcal{F}_2}$, + prove the support inclusion, and combine with + Prop.~\ref{prop:konig-overlap} to close the worst-case + lower bound. +\end{itemize} + +\end{document}