From 03389a11d1770ccb60fed48d9d743a56a9328432 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 22:47:17 -0700 Subject: [PATCH 01/59] Add one-shot checkerboard proof migration --- .../workflows/migrate-checkerboard-alln.yml | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/workflows/migrate-checkerboard-alln.yml diff --git a/.github/workflows/migrate-checkerboard-alln.yml b/.github/workflows/migrate-checkerboard-alln.yml new file mode 100644 index 00000000..a78dc7d7 --- /dev/null +++ b/.github/workflows/migrate-checkerboard-alln.yml @@ -0,0 +1,66 @@ +# Copyright 2026 Dominic Dabish +# Licensed under the Apache License, Version 2.0. + +name: Migrate checkerboard all-n proof + +on: + push: + branches: + - migrate/checkerboard-alln-27a80067 + paths: + - '.github/workflows/migrate-checkerboard-alln.yml' + workflow_dispatch: + +permissions: + contents: write + +jobs: + migrate: + runs-on: ubuntu-latest + steps: + - name: Checkout ProofPlaygrond migration branch + uses: actions/checkout@v6 + with: + ref: migrate/checkerboard-alln-27a80067 + fetch-depth: 0 + + - name: Checkout frozen CRL proof source + uses: actions/checkout@v6 + with: + repository: DomTheDeveloper/crl + ref: 27a800672db58c9fe0c3d02b48c798347fb02fd5 + path: _checkerboard_source + persist-credentials: false + + - name: Copy exact all-n dependency closure + run: | + set -euo pipefail + src='_checkerboard_source/proofs/lean/Checkerboard/Checkerboard' + mkdir -p Checkerboard + for file in \ + Model.lean \ + FiberSums.lean \ + FourCertificate.lean \ + QuadraticWeights.lean \ + PolynomialSums.lean \ + FinPolynomialSums.lean \ + QuadraticCosts.lean \ + AllNUpper.lean \ + N6Base.lean \ + AllNTheorem.lean; do + cp "$src/$file" "Checkerboard/$file" + done + rm -rf _checkerboard_source + + - name: Commit exact migrated proof + run: | + set -euo pipefail + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add Checkerboard + if git diff --cached --quiet; then + echo 'Checkerboard proof files already match the frozen source.' + exit 0 + fi + git commit -m 'Migrate checkerboard all-n proof from frozen CRL commit' + git push origin HEAD:migrate/checkerboard-alln-27a80067 From 61cc6a92672c5d6db52afbf3b56ec4e16a865ad8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 23 Jul 2026 05:47:26 +0000 Subject: [PATCH 02/59] Migrate checkerboard all-n proof from frozen CRL commit --- Checkerboard/AllNTheorem.lean | 29 ++++ Checkerboard/AllNUpper.lean | 168 ++++++++++++++++++++++ Checkerboard/FiberSums.lean | 95 ++++++++++++ Checkerboard/FinPolynomialSums.lean | 72 ++++++++++ Checkerboard/FourCertificate.lean | 216 ++++++++++++++++++++++++++++ Checkerboard/Model.lean | 199 +++++++++++++++++++++++++ Checkerboard/N6Base.lean | 162 +++++++++++++++++++++ Checkerboard/PolynomialSums.lean | 133 +++++++++++++++++ Checkerboard/QuadraticCosts.lean | 138 ++++++++++++++++++ Checkerboard/QuadraticWeights.lean | 141 ++++++++++++++++++ 10 files changed, 1353 insertions(+) create mode 100644 Checkerboard/AllNTheorem.lean create mode 100644 Checkerboard/AllNUpper.lean create mode 100644 Checkerboard/FiberSums.lean create mode 100644 Checkerboard/FinPolynomialSums.lean create mode 100644 Checkerboard/FourCertificate.lean create mode 100644 Checkerboard/Model.lean create mode 100644 Checkerboard/N6Base.lean create mode 100644 Checkerboard/PolynomialSums.lean create mode 100644 Checkerboard/QuadraticCosts.lean create mode 100644 Checkerboard/QuadraticWeights.lean diff --git a/Checkerboard/AllNTheorem.lean b/Checkerboard/AllNTheorem.lean new file mode 100644 index 00000000..18137882 --- /dev/null +++ b/Checkerboard/AllNTheorem.lean @@ -0,0 +1,29 @@ +import Checkerboard.AllNUpper +import Checkerboard.N6Base + +/-! +# Complete all-n checkerboard upper bound +-/ + +namespace Checkerboard + +/-- For every `n ≥ 6`, every no-three-in-line subset of either checkerboard +color class has at most `2n-4` points. -/ +theorem checkerboard_upper_all_n {n parity : ℕ} + (hn : 6 ≤ n) (hp : parity = 0 ∨ parity = 1) + (s : Finset (Point n)) + (hcolor : Monochromatic parity s) (hntil : NoThreeInLine s) : + s.card ≤ 2 * n - 4 := by + by_cases h6 : n = 6 + · subst n + rcases hp with rfl | rfl + · exact n6_zero_upper s hcolor hntil + · exact n6_one_upper s hcolor hntil + · apply checkerboard_upper_from_seven (n := n) (parity := parity) + · omega + · exact hp + · exact s + · exact hcolor + · exact hntil + +end Checkerboard diff --git a/Checkerboard/AllNUpper.lean b/Checkerboard/AllNUpper.lean new file mode 100644 index 00000000..0c0b7e15 --- /dev/null +++ b/Checkerboard/AllNUpper.lean @@ -0,0 +1,168 @@ +import Checkerboard.QuadraticCosts + +/-! +# The general checkerboard upper bound above the final 6×6 base case + +The quadratic line cover proves `|S| ≤ 2n-4` for both checkerboard colors on +every board `n≥7`. The thin color of the 7-board uses a separate exact small +cover; all larger cases use the uniform quadratic family. +-/ + +namespace Checkerboard + +/-- Fat color on every odd board `2m+1`, `m≥3`. -/ +theorem odd_zero_upper {m : ℕ} (hm : 3 ≤ m) + (s : Finset (Point (2 * m + 1))) + (hcolor : Monochromatic 0 s) (hntil : NoThreeInLine s) : + s.card ≤ 4 * m - 2 := by + obtain ⟨hr, hc, hs, hd⟩ := oddQuadratic_nonnegative m 0 + apply card_le_of_fourCertificate (oddQuadraticWeights m 0) + (q := 16 * (m : ℚ) ^ 2) (k := 4 * m - 2) + · positivity + · rw [oddQuadratic_cost_zero] + have hmQ : (3 : ℚ) ≤ m := by exact_mod_cast hm + have hmpos : (0 : ℚ) < m := by nlinarith + have hpoly : 0 < 2 * (m : ℚ) ^ 2 - 6 * m + 1 := by nlinarith + have hprod := mul_pos hmpos hpoly + push_cast + norm_num [show 4 * m - 2 + 1 = 4 * m - 1 by omega] + nlinarith + · exact hr + · exact hc + · exact hs + · exact hd + · intro p + rw [oddQuadratic_coverage m 0 (Or.inl rfl) p.1 (hcolor p)] + · exact hntil + +/-- Thin color on every odd board `2m+1`, `m≥4`. -/ +theorem odd_one_upper {m : ℕ} (hm : 4 ≤ m) + (s : Finset (Point (2 * m + 1))) + (hcolor : Monochromatic 1 s) (hntil : NoThreeInLine s) : + s.card ≤ 4 * m - 2 := by + obtain ⟨hr, hc, hs, hd⟩ := oddQuadratic_nonnegative m 1 + apply card_le_of_fourCertificate (oddQuadraticWeights m 1) + (q := 16 * (m : ℚ) ^ 2) (k := 4 * m - 2) + · positivity + · rw [oddQuadratic_cost_one] + have hmQ : (4 : ℚ) ≤ m := by exact_mod_cast hm + have hmpos : (0 : ℚ) < m := by nlinarith + have hpoly : 0 < 2 * (m : ℚ) ^ 2 - 6 * m - 2 := by nlinarith + have hprod := mul_pos hmpos hpoly + push_cast + norm_num [show 4 * m - 2 + 1 = 4 * m - 1 by omega] + nlinarith + · exact hr + · exact hc + · exact hs + · exact hd + · intro p + rw [oddQuadratic_coverage m 1 (Or.inr rfl) p.1 (hcolor p)] + · exact hntil + +/-- Both colors on every even board `2m`, `m≥4`. -/ +theorem even_upper {m parity : ℕ} (hm : 4 ≤ m) + (hp : parity = 0 ∨ parity = 1) + (s : Finset (Point (2 * m))) + (hcolor : Monochromatic parity s) (hntil : NoThreeInLine s) : + s.card ≤ 4 * m - 4 := by + have hm1 : 1 ≤ m := by omega + have hpCost := hp + obtain ⟨hr, hc, hs, hd⟩ := evenQuadratic_nonnegative m parity hm1 + apply card_le_of_fourCertificate (evenQuadraticWeights m parity) + (q := 4 * ((2 * m : ℚ) - 1) ^ 2) (k := 4 * m - 4) + · positivity + · rcases hpCost with rfl | rfl + · rw [evenQuadratic_cost_zero m hm1] + have hmQ : (4 : ℚ) ≤ m := by exact_mod_cast hm + have hcenter : (0 : ℚ) < 2 * m - 1 := by nlinarith + have hpoly : 0 < 2 * (m : ℚ) ^ 2 - 8 * m + 3 := by nlinarith + have hprod := mul_pos hcenter hpoly + push_cast + norm_num [show 4 * m - 4 + 1 = 4 * m - 3 by omega] + nlinarith + · rw [evenQuadratic_cost_one m hm1] + have hmQ : (4 : ℚ) ≤ m := by exact_mod_cast hm + have hcenter : (0 : ℚ) < 2 * m - 1 := by nlinarith + have hpoly : 0 < 2 * (m : ℚ) ^ 2 - 8 * m + 3 := by nlinarith + have hprod := mul_pos hcenter hpoly + push_cast + norm_num [show 4 * m - 4 + 1 = 4 * m - 3 by omega] + nlinarith + · exact hr + · exact hc + · exact hs + · exact hd + · intro p + rw [evenQuadratic_coverage m parity hp hm1 p.1 (hcolor p)] + · exact hntil + +/-- Small exact cover for the exceptional thin color of the 7-board. -/ +def n7ThinWeights : FourWeights 7 where + row i := if i.1 = 0 ∨ i.1 = 6 then 1 else 0 + column i := if i.1 = 0 ∨ i.1 = 6 then 1 else 0 + sum j := + if j.1 % 2 = 1 then + if Nat.dist j.1 6 = 1 then 2 else if Nat.dist j.1 6 = 3 then 1 else 0 + else 0 + difference j := + if j.1 % 2 = 1 then + if Nat.dist j.1 6 = 1 then 2 else if Nat.dist j.1 6 = 3 then 1 else 0 + else 0 + +private theorem n7Thin_cost : fourCost n7ThinWeights = 32 := by decide +private theorem n7Thin_nonnegative : + (∀ i, 0 ≤ n7ThinWeights.row i) ∧ + (∀ i, 0 ≤ n7ThinWeights.column i) ∧ + (∀ i, 0 ≤ n7ThinWeights.sum i) ∧ + ∀ i, 0 ≤ n7ThinWeights.difference i := by decide +private theorem n7Thin_cover : + ∀ p : Point 7, InColor 1 p → 3 ≤ fourCoverage n7ThinWeights p := by decide + +/-- Exceptional thin-color bound on the 7-board. -/ +theorem n7_one_upper (s : Finset (Point 7)) + (hcolor : Monochromatic 1 s) (hntil : NoThreeInLine s) : s.card ≤ 10 := by + obtain ⟨hr, hc, hs, hd⟩ := n7Thin_nonnegative + apply card_le_of_fourCertificate n7ThinWeights (q := 3) (k := 10) + · norm_num + · rw [n7Thin_cost] + norm_num + · exact hr + · exact hc + · exact hs + · exact hd + · intro p + exact n7Thin_cover p.1 (hcolor p) + · exact hntil + +/-- Fat-color bound on the 7-board. -/ +theorem n7_zero_upper (s : Finset (Point 7)) + (hcolor : Monochromatic 0 s) (hntil : NoThreeInLine s) : s.card ≤ 10 := by + simpa using odd_zero_upper (m := 3) (by decide) s hcolor hntil + +/-- The general bound for all boards `n≥7` and either color. -/ +theorem checkerboard_upper_from_seven {n parity : ℕ} + (hn : 7 ≤ n) (hp : parity = 0 ∨ parity = 1) + (s : Finset (Point n)) + (hcolor : Monochromatic parity s) (hntil : NoThreeInLine s) : + s.card ≤ 2 * n - 4 := by + obtain ⟨m, hEven | hOdd⟩ := n.even_or_odd' + · subst n + have hm : 4 ≤ m := by omega + have h := even_upper hm hp s hcolor hntil + omega + · subst n + have hm : 3 ≤ m := by omega + by_cases hsmall : m = 3 + · subst m + rcases hp with rfl | rfl + · exact n7_zero_upper s hcolor hntil + · exact n7_one_upper s hcolor hntil + · have hm4 : 4 ≤ m := by omega + rcases hp with rfl | rfl + · have h := odd_zero_upper hm s hcolor hntil + omega + · have h := odd_one_upper hm4 s hcolor hntil + omega + +end Checkerboard diff --git a/Checkerboard/FiberSums.lean b/Checkerboard/FiberSums.lean new file mode 100644 index 00000000..c260bae7 --- /dev/null +++ b/Checkerboard/FiberSums.lean @@ -0,0 +1,95 @@ +import Mathlib + +/-! +# Exact finite fiber sums + +Elementary double-counting lemmas used to pass between sums over selected board +points and sums over rows, columns, or diagonal fibers. +-/ + +namespace Checkerboard + +open scoped BigOperators + +section + +variable {α β R : Type*} [DecidableEq α] [DecidableEq β] + +/-- Cardinality of one fiber of `f` inside `s`. -/ +def fiberCard (s : Finset α) (f : α → β) (b : β) : ℕ := + (s.filter fun a => f a = b).card + +@[simp] theorem fiberCard_empty (f : α → β) (b : β) : + fiberCard ∅ f b = 0 := by + simp [fiberCard] + +/-- Every element of a finite set belongs to exactly one fiber. -/ +theorem sum_fiberCard [Fintype β] (s : Finset α) (f : α → β) : + ∑ b : β, fiberCard s f b = s.card := by + classical + induction s using Finset.induction_on with + | empty => simp + | @insert a s ha ih => + simp only [fiberCard, Finset.filter_insert] + simp [ha, ih] + +/-- Weighted double counting over all fibers. -/ +theorem sum_fiberCard_mul [Fintype β] [CommSemiring R] + (s : Finset α) (f : α → β) (g : β → R) : + ∑ b : β, (fiberCard s f b : R) * g b = + ∑ a ∈ s, g (f a) := by + classical + induction s using Finset.induction_on with + | empty => simp [fiberCard] + | @insert a s ha ih => + simp only [fiberCard, Finset.filter_insert] + simp [ha, ih, add_mul] + +/-- Unweighted point count as the sum of all fiber counts, cast to a semiring. -/ +theorem sum_fiberCard_cast [Fintype β] [CommSemiring R] + (s : Finset α) (f : α → β) : + ∑ b : β, (fiberCard s f b : R) = (s.card : R) := by + simpa using sum_fiberCard_mul (R := R) s f (fun _ => 1) + +/-- A pointwise bound on fiber cardinalities sums to a global bound. -/ +theorem card_le_sum_capacity [Fintype β] + (s : Finset α) (f : α → β) (capacity : β → ℕ) + (hcapacity : ∀ b, fiberCard s f b ≤ capacity b) : + s.card ≤ ∑ b, capacity b := by + rw [← sum_fiberCard s f] + exact Finset.sum_le_sum fun b _ => hcapacity b + +/-- Real first moment of natural deficits. -/ +theorem sum_defect_mul [Fintype β] + (s : Finset α) (f : α → β) (capacity : β → ℕ) + (coordinate : β → ℝ) + (hcapacity : ∀ b, fiberCard s f b ≤ capacity b) : + (∑ b, ((capacity b - fiberCard s f b : ℕ) : ℝ) * coordinate b) = + (∑ b, (capacity b : ℝ) * coordinate b) - + ∑ a ∈ s, coordinate (f a) := by + calc + (∑ b, ((capacity b - fiberCard s f b : ℕ) : ℝ) * coordinate b) = + ∑ b, ((capacity b : ℝ) - (fiberCard s f b : ℝ)) * coordinate b := by + apply Finset.sum_congr rfl + intro b _ + rw [Nat.cast_sub (hcapacity b)] + _ = (∑ b, (capacity b : ℝ) * coordinate b) - + ∑ b, (fiberCard s f b : ℝ) * coordinate b := by + simp only [sub_mul, Finset.sum_sub_distrib] + _ = (∑ b, (capacity b : ℝ) * coordinate b) - + ∑ a ∈ s, coordinate (f a) := by + rw [sum_fiberCard_mul] + +/-- Real second moment of natural deficits. -/ +theorem sum_defect_mul_sq [Fintype β] + (s : Finset α) (f : α → β) (capacity : β → ℕ) + (coordinate : β → ℝ) + (hcapacity : ∀ b, fiberCard s f b ≤ capacity b) : + (∑ b, ((capacity b - fiberCard s f b : ℕ) : ℝ) * coordinate b ^ 2) = + (∑ b, (capacity b : ℝ) * coordinate b ^ 2) - + ∑ a ∈ s, coordinate (f a) ^ 2 := by + simpa using sum_defect_mul s f capacity (fun b => coordinate b ^ 2) hcapacity + +end + +end Checkerboard diff --git a/Checkerboard/FinPolynomialSums.lean b/Checkerboard/FinPolynomialSums.lean new file mode 100644 index 00000000..21b5150a --- /dev/null +++ b/Checkerboard/FinPolynomialSums.lean @@ -0,0 +1,72 @@ +import Checkerboard.PolynomialSums + +/-! +# Polynomial sums over `Fin` +-/ + +namespace Checkerboard + +open scoped BigOperators + +/-- Sum of an affine square over `Fin n`. -/ +theorem sum_fin_affine_sq (n : ℕ) (a b : ℚ) : + (∑ i : Fin n, (a * (i.1 : ℚ) + b) ^ 2) = + a ^ 2 * ((n : ℚ) * ((n : ℚ) - 1) * (2 * (n : ℚ) - 1) / 6) + + 2 * a * b * ((n : ℚ) * ((n : ℚ) - 1) / 2) + + (n : ℚ) * b ^ 2 := by + rw [Finset.sum_fin_eq_sum_range] + convert sum_range_affine_sq n a b using 1 + apply Finset.sum_congr rfl + intro i hi + rw [Finset.mem_range] at hi + rw [dif_pos hi] + +/-- Sum of the centered axis-square weights. -/ +theorem axis_quadratic_sum (n : ℕ) : + (∑ i : Fin n, (2 * (i.1 : ℚ) - ((n : ℚ) - 1)) ^ 2) = + (n : ℚ) * ((n : ℚ) ^ 2 - 1) / 3 := by + rw [sum_fin_affine_sq] + ring + +/-- Full sum of a quadratic diagonal cap over `Fin (2N+1)`. -/ +theorem fin_quadratic_cap_sum (N : ℕ) : + (∑ j : Fin (2 * N + 1), + 2 * ((N : ℚ) ^ 2 - ((j.1 : ℚ) - N) ^ 2)) = + 2 * (N : ℚ) * (2 * (N : ℚ) - 1) * (2 * (N : ℚ) + 1) / 3 := by + rw [Finset.sum_fin_eq_sum_range] + convert sum_range_quadratic_cap N using 1 + apply Finset.sum_congr rfl + intro j hj + rw [Finset.mem_range] at hj + rw [dif_pos hj] + +/-- Even-indexed cap sum over `Fin (4m+1)`. -/ +theorem fin_even_quadratic_cap_sum (m : ℕ) : + (∑ j : Fin (4 * m + 1), + if j.1 % 2 = 0 then + 2 * ((2 * m : ℚ) ^ 2 - ((j.1 : ℚ) - 2 * m) ^ 2) + else 0) = + 8 * (m : ℚ) * (2 * (m : ℚ) - 1) * + (2 * (m : ℚ) + 1) / 3 := by + rw [Finset.sum_fin_eq_sum_range] + convert even_quadratic_cap_sum m using 1 + apply Finset.sum_congr rfl + intro j hj + rw [Finset.mem_range] at hj + rw [dif_pos hj] + +/-- Odd-indexed cap sum over `Fin (4m+1)`. -/ +theorem fin_odd_quadratic_cap_sum (m : ℕ) : + (∑ j : Fin (4 * m + 1), + if j.1 % 2 = 1 then + 2 * ((2 * m : ℚ) ^ 2 - ((j.1 : ℚ) - 2 * m) ^ 2) + else 0) = + 4 * (m : ℚ) * (8 * (m : ℚ) ^ 2 + 1) / 3 := by + rw [Finset.sum_fin_eq_sum_range] + convert odd_quadratic_cap_sum m using 1 + apply Finset.sum_congr rfl + intro j hj + rw [Finset.mem_range] at hj + rw [dif_pos hj] + +end Checkerboard diff --git a/Checkerboard/FourCertificate.lean b/Checkerboard/FourCertificate.lean new file mode 100644 index 00000000..c336fe6b --- /dev/null +++ b/Checkerboard/FourCertificate.lean @@ -0,0 +1,216 @@ +import Checkerboard.Model +import Checkerboard.FiberSums + +/-! +# Four-direction rational line-cover certificates + +A no-three-in-line set has capacity at most two on every row, column, sum +diagonal, and difference diagonal. This file packages that observation as a +generic exact rational certificate theorem. +-/ + +namespace Checkerboard + +open scoped BigOperators + +/-- Index of the sum diagonal through a board point. -/ +def sumIndex {n : ℕ} (p : Point n) : Fin (2 * n - 1) := + ⟨p.1.1 + p.2.1, by omega⟩ + +/-- Index of the difference diagonal, shifted to the interval `0, …, 2n-2`. -/ +def differenceIndex {n : ℕ} (p : Point n) : Fin (2 * n - 1) := + ⟨p.1.1 + (n - 1 - p.2.1), by omega⟩ + +/-- Rational weights on the four principal line families. -/ +structure FourWeights (n : ℕ) where + row : Fin n → ℚ + column : Fin n → ℚ + sum : Fin (2 * n - 1) → ℚ + difference : Fin (2 * n - 1) → ℚ + +/-- Coverage of one point by its four incident principal lines. -/ +def fourCoverage {n : ℕ} (w : FourWeights n) (p : Point n) : ℚ := + w.row p.1 + w.column p.2 + w.sum (sumIndex p) + + w.difference (differenceIndex p) + +/-- Capacity-two objective of a four-direction line cover. -/ +def fourCost {n : ℕ} (w : FourWeights n) : ℚ := + 2 * ((∑ i, w.row i) + (∑ i, w.column i) + + (∑ i, w.sum i) + ∑ i, w.difference i) + +private theorem fiberCard_le_two_of_collinear + {n : ℕ} {β : Type*} [DecidableEq β] + {s : Finset (Point n)} (hntil : NoThreeInLine s) + (f : Point n → β) + (hcollinear : ∀ {a b c : Point n}, + f a = f b → f a = f c → determinant a b c = 0) + (value : β) : fiberCard s f value ≤ 2 := by + change (s.filter fun p => f p = value).card ≤ 2 + by_contra h + have hthree : 2 < (s.filter fun p => f p = value).card := + Nat.lt_of_not_ge h + obtain ⟨a, ha, b, hb, c, hc, hab, hac, hbc⟩ := + Finset.two_lt_card.mp hthree + have haS : a ∈ s := (Finset.mem_filter.mp ha).1 + have hbS : b ∈ s := (Finset.mem_filter.mp hb).1 + have hcS : c ∈ s := (Finset.mem_filter.mp hc).1 + have haf : f a = value := (Finset.mem_filter.mp ha).2 + have hbf : f b = value := (Finset.mem_filter.mp hb).2 + have hcf : f c = value := (Finset.mem_filter.mp hc).2 + have hab' : (⟨a, haS⟩ : ↥s) ≠ ⟨b, hbS⟩ := by + intro e + exact hab (congrArg Subtype.val e) + have hac' : (⟨a, haS⟩ : ↥s) ≠ ⟨c, hcS⟩ := by + intro e + exact hac (congrArg Subtype.val e) + have hbc' : (⟨b, hbS⟩ : ↥s) ≠ ⟨c, hcS⟩ := by + intro e + exact hbc (congrArg Subtype.val e) + exact hntil ⟨a, haS⟩ ⟨b, hbS⟩ ⟨c, hcS⟩ hab' hac' hbc' + (hcollinear (haf.trans hbf.symm) (haf.trans hcf.symm)) + +/-- A no-three-in-line set occupies each row at most twice. -/ +theorem rowFiber_le_two {n : ℕ} {s : Finset (Point n)} + (hntil : NoThreeInLine s) (i : Fin n) : + fiberCard s (fun p : Point n => p.1) i ≤ 2 := by + apply fiberCard_le_two_of_collinear hntil (fun p : Point n => p.1) + intro a b c hab hac + have habv : a.1.1 = b.1.1 := congrArg Fin.val hab + have hacv : a.1.1 = c.1.1 := congrArg Fin.val hac + simp [determinant, habv, hacv] + +/-- A no-three-in-line set occupies each column at most twice. -/ +theorem columnFiber_le_two {n : ℕ} {s : Finset (Point n)} + (hntil : NoThreeInLine s) (i : Fin n) : + fiberCard s (fun p : Point n => p.2) i ≤ 2 := by + apply fiberCard_le_two_of_collinear hntil (fun p : Point n => p.2) + intro a b c hab hac + have habv : a.2.1 = b.2.1 := congrArg Fin.val hab + have hacv : a.2.1 = c.2.1 := congrArg Fin.val hac + simp [determinant, habv, hacv] + +/-- A no-three-in-line set occupies each sum diagonal at most twice. -/ +theorem sumFiber_le_two {n : ℕ} {s : Finset (Point n)} + (hntil : NoThreeInLine s) (i : Fin (2 * n - 1)) : + fiberCard s sumIndex i ≤ 2 := by + apply fiberCard_le_two_of_collinear hntil sumIndex + intro a b c hab hac + have habv : a.1.1 + a.2.1 = b.1.1 + b.2.1 := + congrArg Fin.val hab + have hacv : a.1.1 + a.2.1 = c.1.1 + c.2.1 := + congrArg Fin.val hac + have habz : (a.1.1 : ℤ) + a.2.1 = (b.1.1 : ℤ) + b.2.1 := by + exact_mod_cast habv + have hacz : (a.1.1 : ℤ) + a.2.1 = (c.1.1 : ℤ) + c.2.1 := by + exact_mod_cast hacv + have hb : (b.2.1 : ℤ) - a.2.1 = -((b.1.1 : ℤ) - a.1.1) := by + linarith + have hc : (c.2.1 : ℤ) - a.2.1 = -((c.1.1 : ℤ) - a.1.1) := by + linarith + rw [determinant, hb, hc] + ring + +/-- A no-three-in-line set occupies each difference diagonal at most twice. -/ +theorem differenceFiber_le_two {n : ℕ} {s : Finset (Point n)} + (hntil : NoThreeInLine s) (i : Fin (2 * n - 1)) : + fiberCard s differenceIndex i ≤ 2 := by + apply fiberCard_le_two_of_collinear hntil differenceIndex + intro a b c hab hac + have habv : + a.1.1 + (n - 1 - a.2.1) = b.1.1 + (n - 1 - b.2.1) := + congrArg Fin.val hab + have hacv : + a.1.1 + (n - 1 - a.2.1) = c.1.1 + (n - 1 - c.2.1) := + congrArg Fin.val hac + have habn : a.1.1 + b.2.1 = b.1.1 + a.2.1 := by omega + have hacn : a.1.1 + c.2.1 = c.1.1 + a.2.1 := by omega + have habz : (a.1.1 : ℤ) + b.2.1 = (b.1.1 : ℤ) + a.2.1 := by + exact_mod_cast habn + have hacz : (a.1.1 : ℤ) + c.2.1 = (c.1.1 : ℤ) + a.2.1 := by + exact_mod_cast hacn + have hb : (b.2.1 : ℤ) - a.2.1 = (b.1.1 : ℤ) - a.1.1 := by + linarith + have hc : (c.2.1 : ℤ) - a.2.1 = (c.1.1 : ℤ) - a.1.1 := by + linarith + rw [determinant, hb, hc] + ring + +private theorem weightedFibers_le_two + {α β : Type*} [DecidableEq α] [DecidableEq β] [Fintype β] + (s : Finset α) (f : α → β) (weight : β → ℚ) + (hweight : ∀ i, 0 ≤ weight i) + (hcard : ∀ i, fiberCard s f i ≤ 2) : + (∑ i, (fiberCard s f i : ℚ) * weight i) ≤ + 2 * ∑ i, weight i := by + rw [Finset.mul_sum] + apply Finset.sum_le_sum + intro i _ + have hi : (fiberCard s f i : ℚ) ≤ 2 := by + exact_mod_cast hcard i + nlinarith [hweight i] + +/-- Exact capacity-two upper bound supplied by any nonnegative rational cover. -/ +theorem fourCertificate_bound {n : ℕ} {s : Finset (Point n)} + (w : FourWeights n) + (hrow : ∀ i, 0 ≤ w.row i) + (hcolumn : ∀ i, 0 ≤ w.column i) + (hsum : ∀ i, 0 ≤ w.sum i) + (hdifference : ∀ i, 0 ≤ w.difference i) + (hntil : NoThreeInLine s) : + (∑ p ∈ s, fourCoverage w p) ≤ fourCost w := by + have hr : (∑ p ∈ s, w.row p.1) ≤ 2 * ∑ i, w.row i := by + rw [← sum_fiberCard_mul (R := ℚ) s (fun p : Point n => p.1) w.row] + exact weightedFibers_le_two s (fun p : Point n => p.1) w.row hrow + (rowFiber_le_two hntil) + have hc : (∑ p ∈ s, w.column p.2) ≤ 2 * ∑ i, w.column i := by + rw [← sum_fiberCard_mul (R := ℚ) s (fun p : Point n => p.2) w.column] + exact weightedFibers_le_two s (fun p : Point n => p.2) w.column hcolumn + (columnFiber_le_two hntil) + have hs : (∑ p ∈ s, w.sum (sumIndex p)) ≤ 2 * ∑ i, w.sum i := by + rw [← sum_fiberCard_mul (R := ℚ) s sumIndex w.sum] + exact weightedFibers_le_two s sumIndex w.sum hsum + (sumFiber_le_two hntil) + have hd : (∑ p ∈ s, w.difference (differenceIndex p)) ≤ + 2 * ∑ i, w.difference i := by + rw [← sum_fiberCard_mul (R := ℚ) s differenceIndex w.difference] + exact weightedFibers_le_two s differenceIndex w.difference hdifference + (differenceFiber_le_two hntil) + calc + (∑ p ∈ s, fourCoverage w p) = + (∑ p ∈ s, w.row p.1) + (∑ p ∈ s, w.column p.2) + + (∑ p ∈ s, w.sum (sumIndex p)) + + ∑ p ∈ s, w.difference (differenceIndex p) := by + simp [fourCoverage, Finset.sum_add_distrib, add_assoc] + _ ≤ 2 * (∑ i, w.row i) + 2 * (∑ i, w.column i) + + 2 * (∑ i, w.sum i) + 2 * ∑ i, w.difference i := by + linarith + _ = fourCost w := by + simp [fourCost] + ring + +/-- A positive cover whose objective is below `q(k+1)` proves `|s| ≤ k`. -/ +theorem card_le_of_fourCertificate {n k : ℕ} {q : ℚ} + {s : Finset (Point n)} (w : FourWeights n) + (hq : 0 < q) + (hcost : fourCost w < q * (k + 1)) + (hrow : ∀ i, 0 ≤ w.row i) + (hcolumn : ∀ i, 0 ≤ w.column i) + (hsum : ∀ i, 0 ≤ w.sum i) + (hdifference : ∀ i, 0 ≤ w.difference i) + (hcover : ∀ p : ↥s, q ≤ fourCoverage w p.1) + (hntil : NoThreeInLine s) : s.card ≤ k := by + have hlower : q * (s.card : ℚ) ≤ ∑ p ∈ s, fourCoverage w p := by + calc + q * (s.card : ℚ) = ∑ _p ∈ s, q := by simp [mul_comm] + _ ≤ ∑ p ∈ s, fourCoverage w p := by + apply Finset.sum_le_sum + intro p hp + exact hcover ⟨p, hp⟩ + have hupper := fourCertificate_bound w hrow hcolumn hsum hdifference hntil + have hltQ : (s.card : ℚ) < k + 1 := by + nlinarith + have hltN : s.card < k + 1 := by + exact_mod_cast hltQ + omega + +end Checkerboard diff --git a/Checkerboard/Model.lean b/Checkerboard/Model.lean new file mode 100644 index 00000000..8cf03ca7 --- /dev/null +++ b/Checkerboard/Model.lean @@ -0,0 +1,199 @@ +import Mathlib + +/-! +# Finite checkerboard no-three-in-line model + +This file gives a self-contained finite model of monochromatic checkerboard +point sets, Euclidean collinearity, the four principal line families, and a +kernel-checked weighted line-cover bound. +-/ + +namespace Checkerboard + +abbrev Point (n : ℕ) := Fin n × Fin n + +/-- Twice the signed Euclidean area of the triangle `a b c`. -/ +def determinant {n : ℕ} (a b c : Point n) : ℤ := + ((b.1.1 : ℤ) - (a.1.1 : ℤ)) * ((c.2.1 : ℤ) - (a.2.1 : ℤ)) - + ((b.2.1 : ℤ) - (a.2.1 : ℤ)) * ((c.1.1 : ℤ) - (a.1.1 : ℤ)) + +/-- The checkerboard color class indexed by `parity mod 2`. -/ +def InColor {n : ℕ} (parity : ℕ) (p : Point n) : Prop := + (p.1.1 + p.2.1) % 2 = parity % 2 + +/-- Every point of `s` lies in one checkerboard color class. -/ +def Monochromatic {n : ℕ} (parity : ℕ) (s : Finset (Point n)) : Prop := + ∀ p : ↥s, InColor parity p.1 + +/-- No three distinct selected points are collinear. Quantifying over the +subtype `↥s` makes direct checking of explicit constructions finite and small. -/ +def NoThreeInLine {n : ℕ} (s : Finset (Point n)) : Prop := + ∀ a b c : ↥s, a ≠ b → a ≠ c → b ≠ c → + determinant a.1 b.1 c.1 ≠ 0 + +/-- A convenient exact-maximum statement, avoiding any dependence on a chosen +implementation of `argmax` over all subsets. -/ +def IsExactMaximum (n parity k : ℕ) : Prop := + (∃ s : Finset (Point n), + Monochromatic parity s ∧ NoThreeInLine s ∧ s.card = k) ∧ + ∀ s : Finset (Point n), + Monochromatic parity s → NoThreeInLine s → s.card ≤ k + +inductive LineFamily + | row + | column + | sum + | difference + deriving DecidableEq, Fintype, Repr + +/-- Principal rows, columns, and slope `±1` diagonals. The second component is +an index in `0, …, 2n-2`; unused row/column indices simply describe empty lines. -/ +abbrev PrincipalLine (n : ℕ) := LineFamily × Fin (2 * n - 1) + +/-- Integer line coordinate. Difference diagonals are shifted by `n-1`, so all +four families use nonnegative indices. -/ +def lineValue {n : ℕ} (family : LineFamily) (p : Point n) : ℤ := + match family with + | .row => p.1.1 + | .column => p.2.1 + | .sum => p.1.1 + p.2.1 + | .difference => (p.1.1 : ℤ) - (p.2.1 : ℤ) + (n - 1 : ℕ) + +/-- Incidence with a principal line. -/ +def OnLine {n : ℕ} (line : PrincipalLine n) (p : Point n) : Prop := + lineValue line.1 p = line.2.1 + +instance {n : ℕ} (line : PrincipalLine n) : DecidablePred (OnLine line) := + fun _ => inferInstance + +/-- Three points on one principal line are Euclidean-collinear. -/ +theorem principal_collinear {n : ℕ} {line : PrincipalLine n} + {a b c : Point n} (ha : OnLine line a) (hb : OnLine line b) + (hc : OnLine line c) : determinant a b c = 0 := by + rcases line with ⟨family, index⟩ + cases family with + | row => + simp only [OnLine, lineValue] at ha hb hc + simp [determinant, ha, hb, hc] + | column => + simp only [OnLine, lineValue] at ha hb hc + simp [determinant, ha, hb, hc] + | sum => + simp only [OnLine, lineValue] at ha hb hc + have hba : ((b.2.1 : ℤ) - (a.2.1 : ℤ)) = + -((b.1.1 : ℤ) - (a.1.1 : ℤ)) := by + linarith + have hca : ((c.2.1 : ℤ) - (a.2.1 : ℤ)) = + -((c.1.1 : ℤ) - (a.1.1 : ℤ)) := by + linarith + rw [determinant, hba, hca] + ring + | difference => + simp only [OnLine, lineValue] at ha hb hc + have hba : ((b.2.1 : ℤ) - (a.2.1 : ℤ)) = + ((b.1.1 : ℤ) - (a.1.1 : ℤ)) := by + linarith + have hca : ((c.2.1 : ℤ) - (a.2.1 : ℤ)) = + ((c.1.1 : ℤ) - (a.1.1 : ℤ)) := by + linarith + rw [determinant, hba, hca] + ring + +/-- A no-three-in-line set occupies every principal line at most twice. -/ +theorem principalLine_card_le_two {n : ℕ} {s : Finset (Point n)} + (hntil : NoThreeInLine s) (line : PrincipalLine n) : + (s.filter (OnLine line)).card ≤ 2 := by + by_contra h + have hthree : 2 < (s.filter (OnLine line)).card := Nat.lt_of_not_ge h + obtain ⟨a, ha, b, hb, c, hc, hab, hac, hbc⟩ := + Finset.two_lt_card.mp hthree + have haS : a ∈ s := (Finset.mem_filter.mp ha).1 + have hbS : b ∈ s := (Finset.mem_filter.mp hb).1 + have hcS : c ∈ s := (Finset.mem_filter.mp hc).1 + have haL : OnLine line a := (Finset.mem_filter.mp ha).2 + have hbL : OnLine line b := (Finset.mem_filter.mp hb).2 + have hcL : OnLine line c := (Finset.mem_filter.mp hc).2 + have hab' : (⟨a, haS⟩ : ↥s) ≠ ⟨b, hbS⟩ := by + intro e + exact hab (congrArg Subtype.val e) + have hac' : (⟨a, haS⟩ : ↥s) ≠ ⟨c, hcS⟩ := by + intro e + exact hac (congrArg Subtype.val e) + have hbc' : (⟨b, hbS⟩ : ↥s) ≠ ⟨c, hcS⟩ := by + intro e + exact hbc (congrArg Subtype.val e) + exact hntil ⟨a, haS⟩ ⟨b, hbS⟩ ⟨c, hcS⟩ hab' hac' hbc' + (principal_collinear haL hbL hcL) + +/-- Weighted coverage of a point by all principal lines. -/ +def coverage {n : ℕ} (weight : PrincipalLine n → ℕ) (p : Point n) : ℕ := + ∑ line : PrincipalLine n, if OnLine line p then weight line else 0 + +/-- Twice the total line weight, the capacity-two dual objective. -/ +def certificateCost {n : ℕ} (weight : PrincipalLine n → ℕ) : ℕ := + ∑ line : PrincipalLine n, 2 * weight line + +private theorem sum_indicator_eq_card_filter {α : Type*} [DecidableEq α] + (s : Finset α) (P : α → Prop) [DecidablePred P] (w : ℕ) : + (∑ a ∈ s, if P a then w else 0) = (s.filter P).card * w := by + induction s using Finset.induction_on with + | empty => simp + | @insert a s ha ih => + by_cases hP : P a <;> + simp [ha, hP, ih, Nat.add_mul] + +private theorem double_count {n : ℕ} (s : Finset (Point n)) + (weight : PrincipalLine n → ℕ) : + (∑ p ∈ s, coverage weight p) = + ∑ line : PrincipalLine n, (s.filter (OnLine line)).card * weight line := by + calc + (∑ p ∈ s, coverage weight p) = + ∑ p ∈ s, ∑ line : PrincipalLine n, + if OnLine line p then weight line else 0 := by rfl + _ = ∑ line : PrincipalLine n, ∑ p ∈ s, + if OnLine line p then weight line else 0 := by + rw [Finset.sum_comm] + _ = ∑ line : PrincipalLine n, + (s.filter (OnLine line)).card * weight line := by + apply Finset.sum_congr rfl + intro line _ + exact sum_indicator_eq_card_filter s (OnLine line) (weight line) + +/-- Exact weighted line-cover inequality. -/ +theorem certificate_bound {n q : ℕ} {s : Finset (Point n)} + (weight : PrincipalLine n → ℕ) + (hcover : ∀ p : ↥s, q ≤ coverage weight p.1) + (hntil : NoThreeInLine s) : + q * s.card ≤ certificateCost weight := by + have hpoint : (∑ p ∈ s, q) ≤ ∑ p ∈ s, coverage weight p := by + apply Finset.sum_le_sum + intro p hp + exact hcover ⟨p, hp⟩ + have hline : + (∑ line : PrincipalLine n, + (s.filter (OnLine line)).card * weight line) ≤ + certificateCost weight := by + apply Finset.sum_le_sum + intro line _ + exact Nat.mul_le_mul_right (weight line) + (principalLine_card_le_two hntil line) + calc + q * s.card = ∑ _p ∈ s, q := by simp [Nat.mul_comm] + _ ≤ ∑ p ∈ s, coverage weight p := hpoint + _ = ∑ line : PrincipalLine n, + (s.filter (OnLine line)).card * weight line := double_count s weight + _ ≤ certificateCost weight := hline + +/-- A strict integral dual objective gives a cardinality upper bound. -/ +theorem card_le_of_certificate {n parity q k : ℕ} {s : Finset (Point n)} + (weight : PrincipalLine n → ℕ) (hq : 0 < q) + (hcost : certificateCost weight < q * (k + 1)) + (hglobal : ∀ p : Point n, InColor parity p → q ≤ coverage weight p) + (hcolor : Monochromatic parity s) (hntil : NoThreeInLine s) : + s.card ≤ k := by + have hb := certificate_bound weight (fun p => hglobal p.1 (hcolor p)) hntil + have hmul : q * s.card < q * (k + 1) := lt_of_le_of_lt hb hcost + have hlt : s.card < k + 1 := (Nat.mul_lt_mul_left hq).mp hmul + omega + +end Checkerboard diff --git a/Checkerboard/N6Base.lean b/Checkerboard/N6Base.lean new file mode 100644 index 00000000..9e392055 --- /dev/null +++ b/Checkerboard/N6Base.lean @@ -0,0 +1,162 @@ +import Checkerboard.FourCertificate + +/-! +# The final 6×6 base cases + +The uniform quadratic cover is sharp at value nine on the 6-board, so an +integrality argument is required. Each color class has eighteen points. We +transport an arbitrary monochromatic set to eighteen Boolean variables, and +`bv_decide` checks the finite statement that row, column, and slope `±1` +capacities already force at most eight selected points. +-/ + +namespace Checkerboard + +/-- Enumeration of the fat color class of the 6-board. -/ +def n6p0Point : Fin 18 → Point 6 := ![ + ((0 : Fin 6), (0 : Fin 6)), ((0 : Fin 6), (2 : Fin 6)), + ((0 : Fin 6), (4 : Fin 6)), ((1 : Fin 6), (1 : Fin 6)), + ((1 : Fin 6), (3 : Fin 6)), ((1 : Fin 6), (5 : Fin 6)), + ((2 : Fin 6), (0 : Fin 6)), ((2 : Fin 6), (2 : Fin 6)), + ((2 : Fin 6), (4 : Fin 6)), ((3 : Fin 6), (1 : Fin 6)), + ((3 : Fin 6), (3 : Fin 6)), ((3 : Fin 6), (5 : Fin 6)), + ((4 : Fin 6), (0 : Fin 6)), ((4 : Fin 6), (2 : Fin 6)), + ((4 : Fin 6), (4 : Fin 6)), ((5 : Fin 6), (1 : Fin 6)), + ((5 : Fin 6), (3 : Fin 6)), ((5 : Fin 6), (5 : Fin 6))] + +/-- Enumeration of the thin color class of the 6-board. -/ +def n6p1Point : Fin 18 → Point 6 := ![ + ((0 : Fin 6), (1 : Fin 6)), ((0 : Fin 6), (3 : Fin 6)), + ((0 : Fin 6), (5 : Fin 6)), ((1 : Fin 6), (0 : Fin 6)), + ((1 : Fin 6), (2 : Fin 6)), ((1 : Fin 6), (4 : Fin 6)), + ((2 : Fin 6), (1 : Fin 6)), ((2 : Fin 6), (3 : Fin 6)), + ((2 : Fin 6), (5 : Fin 6)), ((3 : Fin 6), (0 : Fin 6)), + ((3 : Fin 6), (2 : Fin 6)), ((3 : Fin 6), (4 : Fin 6)), + ((4 : Fin 6), (1 : Fin 6)), ((4 : Fin 6), (3 : Fin 6)), + ((4 : Fin 6), (5 : Fin 6)), ((5 : Fin 6), (0 : Fin 6)), + ((5 : Fin 6), (2 : Fin 6)), ((5 : Fin 6), (4 : Fin 6))] + +private theorem n6p0_injective : Function.Injective n6p0Point := by decide +private theorem n6p1_injective : Function.Injective n6p1Point := by decide + +private theorem n6p0_surjective : + ∀ p : Point 6, InColor 0 p → ∃ i, n6p0Point i = p := by decide + +private theorem n6p1_surjective : + ∀ p : Point 6, InColor 1 p → ∃ i, n6p1Point i = p := by decide + +private def chosenIndices (point : Fin 18 → Point 6) + (s : Finset (Point 6)) : Finset (Fin 18) := + Finset.univ.filter fun i => point i ∈ s + +private def chosenOnLine (point : Fin 18 → Point 6) + (s : Finset (Point 6)) (line : PrincipalLine 6) : Finset (Fin 18) := + Finset.univ.filter fun i => point i ∈ s ∧ OnLine line (point i) + +private theorem chosenIndices_image + {parity : ℕ} (point : Fin 18 → Point 6) + (hsurj : ∀ p : Point 6, InColor parity p → ∃ i, point i = p) + (s : Finset (Point 6)) (hcolor : Monochromatic parity s) : + (chosenIndices point s).image point = s := by + ext p + constructor + · intro hp + rcases Finset.mem_image.mp hp with ⟨i, hi, rfl⟩ + exact (Finset.mem_filter.mp hi).2 + · intro hp + obtain ⟨i, hi⟩ := hsurj p (hcolor ⟨p, hp⟩) + subst p + apply Finset.mem_image.mpr + exact ⟨i, Finset.mem_filter.mpr ⟨Finset.mem_univ _, hp⟩, rfl⟩ + +private theorem chosenOnLine_image + {parity : ℕ} (point : Fin 18 → Point 6) + (hsurj : ∀ p : Point 6, InColor parity p → ∃ i, point i = p) + (s : Finset (Point 6)) (hcolor : Monochromatic parity s) + (line : PrincipalLine 6) : + (chosenOnLine point s line).image point = s.filter (OnLine line) := by + ext p + constructor + · intro hp + rcases Finset.mem_image.mp hp with ⟨i, hi, rfl⟩ + exact Finset.mem_filter.mpr (Finset.mem_filter.mp hi).2 + · intro hp + have hpS := (Finset.mem_filter.mp hp).1 + have hpL := (Finset.mem_filter.mp hp).2 + obtain ⟨i, hi⟩ := hsurj p (hcolor ⟨p, hpS⟩) + subst p + apply Finset.mem_image.mpr + exact ⟨i, Finset.mem_filter.mpr + ⟨Finset.mem_univ _, ⟨hpS, hpL⟩⟩, rfl⟩ + +private theorem upper_of_boolean_certificate + {parity : ℕ} (point : Fin 18 → Point 6) + (hinj : Function.Injective point) + (hsurj : ∀ p : Point 6, InColor parity p → ∃ i, point i = p) + (hfinite : ∀ x : Fin 18 → Bool, + (∀ line : PrincipalLine 6, + (Finset.univ.filter fun i => x i = true ∧ OnLine line (point i)).card ≤ 2) → + (Finset.univ.filter fun i => x i = true).card ≤ 8) + (s : Finset (Point 6)) + (hcolor : Monochromatic parity s) (hntil : NoThreeInLine s) : + s.card ≤ 8 := by + let x : Fin 18 → Bool := fun i => decide (point i ∈ s) + have hline : ∀ line : PrincipalLine 6, + (Finset.univ.filter fun i => x i = true ∧ OnLine line (point i)).card ≤ 2 := by + intro line + have himage := chosenOnLine_image point hsurj s hcolor line + have hcardImage := Finset.card_image_of_injective + (chosenOnLine point s line) hinj + have hchosen : + (chosenOnLine point s line).card = (s.filter (OnLine line)).card := by + calc + (chosenOnLine point s line).card = + ((chosenOnLine point s line).image point).card := hcardImage.symm + _ = (s.filter (OnLine line)).card := congrArg Finset.card himage + have heq : + (Finset.univ.filter fun i => x i = true ∧ OnLine line (point i)).card = + (s.filter (OnLine line)).card := by + simpa [x, chosenOnLine] using hchosen + rw [heq] + exact principalLine_card_le_two hntil line + have hbool := hfinite x hline + have himage := chosenIndices_image point hsurj s hcolor + have hcardImage := Finset.card_image_of_injective (chosenIndices point s) hinj + have hchosen : (chosenIndices point s).card = s.card := by + calc + (chosenIndices point s).card = ((chosenIndices point s).image point).card := + hcardImage.symm + _ = s.card := congrArg Finset.card himage + have heq : (Finset.univ.filter fun i => x i = true).card = s.card := by + simpa [x, chosenIndices] using hchosen + rwa [heq] at hbool + +private theorem n6p0_boolean_bound : + ∀ x : Fin 18 → Bool, + (∀ line : PrincipalLine 6, + (Finset.univ.filter fun i => + x i = true ∧ OnLine line (n6p0Point i)).card ≤ 2) → + (Finset.univ.filter fun i => x i = true).card ≤ 8 := by + bv_decide + +private theorem n6p1_boolean_bound : + ∀ x : Fin 18 → Bool, + (∀ line : PrincipalLine 6, + (Finset.univ.filter fun i => + x i = true ∧ OnLine line (n6p1Point i)).card ≤ 2) → + (Finset.univ.filter fun i => x i = true).card ≤ 8 := by + bv_decide + +/-- `D_mono(6,0) ≤ 8`. -/ +theorem n6_zero_upper (s : Finset (Point 6)) + (hcolor : Monochromatic 0 s) (hntil : NoThreeInLine s) : s.card ≤ 8 := by + exact upper_of_boolean_certificate n6p0Point n6p0_injective n6p0_surjective + n6p0_boolean_bound s hcolor hntil + +/-- `D_mono(6,1) ≤ 8`. -/ +theorem n6_one_upper (s : Finset (Point 6)) + (hcolor : Monochromatic 1 s) (hntil : NoThreeInLine s) : s.card ≤ 8 := by + exact upper_of_boolean_certificate n6p1Point n6p1_injective n6p1_surjective + n6p1_boolean_bound s hcolor hntil + +end Checkerboard diff --git a/Checkerboard/PolynomialSums.lean b/Checkerboard/PolynomialSums.lean new file mode 100644 index 00000000..232142f2 --- /dev/null +++ b/Checkerboard/PolynomialSums.lean @@ -0,0 +1,133 @@ +import Mathlib + +/-! +# Exact polynomial sums used by the all-n line cover +-/ + +namespace Checkerboard + +open scoped BigOperators + +/-- Sum of an affine square over `0, …, n-1`. -/ +theorem sum_range_affine_sq (n : ℕ) (a b : ℚ) : + (∑ i ∈ Finset.range n, (a * (i : ℚ) + b) ^ 2) = + a ^ 2 * ((n : ℚ) * ((n : ℚ) - 1) * (2 * (n : ℚ) - 1) / 6) + + 2 * a * b * ((n : ℚ) * ((n : ℚ) - 1) / 2) + + (n : ℚ) * b ^ 2 := by + induction n with + | zero => norm_num + | succ n ih => + rw [Finset.sum_range_succ, ih] + push_cast + ring + +/-- Sum of a quadratic cap centered at `N` on the full interval `0, …, 2N`. -/ +theorem sum_range_quadratic_cap (N : ℕ) : + (∑ j ∈ Finset.range (2 * N + 1), + 2 * ((N : ℚ) ^ 2 - ((j : ℚ) - N) ^ 2)) = + 2 * (N : ℚ) * (2 * (N : ℚ) - 1) * (2 * (N : ℚ) + 1) / 3 := by + have h := sum_range_affine_sq (2 * N + 1) (1 : ℚ) (-(N : ℚ)) + push_cast at h ⊢ + calc + (∑ j ∈ Finset.range (2 * N + 1), + 2 * ((N : ℚ) ^ 2 - ((j : ℚ) - N) ^ 2)) = + 2 * ((2 * (N : ℚ) + 1) * (N : ℚ) ^ 2 - + ∑ j ∈ Finset.range (2 * N + 1), + ((j : ℚ) - N) ^ 2) := by + simp only [Finset.sum_sub_distrib, Finset.sum_mul, + Finset.sum_const, Finset.card_range, nsmul_eq_mul] + ring + _ = 2 * (N : ℚ) * (2 * (N : ℚ) - 1) * + (2 * (N : ℚ) + 1) / 3 := by + rw [h] + ring + +/-- Extract the even-indexed terms from a range of even length. -/ +theorem sum_range_even_terms (k : ℕ) (f : ℕ → ℚ) : + (∑ j ∈ Finset.range (2 * k), if j % 2 = 0 then f j else 0) = + ∑ r ∈ Finset.range k, f (2 * r) := by + induction k with + | zero => simp + | succ k ih => + simp only [Nat.mul_succ, Finset.sum_range_succ] + rw [ih] + norm_num [Nat.add_mod, Nat.mul_mod] + +/-- Extract the odd-indexed terms from a range of even length. -/ +theorem sum_range_odd_terms (k : ℕ) (f : ℕ → ℚ) : + (∑ j ∈ Finset.range (2 * k), if j % 2 = 1 then f j else 0) = + ∑ r ∈ Finset.range k, f (2 * r + 1) := by + induction k with + | zero => simp + | succ k ih => + simp only [Nat.mul_succ, Finset.sum_range_succ] + rw [ih] + norm_num [Nat.add_mod, Nat.mul_mod] + +/-- Even-indexed terms in a range ending at an even index. -/ +theorem sum_range_even_terms_succ (k : ℕ) (f : ℕ → ℚ) : + (∑ j ∈ Finset.range (2 * k + 1), if j % 2 = 0 then f j else 0) = + ∑ r ∈ Finset.range (k + 1), f (2 * r) := by + rw [Finset.sum_range_succ, sum_range_even_terms, Finset.sum_range_succ] + norm_num [Nat.add_mod, Nat.mul_mod] + +/-- Odd-indexed terms in a range ending at an even index. -/ +theorem sum_range_odd_terms_succ (k : ℕ) (f : ℕ → ℚ) : + (∑ j ∈ Finset.range (2 * k + 1), if j % 2 = 1 then f j else 0) = + ∑ r ∈ Finset.range k, f (2 * r + 1) := by + rw [Finset.sum_range_succ, sum_range_odd_terms] + norm_num [Nat.add_mod, Nat.mul_mod] + +/-- Even offsets in the quadratic cap on `-2m, …, 2m`. -/ +theorem even_quadratic_cap_sum (m : ℕ) : + (∑ j ∈ Finset.range (4 * m + 1), + if j % 2 = 0 then + 2 * ((2 * m : ℚ) ^ 2 - ((j : ℚ) - 2 * m) ^ 2) + else 0) = + 8 * (m : ℚ) * (2 * (m : ℚ) - 1) * + (2 * (m : ℚ) + 1) / 3 := by + have h := sum_range_quadratic_cap m + rw [show 4 * m + 1 = 2 * (2 * m) + 1 by omega, + sum_range_even_terms_succ] + push_cast + convert (show + (4 : ℚ) * + (∑ r ∈ Finset.range (2 * m + 1), + 2 * ((m : ℚ) ^ 2 - ((r : ℚ) - m) ^ 2)) = + 8 * (m : ℚ) * (2 * (m : ℚ) - 1) * + (2 * (m : ℚ) + 1) / 3 by rw [h]; ring) using 1 + · apply Finset.sum_congr rfl + intro r hr + rw [dif_pos] + · push_cast + ring + · omega + +/-- Odd offsets in the quadratic cap on `-2m, …, 2m`. -/ +theorem odd_quadratic_cap_sum (m : ℕ) : + (∑ j ∈ Finset.range (4 * m + 1), + if j % 2 = 1 then + 2 * ((2 * m : ℚ) ^ 2 - ((j : ℚ) - 2 * m) ^ 2) + else 0) = + 4 * (m : ℚ) * (8 * (m : ℚ) ^ 2 + 1) / 3 := by + rw [show 4 * m + 1 = 2 * (2 * m) + 1 by omega, + sum_range_odd_terms_succ] + have h := sum_range_affine_sq (2 * m) (2 : ℚ) + (1 - 2 * (m : ℚ)) + push_cast at h ⊢ + calc + (∑ r ∈ Finset.range (2 * m), + 2 * ((2 * (m : ℚ)) ^ 2 - + (((2 * r + 1 : ℕ) : ℚ) - 2 * (m : ℚ)) ^ 2)) = + 2 * ((2 * (m : ℚ)) * (2 * (m : ℚ)) ^ 2 - + ∑ r ∈ Finset.range (2 * m), + (2 * (r : ℚ) + (1 - 2 * (m : ℚ))) ^ 2) := by + push_cast + simp only [Finset.sum_sub_distrib, Finset.sum_mul, + Finset.sum_const, Finset.card_range, nsmul_eq_mul] + ring + _ = 4 * (m : ℚ) * (8 * (m : ℚ) ^ 2 + 1) / 3 := by + rw [h] + ring + +end Checkerboard diff --git a/Checkerboard/QuadraticCosts.lean b/Checkerboard/QuadraticCosts.lean new file mode 100644 index 00000000..f3f31668 --- /dev/null +++ b/Checkerboard/QuadraticCosts.lean @@ -0,0 +1,138 @@ +import Checkerboard.QuadraticWeights +import Checkerboard.FinPolynomialSums + +/-! +# Exact objectives of the quadratic line covers +-/ + +namespace Checkerboard + +open scoped BigOperators + +private def oddCapExpr (m : ℕ) {k : ℕ} (j : Fin k) : ℚ := + 2 * ((2 * m : ℚ) ^ 2 - ((j.1 : ℚ) - 2 * m) ^ 2) + +private def evenCapExpr (m : ℕ) {k : ℕ} (j : Fin k) : ℚ := + 2 * (((2 * m : ℚ) - 1) ^ 2 - + ((j.1 : ℚ) - ((2 * m : ℚ) - 1)) ^ 2) + +private theorem odd_axis_sum (m : ℕ) : + (∑ i : Fin (2 * m + 1), (2 * (i.1 : ℚ) - 2 * m) ^ 2) = + 4 * (m : ℚ) * ((m : ℚ) + 1) * (2 * (m : ℚ) + 1) / 3 := by + have h := axis_quadratic_sum (2 * m + 1) + push_cast at h ⊢ + convert h using 1 <;> ring + +private theorem even_axis_sum (m : ℕ) : + (∑ i : Fin (2 * m), + (2 * (i.1 : ℚ) - ((2 * m : ℚ) - 1)) ^ 2) = + 2 * (m : ℚ) * (4 * (m : ℚ) ^ 2 - 1) / 3 := by + have h := axis_quadratic_sum (2 * m) + push_cast at h ⊢ + convert h using 1 <;> ring + +private theorem odd_even_diag_sum (m : ℕ) : + (∑ j : Fin (2 * (2 * m + 1) - 1), + if j.1 % 2 = 0 then oddCapExpr m j else 0) = + 8 * (m : ℚ) * (2 * (m : ℚ) - 1) * + (2 * (m : ℚ) + 1) / 3 := by + have hdim : 2 * (2 * m + 1) - 1 = 4 * m + 1 := by omega + rw [hdim] + simpa [oddCapExpr] using fin_even_quadratic_cap_sum m + +private theorem odd_odd_diag_sum (m : ℕ) : + (∑ j : Fin (2 * (2 * m + 1) - 1), + if j.1 % 2 = 1 then oddCapExpr m j else 0) = + 4 * (m : ℚ) * (8 * (m : ℚ) ^ 2 + 1) / 3 := by + have hdim : 2 * (2 * m + 1) - 1 = 4 * m + 1 := by omega + rw [hdim] + simpa [oddCapExpr] using fin_odd_quadratic_cap_sum m + +private theorem parity_partition {k : ℕ} (f : Fin k → ℚ) : + (∑ j : Fin k, if j.1 % 2 = 0 then f j else 0) + + (∑ j : Fin k, if j.1 % 2 = 1 then f j else 0) = + ∑ j : Fin k, f j := by + rw [← Finset.sum_add_distrib] + apply Finset.sum_congr rfl + intro j _ + rcases Nat.mod_two_eq_zero_or_one j.1 with h | h <;> simp [h] + +private theorem even_all_diag_sum (m : ℕ) (hm : 1 ≤ m) : + (∑ j : Fin (2 * (2 * m) - 1), evenCapExpr m j) = + 2 * ((2 * m : ℚ) - 1) * (4 * (m : ℚ) - 3) * + (4 * (m : ℚ) - 1) / 3 := by + have hdim : 2 * (2 * m) - 1 = 2 * (2 * m - 1) + 1 := by omega + rw [hdim] + have h := fin_quadratic_cap_sum (2 * m - 1) + push_cast at h ⊢ + simpa [evenCapExpr] using h + +/-- Exact objective for the fat color of an odd board. -/ +theorem oddQuadratic_cost_zero (m : ℕ) : + fourCost (oddQuadraticWeights m 0) = + 16 * (m : ℚ) * (10 * (m : ℚ) ^ 2 + 3 * (m : ℚ) - 1) / 3 := by + change 2 * ( + (∑ i : Fin (2 * m + 1), (2 * (i.1 : ℚ) - 2 * m) ^ 2) + + (∑ i : Fin (2 * m + 1), (2 * (i.1 : ℚ) - 2 * m) ^ 2) + + (∑ j : Fin (2 * (2 * m + 1) - 1), + if j.1 % 2 = 0 then oddCapExpr m j else 0) + + (∑ j : Fin (2 * (2 * m + 1) - 1), + if j.1 % 2 = 0 then oddCapExpr m j else 0)) = _ + rw [odd_axis_sum, odd_axis_sum, odd_even_diag_sum, odd_even_diag_sum] + ring + +/-- Exact objective for the thin color of an odd board. -/ +theorem oddQuadratic_cost_one (m : ℕ) : + fourCost (oddQuadraticWeights m 1) = + 16 * (m : ℚ) * (10 * (m : ℚ) ^ 2 + 3 * (m : ℚ) + 2) / 3 := by + change 2 * ( + (∑ i : Fin (2 * m + 1), (2 * (i.1 : ℚ) - 2 * m) ^ 2) + + (∑ i : Fin (2 * m + 1), (2 * (i.1 : ℚ) - 2 * m) ^ 2) + + (∑ j : Fin (2 * (2 * m + 1) - 1), + if j.1 % 2 = 1 then oddCapExpr m j else 0) + + (∑ j : Fin (2 * (2 * m + 1) - 1), + if j.1 % 2 = 1 then oddCapExpr m j else 0)) = _ + rw [odd_axis_sum, odd_axis_sum, odd_odd_diag_sum, odd_odd_diag_sum] + ring + +/-- Both checkerboard colors have the same objective on an even board. -/ +theorem evenQuadratic_cost_zero (m : ℕ) (hm : 1 ≤ m) : + fourCost (evenQuadraticWeights m 0) = + 4 * ((2 * m : ℚ) - 1) * + (20 * (m : ℚ) ^ 2 - 14 * (m : ℚ) + 3) / 3 := by + change 2 * ( + (∑ i : Fin (2 * m), + (2 * (i.1 : ℚ) - ((2 * m : ℚ) - 1)) ^ 2) + + (∑ i : Fin (2 * m), + (2 * (i.1 : ℚ) - ((2 * m : ℚ) - 1)) ^ 2) + + (∑ j : Fin (2 * (2 * m) - 1), + if j.1 % 2 = 0 then evenCapExpr m j else 0) + + (∑ j : Fin (2 * (2 * m) - 1), + if j.1 % 2 = 1 then evenCapExpr m j else 0)) = _ + rw [even_axis_sum, even_axis_sum, + parity_partition (fun j : Fin (2 * (2 * m) - 1) => evenCapExpr m j), + even_all_diag_sum m hm] + ring + +/-- Same objective for the other color of an even board. -/ +theorem evenQuadratic_cost_one (m : ℕ) (hm : 1 ≤ m) : + fourCost (evenQuadraticWeights m 1) = + 4 * ((2 * m : ℚ) - 1) * + (20 * (m : ℚ) ^ 2 - 14 * (m : ℚ) + 3) / 3 := by + change 2 * ( + (∑ i : Fin (2 * m), + (2 * (i.1 : ℚ) - ((2 * m : ℚ) - 1)) ^ 2) + + (∑ i : Fin (2 * m), + (2 * (i.1 : ℚ) - ((2 * m : ℚ) - 1)) ^ 2) + + (∑ j : Fin (2 * (2 * m) - 1), + if j.1 % 2 = 1 then evenCapExpr m j else 0) + + (∑ j : Fin (2 * (2 * m) - 1), + if j.1 % 2 = 0 then evenCapExpr m j else 0)) = _ + rw [even_axis_sum, even_axis_sum] + have hpartition := + parity_partition (fun j : Fin (2 * (2 * m) - 1) => evenCapExpr m j) + rw [add_comm] at hpartition + rw [hpartition, even_all_diag_sum m hm] + ring + +end Checkerboard diff --git a/Checkerboard/QuadraticWeights.lean b/Checkerboard/QuadraticWeights.lean new file mode 100644 index 00000000..a718dab8 --- /dev/null +++ b/Checkerboard/QuadraticWeights.lean @@ -0,0 +1,141 @@ +import Checkerboard.FourCertificate + +/-! +# Quadratic line-cover weights + +For a point `(x,y)` on an `n` board, put `N=n-1`, `u=x+y-N`, +and `v=x-y`. The exact identity + +`(2x-N)^2 + (2y-N)^2 + 2(N^2-u^2) + 2(N^2-v^2) = 4N^2` + +gives constant point coverage after retaining the diagonals of the required +checkerboard parity. +-/ + +namespace Checkerboard + +private def oddCap (m : ℕ) {k : ℕ} (j : Fin k) : ℚ := + 2 * ((2 * m : ℚ) ^ 2 - ((j.1 : ℚ) - 2 * m) ^ 2) + +private def evenCap (m : ℕ) {k : ℕ} (j : Fin k) : ℚ := + 2 * (((2 * m : ℚ) - 1) ^ 2 - + ((j.1 : ℚ) - ((2 * m : ℚ) - 1)) ^ 2) + +/-- Quadratic cover for the odd board `n=2m+1`. -/ +def oddQuadraticWeights (m parity : ℕ) : FourWeights (2 * m + 1) where + row i := (2 * (i.1 : ℚ) - 2 * m) ^ 2 + column i := (2 * (i.1 : ℚ) - 2 * m) ^ 2 + sum j := if j.1 % 2 = parity % 2 then oddCap m j else 0 + difference j := if j.1 % 2 = parity % 2 then oddCap m j else 0 + +/-- Quadratic cover for the even board `n=2m`. Difference-line indices are +shifted by the odd number `2m-1`, hence use the opposite index parity. -/ +def evenQuadraticWeights (m parity : ℕ) : FourWeights (2 * m) where + row i := (2 * (i.1 : ℚ) - ((2 * m : ℚ) - 1)) ^ 2 + column i := (2 * (i.1 : ℚ) - ((2 * m : ℚ) - 1)) ^ 2 + sum j := if j.1 % 2 = parity % 2 then evenCap m j else 0 + difference j := + if j.1 % 2 = (parity + 1) % 2 then evenCap m j else 0 + +private theorem oddCap_nonneg (m : ℕ) + (j : Fin (2 * (2 * m + 1) - 1)) : 0 ≤ oddCap m j := by + have hj0 : (0 : ℚ) ≤ j.1 := by positivity + have hjmax : (j.1 : ℚ) ≤ 4 * (m : ℚ) := by + exact_mod_cast (show j.1 ≤ 4 * m by omega) + have hprod : 0 ≤ (j.1 : ℚ) * (4 * (m : ℚ) - j.1) := + mul_nonneg hj0 (sub_nonneg.mpr hjmax) + unfold oddCap + nlinarith + +private theorem evenCap_nonneg (m : ℕ) (hm : 1 ≤ m) + (j : Fin (2 * (2 * m) - 1)) : 0 ≤ evenCap m j := by + have hj0 : (0 : ℚ) ≤ j.1 := by positivity + have hjmax : (j.1 : ℚ) ≤ 2 * ((2 * m : ℚ) - 1) := by + have hjmaxNat : j.1 ≤ 2 * (2 * m - 1) := by omega + exact_mod_cast hjmaxNat + have hprod : 0 ≤ (j.1 : ℚ) * + (2 * ((2 * m : ℚ) - 1) - j.1) := + mul_nonneg hj0 (sub_nonneg.mpr hjmax) + unfold evenCap + nlinarith + +/-- All four odd-board line weights are nonnegative. -/ +theorem oddQuadratic_nonnegative (m parity : ℕ) : + (∀ i, 0 ≤ (oddQuadraticWeights m parity).row i) ∧ + (∀ i, 0 ≤ (oddQuadraticWeights m parity).column i) ∧ + (∀ i, 0 ≤ (oddQuadraticWeights m parity).sum i) ∧ + ∀ i, 0 ≤ (oddQuadraticWeights m parity).difference i := by + constructor + · intro i + simp [oddQuadraticWeights] + positivity + constructor + · intro i + simp [oddQuadraticWeights] + positivity + constructor + · intro i + simp only [oddQuadraticWeights] + split <;> simp_all [oddCap_nonneg] + · intro i + simp only [oddQuadraticWeights] + split <;> simp_all [oddCap_nonneg] + +/-- All four even-board line weights are nonnegative. -/ +theorem evenQuadratic_nonnegative (m parity : ℕ) (hm : 1 ≤ m) : + (∀ i, 0 ≤ (evenQuadraticWeights m parity).row i) ∧ + (∀ i, 0 ≤ (evenQuadraticWeights m parity).column i) ∧ + (∀ i, 0 ≤ (evenQuadraticWeights m parity).sum i) ∧ + ∀ i, 0 ≤ (evenQuadraticWeights m parity).difference i := by + constructor + · intro i + simp [evenQuadraticWeights] + positivity + constructor + · intro i + simp [evenQuadraticWeights] + positivity + constructor + · intro i + simp only [evenQuadraticWeights] + split <;> simp_all [evenCap_nonneg m hm] + · intro i + simp only [evenQuadraticWeights] + split <;> simp_all [evenCap_nonneg m hm] + +/-- Constant coverage on an odd board. -/ +theorem oddQuadratic_coverage (m parity : ℕ) (hp : parity = 0 ∨ parity = 1) + (p : Point (2 * m + 1)) (hcolor : InColor parity p) : + fourCoverage (oddQuadraticWeights m parity) p = 16 * (m : ℚ) ^ 2 := by + have hsum : (sumIndex p).1 % 2 = parity % 2 := by + simpa [sumIndex, InColor] using hcolor + have hdiff : (differenceIndex p).1 % 2 = parity % 2 := by + rcases hp with rfl | rfl <;> + simp [differenceIndex, InColor] at hcolor ⊢ <;> omega + have hy : p.2.1 ≤ 2 * m := by omega + unfold fourCoverage oddQuadraticWeights + dsimp + rw [if_pos hsum, if_pos hdiff] + simp only [oddCap, sumIndex, differenceIndex] + push_cast [Nat.cast_sub hy] + ring + +/-- Constant coverage on an even board. -/ +theorem evenQuadratic_coverage (m parity : ℕ) (hp : parity = 0 ∨ parity = 1) + (hm : 1 ≤ m) (p : Point (2 * m)) (hcolor : InColor parity p) : + fourCoverage (evenQuadraticWeights m parity) p = + 4 * ((2 * m : ℚ) - 1) ^ 2 := by + have hsum : (sumIndex p).1 % 2 = parity % 2 := by + simpa [sumIndex, InColor] using hcolor + have hdiff : (differenceIndex p).1 % 2 = (parity + 1) % 2 := by + rcases hp with rfl | rfl <;> + simp [differenceIndex, InColor] at hcolor ⊢ <;> omega + have hy : p.2.1 ≤ 2 * m - 1 := by omega + unfold fourCoverage evenQuadraticWeights + dsimp + rw [if_pos hsum, if_pos hdiff] + simp only [evenCap, sumIndex, differenceIndex] + push_cast [Nat.cast_sub hy] + ring + +end Checkerboard From 9d1faa296a32f9522899d2a7d0edfbc38d6f324d Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 22:47:51 -0700 Subject: [PATCH 03/59] Allow PR-triggered checkerboard migration --- .github/workflows/migrate-checkerboard-alln.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/migrate-checkerboard-alln.yml b/.github/workflows/migrate-checkerboard-alln.yml index a78dc7d7..9aad8034 100644 --- a/.github/workflows/migrate-checkerboard-alln.yml +++ b/.github/workflows/migrate-checkerboard-alln.yml @@ -9,6 +9,10 @@ on: - migrate/checkerboard-alln-27a80067 paths: - '.github/workflows/migrate-checkerboard-alln.yml' + pull_request: + branches: [main] + paths: + - '.github/workflows/migrate-checkerboard-alln.yml' workflow_dispatch: permissions: From 8fc0535a3677bebdfbb16a699e2897da9958ec90 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 22:48:25 -0700 Subject: [PATCH 04/59] Remove one-shot checkerboard migration workflow --- .../workflows/migrate-checkerboard-alln.yml | 70 ------------------- 1 file changed, 70 deletions(-) delete mode 100644 .github/workflows/migrate-checkerboard-alln.yml diff --git a/.github/workflows/migrate-checkerboard-alln.yml b/.github/workflows/migrate-checkerboard-alln.yml deleted file mode 100644 index 9aad8034..00000000 --- a/.github/workflows/migrate-checkerboard-alln.yml +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2026 Dominic Dabish -# Licensed under the Apache License, Version 2.0. - -name: Migrate checkerboard all-n proof - -on: - push: - branches: - - migrate/checkerboard-alln-27a80067 - paths: - - '.github/workflows/migrate-checkerboard-alln.yml' - pull_request: - branches: [main] - paths: - - '.github/workflows/migrate-checkerboard-alln.yml' - workflow_dispatch: - -permissions: - contents: write - -jobs: - migrate: - runs-on: ubuntu-latest - steps: - - name: Checkout ProofPlaygrond migration branch - uses: actions/checkout@v6 - with: - ref: migrate/checkerboard-alln-27a80067 - fetch-depth: 0 - - - name: Checkout frozen CRL proof source - uses: actions/checkout@v6 - with: - repository: DomTheDeveloper/crl - ref: 27a800672db58c9fe0c3d02b48c798347fb02fd5 - path: _checkerboard_source - persist-credentials: false - - - name: Copy exact all-n dependency closure - run: | - set -euo pipefail - src='_checkerboard_source/proofs/lean/Checkerboard/Checkerboard' - mkdir -p Checkerboard - for file in \ - Model.lean \ - FiberSums.lean \ - FourCertificate.lean \ - QuadraticWeights.lean \ - PolynomialSums.lean \ - FinPolynomialSums.lean \ - QuadraticCosts.lean \ - AllNUpper.lean \ - N6Base.lean \ - AllNTheorem.lean; do - cp "$src/$file" "Checkerboard/$file" - done - rm -rf _checkerboard_source - - - name: Commit exact migrated proof - run: | - set -euo pipefail - git config user.name 'github-actions[bot]' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add Checkerboard - if git diff --cached --quiet; then - echo 'Checkerboard proof files already match the frozen source.' - exit 0 - fi - git commit -m 'Migrate checkerboard all-n proof from frozen CRL commit' - git push origin HEAD:migrate/checkerboard-alln-27a80067 From 90ffbf0e2f58c4a88dde9361b06648335ef9d868 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 22:57:00 -0700 Subject: [PATCH 05/59] Add checkerboard pinned Lean toolchain --- lean-toolchain | 1 + 1 file changed, 1 insertion(+) create mode 100644 lean-toolchain diff --git a/lean-toolchain b/lean-toolchain new file mode 100644 index 00000000..94b9f495 --- /dev/null +++ b/lean-toolchain @@ -0,0 +1 @@ +leanprover/lean4:v4.32.0 From 85f69c802c08b145dbf2946055d34ec902ac6697 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 22:57:12 -0700 Subject: [PATCH 06/59] Add checkerboard Lean project configuration --- lakefile.lean | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 lakefile.lean diff --git a/lakefile.lean b/lakefile.lean new file mode 100644 index 00000000..7de55dbf --- /dev/null +++ b/lakefile.lean @@ -0,0 +1,11 @@ +import Lake +open Lake DSL + +package «checkerboard-verification» where + version := v!"0.1.0" + +require mathlib from git + "https://github.com/leanprover-community/mathlib4.git" @ "v4.32.0" + +lean_lib Checkerboard where + roots := #[`Checkerboard] From be4caf8714f89d84d8f56662c01eea5eb6f05c70 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 23:01:01 -0700 Subject: [PATCH 07/59] Scope checkerboard library to all-n theorem --- lakefile.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lakefile.lean b/lakefile.lean index 7de55dbf..d0c126ea 100644 --- a/lakefile.lean +++ b/lakefile.lean @@ -8,4 +8,4 @@ require mathlib from git "https://github.com/leanprover-community/mathlib4.git" @ "v4.32.0" lean_lib Checkerboard where - roots := #[`Checkerboard] + roots := #[`Checkerboard.AllNTheorem] From 6b39a9522f258425c6f0ff052205e48a84aa4248 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 23:04:34 -0700 Subject: [PATCH 08/59] Add minimal checkerboard library root --- Checkerboard.lean | 1 + 1 file changed, 1 insertion(+) create mode 100644 Checkerboard.lean diff --git a/Checkerboard.lean b/Checkerboard.lean new file mode 100644 index 00000000..57ed8d63 --- /dev/null +++ b/Checkerboard.lean @@ -0,0 +1 @@ +import Checkerboard.AllNTheorem From d1c24f00796c59c695eb0ceb1ade131f0e463b5d Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 23:04:51 -0700 Subject: [PATCH 09/59] Use minimal checkerboard root module --- lakefile.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lakefile.lean b/lakefile.lean index d0c126ea..7de55dbf 100644 --- a/lakefile.lean +++ b/lakefile.lean @@ -8,4 +8,4 @@ require mathlib from git "https://github.com/leanprover-community/mathlib4.git" @ "v4.32.0" lean_lib Checkerboard where - roots := #[`Checkerboard.AllNTheorem] + roots := #[`Checkerboard] From 73965eff5fb3585865fcf550deca27237d72c915 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 23:27:35 -0700 Subject: [PATCH 10/59] Add one-shot checkerboard support repair --- .../repair-checkerboard-support-once.yml | 248 ++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 .github/workflows/repair-checkerboard-support-once.yml diff --git a/.github/workflows/repair-checkerboard-support-once.yml b/.github/workflows/repair-checkerboard-support-once.yml new file mode 100644 index 00000000..5fdba395 --- /dev/null +++ b/.github/workflows/repair-checkerboard-support-once.yml @@ -0,0 +1,248 @@ +# Copyright 2026 Dominic Dabish +# Licensed under the Apache License, Version 2.0. + +name: Repair checkerboard support once + +on: + push: + branches: [migrate/checkerboard-alln-27a80067] + paths: ['.github/workflows/repair-checkerboard-support-once.yml'] + +permissions: + contents: write + +jobs: + repair: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + ref: migrate/checkerboard-alln-27a80067 + fetch-depth: 0 + - name: Apply exact support compatibility repairs + run: | + python3 - <<'PY' + from pathlib import Path + + def replace_once(path: str, old: str, new: str) -> None: + p = Path(path) + text = p.read_text() + if text.count(old) != 1: + raise SystemExit(f'{path}: expected one match, found {text.count(old)}') + p.write_text(text.replace(old, new, 1)) + + replace_once( + 'Checkerboard/Model.lean', + '''instance {n : ℕ} (line : PrincipalLine n) : DecidablePred (OnLine line) := + fun _ => inferInstance''', + '''instance {n : ℕ} (line : PrincipalLine n) : DecidablePred (OnLine line) := by + intro p + unfold OnLine + infer_instance''') + + replace_once( + 'Checkerboard/Model.lean', + '''private theorem sum_indicator_eq_card_filter {α : Type*} [DecidableEq α] + (s : Finset α) (P : α → Prop) [DecidablePred P] (w : ℕ) : + (∑ a ∈ s, if P a then w else 0) = (s.filter P).card * w := by + induction s using Finset.induction_on with + | empty => simp + | @insert a s ha ih => + by_cases hP : P a <;> + simp [ha, hP, ih, Nat.add_mul]''', + '''private theorem sum_indicator_eq_card_filter {α : Type*} [DecidableEq α] + (s : Finset α) (P : α → Prop) [DecidablePred P] (w : ℕ) : + (∑ a ∈ s, if P a then w else 0) = (s.filter P).card * w := by + induction s using Finset.induction_on with + | empty => simp + | @insert a s ha ih => + by_cases hP : P a + · have hnot : a ∉ s.filter P := by + intro hmem + exact ha (Finset.mem_of_mem_filter hmem) + simp [ha, hP, hnot, ih, Nat.add_mul, Nat.add_comm] + · simp [ha, hP, ih]''') + + fiber = Path('Checkerboard/FiberSums.lean') + text = fiber.read_text() + start = text.index('/-- Every element of a finite set belongs to exactly one fiber. -/') + end = text.index('/-- Unweighted point count as the sum of all fiber counts, cast to a semiring. -/') + replacement = '''private theorem fiberCard_mul_eq_sum [CommSemiring R] + (s : Finset α) (f : α → β) (b : β) (g : β → R) : + (fiberCard s f b : R) * g b = + ∑ a ∈ s, if f a = b then g b else 0 := by + classical + induction s using Finset.induction_on with + | empty => simp [fiberCard] + | @insert a s ha ih => + by_cases h : f a = b + · have hnot : a ∉ s.filter fun x => f x = b := by + intro hmem + exact ha (Finset.mem_of_mem_filter hmem) + simp [fiberCard, ha, h, hnot, ih, add_mul] + · simp [fiberCard, ha, h, ih] + +/-- Weighted double counting over all fibers. -/ +theorem sum_fiberCard_mul [Fintype β] [CommSemiring R] + (s : Finset α) (f : α → β) (g : β → R) : + ∑ b : β, (fiberCard s f b : R) * g b = + ∑ a ∈ s, g (f a) := by + classical + calc + ∑ b : β, (fiberCard s f b : R) * g b = + ∑ b : β, ∑ a ∈ s, if f a = b then g b else 0 := by + apply Finset.sum_congr rfl + intro b _ + exact fiberCard_mul_eq_sum s f b g + _ = ∑ a ∈ s, ∑ b : β, if f a = b then g b else 0 := by + rw [Finset.sum_comm] + _ = ∑ a ∈ s, g (f a) := by + apply Finset.sum_congr rfl + intro a _ + simp + +/-- Every element of a finite set belongs to exactly one fiber. -/ +theorem sum_fiberCard [Fintype β] (s : Finset α) (f : α → β) : + ∑ b : β, fiberCard s f b = s.card := by + simpa using sum_fiberCard_mul (R := ℕ) s f (fun _ => 1) + +''' + fiber.write_text(text[:start] + replacement + text[end:]) + + replace_once( + 'Checkerboard/PolynomialSums.lean', + '''theorem sum_range_quadratic_cap (N : ℕ) : + (∑ j ∈ Finset.range (2 * N + 1), + 2 * ((N : ℚ) ^ 2 - ((j : ℚ) - N) ^ 2)) = + 2 * (N : ℚ) * (2 * (N : ℚ) - 1) * (2 * (N : ℚ) + 1) / 3 := by + have h := sum_range_affine_sq (2 * N + 1) (1 : ℚ) (-(N : ℚ)) + push_cast at h ⊢ + calc + (∑ j ∈ Finset.range (2 * N + 1), + 2 * ((N : ℚ) ^ 2 - ((j : ℚ) - N) ^ 2)) = + 2 * ((2 * (N : ℚ) + 1) * (N : ℚ) ^ 2 - + ∑ j ∈ Finset.range (2 * N + 1), + ((j : ℚ) - N) ^ 2) := by + simp only [Finset.sum_sub_distrib, Finset.sum_mul, + Finset.sum_const, Finset.card_range, nsmul_eq_mul] + ring + _ = 2 * (N : ℚ) * (2 * (N : ℚ) - 1) * + (2 * (N : ℚ) + 1) / 3 := by + rw [h] + ring''', + '''theorem sum_range_quadratic_cap (N : ℕ) : + (∑ j ∈ Finset.range (2 * N + 1), + 2 * ((N : ℚ) ^ 2 - ((j : ℚ) - N) ^ 2)) = + 2 * (N : ℚ) * (2 * (N : ℚ) - 1) * (2 * (N : ℚ) + 1) / 3 := by + have h := sum_range_affine_sq (2 * N + 1) (1 : ℚ) (-(N : ℚ)) + push_cast at h ⊢ + have hsum : + (∑ j ∈ Finset.range (2 * N + 1), ((j : ℚ) - N) ^ 2) = + ∑ j ∈ Finset.range (2 * N + 1), + ((1 : ℚ) * (j : ℚ) + (-(N : ℚ))) ^ 2 := by + apply Finset.sum_congr rfl + intro j _ + ring + calc + (∑ j ∈ Finset.range (2 * N + 1), + 2 * ((N : ℚ) ^ 2 - ((j : ℚ) - N) ^ 2)) = + 2 * ((2 * (N : ℚ) + 1) * (N : ℚ) ^ 2 - + ∑ j ∈ Finset.range (2 * N + 1), + ((j : ℚ) - N) ^ 2) := by + simp only [Finset.sum_sub_distrib, Finset.sum_mul, + Finset.sum_const, Finset.card_range, nsmul_eq_mul] + ring + _ = 2 * (N : ℚ) * (2 * (N : ℚ) - 1) * + (2 * (N : ℚ) + 1) / 3 := by + rw [hsum, h] + ring''') + + replace_once( + 'Checkerboard/PolynomialSums.lean', + ''' convert (show + (4 : ℚ) * + (∑ r ∈ Finset.range (2 * m + 1), + 2 * ((m : ℚ) ^ 2 - ((r : ℚ) - m) ^ 2)) = + 8 * (m : ℚ) * (2 * (m : ℚ) - 1) * + (2 * (m : ℚ) + 1) / 3 by rw [h]; ring) using 1 + · apply Finset.sum_congr rfl + intro r hr + rw [dif_pos] + · push_cast + ring + · omega''', + ''' have hscale : + (∑ r ∈ Finset.range (2 * m + 1), + 2 * ((2 * m : ℚ) ^ 2 - ((2 * r : ℕ) : ℚ) ^ 2 + + 4 * (r : ℚ) * (m : ℚ))) = + 4 * (∑ r ∈ Finset.range (2 * m + 1), + 2 * ((m : ℚ) ^ 2 - ((r : ℚ) - m) ^ 2)) := by + rw [Finset.mul_sum] + apply Finset.sum_congr rfl + intro r _ + push_cast + ring + convert (show + (4 : ℚ) * + (∑ r ∈ Finset.range (2 * m + 1), + 2 * ((m : ℚ) ^ 2 - ((r : ℚ) - m) ^ 2)) = + 8 * (m : ℚ) * (2 * (m : ℚ) - 1) * + (2 * (m : ℚ) + 1) / 3 by rw [h]; ring) using 1 + · rw [Finset.mul_sum] + apply Finset.sum_congr rfl + intro r _ + push_cast + ring''') + + replace_once( + 'Checkerboard/PolynomialSums.lean', + ''' calc + (∑ r ∈ Finset.range (2 * m), + 2 * ((2 * (m : ℚ)) ^ 2 - + (((2 * r + 1 : ℕ) : ℚ) - 2 * (m : ℚ)) ^ 2)) = + 2 * ((2 * (m : ℚ)) * (2 * (m : ℚ)) ^ 2 - + ∑ r ∈ Finset.range (2 * m), + (2 * (r : ℚ) + (1 - 2 * (m : ℚ))) ^ 2) := by + push_cast + simp only [Finset.sum_sub_distrib, Finset.sum_mul, + Finset.sum_const, Finset.card_range, nsmul_eq_mul] + ring + _ = 4 * (m : ℚ) * (8 * (m : ℚ) ^ 2 + 1) / 3 := by + rw [h] + ring''', + ''' have hcast : + (∑ r ∈ Finset.range (2 * m), + 2 * ((2 * (m : ℚ)) ^ 2 - + (((2 * r + 1 : ℕ) : ℚ) - 2 * (m : ℚ)) ^ 2)) = + ∑ r ∈ Finset.range (2 * m), + 2 * ((2 * (m : ℚ)) ^ 2 - + (2 * (r : ℚ) + 1 - 2 * (m : ℚ)) ^ 2) := by + apply Finset.sum_congr rfl + intro r _ + push_cast + ring + rw [hcast] + calc + (∑ r ∈ Finset.range (2 * m), + 2 * ((2 * (m : ℚ)) ^ 2 - + (2 * (r : ℚ) + 1 - 2 * (m : ℚ)) ^ 2)) = + 2 * ((2 * (m : ℚ)) * (2 * (m : ℚ)) ^ 2 - + ∑ r ∈ Finset.range (2 * m), + (2 * (r : ℚ) + (1 - 2 * (m : ℚ))) ^ 2) := by + simp only [Finset.sum_sub_distrib, Finset.sum_mul, + Finset.sum_const, Finset.card_range, nsmul_eq_mul] + ring + _ = 4 * (m : ℚ) * (8 * (m : ℚ) ^ 2 + 1) / 3 := by + rw [h] + ring''') + + Path('.github/workflows/repair-checkerboard-support-once.yml').unlink() + PY + - name: Commit repaired support modules + run: | + set -euo pipefail + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add Checkerboard .github/workflows/repair-checkerboard-support-once.yml + git commit -m 'Repair checkerboard support modules for Lean 4.32' + git push origin HEAD:migrate/checkerboard-alln-27a80067 From a124c0cde14dda2738735042eb223ca284d7f233 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 23:32:25 -0700 Subject: [PATCH 11/59] Make checkerboard model proofs explicit under Lean 4.32 --- Checkerboard/Model.lean | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Checkerboard/Model.lean b/Checkerboard/Model.lean index 8cf03ca7..edaa12ab 100644 --- a/Checkerboard/Model.lean +++ b/Checkerboard/Model.lean @@ -63,8 +63,10 @@ def lineValue {n : ℕ} (family : LineFamily) (p : Point n) : ℤ := def OnLine {n : ℕ} (line : PrincipalLine n) (p : Point n) : Prop := lineValue line.1 p = line.2.1 -instance {n : ℕ} (line : PrincipalLine n) : DecidablePred (OnLine line) := - fun _ => inferInstance +instance {n : ℕ} (line : PrincipalLine n) : DecidablePred (OnLine line) := by + intro p + unfold OnLine + infer_instance /-- Three points on one principal line are Euclidean-collinear. -/ theorem principal_collinear {n : ℕ} {line : PrincipalLine n} @@ -139,8 +141,12 @@ private theorem sum_indicator_eq_card_filter {α : Type*} [DecidableEq α] induction s using Finset.induction_on with | empty => simp | @insert a s ha ih => - by_cases hP : P a <;> - simp [ha, hP, ih, Nat.add_mul] + by_cases hP : P a + · have hnot : a ∉ s.filter P := by + intro hmem + exact ha (Finset.mem_of_mem_filter hmem) + simp [ha, hP, hnot, ih, Nat.add_mul, Nat.add_comm] + · simp [ha, hP, ih] private theorem double_count {n : ℕ} (s : Finset (Point n)) (weight : PrincipalLine n → ℕ) : From d8aec4c1eb02f59874f15fcb349401f22c74052e Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 23:32:46 -0700 Subject: [PATCH 12/59] Replace checkerboard fiber induction with explicit double counting --- Checkerboard/FiberSums.lean | 39 ++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/Checkerboard/FiberSums.lean b/Checkerboard/FiberSums.lean index c260bae7..0984162c 100644 --- a/Checkerboard/FiberSums.lean +++ b/Checkerboard/FiberSums.lean @@ -23,15 +23,20 @@ def fiberCard (s : Finset α) (f : α → β) (b : β) : ℕ := fiberCard ∅ f b = 0 := by simp [fiberCard] -/-- Every element of a finite set belongs to exactly one fiber. -/ -theorem sum_fiberCard [Fintype β] (s : Finset α) (f : α → β) : - ∑ b : β, fiberCard s f b = s.card := by +private theorem fiberCard_mul_eq_sum [CommSemiring R] + (s : Finset α) (f : α → β) (b : β) (g : β → R) : + (fiberCard s f b : R) * g b = + ∑ a ∈ s, if f a = b then g b else 0 := by classical induction s using Finset.induction_on with - | empty => simp + | empty => simp [fiberCard] | @insert a s ha ih => - simp only [fiberCard, Finset.filter_insert] - simp [ha, ih] + by_cases h : f a = b + · have hnot : a ∉ s.filter fun x => f x = b := by + intro hmem + exact ha (Finset.mem_of_mem_filter hmem) + simp [fiberCard, ha, h, hnot, ih, add_mul] + · simp [fiberCard, ha, h, ih] /-- Weighted double counting over all fibers. -/ theorem sum_fiberCard_mul [Fintype β] [CommSemiring R] @@ -39,11 +44,23 @@ theorem sum_fiberCard_mul [Fintype β] [CommSemiring R] ∑ b : β, (fiberCard s f b : R) * g b = ∑ a ∈ s, g (f a) := by classical - induction s using Finset.induction_on with - | empty => simp [fiberCard] - | @insert a s ha ih => - simp only [fiberCard, Finset.filter_insert] - simp [ha, ih, add_mul] + calc + ∑ b : β, (fiberCard s f b : R) * g b = + ∑ b : β, ∑ a ∈ s, if f a = b then g b else 0 := by + apply Finset.sum_congr rfl + intro b _ + exact fiberCard_mul_eq_sum s f b g + _ = ∑ a ∈ s, ∑ b : β, if f a = b then g b else 0 := by + rw [Finset.sum_comm] + _ = ∑ a ∈ s, g (f a) := by + apply Finset.sum_congr rfl + intro a _ + simp + +/-- Every element of a finite set belongs to exactly one fiber. -/ +theorem sum_fiberCard [Fintype β] (s : Finset α) (f : α → β) : + ∑ b : β, fiberCard s f b = s.card := by + simpa using sum_fiberCard_mul (R := ℕ) s f (fun _ => 1) /-- Unweighted point count as the sum of all fiber counts, cast to a semiring. -/ theorem sum_fiberCard_cast [Fintype β] [CommSemiring R] From 7eb21d020e45817efe9773649b76d31cd0c7cf62 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 23:33:20 -0700 Subject: [PATCH 13/59] Make checkerboard polynomial rescalings explicit --- Checkerboard/PolynomialSums.lean | 41 +++++++++++++++++++------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/Checkerboard/PolynomialSums.lean b/Checkerboard/PolynomialSums.lean index 232142f2..3ee20fec 100644 --- a/Checkerboard/PolynomialSums.lean +++ b/Checkerboard/PolynomialSums.lean @@ -28,6 +28,13 @@ theorem sum_range_quadratic_cap (N : ℕ) : 2 * (N : ℚ) * (2 * (N : ℚ) - 1) * (2 * (N : ℚ) + 1) / 3 := by have h := sum_range_affine_sq (2 * N + 1) (1 : ℚ) (-(N : ℚ)) push_cast at h ⊢ + have hsum : + (∑ j ∈ Finset.range (2 * N + 1), ((j : ℚ) - N) ^ 2) = + ∑ j ∈ Finset.range (2 * N + 1), + ((1 : ℚ) * (j : ℚ) + (-(N : ℚ))) ^ 2 := by + apply Finset.sum_congr rfl + intro j _ + ring calc (∑ j ∈ Finset.range (2 * N + 1), 2 * ((N : ℚ) ^ 2 - ((j : ℚ) - N) ^ 2)) = @@ -39,7 +46,7 @@ theorem sum_range_quadratic_cap (N : ℕ) : ring _ = 2 * (N : ℚ) * (2 * (N : ℚ) - 1) * (2 * (N : ℚ) + 1) / 3 := by - rw [h] + rw [hsum, h] ring /-- Extract the even-indexed terms from a range of even length. -/ @@ -90,18 +97,20 @@ theorem even_quadratic_cap_sum (m : ℕ) : rw [show 4 * m + 1 = 2 * (2 * m) + 1 by omega, sum_range_even_terms_succ] push_cast - convert (show - (4 : ℚ) * - (∑ r ∈ Finset.range (2 * m + 1), - 2 * ((m : ℚ) ^ 2 - ((r : ℚ) - m) ^ 2)) = - 8 * (m : ℚ) * (2 * (m : ℚ) - 1) * - (2 * (m : ℚ) + 1) / 3 by rw [h]; ring) using 1 - · apply Finset.sum_congr rfl - intro r hr - rw [dif_pos] - · push_cast - ring - · omega + calc + (∑ r ∈ Finset.range (2 * m + 1), + 2 * ((2 * (m : ℚ)) ^ 2 - + (2 * (r : ℚ) - 2 * (m : ℚ)) ^ 2)) = + 4 * (∑ r ∈ Finset.range (2 * m + 1), + 2 * ((m : ℚ) ^ 2 - ((r : ℚ) - m) ^ 2)) := by + rw [Finset.mul_sum] + apply Finset.sum_congr rfl + intro r _ + ring + _ = 8 * (m : ℚ) * (2 * (m : ℚ) - 1) * + (2 * (m : ℚ) + 1) / 3 := by + rw [h] + ring /-- Odd offsets in the quadratic cap on `-2m, …, 2m`. -/ theorem odd_quadratic_cap_sum (m : ℕ) : @@ -114,15 +123,15 @@ theorem odd_quadratic_cap_sum (m : ℕ) : sum_range_odd_terms_succ] have h := sum_range_affine_sq (2 * m) (2 : ℚ) (1 - 2 * (m : ℚ)) - push_cast at h ⊢ + push_cast at h + simp_rw [Nat.cast_add, Nat.cast_mul, Nat.cast_one] calc (∑ r ∈ Finset.range (2 * m), 2 * ((2 * (m : ℚ)) ^ 2 - - (((2 * r + 1 : ℕ) : ℚ) - 2 * (m : ℚ)) ^ 2)) = + (2 * (r : ℚ) + 1 - 2 * (m : ℚ)) ^ 2)) = 2 * ((2 * (m : ℚ)) * (2 * (m : ℚ)) ^ 2 - ∑ r ∈ Finset.range (2 * m), (2 * (r : ℚ) + (1 - 2 * (m : ℚ))) ^ 2) := by - push_cast simp only [Finset.sum_sub_distrib, Finset.sum_mul, Finset.sum_const, Finset.card_range, nsmul_eq_mul] ring From 2ac1cabede0f3c0b6d4324d41912c86e131e96c6 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 23:33:32 -0700 Subject: [PATCH 14/59] Remove unused checkerboard repair workflow --- .../repair-checkerboard-support-once.yml | 248 ------------------ 1 file changed, 248 deletions(-) delete mode 100644 .github/workflows/repair-checkerboard-support-once.yml diff --git a/.github/workflows/repair-checkerboard-support-once.yml b/.github/workflows/repair-checkerboard-support-once.yml deleted file mode 100644 index 5fdba395..00000000 --- a/.github/workflows/repair-checkerboard-support-once.yml +++ /dev/null @@ -1,248 +0,0 @@ -# Copyright 2026 Dominic Dabish -# Licensed under the Apache License, Version 2.0. - -name: Repair checkerboard support once - -on: - push: - branches: [migrate/checkerboard-alln-27a80067] - paths: ['.github/workflows/repair-checkerboard-support-once.yml'] - -permissions: - contents: write - -jobs: - repair: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - with: - ref: migrate/checkerboard-alln-27a80067 - fetch-depth: 0 - - name: Apply exact support compatibility repairs - run: | - python3 - <<'PY' - from pathlib import Path - - def replace_once(path: str, old: str, new: str) -> None: - p = Path(path) - text = p.read_text() - if text.count(old) != 1: - raise SystemExit(f'{path}: expected one match, found {text.count(old)}') - p.write_text(text.replace(old, new, 1)) - - replace_once( - 'Checkerboard/Model.lean', - '''instance {n : ℕ} (line : PrincipalLine n) : DecidablePred (OnLine line) := - fun _ => inferInstance''', - '''instance {n : ℕ} (line : PrincipalLine n) : DecidablePred (OnLine line) := by - intro p - unfold OnLine - infer_instance''') - - replace_once( - 'Checkerboard/Model.lean', - '''private theorem sum_indicator_eq_card_filter {α : Type*} [DecidableEq α] - (s : Finset α) (P : α → Prop) [DecidablePred P] (w : ℕ) : - (∑ a ∈ s, if P a then w else 0) = (s.filter P).card * w := by - induction s using Finset.induction_on with - | empty => simp - | @insert a s ha ih => - by_cases hP : P a <;> - simp [ha, hP, ih, Nat.add_mul]''', - '''private theorem sum_indicator_eq_card_filter {α : Type*} [DecidableEq α] - (s : Finset α) (P : α → Prop) [DecidablePred P] (w : ℕ) : - (∑ a ∈ s, if P a then w else 0) = (s.filter P).card * w := by - induction s using Finset.induction_on with - | empty => simp - | @insert a s ha ih => - by_cases hP : P a - · have hnot : a ∉ s.filter P := by - intro hmem - exact ha (Finset.mem_of_mem_filter hmem) - simp [ha, hP, hnot, ih, Nat.add_mul, Nat.add_comm] - · simp [ha, hP, ih]''') - - fiber = Path('Checkerboard/FiberSums.lean') - text = fiber.read_text() - start = text.index('/-- Every element of a finite set belongs to exactly one fiber. -/') - end = text.index('/-- Unweighted point count as the sum of all fiber counts, cast to a semiring. -/') - replacement = '''private theorem fiberCard_mul_eq_sum [CommSemiring R] - (s : Finset α) (f : α → β) (b : β) (g : β → R) : - (fiberCard s f b : R) * g b = - ∑ a ∈ s, if f a = b then g b else 0 := by - classical - induction s using Finset.induction_on with - | empty => simp [fiberCard] - | @insert a s ha ih => - by_cases h : f a = b - · have hnot : a ∉ s.filter fun x => f x = b := by - intro hmem - exact ha (Finset.mem_of_mem_filter hmem) - simp [fiberCard, ha, h, hnot, ih, add_mul] - · simp [fiberCard, ha, h, ih] - -/-- Weighted double counting over all fibers. -/ -theorem sum_fiberCard_mul [Fintype β] [CommSemiring R] - (s : Finset α) (f : α → β) (g : β → R) : - ∑ b : β, (fiberCard s f b : R) * g b = - ∑ a ∈ s, g (f a) := by - classical - calc - ∑ b : β, (fiberCard s f b : R) * g b = - ∑ b : β, ∑ a ∈ s, if f a = b then g b else 0 := by - apply Finset.sum_congr rfl - intro b _ - exact fiberCard_mul_eq_sum s f b g - _ = ∑ a ∈ s, ∑ b : β, if f a = b then g b else 0 := by - rw [Finset.sum_comm] - _ = ∑ a ∈ s, g (f a) := by - apply Finset.sum_congr rfl - intro a _ - simp - -/-- Every element of a finite set belongs to exactly one fiber. -/ -theorem sum_fiberCard [Fintype β] (s : Finset α) (f : α → β) : - ∑ b : β, fiberCard s f b = s.card := by - simpa using sum_fiberCard_mul (R := ℕ) s f (fun _ => 1) - -''' - fiber.write_text(text[:start] + replacement + text[end:]) - - replace_once( - 'Checkerboard/PolynomialSums.lean', - '''theorem sum_range_quadratic_cap (N : ℕ) : - (∑ j ∈ Finset.range (2 * N + 1), - 2 * ((N : ℚ) ^ 2 - ((j : ℚ) - N) ^ 2)) = - 2 * (N : ℚ) * (2 * (N : ℚ) - 1) * (2 * (N : ℚ) + 1) / 3 := by - have h := sum_range_affine_sq (2 * N + 1) (1 : ℚ) (-(N : ℚ)) - push_cast at h ⊢ - calc - (∑ j ∈ Finset.range (2 * N + 1), - 2 * ((N : ℚ) ^ 2 - ((j : ℚ) - N) ^ 2)) = - 2 * ((2 * (N : ℚ) + 1) * (N : ℚ) ^ 2 - - ∑ j ∈ Finset.range (2 * N + 1), - ((j : ℚ) - N) ^ 2) := by - simp only [Finset.sum_sub_distrib, Finset.sum_mul, - Finset.sum_const, Finset.card_range, nsmul_eq_mul] - ring - _ = 2 * (N : ℚ) * (2 * (N : ℚ) - 1) * - (2 * (N : ℚ) + 1) / 3 := by - rw [h] - ring''', - '''theorem sum_range_quadratic_cap (N : ℕ) : - (∑ j ∈ Finset.range (2 * N + 1), - 2 * ((N : ℚ) ^ 2 - ((j : ℚ) - N) ^ 2)) = - 2 * (N : ℚ) * (2 * (N : ℚ) - 1) * (2 * (N : ℚ) + 1) / 3 := by - have h := sum_range_affine_sq (2 * N + 1) (1 : ℚ) (-(N : ℚ)) - push_cast at h ⊢ - have hsum : - (∑ j ∈ Finset.range (2 * N + 1), ((j : ℚ) - N) ^ 2) = - ∑ j ∈ Finset.range (2 * N + 1), - ((1 : ℚ) * (j : ℚ) + (-(N : ℚ))) ^ 2 := by - apply Finset.sum_congr rfl - intro j _ - ring - calc - (∑ j ∈ Finset.range (2 * N + 1), - 2 * ((N : ℚ) ^ 2 - ((j : ℚ) - N) ^ 2)) = - 2 * ((2 * (N : ℚ) + 1) * (N : ℚ) ^ 2 - - ∑ j ∈ Finset.range (2 * N + 1), - ((j : ℚ) - N) ^ 2) := by - simp only [Finset.sum_sub_distrib, Finset.sum_mul, - Finset.sum_const, Finset.card_range, nsmul_eq_mul] - ring - _ = 2 * (N : ℚ) * (2 * (N : ℚ) - 1) * - (2 * (N : ℚ) + 1) / 3 := by - rw [hsum, h] - ring''') - - replace_once( - 'Checkerboard/PolynomialSums.lean', - ''' convert (show - (4 : ℚ) * - (∑ r ∈ Finset.range (2 * m + 1), - 2 * ((m : ℚ) ^ 2 - ((r : ℚ) - m) ^ 2)) = - 8 * (m : ℚ) * (2 * (m : ℚ) - 1) * - (2 * (m : ℚ) + 1) / 3 by rw [h]; ring) using 1 - · apply Finset.sum_congr rfl - intro r hr - rw [dif_pos] - · push_cast - ring - · omega''', - ''' have hscale : - (∑ r ∈ Finset.range (2 * m + 1), - 2 * ((2 * m : ℚ) ^ 2 - ((2 * r : ℕ) : ℚ) ^ 2 + - 4 * (r : ℚ) * (m : ℚ))) = - 4 * (∑ r ∈ Finset.range (2 * m + 1), - 2 * ((m : ℚ) ^ 2 - ((r : ℚ) - m) ^ 2)) := by - rw [Finset.mul_sum] - apply Finset.sum_congr rfl - intro r _ - push_cast - ring - convert (show - (4 : ℚ) * - (∑ r ∈ Finset.range (2 * m + 1), - 2 * ((m : ℚ) ^ 2 - ((r : ℚ) - m) ^ 2)) = - 8 * (m : ℚ) * (2 * (m : ℚ) - 1) * - (2 * (m : ℚ) + 1) / 3 by rw [h]; ring) using 1 - · rw [Finset.mul_sum] - apply Finset.sum_congr rfl - intro r _ - push_cast - ring''') - - replace_once( - 'Checkerboard/PolynomialSums.lean', - ''' calc - (∑ r ∈ Finset.range (2 * m), - 2 * ((2 * (m : ℚ)) ^ 2 - - (((2 * r + 1 : ℕ) : ℚ) - 2 * (m : ℚ)) ^ 2)) = - 2 * ((2 * (m : ℚ)) * (2 * (m : ℚ)) ^ 2 - - ∑ r ∈ Finset.range (2 * m), - (2 * (r : ℚ) + (1 - 2 * (m : ℚ))) ^ 2) := by - push_cast - simp only [Finset.sum_sub_distrib, Finset.sum_mul, - Finset.sum_const, Finset.card_range, nsmul_eq_mul] - ring - _ = 4 * (m : ℚ) * (8 * (m : ℚ) ^ 2 + 1) / 3 := by - rw [h] - ring''', - ''' have hcast : - (∑ r ∈ Finset.range (2 * m), - 2 * ((2 * (m : ℚ)) ^ 2 - - (((2 * r + 1 : ℕ) : ℚ) - 2 * (m : ℚ)) ^ 2)) = - ∑ r ∈ Finset.range (2 * m), - 2 * ((2 * (m : ℚ)) ^ 2 - - (2 * (r : ℚ) + 1 - 2 * (m : ℚ)) ^ 2) := by - apply Finset.sum_congr rfl - intro r _ - push_cast - ring - rw [hcast] - calc - (∑ r ∈ Finset.range (2 * m), - 2 * ((2 * (m : ℚ)) ^ 2 - - (2 * (r : ℚ) + 1 - 2 * (m : ℚ)) ^ 2)) = - 2 * ((2 * (m : ℚ)) * (2 * (m : ℚ)) ^ 2 - - ∑ r ∈ Finset.range (2 * m), - (2 * (r : ℚ) + (1 - 2 * (m : ℚ))) ^ 2) := by - simp only [Finset.sum_sub_distrib, Finset.sum_mul, - Finset.sum_const, Finset.card_range, nsmul_eq_mul] - ring - _ = 4 * (m : ℚ) * (8 * (m : ℚ) ^ 2 + 1) / 3 := by - rw [h] - ring''') - - Path('.github/workflows/repair-checkerboard-support-once.yml').unlink() - PY - - name: Commit repaired support modules - run: | - set -euo pipefail - git config user.name 'github-actions[bot]' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add Checkerboard .github/workflows/repair-checkerboard-support-once.yml - git commit -m 'Repair checkerboard support modules for Lean 4.32' - git push origin HEAD:migrate/checkerboard-alln-27a80067 From a4010fa45cea1eeedbe6542365278fe7c61bf129 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 23:41:44 -0700 Subject: [PATCH 15/59] Finish checkerboard indicator-cardinality induction --- Checkerboard/Model.lean | 53 ++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 35 deletions(-) diff --git a/Checkerboard/Model.lean b/Checkerboard/Model.lean index edaa12ab..6759eaa1 100644 --- a/Checkerboard/Model.lean +++ b/Checkerboard/Model.lean @@ -12,27 +12,20 @@ namespace Checkerboard abbrev Point (n : ℕ) := Fin n × Fin n -/-- Twice the signed Euclidean area of the triangle `a b c`. -/ def determinant {n : ℕ} (a b c : Point n) : ℤ := ((b.1.1 : ℤ) - (a.1.1 : ℤ)) * ((c.2.1 : ℤ) - (a.2.1 : ℤ)) - ((b.2.1 : ℤ) - (a.2.1 : ℤ)) * ((c.1.1 : ℤ) - (a.1.1 : ℤ)) -/-- The checkerboard color class indexed by `parity mod 2`. -/ def InColor {n : ℕ} (parity : ℕ) (p : Point n) : Prop := (p.1.1 + p.2.1) % 2 = parity % 2 -/-- Every point of `s` lies in one checkerboard color class. -/ def Monochromatic {n : ℕ} (parity : ℕ) (s : Finset (Point n)) : Prop := ∀ p : ↥s, InColor parity p.1 -/-- No three distinct selected points are collinear. Quantifying over the -subtype `↥s` makes direct checking of explicit constructions finite and small. -/ def NoThreeInLine {n : ℕ} (s : Finset (Point n)) : Prop := ∀ a b c : ↥s, a ≠ b → a ≠ c → b ≠ c → determinant a.1 b.1 c.1 ≠ 0 -/-- A convenient exact-maximum statement, avoiding any dependence on a chosen -implementation of `argmax` over all subsets. -/ def IsExactMaximum (n parity k : ℕ) : Prop := (∃ s : Finset (Point n), Monochromatic parity s ∧ NoThreeInLine s ∧ s.card = k) ∧ @@ -46,12 +39,8 @@ inductive LineFamily | difference deriving DecidableEq, Fintype, Repr -/-- Principal rows, columns, and slope `±1` diagonals. The second component is -an index in `0, …, 2n-2`; unused row/column indices simply describe empty lines. -/ abbrev PrincipalLine (n : ℕ) := LineFamily × Fin (2 * n - 1) -/-- Integer line coordinate. Difference diagonals are shifted by `n-1`, so all -four families use nonnegative indices. -/ def lineValue {n : ℕ} (family : LineFamily) (p : Point n) : ℤ := match family with | .row => p.1.1 @@ -59,7 +48,6 @@ def lineValue {n : ℕ} (family : LineFamily) (p : Point n) : ℤ := | .sum => p.1.1 + p.2.1 | .difference => (p.1.1 : ℤ) - (p.2.1 : ℤ) + (n - 1 : ℕ) -/-- Incidence with a principal line. -/ def OnLine {n : ℕ} (line : PrincipalLine n) (p : Point n) : Prop := lineValue line.1 p = line.2.1 @@ -68,7 +56,6 @@ instance {n : ℕ} (line : PrincipalLine n) : DecidablePred (OnLine line) := by unfold OnLine infer_instance -/-- Three points on one principal line are Euclidean-collinear. -/ theorem principal_collinear {n : ℕ} {line : PrincipalLine n} {a b c : Point n} (ha : OnLine line a) (hb : OnLine line b) (hc : OnLine line c) : determinant a b c = 0 := by @@ -83,25 +70,20 @@ theorem principal_collinear {n : ℕ} {line : PrincipalLine n} | sum => simp only [OnLine, lineValue] at ha hb hc have hba : ((b.2.1 : ℤ) - (a.2.1 : ℤ)) = - -((b.1.1 : ℤ) - (a.1.1 : ℤ)) := by - linarith + -((b.1.1 : ℤ) - (a.1.1 : ℤ)) := by linarith have hca : ((c.2.1 : ℤ) - (a.2.1 : ℤ)) = - -((c.1.1 : ℤ) - (a.1.1 : ℤ)) := by - linarith + -((c.1.1 : ℤ) - (a.1.1 : ℤ)) := by linarith rw [determinant, hba, hca] ring | difference => simp only [OnLine, lineValue] at ha hb hc have hba : ((b.2.1 : ℤ) - (a.2.1 : ℤ)) = - ((b.1.1 : ℤ) - (a.1.1 : ℤ)) := by - linarith + ((b.1.1 : ℤ) - (a.1.1 : ℤ)) := by linarith have hca : ((c.2.1 : ℤ) - (a.2.1 : ℤ)) = - ((c.1.1 : ℤ) - (a.1.1 : ℤ)) := by - linarith + ((c.1.1 : ℤ) - (a.1.1 : ℤ)) := by linarith rw [determinant, hba, hca] ring -/-- A no-three-in-line set occupies every principal line at most twice. -/ theorem principalLine_card_le_two {n : ℕ} {s : Finset (Point n)} (hntil : NoThreeInLine s) (line : PrincipalLine n) : (s.filter (OnLine line)).card ≤ 2 := by @@ -116,22 +98,17 @@ theorem principalLine_card_le_two {n : ℕ} {s : Finset (Point n)} have hbL : OnLine line b := (Finset.mem_filter.mp hb).2 have hcL : OnLine line c := (Finset.mem_filter.mp hc).2 have hab' : (⟨a, haS⟩ : ↥s) ≠ ⟨b, hbS⟩ := by - intro e - exact hab (congrArg Subtype.val e) + intro e; exact hab (congrArg Subtype.val e) have hac' : (⟨a, haS⟩ : ↥s) ≠ ⟨c, hcS⟩ := by - intro e - exact hac (congrArg Subtype.val e) + intro e; exact hac (congrArg Subtype.val e) have hbc' : (⟨b, hbS⟩ : ↥s) ≠ ⟨c, hcS⟩ := by - intro e - exact hbc (congrArg Subtype.val e) + intro e; exact hbc (congrArg Subtype.val e) exact hntil ⟨a, haS⟩ ⟨b, hbS⟩ ⟨c, hcS⟩ hab' hac' hbc' (principal_collinear haL hbL hcL) -/-- Weighted coverage of a point by all principal lines. -/ def coverage {n : ℕ} (weight : PrincipalLine n → ℕ) (p : Point n) : ℕ := ∑ line : PrincipalLine n, if OnLine line p then weight line else 0 -/-- Twice the total line weight, the capacity-two dual objective. -/ def certificateCost {n : ℕ} (weight : PrincipalLine n → ℕ) : ℕ := ∑ line : PrincipalLine n, 2 * weight line @@ -144,9 +121,17 @@ private theorem sum_indicator_eq_card_filter {α : Type*} [DecidableEq α] by_cases hP : P a · have hnot : a ∉ s.filter P := by intro hmem - exact ha (Finset.mem_of_mem_filter hmem) - simp [ha, hP, hnot, ih, Nat.add_mul, Nat.add_comm] - · simp [ha, hP, ih] + exact ha (Finset.mem_filter.mp hmem).1 + have hfilter : (insert a s).filter P = insert a (s.filter P) := by + ext x + simp [hP] + rw [Finset.sum_insert ha, if_pos hP, hfilter, Finset.card_insert hnot, ih] + simp [Nat.add_mul, Nat.add_comm] + · have hfilter : (insert a s).filter P = s.filter P := by + ext x + simp [hP] + rw [Finset.sum_insert ha, if_neg hP, hfilter, ih] + simp private theorem double_count {n : ℕ} (s : Finset (Point n)) (weight : PrincipalLine n → ℕ) : @@ -165,7 +150,6 @@ private theorem double_count {n : ℕ} (s : Finset (Point n)) intro line _ exact sum_indicator_eq_card_filter s (OnLine line) (weight line) -/-- Exact weighted line-cover inequality. -/ theorem certificate_bound {n q : ℕ} {s : Finset (Point n)} (weight : PrincipalLine n → ℕ) (hcover : ∀ p : ↥s, q ≤ coverage weight p.1) @@ -190,7 +174,6 @@ theorem certificate_bound {n q : ℕ} {s : Finset (Point n)} (s.filter (OnLine line)).card * weight line := double_count s weight _ ≤ certificateCost weight := hline -/-- A strict integral dual objective gives a cardinality upper bound. -/ theorem card_le_of_certificate {n parity q k : ℕ} {s : Finset (Point n)} (weight : PrincipalLine n → ℕ) (hq : 0 < q) (hcost : certificateCost weight < q * (k + 1)) From 4936f2638e273201cd22a57419ae20922f5009f0 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 23:42:05 -0700 Subject: [PATCH 16/59] Finish checkerboard fiber double counting --- Checkerboard/FiberSums.lean | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/Checkerboard/FiberSums.lean b/Checkerboard/FiberSums.lean index 0984162c..55ad6a2e 100644 --- a/Checkerboard/FiberSums.lean +++ b/Checkerboard/FiberSums.lean @@ -15,7 +15,6 @@ section variable {α β R : Type*} [DecidableEq α] [DecidableEq β] -/-- Cardinality of one fiber of `f` inside `s`. -/ def fiberCard (s : Finset α) (f : α → β) (b : β) : ℕ := (s.filter fun a => f a = b).card @@ -34,11 +33,22 @@ private theorem fiberCard_mul_eq_sum [CommSemiring R] by_cases h : f a = b · have hnot : a ∉ s.filter fun x => f x = b := by intro hmem - exact ha (Finset.mem_of_mem_filter hmem) - simp [fiberCard, ha, h, hnot, ih, add_mul] - · simp [fiberCard, ha, h, ih] + exact ha (Finset.mem_filter.mp hmem).1 + have hfilter : (insert a s).filter (fun x => f x = b) = + insert a (s.filter fun x => f x = b) := by + ext x + simp [h] + rw [fiberCard, hfilter, Finset.card_insert hnot, Nat.cast_add, add_mul] + rw [Finset.sum_insert ha, if_pos h] + exact congrArg (fun z => g b + z) ih + · have hfilter : (insert a s).filter (fun x => f x = b) = + s.filter fun x => f x = b := by + ext x + simp [h] + rw [fiberCard, hfilter] + rw [Finset.sum_insert ha, if_neg h] + exact ih -/-- Weighted double counting over all fibers. -/ theorem sum_fiberCard_mul [Fintype β] [CommSemiring R] (s : Finset α) (f : α → β) (g : β → R) : ∑ b : β, (fiberCard s f b : R) * g b = @@ -57,18 +67,15 @@ theorem sum_fiberCard_mul [Fintype β] [CommSemiring R] intro a _ simp -/-- Every element of a finite set belongs to exactly one fiber. -/ theorem sum_fiberCard [Fintype β] (s : Finset α) (f : α → β) : ∑ b : β, fiberCard s f b = s.card := by simpa using sum_fiberCard_mul (R := ℕ) s f (fun _ => 1) -/-- Unweighted point count as the sum of all fiber counts, cast to a semiring. -/ theorem sum_fiberCard_cast [Fintype β] [CommSemiring R] (s : Finset α) (f : α → β) : ∑ b : β, (fiberCard s f b : R) = (s.card : R) := by simpa using sum_fiberCard_mul (R := R) s f (fun _ => 1) -/-- A pointwise bound on fiber cardinalities sums to a global bound. -/ theorem card_le_sum_capacity [Fintype β] (s : Finset α) (f : α → β) (capacity : β → ℕ) (hcapacity : ∀ b, fiberCard s f b ≤ capacity b) : @@ -76,7 +83,6 @@ theorem card_le_sum_capacity [Fintype β] rw [← sum_fiberCard s f] exact Finset.sum_le_sum fun b _ => hcapacity b -/-- Real first moment of natural deficits. -/ theorem sum_defect_mul [Fintype β] (s : Finset α) (f : α → β) (capacity : β → ℕ) (coordinate : β → ℝ) @@ -97,7 +103,6 @@ theorem sum_defect_mul [Fintype β] ∑ a ∈ s, coordinate (f a) := by rw [sum_fiberCard_mul] -/-- Real second moment of natural deficits. -/ theorem sum_defect_mul_sq [Fintype β] (s : Finset α) (f : α → β) (capacity : β → ℕ) (coordinate : β → ℝ) From c6f5ef34bbe926cdb4b60c1da890a0f8f14eea39 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 23:42:32 -0700 Subject: [PATCH 17/59] Finish checkerboard polynomial sum distribution --- Checkerboard/PolynomialSums.lean | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Checkerboard/PolynomialSums.lean b/Checkerboard/PolynomialSums.lean index 3ee20fec..04909a02 100644 --- a/Checkerboard/PolynomialSums.lean +++ b/Checkerboard/PolynomialSums.lean @@ -27,7 +27,7 @@ theorem sum_range_quadratic_cap (N : ℕ) : 2 * ((N : ℚ) ^ 2 - ((j : ℚ) - N) ^ 2)) = 2 * (N : ℚ) * (2 * (N : ℚ) - 1) * (2 * (N : ℚ) + 1) / 3 := by have h := sum_range_affine_sq (2 * N + 1) (1 : ℚ) (-(N : ℚ)) - push_cast at h ⊢ + push_cast at h have hsum : (∑ j ∈ Finset.range (2 * N + 1), ((j : ℚ) - N) ^ 2) = ∑ j ∈ Finset.range (2 * N + 1), @@ -38,11 +38,13 @@ theorem sum_range_quadratic_cap (N : ℕ) : calc (∑ j ∈ Finset.range (2 * N + 1), 2 * ((N : ℚ) ^ 2 - ((j : ℚ) - N) ^ 2)) = - 2 * ((2 * (N : ℚ) + 1) * (N : ℚ) ^ 2 - - ∑ j ∈ Finset.range (2 * N + 1), - ((j : ℚ) - N) ^ 2) := by - simp only [Finset.sum_sub_distrib, Finset.sum_mul, - Finset.sum_const, Finset.card_range, nsmul_eq_mul] + 2 * (∑ j ∈ Finset.range (2 * N + 1), + ((N : ℚ) ^ 2 - ((j : ℚ) - N) ^ 2)) := by + rw [Finset.mul_sum] + _ = 2 * ((2 * (N : ℚ) + 1) * (N : ℚ) ^ 2 - + ∑ j ∈ Finset.range (2 * N + 1), ((j : ℚ) - N) ^ 2) := by + rw [Finset.sum_sub_distrib] + simp only [Finset.sum_const, Finset.card_range, nsmul_eq_mul] ring _ = 2 * (N : ℚ) * (2 * (N : ℚ) - 1) * (2 * (N : ℚ) + 1) / 3 := by @@ -129,11 +131,15 @@ theorem odd_quadratic_cap_sum (m : ℕ) : (∑ r ∈ Finset.range (2 * m), 2 * ((2 * (m : ℚ)) ^ 2 - (2 * (r : ℚ) + 1 - 2 * (m : ℚ)) ^ 2)) = - 2 * ((2 * (m : ℚ)) * (2 * (m : ℚ)) ^ 2 - + 2 * (∑ r ∈ Finset.range (2 * m), + ((2 * (m : ℚ)) ^ 2 - + (2 * (r : ℚ) + 1 - 2 * (m : ℚ)) ^ 2)) := by + rw [Finset.mul_sum] + _ = 2 * ((2 * (m : ℚ)) * (2 * (m : ℚ)) ^ 2 - ∑ r ∈ Finset.range (2 * m), (2 * (r : ℚ) + (1 - 2 * (m : ℚ))) ^ 2) := by - simp only [Finset.sum_sub_distrib, Finset.sum_mul, - Finset.sum_const, Finset.card_range, nsmul_eq_mul] + rw [Finset.sum_sub_distrib] + simp only [Finset.sum_const, Finset.card_range, nsmul_eq_mul] ring _ = 4 * (m : ℚ) * (8 * (m : ℚ) ^ 2 + 1) / 3 := by rw [h] From 7341d15edb689ae7ac5fe23f19a086c6d441724b Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 23:49:59 -0700 Subject: [PATCH 18/59] Use explicit filter cases in checkerboard model --- Checkerboard/Model.lean | 93 ++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 58 deletions(-) diff --git a/Checkerboard/Model.lean b/Checkerboard/Model.lean index 6759eaa1..08af06af 100644 --- a/Checkerboard/Model.lean +++ b/Checkerboard/Model.lean @@ -1,13 +1,5 @@ import Mathlib -/-! -# Finite checkerboard no-three-in-line model - -This file gives a self-contained finite model of monochromatic checkerboard -point sets, Euclidean collinearity, the four principal line families, and a -kernel-checked weighted line-cover bound. --/ - namespace Checkerboard abbrev Point (n : ℕ) := Fin n × Fin n @@ -33,10 +25,7 @@ def IsExactMaximum (n parity k : ℕ) : Prop := Monochromatic parity s → NoThreeInLine s → s.card ≤ k inductive LineFamily - | row - | column - | sum - | difference + | row | column | sum | difference deriving DecidableEq, Fintype, Repr abbrev PrincipalLine (n : ℕ) := LineFamily × Fin (2 * n - 1) @@ -69,18 +58,14 @@ theorem principal_collinear {n : ℕ} {line : PrincipalLine n} simp [determinant, ha, hb, hc] | sum => simp only [OnLine, lineValue] at ha hb hc - have hba : ((b.2.1 : ℤ) - (a.2.1 : ℤ)) = - -((b.1.1 : ℤ) - (a.1.1 : ℤ)) := by linarith - have hca : ((c.2.1 : ℤ) - (a.2.1 : ℤ)) = - -((c.1.1 : ℤ) - (a.1.1 : ℤ)) := by linarith + have hba : ((b.2.1 : ℤ) - (a.2.1 : ℤ)) = -((b.1.1 : ℤ) - (a.1.1 : ℤ)) := by linarith + have hca : ((c.2.1 : ℤ) - (a.2.1 : ℤ)) = -((c.1.1 : ℤ) - (a.1.1 : ℤ)) := by linarith rw [determinant, hba, hca] ring | difference => simp only [OnLine, lineValue] at ha hb hc - have hba : ((b.2.1 : ℤ) - (a.2.1 : ℤ)) = - ((b.1.1 : ℤ) - (a.1.1 : ℤ)) := by linarith - have hca : ((c.2.1 : ℤ) - (a.2.1 : ℤ)) = - ((c.1.1 : ℤ) - (a.1.1 : ℤ)) := by linarith + have hba : ((b.2.1 : ℤ) - (a.2.1 : ℤ)) = ((b.1.1 : ℤ) - (a.1.1 : ℤ)) := by linarith + have hca : ((c.2.1 : ℤ) - (a.2.1 : ℤ)) = ((c.1.1 : ℤ) - (a.1.1 : ℤ)) := by linarith rw [determinant, hba, hca] ring @@ -89,20 +74,16 @@ theorem principalLine_card_le_two {n : ℕ} {s : Finset (Point n)} (s.filter (OnLine line)).card ≤ 2 := by by_contra h have hthree : 2 < (s.filter (OnLine line)).card := Nat.lt_of_not_ge h - obtain ⟨a, ha, b, hb, c, hc, hab, hac, hbc⟩ := - Finset.two_lt_card.mp hthree - have haS : a ∈ s := (Finset.mem_filter.mp ha).1 - have hbS : b ∈ s := (Finset.mem_filter.mp hb).1 - have hcS : c ∈ s := (Finset.mem_filter.mp hc).1 - have haL : OnLine line a := (Finset.mem_filter.mp ha).2 - have hbL : OnLine line b := (Finset.mem_filter.mp hb).2 - have hcL : OnLine line c := (Finset.mem_filter.mp hc).2 - have hab' : (⟨a, haS⟩ : ↥s) ≠ ⟨b, hbS⟩ := by - intro e; exact hab (congrArg Subtype.val e) - have hac' : (⟨a, haS⟩ : ↥s) ≠ ⟨c, hcS⟩ := by - intro e; exact hac (congrArg Subtype.val e) - have hbc' : (⟨b, hbS⟩ : ↥s) ≠ ⟨c, hcS⟩ := by - intro e; exact hbc (congrArg Subtype.val e) + obtain ⟨a, ha, b, hb, c, hc, hab, hac, hbc⟩ := Finset.two_lt_card.mp hthree + have haS := (Finset.mem_filter.mp ha).1 + have hbS := (Finset.mem_filter.mp hb).1 + have hcS := (Finset.mem_filter.mp hc).1 + have haL := (Finset.mem_filter.mp ha).2 + have hbL := (Finset.mem_filter.mp hb).2 + have hcL := (Finset.mem_filter.mp hc).2 + have hab' : (⟨a, haS⟩ : ↥s) ≠ ⟨b, hbS⟩ := by intro e; exact hab (congrArg Subtype.val e) + have hac' : (⟨a, haS⟩ : ↥s) ≠ ⟨c, hcS⟩ := by intro e; exact hac (congrArg Subtype.val e) + have hbc' : (⟨b, hbS⟩ : ↥s) ≠ ⟨c, hcS⟩ := by intro e; exact hbc (congrArg Subtype.val e) exact hntil ⟨a, haS⟩ ⟨b, hbS⟩ ⟨c, hcS⟩ hab' hac' hbc' (principal_collinear haL hbL hcL) @@ -124,12 +105,16 @@ private theorem sum_indicator_eq_card_filter {α : Type*} [DecidableEq α] exact ha (Finset.mem_filter.mp hmem).1 have hfilter : (insert a s).filter P = insert a (s.filter P) := by ext x - simp [hP] - rw [Finset.sum_insert ha, if_pos hP, hfilter, Finset.card_insert hnot, ih] - simp [Nat.add_mul, Nat.add_comm] + by_cases hxa : x = a + · subst x; simp [ha, hP] + · simp [hxa] + rw [Finset.sum_insert ha, if_pos hP, hfilter, ih] + simp [hnot, Nat.add_mul, Nat.add_comm] · have hfilter : (insert a s).filter P = s.filter P := by ext x - simp [hP] + by_cases hxa : x = a + · subst x; simp [ha, hP] + · simp [hxa] rw [Finset.sum_insert ha, if_neg hP, hfilter, ih] simp @@ -139,47 +124,39 @@ private theorem double_count {n : ℕ} (s : Finset (Point n)) ∑ line : PrincipalLine n, (s.filter (OnLine line)).card * weight line := by calc (∑ p ∈ s, coverage weight p) = - ∑ p ∈ s, ∑ line : PrincipalLine n, - if OnLine line p then weight line else 0 := by rfl - _ = ∑ line : PrincipalLine n, ∑ p ∈ s, - if OnLine line p then weight line else 0 := by - rw [Finset.sum_comm] - _ = ∑ line : PrincipalLine n, - (s.filter (OnLine line)).card * weight line := by - apply Finset.sum_congr rfl - intro line _ - exact sum_indicator_eq_card_filter s (OnLine line) (weight line) + ∑ p ∈ s, ∑ line : PrincipalLine n, if OnLine line p then weight line else 0 := by rfl + _ = ∑ line : PrincipalLine n, ∑ p ∈ s, if OnLine line p then weight line else 0 := by + rw [Finset.sum_comm] + _ = ∑ line : PrincipalLine n, (s.filter (OnLine line)).card * weight line := by + apply Finset.sum_congr rfl + intro line _ + exact sum_indicator_eq_card_filter s (OnLine line) (weight line) theorem certificate_bound {n q : ℕ} {s : Finset (Point n)} (weight : PrincipalLine n → ℕ) (hcover : ∀ p : ↥s, q ≤ coverage weight p.1) - (hntil : NoThreeInLine s) : - q * s.card ≤ certificateCost weight := by + (hntil : NoThreeInLine s) : q * s.card ≤ certificateCost weight := by have hpoint : (∑ p ∈ s, q) ≤ ∑ p ∈ s, coverage weight p := by apply Finset.sum_le_sum intro p hp exact hcover ⟨p, hp⟩ have hline : - (∑ line : PrincipalLine n, - (s.filter (OnLine line)).card * weight line) ≤ + (∑ line : PrincipalLine n, (s.filter (OnLine line)).card * weight line) ≤ certificateCost weight := by apply Finset.sum_le_sum intro line _ - exact Nat.mul_le_mul_right (weight line) - (principalLine_card_le_two hntil line) + exact Nat.mul_le_mul_right (weight line) (principalLine_card_le_two hntil line) calc q * s.card = ∑ _p ∈ s, q := by simp [Nat.mul_comm] _ ≤ ∑ p ∈ s, coverage weight p := hpoint - _ = ∑ line : PrincipalLine n, - (s.filter (OnLine line)).card * weight line := double_count s weight + _ = ∑ line : PrincipalLine n, (s.filter (OnLine line)).card * weight line := double_count s weight _ ≤ certificateCost weight := hline theorem card_le_of_certificate {n parity q k : ℕ} {s : Finset (Point n)} (weight : PrincipalLine n → ℕ) (hq : 0 < q) (hcost : certificateCost weight < q * (k + 1)) (hglobal : ∀ p : Point n, InColor parity p → q ≤ coverage weight p) - (hcolor : Monochromatic parity s) (hntil : NoThreeInLine s) : - s.card ≤ k := by + (hcolor : Monochromatic parity s) (hntil : NoThreeInLine s) : s.card ≤ k := by have hb := certificate_bound weight (fun p => hglobal p.1 (hcolor p)) hntil have hmul : q * s.card < q * (k + 1) := lt_of_le_of_lt hb hcost have hlt : s.card < k + 1 := (Nat.mul_lt_mul_left hq).mp hmul From eff6b30330bd6b90025357d3b787d15dac964c4e Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 23:50:19 -0700 Subject: [PATCH 19/59] Use explicit filter cases in checkerboard fiber sums --- Checkerboard/FiberSums.lean | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/Checkerboard/FiberSums.lean b/Checkerboard/FiberSums.lean index 55ad6a2e..2c7a2b0c 100644 --- a/Checkerboard/FiberSums.lean +++ b/Checkerboard/FiberSums.lean @@ -1,12 +1,5 @@ import Mathlib -/-! -# Exact finite fiber sums - -Elementary double-counting lemmas used to pass between sums over selected board -points and sums over rows, columns, or diagonal fibers. --/ - namespace Checkerboard open scoped BigOperators @@ -19,8 +12,7 @@ def fiberCard (s : Finset α) (f : α → β) (b : β) : ℕ := (s.filter fun a => f a = b).card @[simp] theorem fiberCard_empty (f : α → β) (b : β) : - fiberCard ∅ f b = 0 := by - simp [fiberCard] + fiberCard ∅ f b = 0 := by simp [fiberCard] private theorem fiberCard_mul_eq_sum [CommSemiring R] (s : Finset α) (f : α → β) (b : β) (g : β → R) : @@ -37,17 +29,21 @@ private theorem fiberCard_mul_eq_sum [CommSemiring R] have hfilter : (insert a s).filter (fun x => f x = b) = insert a (s.filter fun x => f x = b) := by ext x - simp [h] - rw [fiberCard, hfilter, Finset.card_insert hnot, Nat.cast_add, add_mul] + by_cases hxa : x = a + · subst x; simp [ha, h] + · simp [hxa] + rw [fiberCard, hfilter] rw [Finset.sum_insert ha, if_pos h] - exact congrArg (fun z => g b + z) ih + simp [hnot, ih, add_mul] · have hfilter : (insert a s).filter (fun x => f x = b) = s.filter fun x => f x = b := by ext x - simp [h] + by_cases hxa : x = a + · subst x; simp [ha, h] + · simp [hxa] rw [fiberCard, hfilter] rw [Finset.sum_insert ha, if_neg h] - exact ih + simpa [fiberCard] using ih theorem sum_fiberCard_mul [Fintype β] [CommSemiring R] (s : Finset α) (f : α → β) (g : β → R) : From d59a5abcbdca0a41f874b5a8b568e32ea8a29dfe Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 23:50:45 -0700 Subject: [PATCH 20/59] Normalize casts in checkerboard polynomial sums --- Checkerboard/PolynomialSums.lean | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/Checkerboard/PolynomialSums.lean b/Checkerboard/PolynomialSums.lean index 04909a02..42f25401 100644 --- a/Checkerboard/PolynomialSums.lean +++ b/Checkerboard/PolynomialSums.lean @@ -1,14 +1,9 @@ import Mathlib -/-! -# Exact polynomial sums used by the all-n line cover --/ - namespace Checkerboard open scoped BigOperators -/-- Sum of an affine square over `0, …, n-1`. -/ theorem sum_range_affine_sq (n : ℕ) (a b : ℚ) : (∑ i ∈ Finset.range n, (a * (i : ℚ) + b) ^ 2) = a ^ 2 * ((n : ℚ) * ((n : ℚ) - 1) * (2 * (n : ℚ) - 1) / 6) + @@ -21,7 +16,6 @@ theorem sum_range_affine_sq (n : ℕ) (a b : ℚ) : push_cast ring -/-- Sum of a quadratic cap centered at `N` on the full interval `0, …, 2N`. -/ theorem sum_range_quadratic_cap (N : ℕ) : (∑ j ∈ Finset.range (2 * N + 1), 2 * ((N : ℚ) ^ 2 - ((j : ℚ) - N) ^ 2)) = @@ -45,13 +39,13 @@ theorem sum_range_quadratic_cap (N : ℕ) : ∑ j ∈ Finset.range (2 * N + 1), ((j : ℚ) - N) ^ 2) := by rw [Finset.sum_sub_distrib] simp only [Finset.sum_const, Finset.card_range, nsmul_eq_mul] + push_cast ring _ = 2 * (N : ℚ) * (2 * (N : ℚ) - 1) * (2 * (N : ℚ) + 1) / 3 := by rw [hsum, h] ring -/-- Extract the even-indexed terms from a range of even length. -/ theorem sum_range_even_terms (k : ℕ) (f : ℕ → ℚ) : (∑ j ∈ Finset.range (2 * k), if j % 2 = 0 then f j else 0) = ∑ r ∈ Finset.range k, f (2 * r) := by @@ -62,7 +56,6 @@ theorem sum_range_even_terms (k : ℕ) (f : ℕ → ℚ) : rw [ih] norm_num [Nat.add_mod, Nat.mul_mod] -/-- Extract the odd-indexed terms from a range of even length. -/ theorem sum_range_odd_terms (k : ℕ) (f : ℕ → ℚ) : (∑ j ∈ Finset.range (2 * k), if j % 2 = 1 then f j else 0) = ∑ r ∈ Finset.range k, f (2 * r + 1) := by @@ -73,21 +66,18 @@ theorem sum_range_odd_terms (k : ℕ) (f : ℕ → ℚ) : rw [ih] norm_num [Nat.add_mod, Nat.mul_mod] -/-- Even-indexed terms in a range ending at an even index. -/ theorem sum_range_even_terms_succ (k : ℕ) (f : ℕ → ℚ) : (∑ j ∈ Finset.range (2 * k + 1), if j % 2 = 0 then f j else 0) = ∑ r ∈ Finset.range (k + 1), f (2 * r) := by rw [Finset.sum_range_succ, sum_range_even_terms, Finset.sum_range_succ] norm_num [Nat.add_mod, Nat.mul_mod] -/-- Odd-indexed terms in a range ending at an even index. -/ theorem sum_range_odd_terms_succ (k : ℕ) (f : ℕ → ℚ) : (∑ j ∈ Finset.range (2 * k + 1), if j % 2 = 1 then f j else 0) = ∑ r ∈ Finset.range k, f (2 * r + 1) := by rw [Finset.sum_range_succ, sum_range_odd_terms] norm_num [Nat.add_mod, Nat.mul_mod] -/-- Even offsets in the quadratic cap on `-2m, …, 2m`. -/ theorem even_quadratic_cap_sum (m : ℕ) : (∑ j ∈ Finset.range (4 * m + 1), if j % 2 = 0 then @@ -114,7 +104,6 @@ theorem even_quadratic_cap_sum (m : ℕ) : rw [h] ring -/-- Odd offsets in the quadratic cap on `-2m, …, 2m`. -/ theorem odd_quadratic_cap_sum (m : ℕ) : (∑ j ∈ Finset.range (4 * m + 1), if j % 2 = 1 then @@ -140,6 +129,7 @@ theorem odd_quadratic_cap_sum (m : ℕ) : (2 * (r : ℚ) + (1 - 2 * (m : ℚ))) ^ 2) := by rw [Finset.sum_sub_distrib] simp only [Finset.sum_const, Finset.card_range, nsmul_eq_mul] + push_cast ring _ = 4 * (m : ℚ) * (8 * (m : ℚ) ^ 2 + 1) / 3 := by rw [h] From 7b50bfed40cd5ac24897fe8244af48e0cfa7aab2 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 23:59:10 -0700 Subject: [PATCH 21/59] Close checkerboard fiber commutativity goal --- Checkerboard/FiberSums.lean | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Checkerboard/FiberSums.lean b/Checkerboard/FiberSums.lean index 2c7a2b0c..7cfe45f1 100644 --- a/Checkerboard/FiberSums.lean +++ b/Checkerboard/FiberSums.lean @@ -34,7 +34,10 @@ private theorem fiberCard_mul_eq_sum [CommSemiring R] · simp [hxa] rw [fiberCard, hfilter] rw [Finset.sum_insert ha, if_pos h] - simp [hnot, ih, add_mul] + simp only [Finset.card_insert_of_notMem hnot, Nat.cast_add, Nat.cast_one, + add_mul, one_mul] + rw [ih] + ac_rfl · have hfilter : (insert a s).filter (fun x => f x = b) = s.filter fun x => f x = b := by ext x From 0a9bbc29df42110e9a4cc72e0591a60d6df554c6 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 23:59:31 -0700 Subject: [PATCH 22/59] Make checkerboard Fin polynomial specialization explicit --- Checkerboard/FinPolynomialSums.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Checkerboard/FinPolynomialSums.lean b/Checkerboard/FinPolynomialSums.lean index 21b5150a..9f3c014a 100644 --- a/Checkerboard/FinPolynomialSums.lean +++ b/Checkerboard/FinPolynomialSums.lean @@ -25,8 +25,8 @@ theorem sum_fin_affine_sq (n : ℕ) (a b : ℚ) : theorem axis_quadratic_sum (n : ℕ) : (∑ i : Fin n, (2 * (i.1 : ℚ) - ((n : ℚ) - 1)) ^ 2) = (n : ℚ) * ((n : ℚ) ^ 2 - 1) / 3 := by - rw [sum_fin_affine_sq] - ring + have h := sum_fin_affine_sq n (2 : ℚ) (1 - (n : ℚ)) + convert h using 1 <;> ring /-- Full sum of a quadratic diagonal cap over `Fin (2N+1)`. -/ theorem fin_quadratic_cap_sum (N : ℕ) : From c68bff69ac764e75a2ac2523b0c759047ebc55b5 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 00:06:24 -0700 Subject: [PATCH 23/59] Unfold checkerboard fiber induction hypothesis --- Checkerboard/FiberSums.lean | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Checkerboard/FiberSums.lean b/Checkerboard/FiberSums.lean index 7cfe45f1..3ab7902d 100644 --- a/Checkerboard/FiberSums.lean +++ b/Checkerboard/FiberSums.lean @@ -32,11 +32,15 @@ private theorem fiberCard_mul_eq_sum [CommSemiring R] by_cases hxa : x = a · subst x; simp [ha, h] · simp [hxa] + have ih' : + ((s.filter fun x => f x = b).card : R) * g b = + ∑ x ∈ s, if f x = b then g b else 0 := by + simpa [fiberCard] using ih rw [fiberCard, hfilter] rw [Finset.sum_insert ha, if_pos h] simp only [Finset.card_insert_of_notMem hnot, Nat.cast_add, Nat.cast_one, add_mul, one_mul] - rw [ih] + rw [ih'] ac_rfl · have hfilter : (insert a s).filter (fun x => f x = b) = s.filter fun x => f x = b := by From 03d2e3dca3740d8557ddccf0938b576ad56da2da Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 00:06:45 -0700 Subject: [PATCH 24/59] Separate checkerboard axis pointwise normalization --- Checkerboard/FinPolynomialSums.lean | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Checkerboard/FinPolynomialSums.lean b/Checkerboard/FinPolynomialSums.lean index 9f3c014a..a082ecb7 100644 --- a/Checkerboard/FinPolynomialSums.lean +++ b/Checkerboard/FinPolynomialSums.lean @@ -26,7 +26,16 @@ theorem axis_quadratic_sum (n : ℕ) : (∑ i : Fin n, (2 * (i.1 : ℚ) - ((n : ℚ) - 1)) ^ 2) = (n : ℚ) * ((n : ℚ) ^ 2 - 1) / 3 := by have h := sum_fin_affine_sq n (2 : ℚ) (1 - (n : ℚ)) - convert h using 1 <;> ring + calc + (∑ i : Fin n, (2 * (i.1 : ℚ) - ((n : ℚ) - 1)) ^ 2) = + ∑ i : Fin n, (2 * (i.1 : ℚ) + (1 - (n : ℚ))) ^ 2 := by + apply Finset.sum_congr rfl + intro i _ + ring + _ = 2 ^ 2 * ((n : ℚ) * ((n : ℚ) - 1) * (2 * (n : ℚ) - 1) / 6) + + 2 * 2 * (1 - (n : ℚ)) * ((n : ℚ) * ((n : ℚ) - 1) / 2) + + (n : ℚ) * (1 - (n : ℚ)) ^ 2 := h + _ = (n : ℚ) * ((n : ℚ) ^ 2 - 1) / 3 := by ring /-- Full sum of a quadratic diagonal cap over `Fin (2N+1)`. -/ theorem fin_quadratic_cap_sum (N : ℕ) : From 8b74711053b5fe6069ca2e9c42e52c2b1c168146 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 00:14:12 -0700 Subject: [PATCH 25/59] Make checkerboard row and column collinearity explicit --- Checkerboard/FourCertificate.lean | 46 +++++++++++++------------------ 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/Checkerboard/FourCertificate.lean b/Checkerboard/FourCertificate.lean index c336fe6b..bf4ae4a6 100644 --- a/Checkerboard/FourCertificate.lean +++ b/Checkerboard/FourCertificate.lean @@ -13,27 +13,22 @@ namespace Checkerboard open scoped BigOperators -/-- Index of the sum diagonal through a board point. -/ def sumIndex {n : ℕ} (p : Point n) : Fin (2 * n - 1) := ⟨p.1.1 + p.2.1, by omega⟩ -/-- Index of the difference diagonal, shifted to the interval `0, …, 2n-2`. -/ def differenceIndex {n : ℕ} (p : Point n) : Fin (2 * n - 1) := ⟨p.1.1 + (n - 1 - p.2.1), by omega⟩ -/-- Rational weights on the four principal line families. -/ structure FourWeights (n : ℕ) where row : Fin n → ℚ column : Fin n → ℚ sum : Fin (2 * n - 1) → ℚ difference : Fin (2 * n - 1) → ℚ -/-- Coverage of one point by its four incident principal lines. -/ def fourCoverage {n : ℕ} (w : FourWeights n) (p : Point n) : ℚ := w.row p.1 + w.column p.2 + w.sum (sumIndex p) + w.difference (differenceIndex p) -/-- Capacity-two objective of a four-direction line cover. -/ def fourCost {n : ℕ} (w : FourWeights n) : ℚ := 2 * ((∑ i, w.row i) + (∑ i, w.column i) + (∑ i, w.sum i) + ∑ i, w.difference i) @@ -69,7 +64,6 @@ private theorem fiberCard_le_two_of_collinear exact hntil ⟨a, haS⟩ ⟨b, hbS⟩ ⟨c, hcS⟩ hab' hac' hbc' (hcollinear (haf.trans hbf.symm) (haf.trans hcf.symm)) -/-- A no-three-in-line set occupies each row at most twice. -/ theorem rowFiber_le_two {n : ℕ} {s : Finset (Point n)} (hntil : NoThreeInLine s) (i : Fin n) : fiberCard s (fun p : Point n => p.1) i ≤ 2 := by @@ -77,9 +71,13 @@ theorem rowFiber_le_two {n : ℕ} {s : Finset (Point n)} intro a b c hab hac have habv : a.1.1 = b.1.1 := congrArg Fin.val hab have hacv : a.1.1 = c.1.1 := congrArg Fin.val hac - simp [determinant, habv, hacv] + have hba : (b.1.1 : ℤ) - (a.1.1 : ℤ) = 0 := by + exact_mod_cast habv.symm + have hca : (c.1.1 : ℤ) - (a.1.1 : ℤ) = 0 := by + exact_mod_cast hacv.symm + rw [determinant, hba, hca] + ring -/-- A no-three-in-line set occupies each column at most twice. -/ theorem columnFiber_le_two {n : ℕ} {s : Finset (Point n)} (hntil : NoThreeInLine s) (i : Fin n) : fiberCard s (fun p : Point n => p.2) i ≤ 2 := by @@ -87,18 +85,20 @@ theorem columnFiber_le_two {n : ℕ} {s : Finset (Point n)} intro a b c hab hac have habv : a.2.1 = b.2.1 := congrArg Fin.val hab have hacv : a.2.1 = c.2.1 := congrArg Fin.val hac - simp [determinant, habv, hacv] + have hba : (b.2.1 : ℤ) - (a.2.1 : ℤ) = 0 := by + exact_mod_cast habv.symm + have hca : (c.2.1 : ℤ) - (a.2.1 : ℤ) = 0 := by + exact_mod_cast hacv.symm + rw [determinant, hba, hca] + ring -/-- A no-three-in-line set occupies each sum diagonal at most twice. -/ theorem sumFiber_le_two {n : ℕ} {s : Finset (Point n)} (hntil : NoThreeInLine s) (i : Fin (2 * n - 1)) : fiberCard s sumIndex i ≤ 2 := by apply fiberCard_le_two_of_collinear hntil sumIndex intro a b c hab hac - have habv : a.1.1 + a.2.1 = b.1.1 + b.2.1 := - congrArg Fin.val hab - have hacv : a.1.1 + a.2.1 = c.1.1 + c.2.1 := - congrArg Fin.val hac + have habv : a.1.1 + a.2.1 = b.1.1 + b.2.1 := congrArg Fin.val hab + have hacv : a.1.1 + a.2.1 = c.1.1 + c.2.1 := congrArg Fin.val hac have habz : (a.1.1 : ℤ) + a.2.1 = (b.1.1 : ℤ) + b.2.1 := by exact_mod_cast habv have hacz : (a.1.1 : ℤ) + a.2.1 = (c.1.1 : ℤ) + c.2.1 := by @@ -110,7 +110,6 @@ theorem sumFiber_le_two {n : ℕ} {s : Finset (Point n)} rw [determinant, hb, hc] ring -/-- A no-three-in-line set occupies each difference diagonal at most twice. -/ theorem differenceFiber_le_two {n : ℕ} {s : Finset (Point n)} (hntil : NoThreeInLine s) (i : Fin (2 * n - 1)) : fiberCard s differenceIndex i ≤ 2 := by @@ -140,8 +139,7 @@ private theorem weightedFibers_le_two (s : Finset α) (f : α → β) (weight : β → ℚ) (hweight : ∀ i, 0 ≤ weight i) (hcard : ∀ i, fiberCard s f i ≤ 2) : - (∑ i, (fiberCard s f i : ℚ) * weight i) ≤ - 2 * ∑ i, weight i := by + (∑ i, (fiberCard s f i : ℚ) * weight i) ≤ 2 * ∑ i, weight i := by rw [Finset.mul_sum] apply Finset.sum_le_sum intro i _ @@ -149,7 +147,6 @@ private theorem weightedFibers_le_two exact_mod_cast hcard i nlinarith [hweight i] -/-- Exact capacity-two upper bound supplied by any nonnegative rational cover. -/ theorem fourCertificate_bound {n : ℕ} {s : Finset (Point n)} (w : FourWeights n) (hrow : ∀ i, 0 ≤ w.row i) @@ -168,10 +165,8 @@ theorem fourCertificate_bound {n : ℕ} {s : Finset (Point n)} (columnFiber_le_two hntil) have hs : (∑ p ∈ s, w.sum (sumIndex p)) ≤ 2 * ∑ i, w.sum i := by rw [← sum_fiberCard_mul (R := ℚ) s sumIndex w.sum] - exact weightedFibers_le_two s sumIndex w.sum hsum - (sumFiber_le_two hntil) - have hd : (∑ p ∈ s, w.difference (differenceIndex p)) ≤ - 2 * ∑ i, w.difference i := by + exact weightedFibers_le_two s sumIndex w.sum hsum (sumFiber_le_two hntil) + have hd : (∑ p ∈ s, w.difference (differenceIndex p)) ≤ 2 * ∑ i, w.difference i := by rw [← sum_fiberCard_mul (R := ℚ) s differenceIndex w.difference] exact weightedFibers_le_two s differenceIndex w.difference hdifference (differenceFiber_le_two hntil) @@ -188,7 +183,6 @@ theorem fourCertificate_bound {n : ℕ} {s : Finset (Point n)} simp [fourCost] ring -/-- A positive cover whose objective is below `q(k+1)` proves `|s| ≤ k`. -/ theorem card_le_of_fourCertificate {n k : ℕ} {q : ℚ} {s : Finset (Point n)} (w : FourWeights n) (hq : 0 < q) @@ -207,10 +201,8 @@ theorem card_le_of_fourCertificate {n k : ℕ} {q : ℚ} intro p hp exact hcover ⟨p, hp⟩ have hupper := fourCertificate_bound w hrow hcolumn hsum hdifference hntil - have hltQ : (s.card : ℚ) < k + 1 := by - nlinarith - have hltN : s.card < k + 1 := by - exact_mod_cast hltQ + have hltQ : (s.card : ℚ) < k + 1 := by nlinarith + have hltN : s.card < k + 1 := by exact_mod_cast hltQ omega end Checkerboard From b6b2e5541702a09f89a0176bae2dc0c7899a01c4 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 00:24:23 -0700 Subject: [PATCH 26/59] Fix checkerboard casted coordinate differences --- Checkerboard/FourCertificate.lean | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Checkerboard/FourCertificate.lean b/Checkerboard/FourCertificate.lean index bf4ae4a6..8c1304b5 100644 --- a/Checkerboard/FourCertificate.lean +++ b/Checkerboard/FourCertificate.lean @@ -71,10 +71,12 @@ theorem rowFiber_le_two {n : ℕ} {s : Finset (Point n)} intro a b c hab hac have habv : a.1.1 = b.1.1 := congrArg Fin.val hab have hacv : a.1.1 = c.1.1 := congrArg Fin.val hac - have hba : (b.1.1 : ℤ) - (a.1.1 : ℤ) = 0 := by + have hbaEq : (b.1.1 : ℤ) = (a.1.1 : ℤ) := by exact_mod_cast habv.symm - have hca : (c.1.1 : ℤ) - (a.1.1 : ℤ) = 0 := by + have hcaEq : (c.1.1 : ℤ) = (a.1.1 : ℤ) := by exact_mod_cast hacv.symm + have hba : (b.1.1 : ℤ) - (a.1.1 : ℤ) = 0 := sub_eq_zero.mpr hbaEq + have hca : (c.1.1 : ℤ) - (a.1.1 : ℤ) = 0 := sub_eq_zero.mpr hcaEq rw [determinant, hba, hca] ring @@ -85,10 +87,12 @@ theorem columnFiber_le_two {n : ℕ} {s : Finset (Point n)} intro a b c hab hac have habv : a.2.1 = b.2.1 := congrArg Fin.val hab have hacv : a.2.1 = c.2.1 := congrArg Fin.val hac - have hba : (b.2.1 : ℤ) - (a.2.1 : ℤ) = 0 := by + have hbaEq : (b.2.1 : ℤ) = (a.2.1 : ℤ) := by exact_mod_cast habv.symm - have hca : (c.2.1 : ℤ) - (a.2.1 : ℤ) = 0 := by + have hcaEq : (c.2.1 : ℤ) = (a.2.1 : ℤ) := by exact_mod_cast hacv.symm + have hba : (b.2.1 : ℤ) - (a.2.1 : ℤ) = 0 := sub_eq_zero.mpr hbaEq + have hca : (c.2.1 : ℤ) - (a.2.1 : ℤ) = 0 := sub_eq_zero.mpr hcaEq rw [determinant, hba, hca] ring From 5b1a99ff750a6160c7e284dee3c62f85e2262dfa Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 00:49:26 -0700 Subject: [PATCH 27/59] Rewrite checkerboard row and column coordinates directly --- Checkerboard/FourCertificate.lean | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/Checkerboard/FourCertificate.lean b/Checkerboard/FourCertificate.lean index 8c1304b5..d554d450 100644 --- a/Checkerboard/FourCertificate.lean +++ b/Checkerboard/FourCertificate.lean @@ -69,32 +69,18 @@ theorem rowFiber_le_two {n : ℕ} {s : Finset (Point n)} fiberCard s (fun p : Point n => p.1) i ≤ 2 := by apply fiberCard_le_two_of_collinear hntil (fun p : Point n => p.1) intro a b c hab hac - have habv : a.1.1 = b.1.1 := congrArg Fin.val hab - have hacv : a.1.1 = c.1.1 := congrArg Fin.val hac - have hbaEq : (b.1.1 : ℤ) = (a.1.1 : ℤ) := by - exact_mod_cast habv.symm - have hcaEq : (c.1.1 : ℤ) = (a.1.1 : ℤ) := by - exact_mod_cast hacv.symm - have hba : (b.1.1 : ℤ) - (a.1.1 : ℤ) = 0 := sub_eq_zero.mpr hbaEq - have hca : (c.1.1 : ℤ) - (a.1.1 : ℤ) = 0 := sub_eq_zero.mpr hcaEq - rw [determinant, hba, hca] - ring + have hb : b.1 = a.1 := hab.symm + have hc : c.1 = a.1 := hac.symm + simp [determinant, hb, hc] theorem columnFiber_le_two {n : ℕ} {s : Finset (Point n)} (hntil : NoThreeInLine s) (i : Fin n) : fiberCard s (fun p : Point n => p.2) i ≤ 2 := by apply fiberCard_le_two_of_collinear hntil (fun p : Point n => p.2) intro a b c hab hac - have habv : a.2.1 = b.2.1 := congrArg Fin.val hab - have hacv : a.2.1 = c.2.1 := congrArg Fin.val hac - have hbaEq : (b.2.1 : ℤ) = (a.2.1 : ℤ) := by - exact_mod_cast habv.symm - have hcaEq : (c.2.1 : ℤ) = (a.2.1 : ℤ) := by - exact_mod_cast hacv.symm - have hba : (b.2.1 : ℤ) - (a.2.1 : ℤ) = 0 := sub_eq_zero.mpr hbaEq - have hca : (c.2.1 : ℤ) - (a.2.1 : ℤ) = 0 := sub_eq_zero.mpr hcaEq - rw [determinant, hba, hca] - ring + have hb : b.2 = a.2 := hab.symm + have hc : c.2 = a.2 := hac.symm + simp [determinant, hb, hc] theorem sumFiber_le_two {n : ℕ} {s : Finset (Point n)} (hntil : NoThreeInLine s) (i : Fin (2 * n - 1)) : From 252758d38c73560b4580a3fac82408300988522a Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 01:29:08 -0700 Subject: [PATCH 28/59] Normalize checkerboard even-board casts --- Checkerboard/QuadraticWeights.lean | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Checkerboard/QuadraticWeights.lean b/Checkerboard/QuadraticWeights.lean index a718dab8..732beeb5 100644 --- a/Checkerboard/QuadraticWeights.lean +++ b/Checkerboard/QuadraticWeights.lean @@ -52,7 +52,12 @@ private theorem evenCap_nonneg (m : ℕ) (hm : 1 ≤ m) have hj0 : (0 : ℚ) ≤ j.1 := by positivity have hjmax : (j.1 : ℚ) ≤ 2 * ((2 * m : ℚ) - 1) := by have hjmaxNat : j.1 ≤ 2 * (2 * m - 1) := by omega - exact_mod_cast hjmaxNat + have htwo : 1 ≤ 2 * m := by omega + calc + (j.1 : ℚ) ≤ ((2 * (2 * m - 1) : ℕ) : ℚ) := by + exact_mod_cast hjmaxNat + _ = 2 * ((2 * m : ℚ) - 1) := by + norm_num [Nat.cast_sub htwo] have hprod : 0 ≤ (j.1 : ℚ) * (2 * ((2 * m : ℚ) - 1) - j.1) := mul_nonneg hj0 (sub_nonneg.mpr hjmax) @@ -131,11 +136,12 @@ theorem evenQuadratic_coverage (m parity : ℕ) (hp : parity = 0 ∨ parity = 1) rcases hp with rfl | rfl <;> simp [differenceIndex, InColor] at hcolor ⊢ <;> omega have hy : p.2.1 ≤ 2 * m - 1 := by omega + have hmtwo : 1 ≤ m * 2 := by omega unfold fourCoverage evenQuadraticWeights dsimp rw [if_pos hsum, if_pos hdiff] simp only [evenCap, sumIndex, differenceIndex] - push_cast [Nat.cast_sub hy] + push_cast [Nat.cast_sub hy, Nat.cast_sub hmtwo] ring end Checkerboard From b790c9d75033659e272fc64bac23b185c07fabc2 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 01:29:46 -0700 Subject: [PATCH 29/59] Use explicit finite kernel decision for checkerboard n6 base --- Checkerboard/N6Base.lean | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/Checkerboard/N6Base.lean b/Checkerboard/N6Base.lean index 9e392055..9e20cd79 100644 --- a/Checkerboard/N6Base.lean +++ b/Checkerboard/N6Base.lean @@ -6,12 +6,15 @@ import Checkerboard.FourCertificate The uniform quadratic cover is sharp at value nine on the 6-board, so an integrality argument is required. Each color class has eighteen points. We transport an arbitrary monochromatic set to eighteen Boolean variables, and -`bv_decide` checks the finite statement that row, column, and slope `±1` +an exact finite kernel decision checks that row, column, and slope `±1` capacities already force at most eight selected points. -/ namespace Checkerboard +set_option maxHeartbeats 0 +set_option maxRecDepth 1000000 + /-- Enumeration of the fat color class of the 6-board. -/ def n6p0Point : Fin 18 → Point 6 := ![ ((0 : Fin 6), (0 : Fin 6)), ((0 : Fin 6), (2 : Fin 6)), @@ -40,10 +43,22 @@ private theorem n6p0_injective : Function.Injective n6p0Point := by decide private theorem n6p1_injective : Function.Injective n6p1Point := by decide private theorem n6p0_surjective : - ∀ p : Point 6, InColor 0 p → ∃ i, n6p0Point i = p := by decide + ∀ p : Point 6, InColor 0 p → ∃ i, n6p0Point i = p := by + letI : DecidablePred (fun p : Point 6 => + InColor 0 p → ∃ i, n6p0Point i = p) := by + intro p + unfold InColor + infer_instance + exact of_decide_eq_true rfl private theorem n6p1_surjective : - ∀ p : Point 6, InColor 1 p → ∃ i, n6p1Point i = p := by decide + ∀ p : Point 6, InColor 1 p → ∃ i, n6p1Point i = p := by + letI : DecidablePred (fun p : Point 6 => + InColor 1 p → ∃ i, n6p1Point i = p) := by + intro p + unfold InColor + infer_instance + exact of_decide_eq_true rfl private def chosenIndices (point : Fin 18 → Point 6) (s : Finset (Point 6)) : Finset (Fin 18) := @@ -137,7 +152,14 @@ private theorem n6p0_boolean_bound : (Finset.univ.filter fun i => x i = true ∧ OnLine line (n6p0Point i)).card ≤ 2) → (Finset.univ.filter fun i => x i = true).card ≤ 8 := by - bv_decide + letI : DecidablePred (fun x : Fin 18 → Bool => + (∀ line : PrincipalLine 6, + (Finset.univ.filter fun i => + x i = true ∧ OnLine line (n6p0Point i)).card ≤ 2) → + (Finset.univ.filter fun i => x i = true).card ≤ 8) := by + intro x + infer_instance + exact of_decide_eq_true rfl private theorem n6p1_boolean_bound : ∀ x : Fin 18 → Bool, @@ -145,7 +167,14 @@ private theorem n6p1_boolean_bound : (Finset.univ.filter fun i => x i = true ∧ OnLine line (n6p1Point i)).card ≤ 2) → (Finset.univ.filter fun i => x i = true).card ≤ 8 := by - bv_decide + letI : DecidablePred (fun x : Fin 18 → Bool => + (∀ line : PrincipalLine 6, + (Finset.univ.filter fun i => + x i = true ∧ OnLine line (n6p1Point i)).card ≤ 2) → + (Finset.univ.filter fun i => x i = true).card ≤ 8) := by + intro x + infer_instance + exact of_decide_eq_true rfl /-- `D_mono(6,0) ≤ 8`. -/ theorem n6_zero_upper (s : Finset (Point 6)) From aa165e404a0319c272c2eb6cf76efa29e144b06c Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 01:45:52 -0700 Subject: [PATCH 30/59] Add compact n6 Boolean SAT certificate test --- Checkerboard/N6SATTest.lean | 66 +++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 Checkerboard/N6SATTest.lean diff --git a/Checkerboard/N6SATTest.lean b/Checkerboard/N6SATTest.lean new file mode 100644 index 00000000..d98b7ef6 --- /dev/null +++ b/Checkerboard/N6SATTest.lean @@ -0,0 +1,66 @@ +import Mathlib + +namespace Checkerboard + +private def bitNat (b : Bool) : ℕ := if b then 1 else 0 + +private theorem p0_sat + (x0 : Bool) (x1 : Bool) (x2 : Bool) (x3 : Bool) (x4 : Bool) (x5 : Bool) + (x6 : Bool) (x7 : Bool) (x8 : Bool) (x9 : Bool) (x10 : Bool) (x11 : Bool) + (x12 : Bool) (x13 : Bool) (x14 : Bool) (x15 : Bool) (x16 : Bool) (x17 : Bool) + (h0 : bitNat x0 + bitNat x1 + bitNat x2 ≤ 2) + (h1 : bitNat x3 + bitNat x4 + bitNat x5 ≤ 2) + (h2 : bitNat x6 + bitNat x7 + bitNat x8 ≤ 2) + (h3 : bitNat x9 + bitNat x10 + bitNat x11 ≤ 2) + (h4 : bitNat x12 + bitNat x13 + bitNat x14 ≤ 2) + (h5 : bitNat x15 + bitNat x16 + bitNat x17 ≤ 2) + (h6 : bitNat x0 + bitNat x6 + bitNat x12 ≤ 2) + (h7 : bitNat x1 + bitNat x7 + bitNat x13 ≤ 2) + (h8 : bitNat x2 + bitNat x8 + bitNat x14 ≤ 2) + (h9 : bitNat x3 + bitNat x9 + bitNat x15 ≤ 2) + (h10 : bitNat x4 + bitNat x10 + bitNat x16 ≤ 2) + (h11 : bitNat x5 + bitNat x11 + bitNat x17 ≤ 2) + (h12 : bitNat x1 + bitNat x3 + bitNat x6 ≤ 2) + (h13 : bitNat x2 + bitNat x4 + bitNat x7 + bitNat x9 + bitNat x12 ≤ 2) + (h14 : bitNat x5 + bitNat x8 + bitNat x10 + bitNat x13 + bitNat x15 ≤ 2) + (h15 : bitNat x11 + bitNat x14 + bitNat x16 ≤ 2) + (h16 : bitNat x0 + bitNat x3 + bitNat x7 + bitNat x10 + bitNat x14 + bitNat x17 ≤ 2) + (h17 : bitNat x1 + bitNat x4 + bitNat x8 + bitNat x11 ≤ 2) + (h18 : bitNat x6 + bitNat x9 + bitNat x13 + bitNat x16 ≤ 2) : + bitNat x0 + bitNat x1 + bitNat x2 + bitNat x3 + bitNat x4 + bitNat x5 + + bitNat x6 + bitNat x7 + bitNat x8 + bitNat x9 + bitNat x10 + bitNat x11 + + bitNat x12 + bitNat x13 + bitNat x14 + bitNat x15 + bitNat x16 + bitNat x17 ≤ 8 := by + bv_decide + +private theorem p1_sat + (x0 : Bool) (x1 : Bool) (x2 : Bool) (x3 : Bool) (x4 : Bool) (x5 : Bool) + (x6 : Bool) (x7 : Bool) (x8 : Bool) (x9 : Bool) (x10 : Bool) (x11 : Bool) + (x12 : Bool) (x13 : Bool) (x14 : Bool) (x15 : Bool) (x16 : Bool) (x17 : Bool) + (h0 : bitNat x0 + bitNat x1 + bitNat x2 ≤ 2) + (h1 : bitNat x3 + bitNat x4 + bitNat x5 ≤ 2) + (h2 : bitNat x6 + bitNat x7 + bitNat x8 ≤ 2) + (h3 : bitNat x9 + bitNat x10 + bitNat x11 ≤ 2) + (h4 : bitNat x12 + bitNat x13 + bitNat x14 ≤ 2) + (h5 : bitNat x15 + bitNat x16 + bitNat x17 ≤ 2) + (h6 : bitNat x0 + bitNat x6 + bitNat x12 ≤ 2) + (h7 : bitNat x1 + bitNat x7 + bitNat x13 ≤ 2) + (h8 : bitNat x2 + bitNat x8 + bitNat x14 ≤ 2) + (h9 : bitNat x3 + bitNat x9 + bitNat x15 ≤ 2) + (h10 : bitNat x4 + bitNat x10 + bitNat x16 ≤ 2) + (h11 : bitNat x5 + bitNat x11 + bitNat x17 ≤ 2) + (h12 : bitNat x1 + bitNat x4 + bitNat x6 + bitNat x9 ≤ 2) + (h13 : bitNat x2 + bitNat x5 + bitNat x7 + bitNat x10 + bitNat x12 + bitNat x15 ≤ 2) + (h14 : bitNat x8 + bitNat x11 + bitNat x13 + bitNat x16 ≤ 2) + (h15 : bitNat x0 + bitNat x4 + bitNat x7 + bitNat x11 + bitNat x14 ≤ 2) + (h16 : bitNat x1 + bitNat x5 + bitNat x8 ≤ 2) + (h17 : bitNat x3 + bitNat x6 + bitNat x10 + bitNat x13 + bitNat x17 ≤ 2) + (h18 : bitNat x9 + bitNat x12 + bitNat x16 ≤ 2) : + bitNat x0 + bitNat x1 + bitNat x2 + bitNat x3 + bitNat x4 + bitNat x5 + + bitNat x6 + bitNat x7 + bitNat x8 + bitNat x9 + bitNat x10 + bitNat x11 + + bitNat x12 + bitNat x13 + bitNat x14 + bitNat x15 + bitNat x16 + bitNat x17 ≤ 8 := by + bv_decide + +#print axioms p0_sat +#print axioms p1_sat + +end Checkerboard From f7bb9301c63bad3e23121b90117c0df7b4f3a9d2 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 01:55:40 -0700 Subject: [PATCH 31/59] Encode checkerboard n6 certificate as pure BitVec SAT --- Checkerboard/N6SATTest.lean | 103 +++++++++++++++++------------------- 1 file changed, 50 insertions(+), 53 deletions(-) diff --git a/Checkerboard/N6SATTest.lean b/Checkerboard/N6SATTest.lean index d98b7ef6..06255130 100644 --- a/Checkerboard/N6SATTest.lean +++ b/Checkerboard/N6SATTest.lean @@ -2,62 +2,59 @@ import Mathlib namespace Checkerboard -private def bitNat (b : Bool) : ℕ := if b then 1 else 0 +private def pop18 (x : BitVec 18) : BitVec 18 := + go x 0 18 +where + go (x pop : BitVec 18) : Nat → BitVec 18 + | 0 => pop + | n + 1 => go (x >>> 1) (pop + (x &&& 1)) n -private theorem p0_sat - (x0 : Bool) (x1 : Bool) (x2 : Bool) (x3 : Bool) (x4 : Bool) (x5 : Bool) - (x6 : Bool) (x7 : Bool) (x8 : Bool) (x9 : Bool) (x10 : Bool) (x11 : Bool) - (x12 : Bool) (x13 : Bool) (x14 : Bool) (x15 : Bool) (x16 : Bool) (x17 : Bool) - (h0 : bitNat x0 + bitNat x1 + bitNat x2 ≤ 2) - (h1 : bitNat x3 + bitNat x4 + bitNat x5 ≤ 2) - (h2 : bitNat x6 + bitNat x7 + bitNat x8 ≤ 2) - (h3 : bitNat x9 + bitNat x10 + bitNat x11 ≤ 2) - (h4 : bitNat x12 + bitNat x13 + bitNat x14 ≤ 2) - (h5 : bitNat x15 + bitNat x16 + bitNat x17 ≤ 2) - (h6 : bitNat x0 + bitNat x6 + bitNat x12 ≤ 2) - (h7 : bitNat x1 + bitNat x7 + bitNat x13 ≤ 2) - (h8 : bitNat x2 + bitNat x8 + bitNat x14 ≤ 2) - (h9 : bitNat x3 + bitNat x9 + bitNat x15 ≤ 2) - (h10 : bitNat x4 + bitNat x10 + bitNat x16 ≤ 2) - (h11 : bitNat x5 + bitNat x11 + bitNat x17 ≤ 2) - (h12 : bitNat x1 + bitNat x3 + bitNat x6 ≤ 2) - (h13 : bitNat x2 + bitNat x4 + bitNat x7 + bitNat x9 + bitNat x12 ≤ 2) - (h14 : bitNat x5 + bitNat x8 + bitNat x10 + bitNat x13 + bitNat x15 ≤ 2) - (h15 : bitNat x11 + bitNat x14 + bitNat x16 ≤ 2) - (h16 : bitNat x0 + bitNat x3 + bitNat x7 + bitNat x10 + bitNat x14 + bitNat x17 ≤ 2) - (h17 : bitNat x1 + bitNat x4 + bitNat x8 + bitNat x11 ≤ 2) - (h18 : bitNat x6 + bitNat x9 + bitNat x13 + bitNat x16 ≤ 2) : - bitNat x0 + bitNat x1 + bitNat x2 + bitNat x3 + bitNat x4 + bitNat x5 + - bitNat x6 + bitNat x7 + bitNat x8 + bitNat x9 + bitNat x10 + bitNat x11 + - bitNat x12 + bitNat x13 + bitNat x14 + bitNat x15 + bitNat x16 + bitNat x17 ≤ 8 := by +private theorem p0_sat (x : BitVec 18) + (h0 : pop18 (x &&& 0x7#18) ≤ 2#18) + (h1 : pop18 (x &&& 0x38#18) ≤ 2#18) + (h2 : pop18 (x &&& 0x1c0#18) ≤ 2#18) + (h3 : pop18 (x &&& 0xe00#18) ≤ 2#18) + (h4 : pop18 (x &&& 0x7000#18) ≤ 2#18) + (h5 : pop18 (x &&& 0x38000#18) ≤ 2#18) + (h6 : pop18 (x &&& 0x1041#18) ≤ 2#18) + (h7 : pop18 (x &&& 0x2082#18) ≤ 2#18) + (h8 : pop18 (x &&& 0x4104#18) ≤ 2#18) + (h9 : pop18 (x &&& 0x8208#18) ≤ 2#18) + (h10 : pop18 (x &&& 0x10410#18) ≤ 2#18) + (h11 : pop18 (x &&& 0x20820#18) ≤ 2#18) + (h12 : pop18 (x &&& 0x4a#18) ≤ 2#18) + (h13 : pop18 (x &&& 0x1294#18) ≤ 2#18) + (h14 : pop18 (x &&& 0xa520#18) ≤ 2#18) + (h15 : pop18 (x &&& 0x14800#18) ≤ 2#18) + (h16 : pop18 (x &&& 0x24489#18) ≤ 2#18) + (h17 : pop18 (x &&& 0x912#18) ≤ 2#18) + (h18 : pop18 (x &&& 0x12240#18) ≤ 2#18) : + pop18 x ≤ 8#18 := by + dsimp [pop18, pop18.go] at * bv_decide -private theorem p1_sat - (x0 : Bool) (x1 : Bool) (x2 : Bool) (x3 : Bool) (x4 : Bool) (x5 : Bool) - (x6 : Bool) (x7 : Bool) (x8 : Bool) (x9 : Bool) (x10 : Bool) (x11 : Bool) - (x12 : Bool) (x13 : Bool) (x14 : Bool) (x15 : Bool) (x16 : Bool) (x17 : Bool) - (h0 : bitNat x0 + bitNat x1 + bitNat x2 ≤ 2) - (h1 : bitNat x3 + bitNat x4 + bitNat x5 ≤ 2) - (h2 : bitNat x6 + bitNat x7 + bitNat x8 ≤ 2) - (h3 : bitNat x9 + bitNat x10 + bitNat x11 ≤ 2) - (h4 : bitNat x12 + bitNat x13 + bitNat x14 ≤ 2) - (h5 : bitNat x15 + bitNat x16 + bitNat x17 ≤ 2) - (h6 : bitNat x0 + bitNat x6 + bitNat x12 ≤ 2) - (h7 : bitNat x1 + bitNat x7 + bitNat x13 ≤ 2) - (h8 : bitNat x2 + bitNat x8 + bitNat x14 ≤ 2) - (h9 : bitNat x3 + bitNat x9 + bitNat x15 ≤ 2) - (h10 : bitNat x4 + bitNat x10 + bitNat x16 ≤ 2) - (h11 : bitNat x5 + bitNat x11 + bitNat x17 ≤ 2) - (h12 : bitNat x1 + bitNat x4 + bitNat x6 + bitNat x9 ≤ 2) - (h13 : bitNat x2 + bitNat x5 + bitNat x7 + bitNat x10 + bitNat x12 + bitNat x15 ≤ 2) - (h14 : bitNat x8 + bitNat x11 + bitNat x13 + bitNat x16 ≤ 2) - (h15 : bitNat x0 + bitNat x4 + bitNat x7 + bitNat x11 + bitNat x14 ≤ 2) - (h16 : bitNat x1 + bitNat x5 + bitNat x8 ≤ 2) - (h17 : bitNat x3 + bitNat x6 + bitNat x10 + bitNat x13 + bitNat x17 ≤ 2) - (h18 : bitNat x9 + bitNat x12 + bitNat x16 ≤ 2) : - bitNat x0 + bitNat x1 + bitNat x2 + bitNat x3 + bitNat x4 + bitNat x5 + - bitNat x6 + bitNat x7 + bitNat x8 + bitNat x9 + bitNat x10 + bitNat x11 + - bitNat x12 + bitNat x13 + bitNat x14 + bitNat x15 + bitNat x16 + bitNat x17 ≤ 8 := by +private theorem p1_sat (x : BitVec 18) + (h0 : pop18 (x &&& 0x7#18) ≤ 2#18) + (h1 : pop18 (x &&& 0x38#18) ≤ 2#18) + (h2 : pop18 (x &&& 0x1c0#18) ≤ 2#18) + (h3 : pop18 (x &&& 0xe00#18) ≤ 2#18) + (h4 : pop18 (x &&& 0x7000#18) ≤ 2#18) + (h5 : pop18 (x &&& 0x38000#18) ≤ 2#18) + (h6 : pop18 (x &&& 0x1041#18) ≤ 2#18) + (h7 : pop18 (x &&& 0x2082#18) ≤ 2#18) + (h8 : pop18 (x &&& 0x4104#18) ≤ 2#18) + (h9 : pop18 (x &&& 0x8208#18) ≤ 2#18) + (h10 : pop18 (x &&& 0x10410#18) ≤ 2#18) + (h11 : pop18 (x &&& 0x20820#18) ≤ 2#18) + (h12 : pop18 (x &&& 0x252#18) ≤ 2#18) + (h13 : pop18 (x &&& 0x94a4#18) ≤ 2#18) + (h14 : pop18 (x &&& 0x12900#18) ≤ 2#18) + (h15 : pop18 (x &&& 0x4891#18) ≤ 2#18) + (h16 : pop18 (x &&& 0x122#18) ≤ 2#18) + (h17 : pop18 (x &&& 0x22448#18) ≤ 2#18) + (h18 : pop18 (x &&& 0x11200#18) ≤ 2#18) : + pop18 x ≤ 8#18 := by + dsimp [pop18, pop18.go] at * bv_decide #print axioms p0_sat From d8650ce8d9e2528adaf92c91bb58a8e9d8e23231 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 02:04:01 -0700 Subject: [PATCH 32/59] Generate checkerboard n6 LRAT certificates --- Checkerboard/N6SATTest.lean | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Checkerboard/N6SATTest.lean b/Checkerboard/N6SATTest.lean index 06255130..2f12efb7 100644 --- a/Checkerboard/N6SATTest.lean +++ b/Checkerboard/N6SATTest.lean @@ -31,7 +31,7 @@ private theorem p0_sat (x : BitVec 18) (h18 : pop18 (x &&& 0x12240#18) ≤ 2#18) : pop18 x ≤ 8#18 := by dsimp [pop18, pop18.go] at * - bv_decide + bv_decide? private theorem p1_sat (x : BitVec 18) (h0 : pop18 (x &&& 0x7#18) ≤ 2#18) @@ -55,9 +55,6 @@ private theorem p1_sat (x : BitVec 18) (h18 : pop18 (x &&& 0x11200#18) ≤ 2#18) : pop18 x ≤ 8#18 := by dsimp [pop18, pop18.go] at * - bv_decide - -#print axioms p0_sat -#print axioms p1_sat + bv_decide? end Checkerboard From ddac364bedbd748af9a4b3c3f8643ee3f65e5f7d Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 02:07:24 -0700 Subject: [PATCH 33/59] Prove checkerboard n6 Boolean certificate with omega --- Checkerboard/N6SATTest.lean | 146 +++++++++++++++++++++++------------- 1 file changed, 94 insertions(+), 52 deletions(-) diff --git a/Checkerboard/N6SATTest.lean b/Checkerboard/N6SATTest.lean index 2f12efb7..b66699e9 100644 --- a/Checkerboard/N6SATTest.lean +++ b/Checkerboard/N6SATTest.lean @@ -2,59 +2,101 @@ import Mathlib namespace Checkerboard -private def pop18 (x : BitVec 18) : BitVec 18 := - go x 0 18 -where - go (x pop : BitVec 18) : Nat → BitVec 18 - | 0 => pop - | n + 1 => go (x >>> 1) (pop + (x &&& 1)) n +private def bitNat (b : Bool) : ℕ := if b then 1 else 0 -private theorem p0_sat (x : BitVec 18) - (h0 : pop18 (x &&& 0x7#18) ≤ 2#18) - (h1 : pop18 (x &&& 0x38#18) ≤ 2#18) - (h2 : pop18 (x &&& 0x1c0#18) ≤ 2#18) - (h3 : pop18 (x &&& 0xe00#18) ≤ 2#18) - (h4 : pop18 (x &&& 0x7000#18) ≤ 2#18) - (h5 : pop18 (x &&& 0x38000#18) ≤ 2#18) - (h6 : pop18 (x &&& 0x1041#18) ≤ 2#18) - (h7 : pop18 (x &&& 0x2082#18) ≤ 2#18) - (h8 : pop18 (x &&& 0x4104#18) ≤ 2#18) - (h9 : pop18 (x &&& 0x8208#18) ≤ 2#18) - (h10 : pop18 (x &&& 0x10410#18) ≤ 2#18) - (h11 : pop18 (x &&& 0x20820#18) ≤ 2#18) - (h12 : pop18 (x &&& 0x4a#18) ≤ 2#18) - (h13 : pop18 (x &&& 0x1294#18) ≤ 2#18) - (h14 : pop18 (x &&& 0xa520#18) ≤ 2#18) - (h15 : pop18 (x &&& 0x14800#18) ≤ 2#18) - (h16 : pop18 (x &&& 0x24489#18) ≤ 2#18) - (h17 : pop18 (x &&& 0x912#18) ≤ 2#18) - (h18 : pop18 (x &&& 0x12240#18) ≤ 2#18) : - pop18 x ≤ 8#18 := by - dsimp [pop18, pop18.go] at * - bv_decide? +private theorem p0_sat + (x0 : Bool) (x1 : Bool) (x2 : Bool) (x3 : Bool) (x4 : Bool) (x5 : Bool) + (x6 : Bool) (x7 : Bool) (x8 : Bool) (x9 : Bool) (x10 : Bool) (x11 : Bool) + (x12 : Bool) (x13 : Bool) (x14 : Bool) (x15 : Bool) (x16 : Bool) (x17 : Bool) + (h0 : bitNat x0 + bitNat x1 + bitNat x2 ≤ 2) + (h1 : bitNat x3 + bitNat x4 + bitNat x5 ≤ 2) + (h2 : bitNat x6 + bitNat x7 + bitNat x8 ≤ 2) + (h3 : bitNat x9 + bitNat x10 + bitNat x11 ≤ 2) + (h4 : bitNat x12 + bitNat x13 + bitNat x14 ≤ 2) + (h5 : bitNat x15 + bitNat x16 + bitNat x17 ≤ 2) + (h6 : bitNat x0 + bitNat x6 + bitNat x12 ≤ 2) + (h7 : bitNat x1 + bitNat x7 + bitNat x13 ≤ 2) + (h8 : bitNat x2 + bitNat x8 + bitNat x14 ≤ 2) + (h9 : bitNat x3 + bitNat x9 + bitNat x15 ≤ 2) + (h10 : bitNat x4 + bitNat x10 + bitNat x16 ≤ 2) + (h11 : bitNat x5 + bitNat x11 + bitNat x17 ≤ 2) + (h12 : bitNat x1 + bitNat x3 + bitNat x6 ≤ 2) + (h13 : bitNat x2 + bitNat x4 + bitNat x7 + bitNat x9 + bitNat x12 ≤ 2) + (h14 : bitNat x5 + bitNat x8 + bitNat x10 + bitNat x13 + bitNat x15 ≤ 2) + (h15 : bitNat x11 + bitNat x14 + bitNat x16 ≤ 2) + (h16 : bitNat x0 + bitNat x3 + bitNat x7 + bitNat x10 + bitNat x14 + bitNat x17 ≤ 2) + (h17 : bitNat x1 + bitNat x4 + bitNat x8 + bitNat x11 ≤ 2) + (h18 : bitNat x6 + bitNat x9 + bitNat x13 + bitNat x16 ≤ 2) : + bitNat x0 + bitNat x1 + bitNat x2 + bitNat x3 + bitNat x4 + bitNat x5 + + bitNat x6 + bitNat x7 + bitNat x8 + bitNat x9 + bitNat x10 + bitNat x11 + + bitNat x12 + bitNat x13 + bitNat x14 + bitNat x15 + bitNat x16 + bitNat x17 ≤ 8 := by + have hx0 : bitNat x0 ≤ 1 := by cases x0 <;> simp [bitNat] + have hx1 : bitNat x1 ≤ 1 := by cases x1 <;> simp [bitNat] + have hx2 : bitNat x2 ≤ 1 := by cases x2 <;> simp [bitNat] + have hx3 : bitNat x3 ≤ 1 := by cases x3 <;> simp [bitNat] + have hx4 : bitNat x4 ≤ 1 := by cases x4 <;> simp [bitNat] + have hx5 : bitNat x5 ≤ 1 := by cases x5 <;> simp [bitNat] + have hx6 : bitNat x6 ≤ 1 := by cases x6 <;> simp [bitNat] + have hx7 : bitNat x7 ≤ 1 := by cases x7 <;> simp [bitNat] + have hx8 : bitNat x8 ≤ 1 := by cases x8 <;> simp [bitNat] + have hx9 : bitNat x9 ≤ 1 := by cases x9 <;> simp [bitNat] + have hx10 : bitNat x10 ≤ 1 := by cases x10 <;> simp [bitNat] + have hx11 : bitNat x11 ≤ 1 := by cases x11 <;> simp [bitNat] + have hx12 : bitNat x12 ≤ 1 := by cases x12 <;> simp [bitNat] + have hx13 : bitNat x13 ≤ 1 := by cases x13 <;> simp [bitNat] + have hx14 : bitNat x14 ≤ 1 := by cases x14 <;> simp [bitNat] + have hx15 : bitNat x15 ≤ 1 := by cases x15 <;> simp [bitNat] + have hx16 : bitNat x16 ≤ 1 := by cases x16 <;> simp [bitNat] + have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp [bitNat] + omega -private theorem p1_sat (x : BitVec 18) - (h0 : pop18 (x &&& 0x7#18) ≤ 2#18) - (h1 : pop18 (x &&& 0x38#18) ≤ 2#18) - (h2 : pop18 (x &&& 0x1c0#18) ≤ 2#18) - (h3 : pop18 (x &&& 0xe00#18) ≤ 2#18) - (h4 : pop18 (x &&& 0x7000#18) ≤ 2#18) - (h5 : pop18 (x &&& 0x38000#18) ≤ 2#18) - (h6 : pop18 (x &&& 0x1041#18) ≤ 2#18) - (h7 : pop18 (x &&& 0x2082#18) ≤ 2#18) - (h8 : pop18 (x &&& 0x4104#18) ≤ 2#18) - (h9 : pop18 (x &&& 0x8208#18) ≤ 2#18) - (h10 : pop18 (x &&& 0x10410#18) ≤ 2#18) - (h11 : pop18 (x &&& 0x20820#18) ≤ 2#18) - (h12 : pop18 (x &&& 0x252#18) ≤ 2#18) - (h13 : pop18 (x &&& 0x94a4#18) ≤ 2#18) - (h14 : pop18 (x &&& 0x12900#18) ≤ 2#18) - (h15 : pop18 (x &&& 0x4891#18) ≤ 2#18) - (h16 : pop18 (x &&& 0x122#18) ≤ 2#18) - (h17 : pop18 (x &&& 0x22448#18) ≤ 2#18) - (h18 : pop18 (x &&& 0x11200#18) ≤ 2#18) : - pop18 x ≤ 8#18 := by - dsimp [pop18, pop18.go] at * - bv_decide? +private theorem p1_sat + (x0 : Bool) (x1 : Bool) (x2 : Bool) (x3 : Bool) (x4 : Bool) (x5 : Bool) + (x6 : Bool) (x7 : Bool) (x8 : Bool) (x9 : Bool) (x10 : Bool) (x11 : Bool) + (x12 : Bool) (x13 : Bool) (x14 : Bool) (x15 : Bool) (x16 : Bool) (x17 : Bool) + (h0 : bitNat x0 + bitNat x1 + bitNat x2 ≤ 2) + (h1 : bitNat x3 + bitNat x4 + bitNat x5 ≤ 2) + (h2 : bitNat x6 + bitNat x7 + bitNat x8 ≤ 2) + (h3 : bitNat x9 + bitNat x10 + bitNat x11 ≤ 2) + (h4 : bitNat x12 + bitNat x13 + bitNat x14 ≤ 2) + (h5 : bitNat x15 + bitNat x16 + bitNat x17 ≤ 2) + (h6 : bitNat x0 + bitNat x6 + bitNat x12 ≤ 2) + (h7 : bitNat x1 + bitNat x7 + bitNat x13 ≤ 2) + (h8 : bitNat x2 + bitNat x8 + bitNat x14 ≤ 2) + (h9 : bitNat x3 + bitNat x9 + bitNat x15 ≤ 2) + (h10 : bitNat x4 + bitNat x10 + bitNat x16 ≤ 2) + (h11 : bitNat x5 + bitNat x11 + bitNat x17 ≤ 2) + (h12 : bitNat x1 + bitNat x4 + bitNat x6 + bitNat x9 ≤ 2) + (h13 : bitNat x2 + bitNat x5 + bitNat x7 + bitNat x10 + bitNat x12 + bitNat x15 ≤ 2) + (h14 : bitNat x8 + bitNat x11 + bitNat x13 + bitNat x16 ≤ 2) + (h15 : bitNat x0 + bitNat x4 + bitNat x7 + bitNat x11 + bitNat x14 ≤ 2) + (h16 : bitNat x1 + bitNat x5 + bitNat x8 ≤ 2) + (h17 : bitNat x3 + bitNat x6 + bitNat x10 + bitNat x13 + bitNat x17 ≤ 2) + (h18 : bitNat x9 + bitNat x12 + bitNat x16 ≤ 2) : + bitNat x0 + bitNat x1 + bitNat x2 + bitNat x3 + bitNat x4 + bitNat x5 + + bitNat x6 + bitNat x7 + bitNat x8 + bitNat x9 + bitNat x10 + bitNat x11 + + bitNat x12 + bitNat x13 + bitNat x14 + bitNat x15 + bitNat x16 + bitNat x17 ≤ 8 := by + have hx0 : bitNat x0 ≤ 1 := by cases x0 <;> simp [bitNat] + have hx1 : bitNat x1 ≤ 1 := by cases x1 <;> simp [bitNat] + have hx2 : bitNat x2 ≤ 1 := by cases x2 <;> simp [bitNat] + have hx3 : bitNat x3 ≤ 1 := by cases x3 <;> simp [bitNat] + have hx4 : bitNat x4 ≤ 1 := by cases x4 <;> simp [bitNat] + have hx5 : bitNat x5 ≤ 1 := by cases x5 <;> simp [bitNat] + have hx6 : bitNat x6 ≤ 1 := by cases x6 <;> simp [bitNat] + have hx7 : bitNat x7 ≤ 1 := by cases x7 <;> simp [bitNat] + have hx8 : bitNat x8 ≤ 1 := by cases x8 <;> simp [bitNat] + have hx9 : bitNat x9 ≤ 1 := by cases x9 <;> simp [bitNat] + have hx10 : bitNat x10 ≤ 1 := by cases x10 <;> simp [bitNat] + have hx11 : bitNat x11 ≤ 1 := by cases x11 <;> simp [bitNat] + have hx12 : bitNat x12 ≤ 1 := by cases x12 <;> simp [bitNat] + have hx13 : bitNat x13 ≤ 1 := by cases x13 <;> simp [bitNat] + have hx14 : bitNat x14 ≤ 1 := by cases x14 <;> simp [bitNat] + have hx15 : bitNat x15 ≤ 1 := by cases x15 <;> simp [bitNat] + have hx16 : bitNat x16 ≤ 1 := by cases x16 <;> simp [bitNat] + have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp [bitNat] + omega + +#print axioms p0_sat +#print axioms p1_sat end Checkerboard From b1fdf5123d13d6ef79401e8386a9d0e34be9d020 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 02:21:10 -0700 Subject: [PATCH 34/59] Export kernel-only checkerboard n6 omega certificates --- Checkerboard/N6SATTest.lean | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Checkerboard/N6SATTest.lean b/Checkerboard/N6SATTest.lean index b66699e9..93827ef6 100644 --- a/Checkerboard/N6SATTest.lean +++ b/Checkerboard/N6SATTest.lean @@ -2,9 +2,11 @@ import Mathlib namespace Checkerboard -private def bitNat (b : Bool) : ℕ := if b then 1 else 0 +/-- Convert a Boolean selection bit to its natural indicator. -/ +def bitNat (b : Bool) : ℕ := if b then 1 else 0 -private theorem p0_sat +/-- Integer certificate for the even checkerboard color class on the 6-board. -/ +theorem n6p0_sat (x0 : Bool) (x1 : Bool) (x2 : Bool) (x3 : Bool) (x4 : Bool) (x5 : Bool) (x6 : Bool) (x7 : Bool) (x8 : Bool) (x9 : Bool) (x10 : Bool) (x11 : Bool) (x12 : Bool) (x13 : Bool) (x14 : Bool) (x15 : Bool) (x16 : Bool) (x17 : Bool) @@ -50,7 +52,8 @@ private theorem p0_sat have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp [bitNat] omega -private theorem p1_sat +/-- Integer certificate for the odd checkerboard color class on the 6-board. -/ +theorem n6p1_sat (x0 : Bool) (x1 : Bool) (x2 : Bool) (x3 : Bool) (x4 : Bool) (x5 : Bool) (x6 : Bool) (x7 : Bool) (x8 : Bool) (x9 : Bool) (x10 : Bool) (x11 : Bool) (x12 : Bool) (x13 : Bool) (x14 : Bool) (x15 : Bool) (x16 : Bool) (x17 : Bool) @@ -96,7 +99,7 @@ private theorem p1_sat have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp [bitNat] omega -#print axioms p0_sat -#print axioms p1_sat +#print axioms n6p0_sat +#print axioms n6p1_sat end Checkerboard From 0b6ac8fe2444f8b42a871cb397d276b36829a5e9 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 02:21:37 -0700 Subject: [PATCH 35/59] Add focused bridge test for checkerboard n6 omega certificate --- Checkerboard/N6BridgeTest.lean | 49 ++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Checkerboard/N6BridgeTest.lean diff --git a/Checkerboard/N6BridgeTest.lean b/Checkerboard/N6BridgeTest.lean new file mode 100644 index 00000000..3ace0592 --- /dev/null +++ b/Checkerboard/N6BridgeTest.lean @@ -0,0 +1,49 @@ +import Checkerboard.FourCertificate +import Checkerboard.N6SATTest + +namespace Checkerboard + +private def p0Point : Fin 18 → Point 6 := ![ + ((0 : Fin 6), (0 : Fin 6)), ((0 : Fin 6), (2 : Fin 6)), + ((0 : Fin 6), (4 : Fin 6)), ((1 : Fin 6), (1 : Fin 6)), + ((1 : Fin 6), (3 : Fin 6)), ((1 : Fin 6), (5 : Fin 6)), + ((2 : Fin 6), (0 : Fin 6)), ((2 : Fin 6), (2 : Fin 6)), + ((2 : Fin 6), (4 : Fin 6)), ((3 : Fin 6), (1 : Fin 6)), + ((3 : Fin 6), (3 : Fin 6)), ((3 : Fin 6), (5 : Fin 6)), + ((4 : Fin 6), (0 : Fin 6)), ((4 : Fin 6), (2 : Fin 6)), + ((4 : Fin 6), (4 : Fin 6)), ((5 : Fin 6), (1 : Fin 6)), + ((5 : Fin 6), (3 : Fin 6)), ((5 : Fin 6), (5 : Fin 6))] + +private theorem p0_bridge + (x : Fin 18 → Bool) + (hline : ∀ line : PrincipalLine 6, + (Finset.univ.filter fun i => x i = true ∧ OnLine line (p0Point i)).card ≤ 2) : + (Finset.univ.filter fun i => x i = true).card ≤ 8 := by + have h0 := hline (LineFamily.row, ⟨0, by decide⟩) + have h1 := hline (LineFamily.row, ⟨1, by decide⟩) + have h2 := hline (LineFamily.row, ⟨2, by decide⟩) + have h3 := hline (LineFamily.row, ⟨3, by decide⟩) + have h4 := hline (LineFamily.row, ⟨4, by decide⟩) + have h5 := hline (LineFamily.row, ⟨5, by decide⟩) + have h6 := hline (LineFamily.column, ⟨0, by decide⟩) + have h7 := hline (LineFamily.column, ⟨2, by decide⟩) + have h8 := hline (LineFamily.column, ⟨4, by decide⟩) + have h9 := hline (LineFamily.column, ⟨1, by decide⟩) + have h10 := hline (LineFamily.column, ⟨3, by decide⟩) + have h11 := hline (LineFamily.column, ⟨5, by decide⟩) + have h12 := hline (LineFamily.sum, ⟨2, by decide⟩) + have h13 := hline (LineFamily.sum, ⟨4, by decide⟩) + have h14 := hline (LineFamily.sum, ⟨6, by decide⟩) + have h15 := hline (LineFamily.sum, ⟨8, by decide⟩) + have h16 := hline (LineFamily.difference, ⟨5, by decide⟩) + have h17 := hline (LineFamily.difference, ⟨3, by decide⟩) + have h18 := hline (LineFamily.difference, ⟨7, by decide⟩) + norm_num [p0Point, OnLine, lineValue, bitNat] at h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 ⊢ + exact n6p0_sat (x 0) (x 1) (x 2) (x 3) (x 4) (x 5) + (x 6) (x 7) (x 8) (x 9) (x 10) (x 11) + (x 12) (x 13) (x 14) (x 15) (x 16) (x 17) + h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 + +#print axioms p0_bridge + +end Checkerboard From c878440b8c43a3703a057392655d61ef2b0b266c Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 02:25:12 -0700 Subject: [PATCH 36/59] Prove checkerboard n6 certificate with bv_omega --- Checkerboard/N6SATTest.lean | 150 +++++++++++++----------------------- 1 file changed, 54 insertions(+), 96 deletions(-) diff --git a/Checkerboard/N6SATTest.lean b/Checkerboard/N6SATTest.lean index 93827ef6..ad2b78a3 100644 --- a/Checkerboard/N6SATTest.lean +++ b/Checkerboard/N6SATTest.lean @@ -2,104 +2,62 @@ import Mathlib namespace Checkerboard -/-- Convert a Boolean selection bit to its natural indicator. -/ -def bitNat (b : Bool) : ℕ := if b then 1 else 0 +private def pop18 (x : BitVec 18) : BitVec 18 := + go x 0 18 +where + go (x pop : BitVec 18) : Nat → BitVec 18 + | 0 => pop + | n + 1 => go (x >>> 1) (pop + (x &&& 1)) n -/-- Integer certificate for the even checkerboard color class on the 6-board. -/ -theorem n6p0_sat - (x0 : Bool) (x1 : Bool) (x2 : Bool) (x3 : Bool) (x4 : Bool) (x5 : Bool) - (x6 : Bool) (x7 : Bool) (x8 : Bool) (x9 : Bool) (x10 : Bool) (x11 : Bool) - (x12 : Bool) (x13 : Bool) (x14 : Bool) (x15 : Bool) (x16 : Bool) (x17 : Bool) - (h0 : bitNat x0 + bitNat x1 + bitNat x2 ≤ 2) - (h1 : bitNat x3 + bitNat x4 + bitNat x5 ≤ 2) - (h2 : bitNat x6 + bitNat x7 + bitNat x8 ≤ 2) - (h3 : bitNat x9 + bitNat x10 + bitNat x11 ≤ 2) - (h4 : bitNat x12 + bitNat x13 + bitNat x14 ≤ 2) - (h5 : bitNat x15 + bitNat x16 + bitNat x17 ≤ 2) - (h6 : bitNat x0 + bitNat x6 + bitNat x12 ≤ 2) - (h7 : bitNat x1 + bitNat x7 + bitNat x13 ≤ 2) - (h8 : bitNat x2 + bitNat x8 + bitNat x14 ≤ 2) - (h9 : bitNat x3 + bitNat x9 + bitNat x15 ≤ 2) - (h10 : bitNat x4 + bitNat x10 + bitNat x16 ≤ 2) - (h11 : bitNat x5 + bitNat x11 + bitNat x17 ≤ 2) - (h12 : bitNat x1 + bitNat x3 + bitNat x6 ≤ 2) - (h13 : bitNat x2 + bitNat x4 + bitNat x7 + bitNat x9 + bitNat x12 ≤ 2) - (h14 : bitNat x5 + bitNat x8 + bitNat x10 + bitNat x13 + bitNat x15 ≤ 2) - (h15 : bitNat x11 + bitNat x14 + bitNat x16 ≤ 2) - (h16 : bitNat x0 + bitNat x3 + bitNat x7 + bitNat x10 + bitNat x14 + bitNat x17 ≤ 2) - (h17 : bitNat x1 + bitNat x4 + bitNat x8 + bitNat x11 ≤ 2) - (h18 : bitNat x6 + bitNat x9 + bitNat x13 + bitNat x16 ≤ 2) : - bitNat x0 + bitNat x1 + bitNat x2 + bitNat x3 + bitNat x4 + bitNat x5 + - bitNat x6 + bitNat x7 + bitNat x8 + bitNat x9 + bitNat x10 + bitNat x11 + - bitNat x12 + bitNat x13 + bitNat x14 + bitNat x15 + bitNat x16 + bitNat x17 ≤ 8 := by - have hx0 : bitNat x0 ≤ 1 := by cases x0 <;> simp [bitNat] - have hx1 : bitNat x1 ≤ 1 := by cases x1 <;> simp [bitNat] - have hx2 : bitNat x2 ≤ 1 := by cases x2 <;> simp [bitNat] - have hx3 : bitNat x3 ≤ 1 := by cases x3 <;> simp [bitNat] - have hx4 : bitNat x4 ≤ 1 := by cases x4 <;> simp [bitNat] - have hx5 : bitNat x5 ≤ 1 := by cases x5 <;> simp [bitNat] - have hx6 : bitNat x6 ≤ 1 := by cases x6 <;> simp [bitNat] - have hx7 : bitNat x7 ≤ 1 := by cases x7 <;> simp [bitNat] - have hx8 : bitNat x8 ≤ 1 := by cases x8 <;> simp [bitNat] - have hx9 : bitNat x9 ≤ 1 := by cases x9 <;> simp [bitNat] - have hx10 : bitNat x10 ≤ 1 := by cases x10 <;> simp [bitNat] - have hx11 : bitNat x11 ≤ 1 := by cases x11 <;> simp [bitNat] - have hx12 : bitNat x12 ≤ 1 := by cases x12 <;> simp [bitNat] - have hx13 : bitNat x13 ≤ 1 := by cases x13 <;> simp [bitNat] - have hx14 : bitNat x14 ≤ 1 := by cases x14 <;> simp [bitNat] - have hx15 : bitNat x15 ≤ 1 := by cases x15 <;> simp [bitNat] - have hx16 : bitNat x16 ≤ 1 := by cases x16 <;> simp [bitNat] - have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp [bitNat] - omega +private theorem p0_sat (x : BitVec 18) + (h0 : pop18 (x &&& 0x7#18) ≤ 2#18) + (h1 : pop18 (x &&& 0x38#18) ≤ 2#18) + (h2 : pop18 (x &&& 0x1c0#18) ≤ 2#18) + (h3 : pop18 (x &&& 0xe00#18) ≤ 2#18) + (h4 : pop18 (x &&& 0x7000#18) ≤ 2#18) + (h5 : pop18 (x &&& 0x38000#18) ≤ 2#18) + (h6 : pop18 (x &&& 0x1041#18) ≤ 2#18) + (h7 : pop18 (x &&& 0x2082#18) ≤ 2#18) + (h8 : pop18 (x &&& 0x4104#18) ≤ 2#18) + (h9 : pop18 (x &&& 0x8208#18) ≤ 2#18) + (h10 : pop18 (x &&& 0x10410#18) ≤ 2#18) + (h11 : pop18 (x &&& 0x20820#18) ≤ 2#18) + (h12 : pop18 (x &&& 0x4a#18) ≤ 2#18) + (h13 : pop18 (x &&& 0x1294#18) ≤ 2#18) + (h14 : pop18 (x &&& 0xa520#18) ≤ 2#18) + (h15 : pop18 (x &&& 0x14800#18) ≤ 2#18) + (h16 : pop18 (x &&& 0x24489#18) ≤ 2#18) + (h17 : pop18 (x &&& 0x912#18) ≤ 2#18) + (h18 : pop18 (x &&& 0x12240#18) ≤ 2#18) : + pop18 x ≤ 8#18 := by + dsimp [pop18, pop18.go] at * + bv_omega -/-- Integer certificate for the odd checkerboard color class on the 6-board. -/ -theorem n6p1_sat - (x0 : Bool) (x1 : Bool) (x2 : Bool) (x3 : Bool) (x4 : Bool) (x5 : Bool) - (x6 : Bool) (x7 : Bool) (x8 : Bool) (x9 : Bool) (x10 : Bool) (x11 : Bool) - (x12 : Bool) (x13 : Bool) (x14 : Bool) (x15 : Bool) (x16 : Bool) (x17 : Bool) - (h0 : bitNat x0 + bitNat x1 + bitNat x2 ≤ 2) - (h1 : bitNat x3 + bitNat x4 + bitNat x5 ≤ 2) - (h2 : bitNat x6 + bitNat x7 + bitNat x8 ≤ 2) - (h3 : bitNat x9 + bitNat x10 + bitNat x11 ≤ 2) - (h4 : bitNat x12 + bitNat x13 + bitNat x14 ≤ 2) - (h5 : bitNat x15 + bitNat x16 + bitNat x17 ≤ 2) - (h6 : bitNat x0 + bitNat x6 + bitNat x12 ≤ 2) - (h7 : bitNat x1 + bitNat x7 + bitNat x13 ≤ 2) - (h8 : bitNat x2 + bitNat x8 + bitNat x14 ≤ 2) - (h9 : bitNat x3 + bitNat x9 + bitNat x15 ≤ 2) - (h10 : bitNat x4 + bitNat x10 + bitNat x16 ≤ 2) - (h11 : bitNat x5 + bitNat x11 + bitNat x17 ≤ 2) - (h12 : bitNat x1 + bitNat x4 + bitNat x6 + bitNat x9 ≤ 2) - (h13 : bitNat x2 + bitNat x5 + bitNat x7 + bitNat x10 + bitNat x12 + bitNat x15 ≤ 2) - (h14 : bitNat x8 + bitNat x11 + bitNat x13 + bitNat x16 ≤ 2) - (h15 : bitNat x0 + bitNat x4 + bitNat x7 + bitNat x11 + bitNat x14 ≤ 2) - (h16 : bitNat x1 + bitNat x5 + bitNat x8 ≤ 2) - (h17 : bitNat x3 + bitNat x6 + bitNat x10 + bitNat x13 + bitNat x17 ≤ 2) - (h18 : bitNat x9 + bitNat x12 + bitNat x16 ≤ 2) : - bitNat x0 + bitNat x1 + bitNat x2 + bitNat x3 + bitNat x4 + bitNat x5 + - bitNat x6 + bitNat x7 + bitNat x8 + bitNat x9 + bitNat x10 + bitNat x11 + - bitNat x12 + bitNat x13 + bitNat x14 + bitNat x15 + bitNat x16 + bitNat x17 ≤ 8 := by - have hx0 : bitNat x0 ≤ 1 := by cases x0 <;> simp [bitNat] - have hx1 : bitNat x1 ≤ 1 := by cases x1 <;> simp [bitNat] - have hx2 : bitNat x2 ≤ 1 := by cases x2 <;> simp [bitNat] - have hx3 : bitNat x3 ≤ 1 := by cases x3 <;> simp [bitNat] - have hx4 : bitNat x4 ≤ 1 := by cases x4 <;> simp [bitNat] - have hx5 : bitNat x5 ≤ 1 := by cases x5 <;> simp [bitNat] - have hx6 : bitNat x6 ≤ 1 := by cases x6 <;> simp [bitNat] - have hx7 : bitNat x7 ≤ 1 := by cases x7 <;> simp [bitNat] - have hx8 : bitNat x8 ≤ 1 := by cases x8 <;> simp [bitNat] - have hx9 : bitNat x9 ≤ 1 := by cases x9 <;> simp [bitNat] - have hx10 : bitNat x10 ≤ 1 := by cases x10 <;> simp [bitNat] - have hx11 : bitNat x11 ≤ 1 := by cases x11 <;> simp [bitNat] - have hx12 : bitNat x12 ≤ 1 := by cases x12 <;> simp [bitNat] - have hx13 : bitNat x13 ≤ 1 := by cases x13 <;> simp [bitNat] - have hx14 : bitNat x14 ≤ 1 := by cases x14 <;> simp [bitNat] - have hx15 : bitNat x15 ≤ 1 := by cases x15 <;> simp [bitNat] - have hx16 : bitNat x16 ≤ 1 := by cases x16 <;> simp [bitNat] - have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp [bitNat] - omega +private theorem p1_sat (x : BitVec 18) + (h0 : pop18 (x &&& 0x7#18) ≤ 2#18) + (h1 : pop18 (x &&& 0x38#18) ≤ 2#18) + (h2 : pop18 (x &&& 0x1c0#18) ≤ 2#18) + (h3 : pop18 (x &&& 0xe00#18) ≤ 2#18) + (h4 : pop18 (x &&& 0x7000#18) ≤ 2#18) + (h5 : pop18 (x &&& 0x38000#18) ≤ 2#18) + (h6 : pop18 (x &&& 0x1041#18) ≤ 2#18) + (h7 : pop18 (x &&& 0x2082#18) ≤ 2#18) + (h8 : pop18 (x &&& 0x4104#18) ≤ 2#18) + (h9 : pop18 (x &&& 0x8208#18) ≤ 2#18) + (h10 : pop18 (x &&& 0x10410#18) ≤ 2#18) + (h11 : pop18 (x &&& 0x20820#18) ≤ 2#18) + (h12 : pop18 (x &&& 0x252#18) ≤ 2#18) + (h13 : pop18 (x &&& 0x94a4#18) ≤ 2#18) + (h14 : pop18 (x &&& 0x12900#18) ≤ 2#18) + (h15 : pop18 (x &&& 0x4891#18) ≤ 2#18) + (h16 : pop18 (x &&& 0x122#18) ≤ 2#18) + (h17 : pop18 (x &&& 0x22448#18) ≤ 2#18) + (h18 : pop18 (x &&& 0x11200#18) ≤ 2#18) : + pop18 x ≤ 8#18 := by + dsimp [pop18, pop18.go] at * + bv_omega -#print axioms n6p0_sat -#print axioms n6p1_sat +#print axioms p0_sat +#print axioms p1_sat end Checkerboard From 4738bccd062f9e6d744ac81da2cef598e1b5303b Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 02:26:49 -0700 Subject: [PATCH 37/59] Use bv_omega for checkerboard Boolean indicator certificate --- Checkerboard/N6SATTest.lean | 146 +++++++++++++++++++++++------------- 1 file changed, 94 insertions(+), 52 deletions(-) diff --git a/Checkerboard/N6SATTest.lean b/Checkerboard/N6SATTest.lean index ad2b78a3..b407ce38 100644 --- a/Checkerboard/N6SATTest.lean +++ b/Checkerboard/N6SATTest.lean @@ -2,62 +2,104 @@ import Mathlib namespace Checkerboard -private def pop18 (x : BitVec 18) : BitVec 18 := - go x 0 18 -where - go (x pop : BitVec 18) : Nat → BitVec 18 - | 0 => pop - | n + 1 => go (x >>> 1) (pop + (x &&& 1)) n +/-- Convert a Boolean selection bit to its natural indicator. -/ +def bitNat (b : Bool) : ℕ := if b then 1 else 0 -private theorem p0_sat (x : BitVec 18) - (h0 : pop18 (x &&& 0x7#18) ≤ 2#18) - (h1 : pop18 (x &&& 0x38#18) ≤ 2#18) - (h2 : pop18 (x &&& 0x1c0#18) ≤ 2#18) - (h3 : pop18 (x &&& 0xe00#18) ≤ 2#18) - (h4 : pop18 (x &&& 0x7000#18) ≤ 2#18) - (h5 : pop18 (x &&& 0x38000#18) ≤ 2#18) - (h6 : pop18 (x &&& 0x1041#18) ≤ 2#18) - (h7 : pop18 (x &&& 0x2082#18) ≤ 2#18) - (h8 : pop18 (x &&& 0x4104#18) ≤ 2#18) - (h9 : pop18 (x &&& 0x8208#18) ≤ 2#18) - (h10 : pop18 (x &&& 0x10410#18) ≤ 2#18) - (h11 : pop18 (x &&& 0x20820#18) ≤ 2#18) - (h12 : pop18 (x &&& 0x4a#18) ≤ 2#18) - (h13 : pop18 (x &&& 0x1294#18) ≤ 2#18) - (h14 : pop18 (x &&& 0xa520#18) ≤ 2#18) - (h15 : pop18 (x &&& 0x14800#18) ≤ 2#18) - (h16 : pop18 (x &&& 0x24489#18) ≤ 2#18) - (h17 : pop18 (x &&& 0x912#18) ≤ 2#18) - (h18 : pop18 (x &&& 0x12240#18) ≤ 2#18) : - pop18 x ≤ 8#18 := by - dsimp [pop18, pop18.go] at * +/-- Integer certificate for the even checkerboard color class on the 6-board. -/ +theorem n6p0_sat + (x0 : Bool) (x1 : Bool) (x2 : Bool) (x3 : Bool) (x4 : Bool) (x5 : Bool) + (x6 : Bool) (x7 : Bool) (x8 : Bool) (x9 : Bool) (x10 : Bool) (x11 : Bool) + (x12 : Bool) (x13 : Bool) (x14 : Bool) (x15 : Bool) (x16 : Bool) (x17 : Bool) + (h0 : bitNat x0 + bitNat x1 + bitNat x2 ≤ 2) + (h1 : bitNat x3 + bitNat x4 + bitNat x5 ≤ 2) + (h2 : bitNat x6 + bitNat x7 + bitNat x8 ≤ 2) + (h3 : bitNat x9 + bitNat x10 + bitNat x11 ≤ 2) + (h4 : bitNat x12 + bitNat x13 + bitNat x14 ≤ 2) + (h5 : bitNat x15 + bitNat x16 + bitNat x17 ≤ 2) + (h6 : bitNat x0 + bitNat x6 + bitNat x12 ≤ 2) + (h7 : bitNat x1 + bitNat x7 + bitNat x13 ≤ 2) + (h8 : bitNat x2 + bitNat x8 + bitNat x14 ≤ 2) + (h9 : bitNat x3 + bitNat x9 + bitNat x15 ≤ 2) + (h10 : bitNat x4 + bitNat x10 + bitNat x16 ≤ 2) + (h11 : bitNat x5 + bitNat x11 + bitNat x17 ≤ 2) + (h12 : bitNat x1 + bitNat x3 + bitNat x6 ≤ 2) + (h13 : bitNat x2 + bitNat x4 + bitNat x7 + bitNat x9 + bitNat x12 ≤ 2) + (h14 : bitNat x5 + bitNat x8 + bitNat x10 + bitNat x13 + bitNat x15 ≤ 2) + (h15 : bitNat x11 + bitNat x14 + bitNat x16 ≤ 2) + (h16 : bitNat x0 + bitNat x3 + bitNat x7 + bitNat x10 + bitNat x14 + bitNat x17 ≤ 2) + (h17 : bitNat x1 + bitNat x4 + bitNat x8 + bitNat x11 ≤ 2) + (h18 : bitNat x6 + bitNat x9 + bitNat x13 + bitNat x16 ≤ 2) : + bitNat x0 + bitNat x1 + bitNat x2 + bitNat x3 + bitNat x4 + bitNat x5 + + bitNat x6 + bitNat x7 + bitNat x8 + bitNat x9 + bitNat x10 + bitNat x11 + + bitNat x12 + bitNat x13 + bitNat x14 + bitNat x15 + bitNat x16 + bitNat x17 ≤ 8 := by + have hx0 : bitNat x0 ≤ 1 := by cases x0 <;> simp [bitNat] + have hx1 : bitNat x1 ≤ 1 := by cases x1 <;> simp [bitNat] + have hx2 : bitNat x2 ≤ 1 := by cases x2 <;> simp [bitNat] + have hx3 : bitNat x3 ≤ 1 := by cases x3 <;> simp [bitNat] + have hx4 : bitNat x4 ≤ 1 := by cases x4 <;> simp [bitNat] + have hx5 : bitNat x5 ≤ 1 := by cases x5 <;> simp [bitNat] + have hx6 : bitNat x6 ≤ 1 := by cases x6 <;> simp [bitNat] + have hx7 : bitNat x7 ≤ 1 := by cases x7 <;> simp [bitNat] + have hx8 : bitNat x8 ≤ 1 := by cases x8 <;> simp [bitNat] + have hx9 : bitNat x9 ≤ 1 := by cases x9 <;> simp [bitNat] + have hx10 : bitNat x10 ≤ 1 := by cases x10 <;> simp [bitNat] + have hx11 : bitNat x11 ≤ 1 := by cases x11 <;> simp [bitNat] + have hx12 : bitNat x12 ≤ 1 := by cases x12 <;> simp [bitNat] + have hx13 : bitNat x13 ≤ 1 := by cases x13 <;> simp [bitNat] + have hx14 : bitNat x14 ≤ 1 := by cases x14 <;> simp [bitNat] + have hx15 : bitNat x15 ≤ 1 := by cases x15 <;> simp [bitNat] + have hx16 : bitNat x16 ≤ 1 := by cases x16 <;> simp [bitNat] + have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp [bitNat] bv_omega -private theorem p1_sat (x : BitVec 18) - (h0 : pop18 (x &&& 0x7#18) ≤ 2#18) - (h1 : pop18 (x &&& 0x38#18) ≤ 2#18) - (h2 : pop18 (x &&& 0x1c0#18) ≤ 2#18) - (h3 : pop18 (x &&& 0xe00#18) ≤ 2#18) - (h4 : pop18 (x &&& 0x7000#18) ≤ 2#18) - (h5 : pop18 (x &&& 0x38000#18) ≤ 2#18) - (h6 : pop18 (x &&& 0x1041#18) ≤ 2#18) - (h7 : pop18 (x &&& 0x2082#18) ≤ 2#18) - (h8 : pop18 (x &&& 0x4104#18) ≤ 2#18) - (h9 : pop18 (x &&& 0x8208#18) ≤ 2#18) - (h10 : pop18 (x &&& 0x10410#18) ≤ 2#18) - (h11 : pop18 (x &&& 0x20820#18) ≤ 2#18) - (h12 : pop18 (x &&& 0x252#18) ≤ 2#18) - (h13 : pop18 (x &&& 0x94a4#18) ≤ 2#18) - (h14 : pop18 (x &&& 0x12900#18) ≤ 2#18) - (h15 : pop18 (x &&& 0x4891#18) ≤ 2#18) - (h16 : pop18 (x &&& 0x122#18) ≤ 2#18) - (h17 : pop18 (x &&& 0x22448#18) ≤ 2#18) - (h18 : pop18 (x &&& 0x11200#18) ≤ 2#18) : - pop18 x ≤ 8#18 := by - dsimp [pop18, pop18.go] at * +/-- Integer certificate for the odd checkerboard color class on the 6-board. -/ +theorem n6p1_sat + (x0 : Bool) (x1 : Bool) (x2 : Bool) (x3 : Bool) (x4 : Bool) (x5 : Bool) + (x6 : Bool) (x7 : Bool) (x8 : Bool) (x9 : Bool) (x10 : Bool) (x11 : Bool) + (x12 : Bool) (x13 : Bool) (x14 : Bool) (x15 : Bool) (x16 : Bool) (x17 : Bool) + (h0 : bitNat x0 + bitNat x1 + bitNat x2 ≤ 2) + (h1 : bitNat x3 + bitNat x4 + bitNat x5 ≤ 2) + (h2 : bitNat x6 + bitNat x7 + bitNat x8 ≤ 2) + (h3 : bitNat x9 + bitNat x10 + bitNat x11 ≤ 2) + (h4 : bitNat x12 + bitNat x13 + bitNat x14 ≤ 2) + (h5 : bitNat x15 + bitNat x16 + bitNat x17 ≤ 2) + (h6 : bitNat x0 + bitNat x6 + bitNat x12 ≤ 2) + (h7 : bitNat x1 + bitNat x7 + bitNat x13 ≤ 2) + (h8 : bitNat x2 + bitNat x8 + bitNat x14 ≤ 2) + (h9 : bitNat x3 + bitNat x9 + bitNat x15 ≤ 2) + (h10 : bitNat x4 + bitNat x10 + bitNat x16 ≤ 2) + (h11 : bitNat x5 + bitNat x11 + bitNat x17 ≤ 2) + (h12 : bitNat x1 + bitNat x4 + bitNat x6 + bitNat x9 ≤ 2) + (h13 : bitNat x2 + bitNat x5 + bitNat x7 + bitNat x10 + bitNat x12 + bitNat x15 ≤ 2) + (h14 : bitNat x8 + bitNat x11 + bitNat x13 + bitNat x16 ≤ 2) + (h15 : bitNat x0 + bitNat x4 + bitNat x7 + bitNat x11 + bitNat x14 ≤ 2) + (h16 : bitNat x1 + bitNat x5 + bitNat x8 ≤ 2) + (h17 : bitNat x3 + bitNat x6 + bitNat x10 + bitNat x13 + bitNat x17 ≤ 2) + (h18 : bitNat x9 + bitNat x12 + bitNat x16 ≤ 2) : + bitNat x0 + bitNat x1 + bitNat x2 + bitNat x3 + bitNat x4 + bitNat x5 + + bitNat x6 + bitNat x7 + bitNat x8 + bitNat x9 + bitNat x10 + bitNat x11 + + bitNat x12 + bitNat x13 + bitNat x14 + bitNat x15 + bitNat x16 + bitNat x17 ≤ 8 := by + have hx0 : bitNat x0 ≤ 1 := by cases x0 <;> simp [bitNat] + have hx1 : bitNat x1 ≤ 1 := by cases x1 <;> simp [bitNat] + have hx2 : bitNat x2 ≤ 1 := by cases x2 <;> simp [bitNat] + have hx3 : bitNat x3 ≤ 1 := by cases x3 <;> simp [bitNat] + have hx4 : bitNat x4 ≤ 1 := by cases x4 <;> simp [bitNat] + have hx5 : bitNat x5 ≤ 1 := by cases x5 <;> simp [bitNat] + have hx6 : bitNat x6 ≤ 1 := by cases x6 <;> simp [bitNat] + have hx7 : bitNat x7 ≤ 1 := by cases x7 <;> simp [bitNat] + have hx8 : bitNat x8 ≤ 1 := by cases x8 <;> simp [bitNat] + have hx9 : bitNat x9 ≤ 1 := by cases x9 <;> simp [bitNat] + have hx10 : bitNat x10 ≤ 1 := by cases x10 <;> simp [bitNat] + have hx11 : bitNat x11 ≤ 1 := by cases x11 <;> simp [bitNat] + have hx12 : bitNat x12 ≤ 1 := by cases x12 <;> simp [bitNat] + have hx13 : bitNat x13 ≤ 1 := by cases x13 <;> simp [bitNat] + have hx14 : bitNat x14 ≤ 1 := by cases x14 <;> simp [bitNat] + have hx15 : bitNat x15 ≤ 1 := by cases x15 <;> simp [bitNat] + have hx16 : bitNat x16 ≤ 1 := by cases x16 <;> simp [bitNat] + have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp [bitNat] bv_omega -#print axioms p0_sat -#print axioms p1_sat +#print axioms n6p0_sat +#print axioms n6p1_sat end Checkerboard From b2c96dd991abcf06da14ea35b19a5a319b036511 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 02:37:14 -0700 Subject: [PATCH 38/59] Bridge both checkerboard n6 color certificates --- Checkerboard/N6BridgeTest.lean | 42 ++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/Checkerboard/N6BridgeTest.lean b/Checkerboard/N6BridgeTest.lean index 3ace0592..d7f00cc7 100644 --- a/Checkerboard/N6BridgeTest.lean +++ b/Checkerboard/N6BridgeTest.lean @@ -14,6 +14,17 @@ private def p0Point : Fin 18 → Point 6 := ![ ((4 : Fin 6), (4 : Fin 6)), ((5 : Fin 6), (1 : Fin 6)), ((5 : Fin 6), (3 : Fin 6)), ((5 : Fin 6), (5 : Fin 6))] +private def p1Point : Fin 18 → Point 6 := ![ + ((0 : Fin 6), (1 : Fin 6)), ((0 : Fin 6), (3 : Fin 6)), + ((0 : Fin 6), (5 : Fin 6)), ((1 : Fin 6), (0 : Fin 6)), + ((1 : Fin 6), (2 : Fin 6)), ((1 : Fin 6), (4 : Fin 6)), + ((2 : Fin 6), (1 : Fin 6)), ((2 : Fin 6), (3 : Fin 6)), + ((2 : Fin 6), (5 : Fin 6)), ((3 : Fin 6), (0 : Fin 6)), + ((3 : Fin 6), (2 : Fin 6)), ((3 : Fin 6), (4 : Fin 6)), + ((4 : Fin 6), (1 : Fin 6)), ((4 : Fin 6), (3 : Fin 6)), + ((4 : Fin 6), (5 : Fin 6)), ((5 : Fin 6), (0 : Fin 6)), + ((5 : Fin 6), (2 : Fin 6)), ((5 : Fin 6), (4 : Fin 6))] + private theorem p0_bridge (x : Fin 18 → Bool) (hline : ∀ line : PrincipalLine 6, @@ -44,6 +55,37 @@ private theorem p0_bridge (x 12) (x 13) (x 14) (x 15) (x 16) (x 17) h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 +private theorem p1_bridge + (x : Fin 18 → Bool) + (hline : ∀ line : PrincipalLine 6, + (Finset.univ.filter fun i => x i = true ∧ OnLine line (p1Point i)).card ≤ 2) : + (Finset.univ.filter fun i => x i = true).card ≤ 8 := by + have h0 := hline (LineFamily.row, ⟨0, by decide⟩) + have h1 := hline (LineFamily.row, ⟨1, by decide⟩) + have h2 := hline (LineFamily.row, ⟨2, by decide⟩) + have h3 := hline (LineFamily.row, ⟨3, by decide⟩) + have h4 := hline (LineFamily.row, ⟨4, by decide⟩) + have h5 := hline (LineFamily.row, ⟨5, by decide⟩) + have h6 := hline (LineFamily.column, ⟨1, by decide⟩) + have h7 := hline (LineFamily.column, ⟨3, by decide⟩) + have h8 := hline (LineFamily.column, ⟨5, by decide⟩) + have h9 := hline (LineFamily.column, ⟨0, by decide⟩) + have h10 := hline (LineFamily.column, ⟨2, by decide⟩) + have h11 := hline (LineFamily.column, ⟨4, by decide⟩) + have h12 := hline (LineFamily.sum, ⟨3, by decide⟩) + have h13 := hline (LineFamily.sum, ⟨5, by decide⟩) + have h14 := hline (LineFamily.sum, ⟨7, by decide⟩) + have h15 := hline (LineFamily.difference, ⟨4, by decide⟩) + have h16 := hline (LineFamily.difference, ⟨2, by decide⟩) + have h17 := hline (LineFamily.difference, ⟨6, by decide⟩) + have h18 := hline (LineFamily.difference, ⟨8, by decide⟩) + norm_num [p1Point, OnLine, lineValue, bitNat] at h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 ⊢ + exact n6p1_sat (x 0) (x 1) (x 2) (x 3) (x 4) (x 5) + (x 6) (x 7) (x 8) (x 9) (x 10) (x 11) + (x 12) (x 13) (x 14) (x 15) (x 16) (x 17) + h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 + #print axioms p0_bridge +#print axioms p1_bridge end Checkerboard From 108f18a86c6388ab0b1996d8621e0b4113b83195 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 10:29:34 -0700 Subject: [PATCH 39/59] Repair compact checkerboard n6 arithmetic proof --- Checkerboard/N6SATTest.lean | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Checkerboard/N6SATTest.lean b/Checkerboard/N6SATTest.lean index b407ce38..8e259adc 100644 --- a/Checkerboard/N6SATTest.lean +++ b/Checkerboard/N6SATTest.lean @@ -1,5 +1,13 @@ import Mathlib +/-! +# Compact 6×6 checkerboard arithmetic certificates + +Proof developed by Dominic Dabish. ProofOrchestrator, using OpenAI GPT-5.6 Thinking, +assisted with the mathematical argument, Lean formalization, and submission +preparation. All formal claims are checked by the repository-pinned Lean compiler. +-/ + namespace Checkerboard /-- Convert a Boolean selection bit to its natural indicator. -/ @@ -50,7 +58,7 @@ theorem n6p0_sat have hx15 : bitNat x15 ≤ 1 := by cases x15 <;> simp [bitNat] have hx16 : bitNat x16 ≤ 1 := by cases x16 <;> simp [bitNat] have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp [bitNat] - bv_omega + omega /-- Integer certificate for the odd checkerboard color class on the 6-board. -/ theorem n6p1_sat @@ -97,7 +105,7 @@ theorem n6p1_sat have hx15 : bitNat x15 ≤ 1 := by cases x15 <;> simp [bitNat] have hx16 : bitNat x16 ≤ 1 := by cases x16 <;> simp [bitNat] have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp [bitNat] - bv_omega + omega #print axioms n6p0_sat #print axioms n6p1_sat From e191c548b76b15755b85cf0a3462f8c55cf98056 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 10:31:13 -0700 Subject: [PATCH 40/59] Integrate explicit checkerboard n6 certificates --- Checkerboard/N6Base.lean | 81 ++++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 20 deletions(-) diff --git a/Checkerboard/N6Base.lean b/Checkerboard/N6Base.lean index 9e20cd79..9d64321e 100644 --- a/Checkerboard/N6Base.lean +++ b/Checkerboard/N6Base.lean @@ -1,13 +1,18 @@ import Checkerboard.FourCertificate +import Checkerboard.N6SATTest /-! # The final 6×6 base cases -The uniform quadratic cover is sharp at value nine on the 6-board, so an +The uniform quadratic cover does not exclude nine points on the 6-board, so an integrality argument is required. Each color class has eighteen points. We -transport an arbitrary monochromatic set to eighteen Boolean variables, and -an exact finite kernel decision checks that row, column, and slope `±1` -capacities already force at most eight selected points. +transport an arbitrary monochromatic set to eighteen Boolean variables, derive +explicit row, column, and slope `±1` capacity inequalities, and discharge the +resulting Presburger certificates with `omega`. + +Proof developed by Dominic Dabish. ProofOrchestrator, using OpenAI GPT-5.6 Thinking, +assisted with the mathematical argument, Lean formalization, and submission +preparation. All formal claims are checked by the repository-pinned Lean compiler. -/ namespace Checkerboard @@ -152,14 +157,32 @@ private theorem n6p0_boolean_bound : (Finset.univ.filter fun i => x i = true ∧ OnLine line (n6p0Point i)).card ≤ 2) → (Finset.univ.filter fun i => x i = true).card ≤ 8 := by - letI : DecidablePred (fun x : Fin 18 → Bool => - (∀ line : PrincipalLine 6, - (Finset.univ.filter fun i => - x i = true ∧ OnLine line (n6p0Point i)).card ≤ 2) → - (Finset.univ.filter fun i => x i = true).card ≤ 8) := by - intro x - infer_instance - exact of_decide_eq_true rfl + intro x hline + have h0 := hline (LineFamily.row, ⟨0, by decide⟩) + have h1 := hline (LineFamily.row, ⟨1, by decide⟩) + have h2 := hline (LineFamily.row, ⟨2, by decide⟩) + have h3 := hline (LineFamily.row, ⟨3, by decide⟩) + have h4 := hline (LineFamily.row, ⟨4, by decide⟩) + have h5 := hline (LineFamily.row, ⟨5, by decide⟩) + have h6 := hline (LineFamily.column, ⟨0, by decide⟩) + have h7 := hline (LineFamily.column, ⟨2, by decide⟩) + have h8 := hline (LineFamily.column, ⟨4, by decide⟩) + have h9 := hline (LineFamily.column, ⟨1, by decide⟩) + have h10 := hline (LineFamily.column, ⟨3, by decide⟩) + have h11 := hline (LineFamily.column, ⟨5, by decide⟩) + have h12 := hline (LineFamily.sum, ⟨2, by decide⟩) + have h13 := hline (LineFamily.sum, ⟨4, by decide⟩) + have h14 := hline (LineFamily.sum, ⟨6, by decide⟩) + have h15 := hline (LineFamily.sum, ⟨8, by decide⟩) + have h16 := hline (LineFamily.difference, ⟨5, by decide⟩) + have h17 := hline (LineFamily.difference, ⟨3, by decide⟩) + have h18 := hline (LineFamily.difference, ⟨7, by decide⟩) + norm_num [n6p0Point, OnLine, lineValue, bitNat] at + h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 ⊢ + exact n6p0_sat (x 0) (x 1) (x 2) (x 3) (x 4) (x 5) + (x 6) (x 7) (x 8) (x 9) (x 10) (x 11) + (x 12) (x 13) (x 14) (x 15) (x 16) (x 17) + h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 private theorem n6p1_boolean_bound : ∀ x : Fin 18 → Bool, @@ -167,14 +190,32 @@ private theorem n6p1_boolean_bound : (Finset.univ.filter fun i => x i = true ∧ OnLine line (n6p1Point i)).card ≤ 2) → (Finset.univ.filter fun i => x i = true).card ≤ 8 := by - letI : DecidablePred (fun x : Fin 18 → Bool => - (∀ line : PrincipalLine 6, - (Finset.univ.filter fun i => - x i = true ∧ OnLine line (n6p1Point i)).card ≤ 2) → - (Finset.univ.filter fun i => x i = true).card ≤ 8) := by - intro x - infer_instance - exact of_decide_eq_true rfl + intro x hline + have h0 := hline (LineFamily.row, ⟨0, by decide⟩) + have h1 := hline (LineFamily.row, ⟨1, by decide⟩) + have h2 := hline (LineFamily.row, ⟨2, by decide⟩) + have h3 := hline (LineFamily.row, ⟨3, by decide⟩) + have h4 := hline (LineFamily.row, ⟨4, by decide⟩) + have h5 := hline (LineFamily.row, ⟨5, by decide⟩) + have h6 := hline (LineFamily.column, ⟨1, by decide⟩) + have h7 := hline (LineFamily.column, ⟨3, by decide⟩) + have h8 := hline (LineFamily.column, ⟨5, by decide⟩) + have h9 := hline (LineFamily.column, ⟨0, by decide⟩) + have h10 := hline (LineFamily.column, ⟨2, by decide⟩) + have h11 := hline (LineFamily.column, ⟨4, by decide⟩) + have h12 := hline (LineFamily.sum, ⟨3, by decide⟩) + have h13 := hline (LineFamily.sum, ⟨5, by decide⟩) + have h14 := hline (LineFamily.sum, ⟨7, by decide⟩) + have h15 := hline (LineFamily.difference, ⟨4, by decide⟩) + have h16 := hline (LineFamily.difference, ⟨2, by decide⟩) + have h17 := hline (LineFamily.difference, ⟨6, by decide⟩) + have h18 := hline (LineFamily.difference, ⟨8, by decide⟩) + norm_num [n6p1Point, OnLine, lineValue, bitNat] at + h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 ⊢ + exact n6p1_sat (x 0) (x 1) (x 2) (x 3) (x 4) (x 5) + (x 6) (x 7) (x 8) (x 9) (x 10) (x 11) + (x 12) (x 13) (x 14) (x 15) (x 16) (x 17) + h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 /-- `D_mono(6,0) ≤ 8`. -/ theorem n6_zero_upper (s : Finset (Point 6)) From bb9e424da60caa687e45303361e5ee43d27c3430 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 10:37:00 -0700 Subject: [PATCH 41/59] Split compact checkerboard n6 certificates --- Checkerboard/N6SATTest.lean | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Checkerboard/N6SATTest.lean b/Checkerboard/N6SATTest.lean index 8e259adc..8bbf2c6e 100644 --- a/Checkerboard/N6SATTest.lean +++ b/Checkerboard/N6SATTest.lean @@ -10,6 +10,8 @@ preparation. All formal claims are checked by the repository-pinned Lean compile namespace Checkerboard +set_option maxHeartbeats 0 + /-- Convert a Boolean selection bit to its natural indicator. -/ def bitNat (b : Bool) : ℕ := if b then 1 else 0 @@ -58,7 +60,7 @@ theorem n6p0_sat have hx15 : bitNat x15 ≤ 1 := by cases x15 <;> simp [bitNat] have hx16 : bitNat x16 ≤ 1 := by cases x16 <;> simp [bitNat] have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp [bitNat] - omega + cases x0 <;> cases x1 <;> simp [bitNat] at * <;> omega /-- Integer certificate for the odd checkerboard color class on the 6-board. -/ theorem n6p1_sat @@ -105,7 +107,7 @@ theorem n6p1_sat have hx15 : bitNat x15 ≤ 1 := by cases x15 <;> simp [bitNat] have hx16 : bitNat x16 ≤ 1 := by cases x16 <;> simp [bitNat] have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp [bitNat] - omega + cases x0 <;> cases x1 <;> simp [bitNat] at * <;> omega #print axioms n6p0_sat #print axioms n6p1_sat From ad1baeac925239fa830496fc3169e9f057748c50 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 10:41:47 -0700 Subject: [PATCH 42/59] Keep checkerboard n6 indicators opaque --- Checkerboard/N6SATTest.lean | 81 ++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/Checkerboard/N6SATTest.lean b/Checkerboard/N6SATTest.lean index 8bbf2c6e..9e2fc9e3 100644 --- a/Checkerboard/N6SATTest.lean +++ b/Checkerboard/N6SATTest.lean @@ -15,6 +15,9 @@ set_option maxHeartbeats 0 /-- Convert a Boolean selection bit to its natural indicator. -/ def bitNat (b : Bool) : ℕ := if b then 1 else 0 +@[simp] theorem bitNat_false : bitNat false = 0 := rfl +@[simp] theorem bitNat_true : bitNat true = 1 := rfl + /-- Integer certificate for the even checkerboard color class on the 6-board. -/ theorem n6p0_sat (x0 : Bool) (x1 : Bool) (x2 : Bool) (x3 : Bool) (x4 : Bool) (x5 : Bool) @@ -42,25 +45,26 @@ theorem n6p0_sat bitNat x0 + bitNat x1 + bitNat x2 + bitNat x3 + bitNat x4 + bitNat x5 + bitNat x6 + bitNat x7 + bitNat x8 + bitNat x9 + bitNat x10 + bitNat x11 + bitNat x12 + bitNat x13 + bitNat x14 + bitNat x15 + bitNat x16 + bitNat x17 ≤ 8 := by - have hx0 : bitNat x0 ≤ 1 := by cases x0 <;> simp [bitNat] - have hx1 : bitNat x1 ≤ 1 := by cases x1 <;> simp [bitNat] - have hx2 : bitNat x2 ≤ 1 := by cases x2 <;> simp [bitNat] - have hx3 : bitNat x3 ≤ 1 := by cases x3 <;> simp [bitNat] - have hx4 : bitNat x4 ≤ 1 := by cases x4 <;> simp [bitNat] - have hx5 : bitNat x5 ≤ 1 := by cases x5 <;> simp [bitNat] - have hx6 : bitNat x6 ≤ 1 := by cases x6 <;> simp [bitNat] - have hx7 : bitNat x7 ≤ 1 := by cases x7 <;> simp [bitNat] - have hx8 : bitNat x8 ≤ 1 := by cases x8 <;> simp [bitNat] - have hx9 : bitNat x9 ≤ 1 := by cases x9 <;> simp [bitNat] - have hx10 : bitNat x10 ≤ 1 := by cases x10 <;> simp [bitNat] - have hx11 : bitNat x11 ≤ 1 := by cases x11 <;> simp [bitNat] - have hx12 : bitNat x12 ≤ 1 := by cases x12 <;> simp [bitNat] - have hx13 : bitNat x13 ≤ 1 := by cases x13 <;> simp [bitNat] - have hx14 : bitNat x14 ≤ 1 := by cases x14 <;> simp [bitNat] - have hx15 : bitNat x15 ≤ 1 := by cases x15 <;> simp [bitNat] - have hx16 : bitNat x16 ≤ 1 := by cases x16 <;> simp [bitNat] - have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp [bitNat] - cases x0 <;> cases x1 <;> simp [bitNat] at * <;> omega + have hx0 : bitNat x0 ≤ 1 := by cases x0 <;> simp + have hx1 : bitNat x1 ≤ 1 := by cases x1 <;> simp + have hx2 : bitNat x2 ≤ 1 := by cases x2 <;> simp + have hx3 : bitNat x3 ≤ 1 := by cases x3 <;> simp + have hx4 : bitNat x4 ≤ 1 := by cases x4 <;> simp + have hx5 : bitNat x5 ≤ 1 := by cases x5 <;> simp + have hx6 : bitNat x6 ≤ 1 := by cases x6 <;> simp + have hx7 : bitNat x7 ≤ 1 := by cases x7 <;> simp + have hx8 : bitNat x8 ≤ 1 := by cases x8 <;> simp + have hx9 : bitNat x9 ≤ 1 := by cases x9 <;> simp + have hx10 : bitNat x10 ≤ 1 := by cases x10 <;> simp + have hx11 : bitNat x11 ≤ 1 := by cases x11 <;> simp + have hx12 : bitNat x12 ≤ 1 := by cases x12 <;> simp + have hx13 : bitNat x13 ≤ 1 := by cases x13 <;> simp + have hx14 : bitNat x14 ≤ 1 := by cases x14 <;> simp + have hx15 : bitNat x15 ≤ 1 := by cases x15 <;> simp + have hx16 : bitNat x16 ≤ 1 := by cases x16 <;> simp + have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp + cases x0 <;> cases x1 <;> + simp only [bitNat_false, bitNat_true, Nat.zero_add, Nat.add_zero] at * <;> omega /-- Integer certificate for the odd checkerboard color class on the 6-board. -/ theorem n6p1_sat @@ -89,25 +93,26 @@ theorem n6p1_sat bitNat x0 + bitNat x1 + bitNat x2 + bitNat x3 + bitNat x4 + bitNat x5 + bitNat x6 + bitNat x7 + bitNat x8 + bitNat x9 + bitNat x10 + bitNat x11 + bitNat x12 + bitNat x13 + bitNat x14 + bitNat x15 + bitNat x16 + bitNat x17 ≤ 8 := by - have hx0 : bitNat x0 ≤ 1 := by cases x0 <;> simp [bitNat] - have hx1 : bitNat x1 ≤ 1 := by cases x1 <;> simp [bitNat] - have hx2 : bitNat x2 ≤ 1 := by cases x2 <;> simp [bitNat] - have hx3 : bitNat x3 ≤ 1 := by cases x3 <;> simp [bitNat] - have hx4 : bitNat x4 ≤ 1 := by cases x4 <;> simp [bitNat] - have hx5 : bitNat x5 ≤ 1 := by cases x5 <;> simp [bitNat] - have hx6 : bitNat x6 ≤ 1 := by cases x6 <;> simp [bitNat] - have hx7 : bitNat x7 ≤ 1 := by cases x7 <;> simp [bitNat] - have hx8 : bitNat x8 ≤ 1 := by cases x8 <;> simp [bitNat] - have hx9 : bitNat x9 ≤ 1 := by cases x9 <;> simp [bitNat] - have hx10 : bitNat x10 ≤ 1 := by cases x10 <;> simp [bitNat] - have hx11 : bitNat x11 ≤ 1 := by cases x11 <;> simp [bitNat] - have hx12 : bitNat x12 ≤ 1 := by cases x12 <;> simp [bitNat] - have hx13 : bitNat x13 ≤ 1 := by cases x13 <;> simp [bitNat] - have hx14 : bitNat x14 ≤ 1 := by cases x14 <;> simp [bitNat] - have hx15 : bitNat x15 ≤ 1 := by cases x15 <;> simp [bitNat] - have hx16 : bitNat x16 ≤ 1 := by cases x16 <;> simp [bitNat] - have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp [bitNat] - cases x0 <;> cases x1 <;> simp [bitNat] at * <;> omega + have hx0 : bitNat x0 ≤ 1 := by cases x0 <;> simp + have hx1 : bitNat x1 ≤ 1 := by cases x1 <;> simp + have hx2 : bitNat x2 ≤ 1 := by cases x2 <;> simp + have hx3 : bitNat x3 ≤ 1 := by cases x3 <;> simp + have hx4 : bitNat x4 ≤ 1 := by cases x4 <;> simp + have hx5 : bitNat x5 ≤ 1 := by cases x5 <;> simp + have hx6 : bitNat x6 ≤ 1 := by cases x6 <;> simp + have hx7 : bitNat x7 ≤ 1 := by cases x7 <;> simp + have hx8 : bitNat x8 ≤ 1 := by cases x8 <;> simp + have hx9 : bitNat x9 ≤ 1 := by cases x9 <;> simp + have hx10 : bitNat x10 ≤ 1 := by cases x10 <;> simp + have hx11 : bitNat x11 ≤ 1 := by cases x11 <;> simp + have hx12 : bitNat x12 ≤ 1 := by cases x12 <;> simp + have hx13 : bitNat x13 ≤ 1 := by cases x13 <;> simp + have hx14 : bitNat x14 ≤ 1 := by cases x14 <;> simp + have hx15 : bitNat x15 ≤ 1 := by cases x15 <;> simp + have hx16 : bitNat x16 ≤ 1 := by cases x16 <;> simp + have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp + cases x0 <;> cases x1 <;> + simp only [bitNat_false, bitNat_true, Nat.zero_add, Nat.add_zero] at * <;> omega #print axioms n6p0_sat #print axioms n6p1_sat From 100efa954491eb2c201796d251764d94dbb65edf Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 10:46:40 -0700 Subject: [PATCH 43/59] Use sparse checkerboard n6 dual supports --- Checkerboard/N6SATTest.lean | 113 +++++++++++++++++++++++------------- 1 file changed, 73 insertions(+), 40 deletions(-) diff --git a/Checkerboard/N6SATTest.lean b/Checkerboard/N6SATTest.lean index 9e2fc9e3..fe71cf41 100644 --- a/Checkerboard/N6SATTest.lean +++ b/Checkerboard/N6SATTest.lean @@ -18,6 +18,9 @@ def bitNat (b : Bool) : ℕ := if b then 1 else 0 @[simp] theorem bitNat_false : bitNat false = 0 := rfl @[simp] theorem bitNat_true : bitNat true = 1 := rfl +theorem bitNat_le_one (b : Bool) : bitNat b ≤ 1 := by + cases b <;> simp + /-- Integer certificate for the even checkerboard color class on the 6-board. -/ theorem n6p0_sat (x0 : Bool) (x1 : Bool) (x2 : Bool) (x3 : Bool) (x4 : Bool) (x5 : Bool) @@ -45,26 +48,41 @@ theorem n6p0_sat bitNat x0 + bitNat x1 + bitNat x2 + bitNat x3 + bitNat x4 + bitNat x5 + bitNat x6 + bitNat x7 + bitNat x8 + bitNat x9 + bitNat x10 + bitNat x11 + bitNat x12 + bitNat x13 + bitNat x14 + bitNat x15 + bitNat x16 + bitNat x17 ≤ 8 := by - have hx0 : bitNat x0 ≤ 1 := by cases x0 <;> simp - have hx1 : bitNat x1 ≤ 1 := by cases x1 <;> simp - have hx2 : bitNat x2 ≤ 1 := by cases x2 <;> simp - have hx3 : bitNat x3 ≤ 1 := by cases x3 <;> simp - have hx4 : bitNat x4 ≤ 1 := by cases x4 <;> simp - have hx5 : bitNat x5 ≤ 1 := by cases x5 <;> simp - have hx6 : bitNat x6 ≤ 1 := by cases x6 <;> simp - have hx7 : bitNat x7 ≤ 1 := by cases x7 <;> simp - have hx8 : bitNat x8 ≤ 1 := by cases x8 <;> simp - have hx9 : bitNat x9 ≤ 1 := by cases x9 <;> simp - have hx10 : bitNat x10 ≤ 1 := by cases x10 <;> simp - have hx11 : bitNat x11 ≤ 1 := by cases x11 <;> simp - have hx12 : bitNat x12 ≤ 1 := by cases x12 <;> simp - have hx13 : bitNat x13 ≤ 1 := by cases x13 <;> simp - have hx14 : bitNat x14 ≤ 1 := by cases x14 <;> simp - have hx15 : bitNat x15 ≤ 1 := by cases x15 <;> simp - have hx16 : bitNat x16 ≤ 1 := by cases x16 <;> simp - have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp - cases x0 <;> cases x1 <;> - simp only [bitNat_false, bitNat_true, Nat.zero_add, Nat.add_zero] at * <;> omega + have hx0 := bitNat_le_one x0 + have hx1 := bitNat_le_one x1 + have hx2 := bitNat_le_one x2 + have hx3 := bitNat_le_one x3 + have hx4 := bitNat_le_one x4 + have hx5 := bitNat_le_one x5 + have hx6 := bitNat_le_one x6 + have hx7 := bitNat_le_one x7 + have hx8 := bitNat_le_one x8 + have hx9 := bitNat_le_one x9 + have hx10 := bitNat_le_one x10 + have hx11 := bitNat_le_one x11 + have hx12 := bitNat_le_one x12 + have hx13 := bitNat_le_one x13 + have hx14 := bitNat_le_one x14 + have hx15 := bitNat_le_one x15 + have hx16 := bitNat_le_one x16 + have hx17 := bitNat_le_one x17 + cases x0 <;> cases x1 + · simp only [bitNat_false, bitNat_true, Nat.zero_add, Nat.add_zero] at * + clear h0 h1 h2 h3 h4 h6 h7 h9 h10 h12 + hx0 hx1 hx2 hx4 hx5 hx7 hx8 hx9 hx10 hx13 hx14 hx15 hx16 hx17 + omega + · simp only [bitNat_false, bitNat_true, Nat.zero_add, Nat.add_zero] at * + clear h0 h1 h2 h3 h6 h7 h9 h10 + hx0 hx1 hx2 hx3 hx4 hx5 hx7 hx8 hx9 hx10 hx11 hx12 hx13 hx14 hx15 hx16 hx17 + omega + · simp only [bitNat_false, bitNat_true, Nat.zero_add, Nat.add_zero] at * + clear h0 h2 h3 h4 h7 h8 h9 h10 h11 h12 + hx0 hx1 hx3 hx4 hx5 hx6 hx7 hx8 hx9 hx10 hx12 hx13 hx14 hx15 hx16 hx17 + omega + · simp only [bitNat_false, bitNat_true, Nat.zero_add, Nat.add_zero] at * + clear h1 h2 h3 h4 h7 h8 h10 h12 + hx0 hx1 hx2 hx3 hx4 hx6 hx7 hx8 hx9 hx10 hx11 hx12 hx13 hx14 hx15 hx17 + omega /-- Integer certificate for the odd checkerboard color class on the 6-board. -/ theorem n6p1_sat @@ -93,26 +111,41 @@ theorem n6p1_sat bitNat x0 + bitNat x1 + bitNat x2 + bitNat x3 + bitNat x4 + bitNat x5 + bitNat x6 + bitNat x7 + bitNat x8 + bitNat x9 + bitNat x10 + bitNat x11 + bitNat x12 + bitNat x13 + bitNat x14 + bitNat x15 + bitNat x16 + bitNat x17 ≤ 8 := by - have hx0 : bitNat x0 ≤ 1 := by cases x0 <;> simp - have hx1 : bitNat x1 ≤ 1 := by cases x1 <;> simp - have hx2 : bitNat x2 ≤ 1 := by cases x2 <;> simp - have hx3 : bitNat x3 ≤ 1 := by cases x3 <;> simp - have hx4 : bitNat x4 ≤ 1 := by cases x4 <;> simp - have hx5 : bitNat x5 ≤ 1 := by cases x5 <;> simp - have hx6 : bitNat x6 ≤ 1 := by cases x6 <;> simp - have hx7 : bitNat x7 ≤ 1 := by cases x7 <;> simp - have hx8 : bitNat x8 ≤ 1 := by cases x8 <;> simp - have hx9 : bitNat x9 ≤ 1 := by cases x9 <;> simp - have hx10 : bitNat x10 ≤ 1 := by cases x10 <;> simp - have hx11 : bitNat x11 ≤ 1 := by cases x11 <;> simp - have hx12 : bitNat x12 ≤ 1 := by cases x12 <;> simp - have hx13 : bitNat x13 ≤ 1 := by cases x13 <;> simp - have hx14 : bitNat x14 ≤ 1 := by cases x14 <;> simp - have hx15 : bitNat x15 ≤ 1 := by cases x15 <;> simp - have hx16 : bitNat x16 ≤ 1 := by cases x16 <;> simp - have hx17 : bitNat x17 ≤ 1 := by cases x17 <;> simp - cases x0 <;> cases x1 <;> - simp only [bitNat_false, bitNat_true, Nat.zero_add, Nat.add_zero] at * <;> omega + have hx0 := bitNat_le_one x0 + have hx1 := bitNat_le_one x1 + have hx2 := bitNat_le_one x2 + have hx3 := bitNat_le_one x3 + have hx4 := bitNat_le_one x4 + have hx5 := bitNat_le_one x5 + have hx6 := bitNat_le_one x6 + have hx7 := bitNat_le_one x7 + have hx8 := bitNat_le_one x8 + have hx9 := bitNat_le_one x9 + have hx10 := bitNat_le_one x10 + have hx11 := bitNat_le_one x11 + have hx12 := bitNat_le_one x12 + have hx13 := bitNat_le_one x13 + have hx14 := bitNat_le_one x14 + have hx15 := bitNat_le_one x15 + have hx16 := bitNat_le_one x16 + have hx17 := bitNat_le_one x17 + cases x0 <;> cases x1 + · simp only [bitNat_false, bitNat_true, Nat.zero_add, Nat.add_zero] at * + clear h0 h2 h3 h4 h6 h7 h10 h16 + hx0 hx1 hx2 hx3 hx4 hx5 hx6 hx7 hx9 hx10 hx11 hx12 hx13 hx15 hx16 hx17 + omega + · simp only [bitNat_false, bitNat_true, Nat.zero_add, Nat.add_zero] at * + clear h0 h1 h2 h3 h4 h6 h7 h10 + hx0 hx1 hx2 hx4 hx5 hx6 hx7 hx8 hx9 hx10 hx11 hx12 hx13 hx15 hx16 hx17 + omega + · simp only [bitNat_false, bitNat_true, Nat.zero_add, Nat.add_zero] at * + clear h0 h2 h3 h4 h6 h7 h10 h11 h16 + hx0 hx1 hx2 hx3 hx4 hx6 hx7 hx10 hx11 hx12 hx13 hx14 hx15 hx16 hx17 + omega + · simp only [bitNat_false, bitNat_true, Nat.zero_add, Nat.add_zero] at * + clear h1 h2 h3 h7 h8 h10 h11 + hx0 hx1 hx2 hx3 hx4 hx5 hx6 hx7 hx9 hx10 hx11 hx12 hx13 hx14 hx15 hx16 hx17 + omega #print axioms n6p0_sat #print axioms n6p1_sat From 10d707f79fb189bd69fdf3a38c9ba309e16ee3f9 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 10:52:01 -0700 Subject: [PATCH 44/59] Fix checkerboard n6 normalization syntax --- Checkerboard/N6Base.lean | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Checkerboard/N6Base.lean b/Checkerboard/N6Base.lean index 9d64321e..176b86cc 100644 --- a/Checkerboard/N6Base.lean +++ b/Checkerboard/N6Base.lean @@ -177,8 +177,7 @@ private theorem n6p0_boolean_bound : have h16 := hline (LineFamily.difference, ⟨5, by decide⟩) have h17 := hline (LineFamily.difference, ⟨3, by decide⟩) have h18 := hline (LineFamily.difference, ⟨7, by decide⟩) - norm_num [n6p0Point, OnLine, lineValue, bitNat] at - h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 ⊢ + norm_num [n6p0Point, OnLine, lineValue, bitNat] at h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 ⊢ exact n6p0_sat (x 0) (x 1) (x 2) (x 3) (x 4) (x 5) (x 6) (x 7) (x 8) (x 9) (x 10) (x 11) (x 12) (x 13) (x 14) (x 15) (x 16) (x 17) @@ -210,8 +209,7 @@ private theorem n6p1_boolean_bound : have h16 := hline (LineFamily.difference, ⟨2, by decide⟩) have h17 := hline (LineFamily.difference, ⟨6, by decide⟩) have h18 := hline (LineFamily.difference, ⟨8, by decide⟩) - norm_num [n6p1Point, OnLine, lineValue, bitNat] at - h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 ⊢ + norm_num [n6p1Point, OnLine, lineValue, bitNat] at h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 ⊢ exact n6p1_sat (x 0) (x 1) (x 2) (x 3) (x 4) (x 5) (x 6) (x 7) (x 8) (x 9) (x 10) (x 11) (x 12) (x 13) (x 14) (x 15) (x 16) (x 17) From 2151891ca7ed01b573139491a6e20c59dac729a2 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 10:52:26 -0700 Subject: [PATCH 45/59] Normalize even checkerboard quadratic identity --- Checkerboard/QuadraticWeights.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Checkerboard/QuadraticWeights.lean b/Checkerboard/QuadraticWeights.lean index 732beeb5..70e228a4 100644 --- a/Checkerboard/QuadraticWeights.lean +++ b/Checkerboard/QuadraticWeights.lean @@ -142,6 +142,6 @@ theorem evenQuadratic_coverage (m parity : ℕ) (hp : parity = 0 ∨ parity = 1) rw [if_pos hsum, if_pos hdiff] simp only [evenCap, sumIndex, differenceIndex] push_cast [Nat.cast_sub hy, Nat.cast_sub hmtwo] - ring + ring_nf end Checkerboard From e5aba03c2371c5fb259dcd9333dc85a0a5c723b6 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 10:56:41 -0700 Subject: [PATCH 46/59] Make even checkerboard cast identity explicit --- Checkerboard/QuadraticWeights.lean | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Checkerboard/QuadraticWeights.lean b/Checkerboard/QuadraticWeights.lean index 70e228a4..ddafa1bd 100644 --- a/Checkerboard/QuadraticWeights.lean +++ b/Checkerboard/QuadraticWeights.lean @@ -137,11 +137,16 @@ theorem evenQuadratic_coverage (m parity : ℕ) (hp : parity = 0 ∨ parity = 1) simp [differenceIndex, InColor] at hcolor ⊢ <;> omega have hy : p.2.1 ≤ 2 * m - 1 := by omega have hmtwo : 1 ≤ m * 2 := by omega + have hcast : (((m * 2 - 1 : ℕ) : ℚ)) = 2 * (m : ℚ) - 1 := by + rw [Nat.cast_sub hmtwo] + norm_num + ring unfold fourCoverage evenQuadraticWeights dsimp rw [if_pos hsum, if_pos hdiff] simp only [evenCap, sumIndex, differenceIndex] - push_cast [Nat.cast_sub hy, Nat.cast_sub hmtwo] - ring_nf + push_cast [Nat.cast_sub hy] + rw [hcast] + ring end Checkerboard From 5fa90d646295dfc48baef23a90fe1e2883366ec5 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 10:57:29 -0700 Subject: [PATCH 47/59] Bridge checkerboard line cards to Boolean indicators --- Checkerboard/N6Base.lean | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/Checkerboard/N6Base.lean b/Checkerboard/N6Base.lean index 176b86cc..4d3b8a50 100644 --- a/Checkerboard/N6Base.lean +++ b/Checkerboard/N6Base.lean @@ -73,6 +73,27 @@ private def chosenOnLine (point : Fin 18 → Point 6) (s : Finset (Point 6)) (line : PrincipalLine 6) : Finset (Fin 18) := Finset.univ.filter fun i => point i ∈ s ∧ OnLine line (point i) +private theorem card_filter_bool {α : Type*} (s : Finset α) (x : α → Bool) : + (s.filter fun i => x i = true).card = ∑ i in s, bitNat (x i) := by + classical + induction s using Finset.induction_on with + | empty => simp + | @insert a s ha ih => + cases hxa : x a <;> simp [ha, ih, hxa, bitNat] + +private theorem card_filter_bool_and {α : Type*} (s : Finset α) + (x : α → Bool) (p : α → Prop) [DecidablePred p] : + (s.filter fun i => x i = true ∧ p i).card = + ∑ i in s.filter p, bitNat (x i) := by + classical + have hfilter : + s.filter (fun i => x i = true ∧ p i) = + (s.filter p).filter (fun i => x i = true) := by + ext i + simp [and_comm] + rw [hfilter] + exact card_filter_bool (s.filter p) x + private theorem chosenIndices_image {parity : ℕ} (point : Fin 18 → Point 6) (hsurj : ∀ p : Point 6, InColor parity p → ∃ i, point i = p) @@ -177,7 +198,10 @@ private theorem n6p0_boolean_bound : have h16 := hline (LineFamily.difference, ⟨5, by decide⟩) have h17 := hline (LineFamily.difference, ⟨3, by decide⟩) have h18 := hline (LineFamily.difference, ⟨7, by decide⟩) - norm_num [n6p0Point, OnLine, lineValue, bitNat] at h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 ⊢ + rw [card_filter_bool_and] at h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 + norm_num [n6p0Point, OnLine, lineValue] at h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 + rw [card_filter_bool] + norm_num exact n6p0_sat (x 0) (x 1) (x 2) (x 3) (x 4) (x 5) (x 6) (x 7) (x 8) (x 9) (x 10) (x 11) (x 12) (x 13) (x 14) (x 15) (x 16) (x 17) @@ -209,7 +233,10 @@ private theorem n6p1_boolean_bound : have h16 := hline (LineFamily.difference, ⟨2, by decide⟩) have h17 := hline (LineFamily.difference, ⟨6, by decide⟩) have h18 := hline (LineFamily.difference, ⟨8, by decide⟩) - norm_num [n6p1Point, OnLine, lineValue, bitNat] at h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 ⊢ + rw [card_filter_bool_and] at h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 + norm_num [n6p1Point, OnLine, lineValue] at h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 + rw [card_filter_bool] + norm_num exact n6p1_sat (x 0) (x 1) (x 2) (x 3) (x 4) (x 5) (x 6) (x 7) (x 8) (x 9) (x 10) (x 11) (x 12) (x 13) (x 14) (x 15) (x 16) (x 17) From 4bee2a930d94250c444f32bd7f055ca7d54f255a Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 11:02:11 -0700 Subject: [PATCH 48/59] Enable finite-sum notation for checkerboard n6 bridge --- Checkerboard/N6Base.lean | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Checkerboard/N6Base.lean b/Checkerboard/N6Base.lean index 4d3b8a50..bcc59984 100644 --- a/Checkerboard/N6Base.lean +++ b/Checkerboard/N6Base.lean @@ -17,6 +17,8 @@ preparation. All formal claims are checked by the repository-pinned Lean compile namespace Checkerboard +open scoped BigOperators + set_option maxHeartbeats 0 set_option maxRecDepth 1000000 From 09ec4378778afaa244a8b8d01e6a47c2989b2f34 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 11:06:24 -0700 Subject: [PATCH 49/59] Use explicit Finset sums in checkerboard n6 bridge --- Checkerboard/N6Base.lean | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Checkerboard/N6Base.lean b/Checkerboard/N6Base.lean index bcc59984..38074303 100644 --- a/Checkerboard/N6Base.lean +++ b/Checkerboard/N6Base.lean @@ -17,8 +17,6 @@ preparation. All formal claims are checked by the repository-pinned Lean compile namespace Checkerboard -open scoped BigOperators - set_option maxHeartbeats 0 set_option maxRecDepth 1000000 @@ -76,7 +74,8 @@ private def chosenOnLine (point : Fin 18 → Point 6) Finset.univ.filter fun i => point i ∈ s ∧ OnLine line (point i) private theorem card_filter_bool {α : Type*} (s : Finset α) (x : α → Bool) : - (s.filter fun i => x i = true).card = ∑ i in s, bitNat (x i) := by + (s.filter fun i => x i = true).card = + Finset.sum s (fun i => bitNat (x i)) := by classical induction s using Finset.induction_on with | empty => simp @@ -86,7 +85,7 @@ private theorem card_filter_bool {α : Type*} (s : Finset α) (x : α → Bool) private theorem card_filter_bool_and {α : Type*} (s : Finset α) (x : α → Bool) (p : α → Prop) [DecidablePred p] : (s.filter fun i => x i = true ∧ p i).card = - ∑ i in s.filter p, bitNat (x i) := by + Finset.sum (s.filter p) (fun i => bitNat (x i)) := by classical have hfilter : s.filter (fun i => x i = true ∧ p i) = From 3752ef840b20195d79305978e64318cb686068df Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 11:17:21 -0700 Subject: [PATCH 50/59] Add explicit fast checkerboard n6 bridge --- Checkerboard/N6Explicit.lean | 322 +++++++++++++++++++++++++++++++++++ 1 file changed, 322 insertions(+) create mode 100644 Checkerboard/N6Explicit.lean diff --git a/Checkerboard/N6Explicit.lean b/Checkerboard/N6Explicit.lean new file mode 100644 index 00000000..66df00c5 --- /dev/null +++ b/Checkerboard/N6Explicit.lean @@ -0,0 +1,322 @@ +import Checkerboard.FourCertificate +import Checkerboard.N6SATTest + +/-! +# Explicit 6×6 checkerboard base cases + +The quadratic relaxation is not integral on the 6-board. This module transports +an arbitrary monochromatic no-three-in-line set to eighteen Boolean indicators, +uses closed certificates for the relevant row, column, and diagonal fibers, and +then applies the compact Presburger certificates in `N6SATTest`. + +Proof developed by Dominic Dabish. ProofOrchestrator, using OpenAI GPT-5.6 Thinking, +assisted with the mathematical argument, Lean formalization, and submission +preparation. All formal claims are checked by the repository-pinned Lean compiler. +-/ + +namespace Checkerboard + +set_option maxHeartbeats 0 +set_option maxRecDepth 1000000 + +private def n6p0Point : Fin 18 → Point 6 := ![ + ((0 : Fin 6), (0 : Fin 6)), ((0 : Fin 6), (2 : Fin 6)), + ((0 : Fin 6), (4 : Fin 6)), ((1 : Fin 6), (1 : Fin 6)), + ((1 : Fin 6), (3 : Fin 6)), ((1 : Fin 6), (5 : Fin 6)), + ((2 : Fin 6), (0 : Fin 6)), ((2 : Fin 6), (2 : Fin 6)), + ((2 : Fin 6), (4 : Fin 6)), ((3 : Fin 6), (1 : Fin 6)), + ((3 : Fin 6), (3 : Fin 6)), ((3 : Fin 6), (5 : Fin 6)), + ((4 : Fin 6), (0 : Fin 6)), ((4 : Fin 6), (2 : Fin 6)), + ((4 : Fin 6), (4 : Fin 6)), ((5 : Fin 6), (1 : Fin 6)), + ((5 : Fin 6), (3 : Fin 6)), ((5 : Fin 6), (5 : Fin 6))] + +private def n6p1Point : Fin 18 → Point 6 := ![ + ((0 : Fin 6), (1 : Fin 6)), ((0 : Fin 6), (3 : Fin 6)), + ((0 : Fin 6), (5 : Fin 6)), ((1 : Fin 6), (0 : Fin 6)), + ((1 : Fin 6), (2 : Fin 6)), ((1 : Fin 6), (4 : Fin 6)), + ((2 : Fin 6), (1 : Fin 6)), ((2 : Fin 6), (3 : Fin 6)), + ((2 : Fin 6), (5 : Fin 6)), ((3 : Fin 6), (0 : Fin 6)), + ((3 : Fin 6), (2 : Fin 6)), ((3 : Fin 6), (4 : Fin 6)), + ((4 : Fin 6), (1 : Fin 6)), ((4 : Fin 6), (3 : Fin 6)), + ((4 : Fin 6), (5 : Fin 6)), ((5 : Fin 6), (0 : Fin 6)), + ((5 : Fin 6), (2 : Fin 6)), ((5 : Fin 6), (4 : Fin 6))] + +private theorem n6p0_injective : Function.Injective n6p0Point := by decide +private theorem n6p1_injective : Function.Injective n6p1Point := by decide + +private theorem n6p0_surjective : + ∀ p : Point 6, InColor 0 p → ∃ i, n6p0Point i = p := by + letI : DecidablePred (fun p : Point 6 => + InColor 0 p → ∃ i, n6p0Point i = p) := by + intro p + unfold InColor + infer_instance + exact of_decide_eq_true rfl + +private theorem n6p1_surjective : + ∀ p : Point 6, InColor 1 p → ∃ i, n6p1Point i = p := by + letI : DecidablePred (fun p : Point 6 => + InColor 1 p → ∃ i, n6p1Point i = p) := by + intro p + unfold InColor + infer_instance + exact of_decide_eq_true rfl + +private def chosenIndices (point : Fin 18 → Point 6) + (s : Finset (Point 6)) : Finset (Fin 18) := + Finset.univ.filter fun i => point i ∈ s + +private def chosenOnLine (point : Fin 18 → Point 6) + (s : Finset (Point 6)) (line : PrincipalLine 6) : Finset (Fin 18) := + Finset.univ.filter fun i => point i ∈ s ∧ OnLine line (point i) + +private theorem card_filter_bool {α : Type*} (s : Finset α) (x : α → Bool) : + (s.filter fun i => x i = true).card = + Finset.sum s (fun i => bitNat (x i)) := by + classical + induction s using Finset.induction_on with + | empty => simp + | @insert a s ha ih => + cases hxa : x a <;> simp [ha, ih, hxa, bitNat] + +private theorem card_filter_bool_and {α : Type*} (s : Finset α) + (x : α → Bool) (p : α → Prop) [DecidablePred p] : + (s.filter fun i => x i = true ∧ p i).card = + Finset.sum (s.filter p) (fun i => bitNat (x i)) := by + classical + have hfilter : + s.filter (fun i => x i = true ∧ p i) = + (s.filter p).filter (fun i => x i = true) := by + ext i + simp [and_comm] + rw [hfilter] + exact card_filter_bool (s.filter p) x + +private theorem chosenIndices_image + {parity : ℕ} (point : Fin 18 → Point 6) + (hsurj : ∀ p : Point 6, InColor parity p → ∃ i, point i = p) + (s : Finset (Point 6)) (hcolor : Monochromatic parity s) : + (chosenIndices point s).image point = s := by + ext p + constructor + · intro hp + rcases Finset.mem_image.mp hp with ⟨i, hi, rfl⟩ + exact (Finset.mem_filter.mp hi).2 + · intro hp + obtain ⟨i, hi⟩ := hsurj p (hcolor ⟨p, hp⟩) + subst p + apply Finset.mem_image.mpr + exact ⟨i, Finset.mem_filter.mpr ⟨Finset.mem_univ _, hp⟩, rfl⟩ + +private theorem chosenOnLine_image + {parity : ℕ} (point : Fin 18 → Point 6) + (hsurj : ∀ p : Point 6, InColor parity p → ∃ i, point i = p) + (s : Finset (Point 6)) (hcolor : Monochromatic parity s) + (line : PrincipalLine 6) : + (chosenOnLine point s line).image point = s.filter (OnLine line) := by + ext p + constructor + · intro hp + rcases Finset.mem_image.mp hp with ⟨i, hi, rfl⟩ + exact Finset.mem_filter.mpr (Finset.mem_filter.mp hi).2 + · intro hp + have hpS := (Finset.mem_filter.mp hp).1 + have hpL := (Finset.mem_filter.mp hp).2 + obtain ⟨i, hi⟩ := hsurj p (hcolor ⟨p, hpS⟩) + subst p + apply Finset.mem_image.mpr + exact ⟨i, Finset.mem_filter.mpr + ⟨Finset.mem_univ _, ⟨hpS, hpL⟩⟩, rfl⟩ + +private theorem upper_of_boolean_certificate + {parity : ℕ} (point : Fin 18 → Point 6) + (hinj : Function.Injective point) + (hsurj : ∀ p : Point 6, InColor parity p → ∃ i, point i = p) + (hfinite : ∀ x : Fin 18 → Bool, + (∀ line : PrincipalLine 6, + (Finset.univ.filter fun i => x i = true ∧ OnLine line (point i)).card ≤ 2) → + (Finset.univ.filter fun i => x i = true).card ≤ 8) + (s : Finset (Point 6)) + (hcolor : Monochromatic parity s) (hntil : NoThreeInLine s) : + s.card ≤ 8 := by + let x : Fin 18 → Bool := fun i => decide (point i ∈ s) + have hline : ∀ line : PrincipalLine 6, + (Finset.univ.filter fun i => x i = true ∧ OnLine line (point i)).card ≤ 2 := by + intro line + have himage := chosenOnLine_image point hsurj s hcolor line + have hcardImage := Finset.card_image_of_injective + (chosenOnLine point s line) hinj + have hchosen : + (chosenOnLine point s line).card = (s.filter (OnLine line)).card := by + calc + (chosenOnLine point s line).card = + ((chosenOnLine point s line).image point).card := hcardImage.symm + _ = (s.filter (OnLine line)).card := congrArg Finset.card himage + have heq : + (Finset.univ.filter fun i => x i = true ∧ OnLine line (point i)).card = + (s.filter (OnLine line)).card := by + simpa [x, chosenOnLine] using hchosen + rw [heq] + exact principalLine_card_le_two hntil line + have hbool := hfinite x hline + have himage := chosenIndices_image point hsurj s hcolor + have hcardImage := Finset.card_image_of_injective (chosenIndices point s) hinj + have hchosen : (chosenIndices point s).card = s.card := by + calc + (chosenIndices point s).card = ((chosenIndices point s).image point).card := + hcardImage.symm + _ = s.card := congrArg Finset.card himage + have heq : (Finset.univ.filter fun i => x i = true).card = s.card := by + simpa [x, chosenIndices] using hchosen + rwa [heq] at hbool + +private def p0Line : Fin 19 → PrincipalLine 6 := ![ + (.row, ⟨0, by decide⟩), (.row, ⟨1, by decide⟩), + (.row, ⟨2, by decide⟩), (.row, ⟨3, by decide⟩), + (.row, ⟨4, by decide⟩), (.row, ⟨5, by decide⟩), + (.column, ⟨0, by decide⟩), (.column, ⟨2, by decide⟩), + (.column, ⟨4, by decide⟩), (.column, ⟨1, by decide⟩), + (.column, ⟨3, by decide⟩), (.column, ⟨5, by decide⟩), + (.sum, ⟨2, by decide⟩), (.sum, ⟨4, by decide⟩), + (.sum, ⟨6, by decide⟩), (.sum, ⟨8, by decide⟩), + (.difference, ⟨5, by decide⟩), (.difference, ⟨3, by decide⟩), + (.difference, ⟨7, by decide⟩)] + +private def p0Index : Fin 19 → Finset (Fin 18) := ![ + {0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}, + {12, 13, 14}, {15, 16, 17}, {0, 6, 12}, {1, 7, 13}, + {2, 8, 14}, {3, 9, 15}, {4, 10, 16}, {5, 11, 17}, + {1, 3, 6}, {2, 4, 7, 9, 12}, {5, 8, 10, 13, 15}, + {11, 14, 16}, {0, 3, 7, 10, 14, 17}, {1, 4, 8, 11}, + {6, 9, 13, 16}] + +private def p1Line : Fin 19 → PrincipalLine 6 := ![ + (.row, ⟨0, by decide⟩), (.row, ⟨1, by decide⟩), + (.row, ⟨2, by decide⟩), (.row, ⟨3, by decide⟩), + (.row, ⟨4, by decide⟩), (.row, ⟨5, by decide⟩), + (.column, ⟨1, by decide⟩), (.column, ⟨3, by decide⟩), + (.column, ⟨5, by decide⟩), (.column, ⟨0, by decide⟩), + (.column, ⟨2, by decide⟩), (.column, ⟨4, by decide⟩), + (.sum, ⟨3, by decide⟩), (.sum, ⟨5, by decide⟩), + (.sum, ⟨7, by decide⟩), (.difference, ⟨4, by decide⟩), + (.difference, ⟨2, by decide⟩), (.difference, ⟨6, by decide⟩), + (.difference, ⟨8, by decide⟩)] + +private def p1Index : Fin 19 → Finset (Fin 18) := ![ + {0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}, + {12, 13, 14}, {15, 16, 17}, {0, 6, 12}, {1, 7, 13}, + {2, 8, 14}, {3, 9, 15}, {4, 10, 16}, {5, 11, 17}, + {1, 4, 6, 9}, {2, 5, 7, 10, 12, 15}, {8, 11, 13, 16}, + {0, 4, 7, 11, 14}, {1, 5, 8}, {3, 6, 10, 13, 17}, + {9, 12, 16}] + +private theorem p0_line_indices (j : Fin 19) : + Finset.univ.filter (fun i => OnLine (p0Line j) (n6p0Point i)) = p0Index j := by + fin_cases j <;> decide + +private theorem p1_line_indices (j : Fin 19) : + Finset.univ.filter (fun i => OnLine (p1Line j) (n6p1Point i)) = p1Index j := by + fin_cases j <;> decide + +private theorem line_sum_le_two + (point : Fin 18 → Point 6) (x : Fin 18 → Bool) + (line : PrincipalLine 6) (idx : Finset (Fin 18)) + (hidx : Finset.univ.filter (fun i => OnLine line (point i)) = idx) + (hline : (Finset.univ.filter fun i => + x i = true ∧ OnLine line (point i)).card ≤ 2) : + Finset.sum idx (fun i => bitNat (x i)) ≤ 2 := by + rw [card_filter_bool_and, hidx] at hline + exact hline + +private def all18 : Finset (Fin 18) := + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17} + +private theorem all18_eq_univ : all18 = Finset.univ := by decide + +private theorem n6p0_boolean_bound : + ∀ x : Fin 18 → Bool, + (∀ line : PrincipalLine 6, + (Finset.univ.filter fun i => + x i = true ∧ OnLine line (n6p0Point i)).card ≤ 2) → + (Finset.univ.filter fun i => x i = true).card ≤ 8 := by + intro x hline + have hb (j : Fin 19) : Finset.sum (p0Index j) (fun i => bitNat (x i)) ≤ 2 := + line_sum_le_two n6p0Point x (p0Line j) (p0Index j) + (p0_line_indices j) (hline (p0Line j)) + have h0 : bitNat (x 0) + bitNat (x 1) + bitNat (x 2) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 0 + have h1 : bitNat (x 3) + bitNat (x 4) + bitNat (x 5) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 1 + have h2 : bitNat (x 6) + bitNat (x 7) + bitNat (x 8) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 2 + have h3 : bitNat (x 9) + bitNat (x 10) + bitNat (x 11) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 3 + have h4 : bitNat (x 12) + bitNat (x 13) + bitNat (x 14) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 4 + have h5 : bitNat (x 15) + bitNat (x 16) + bitNat (x 17) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 5 + have h6 : bitNat (x 0) + bitNat (x 6) + bitNat (x 12) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 6 + have h7 : bitNat (x 1) + bitNat (x 7) + bitNat (x 13) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 7 + have h8 : bitNat (x 2) + bitNat (x 8) + bitNat (x 14) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 8 + have h9 : bitNat (x 3) + bitNat (x 9) + bitNat (x 15) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 9 + have h10 : bitNat (x 4) + bitNat (x 10) + bitNat (x 16) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 10 + have h11 : bitNat (x 5) + bitNat (x 11) + bitNat (x 17) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 11 + have h12 : bitNat (x 1) + bitNat (x 3) + bitNat (x 6) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 12 + have h13 : bitNat (x 2) + bitNat (x 4) + bitNat (x 7) + bitNat (x 9) + bitNat (x 12) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 13 + have h14 : bitNat (x 5) + bitNat (x 8) + bitNat (x 10) + bitNat (x 13) + bitNat (x 15) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 14 + have h15 : bitNat (x 11) + bitNat (x 14) + bitNat (x 16) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 15 + have h16 : bitNat (x 0) + bitNat (x 3) + bitNat (x 7) + bitNat (x 10) + bitNat (x 14) + bitNat (x 17) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 16 + have h17 : bitNat (x 1) + bitNat (x 4) + bitNat (x 8) + bitNat (x 11) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 17 + have h18 : bitNat (x 6) + bitNat (x 9) + bitNat (x 13) + bitNat (x 16) ≤ 2 := by simpa [p0Index, Nat.add_assoc] using hb 18 + rw [card_filter_bool] + rw [← all18_eq_univ] + simpa [all18, Nat.add_assoc] using + n6p0_sat (x 0) (x 1) (x 2) (x 3) (x 4) (x 5) + (x 6) (x 7) (x 8) (x 9) (x 10) (x 11) + (x 12) (x 13) (x 14) (x 15) (x 16) (x 17) + h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 + +private theorem n6p1_boolean_bound : + ∀ x : Fin 18 → Bool, + (∀ line : PrincipalLine 6, + (Finset.univ.filter fun i => + x i = true ∧ OnLine line (n6p1Point i)).card ≤ 2) → + (Finset.univ.filter fun i => x i = true).card ≤ 8 := by + intro x hline + have hb (j : Fin 19) : Finset.sum (p1Index j) (fun i => bitNat (x i)) ≤ 2 := + line_sum_le_two n6p1Point x (p1Line j) (p1Index j) + (p1_line_indices j) (hline (p1Line j)) + have h0 : bitNat (x 0) + bitNat (x 1) + bitNat (x 2) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 0 + have h1 : bitNat (x 3) + bitNat (x 4) + bitNat (x 5) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 1 + have h2 : bitNat (x 6) + bitNat (x 7) + bitNat (x 8) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 2 + have h3 : bitNat (x 9) + bitNat (x 10) + bitNat (x 11) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 3 + have h4 : bitNat (x 12) + bitNat (x 13) + bitNat (x 14) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 4 + have h5 : bitNat (x 15) + bitNat (x 16) + bitNat (x 17) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 5 + have h6 : bitNat (x 0) + bitNat (x 6) + bitNat (x 12) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 6 + have h7 : bitNat (x 1) + bitNat (x 7) + bitNat (x 13) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 7 + have h8 : bitNat (x 2) + bitNat (x 8) + bitNat (x 14) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 8 + have h9 : bitNat (x 3) + bitNat (x 9) + bitNat (x 15) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 9 + have h10 : bitNat (x 4) + bitNat (x 10) + bitNat (x 16) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 10 + have h11 : bitNat (x 5) + bitNat (x 11) + bitNat (x 17) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 11 + have h12 : bitNat (x 1) + bitNat (x 4) + bitNat (x 6) + bitNat (x 9) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 12 + have h13 : bitNat (x 2) + bitNat (x 5) + bitNat (x 7) + bitNat (x 10) + bitNat (x 12) + bitNat (x 15) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 13 + have h14 : bitNat (x 8) + bitNat (x 11) + bitNat (x 13) + bitNat (x 16) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 14 + have h15 : bitNat (x 0) + bitNat (x 4) + bitNat (x 7) + bitNat (x 11) + bitNat (x 14) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 15 + have h16 : bitNat (x 1) + bitNat (x 5) + bitNat (x 8) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 16 + have h17 : bitNat (x 3) + bitNat (x 6) + bitNat (x 10) + bitNat (x 13) + bitNat (x 17) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 17 + have h18 : bitNat (x 9) + bitNat (x 12) + bitNat (x 16) ≤ 2 := by simpa [p1Index, Nat.add_assoc] using hb 18 + rw [card_filter_bool] + rw [← all18_eq_univ] + simpa [all18, Nat.add_assoc] using + n6p1_sat (x 0) (x 1) (x 2) (x 3) (x 4) (x 5) + (x 6) (x 7) (x 8) (x 9) (x 10) (x 11) + (x 12) (x 13) (x 14) (x 15) (x 16) (x 17) + h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16 h17 h18 + +/-- `D_mono(6,0) ≤ 8`. -/ +theorem n6_zero_upper (s : Finset (Point 6)) + (hcolor : Monochromatic 0 s) (hntil : NoThreeInLine s) : s.card ≤ 8 := by + exact upper_of_boolean_certificate n6p0Point n6p0_injective n6p0_surjective + n6p0_boolean_bound s hcolor hntil + +/-- `D_mono(6,1) ≤ 8`. -/ +theorem n6_one_upper (s : Finset (Point 6)) + (hcolor : Monochromatic 1 s) (hntil : NoThreeInLine s) : s.card ≤ 8 := by + exact upper_of_boolean_certificate n6p1Point n6p1_injective n6p1_surjective + n6p1_boolean_bound s hcolor hntil + +end Checkerboard From 865f796eb97fa53fc17820be2478d4268b7b5363 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 11:17:30 -0700 Subject: [PATCH 51/59] Use explicit checkerboard n6 proof module --- Checkerboard/AllNTheorem.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Checkerboard/AllNTheorem.lean b/Checkerboard/AllNTheorem.lean index 18137882..ed951fac 100644 --- a/Checkerboard/AllNTheorem.lean +++ b/Checkerboard/AllNTheorem.lean @@ -1,5 +1,5 @@ import Checkerboard.AllNUpper -import Checkerboard.N6Base +import Checkerboard.N6Explicit /-! # Complete all-n checkerboard upper bound From 913adfd724cbedd5c47b52a2c538a94a7c7cf785 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 11:21:23 -0700 Subject: [PATCH 52/59] Normalize checkerboard filter conjunctions --- Checkerboard/N6Explicit.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Checkerboard/N6Explicit.lean b/Checkerboard/N6Explicit.lean index 66df00c5..0bcf2101 100644 --- a/Checkerboard/N6Explicit.lean +++ b/Checkerboard/N6Explicit.lean @@ -88,7 +88,7 @@ private theorem card_filter_bool_and {α : Type*} (s : Finset α) s.filter (fun i => x i = true ∧ p i) = (s.filter p).filter (fun i => x i = true) := by ext i - simp [and_comm] + simp [and_comm, and_left_comm, and_assoc] rw [hfilter] exact card_filter_bool (s.filter p) x From 22a5407d93ddda02d2b5678e8c31e7702eac2f35 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 11:25:40 -0700 Subject: [PATCH 53/59] Align even checkerboard cast normal form --- Checkerboard/QuadraticWeights.lean | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Checkerboard/QuadraticWeights.lean b/Checkerboard/QuadraticWeights.lean index ddafa1bd..ebe25e1e 100644 --- a/Checkerboard/QuadraticWeights.lean +++ b/Checkerboard/QuadraticWeights.lean @@ -136,11 +136,10 @@ theorem evenQuadratic_coverage (m parity : ℕ) (hp : parity = 0 ∨ parity = 1) rcases hp with rfl | rfl <;> simp [differenceIndex, InColor] at hcolor ⊢ <;> omega have hy : p.2.1 ≤ 2 * m - 1 := by omega - have hmtwo : 1 ≤ m * 2 := by omega - have hcast : (((m * 2 - 1 : ℕ) : ℚ)) = 2 * (m : ℚ) - 1 := by - rw [Nat.cast_sub hmtwo] + have htwo : 1 ≤ 2 * m := by omega + have hcast : (((2 * m - 1 : ℕ) : ℚ)) = 2 * (m : ℚ) - 1 := by + rw [Nat.cast_sub htwo] norm_num - ring unfold fourCoverage evenQuadraticWeights dsimp rw [if_pos hsum, if_pos hdiff] From 3a792adcefe4f44a2827d181701834a9bc8e9202 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 11:30:29 -0700 Subject: [PATCH 54/59] Repair exact checkerboard objective sums --- Checkerboard/QuadraticCosts.lean | 45 +++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/Checkerboard/QuadraticCosts.lean b/Checkerboard/QuadraticCosts.lean index f3f31668..3b9a05a6 100644 --- a/Checkerboard/QuadraticCosts.lean +++ b/Checkerboard/QuadraticCosts.lean @@ -20,16 +20,29 @@ private theorem odd_axis_sum (m : ℕ) : (∑ i : Fin (2 * m + 1), (2 * (i.1 : ℚ) - 2 * m) ^ 2) = 4 * (m : ℚ) * ((m : ℚ) + 1) * (2 * (m : ℚ) + 1) / 3 := by have h := axis_quadratic_sum (2 * m + 1) - push_cast at h ⊢ - convert h using 1 <;> ring + push_cast at h + calc + (∑ i : Fin (2 * m + 1), (2 * (i.1 : ℚ) - 2 * m) ^ 2) = + ∑ i : Fin (2 * m + 1), + (2 * (i.1 : ℚ) - (2 * (m : ℚ) + 1 - 1)) ^ 2 := by + apply Finset.sum_congr rfl + intro i _ + ring + _ = (2 * (m : ℚ) + 1) * ((2 * (m : ℚ) + 1) ^ 2 - 1) / 3 := h + _ = 4 * (m : ℚ) * ((m : ℚ) + 1) * (2 * (m : ℚ) + 1) / 3 := by ring private theorem even_axis_sum (m : ℕ) : (∑ i : Fin (2 * m), (2 * (i.1 : ℚ) - ((2 * m : ℚ) - 1)) ^ 2) = 2 * (m : ℚ) * (4 * (m : ℚ) ^ 2 - 1) / 3 := by have h := axis_quadratic_sum (2 * m) - push_cast at h ⊢ - convert h using 1 <;> ring + push_cast at h + calc + (∑ i : Fin (2 * m), + (2 * (i.1 : ℚ) - ((2 * m : ℚ) - 1)) ^ 2) = + (2 * (m : ℚ)) * ((2 * (m : ℚ)) ^ 2 - 1) / 3 := by + simpa using h + _ = 2 * (m : ℚ) * (4 * (m : ℚ) ^ 2 - 1) / 3 := by ring private theorem odd_even_diag_sum (m : ℕ) : (∑ j : Fin (2 * (2 * m + 1) - 1), @@ -64,8 +77,20 @@ private theorem even_all_diag_sum (m : ℕ) (hm : 1 ≤ m) : have hdim : 2 * (2 * m) - 1 = 2 * (2 * m - 1) + 1 := by omega rw [hdim] have h := fin_quadratic_cap_sum (2 * m - 1) - push_cast at h ⊢ - simpa [evenCapExpr] using h + have htwo : 1 ≤ 2 * m := by omega + have hcast : (((2 * m - 1 : ℕ) : ℚ)) = 2 * (m : ℚ) - 1 := by + rw [Nat.cast_sub htwo] + norm_num + rw [hcast] at h + change (∑ j : Fin (2 * (2 * m - 1) + 1), + 2 * ((2 * (m : ℚ) - 1) ^ 2 - + ((j.1 : ℚ) - (2 * (m : ℚ) - 1)) ^ 2)) = _ + calc + _ = 2 * (2 * (m : ℚ) - 1) * + (2 * (2 * (m : ℚ) - 1) - 1) * + (2 * (2 * (m : ℚ) - 1) + 1) / 3 := h + _ = 2 * ((2 * m : ℚ) - 1) * (4 * (m : ℚ) - 3) * + (4 * (m : ℚ) - 1) / 3 := by ring /-- Exact objective for the fat color of an odd board. -/ theorem oddQuadratic_cost_zero (m : ℕ) : @@ -78,7 +103,7 @@ theorem oddQuadratic_cost_zero (m : ℕ) : if j.1 % 2 = 0 then oddCapExpr m j else 0) + (∑ j : Fin (2 * (2 * m + 1) - 1), if j.1 % 2 = 0 then oddCapExpr m j else 0)) = _ - rw [odd_axis_sum, odd_axis_sum, odd_even_diag_sum, odd_even_diag_sum] + rw [odd_axis_sum, odd_even_diag_sum] ring /-- Exact objective for the thin color of an odd board. -/ @@ -92,7 +117,7 @@ theorem oddQuadratic_cost_one (m : ℕ) : if j.1 % 2 = 1 then oddCapExpr m j else 0) + (∑ j : Fin (2 * (2 * m + 1) - 1), if j.1 % 2 = 1 then oddCapExpr m j else 0)) = _ - rw [odd_axis_sum, odd_axis_sum, odd_odd_diag_sum, odd_odd_diag_sum] + rw [odd_axis_sum, odd_odd_diag_sum] ring /-- Both checkerboard colors have the same objective on an even board. -/ @@ -109,7 +134,7 @@ theorem evenQuadratic_cost_zero (m : ℕ) (hm : 1 ≤ m) : if j.1 % 2 = 0 then evenCapExpr m j else 0) + (∑ j : Fin (2 * (2 * m) - 1), if j.1 % 2 = 1 then evenCapExpr m j else 0)) = _ - rw [even_axis_sum, even_axis_sum, + rw [even_axis_sum, parity_partition (fun j : Fin (2 * (2 * m) - 1) => evenCapExpr m j), even_all_diag_sum m hm] ring @@ -128,7 +153,7 @@ theorem evenQuadratic_cost_one (m : ℕ) (hm : 1 ≤ m) : if j.1 % 2 = 1 then evenCapExpr m j else 0) + (∑ j : Fin (2 * (2 * m) - 1), if j.1 % 2 = 0 then evenCapExpr m j else 0)) = _ - rw [even_axis_sum, even_axis_sum] + rw [even_axis_sum] have hpartition := parity_partition (fun j : Fin (2 * (2 * m) - 1) => evenCapExpr m j) rw [add_comm] at hpartition From 0e97a0be7258fb10afa8be0fb0d23edc5d768e14 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 11:34:21 -0700 Subject: [PATCH 55/59] Regroup even checkerboard objective sums --- Checkerboard/QuadraticCosts.lean | 43 +++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/Checkerboard/QuadraticCosts.lean b/Checkerboard/QuadraticCosts.lean index 3b9a05a6..a9f3a0e5 100644 --- a/Checkerboard/QuadraticCosts.lean +++ b/Checkerboard/QuadraticCosts.lean @@ -134,10 +134,26 @@ theorem evenQuadratic_cost_zero (m : ℕ) (hm : 1 ≤ m) : if j.1 % 2 = 0 then evenCapExpr m j else 0) + (∑ j : Fin (2 * (2 * m) - 1), if j.1 % 2 = 1 then evenCapExpr m j else 0)) = _ - rw [even_axis_sum, - parity_partition (fun j : Fin (2 * (2 * m) - 1) => evenCapExpr m j), - even_all_diag_sum m hm] - ring + rw [even_axis_sum] + have hpartition := + parity_partition (fun j : Fin (2 * (2 * m) - 1) => evenCapExpr m j) + calc + 2 * ((2 * (m : ℚ) * (4 * (m : ℚ) ^ 2 - 1) / 3 + + 2 * (m : ℚ) * (4 * (m : ℚ) ^ 2 - 1) / 3 + + (∑ j : Fin (2 * (2 * m) - 1), + if j.1 % 2 = 0 then evenCapExpr m j else 0)) + + (∑ j : Fin (2 * (2 * m) - 1), + if j.1 % 2 = 1 then evenCapExpr m j else 0)) = + 2 * (2 * (m : ℚ) * (4 * (m : ℚ) ^ 2 - 1) / 3 + + 2 * (m : ℚ) * (4 * (m : ℚ) ^ 2 - 1) / 3 + + ((∑ j : Fin (2 * (2 * m) - 1), + if j.1 % 2 = 0 then evenCapExpr m j else 0) + + (∑ j : Fin (2 * (2 * m) - 1), + if j.1 % 2 = 1 then evenCapExpr m j else 0))) := by ring + _ = 2 * (2 * (m : ℚ) * (4 * (m : ℚ) ^ 2 - 1) / 3 + + 2 * (m : ℚ) * (4 * (m : ℚ) ^ 2 - 1) / 3 + + (∑ j : Fin (2 * (2 * m) - 1), evenCapExpr m j)) := by rw [hpartition] + _ = _ := by rw [even_all_diag_sum m hm]; ring /-- Same objective for the other color of an even board. -/ theorem evenQuadratic_cost_one (m : ℕ) (hm : 1 ≤ m) : @@ -157,7 +173,22 @@ theorem evenQuadratic_cost_one (m : ℕ) (hm : 1 ≤ m) : have hpartition := parity_partition (fun j : Fin (2 * (2 * m) - 1) => evenCapExpr m j) rw [add_comm] at hpartition - rw [hpartition, even_all_diag_sum m hm] - ring + calc + 2 * ((2 * (m : ℚ) * (4 * (m : ℚ) ^ 2 - 1) / 3 + + 2 * (m : ℚ) * (4 * (m : ℚ) ^ 2 - 1) / 3 + + (∑ j : Fin (2 * (2 * m) - 1), + if j.1 % 2 = 1 then evenCapExpr m j else 0)) + + (∑ j : Fin (2 * (2 * m) - 1), + if j.1 % 2 = 0 then evenCapExpr m j else 0)) = + 2 * (2 * (m : ℚ) * (4 * (m : ℚ) ^ 2 - 1) / 3 + + 2 * (m : ℚ) * (4 * (m : ℚ) ^ 2 - 1) / 3 + + ((∑ j : Fin (2 * (2 * m) - 1), + if j.1 % 2 = 1 then evenCapExpr m j else 0) + + (∑ j : Fin (2 * (2 * m) - 1), + if j.1 % 2 = 0 then evenCapExpr m j else 0))) := by ring + _ = 2 * (2 * (m : ℚ) * (4 * (m : ℚ) ^ 2 - 1) / 3 + + 2 * (m : ℚ) * (4 * (m : ℚ) ^ 2 - 1) / 3 + + (∑ j : Fin (2 * (2 * m) - 1), evenCapExpr m j)) := by rw [hpartition] + _ = _ := by rw [even_all_diag_sum m hm]; ring end Checkerboard From e469ca9ba216b0cd75c0acc02ff0181423536c69 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 11:38:46 -0700 Subject: [PATCH 56/59] Make final checkerboard bounds explicit --- Checkerboard/AllNUpper.lean | 62 ++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/Checkerboard/AllNUpper.lean b/Checkerboard/AllNUpper.lean index 0c0b7e15..c66b6d02 100644 --- a/Checkerboard/AllNUpper.lean +++ b/Checkerboard/AllNUpper.lean @@ -24,8 +24,11 @@ theorem odd_zero_upper {m : ℕ} (hm : 3 ≤ m) have hmpos : (0 : ℚ) < m := by nlinarith have hpoly : 0 < 2 * (m : ℚ) ^ 2 - 6 * m + 1 := by nlinarith have hprod := mul_pos hmpos hpoly - push_cast - norm_num [show 4 * m - 2 + 1 = 4 * m - 1 by omega] + have hk : 2 ≤ 4 * m := by omega + have hcast : (((4 * m - 2 : ℕ) : ℚ)) = 4 * (m : ℚ) - 2 := by + rw [Nat.cast_sub hk] + norm_num + rw [hcast] nlinarith · exact hr · exact hc @@ -49,8 +52,11 @@ theorem odd_one_upper {m : ℕ} (hm : 4 ≤ m) have hmpos : (0 : ℚ) < m := by nlinarith have hpoly : 0 < 2 * (m : ℚ) ^ 2 - 6 * m - 2 := by nlinarith have hprod := mul_pos hmpos hpoly - push_cast - norm_num [show 4 * m - 2 + 1 = 4 * m - 1 by omega] + have hk : 2 ≤ 4 * m := by omega + have hcast : (((4 * m - 2 : ℕ) : ℚ)) = 4 * (m : ℚ) - 2 := by + rw [Nat.cast_sub hk] + norm_num + rw [hcast] nlinarith · exact hr · exact hc @@ -67,27 +73,23 @@ theorem even_upper {m parity : ℕ} (hm : 4 ≤ m) (hcolor : Monochromatic parity s) (hntil : NoThreeInLine s) : s.card ≤ 4 * m - 4 := by have hm1 : 1 ≤ m := by omega + have hmQ : (4 : ℚ) ≤ m := by exact_mod_cast hm + have hcenter : (0 : ℚ) < 2 * m - 1 := by nlinarith + have hpoly : 0 < 2 * (m : ℚ) ^ 2 - 8 * m + 3 := by nlinarith + have hprod := mul_pos hcenter hpoly + have hk : 4 ≤ 4 * m := by omega + have hcast : (((4 * m - 4 : ℕ) : ℚ)) = 4 * (m : ℚ) - 4 := by + rw [Nat.cast_sub hk] + norm_num have hpCost := hp obtain ⟨hr, hc, hs, hd⟩ := evenQuadratic_nonnegative m parity hm1 apply card_le_of_fourCertificate (evenQuadraticWeights m parity) (q := 4 * ((2 * m : ℚ) - 1) ^ 2) (k := 4 * m - 4) · positivity · rcases hpCost with rfl | rfl - · rw [evenQuadratic_cost_zero m hm1] - have hmQ : (4 : ℚ) ≤ m := by exact_mod_cast hm - have hcenter : (0 : ℚ) < 2 * m - 1 := by nlinarith - have hpoly : 0 < 2 * (m : ℚ) ^ 2 - 8 * m + 3 := by nlinarith - have hprod := mul_pos hcenter hpoly - push_cast - norm_num [show 4 * m - 4 + 1 = 4 * m - 3 by omega] + · rw [evenQuadratic_cost_zero m hm1, hcast] nlinarith - · rw [evenQuadratic_cost_one m hm1] - have hmQ : (4 : ℚ) ≤ m := by exact_mod_cast hm - have hcenter : (0 : ℚ) < 2 * m - 1 := by nlinarith - have hpoly : 0 < 2 * (m : ℚ) ^ 2 - 8 * m + 3 := by nlinarith - have hprod := mul_pos hcenter hpoly - push_cast - norm_num [show 4 * m - 4 + 1 = 4 * m - 3 by omega] + · rw [evenQuadratic_cost_one m hm1, hcast] nlinarith · exact hr · exact hc @@ -110,14 +112,32 @@ def n7ThinWeights : FourWeights 7 where if Nat.dist j.1 6 = 1 then 2 else if Nat.dist j.1 6 = 3 then 1 else 0 else 0 -private theorem n7Thin_cost : fourCost n7ThinWeights = 32 := by decide +private theorem n7Thin_cost : fourCost n7ThinWeights = 32 := by + norm_num [fourCost, n7ThinWeights, Fin.sum_univ_succ, Nat.dist] + private theorem n7Thin_nonnegative : (∀ i, 0 ≤ n7ThinWeights.row i) ∧ (∀ i, 0 ≤ n7ThinWeights.column i) ∧ (∀ i, 0 ≤ n7ThinWeights.sum i) ∧ - ∀ i, 0 ≤ n7ThinWeights.difference i := by decide + ∀ i, 0 ≤ n7ThinWeights.difference i := by + constructor + · intro i + fin_cases i <;> norm_num [n7ThinWeights] + constructor + · intro i + fin_cases i <;> norm_num [n7ThinWeights] + constructor + · intro i + fin_cases i <;> norm_num [n7ThinWeights, Nat.dist] + · intro i + fin_cases i <;> norm_num [n7ThinWeights, Nat.dist] + private theorem n7Thin_cover : - ∀ p : Point 7, InColor 1 p → 3 ≤ fourCoverage n7ThinWeights p := by decide + ∀ p : Point 7, InColor 1 p → 3 ≤ fourCoverage n7ThinWeights p := by + rintro ⟨i, j⟩ hp + fin_cases i <;> fin_cases j <;> + norm_num [InColor, fourCoverage, n7ThinWeights, sumIndex, + differenceIndex, Nat.dist] at hp ⊢ /-- Exceptional thin-color bound on the 7-board. -/ theorem n7_one_upper (s : Finset (Point 7)) From b30957c9b86259159e00499851d8fc1816a48e4f Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 11:42:34 -0700 Subject: [PATCH 57/59] Finish explicit seven-board certificate --- Checkerboard/AllNUpper.lean | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Checkerboard/AllNUpper.lean b/Checkerboard/AllNUpper.lean index c66b6d02..9b23883e 100644 --- a/Checkerboard/AllNUpper.lean +++ b/Checkerboard/AllNUpper.lean @@ -114,6 +114,7 @@ def n7ThinWeights : FourWeights 7 where private theorem n7Thin_cost : fourCost n7ThinWeights = 32 := by norm_num [fourCost, n7ThinWeights, Fin.sum_univ_succ, Nat.dist] + decide private theorem n7Thin_nonnegative : (∀ i, 0 ≤ n7ThinWeights.row i) ∧ @@ -135,9 +136,12 @@ private theorem n7Thin_nonnegative : private theorem n7Thin_cover : ∀ p : Point 7, InColor 1 p → 3 ≤ fourCoverage n7ThinWeights p := by rintro ⟨i, j⟩ hp - fin_cases i <;> fin_cases j <;> - norm_num [InColor, fourCoverage, n7ThinWeights, sumIndex, - differenceIndex, Nat.dist] at hp ⊢ + fin_cases i <;> fin_cases j + all_goals + norm_num [InColor] at hp + all_goals + norm_num [fourCoverage, n7ThinWeights, sumIndex, + differenceIndex, Nat.dist] /-- Exceptional thin-color bound on the 7-board. -/ theorem n7_one_upper (s : Finset (Point 7)) From 017258bcda2cd8240c9eeedf62be68fdf87839dc Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 11:46:37 -0700 Subject: [PATCH 58/59] Prove seven-board boundary cardinality explicitly --- Checkerboard/AllNUpper.lean | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Checkerboard/AllNUpper.lean b/Checkerboard/AllNUpper.lean index 9b23883e..712e277a 100644 --- a/Checkerboard/AllNUpper.lean +++ b/Checkerboard/AllNUpper.lean @@ -114,7 +114,11 @@ def n7ThinWeights : FourWeights 7 where private theorem n7Thin_cost : fourCost n7ThinWeights = 32 := by norm_num [fourCost, n7ThinWeights, Fin.sum_univ_succ, Nat.dist] - decide + have hboundary : + ({x : Fin 7 | x = 0 ∨ (x : ℕ) = 6} : Finset (Fin 7)).card = 2 := by + decide + rw [hboundary] + norm_num private theorem n7Thin_nonnegative : (∀ i, 0 ≤ n7ThinWeights.row i) ∧ From 11391b32292ca39da502522a733486b580916439 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Thu, 23 Jul 2026 11:50:26 -0700 Subject: [PATCH 59/59] Fix final checkerboard theorem application --- Checkerboard/AllNTheorem.lean | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Checkerboard/AllNTheorem.lean b/Checkerboard/AllNTheorem.lean index ed951fac..02de75f4 100644 --- a/Checkerboard/AllNTheorem.lean +++ b/Checkerboard/AllNTheorem.lean @@ -19,11 +19,7 @@ theorem checkerboard_upper_all_n {n parity : ℕ} rcases hp with rfl | rfl · exact n6_zero_upper s hcolor hntil · exact n6_one_upper s hcolor hntil - · apply checkerboard_upper_from_seven (n := n) (parity := parity) - · omega - · exact hp - · exact s - · exact hcolor - · exact hntil + · exact checkerboard_upper_from_seven (n := n) (parity := parity) + (s := s) (by omega) hp hcolor hntil end Checkerboard