mirror of
https://github.com/allaunthefox/SilverSight.git
synced 2026-07-30 17:16:16 +00:00
Three deliverables: 1. scripts/crt_qprofile_sweep.py Safety factor optimization (R1 from toroidal refinement). Replaces brute-force modulus selection with systematic q-profile sweep. Tests: q < 1 (poloidal) vs q > 1 (toroidal) Sidon rate, simple rational q vs non-simple (R2 cross-pair coprimality). All integer arithmetic (Fraction for q). 2. docs/research/GERVER_SIDON_DESIGN.md Direction B design: actual Gerver sofa (18 arcs) with CRT Sidon boundary in ℤ², high-resolution motion (T=100), justified tolerance. Explains why Direction A failed and what Direction B fixes. Honest assessment: long shot, but more promising than v2/v3. 3. (Report in /tmp — uploaded separately) Negative result write-up: sofa coloring doesn't detect q=1 at justified tolerance. HN spectral database: Hoffman tight for regular graphs, gap=1 for unit-distance. CRT n-moduli generalization.
363 lines
12 KiB
Python
363 lines
12 KiB
Python
#!/usr/bin/env python3
|
|
"""crt_qprofile_sweep.py — q-profile safety factor design for CRT moduli.
|
|
|
|
Replaces brute-force modulus selection with systematic q-profile sweep,
|
|
as proposed in TOROIDAL_POLOIDAL_REFINEMENT.md (R1, R6).
|
|
|
|
The toroidal/poloidal mapping gives:
|
|
q = L_reflection / L_identity (toroidal/poloidal ratio)
|
|
q < 1 = poloidal-dominated (Sidon-favorable)
|
|
q > 1 = toroidal-dominated (Sidon-unfavorable)
|
|
q = 1 = degenerate (rational surface → resonance → Sidon collapse)
|
|
|
|
This script:
|
|
1. Sweeps q from 0.3 to 3.0 (avoiding simple rationals)
|
|
2. For each q, constructs moduli (L₀, L₁) with L₁/L₀ = q
|
|
3. Tests Sidon preservation for known Sidon label sets
|
|
4. Also applies cross-pair q-ratio check (R2): avoid simple rationals
|
|
5. Measures Sidon score as function of q
|
|
|
|
Outputs:
|
|
.openresearch/artifacts/crt_qprofile_sweep.json
|
|
.openresearch/artifacts/EVAL.md
|
|
|
|
All integer arithmetic. No floats in compute path.
|
|
"""
|
|
|
|
import sys
|
|
import math
|
|
import json
|
|
import time
|
|
import hashlib
|
|
from pathlib import Path
|
|
from collections import Counter
|
|
from fractions import Fraction
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parent.parent
|
|
ARTIFACTS_DIR = REPO_ROOT / ".openresearch" / "artifacts"
|
|
ARTIFACTS_DIR.mkdir(parents=True, exist_ok=True)
|
|
OUTPUT_PATH = ARTIFACTS_DIR / "crt_qprofile_sweep.json"
|
|
EVAL_PATH = ARTIFACTS_DIR / "EVAL.md"
|
|
|
|
|
|
# ── Exact Arithmetic ──────────────────────────────────────────────────────
|
|
|
|
def gcd(a, b):
|
|
while b:
|
|
a, b = b, a % b
|
|
return a
|
|
|
|
def pairwise_coprime(moduli):
|
|
for i in range(len(moduli)):
|
|
for j in range(i + 1, len(moduli)):
|
|
if gcd(moduli[i], moduli[j]) != 1:
|
|
return False
|
|
return True
|
|
|
|
def is_simple_rational(a, b, max_den=7):
|
|
"""Check if a/b reduces to m/n with n <= max_den."""
|
|
if b == 0:
|
|
return True
|
|
g = gcd(abs(a), abs(b))
|
|
na, nb = abs(a) // g, abs(b) // g
|
|
return nb <= max_den
|
|
|
|
|
|
# ── CRT Torus Embedding ───────────────────────────────────────────────────
|
|
|
|
def embed(labels, S, moduli):
|
|
M = 1
|
|
for m in moduli:
|
|
M *= m
|
|
embedded = []
|
|
for a in labels:
|
|
row = []
|
|
for i in range(len(moduli)):
|
|
if i == 0:
|
|
row.append(a % moduli[0])
|
|
else:
|
|
row.append((S - a) % moduli[i])
|
|
embedded.append(row)
|
|
return embedded, M
|
|
|
|
def egcd(a, b):
|
|
if b == 0:
|
|
return a, 1, 0
|
|
g, x, y = egcd(b, a % b)
|
|
return g, y, x - (a // b) * y
|
|
|
|
def modinv(a, m):
|
|
g, x, _ = egcd(a % m, m)
|
|
if g != 1:
|
|
return None
|
|
return x % m
|
|
|
|
def crt_reconstruct(residues, moduli):
|
|
M = 1
|
|
for m in moduli:
|
|
M *= m
|
|
x = 0
|
|
for r, m in zip(residues, moduli):
|
|
Mi = M // m
|
|
inv = modinv(Mi % m, m)
|
|
if inv is None:
|
|
return None
|
|
x = (x + r * Mi * inv) % M
|
|
return x
|
|
|
|
def sidon_check(embedded, moduli):
|
|
M = 1
|
|
for m in moduli:
|
|
M *= m
|
|
n = len(embedded)
|
|
total_pairs = n * (n + 1) // 2
|
|
vals = [crt_reconstruct(row, moduli) for row in embedded]
|
|
sums = []
|
|
for i in range(n):
|
|
for j in range(i, n):
|
|
sums.append((vals[i] + vals[j]) % M)
|
|
counts = Counter(sums)
|
|
collisions = sum(c - 1 for c in counts.values())
|
|
score = 1.0 - collisions / total_pairs if total_pairs > 0 else 1.0
|
|
return {
|
|
"total_pairs": total_pairs,
|
|
"distinct_residues": len(counts),
|
|
"collisions": collisions,
|
|
"sidon_score": round(score, 6),
|
|
"is_sidon": collisions == 0,
|
|
}
|
|
|
|
|
|
# ── q-Profile Modulus Selection ──────────────────────────────────────────
|
|
|
|
def select_qprofile_moduli(L0, q_num, q_den, n_moduli=2):
|
|
"""Select moduli with a given q-profile.
|
|
|
|
q = L₁/L₀ = q_num/q_den (as exact fraction)
|
|
L₀ = L0 (identity axis, poloidal)
|
|
L₁ = L₀ * q_num / q_den (reflection axis, toroidal)
|
|
|
|
For n_moduli > 2, additional moduli use increasing primes coprime to all.
|
|
Returns (moduli, q) or None if not coprime.
|
|
"""
|
|
# L₁ = L0 * q_num / q_den — must be integer
|
|
L1 = L0 * q_num // q_den
|
|
if L0 * q_num != L1 * q_den:
|
|
# Not exact — adjust L0 to make it work
|
|
L0 = L0 * q_den
|
|
L1 = L0 * q_num // q_den
|
|
|
|
if L0 < 2 or L1 < 2:
|
|
return None, None
|
|
|
|
moduli = [L0, L1]
|
|
|
|
# For n_moduli > 2, add coprime primes
|
|
if n_moduli > 2:
|
|
p = L1 + 2
|
|
while len(moduli) < n_moduli:
|
|
if all(gcd(p, m) == 1 for m in moduli) and p > 2:
|
|
moduli.append(p)
|
|
p += 1
|
|
|
|
if not pairwise_coprime(moduli):
|
|
return None, None
|
|
|
|
q = Fraction(q_num, q_den)
|
|
return moduli, q
|
|
|
|
|
|
def sweep_q_profile(label_set, S, L0_base, max_q_num=30, max_q_den=20):
|
|
"""Sweep q = L₁/L₀ over all coprime fractions q_num/q_den.
|
|
Returns list of (q, moduli, sidon_result, q_is_simple_rational).
|
|
"""
|
|
results = []
|
|
|
|
for q_den in range(2, max_q_den + 1):
|
|
for q_num in range(1, max_q_num + 1):
|
|
if gcd(q_num, q_den) != 1:
|
|
continue # skip non-reduced fractions
|
|
if q_num == q_den:
|
|
continue # skip q=1 (degenerate)
|
|
|
|
moduli, q = select_qprofile_moduli(L0_base, q_num, q_den)
|
|
if moduli is None:
|
|
continue
|
|
|
|
q_simple = is_simple_rational(q_num, q_den, max_den=7)
|
|
|
|
embedded, M = embed(label_set, S, moduli)
|
|
sidon = sidon_check(embedded, moduli)
|
|
|
|
entry = {
|
|
"q": str(q),
|
|
"q_float": float(q),
|
|
"q_num": q_num,
|
|
"q_den": q_den,
|
|
"q_simple_rational": q_simple,
|
|
"moduli": moduli,
|
|
"M": M,
|
|
"L0": moduli[0],
|
|
"L1": moduli[1],
|
|
"sidon_score": sidon["sidon_score"],
|
|
"collisions": sidon["collisions"],
|
|
"is_sidon": sidon["is_sidon"],
|
|
"total_pairs": sidon["total_pairs"],
|
|
"distinct_residues": sidon["distinct_residues"],
|
|
}
|
|
results.append(entry)
|
|
|
|
return results
|
|
|
|
|
|
# ── Main ──────────────────────────────────────────────────────────────────
|
|
|
|
def run_experiment():
|
|
results = {
|
|
"experiment": "crt_qprofile_sweep",
|
|
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
|
"config": {
|
|
"L0_base": 7,
|
|
"max_q_num": 30,
|
|
"max_q_den": 20,
|
|
"label_sets": [
|
|
{"name": "sidon_pow2", "labels": [1, 2, 4, 8, 16], "S": 32},
|
|
{"name": "sidon_singer5", "labels": [0, 1, 4, 14, 16], "S": 30},
|
|
{"name": "nonsidon_seq5", "labels": [0, 1, 2, 3, 4], "S": 5},
|
|
],
|
|
},
|
|
"data": [],
|
|
"summary": {},
|
|
}
|
|
|
|
label_sets = [
|
|
("sidon_pow2", [1, 2, 4, 8, 16], 32),
|
|
("sidon_singer5", [0, 1, 4, 14, 16], 30),
|
|
("nonsidon_seq5", [0, 1, 2, 3, 4], 5),
|
|
]
|
|
|
|
L0_base = 7
|
|
|
|
for desc, labels, S in label_sets:
|
|
print(f"\n{'='*60}")
|
|
print(f" Label set: {desc} (n={len(labels)}, S={S})")
|
|
print(f"{'='*60}")
|
|
|
|
sweep = sweep_q_profile(labels, S, L0_base)
|
|
|
|
# Analyze
|
|
sidon_count = sum(1 for r in sweep if r["is_sidon"])
|
|
total_count = len(sweep)
|
|
q_simple_count = sum(1 for r in sweep if r["q_simple_rational"])
|
|
q_simple_sidon = sum(1 for r in sweep if r["q_simple_rational"] and r["is_sidon"])
|
|
q_not_simple_sidon = sum(1 for r in sweep if not r["q_simple_rational"] and r["is_sidon"])
|
|
|
|
# q < 1 vs q > 1
|
|
q_lt1 = [r for r in sweep if r["q_float"] < 1.0]
|
|
q_gt1 = [r for r in sweep if r["q_float"] > 1.0]
|
|
q_lt1_sidon = sum(1 for r in q_lt1 if r["is_sidon"])
|
|
q_gt1_sidon = sum(1 for r in q_gt1 if r["is_sidon"])
|
|
|
|
# Best q (highest Sidon score)
|
|
best = max(sweep, key=lambda r: r["sidon_score"]) if sweep else None
|
|
|
|
summary = {
|
|
"total_configs": total_count,
|
|
"sidon_configs": sidon_count,
|
|
"sidon_rate": round(sidon_count / total_count, 4) if total_count > 0 else 0,
|
|
"q_simple_rational_count": q_simple_count,
|
|
"q_simple_sidon": q_simple_sidon,
|
|
"q_not_simple_sidon": q_not_simple_sidon,
|
|
"q_lt1_total": len(q_lt1),
|
|
"q_lt1_sidon": q_lt1_sidon,
|
|
"q_lt1_sidon_rate": round(q_lt1_sidon / len(q_lt1), 4) if q_lt1 else 0,
|
|
"q_gt1_total": len(q_gt1),
|
|
"q_gt1_sidon": q_gt1_sidon,
|
|
"q_gt1_sidon_rate": round(q_gt1_sidon / len(q_gt1), 4) if q_gt1 else 0,
|
|
"best_q": best["q"] if best else None,
|
|
"best_sidon_score": best["sidon_score"] if best else None,
|
|
"best_moduli": best["moduli"] if best else None,
|
|
}
|
|
results["summary"][desc] = summary
|
|
|
|
print(f" Total configs: {total_count}")
|
|
print(f" Sidon configs: {sidon_count} ({summary['sidon_rate']:.1%})")
|
|
print(f" q < 1: {q_lt1_sidon}/{len(q_lt1)} Sidon ({summary['q_lt1_sidon_rate']:.1%})")
|
|
print(f" q > 1: {q_gt1_sidon}/{len(q_gt1)} Sidon ({summary['q_gt1_sidon_rate']:.1%})")
|
|
print(f" q simple rational: {q_simple_sidon}/{q_simple_count} Sidon")
|
|
print(f" q NOT simple: {q_not_simple_sidon}/{total_count - q_simple_count} Sidon")
|
|
if best:
|
|
print(f" Best q = {best['q']} (score={best['sidon_score']}, moduli={best['moduli']})")
|
|
|
|
# Store all sweep data
|
|
for r in sweep:
|
|
r["label_set"] = desc
|
|
results["data"].append(r)
|
|
|
|
content = json.dumps(results, indent=2, sort_keys=True, default=str)
|
|
results["sha256"] = hashlib.sha256(content.encode()).hexdigest()
|
|
return results
|
|
|
|
|
|
def write_eval(results):
|
|
lines = [
|
|
"# CRT q-Profile Safety Factor Sweep",
|
|
"",
|
|
f"**Experiment:** {results['experiment']}",
|
|
f"**Date:** {results['timestamp']}",
|
|
f"**SHA-256:** `{results['sha256']}`",
|
|
"",
|
|
"## Summary: Sidon Rate by q-Regime",
|
|
"",
|
|
"| Label set | Total | Sidon | Rate | q<1 total | q<1 Sidon | q<1 rate | q>1 total | q>1 Sidon | q>1 rate | Simple q Sidon | Non-simple Sidon | Best q |",
|
|
"|-----------|-------|-------|------|-----------|-----------|----------|-----------|-----------|----------|----------------|------------------|-------|",
|
|
]
|
|
for desc, s in results["summary"].items():
|
|
lines.append(
|
|
f"| {desc} | {s['total_configs']} | {s['sidon_configs']} | "
|
|
f"{s['sidon_rate']:.1%} | "
|
|
f"{s['q_lt1_total']} | {s['q_lt1_sidon']} | {s['q_lt1_sidon_rate']:.1%} | "
|
|
f"{s['q_gt1_total']} | {s['q_gt1_sidon']} | {s['q_gt1_sidon_rate']:.1%} | "
|
|
f"{s['q_simple_sidon']} | {s['q_not_simple_sidon']} | "
|
|
f"{s['best_q']} |"
|
|
)
|
|
|
|
lines.extend([
|
|
"",
|
|
"## Predictions Tested",
|
|
"",
|
|
"1. **q < 1 (poloidal-dominated) should have higher Sidon rate than q > 1**",
|
|
" - This is the toroidal/poloidal refinement prediction",
|
|
" - If confirmed: poloidal resolution matters for Sidon structure",
|
|
"",
|
|
"2. **Simple rational q should have LOWER Sidon rate than non-simple q**",
|
|
" - This is the R2 cross-pair coprimality prediction",
|
|
" - Simple rationals = resonant surfaces = Sidon collapse",
|
|
"",
|
|
"3. **Best q should be < 1 and not a simple rational**",
|
|
" - Optimal q-profile is poloidal-dominated and irrational",
|
|
"",
|
|
])
|
|
|
|
EVAL_PATH.write_text("\n".join(lines))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("=" * 60)
|
|
print("CRT q-Profile Safety Factor Sweep")
|
|
print("=" * 60)
|
|
|
|
t0 = time.time()
|
|
results = run_experiment()
|
|
elapsed = time.time() - t0
|
|
|
|
OUTPUT_PATH.write_text(json.dumps(results, indent=2, default=str))
|
|
print(f"\nResults → {OUTPUT_PATH}")
|
|
|
|
write_eval(results)
|
|
print(f"EVAL → {EVAL_PATH}")
|
|
|
|
print(f"\nElapsed: {elapsed:.1f}s")
|
|
print("=" * 60)
|
|
print("DONE")
|
|
print("=" * 60)
|