Spaces:
Sleeping
Sleeping
| """ | |
| analysis.py — Automated mathematical analysis of Claude's Cycles solutions. | |
| Given a sigma function or SigmaTable, this module: | |
| 1. STRUCTURAL ANALYSIS | |
| - Detects column-uniformity (does sigma depend only on s,j or all of i,j,k?) | |
| - Computes the Q_c composed permutations | |
| - Identifies the twisted translation form Q_c(i,j) = (i+b_c(j), j+r_c) | |
| 2. THEOREM VERIFICATION | |
| - Theorem 1: Twisted Translation Structure (auto-detected) | |
| - Theorem 2: Single-Cycle Conditions (gcd checks) | |
| - Theorem 3: Existence for odd m (constructive verification) | |
| - Theorem 4: Impossibility for even m (parity argument) | |
| 3. PATTERN REPORTING | |
| - Full solution tables | |
| - Arc sequences for each Hamiltonian cycle | |
| - Comparison across m values | |
| """ | |
| from __future__ import annotations | |
| from typing import Optional, List, Dict, Tuple | |
| from math import gcd | |
| from .core import ( | |
| Vertex, Perm, SigmaFn, | |
| build_functional_graphs, verify_sigma, VerifyResult, | |
| trace_cycle, arc_sequence, vertices | |
| ) | |
| from .fiber import ( | |
| SigmaTable, compose_levels, analyze_Q_structure, | |
| even_m_impossibility_check, verify_single_cycle_conditions, | |
| table_to_sigma_fn, FIBER_SHIFTS | |
| ) | |
| # =========================================================================== # | |
| # Structural analysis of sigma | |
| # =========================================================================== # | |
| def detect_dependencies(sigma: SigmaFn, m: int) -> Dict[str, bool]: | |
| """ | |
| Determine which coordinates sigma actually depends on. | |
| Returns {'i': bool, 'j': bool, 'k': bool, 's': bool} | |
| where s = (i+j+k) mod m. | |
| """ | |
| depends_i = depends_j = depends_k = False | |
| for i in range(m): | |
| for j in range(m): | |
| for k in range(m): | |
| base = sigma(i, j, k) | |
| if i > 0 and sigma(i, j, k) != sigma(0, j, k): | |
| depends_i = True | |
| if j > 0 and sigma(i, j, k) != sigma(i, 0, k): | |
| depends_j = True | |
| if k > 0 and sigma(i, j, k) != sigma(i, j, 0): | |
| depends_k = True | |
| # Check if sigma depends only on s=(i+j+k)%m and j | |
| depends_s_only = True | |
| for i in range(m): | |
| for j in range(m): | |
| for k in range(m): | |
| s = (i + j + k) % m | |
| # Find another vertex with same s and j but different i | |
| other_i = (i + 1) % m | |
| other_k = (s - other_i - j) % m | |
| if sigma(i, j, k) != sigma(other_i, j, other_k): | |
| depends_s_only = False | |
| break | |
| if not depends_s_only: | |
| break | |
| if not depends_s_only: | |
| break | |
| return { | |
| "i": depends_i, | |
| "j": depends_j, | |
| "k": depends_k, | |
| "column_uniform": depends_s_only, # sigma(i,j,k) = f(s,j) | |
| } | |
| def extract_sigma_table(sigma: SigmaFn, m: int) -> Optional[SigmaTable]: | |
| """ | |
| If sigma is column-uniform (depends only on s,j), extract SigmaTable. | |
| Returns None if sigma is not column-uniform. | |
| """ | |
| deps = detect_dependencies(sigma, m) | |
| if not deps["column_uniform"]: | |
| return None | |
| table = [] | |
| for s in range(m): | |
| level = {} | |
| for j in range(m): | |
| # Find a representative vertex in fiber s with column j | |
| i_rep = 0 | |
| k_rep = (s - i_rep - j) % m | |
| level[j] = list(sigma(i_rep, j, k_rep)) | |
| table.append(level) | |
| return table | |
| # =========================================================================== # | |
| # Full solution analysis | |
| # =========================================================================== # | |
| class SolutionAnalysis: | |
| """ | |
| Comprehensive analysis of a Claude's Cycles solution. | |
| Usage: | |
| analysis = SolutionAnalysis(sigma_fn, m=5) | |
| analysis.run() | |
| print(analysis.report()) | |
| """ | |
| def __init__(self, sigma: SigmaFn, m: int): | |
| self.sigma = sigma | |
| self.m = m | |
| self._run = False | |
| def run(self) -> "SolutionAnalysis": | |
| m = self.m | |
| sigma = self.sigma | |
| # 1. Core verification | |
| self.verify_result: VerifyResult = verify_sigma(sigma, m) | |
| # 2. Build functional graphs and traces | |
| self.funcs = build_functional_graphs(sigma, m) | |
| self.cycle_paths = [trace_cycle(fg, m) for fg in self.funcs] | |
| self.arc_seqs = [arc_sequence(p, m) for p in self.cycle_paths] | |
| # 3. Structural dependencies | |
| self.deps = detect_dependencies(sigma, m) | |
| # 4. If column-uniform, extract Q and analyze | |
| self.sigma_table: Optional[SigmaTable] = extract_sigma_table(sigma, m) | |
| if self.sigma_table is not None: | |
| Qs = compose_levels(self.sigma_table, m) | |
| self.Q_analysis: Optional[dict] = analyze_Q_structure(Qs, m) | |
| else: | |
| self.Q_analysis = None | |
| # 5. Theoretical checks | |
| self.impossibility = even_m_impossibility_check(m) | |
| self._run = True | |
| return self | |
| def report(self, verbose: bool = True) -> str: | |
| if not self._run: | |
| self.run() | |
| m = self.m | |
| lines = [ | |
| "=" * 64, | |
| f"CLAUDE'S CYCLES SOLUTION ANALYSIS — m={m}", | |
| "=" * 64, | |
| "", | |
| f"Verification: {self.verify_result}", | |
| "", | |
| ] | |
| # Dependency structure | |
| d = self.deps | |
| dep_str = "sigma depends on: " + ", ".join( | |
| x for x, v in [("i",d["i"]),("j",d["j"]),("k",d["k"])] if v | |
| ) | |
| if d["column_uniform"]: | |
| dep_str += " → COLUMN-UNIFORM (only s=(i+j+k)%m and j)" | |
| lines.append(dep_str) | |
| lines.append("") | |
| # Sigma table | |
| if self.sigma_table is not None and verbose: | |
| lines.append("Sigma table [s][j] → [arc₀→cycle, arc₁→cycle, arc₂→cycle]:") | |
| for s in range(m): | |
| row = [self.sigma_table[s][j] for j in range(m)] | |
| lines.append(f" s={s}: {row}") | |
| lines.append("") | |
| # Arc sequences | |
| lines.append("Hamiltonian cycle arc sequences (I=incr_i, J=incr_j, K=incr_k):") | |
| for c in range(3): | |
| seq = self.arc_seqs[c] | |
| counts = {x: seq.count(x) for x in "IJK"} | |
| lines.append(f" Cycle {c}: {seq[:40]}{'...' if len(seq)>40 else ''}" | |
| f" [I:{counts['I']} J:{counts['J']} K:{counts['K']}]") | |
| lines.append("") | |
| # Q structure | |
| if self.Q_analysis is not None: | |
| qa = self.Q_analysis | |
| lines.append("Composed fiber permutation Q_c:") | |
| twisted_str = "✅ YES" if qa["all_twisted"] else "❌ NO" | |
| lines.append(f" Twisted translation form Q_c(i,j)=(i+b_c(j),j+r_c): {twisted_str}") | |
| if qa["all_twisted"]: | |
| lines.append(f" r-values: {qa['r_values']} sum={qa['sum_r']} (= m? {qa['sum_r']==m})") | |
| for info in qa["cycles"]: | |
| c = info["cycle"] | |
| if info["is_twisted"]: | |
| sc = verify_single_cycle_conditions(info["r_c"], info["b_c"], m) | |
| lines.append( | |
| f" Q_{c}: r={info['r_c']} b={info['b_c']}" | |
| f" Σb={info['sum_b']}" | |
| f" cond_a(gcd(r,m)=1)={'✅' if sc['condition_a'] else '❌'}" | |
| f" cond_b(gcd(Σb,m)=1)={'✅' if sc['condition_b'] else '❌'}" | |
| f" single_cycle={'✅' if info['is_single_cycle'] else '❌'}" | |
| ) | |
| else: | |
| lines.append(f" Q_{c}: NOT in twisted form") | |
| lines.append("") | |
| # Theoretical context | |
| imp = self.impossibility | |
| lines.append(f"Theoretical context (m={m}):") | |
| if imp["m_is_even"]: | |
| lines.append(f" m={m} is EVEN → column-uniform fiber construction IMPOSSIBLE") | |
| lines.append(f" (Proof: {imp['proof']})") | |
| else: | |
| lines.append(f" m={m} is ODD → column-uniform fiber construction POSSIBLE") | |
| ex = imp.get("example") | |
| if ex: | |
| lines.append(f" Example valid (r₀,r₁,r₂) = {ex}") | |
| lines.append("=" * 64) | |
| return "\n".join(lines) | |
| def __repr__(self) -> str: | |
| status = "✅" if (self._run and self.verify_result.is_valid) else "?" | |
| return f"SolutionAnalysis(m={self.m}, valid={status})" | |
| # =========================================================================== # | |
| # Cross-m comparison | |
| # =========================================================================== # | |
| def compare_across_m(results: Dict[int, "SolutionAnalysis"]) -> str: | |
| """ | |
| Generate a comparison table across multiple m values. | |
| results: {m: SolutionAnalysis} | |
| """ | |
| lines = [ | |
| "=" * 72, | |
| "COMPARISON ACROSS m VALUES", | |
| "=" * 72, | |
| f"{'m':>4} {'parity':>6} {'valid':>7} {'col_unif':>9} " | |
| f"{'twisted':>8} {'r_vals':>20}", | |
| "-" * 72, | |
| ] | |
| for m in sorted(results): | |
| a = results[m] | |
| if not a._run: | |
| a.run() | |
| parity = "ODD" if m % 2 == 1 else "EVEN" | |
| valid = "✅" if a.verify_result.is_valid else "❌" | |
| col = "✅" if a.deps["column_uniform"] else "❌" | |
| if a.Q_analysis: | |
| twisted = "✅" if a.Q_analysis["all_twisted"] else "❌" | |
| r = str(a.Q_analysis.get("r_values", "—")) | |
| else: | |
| twisted = "—" | |
| r = "—" | |
| lines.append(f"{m:>4} {parity:>6} {valid:>7} {col:>9} {twisted:>8} {r:>20}") | |
| lines.append("=" * 72) | |
| return "\n".join(lines) | |