use ogdoad::forms::fit_f2_quadratic;
use ogdoad::games::loopy_decision_sets;
mod common;
use common::{bent_gold as gold, bent_polar as polar, p_set};
fn describe(label: &str, p: &[u128], zero: &[u128], draws: usize, m: u128) {
let n = 1usize << m;
let ps: std::collections::HashSet<u128> = p.iter().copied().collect();
let zs: std::collections::HashSet<u128> = zero.iter().copied().collect();
let agree = (0..n as u128)
.filter(|v| ps.contains(v) == zs.contains(v))
.count();
print!(
" {label:<28} |P|={:<3} draws={draws:<3} agree {agree}/{n} with {{Q=0}}",
p.len()
);
if p == zero {
println!(" ← EXACTLY {{Q=0}} !!");
} else {
match fit_f2_quadratic(p, m as usize) {
Some(f) if f.is_genuinely_quadratic() => {
let bent = if f.arf.rank == m as usize {
", BENT"
} else {
""
};
println!(
" quadric (Arf(Q)={}, rank={}, constant={} → win-bias={}{bent})",
f.arf.arf,
f.arf.rank,
f.constant,
f.bias()
)
}
Some(_) => println!(" affine/linear (a subspace coset)"),
None => println!(" not a quadric"),
}
}
}
fn main() {
let (m, a) = (8u128, 1u128);
let n = 1usize << m;
let half = 1u128 << (m - 1);
let off = 1u128 << (m / 2 - 1);
let lam = (1..1u128 << m)
.find(|&l| {
let z = (0..1u128 << m).filter(|&v| gold(v, l, a, m) == 0).count() as u128;
z == half + off || z == half - off
})
.expect("a bent component exists");
let zero: Vec<u128> = (0..n as u128)
.filter(|&v| gold(v, lam, a, m) == 0)
.collect();
let z = zero.len() as u128;
let arf = if z == half + off { 0 } else { 1 };
println!(
"Bent Gold component Q(v) = Tr({lam}·v^{{1+2^{a}}}) on F_2^{m}: bent, Arf={arf}, |{{Q=0}}|={z}\n"
);
let (loss, _draw) = loopy_decision_sets(n, |v| {
(1..n)
.filter(|&d| polar(v as u128, d as u128, lam, a, m) == 1)
.map(|d| v ^ d)
.collect()
});
println!(
"(i) symmetric-B loopy Loss-set = R(B) = {:?} ⇒ radical route empty (bent).\n",
loss
);
let q_diag: Vec<u128> = (0..m).map(|i| gold(1 << i, lam, a, m)).collect();
let delta = |v: u128, i: u128| q_diag[i as usize] ^ polar(v, 1 << i, lam, a, m);
assert!((0..n as u128).all(
|v| (0..m).all(|i| delta(v, i) == (gold(v ^ (1 << i), lam, a, m) ^ gold(v, lam, a, m)))
));
println!("(ii) candidate rules (downward: turn OFF set bits only, so play terminates):\n");
let ra: Vec<Vec<usize>> = (0..n)
.map(|v| {
(0..m)
.filter(|&i| v as u128 & (1 << i) != 0 && delta(v as u128, i) == 1)
.map(|i| (v as u128 ^ (1 << i)) as usize)
.collect()
})
.collect();
let (pa, da) = p_set(&ra);
describe("A local spin-flip (B+field)", &pa, &zero, da, m);
let rb: Vec<Vec<usize>> = (0..n)
.map(|v| {
(0..m)
.filter(|&i| v as u128 & (1 << i) != 0 && polar(v as u128, 1 << i, lam, a, m) == 1)
.map(|i| (v as u128 ^ (1 << i)) as usize)
.collect()
})
.collect();
let (pb, db) = p_set(&rb);
describe("B single-bit B-only", &pb, &zero, db, m);
let rc: Vec<Vec<usize>> = (0..n)
.map(|v| {
(0..v)
.filter(|&w| polar(v as u128, (v ^ w) as u128, lam, a, m) == 1)
.collect()
})
.collect();
let (pc, dc) = p_set(&rc);
describe("C B-coupled descent", &pc, &zero, dc, m);
let rd: Vec<Vec<usize>> = (0..n)
.map(|v| {
(0..v)
.filter(|&w| gold(w as u128, lam, a, m) != gold(v as u128, lam, a, m))
.collect()
})
.collect();
let (pd, dd) = p_set(&rd);
describe("D Q-changing (tautological)", &pd, &zero, dd, m);
println!("\nReading (what the bent form reveals). Rule D (global Q) is the tautological");
println!("baseline and hits {{Q=0}} exactly. The genuine results are B and A:");
println!(" • Rule B reads ONLY the couplings B in the bit frame (no diagonal, no Q) and");
println!(" already produces a genuine BENT quadric of the CORRECT Arf — the right");
println!(" isometry class — but a DIFFERENT member of it (agreement at chance, 128/256).");
println!(" So B+frame reaches the right kind of quadric; the residual gap to the specific");
println!(" Gold {{Q=0}} is alignment within the O(Q)-orbit, i.e. the diagonal framing.");
println!(" • Rule A is the natural Ising completion — the local spin-flip that ADDS the");
println!(" per-coin field q_i to B. It does NOT align B's quadric to {{Q=0}}; it leaves");
println!(" the quadric variety entirely. So the naive local-field assembly fails: the");
println!(" diagonal framing must enter some other way than a per-coin spin-flip gate.");
println!("This sharpens the open question on this bent case: B+frame can reach a");
println!("right-Arf quadric class, but aligning to the specific Gold quadric remains open.");
}