From 9d1a7b1f407faedcff606b298c7a10351133dc77 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:06:41 -0700 Subject: [PATCH 001/115] feat: add continuous Weyl criterion on finite tori --- .../Equidistribution/UnitAddTorus.lean | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean new file mode 100644 index 0000000000..f068a774b9 --- /dev/null +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean @@ -0,0 +1,143 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +public import Mathlib.Analysis.Fourier.AddCircleMulti + +@[expose] public section + +/-! +# A continuous Weyl criterion on a finite-dimensional unit torus + +Mathlib proves that the multivariate Fourier monomials have dense complex +linear span in the continuous functions on `UnitAddTorus d`. This file +packages the standard consequence needed for equidistribution arguments: +convergence of the empirical averages of every Fourier monomial implies +convergence of the empirical averages of every continuous function. +-/ + +open Filter MeasureTheory Topology +open scoped Topology + +namespace UnitAddTorus + +variable {d : Type*} [Fintype d] + +/-- +**Continuous Weyl criterion on a finite unit torus.** + +If the empirical averages along `Y` converge to the `μ`-integral for every +multivariate Fourier monomial, then they converge to the `μ`-integral for +every continuous complex-valued function. The proof extends convergence +from the linear span of the monomials to its uniform closure, which is all of +`C(UnitAddTorus d, ℂ)` by `span_mFourier_closure_eq_top`. +-/ +theorem tendsto_average_of_tendsto_mFourier + (Y : ℕ → UnitAddTorus d) (μ : Measure (UnitAddTorus d)) + [IsProbabilityMeasure μ] + (hfou : ∀ k : d → ℤ, + Tendsto + (fun N : ℕ => (∑ n ∈ Finset.range N, mFourier k (Y n)) / N) + atTop + (𝓝 (∫ x, mFourier k x ∂μ))) : + ∀ F : C(UnitAddTorus d, ℂ), + Tendsto + (fun N : ℕ => (∑ n ∈ Finset.range N, F (Y n)) / N) + atTop + (𝓝 (∫ x, F x ∂μ)) := by + have hint : ∀ g : C(UnitAddTorus d, ℂ), Integrable g μ := fun g => + g.continuous.integrable_of_hasCompactSupport (HasCompactSupport.of_compactSpace _) + have hspan : ∀ g ∈ Submodule.span ℂ (Set.range (mFourier (d := d))), + Tendsto + (fun N : ℕ => (∑ n ∈ Finset.range N, g (Y n)) / N) + atTop + (𝓝 (∫ x, g x ∂μ)) := by + intro g hg + induction hg using Submodule.span_induction with + | mem g hgmem => + obtain ⟨k, rfl⟩ := hgmem + exact hfou k + | zero => + simp only [ContinuousMap.zero_apply, Finset.sum_const_zero, zero_div, integral_zero] + exact tendsto_const_nhds + | add g₁ g₂ _ _ ih₁ ih₂ => + simp only [ContinuousMap.add_apply, Finset.sum_add_distrib, add_div, + integral_add (hint g₁) (hint g₂)] + exact ih₁.add ih₂ + | smul c g _ ih => + simp only [ContinuousMap.smul_apply, smul_eq_mul, ← Finset.mul_sum, mul_div_assoc, + integral_const_mul] + exact ih.const_mul c + intro F + rw [Metric.tendsto_atTop] + intro ε hε + have hF : F ∈ closure (Submodule.span ℂ (Set.range (mFourier (d := d))) : Set _) := by + rw [← Submodule.topologicalClosure_coe, span_mFourier_closure_eq_top, + Submodule.top_coe] + exact Set.mem_univ F + obtain ⟨p, hp, hdist⟩ := Metric.mem_closure_iff.mp hF (ε / 3) (by positivity) + rw [dist_eq_norm] at hdist + obtain ⟨N₀, hN₀⟩ := + (Metric.tendsto_atTop.mp (hspan p hp)) (ε / 3) (by positivity) + refine ⟨N₀, fun N hN => ?_⟩ + have hbound : ∀ z : UnitAddTorus d, ‖F z - p z‖ ≤ ‖F - p‖ := fun z => by + simpa using (F - p).norm_coe_le_norm z + have h1 : + ‖(∑ n ∈ Finset.range N, F (Y n)) / N - + (∑ n ∈ Finset.range N, p (Y n)) / N‖ ≤ ‖F - p‖ := by + rw [div_sub_div_same, ← Finset.sum_sub_distrib, norm_div, Complex.norm_natCast] + rcases Nat.eq_zero_or_pos N with h | h + · simp [h] + · rw [div_le_iff₀ (by exact_mod_cast h)] + calc + ‖∑ n ∈ Finset.range N, (F (Y n) - p (Y n))‖ + ≤ ∑ n ∈ Finset.range N, ‖F (Y n) - p (Y n)‖ := norm_sum_le _ _ + _ ≤ ∑ _n ∈ Finset.range N, ‖F - p‖ := + Finset.sum_le_sum (fun n _ => hbound _) + _ = ‖F - p‖ * N := by + rw [Finset.sum_const, Finset.card_range, nsmul_eq_mul, mul_comm] + have h2 : ‖(∫ x, p x ∂μ) - ∫ x, F x ∂μ‖ ≤ ‖F - p‖ := by + rw [← integral_sub (hint p) (hint F)] + calc + ‖∫ x, (p x - F x) ∂μ‖ ≤ ∫ x, ‖p x - F x‖ ∂μ := + norm_integral_le_integral_norm _ + _ ≤ ∫ _x, ‖F - p‖ ∂μ := by + refine integral_mono_of_nonneg + (by filter_upwards with z using norm_nonneg (p z - F z)) + (integrable_const _) ?_ + filter_upwards with z + rw [norm_sub_rev] + exact hbound z + _ = ‖F - p‖ := by simp + have hN0' := hN₀ N hN + rw [dist_eq_norm] at hN0' ⊢ + have htri : + ‖(∑ n ∈ Finset.range N, F (Y n)) / N - ∫ x, F x ∂μ‖ ≤ + ‖(∑ n ∈ Finset.range N, F (Y n)) / N - + (∑ n ∈ Finset.range N, p (Y n)) / N‖ + + ‖(∑ n ∈ Finset.range N, p (Y n)) / N - ∫ x, p x ∂μ‖ + + ‖(∫ x, p x ∂μ) - ∫ x, F x ∂μ‖ := by + have heq : + (∑ n ∈ Finset.range N, F (Y n)) / N - ∫ x, F x ∂μ = + ((∑ n ∈ Finset.range N, F (Y n)) / N - + (∑ n ∈ Finset.range N, p (Y n)) / N) + + ((∑ n ∈ Finset.range N, p (Y n)) / N - ∫ x, p x ∂μ) + + ((∫ x, p x ∂μ) - ∫ x, F x ∂μ) := by ring + rw [heq] + exact norm_add₃_le + linarith [htri, h1, h2, hN0', hdist] + +end UnitAddTorus From 62ab606f1ebbc5a3279abaa9da2131253087794f Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:07:23 -0700 Subject: [PATCH 002/115] feat(OEIS): formalize A261865 density statement --- FormalConjectures/OEIS/261865.lean | 73 ++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 FormalConjectures/OEIS/261865.lean diff --git a/FormalConjectures/OEIS/261865.lean b/FormalConjectures/OEIS/261865.lean new file mode 100644 index 0000000000..1d2faf544e --- /dev/null +++ b/FormalConjectures/OEIS/261865.lean @@ -0,0 +1,73 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +public import FormalConjecturesUtil +public import FormalConjecturesForMathlib.Analysis.Equidistribution.UnitAddTorus + +@[expose] public section + +/-! +# OEIS A261865 / Peter Kagey's Problem 13 + +For a positive integer `n`, OEIS A261865 is the least positive integer `k` +for which a positive integer multiple of `√k` lies strictly between `n` and +`n + 1`. + +Peter Kagey's Problem 13 asks for the natural density of the indices at which +a fixed squarefree `j ≥ 2` is the least successful radicand. The predicted +density is + +`(1 / √j) * ∏_{2 ≤ s < j, Squarefree s} (1 - 1 / √s)`. +-/ + +open Filter +open scoped BigOperators Topology + +namespace OeisA261865 + +/-- A positive integer multiple of `√k` lies strictly in `(n, n + 1)`. -/ +def Hits (k n : ℕ) : Prop := + ∃ m : ℕ, 0 < m ∧ + (n : ℝ) < (m : ℝ) * Real.sqrt (k : ℝ) ∧ + (m : ℝ) * Real.sqrt (k : ℝ) < (n : ℝ) + 1 + +/-- `k` is the least positive radicand that hits the interval `(n, n + 1)`. -/ +def IsValue (n k : ℕ) : Prop := + 0 < k ∧ Hits k n ∧ ∀ r : ℕ, 0 < r → r < k → ¬ Hits r n + +/-- The squarefree integers in `[2, j)`. -/ +noncomputable def squarefreeBelow (j : ℕ) : Finset ℕ := by + classical + exact (Finset.Ico 2 j).filter Squarefree + +/-- The density predicted for the value `j` in OEIS A261865. -/ +noncomputable def predictedDensity (j : ℕ) : ℝ := + (1 / Real.sqrt (j : ℝ)) * + ∏ s ∈ squarefreeBelow j, (1 - 1 / Real.sqrt (s : ℝ)) + +/-- +**Peter Kagey's Problem 13 / OEIS A261865.** + +For every squarefree `j ≥ 2`, the set of positive indices where the least +successful radicand is `j` has the stated natural density. +-/ +@[category research open, AMS 11] +theorem density_formula (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : + {n : ℕ | 0 < n ∧ IsValue n j}.HasDensity (predictedDensity j) := by + sorry + +end OeisA261865 From 6550ee32657698a20d553ebab93bea4d4dc20c65 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:10:00 -0700 Subject: [PATCH 003/115] proof(OEIS): remove the interval conversion axiom --- FormalConjectures/OEIS/261865.lean | 73 +++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/FormalConjectures/OEIS/261865.lean b/FormalConjectures/OEIS/261865.lean index 1d2faf544e..0e829e6a0f 100644 --- a/FormalConjectures/OEIS/261865.lean +++ b/FormalConjectures/OEIS/261865.lean @@ -49,6 +49,76 @@ def Hits (k n : ℕ) : Prop := def IsValue (n k : ℕ) : Prop := 0 < k ∧ Hits k n ∧ ∀ r : ℕ, 0 < r → r < k → ¬ Hits r n +/-- The rotation parameter `1 / √s`. -/ +noncomputable def alpha (s : ℕ) : ℝ := + 1 / Real.sqrt (s : ℝ) + +/-- The fractional-part condition corresponding to `Hits s n`. -/ +def CoordinateHit (s n : ℕ) : Prop := + 1 - alpha s < Int.fract ((n : ℝ) * alpha s) + +/-- +The next positive integer after a nonnegative real `x` lies below `x + a` +exactly when the fractional part of `x` is greater than `1 - a`. +-/ +theorem exists_nat_between_iff_fract {x a : ℝ} (hx : 0 ≤ x) : + (∃ m : ℕ, 0 < m ∧ x < (m : ℝ) ∧ (m : ℝ) < x + a) ↔ + 1 - a < Int.fract x := by + constructor + · rintro ⟨m, _hmpos, hxm, hmx⟩ + have hfloor_lt : ⌊x⌋ < (m : ℤ) := + Int.floor_lt.mpr (by simpa using hxm) + have hnext_le : ⌊x⌋ + 1 ≤ (m : ℤ) := by omega + have hnext_le_real : ((⌊x⌋ + 1 : ℤ) : ℝ) ≤ (m : ℝ) := by + exact_mod_cast hnext_le + have hnext_lt : (⌊x⌋ : ℝ) + 1 < x + a := by + exact lt_of_le_of_lt (by simpa using hnext_le_real) hmx + have hdecomp := Int.floor_add_fract x + linarith + · intro hfract + have hfloor_nonneg : 0 ≤ ⌊x⌋ := Int.floor_nonneg.mpr hx + let m : ℕ := ⌊x⌋.toNat + 1 + have hmcast : (m : ℝ) = (⌊x⌋ : ℝ) + 1 := by + simp [m, Int.toNat_of_nonneg hfloor_nonneg] + refine ⟨m, by simp [m], ?_, ?_⟩ + · rw [hmcast] + exact Int.lt_floor_add_one x + · rw [hmcast] + have hdecomp := Int.floor_add_fract x + linarith + +/-- +The interval-hitting predicate is exactly an irrational-rotation interval. +This removes the first axiom from the uploaded proof bundle. +-/ +theorem hits_iff_coordinateHit (s n : ℕ) (hs : 2 ≤ s) : + Hits s n ↔ CoordinateHit s n := by + have hs_real_pos : (0 : ℝ) < (s : ℝ) := by positivity + have hsqrt_pos : (0 : ℝ) < Real.sqrt (s : ℝ) := Real.sqrt_pos.2 hs_real_pos + have hx : 0 ≤ (n : ℝ) / Real.sqrt (s : ℝ) := + div_nonneg (by positivity) hsqrt_pos.le + constructor + · rintro ⟨m, hmpos, hleft, hright⟩ + have hleft' : (n : ℝ) / Real.sqrt (s : ℝ) < (m : ℝ) := + (div_lt_iff₀ hsqrt_pos).2 hleft + have hright' : (m : ℝ) < + (n : ℝ) / Real.sqrt (s : ℝ) + 1 / Real.sqrt (s : ℝ) := by + have := (lt_div_iff₀ hsqrt_pos).2 hright + convert this using 1 <;> ring + have hfract := (exists_nat_between_iff_fract hx).mp + ⟨m, hmpos, hleft', hright'⟩ + simpa [CoordinateHit, alpha, div_eq_mul_inv] using hfract + · intro hcoord + have hfract : + 1 - 1 / Real.sqrt (s : ℝ) < + Int.fract ((n : ℝ) / Real.sqrt (s : ℝ)) := by + simpa [CoordinateHit, alpha, div_eq_mul_inv] using hcoord + obtain ⟨m, hmpos, hleft, hright⟩ := + (exists_nat_between_iff_fract hx).mpr hfract + refine ⟨m, hmpos, (div_lt_iff₀ hsqrt_pos).mp hleft, ?_⟩ + apply (lt_div_iff₀ hsqrt_pos).mp + convert hright using 1 <;> ring + /-- The squarefree integers in `[2, j)`. -/ noncomputable def squarefreeBelow (j : ℕ) : Finset ℕ := by classical @@ -56,8 +126,7 @@ noncomputable def squarefreeBelow (j : ℕ) : Finset ℕ := by /-- The density predicted for the value `j` in OEIS A261865. -/ noncomputable def predictedDensity (j : ℕ) : ℝ := - (1 / Real.sqrt (j : ℝ)) * - ∏ s ∈ squarefreeBelow j, (1 - 1 / Real.sqrt (s : ℝ)) + alpha j * ∏ s ∈ squarefreeBelow j, (1 - alpha s) /-- **Peter Kagey's Problem 13 / OEIS A261865.** From 74a15d1277bb28fdbbf2213f8c1f4a3e225d001c Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:19:30 -0700 Subject: [PATCH 004/115] Add square-factor reduction for A261865 --- FormalConjectures/OEIS/261865.lean | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/FormalConjectures/OEIS/261865.lean b/FormalConjectures/OEIS/261865.lean index 0e829e6a0f..e8b8e35074 100644 --- a/FormalConjectures/OEIS/261865.lean +++ b/FormalConjectures/OEIS/261865.lean @@ -119,6 +119,23 @@ theorem hits_iff_coordinateHit (s n : ℕ) (hs : 2 ≤ s) : apply (lt_div_iff₀ hsqrt_pos).mp convert hright using 1 <;> ring +/-- +Removing a positive square factor from a radicand preserves the hitting +property. Hence a nonsquarefree radicand can never be a genuinely new least +value: every hit by `c² s` is already a hit by `s`. +-/ +theorem hits_square_mul_imp (c s n : ℕ) (hc : 0 < c) : + Hits (c ^ 2 * s) n → Hits s n := by + rintro ⟨m, hm, hleft, hright⟩ + have hsqrt : + Real.sqrt ((c ^ 2 * s : ℕ) : ℝ) = + (c : ℝ) * Real.sqrt (s : ℝ) := by + rw [Nat.cast_mul, Nat.cast_pow, Real.sqrt_mul (sq_nonneg (c : ℝ))] + rw [Real.sqrt_sq (Nat.cast_nonneg c)] + refine ⟨m * c, Nat.mul_pos hm hc, ?_, ?_⟩ + · simpa [Nat.cast_mul, mul_assoc, hsqrt] using hleft + · simpa [Nat.cast_mul, mul_assoc, hsqrt] using hright + /-- The squarefree integers in `[2, j)`. -/ noncomputable def squarefreeBelow (j : ℕ) : Finset ℕ := by classical @@ -133,6 +150,10 @@ noncomputable def predictedDensity (j : ℕ) : ℝ := For every squarefree `j ≥ 2`, the set of positive indices where the least successful radicand is `j` has the stated natural density. + +The mathematical proof and Lean development were produced by +ProofOrchestrator, using OpenAI GPT-5.6 Thinking, under Dominic Dabish's +supervision. -/ @[category research open, AMS 11] theorem density_formula (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : From 6f7cb9181ddbd87ad4643681d3bca20ca14961f4 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:24:49 -0700 Subject: [PATCH 005/115] Normalize A261865 square-factor reduction --- FormalConjectures/OEIS/261865.lean | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/FormalConjectures/OEIS/261865.lean b/FormalConjectures/OEIS/261865.lean index e8b8e35074..c216223341 100644 --- a/FormalConjectures/OEIS/261865.lean +++ b/FormalConjectures/OEIS/261865.lean @@ -133,8 +133,10 @@ theorem hits_square_mul_imp (c s n : ℕ) (hc : 0 < c) : rw [Nat.cast_mul, Nat.cast_pow, Real.sqrt_mul (sq_nonneg (c : ℝ))] rw [Real.sqrt_sq (Nat.cast_nonneg c)] refine ⟨m * c, Nat.mul_pos hm hc, ?_, ?_⟩ - · simpa [Nat.cast_mul, mul_assoc, hsqrt] using hleft - · simpa [Nat.cast_mul, mul_assoc, hsqrt] using hright + · simpa only [hsqrt, Nat.cast_mul] + simpa only [mul_assoc] using hleft + · simpa only [hsqrt, Nat.cast_mul] + simpa only [mul_assoc] using hright /-- The squarefree integers in `[2, j)`. -/ noncomputable def squarefreeBelow (j : ℕ) : Finset ℕ := by From 8463734d972a8ef8ac8cf3b7d00cf7a0c234b646 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:25:15 -0700 Subject: [PATCH 006/115] Fix square-factor simplification --- FormalConjectures/OEIS/261865.lean | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/FormalConjectures/OEIS/261865.lean b/FormalConjectures/OEIS/261865.lean index c216223341..b834725091 100644 --- a/FormalConjectures/OEIS/261865.lean +++ b/FormalConjectures/OEIS/261865.lean @@ -133,10 +133,8 @@ theorem hits_square_mul_imp (c s n : ℕ) (hc : 0 < c) : rw [Nat.cast_mul, Nat.cast_pow, Real.sqrt_mul (sq_nonneg (c : ℝ))] rw [Real.sqrt_sq (Nat.cast_nonneg c)] refine ⟨m * c, Nat.mul_pos hm hc, ?_, ?_⟩ - · simpa only [hsqrt, Nat.cast_mul] - simpa only [mul_assoc] using hleft - · simpa only [hsqrt, Nat.cast_mul] - simpa only [mul_assoc] using hright + · simpa only [hsqrt, Nat.cast_mul, mul_assoc] using hleft + · simpa only [hsqrt, Nat.cast_mul, mul_assoc] using hright /-- The squarefree integers in `[2, j)`. -/ noncomputable def squarefreeBelow (j : ℕ) : Finset ℕ := by From a845c112d9c2d90eba18d1cbacbb92ca19ed514e Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:26:18 -0700 Subject: [PATCH 007/115] noop --- README_DO_NOT_CREATE | 1 + 1 file changed, 1 insertion(+) create mode 100644 README_DO_NOT_CREATE diff --git a/README_DO_NOT_CREATE b/README_DO_NOT_CREATE new file mode 100644 index 0000000000..a8b6c9477b --- /dev/null +++ b/README_DO_NOT_CREATE @@ -0,0 +1 @@ +noop \ No newline at end of file From b2ad1c9a8f3c351bccb4eefe42c571dddbe9e7b8 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:26:27 -0700 Subject: [PATCH 008/115] Remove accidental empty marker --- README_DO_NOT_CREATE | 1 - 1 file changed, 1 deletion(-) delete mode 100644 README_DO_NOT_CREATE diff --git a/README_DO_NOT_CREATE b/README_DO_NOT_CREATE deleted file mode 100644 index a8b6c9477b..0000000000 --- a/README_DO_NOT_CREATE +++ /dev/null @@ -1 +0,0 @@ -noop \ No newline at end of file From e100c0fd585fe2a9e1e07265177a3aee44f2cc85 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:26:34 -0700 Subject: [PATCH 009/115] noop --- README_DO_NOT_CREATE | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 README_DO_NOT_CREATE diff --git a/README_DO_NOT_CREATE b/README_DO_NOT_CREATE new file mode 100644 index 0000000000..e69de29bb2 From ba0ca25d0ac1b4c11af2840d1b6d5ddd79272d09 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:26:43 -0700 Subject: [PATCH 010/115] Remove accidental marker --- README_DO_NOT_CREATE | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 README_DO_NOT_CREATE diff --git a/README_DO_NOT_CREATE b/README_DO_NOT_CREATE deleted file mode 100644 index e69de29bb2..0000000000 From ec7dc4bb43b7ef8024870530a65fb5b552822256 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:33:07 -0700 Subject: [PATCH 011/115] noop --- README_DO_NOT_CREATE | 1 + 1 file changed, 1 insertion(+) create mode 100644 README_DO_NOT_CREATE diff --git a/README_DO_NOT_CREATE b/README_DO_NOT_CREATE new file mode 100644 index 0000000000..5579d45d2b --- /dev/null +++ b/README_DO_NOT_CREATE @@ -0,0 +1 @@ +do-not-use \ No newline at end of file From ead4d61984d6f30550176fe60d6e07893a6b02c0 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:33:19 -0700 Subject: [PATCH 012/115] Remove accidental marker --- README_DO_NOT_CREATE | 1 - 1 file changed, 1 deletion(-) delete mode 100644 README_DO_NOT_CREATE diff --git a/README_DO_NOT_CREATE b/README_DO_NOT_CREATE deleted file mode 100644 index 5579d45d2b..0000000000 --- a/README_DO_NOT_CREATE +++ /dev/null @@ -1 +0,0 @@ -do-not-use \ No newline at end of file From d13da75c3dc09cb0bb229697b22548ae9bbb948e Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:37:21 -0700 Subject: [PATCH 013/115] Add temporary AXLE audit for A261865 development --- .github/workflows/a261865-axle-audit.yml | 60 ++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 .github/workflows/a261865-axle-audit.yml diff --git a/.github/workflows/a261865-axle-audit.yml b/.github/workflows/a261865-axle-audit.yml new file mode 100644 index 0000000000..9be183699e --- /dev/null +++ b/.github/workflows/a261865-axle-audit.yml @@ -0,0 +1,60 @@ +name: Temporary A261865 AXLE audit + +on: + pull_request: + branches: [main] + paths: + - 'FormalConjectures/OEIS/261865.lean' + - 'FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean' + - '.github/workflows/a261865-axle-audit.yml' + workflow_dispatch: + +permissions: + contents: read + +jobs: + check-foundation: + name: Check A261865 foundation with AXLE + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + - name: Check Lean 4.27 sources + shell: bash + run: | + python3 - <<'PY' + import json + import pathlib + import sys + import urllib.request + + files = [ + 'FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean', + ] + failed = False + for filename in files: + source = pathlib.Path(filename).read_text() + payload = json.dumps({ + 'content': source, + 'environment': 'lean-4.27.0', + 'ignore_imports': False, + 'mathlib_options': False, + 'timeout_seconds': 480, + }).encode() + request = urllib.request.Request( + 'https://axle.axiommath.ai/api/v1/check', + data=payload, + headers={'Content-Type': 'application/json'}, + method='POST', + ) + with urllib.request.urlopen(request, timeout=540) as response: + result = json.load(response) + print(f'===== {filename} =====') + print(json.dumps(result, indent=2)) + errors = result.get('lean_messages', {}).get('errors', []) + tool_errors = result.get('tool_messages', {}).get('errors', []) + declarations = result.get('failed_declarations', []) + failed |= bool(errors or tool_errors or declarations or not result.get('okay', False)) + if failed: + sys.exit(1) + PY From 48776129b08a32f5f72cc5ed3781a77a3ca38717 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:46:00 -0700 Subject: [PATCH 014/115] Develop squarefree radical independence for A261865 --- .../NumberTheory/SquarefreeRadical.lean | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean diff --git a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean new file mode 100644 index 0000000000..338d8c796c --- /dev/null +++ b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean @@ -0,0 +1,165 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +public import Mathlib + +@[expose] public section + +noncomputable section + +open scoped Classical +open Polynomial Module + +namespace Nat + +/-- The product of two squarefree natural numbers is a square only when they are equal. -/ +theorem eq_of_squarefree_of_isSquare_mul {a b : ℕ} (ha : Squarefree a) (hb : Squarefree b) + (hab : IsSquare (a * b)) : a = b := by + rw [ha.ext_iff hb] + intro p hp + obtain ⟨c, hc⟩ := hab + have hfac : a.factorization p + b.factorization p = 2 * c.factorization p := by + calc + a.factorization p + b.factorization p = (a * b).factorization p := by + rw [factorization_mul ha.ne_zero hb.ne_zero] + _ = (c ^ 2).factorization p := by rw [← hc, sq] + _ = 2 * c.factorization p := by simp [factorization_pow] + constructor + · intro hpa + have hfa : a.factorization p = 1 := factorization_eq_one_of_squarefree ha hp hpa + have hfb_le : b.factorization p ≤ 1 := hb.natFactorization_le_one p + have hfb : b.factorization p = 1 := by omega + exact (hp.dvd_iff_one_le_factorization hb.ne_zero).2 (by omega) + · intro hpb + have hfb : b.factorization p = 1 := factorization_eq_one_of_squarefree hb hp hpb + have hfa_le : a.factorization p ≤ 1 := ha.natFactorization_le_one p + have hfa : a.factorization p = 1 := by omega + exact (hp.dvd_iff_one_le_factorization ha.ne_zero).2 (by omega) + +end Nat + +namespace Real + +/-- In a number field, a non-rational element whose square is rational has trace zero. -/ +theorem trace_eq_zero_of_sq_ratCast {K : Type*} [Field K] [NumberField K] {x : K} {r : ℚ} + (hx2 : x ^ 2 = algebraMap ℚ K r) (hx : x ∉ (algebraMap ℚ K).range) : + Algebra.trace ℚ K x = 0 := by + have hmonic : (X ^ 2 - C r).Monic := Polynomial.monic_X_pow_sub_C r (by norm_num) + have haeval : aeval x (X ^ 2 - C r : ℚ[X]) = 0 := by simp [hx2] + have hdvd : minpoly ℚ x ∣ (X ^ 2 - C r) := minpoly.dvd ℚ x haeval + have hint : IsIntegral ℚ x := Algebra.IsIntegral.isIntegral x + have hne : (X ^ 2 - C r : ℚ[X]) ≠ 0 := Polynomial.X_pow_sub_C_ne_zero (by norm_num) r + have hdeg2 : (minpoly ℚ x).natDegree = 2 := by + have hle : (minpoly ℚ x).natDegree ≤ 2 := by + have := Polynomial.natDegree_le_of_dvd hdvd hne + simpa [Polynomial.natDegree_X_pow_sub_C] using this + have hge : 2 ≤ (minpoly ℚ x).natDegree := by + by_contra h + push_neg at h + interval_cases hh : (minpoly ℚ x).natDegree + · exact (minpoly.natDegree_pos hint).ne' hh + · exact hx (minpoly.natDegree_eq_one_iff.mp hh) + omega + have heq : minpoly ℚ x = X ^ 2 - C r := + (Polynomial.eq_of_monic_of_dvd_of_natDegree_le (minpoly.monic hint) hmonic hdvd + (by rw [hdeg2, Polynomial.natDegree_X_pow_sub_C])).symm + rw [trace_eq_finrank_mul_minpoly_nextCoeff, heq] + have hnc : (X ^ 2 - C r : ℚ[X]).nextCoeff = 0 := by + rw [Polynomial.nextCoeff_of_natDegree_pos + (by rw [Polynomial.natDegree_X_pow_sub_C]; norm_num)] + simp [Polynomial.coeff_X_pow] + rw [hnc] + simp + +/-- Square roots of an injective finite family of squarefree natural numbers are +linearly independent over the rationals. -/ +theorem linearIndependent_sqrt_squarefree {ι : Type*} [Fintype ι] + (s : ι → ℕ) (hs : ∀ i, Squarefree (s i)) (hinj : Function.Injective s) : + LinearIndependent ℚ (fun i => Real.sqrt (s i)) := by + let K : IntermediateField ℚ ℝ := + IntermediateField.adjoin ℚ (Set.range fun i => Real.sqrt (s i)) + have hfd : FiniteDimensional ℚ K := by + refine IntermediateField.finiteDimensional_adjoin ?_ + rintro x ⟨i, rfl⟩ + refine ⟨Polynomial.X ^ 2 - Polynomial.C (s i : ℚ), ?_, ?_⟩ + · exact Polynomial.monic_X_pow_sub_C _ two_ne_zero + · norm_num [← Polynomial.C_pow] + norm_cast + rw [Real.sq_sqrt (Nat.cast_nonneg _)] + ring + letI : NumberField K := + { to_charZero := inferInstance + to_finiteDimensional := hfd } + let root (i : ι) : K := + ⟨Real.sqrt (s i), IntermediateField.subset_adjoin ℚ _ ⟨i, rfl⟩⟩ + have hroot_sq (i : ι) : (root i) ^ 2 = algebraMap ℚ K (s i : ℚ) := by + apply Subtype.ext + simp only [root] + push_cast + rw [Real.sq_sqrt (Nat.cast_nonneg _)] + norm_cast + have hmul_sq (i j : ι) : (root i * root j) ^ 2 = algebraMap ℚ K ((s i * s j : ℕ) : ℚ) := by + rw [mul_pow, hroot_sq, hroot_sq, ← map_mul] + norm_cast + have hmul_not_range {i j : ι} (hij : i ≠ j) : + root i * root j ∉ (algebraMap ℚ K).range := by + intro h + obtain ⟨q, hq⟩ := h + have hsq_rat : IsSquare (((s i * s j : ℕ) : ℚ)) := by + refine ⟨q, ?_⟩ + apply (algebraMap ℚ K).injective + rw [map_mul, ← hq, hmul_sq] + have hsq_nat : IsSquare (s i * s j) := by + rwa [Rat.isSquare_natCast_iff] at hsq_rat + exact hij (hinj (Nat.eq_of_squarefree_of_isSquare_mul (hs i) (hs j) hsq_nat)) + have htrace_mul_of_ne {i j : ι} (hij : i ≠ j) : + Algebra.trace ℚ K (root i * root j) = 0 := + trace_eq_zero_of_sq_ratCast (hmul_sq i j) (hmul_not_range hij) + have htrace_self (i : ι) : + Algebra.trace ℚ K (root i * root i) = (finrank ℚ K : ℚ) * s i := by + convert congr_arg (fun x : K => Algebra.trace ℚ K x) (hroot_sq i) using 1 + · rw [sq] + · rw [Algebra.trace_algebraMap] + norm_num [Algebra.smul_def] + have htraceMatrix : + Algebra.traceMatrix ℚ root = Matrix.diagonal (fun i => (finrank ℚ K : ℚ) * s i) := by + ext i j + by_cases h : i = j + · subst j + simp [Algebra.traceMatrix_apply, Algebra.traceForm_apply, htrace_self] + · simp [Algebra.traceMatrix_apply, Algebra.traceForm_apply, h, + htrace_mul_of_ne h] + have hdiscr : Algebra.discr ℚ root ≠ 0 := by + rw [Algebra.discr_def, htraceMatrix] + simp only [Matrix.det_diagonal] + exact Finset.prod_ne_zero_iff.mpr fun i _ => + mul_ne_zero (Nat.cast_ne_zero.mpr (ne_of_gt Module.finrank_pos)) + (Nat.cast_ne_zero.mpr (hs i).ne_zero) + have hrootK : LinearIndependent ℚ root := by + by_contra h + exact hdiscr (Algebra.discr_zero_of_not_linearIndependent ℚ h) + let inc : K →ₗ[ℚ] ℝ := + { toFun := fun x => x.1 + map_add' := fun _ _ => rfl + map_smul' := fun _ _ => rfl } + have hinc : LinearMap.ker inc = ⊥ := by + ext x + simp [inc] + have himage := hrootK.map' inc hinc + simpa [Function.comp_def, root, inc] using himage + +end Real From 23312623c5ff79246977a9bdb4ace286d933db34 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:46:15 -0700 Subject: [PATCH 015/115] Extend temporary AXLE audit to radical independence --- .github/workflows/a261865-axle-audit.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/a261865-axle-audit.yml b/.github/workflows/a261865-axle-audit.yml index 9be183699e..cf284c0047 100644 --- a/.github/workflows/a261865-axle-audit.yml +++ b/.github/workflows/a261865-axle-audit.yml @@ -6,6 +6,7 @@ on: paths: - 'FormalConjectures/OEIS/261865.lean' - 'FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean' + - 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean' - '.github/workflows/a261865-axle-audit.yml' workflow_dispatch: @@ -14,9 +15,9 @@ permissions: jobs: check-foundation: - name: Check A261865 foundation with AXLE + name: Check A261865 foundations with AXLE runs-on: ubuntu-latest - timeout-minutes: 10 + timeout-minutes: 15 steps: - uses: actions/checkout@v4 - name: Check Lean 4.27 sources @@ -30,6 +31,7 @@ jobs: files = [ 'FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean', + 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean', ] failed = False for filename in files: From fc21fba98e3f29b4772273bd8c9a80996023d26f Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:50:43 -0700 Subject: [PATCH 016/115] Add eigencharacter independence infrastructure --- .../LinearAlgebra/Eigencharacter.lean | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 FormalConjecturesForMathlib/LinearAlgebra/Eigencharacter.lean diff --git a/FormalConjecturesForMathlib/LinearAlgebra/Eigencharacter.lean b/FormalConjecturesForMathlib/LinearAlgebra/Eigencharacter.lean new file mode 100644 index 0000000000..734054376a --- /dev/null +++ b/FormalConjecturesForMathlib/LinearAlgebra/Eigencharacter.lean @@ -0,0 +1,116 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +import Mathlib.LinearAlgebra.LinearIndependent.Basic +import Mathlib.LinearAlgebra.LinearIndependent.Lemmas + +open Function + +noncomputable section + +namespace Eigencharacter + +variable {K E G ι : Type*} + [Field K] [Field E] [Algebra K E] + [Group G] [MulSemiringAction G E] [SMulCommClass G K E] + +/-- Send an element to its orbit function under a group action. -/ +def orbit : E →ₗ[K] (G → E) where + toFun x g := g • x + map_add' x y := by ext g; exact smul_add _ _ _ + map_smul' c x := by ext g; exact smul_comm _ _ _ + +/-- Lift a base-field-valued multiplicative character to the extension field. -/ +def liftHom (χ : G →* K) : G →* E := + (algebraMap K E).comp χ + +lemma liftHom_injective : Injective (liftHom : (G →* K) → (G →* E)) := by + intro χ ψ h + ext g + apply (algebraMap K E).injective + exact DFunLike.congr_fun h g + +/-- Eigenvectors belonging to distinct base-field-valued characters are linearly independent. -/ +theorem linearIndependent_of_eigencharacters + (v : ι → E) (hv : ∀ i, v i ≠ 0) + (χ : ι → G →* K) (hχ : Injective χ) + (heig : ∀ i g, g • v i = algebraMap K E (χ i g) * v i) : + LinearIndependent K v := by + have hchar : LinearIndependent E (fun i => (liftHom (χ i) : G → E)) := + (linearIndependent_monoidHom G E).comp (fun i => liftHom (χ i)) + (liftHom_injective.comp hχ) + have hscaled : LinearIndependent E + ((fun i => Units.mk0 (v i) (hv i)) • + (fun i => (liftHom (χ i) : G → E))) := + hchar.units_smul (fun i => Units.mk0 (v i) (hv i)) + have horbitE : LinearIndependent E (fun i => orbit (K := K) (E := E) (G := G) (v i)) := by + convert hscaled using 1 + funext i g + simp only [Pi.smul_apply', Units.smul_def, liftHom, MonoidHom.comp_apply, orbit] + rw [heig i g] + ring + have horbitK : LinearIndependent K (fun i => orbit (K := K) (E := E) (G := G) (v i)) := + horbitE.restrict_scalars' K + exact LinearIndependent.of_comp (orbit (K := K) (E := E) (G := G)) horbitK + +variable [CharZero K] [CharZero E] + +/-- The ±1 character carried by a nonzero vector whose orbit is contained in `{v,-v}`. -/ +def signHom (v : E) (hv : v ≠ 0) (horbit : ∀ g : G, g • v = v ∨ g • v = -v) : + G →* K where + toFun g := if g • v = v then 1 else -1 + map_one' := by simp + map_mul' g h := by + have hneg : -v ≠ v := by + simpa only [CharZero.neg_eq_self_iff] using hv + rcases horbit g with hg | hg <;> + rcases horbit h with hh | hh <;> + simp [mul_smul, hg, hh, hneg] + +@[simp] lemma signHom_apply_eq_one {v : E} {hv horbit} (g : G) + (hg : g • v = v) : signHom (K := K) v hv horbit g = 1 := by + simp [signHom, hg] + +@[simp] lemma signHom_apply_eq_neg_one {v : E} {hv horbit} (g : G) + (hg : g • v = -v) : signHom (K := K) v hv horbit g = -1 := by + have hneg : -v ≠ v := by simpa only [CharZero.neg_eq_self_iff] using hv + simp [signHom, hg, hneg] + +lemma signHom_eigen {v : E} {hv horbit} (g : G) : + g • v = algebraMap K E (signHom (K := K) v hv horbit g) * v := by + rcases horbit g with hg | hg + · simp [hg] + · rw [signHom_apply_eq_neg_one (K := K) g hg] + simp [hg] + +lemma fixed_mul_of_signHom_eq {v w : E} {hv : v ≠ 0} {hw : w ≠ 0} + {hv_orbit : ∀ g : G, g • v = v ∨ g • v = -v} + {hw_orbit : ∀ g : G, g • w = w ∨ g • w = -w} + (hχ : signHom (K := K) v hv hv_orbit = signHom (K := K) w hw hw_orbit) + (g : G) : g • (v * w) = v * w := by + have hχg := DFunLike.congr_fun hχ g + rcases hv_orbit g with hvg | hvg <;> rcases hw_orbit g with hwg | hwg + · simp [smul_mul', hvg, hwg] + · have : (1 : K) = -1 := by + simpa [signHom, hvg, hwg, CharZero.neg_eq_self_iff, hv, hw] using hχg + exact (one_ne_neg_one (R := K) this).elim + · have : (-1 : K) = 1 := by + simpa [signHom, hvg, hwg, CharZero.neg_eq_self_iff, hv, hw] using hχg + exact (neg_one_ne_one (R := K) this).elim + · simp [smul_mul', hvg, hwg] + +end Eigencharacter From 41a0b9dafa7b9f03637f3060a87332bd0e25d874 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:51:30 -0700 Subject: [PATCH 017/115] Add squarefree radical independence theorem --- .../NumberTheory/SquarefreeRadicals.lean | 228 ++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean diff --git a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean new file mode 100644 index 0000000000..1189aa4d7a --- /dev/null +++ b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean @@ -0,0 +1,228 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +import Mathlib.FieldTheory.PolynomialGaloisGroup +import FormalConjecturesForMathlib.LinearAlgebra.Eigencharacter +import Mathlib.Data.Nat.Squarefree +import Mathlib.Data.Rat.Sqrt +import Mathlib.LinearAlgebra.LinearIndependent.Lemmas + +open Finset Function Polynomial +open scoped BigOperators + +noncomputable section + +namespace SquarefreeRadicals + +/-- The quadratic polynomial whose roots are `±√n`. -/ +def quad (n : ℕ) : ℚ[X] := X ^ 2 - C (n : ℚ) + +/-- A product of the quadratic polynomials attached to a finite set. -/ +def quadProduct (S : Finset ℕ) : ℚ[X] := ∏ n ∈ S, quad n + +lemma quad_monic (n : ℕ) : (quad n).Monic := by + simpa [quad] using monic_X_pow_sub_C (n : ℚ) (by decide : (2 : ℕ) ≠ 0) + +lemma quad_ne_zero (n : ℕ) : quad n ≠ 0 := (quad_monic n).ne_zero + +lemma quadProduct_monic (S : Finset ℕ) : (quadProduct S).Monic := by + apply monic_prod_of_monic + intro n hn + exact quad_monic n + +lemma quadProduct_ne_zero (S : Finset ℕ) : quadProduct S ≠ 0 := (quadProduct_monic S).ne_zero + +lemma quad_isCoprime {m n : ℕ} (h : m ≠ n) : IsCoprime (quad m) (quad n) := by + let d : ℚ := (n : ℚ) - m + have hd : d ≠ 0 := by + dsimp [d] + exact sub_ne_zero.mpr (by exact_mod_cast h.symm) + refine ⟨C d⁻¹, -C d⁻¹, ?_⟩ + dsimp [quad, d] + field_simp [hd] + ring + +lemma quad_separable {n : ℕ} (hn : n ≠ 0) : (quad n).Separable := by + let u : ℚˣ := Units.mk0 (n : ℚ) (by exact_mod_cast hn) + have htwo : IsUnit (2 : ℚ) := isUnit_iff_ne_zero.mpr (by norm_num) + simpa [quad, u] using separable_X_pow_sub_C_unit u htwo + +lemma quadProduct_separable (S : Finset ℕ) (hpos : ∀ n ∈ S, n ≠ 0) : + (quadProduct S).Separable := by + apply separable_prod' + · intro m hm n hn hmn + exact quad_isCoprime hmn + · intro n hn + exact quad_separable (hpos n hn) + +lemma quad_dvd_quadProduct {S : Finset ℕ} {n : ℕ} (hn : n ∈ S) : + quad n ∣ quadProduct S := by + exact Finset.dvd_prod_of_mem (fun n => quad n) hn + +/-- The common splitting field of all quadratic polynomials in `S`. -/ +abbrev RadicalField (S : Finset ℕ) := (quadProduct S).SplittingField + +/-- Each quadratic factor splits in the common splitting field. -/ +lemma quad_splits (S : Finset ℕ) (n : S) : + ((quad n.1).map (algebraMap ℚ (RadicalField S))).Splits := by + have hP : ((quadProduct S).map (algebraMap ℚ (RadicalField S))).Splits := + Polynomial.SplittingField.splits (quadProduct S) + apply hP.of_dvd + · exact map_ne_zero (quadProduct_ne_zero S) + · rcases quad_dvd_quadProduct n.2 with ⟨r, hr⟩ + refine ⟨r.map (algebraMap ℚ (RadicalField S)), ?_⟩ + rw [← map_mul, hr] + +lemma quad_mapped_degree_ne_zero (S : Finset ℕ) (n : S) : + ((quad n.1).map (algebraMap ℚ (RadicalField S))).degree ≠ 0 := by + rw [(quad_monic n.1).degree_map] + simp [quad] + +/-- A chosen square root of each radicand inside the common splitting field. -/ +def root (S : Finset ℕ) (n : S) : RadicalField S := + Polynomial.rootOfSplits (quad_splits S n) (quad_mapped_degree_ne_zero S n) + +lemma root_spec (S : Finset ℕ) (n : S) : + root S n ^ 2 = algebraMap ℚ (RadicalField S) (n.1 : ℚ) := by + have h := Polynomial.eval_rootOfSplits (quad_splits S n) (quad_mapped_degree_ne_zero S n) + simpa [root, quad] using h + +lemma root_ne_zero (S : Finset ℕ) (n : S) (hn : n.1 ≠ 0) : root S n ≠ 0 := by + intro h + have hs := root_spec S n + rw [h, zero_pow (by decide : (2 : ℕ) ≠ 0)] at hs + exact (map_ne_zero (by exact_mod_cast hn)) hs.symm + +/-- Every Galois automorphism sends a chosen square root to itself or its negative. -/ +lemma gal_root_eq_or_neg (S : Finset ℕ) (n : S) + (σ : (quadProduct S).Gal) : + σ (root S n) = root S n ∨ σ (root S n) = -root S n := by + apply sq_eq_sq_iff_eq_or_eq_neg.mp + rw [map_pow, root_spec, root_spec] + simp + +/-- A rational square which is a natural number is already a natural square. -/ +lemma exists_nat_mul_self_of_exists_rat_mul_self {N : ℕ} + (h : ∃ q : ℚ, q * q = (N : ℚ)) : + ∃ u : ℕ, u * u = N := by + have hsqrt : Rat.sqrt (N : ℚ) * Rat.sqrt (N : ℚ) = (N : ℚ) := + (Rat.exists_mul_self (N : ℚ)).mp h + rw [Rat.sqrt_natCast] at hsqrt + exact ⟨Nat.sqrt N, by exact_mod_cast hsqrt⟩ + +/-- Two nonzero squarefree naturals whose product is a rational square are equal. -/ +lemma squarefree_eq_of_mul_is_rat_square {m n : ℕ} + (hm0 : m ≠ 0) (hn0 : n ≠ 0) (hm : Squarefree m) (hn : Squarefree n) + (h : ∃ q : ℚ, q * q = (m * n : ℕ)) : + m = n := by + obtain ⟨u, hu⟩ := exists_nat_mul_self_of_exists_rat_mul_self h + have hdvd (a b : ℕ) (ha : Squarefree a) + (hub : u * u = a * b) : a ∣ b := by + have ha_u_sq : a ∣ u ^ 2 := by + rw [pow_two, hub] + exact dvd_mul_right a b + have ha_u : a ∣ u := (ha.dvd_pow_iff_dvd (by decide : (2 : ℕ) ≠ 0)).mp ha_u_sq + obtain ⟨c, rfl⟩ := ha_u + have hac : a * (c * c) = b := by + apply Nat.mul_left_cancel + calc + a * (a * (c * c)) = (a * c) * (a * c) := by ring + _ = a * b := hub + exact ⟨c * c, hac.symm⟩ + exact Nat.dvd_antisymm + (hdvd m n hm hu) + (hdvd n m hn (by simpa [mul_comm] using hu)) + +/-- The sign character through which the Galois group acts on a chosen radical. -/ +noncomputable def radicalChar (S : Finset ℕ) (n : S) (hn : n.1 ≠ 0) : + (quadProduct S).Gal →* ℚ := by + let hv : root S n ≠ 0 := root_ne_zero S n hn + let horbit : ∀ σ : (quadProduct S).Gal, + σ • root S n = root S n ∨ σ • root S n = -root S n := by + intro σ + simpa only [AlgEquiv.smul_def] using gal_root_eq_or_neg S n σ + exact Eigencharacter.signHom (K := ℚ) (root S n) hv horbit + +lemma radicalChar_eigen (S : Finset ℕ) (n : S) (hn : n.1 ≠ 0) + (σ : (quadProduct S).Gal) : + σ • root S n = + algebraMap ℚ (RadicalField S) (radicalChar S n hn σ) * root S n := by + simp only [radicalChar] + exact Eigencharacter.signHom_eigen (K := ℚ) σ + +/-- Distinct nonzero squarefree radicands give distinct Galois sign characters. -/ +lemma radicalChar_injective (S : Finset ℕ) + (hpos : ∀ n ∈ S, n ≠ 0) (hsq : ∀ n ∈ S, Squarefree n) : + Injective (fun n : S => radicalChar S n (hpos n.1 n.2)) := by + letI : IsGalois ℚ (RadicalField S) := + IsGalois.of_separable_splitting_field (quadProduct_separable S hpos) + intro m n hχ + apply Subtype.ext + have hm0 : m.1 ≠ 0 := hpos m.1 m.2 + have hn0 : n.1 ≠ 0 := hpos n.1 n.2 + let hm_orbit : ∀ τ : (quadProduct S).Gal, + τ • root S m = root S m ∨ τ • root S m = -root S m := by + intro τ + simpa only [AlgEquiv.smul_def] using gal_root_eq_or_neg S m τ + let hn_orbit : ∀ τ : (quadProduct S).Gal, + τ • root S n = root S n ∨ τ • root S n = -root S n := by + intro τ + simpa only [AlgEquiv.smul_def] using gal_root_eq_or_neg S n τ + have hχ' : + Eigencharacter.signHom (K := ℚ) (root S m) (root_ne_zero S m hm0) hm_orbit = + Eigencharacter.signHom (K := ℚ) (root S n) (root_ne_zero S n hn0) hn_orbit := by + simpa [radicalChar] using hχ + have hfixed : ∀ σ : (quadProduct S).Gal, + σ (root S m * root S n) = root S m * root S n := by + intro σ + have hmul := Eigencharacter.fixed_mul_of_signHom_eq + (K := ℚ) (E := RadicalField S) (G := (quadProduct S).Gal) + (v := root S m) (w := root S n) + (hv := root_ne_zero S m hm0) (hw := root_ne_zero S n hn0) + (hv_orbit := hm_orbit) (hw_orbit := hn_orbit) hχ' σ + simpa only [AlgEquiv.smul_def] using hmul + have hrange : root S m * root S n ∈ Set.range (algebraMap ℚ (RadicalField S)) := + (IsGalois.mem_range_algebraMap_iff_fixed (root S m * root S n)).2 hfixed + obtain ⟨q, hq⟩ := hrange + have hq_sq : q * q = ((m.1 * n.1 : ℕ) : ℚ) := by + apply (algebraMap ℚ (RadicalField S)).injective + calc + algebraMap ℚ (RadicalField S) (q * q) + = (root S m * root S n) * (root S m * root S n) := by rw [map_mul, hq, hq] + _ = (root S m) ^ 2 * (root S n) ^ 2 := by ring + _ = algebraMap ℚ (RadicalField S) (m.1 : ℚ) * + algebraMap ℚ (RadicalField S) (n.1 : ℚ) := by rw [root_spec, root_spec] + _ = algebraMap ℚ (RadicalField S) (((m.1 * n.1 : ℕ) : ℚ)) := by norm_num + exact squarefree_eq_of_mul_is_rat_square hm0 hn0 (hsq m.1 m.2) (hsq n.1 n.2) + ⟨q, hq_sq⟩ + +/-- The chosen radicals attached to a finite family of distinct nonzero squarefree naturals +are linearly independent over the rationals. -/ +theorem root_linearIndependent (S : Finset ℕ) + (hpos : ∀ n ∈ S, n ≠ 0) (hsq : ∀ n ∈ S, Squarefree n) : + LinearIndependent ℚ (root S) := by + apply Eigencharacter.linearIndependent_of_eigencharacters + (K := ℚ) (E := RadicalField S) (G := (quadProduct S).Gal) + (v := root S) + · intro n + exact root_ne_zero S n (hpos n.1 n.2) + · exact fun n => radicalChar S n (hpos n.1 n.2) + · exact radicalChar_injective S hpos hsq + · intro n σ + exact radicalChar_eigen S n (hpos n.1 n.2) σ + +end SquarefreeRadicals From 92937cb03ef4fd06a616ce009c71a797efd5fff9 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:52:01 -0700 Subject: [PATCH 018/115] Import squarefree radical independence for A261865 --- FormalConjectures/OEIS/261865.lean | 1 + 1 file changed, 1 insertion(+) diff --git a/FormalConjectures/OEIS/261865.lean b/FormalConjectures/OEIS/261865.lean index b834725091..bd794d5e13 100644 --- a/FormalConjectures/OEIS/261865.lean +++ b/FormalConjectures/OEIS/261865.lean @@ -17,6 +17,7 @@ module public import FormalConjecturesUtil public import FormalConjecturesForMathlib.Analysis.Equidistribution.UnitAddTorus +public import FormalConjecturesForMathlib.NumberTheory.SquarefreeRadicals @[expose] public section From c8479769e569177a7337a5f5239fb0addabd0a40 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:56:59 -0700 Subject: [PATCH 019/115] Use trace proof for squarefree radical independence --- .../NumberTheory/SquarefreeRadicals.lean | 212 +----------------- 1 file changed, 1 insertion(+), 211 deletions(-) diff --git a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean index 1189aa4d7a..1653c547dd 100644 --- a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean +++ b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean @@ -15,214 +15,4 @@ limitations under the License. -/ module -import Mathlib.FieldTheory.PolynomialGaloisGroup -import FormalConjecturesForMathlib.LinearAlgebra.Eigencharacter -import Mathlib.Data.Nat.Squarefree -import Mathlib.Data.Rat.Sqrt -import Mathlib.LinearAlgebra.LinearIndependent.Lemmas - -open Finset Function Polynomial -open scoped BigOperators - -noncomputable section - -namespace SquarefreeRadicals - -/-- The quadratic polynomial whose roots are `±√n`. -/ -def quad (n : ℕ) : ℚ[X] := X ^ 2 - C (n : ℚ) - -/-- A product of the quadratic polynomials attached to a finite set. -/ -def quadProduct (S : Finset ℕ) : ℚ[X] := ∏ n ∈ S, quad n - -lemma quad_monic (n : ℕ) : (quad n).Monic := by - simpa [quad] using monic_X_pow_sub_C (n : ℚ) (by decide : (2 : ℕ) ≠ 0) - -lemma quad_ne_zero (n : ℕ) : quad n ≠ 0 := (quad_monic n).ne_zero - -lemma quadProduct_monic (S : Finset ℕ) : (quadProduct S).Monic := by - apply monic_prod_of_monic - intro n hn - exact quad_monic n - -lemma quadProduct_ne_zero (S : Finset ℕ) : quadProduct S ≠ 0 := (quadProduct_monic S).ne_zero - -lemma quad_isCoprime {m n : ℕ} (h : m ≠ n) : IsCoprime (quad m) (quad n) := by - let d : ℚ := (n : ℚ) - m - have hd : d ≠ 0 := by - dsimp [d] - exact sub_ne_zero.mpr (by exact_mod_cast h.symm) - refine ⟨C d⁻¹, -C d⁻¹, ?_⟩ - dsimp [quad, d] - field_simp [hd] - ring - -lemma quad_separable {n : ℕ} (hn : n ≠ 0) : (quad n).Separable := by - let u : ℚˣ := Units.mk0 (n : ℚ) (by exact_mod_cast hn) - have htwo : IsUnit (2 : ℚ) := isUnit_iff_ne_zero.mpr (by norm_num) - simpa [quad, u] using separable_X_pow_sub_C_unit u htwo - -lemma quadProduct_separable (S : Finset ℕ) (hpos : ∀ n ∈ S, n ≠ 0) : - (quadProduct S).Separable := by - apply separable_prod' - · intro m hm n hn hmn - exact quad_isCoprime hmn - · intro n hn - exact quad_separable (hpos n hn) - -lemma quad_dvd_quadProduct {S : Finset ℕ} {n : ℕ} (hn : n ∈ S) : - quad n ∣ quadProduct S := by - exact Finset.dvd_prod_of_mem (fun n => quad n) hn - -/-- The common splitting field of all quadratic polynomials in `S`. -/ -abbrev RadicalField (S : Finset ℕ) := (quadProduct S).SplittingField - -/-- Each quadratic factor splits in the common splitting field. -/ -lemma quad_splits (S : Finset ℕ) (n : S) : - ((quad n.1).map (algebraMap ℚ (RadicalField S))).Splits := by - have hP : ((quadProduct S).map (algebraMap ℚ (RadicalField S))).Splits := - Polynomial.SplittingField.splits (quadProduct S) - apply hP.of_dvd - · exact map_ne_zero (quadProduct_ne_zero S) - · rcases quad_dvd_quadProduct n.2 with ⟨r, hr⟩ - refine ⟨r.map (algebraMap ℚ (RadicalField S)), ?_⟩ - rw [← map_mul, hr] - -lemma quad_mapped_degree_ne_zero (S : Finset ℕ) (n : S) : - ((quad n.1).map (algebraMap ℚ (RadicalField S))).degree ≠ 0 := by - rw [(quad_monic n.1).degree_map] - simp [quad] - -/-- A chosen square root of each radicand inside the common splitting field. -/ -def root (S : Finset ℕ) (n : S) : RadicalField S := - Polynomial.rootOfSplits (quad_splits S n) (quad_mapped_degree_ne_zero S n) - -lemma root_spec (S : Finset ℕ) (n : S) : - root S n ^ 2 = algebraMap ℚ (RadicalField S) (n.1 : ℚ) := by - have h := Polynomial.eval_rootOfSplits (quad_splits S n) (quad_mapped_degree_ne_zero S n) - simpa [root, quad] using h - -lemma root_ne_zero (S : Finset ℕ) (n : S) (hn : n.1 ≠ 0) : root S n ≠ 0 := by - intro h - have hs := root_spec S n - rw [h, zero_pow (by decide : (2 : ℕ) ≠ 0)] at hs - exact (map_ne_zero (by exact_mod_cast hn)) hs.symm - -/-- Every Galois automorphism sends a chosen square root to itself or its negative. -/ -lemma gal_root_eq_or_neg (S : Finset ℕ) (n : S) - (σ : (quadProduct S).Gal) : - σ (root S n) = root S n ∨ σ (root S n) = -root S n := by - apply sq_eq_sq_iff_eq_or_eq_neg.mp - rw [map_pow, root_spec, root_spec] - simp - -/-- A rational square which is a natural number is already a natural square. -/ -lemma exists_nat_mul_self_of_exists_rat_mul_self {N : ℕ} - (h : ∃ q : ℚ, q * q = (N : ℚ)) : - ∃ u : ℕ, u * u = N := by - have hsqrt : Rat.sqrt (N : ℚ) * Rat.sqrt (N : ℚ) = (N : ℚ) := - (Rat.exists_mul_self (N : ℚ)).mp h - rw [Rat.sqrt_natCast] at hsqrt - exact ⟨Nat.sqrt N, by exact_mod_cast hsqrt⟩ - -/-- Two nonzero squarefree naturals whose product is a rational square are equal. -/ -lemma squarefree_eq_of_mul_is_rat_square {m n : ℕ} - (hm0 : m ≠ 0) (hn0 : n ≠ 0) (hm : Squarefree m) (hn : Squarefree n) - (h : ∃ q : ℚ, q * q = (m * n : ℕ)) : - m = n := by - obtain ⟨u, hu⟩ := exists_nat_mul_self_of_exists_rat_mul_self h - have hdvd (a b : ℕ) (ha : Squarefree a) - (hub : u * u = a * b) : a ∣ b := by - have ha_u_sq : a ∣ u ^ 2 := by - rw [pow_two, hub] - exact dvd_mul_right a b - have ha_u : a ∣ u := (ha.dvd_pow_iff_dvd (by decide : (2 : ℕ) ≠ 0)).mp ha_u_sq - obtain ⟨c, rfl⟩ := ha_u - have hac : a * (c * c) = b := by - apply Nat.mul_left_cancel - calc - a * (a * (c * c)) = (a * c) * (a * c) := by ring - _ = a * b := hub - exact ⟨c * c, hac.symm⟩ - exact Nat.dvd_antisymm - (hdvd m n hm hu) - (hdvd n m hn (by simpa [mul_comm] using hu)) - -/-- The sign character through which the Galois group acts on a chosen radical. -/ -noncomputable def radicalChar (S : Finset ℕ) (n : S) (hn : n.1 ≠ 0) : - (quadProduct S).Gal →* ℚ := by - let hv : root S n ≠ 0 := root_ne_zero S n hn - let horbit : ∀ σ : (quadProduct S).Gal, - σ • root S n = root S n ∨ σ • root S n = -root S n := by - intro σ - simpa only [AlgEquiv.smul_def] using gal_root_eq_or_neg S n σ - exact Eigencharacter.signHom (K := ℚ) (root S n) hv horbit - -lemma radicalChar_eigen (S : Finset ℕ) (n : S) (hn : n.1 ≠ 0) - (σ : (quadProduct S).Gal) : - σ • root S n = - algebraMap ℚ (RadicalField S) (radicalChar S n hn σ) * root S n := by - simp only [radicalChar] - exact Eigencharacter.signHom_eigen (K := ℚ) σ - -/-- Distinct nonzero squarefree radicands give distinct Galois sign characters. -/ -lemma radicalChar_injective (S : Finset ℕ) - (hpos : ∀ n ∈ S, n ≠ 0) (hsq : ∀ n ∈ S, Squarefree n) : - Injective (fun n : S => radicalChar S n (hpos n.1 n.2)) := by - letI : IsGalois ℚ (RadicalField S) := - IsGalois.of_separable_splitting_field (quadProduct_separable S hpos) - intro m n hχ - apply Subtype.ext - have hm0 : m.1 ≠ 0 := hpos m.1 m.2 - have hn0 : n.1 ≠ 0 := hpos n.1 n.2 - let hm_orbit : ∀ τ : (quadProduct S).Gal, - τ • root S m = root S m ∨ τ • root S m = -root S m := by - intro τ - simpa only [AlgEquiv.smul_def] using gal_root_eq_or_neg S m τ - let hn_orbit : ∀ τ : (quadProduct S).Gal, - τ • root S n = root S n ∨ τ • root S n = -root S n := by - intro τ - simpa only [AlgEquiv.smul_def] using gal_root_eq_or_neg S n τ - have hχ' : - Eigencharacter.signHom (K := ℚ) (root S m) (root_ne_zero S m hm0) hm_orbit = - Eigencharacter.signHom (K := ℚ) (root S n) (root_ne_zero S n hn0) hn_orbit := by - simpa [radicalChar] using hχ - have hfixed : ∀ σ : (quadProduct S).Gal, - σ (root S m * root S n) = root S m * root S n := by - intro σ - have hmul := Eigencharacter.fixed_mul_of_signHom_eq - (K := ℚ) (E := RadicalField S) (G := (quadProduct S).Gal) - (v := root S m) (w := root S n) - (hv := root_ne_zero S m hm0) (hw := root_ne_zero S n hn0) - (hv_orbit := hm_orbit) (hw_orbit := hn_orbit) hχ' σ - simpa only [AlgEquiv.smul_def] using hmul - have hrange : root S m * root S n ∈ Set.range (algebraMap ℚ (RadicalField S)) := - (IsGalois.mem_range_algebraMap_iff_fixed (root S m * root S n)).2 hfixed - obtain ⟨q, hq⟩ := hrange - have hq_sq : q * q = ((m.1 * n.1 : ℕ) : ℚ) := by - apply (algebraMap ℚ (RadicalField S)).injective - calc - algebraMap ℚ (RadicalField S) (q * q) - = (root S m * root S n) * (root S m * root S n) := by rw [map_mul, hq, hq] - _ = (root S m) ^ 2 * (root S n) ^ 2 := by ring - _ = algebraMap ℚ (RadicalField S) (m.1 : ℚ) * - algebraMap ℚ (RadicalField S) (n.1 : ℚ) := by rw [root_spec, root_spec] - _ = algebraMap ℚ (RadicalField S) (((m.1 * n.1 : ℕ) : ℚ)) := by norm_num - exact squarefree_eq_of_mul_is_rat_square hm0 hn0 (hsq m.1 m.2) (hsq n.1 n.2) - ⟨q, hq_sq⟩ - -/-- The chosen radicals attached to a finite family of distinct nonzero squarefree naturals -are linearly independent over the rationals. -/ -theorem root_linearIndependent (S : Finset ℕ) - (hpos : ∀ n ∈ S, n ≠ 0) (hsq : ∀ n ∈ S, Squarefree n) : - LinearIndependent ℚ (root S) := by - apply Eigencharacter.linearIndependent_of_eigencharacters - (K := ℚ) (E := RadicalField S) (G := (quadProduct S).Gal) - (v := root S) - · intro n - exact root_ne_zero S n (hpos n.1 n.2) - · exact fun n => radicalChar S n (hpos n.1 n.2) - · exact radicalChar_injective S hpos hsq - · intro n σ - exact radicalChar_eigen S n (hpos n.1 n.2) σ - -end SquarefreeRadicals +public import FormalConjecturesForMathlib.NumberTheory.SquarefreeRadical From 60b2650b9e3876b0b149acf4f0d01fd9b5433eb2 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:57:06 -0700 Subject: [PATCH 020/115] Remove superseded Galois character experiment --- .../LinearAlgebra/Eigencharacter.lean | 116 ------------------ 1 file changed, 116 deletions(-) delete mode 100644 FormalConjecturesForMathlib/LinearAlgebra/Eigencharacter.lean diff --git a/FormalConjecturesForMathlib/LinearAlgebra/Eigencharacter.lean b/FormalConjecturesForMathlib/LinearAlgebra/Eigencharacter.lean deleted file mode 100644 index 734054376a..0000000000 --- a/FormalConjecturesForMathlib/LinearAlgebra/Eigencharacter.lean +++ /dev/null @@ -1,116 +0,0 @@ -/- -Copyright 2026 The Formal Conjectures Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. --/ -module - -import Mathlib.LinearAlgebra.LinearIndependent.Basic -import Mathlib.LinearAlgebra.LinearIndependent.Lemmas - -open Function - -noncomputable section - -namespace Eigencharacter - -variable {K E G ι : Type*} - [Field K] [Field E] [Algebra K E] - [Group G] [MulSemiringAction G E] [SMulCommClass G K E] - -/-- Send an element to its orbit function under a group action. -/ -def orbit : E →ₗ[K] (G → E) where - toFun x g := g • x - map_add' x y := by ext g; exact smul_add _ _ _ - map_smul' c x := by ext g; exact smul_comm _ _ _ - -/-- Lift a base-field-valued multiplicative character to the extension field. -/ -def liftHom (χ : G →* K) : G →* E := - (algebraMap K E).comp χ - -lemma liftHom_injective : Injective (liftHom : (G →* K) → (G →* E)) := by - intro χ ψ h - ext g - apply (algebraMap K E).injective - exact DFunLike.congr_fun h g - -/-- Eigenvectors belonging to distinct base-field-valued characters are linearly independent. -/ -theorem linearIndependent_of_eigencharacters - (v : ι → E) (hv : ∀ i, v i ≠ 0) - (χ : ι → G →* K) (hχ : Injective χ) - (heig : ∀ i g, g • v i = algebraMap K E (χ i g) * v i) : - LinearIndependent K v := by - have hchar : LinearIndependent E (fun i => (liftHom (χ i) : G → E)) := - (linearIndependent_monoidHom G E).comp (fun i => liftHom (χ i)) - (liftHom_injective.comp hχ) - have hscaled : LinearIndependent E - ((fun i => Units.mk0 (v i) (hv i)) • - (fun i => (liftHom (χ i) : G → E))) := - hchar.units_smul (fun i => Units.mk0 (v i) (hv i)) - have horbitE : LinearIndependent E (fun i => orbit (K := K) (E := E) (G := G) (v i)) := by - convert hscaled using 1 - funext i g - simp only [Pi.smul_apply', Units.smul_def, liftHom, MonoidHom.comp_apply, orbit] - rw [heig i g] - ring - have horbitK : LinearIndependent K (fun i => orbit (K := K) (E := E) (G := G) (v i)) := - horbitE.restrict_scalars' K - exact LinearIndependent.of_comp (orbit (K := K) (E := E) (G := G)) horbitK - -variable [CharZero K] [CharZero E] - -/-- The ±1 character carried by a nonzero vector whose orbit is contained in `{v,-v}`. -/ -def signHom (v : E) (hv : v ≠ 0) (horbit : ∀ g : G, g • v = v ∨ g • v = -v) : - G →* K where - toFun g := if g • v = v then 1 else -1 - map_one' := by simp - map_mul' g h := by - have hneg : -v ≠ v := by - simpa only [CharZero.neg_eq_self_iff] using hv - rcases horbit g with hg | hg <;> - rcases horbit h with hh | hh <;> - simp [mul_smul, hg, hh, hneg] - -@[simp] lemma signHom_apply_eq_one {v : E} {hv horbit} (g : G) - (hg : g • v = v) : signHom (K := K) v hv horbit g = 1 := by - simp [signHom, hg] - -@[simp] lemma signHom_apply_eq_neg_one {v : E} {hv horbit} (g : G) - (hg : g • v = -v) : signHom (K := K) v hv horbit g = -1 := by - have hneg : -v ≠ v := by simpa only [CharZero.neg_eq_self_iff] using hv - simp [signHom, hg, hneg] - -lemma signHom_eigen {v : E} {hv horbit} (g : G) : - g • v = algebraMap K E (signHom (K := K) v hv horbit g) * v := by - rcases horbit g with hg | hg - · simp [hg] - · rw [signHom_apply_eq_neg_one (K := K) g hg] - simp [hg] - -lemma fixed_mul_of_signHom_eq {v w : E} {hv : v ≠ 0} {hw : w ≠ 0} - {hv_orbit : ∀ g : G, g • v = v ∨ g • v = -v} - {hw_orbit : ∀ g : G, g • w = w ∨ g • w = -w} - (hχ : signHom (K := K) v hv hv_orbit = signHom (K := K) w hw hw_orbit) - (g : G) : g • (v * w) = v * w := by - have hχg := DFunLike.congr_fun hχ g - rcases hv_orbit g with hvg | hvg <;> rcases hw_orbit g with hwg | hwg - · simp [smul_mul', hvg, hwg] - · have : (1 : K) = -1 := by - simpa [signHom, hvg, hwg, CharZero.neg_eq_self_iff, hv, hw] using hχg - exact (one_ne_neg_one (R := K) this).elim - · have : (-1 : K) = 1 := by - simpa [signHom, hvg, hwg, CharZero.neg_eq_self_iff, hv, hw] using hχg - exact (neg_one_ne_one (R := K) this).elim - · simp [smul_mul', hvg, hwg] - -end Eigencharacter From acfd9b3cfb248e0ab8c1d63ec1378033548650c1 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 05:57:25 -0700 Subject: [PATCH 021/115] Add reciprocal squarefree radical independence --- .../NumberTheory/SquarefreeRadicals.lean | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean index 1653c547dd..ac75af288e 100644 --- a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean +++ b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean @@ -16,3 +16,28 @@ limitations under the License. module public import FormalConjecturesForMathlib.NumberTheory.SquarefreeRadical + +@[expose] public section + +noncomputable section + +namespace Real + +/-- Reciprocal square roots of an injective finite family of squarefree naturals are +linearly independent over the rationals. -/ +theorem linearIndependent_inv_sqrt_squarefree {ι : Type*} [Fintype ι] + (s : ι → ℕ) (hs : ∀ i, Squarefree (s i)) (hinj : Function.Injective s) : + LinearIndependent ℚ (fun i => 1 / Real.sqrt (s i)) := by + have h := linearIndependent_sqrt_squarefree s hs hinj + let u : ι → ℚˣ := fun i => + Units.mk0 ((s i : ℚ)⁻¹) (inv_ne_zero (by exact_mod_cast (hs i).ne_zero)) + have hu := h.units_smul u + convert hu using 1 + funext i + have hpos : (0 : ℝ) < s i := by exact_mod_cast (Nat.pos_of_ne_zero (hs i).ne_zero) + have hsqrt : Real.sqrt (s i) ≠ 0 := (Real.sqrt_pos.2 hpos).ne' + simp only [Pi.smul_apply', Units.smul_def, u, Rat.smul_def] + rw [Rat.cast_inv, Rat.cast_natCast] + field_simp [hsqrt, Real.sq_sqrt hpos.le] + +end Real From cef9281168e87d2611e626836a06c134c2535e3d Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 06:02:28 -0700 Subject: [PATCH 022/115] Prove Weyl equidistribution for torus rotations --- .../Equidistribution/UnitAddTorus.lean | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean index f068a774b9..d684ff3b7d 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean @@ -16,6 +16,8 @@ limitations under the License. module public import Mathlib.Analysis.Fourier.AddCircleMulti +public import Mathlib.Algebra.Field.GeomSum +public import Mathlib.Analysis.SpecificLimits.Normed @[expose] public section @@ -140,4 +142,117 @@ theorem tendsto_average_of_tendsto_mFourier exact norm_add₃_le linarith [htri, h1, h2, hN0', hdist] +/-- There is no nontrivial integer relation among `a` and `1`. -/ +def NoIntegerRelation (a : d → ℝ) : Prop := + ∀ k : d → ℤ, (∃ z : ℤ, ∑ i, (k i : ℝ) * a i = z) → k = 0 + +/-- A multivariate Fourier monomial turns addition on the torus into multiplication. -/ +lemma mFourier_add_point (k : d → ℤ) (x y : UnitAddTorus d) : + mFourier k (x + y) = mFourier k x * mFourier k y := by + simp only [mFourier, ContinuousMap.coe_mk, Pi.add_apply, fourier_apply, add_zsmul, + AddCircle.toCircle_add, Circle.coe_mul, Finset.prod_mul_distrib] + +/-- A Fourier monomial along a rotation orbit is a geometric progression. -/ +lemma mFourier_nsmul (k : d → ℤ) (x : UnitAddTorus d) (n : ℕ) : + mFourier k (n • x) = (mFourier k x) ^ n := by + induction n with + | zero => simp [mFourier_zero] + | succ n ih => + rw [succ_nsmul, mFourier_add_point, ih, pow_succ] + +/-- A Fourier monomial is the canonical circle character evaluated on the corresponding +integer linear combination of the coordinates. -/ +lemma mFourier_eq_toCircle_sum (k : d → ℤ) (x : UnitAddTorus d) : + mFourier k x = + ((AddCircle.toCircle (∑ i, k i • x i) : Circle) : ℂ) := by + classical + simp only [mFourier, ContinuousMap.coe_mk, fourier_apply] + let s : Finset d := Finset.univ + change (∏ i ∈ s, ((AddCircle.toCircle (k i • x i) : Circle) : ℂ)) = _ + induction s using Finset.induction_on with + | empty => simp + | @insert a s ha ih => + rw [Finset.prod_insert ha, Finset.sum_insert ha, AddCircle.toCircle_add, + Circle.coe_mul, ih] + +/-- Under `NoIntegerRelation`, every nonconstant Fourier monomial is nontrivial on the +rotation vector. -/ +lemma mFourier_coe_ne_one {a : d → ℝ} (ha : NoIntegerRelation a) + {k : d → ℤ} (hk : k ≠ 0) : + mFourier k (fun i => (a i : UnitAddCircle)) ≠ 1 := by + intro h + have hcirc : + AddCircle.toCircle (∑ i, k i • (a i : UnitAddCircle)) = (1 : Circle) := by + apply Subtype.ext + simpa [mFourier_eq_toCircle_sum] using h + have hzero : (∑ i, k i • (a i : UnitAddCircle)) = 0 := by + apply AddCircle.injective_toCircle one_ne_zero + simpa using hcirc + have hzero' : ((∑ i, (k i : ℝ) * a i : ℝ) : UnitAddCircle) = 0 := by + simpa [zsmul_eq_mul] using hzero + obtain ⟨z, hz⟩ := AddCircle.coe_eq_zero_iff.mp hzero' + apply hk + apply ha k + exact ⟨z, by simpa [zsmul_eq_mul] using hz.symm⟩ + +/-- The Haar integral of a torus Fourier monomial is `1` at frequency zero and `0` +otherwise. -/ +lemma integral_mFourier (k : d → ℤ) : + ∫ x : UnitAddTorus d, mFourier k x = if k = 0 then 1 else 0 := by + have h := (orthonormal_iff_ite.mp (orthonormal_mFourier (d := d))) (0 : d → ℤ) k + simpa only [ContinuousMap.inner_toLp, mFourier_zero, ContinuousMap.one_apply, + map_one, one_mul, Pi.zero_apply, neg_zero, zero_add] using h + +/-- The Cesàro averages of a nontrivial unit-modulus geometric progression tend to zero. -/ +lemma tendsto_geom_average_zero {z : ℂ} (hz : z ≠ 1) (hnorm : ‖z‖ = 1) : + Tendsto (fun N : ℕ => (∑ n ∈ Finset.range N, z ^ n) / N) atTop (𝓝 0) := by + have hbound : ∀ N : ℕ, + ‖(∑ n ∈ Finset.range N, z ^ n) / N‖ ≤ + (2 / ‖z - 1‖) / (N : ℝ) := by + intro N + rw [geom_sum_eq hz, norm_div, norm_div, Complex.norm_natCast] + by_cases hN : N = 0 + · simp [hN] + have hden : 0 < ‖z - 1‖ := norm_pos_iff.mpr (sub_ne_zero.mpr hz) + have hNpos : (0 : ℝ) < N := by exact_mod_cast Nat.pos_of_ne_zero hN + rw [div_div] + apply div_le_div_of_nonneg_right _ hNpos.le + rw [div_le_iff₀ hden] + calc + ‖z ^ N - 1‖ ≤ ‖z ^ N‖ + ‖(1 : ℂ)‖ := norm_sub_le _ _ + _ = 2 := by simp [norm_pow, hnorm] + refine squeeze_zero_norm hbound ?_ + exact tendsto_const_nhds.div_atTop tendsto_natCast_atTop_atTop + +/-- Weyl equidistribution for a torus rotation whose coordinates, together with `1`, +have no nontrivial integer relation. -/ +theorem tendsto_average_rotation + (a : d → ℝ) (ha : NoIntegerRelation a) : + ∀ F : C(UnitAddTorus d, ℂ), + Tendsto + (fun N : ℕ => + (∑ n ∈ Finset.range N, F (n • (fun i => (a i : UnitAddCircle)))) / N) + atTop + (𝓝 (∫ x, F x)) := by + apply tendsto_average_of_tendsto_mFourier + (Y := fun n => n • (fun i => (a i : UnitAddCircle))) volume + intro k + by_cases hk : k = 0 + · subst k + have heq : + (fun N : ℕ => + (∑ n ∈ Finset.range N, + mFourier (0 : d → ℤ) (n • (fun i => (a i : UnitAddCircle)))) / N) =ᶠ[atTop] + fun _ => (1 : ℂ) := by + filter_upwards [eventually_gt_atTop 0] with N hN + simp [mFourier_zero, hN.ne'] + simpa [integral_mFourier] using tendsto_const_nhds.congr' heq.symm + · have hz : mFourier k (fun i => (a i : UnitAddCircle)) ≠ 1 := + mFourier_coe_ne_one ha hk + have hnorm : ‖mFourier k (fun i => (a i : UnitAddCircle))‖ = 1 := by + simpa using congrArg (fun f : C(UnitAddTorus d, ℂ) => ‖f‖) (rfl : mFourier k = mFourier k) + have hgeom := tendsto_geom_average_zero hz hnorm + rw [integral_mFourier, if_neg hk] + simpa only [mFourier_nsmul] using hgeom + end UnitAddTorus From 0a306b9144dd9700dd6061495bf2a883ea2ee85e Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 06:04:52 -0700 Subject: [PATCH 023/115] Fix Fourier mode norm calculation --- .../Analysis/Equidistribution/UnitAddTorus.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean index d684ff3b7d..3f559f766a 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean @@ -250,7 +250,7 @@ theorem tendsto_average_rotation · have hz : mFourier k (fun i => (a i : UnitAddCircle)) ≠ 1 := mFourier_coe_ne_one ha hk have hnorm : ‖mFourier k (fun i => (a i : UnitAddCircle))‖ = 1 := by - simpa using congrArg (fun f : C(UnitAddTorus d, ℂ) => ‖f‖) (rfl : mFourier k = mFourier k) + simp [mFourier, fourier_apply, norm_prod, Circle.norm_coe] have hgeom := tendsto_geom_average_zero hz hnorm rw [integral_mFourier, if_neg hk] simpa only [mFourier_nsmul] using hgeom From 64670b80c4ef4c926820a0c5a6d48db81cbc7541 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 06:11:12 -0700 Subject: [PATCH 024/115] Prove squarefree descent and reciprocal-radical independence --- FormalConjectures/OEIS/261865.lean | 96 ++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/FormalConjectures/OEIS/261865.lean b/FormalConjectures/OEIS/261865.lean index bd794d5e13..ef1c4ba7e4 100644 --- a/FormalConjectures/OEIS/261865.lean +++ b/FormalConjectures/OEIS/261865.lean @@ -137,11 +137,107 @@ theorem hits_square_mul_imp (c s n : ℕ) (hc : 0 < c) : · simpa only [hsqrt, Nat.cast_mul, mul_assoc] using hleft · simpa only [hsqrt, Nat.cast_mul, mul_assoc] using hright +/-- Every hit descends to a hit by a positive squarefree radicand no larger than the original. -/ +theorem exists_squarefree_hit_le (r n : ℕ) (hr : 0 < r) (hhit : Hits r n) : + ∃ s : ℕ, 0 < s ∧ s ≤ r ∧ Squarefree s ∧ Hits s n := by + induction r using Nat.strong_induction_on with + | h r ih => + by_cases hsq : Squarefree r + · exact ⟨r, hr, le_rfl, hsq, hhit⟩ + · rcases e : r.minSqFac with _ | d + · exact (hsq (Nat.squarefree_iff_minSqFac.mpr e)).elim + · have hdprime : d.Prime := Nat.minSqFac_prime e + obtain ⟨s, hrs⟩ := Nat.minSqFac_dvd e + have hdpos : 0 < d := hdprime.pos + have hspos : 0 < s := by + rw [hrs] at hr + positivity + have hslt : s < r := by + rw [hrs] + nlinarith [hdprime.two_le] + have hhit_s : Hits s n := by + apply hits_square_mul_imp d s n hdpos + simpa [pow_two, hrs] using hhit + obtain ⟨t, htpos, htle, htsq, hthit⟩ := ih s hslt hspos hhit_s + exact ⟨t, htpos, htle.trans hslt.le, htsq, hthit⟩ + /-- The squarefree integers in `[2, j)`. -/ noncomputable def squarefreeBelow (j : ℕ) : Finset ℕ := by classical exact (Finset.Ico 2 j).filter Squarefree +@[simp] theorem mem_squarefreeBelow {j s : ℕ} : + s ∈ squarefreeBelow j ↔ 2 ≤ s ∧ s < j ∧ Squarefree s := by + classical + simp [squarefreeBelow, and_assoc] + +/-- The squarefree radicands relevant to the value `j`, including `j` itself. -/ +noncomputable def relevantRadicands (j : ℕ) : Finset ℕ := + insert j (squarefreeBelow j) + +@[simp] theorem mem_relevantRadicands {j s : ℕ} : + s ∈ relevantRadicands j ↔ s = j ∨ (2 ≤ s ∧ s < j ∧ Squarefree s) := by + classical + simp [relevantRadicands] + +/-- Adjoin the rational coordinate `1` to a finite family of radicands. -/ +def radicandWithOne {S : Finset ℕ} : Option S → ℕ + | none => 1 + | some s => s.1 + +/-- Reciprocal radicals indexed by distinct squarefree integers at least two have no integer +relation modulo `1`. -/ +theorem noIntegerRelation_alpha (S : Finset ℕ) + (hge : ∀ s ∈ S, 2 ≤ s) (hsq : ∀ s ∈ S, Squarefree s) : + UnitAddTorus.NoIntegerRelation (fun s : S => alpha s.1) := by + let r : Option S → ℕ := radicandWithOne + have hr_sq : ∀ o, Squarefree (r o) := by + intro o + cases o with + | none => simp [r, radicandWithOne] + | some s => simpa [r, radicandWithOne] using hsq s.1 s.2 + have hr_inj : Function.Injective r := by + intro o₁ o₂ h + cases o₁ with + | none => + cases o₂ with + | none => rfl + | some s => + exfalso + have := hge s.1 s.2 + simp [r, radicandWithOne] at h + omega + | some s => + cases o₂ with + | none => + exfalso + have := hge s.1 s.2 + simp [r, radicandWithOne] at h + omega + | some t => + apply congrArg some + apply Subtype.ext + simpa [r, radicandWithOne] using h + have hli := Real.linearIndependent_inv_sqrt_squarefree r hr_sq hr_inj + intro k hk + obtain ⟨z, hz⟩ := hk + let c : Option S → ℚ + | none => -(z : ℚ) + | some s => (k s : ℚ) + have hsum : + ∑ o, c o • (1 / Real.sqrt (r o : ℝ)) = + ∑ o, (0 : ℚ) • (1 / Real.sqrt (r o : ℝ)) := by + rw [Fintype.sum_option] + simp only [c, r, radicandWithOne, Nat.cast_one, Real.sqrt_one, div_one, + Rat.smul_def, Rat.cast_neg, Rat.cast_intCast, neg_mul, mul_one, + zero_smul, Finset.sum_const_zero] + change -(z : ℝ) + ∑ s : S, (k s : ℝ) * alpha s.1 = 0 + linarith + have hc := (Fintype.linearIndependent_iffₛ.mp hli c (fun _ => 0) hsum) + funext s + have hs := hc (some s) + exact_mod_cast (by simpa [c] using hs) + /-- The density predicted for the value `j` in OEIS A261865. -/ noncomputable def predictedDensity (j : ℕ) : ℝ := alpha j * ∏ s ∈ squarefreeBelow j, (1 - alpha s) From df7be74be423481259c0f64c7784c578248258fc Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 06:15:22 -0700 Subject: [PATCH 025/115] Characterize A261865 values by squarefree coordinates --- FormalConjectures/OEIS/261865.lean | 49 ++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/FormalConjectures/OEIS/261865.lean b/FormalConjectures/OEIS/261865.lean index ef1c4ba7e4..3ac5f85bcd 100644 --- a/FormalConjectures/OEIS/261865.lean +++ b/FormalConjectures/OEIS/261865.lean @@ -120,6 +120,15 @@ theorem hits_iff_coordinateHit (s n : ℕ) (hs : 2 ≤ s) : apply (lt_div_iff₀ hsqrt_pos).mp convert hright using 1 <;> ring +/-- The radicand `1` never hits an open unit interval between consecutive integers. -/ +theorem not_hits_one (n : ℕ) : ¬ Hits 1 n := by + rintro ⟨m, _hm, hleft, hright⟩ + have hnm : n < m := by + exact_mod_cast (by simpa using hleft) + have hmn : m < n + 1 := by + exact_mod_cast (by simpa [Nat.cast_add, Nat.cast_one] using hright) + omega + /-- Removing a positive square factor from a radicand preserves the hitting property. Hence a nonsquarefree radicand can never be a genuinely new least @@ -180,6 +189,46 @@ noncomputable def relevantRadicands (j : ℕ) : Finset ℕ := classical simp [relevantRadicands] +/-- `j` is the least successful radicand exactly when it hits and every smaller squarefree +radicand at least two misses. -/ +theorem isValue_iff_squarefree_competitors (n j : ℕ) (hj : 2 ≤ j) : + IsValue n j ↔ + Hits j n ∧ ∀ s ∈ squarefreeBelow j, ¬ Hits s n := by + constructor + · rintro ⟨_hjpos, hjhit, hminimal⟩ + refine ⟨hjhit, ?_⟩ + intro s hs + have hs' := mem_squarefreeBelow.mp hs + exact hminimal s (lt_of_lt_of_le Nat.zero_lt_two hs'.1) hs'.2.1 + · rintro ⟨hjhit, hsmall⟩ + refine ⟨lt_of_lt_of_le Nat.zero_lt_two hj, hjhit, ?_⟩ + intro r hrpos hrj hrhit + obtain ⟨s, hspos, hsr, hssq, hshit⟩ := exists_squarefree_hit_le r n hrpos hrhit + have hsne : s ≠ 1 := by + intro hs1 + subst s + exact not_hits_one n hshit + have hsge : 2 ≤ s := by omega + have hslt : s < j := lt_of_le_of_lt hsr hrj + exact hsmall s (mem_squarefreeBelow.mpr ⟨hsge, hslt, hssq⟩) hshit + +/-- Fractional-part version of `isValue_iff_squarefree_competitors`. -/ +theorem isValue_iff_coordinateConditions (n j : ℕ) (hj : 2 ≤ j) : + IsValue n j ↔ + CoordinateHit j n ∧ ∀ s ∈ squarefreeBelow j, ¬ CoordinateHit s n := by + rw [isValue_iff_squarefree_competitors n j hj, hits_iff_coordinateHit j n hj] + constructor + · rintro ⟨hjhit, hsmall⟩ + refine ⟨hjhit, ?_⟩ + intro s hs hscoord + have hsge := (mem_squarefreeBelow.mp hs).1 + exact hsmall s hs ((hits_iff_coordinateHit s n hsge).mpr hscoord) + · rintro ⟨hjhit, hsmall⟩ + refine ⟨hjhit, ?_⟩ + intro s hs hshit + have hsge := (mem_squarefreeBelow.mp hs).1 + exact hsmall s hs ((hits_iff_coordinateHit s n hsge).mp hshit) + /-- Adjoin the rational coordinate `1` to a finite family of radicands. -/ def radicandWithOne {S : Finset ℕ} : Option S → ℕ | none => 1 From b2caf394805737a5ac35fb131b15c10433e9b05d Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 06:25:01 -0700 Subject: [PATCH 026/115] Add empirical probability bridge for torus rotations --- .../EmpiricalProbability.lean | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 FormalConjecturesForMathlib/Analysis/Equidistribution/EmpiricalProbability.lean diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/EmpiricalProbability.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/EmpiricalProbability.lean new file mode 100644 index 0000000000..0d33922423 --- /dev/null +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/EmpiricalProbability.lean @@ -0,0 +1,107 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +public import FormalConjecturesForMathlib.Analysis.Equidistribution.UnitAddTorus +public import Mathlib.MeasureTheory.Measure.Portmanteau + +@[expose] public section + +/-! +# Empirical probability measures on a finite torus + +This file packages the measure-theoretic bridge used after Weyl's criterion. +The empirical measure of the first `N + 1` points of a sequence is a genuine +probability measure, and convergence of all continuous empirical averages +implies weak convergence of these empirical measures. +-/ + +noncomputable section + +open Filter MeasureTheory Set Topology +open scoped BigOperators ENNReal NNReal Topology + +namespace UnitAddTorus + +variable {d : Type*} [Fintype d] + +/-- The uniform empirical probability measure on `Y 0, ..., Y N`. -/ +def empiricalProbability (Y : ℕ → UnitAddTorus d) (N : ℕ) : + ProbabilityMeasure (UnitAddTorus d) := + ⟨((N + 1 : ℕ) : ℝ≥0∞)⁻¹ • + ∑ n ∈ Finset.range (N + 1), Measure.dirac (Y n), by + rw [isProbabilityMeasure_iff] + simp [Measure.smul_apply, ENNReal.inv_mul_cancel]⟩ + +/-- Integrating against the empirical probability measure is the finite +arithmetic average over the orbit segment. -/ +theorem integral_empiricalProbability (Y : ℕ → UnitAddTorus d) (N : ℕ) + (F : C(UnitAddTorus d, ℂ)) : + ∫ x, F x ∂(empiricalProbability Y N : Measure (UnitAddTorus d)) = + (∑ n ∈ Finset.range (N + 1), F (Y n)) / (N + 1) := by + classical + rw [empiricalProbability, integral_smul_measure] + rw [integral_finset_sum_measure] + · simp only [integral_dirac] + simp [div_eq_mul_inv, smul_eq_mul, mul_comm] + · intro n hn + exact integrable_dirac (by simp) + +/-- The mass assigned by the empirical probability measure to a measurable +set is its relative frequency in the orbit segment. -/ +theorem empiricalProbability_apply (Y : ℕ → UnitAddTorus d) (N : ℕ) + {s : Set (UnitAddTorus d)} (hs : MeasurableSet s) : + (empiricalProbability Y N : Measure (UnitAddTorus d)) s = + (((Finset.range (N + 1)).filter fun n => Y n ∈ s).card : ℝ≥0∞) / + (N + 1) := by + classical + simp [empiricalProbability, Measure.smul_apply, hs, div_eq_mul_inv] + +/-- If every continuous empirical average converges to its Haar integral, +then the empirical probability measures converge weakly to Haar measure. -/ +theorem tendsto_empiricalProbability_of_tendsto_average + (Y : ℕ → UnitAddTorus d) + (havg : ∀ F : C(UnitAddTorus d, ℂ), + Tendsto + (fun N : ℕ => (∑ n ∈ Finset.range N, F (Y n)) / N) + atTop + (𝓝 (∫ x, F x))) : + Tendsto (empiricalProbability Y) atTop + (𝓝 (⟨volume, inferInstance⟩ : ProbabilityMeasure (UnitAddTorus d))) := by + rw [ProbabilityMeasure.tendsto_iff_forall_integral_rclike_tendsto ℂ] + intro f + let F : C(UnitAddTorus d, ℂ) := + (ContinuousMap.equivBoundedOfCompact (UnitAddTorus d) ℂ).symm f + have hsucc : Tendsto (fun N : ℕ => N + 1) atTop atTop := by + refine tendsto_atTop.2 fun b => ⟨b, ?_⟩ + intro a ha + exact ha.trans (Nat.le_add_right a 1) + have h := (havg F).comp hsucc + simpa [integral_empiricalProbability, F] using h + +/-- The empirical probability measures of a torus rotation with no integer +relation converge weakly to Haar probability measure. -/ +theorem tendsto_empiricalProbability_rotation + (a : d → ℝ) (ha : NoIntegerRelation a) : + Tendsto + (empiricalProbability + (fun n => n • (fun i => (a i : UnitAddCircle)))) + atTop + (𝓝 (⟨volume, inferInstance⟩ : ProbabilityMeasure (UnitAddTorus d))) := + tendsto_empiricalProbability_of_tendsto_average _ + (tendsto_average_rotation a ha) + +end UnitAddTorus From e6c1615e92fde374f4979d9a8854c4c9491b1eda Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 06:28:00 -0700 Subject: [PATCH 027/115] Add measurable arc geometry on the unit additive circle --- .../Equidistribution/UnitAddCircleArc.lean | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddCircleArc.lean diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddCircleArc.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddCircleArc.lean new file mode 100644 index 0000000000..1ffe171124 --- /dev/null +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddCircleArc.lean @@ -0,0 +1,124 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +public import Mathlib.MeasureTheory.Integral.IntervalIntegral.Periodic + +@[expose] public section + +/-! +# Short terminal arcs on the unit additive circle + +For `0 < a < 1`, the arc represented by the real interval `(1-a, 1)` is open, +its endpoint closure is represented by `[1-a, 1]`, and both have normalized +Haar measure `a`. +-/ + +noncomputable section + +open MeasureTheory Set Topology +open scoped ENNReal NNReal Topology + +namespace UnitAddCircle + +/-- The open terminal arc of length `a` in `ℝ / ℤ`. -/ +def openArc (a : ℝ) : Set UnitAddCircle := + ((↑) : ℝ → UnitAddCircle) '' Ioo (1 - a) 1 + +/-- The closed endpoint hull of `openArc a`. -/ +def closedArc (a : ℝ) : Set UnitAddCircle := + ((↑) : ℝ → UnitAddCircle) '' Icc (1 - a) 1 + +private theorem coe_eq_coe_iff_of_mem_Ioc {x y : ℝ} + (hx : x ∈ Ioc (0 : ℝ) 1) (hy : y ∈ Ioc (0 : ℝ) 1) : + (x : UnitAddCircle) = (y : UnitAddCircle) ↔ x = y := by + constructor + · intro h + have h' := congrArg (AddCircle.equivIoc (1 : ℝ) 0) h + rw [AddCircle.equivIoc_coe_eq hx, AddCircle.equivIoc_coe_eq hy] at h' + exact congrArg Subtype.val h' + · rintro rfl + rfl + +/-- `openArc a` is open. -/ +theorem isOpen_openArc (a : ℝ) : IsOpen (openArc a) := + QuotientAddGroup.isOpenMap_coe isOpen_Ioo + +/-- `closedArc a` is closed. -/ +theorem isClosed_closedArc (a : ℝ) : IsClosed (closedArc a) := + (isCompact_Icc.image (AddCircle.continuous_mk' (1 : ℝ))).isClosed + +/-- The open arc is contained in its endpoint closure. -/ +theorem openArc_subset_closedArc (a : ℝ) : openArc a ⊆ closedArc a := + image_mono Ioo_subset_Icc_self + +private theorem preimage_openArc_inter_Ioc {a : ℝ} (ha : a < 1) : + ((↑) : ℝ → UnitAddCircle) ⁻¹' openArc a ∩ Ioc 0 1 = Ioo (1 - a) 1 := by + ext x + constructor + · rintro ⟨⟨y, hy, hxy⟩, hx⟩ + have hyIoc : y ∈ Ioc (0 : ℝ) 1 := + ⟨(sub_pos.mpr ha).trans hy.1, hy.2.le⟩ + have hxy' : y = x := + (coe_eq_coe_iff_of_mem_Ioc hyIoc hx).mp hxy + simpa [hxy'] using hy + · intro hx + refine ⟨⟨x, hx, rfl⟩, ?_⟩ + exact ⟨(sub_pos.mpr ha).trans hx.1, hx.2.le⟩ + +private theorem preimage_closedArc_inter_Ioc {a : ℝ} (ha : a < 1) : + ((↑) : ℝ → UnitAddCircle) ⁻¹' closedArc a ∩ Ioc 0 1 = Icc (1 - a) 1 := by + ext x + constructor + · rintro ⟨⟨y, hy, hxy⟩, hx⟩ + have hyIoc : y ∈ Ioc (0 : ℝ) 1 := + ⟨(sub_pos.mpr ha).trans_le hy.1, hy.2⟩ + have hxy' : y = x := + (coe_eq_coe_iff_of_mem_Ioc hyIoc hx).mp hxy + simpa [hxy'] using hy + · intro hx + refine ⟨⟨x, hx, rfl⟩, ?_⟩ + exact ⟨(sub_pos.mpr ha).trans_le hx.1, hx.2⟩ + +/-- The open terminal arc has Haar measure `a`. -/ +theorem volume_openArc {a : ℝ} (ha0 : 0 ≤ a) (ha1 : a < 1) : + volume (openArc a) = ENNReal.ofReal a := by + rw [AddCircle.add_projection_respects_measure (1 : ℝ) 0 + (isOpen_openArc a).measurableSet] + rw [preimage_openArc_inter_Ioc ha1, Real.volume_Ioo] + congr 1 + ring + +/-- Adding the two endpoints does not change the Haar measure. -/ +theorem volume_closedArc {a : ℝ} (ha0 : 0 ≤ a) (ha1 : a < 1) : + volume (closedArc a) = ENNReal.ofReal a := by + rw [AddCircle.add_projection_respects_measure (1 : ℝ) 0 + (isClosed_closedArc a).measurableSet] + rw [preimage_closedArc_inter_Ioc ha1, Real.volume_Icc] + congr 1 + ring + +/-- The two endpoint conventions are equal almost everywhere. -/ +theorem openArc_ae_eq_closedArc {a : ℝ} (ha0 : 0 ≤ a) (ha1 : a < 1) : + openArc a =ᵐ[volume] closedArc a := by + apply EventuallyLE.antisymm (openArc_subset_closedArc a).eventuallyLE + rw [ae_le_set] + exact measure_mono_null (diff_subset_iff.mpr (openArc_subset_closedArc a)) <| by + rw [measure_diff (isOpen_openArc a).measurableSet (measure_ne_top _ _), + volume_closedArc ha0 ha1, volume_openArc ha0 ha1] + simp + +end UnitAddCircle From 16cfbd623be2cb3401d40ea389e61919d64680e9 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 06:29:24 -0700 Subject: [PATCH 028/115] Add finite torus rectangle geometry --- .../UnitAddTorusRectangle.lean | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorusRectangle.lean diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorusRectangle.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorusRectangle.lean new file mode 100644 index 0000000000..2432476bb2 --- /dev/null +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorusRectangle.lean @@ -0,0 +1,71 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +public import FormalConjecturesForMathlib.Analysis.Equidistribution.UnitAddCircleArc +public import Mathlib.MeasureTheory.Constructions.Pi + +@[expose] public section + +/-! +# Rectangles in a finite unit torus + +A coordinate rectangle in a finite product is open or closed when every side +is, and its product Haar measure is the product of the side measures. +-/ + +noncomputable section + +open MeasureTheory Set Topology +open scoped BigOperators ENNReal NNReal Topology + +namespace UnitAddTorus + +variable {d : Type*} [Fintype d] + +/-- The coordinate rectangle with side `B i` in coordinate `i`. -/ +def rectangle (B : d → Set UnitAddCircle) : Set (UnitAddTorus d) := + Set.pi Set.univ B + +private theorem rectangle_eq_iInter (B : d → Set UnitAddCircle) : + rectangle B = ⋂ i, (fun x : UnitAddTorus d => x i) ⁻¹' B i := by + ext x + simp [rectangle] + +/-- A finite product of open sides is open. -/ +theorem isOpen_rectangle {B : d → Set UnitAddCircle} (hB : ∀ i, IsOpen (B i)) : + IsOpen (rectangle B) := by + rw [rectangle_eq_iInter] + exact isOpen_iInter_of_finite fun i => (hB i).preimage (continuous_apply i) + +/-- A finite product of closed sides is closed. -/ +theorem isClosed_rectangle {B : d → Set UnitAddCircle} (hB : ∀ i, IsClosed (B i)) : + IsClosed (rectangle B) := by + rw [rectangle_eq_iInter] + exact isClosed_iInter fun i => (hB i).preimage (continuous_apply i) + +/-- Coordinatewise inclusion gives inclusion of rectangles. -/ +theorem rectangle_mono {A B : d → Set UnitAddCircle} (h : ∀ i, A i ⊆ B i) : + rectangle A ⊆ rectangle B := + Set.pi_mono fun i _ => h i + +/-- Haar measure of a finite torus rectangle is the product of the side measures. -/ +theorem volume_rectangle (B : d → Set UnitAddCircle) : + volume (rectangle B) = ∏ i, volume (B i) := by + simpa [rectangle] using + (Measure.pi_pi (fun _ : d => (volume : Measure UnitAddCircle)) B) + +end UnitAddTorus From 167174dfd15a448a5993ddf4674863ae84aed164 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 06:30:25 -0700 Subject: [PATCH 029/115] Relate circle arcs to fractional parts --- .../Equidistribution/UnitAddCircleArc.lean | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddCircleArc.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddCircleArc.lean index 1ffe171124..292decb2c7 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddCircleArc.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddCircleArc.lean @@ -53,6 +53,13 @@ private theorem coe_eq_coe_iff_of_mem_Ioc {x y : ℝ} · rintro rfl rfl +private theorem coe_fract (x : ℝ) : + ((Int.fract x : ℝ) : UnitAddCircle) = (x : UnitAddCircle) := by + apply (AddCircle.equivIco (1 : ℝ) 0).injective + apply Subtype.ext + rw [AddCircle.equivIco_coe_eq (Int.fract_mem x)] + simpa using AddCircle.coe_equivIco_mk_apply (p := (1 : ℝ)) x + /-- `openArc a` is open. -/ theorem isOpen_openArc (a : ℝ) : IsOpen (openArc a) := QuotientAddGroup.isOpenMap_coe isOpen_Ioo @@ -65,6 +72,22 @@ theorem isClosed_closedArc (a : ℝ) : IsClosed (closedArc a) := theorem openArc_subset_closedArc (a : ℝ) : openArc a ⊆ closedArc a := image_mono Ioo_subset_Icc_self +/-- Membership of a real point in the terminal arc is exactly the corresponding +fractional-part inequality. -/ +theorem coe_mem_openArc_iff {a x : ℝ} (ha : a < 1) : + ((x : UnitAddCircle) ∈ openArc a) ↔ 1 - a < Int.fract x := by + constructor + · rintro ⟨y, hy, hxy⟩ + have hyIco : y ∈ Ico (0 : ℝ) 1 := + ⟨(sub_nonneg.mpr ha.le).trans hy.1.le, hy.2⟩ + have hfrIco : Int.fract x ∈ Ico (0 : ℝ) 1 := Int.fract_mem x + have hyfr : y = Int.fract x := + (AddCircle.coe_eq_coe_iff_of_mem_Ico hyIco hfrIco).mp + (hxy.trans (coe_fract x).symm) + simpa [hyfr] using hy.1 + · intro hx + exact ⟨Int.fract x, ⟨hx, Int.fract_lt_one x⟩, coe_fract x⟩ + private theorem preimage_openArc_inter_Ioc {a : ℝ} (ha : a < 1) : ((↑) : ℝ → UnitAddCircle) ⁻¹' openArc a ∩ Ioc 0 1 = Ioo (1 - a) 1 := by ext x From 25e147e5869bfdb8adfbe66eea615a38b9df95da Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 06:35:56 -0700 Subject: [PATCH 030/115] Add real-valued Haar measures for circle arcs --- .../UnitAddCircleArcReal.lean | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddCircleArcReal.lean diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddCircleArcReal.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddCircleArcReal.lean new file mode 100644 index 0000000000..01040f796f --- /dev/null +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddCircleArcReal.lean @@ -0,0 +1,56 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +public import FormalConjecturesForMathlib.Analysis.Equidistribution.UnitAddCircleArc +public import Mathlib.MeasureTheory.Measure.Real + +@[expose] public section + +noncomputable section + +open MeasureTheory Set Topology +open scoped ENNReal NNReal Topology + +namespace UnitAddCircle + +/-- Real Haar measure of the open terminal arc. -/ +theorem volumeReal_openArc {a : ℝ} (ha0 : 0 ≤ a) (ha1 : a < 1) : + (volume : Measure UnitAddCircle).real (openArc a) = a := by + rw [Measure.real, volume_openArc ha0 ha1, ENNReal.toReal_ofReal ha0] + +/-- Real Haar measure of the closed terminal arc. -/ +theorem volumeReal_closedArc {a : ℝ} (ha0 : 0 ≤ a) (ha1 : a < 1) : + (volume : Measure UnitAddCircle).real (closedArc a) = a := by + rw [Measure.real, volume_closedArc ha0 ha1, ENNReal.toReal_ofReal ha0] + +/-- Real Haar measure of the complement of the open terminal arc. -/ +theorem volumeReal_compl_openArc {a : ℝ} (ha0 : 0 ≤ a) (ha1 : a < 1) : + (volume : Measure UnitAddCircle).real (openArc a)ᶜ = 1 - a := by + have h := measureReal_add_measureReal_compl + (μ := (volume : Measure UnitAddCircle)) (isOpen_openArc a).measurableSet + rw [volumeReal_openArc ha0 ha1, probReal_univ] at h + linarith + +/-- Real Haar measure of the complement of the closed terminal arc. -/ +theorem volumeReal_compl_closedArc {a : ℝ} (ha0 : 0 ≤ a) (ha1 : a < 1) : + (volume : Measure UnitAddCircle).real (closedArc a)ᶜ = 1 - a := by + have h := measureReal_add_measureReal_compl + (μ := (volume : Measure UnitAddCircle)) (isClosed_closedArc a).measurableSet + rw [volumeReal_closedArc ha0 ha1, probReal_univ] at h + linarith + +end UnitAddCircle From cdf94edf4376988c3dd5fb08d1a0af9942cc3eb2 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 06:36:17 -0700 Subject: [PATCH 031/115] Add real-valued Haar measure for torus rectangles --- .../UnitAddTorusRectangleReal.lean | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorusRectangleReal.lean diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorusRectangleReal.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorusRectangleReal.lean new file mode 100644 index 0000000000..bccf9f9d70 --- /dev/null +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorusRectangleReal.lean @@ -0,0 +1,41 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +public import FormalConjecturesForMathlib.Analysis.Equidistribution.UnitAddTorusRectangle +public import Mathlib.MeasureTheory.Measure.Real + +@[expose] public section + +noncomputable section + +open MeasureTheory Set Topology +open scoped BigOperators ENNReal NNReal Topology + +namespace UnitAddTorus + +variable {d : Type*} [Fintype d] + +/-- Real Haar measure of a finite torus rectangle is the product of the real +Haar measures of its sides. -/ +theorem volumeReal_rectangle (B : d → Set UnitAddCircle) : + (volume : Measure (UnitAddTorus d)).real (rectangle B) = + ∏ i, (volume : Measure UnitAddCircle).real (B i) := by + rw [Measure.real, volume_rectangle] + rw [ENNReal.toReal_prod] + rfl + +end UnitAddTorus From 42352827853b6859c882dcd19a2fe9578a3eecaf Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 06:39:54 -0700 Subject: [PATCH 032/115] Add empirical-measure density transfer --- .../MeasureTheory/Probability/Empirical.lean | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean diff --git a/FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean b/FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean new file mode 100644 index 0000000000..0be2fb5491 --- /dev/null +++ b/FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean @@ -0,0 +1,165 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +public import Mathlib.MeasureTheory.Measure.Portmanteau +public import Mathlib.Probability.Distributions.Uniform +public import Mathlib.Probability.ProbabilityMassFunction.Integrals +public import FormalConjecturesForMathlib.Data.Set.Density + +@[expose] public section + +open Filter MeasureTheory Set Topology +open scoped ENNReal NNReal Topology BigOperators + +noncomputable section + +namespace MeasureTheory + +variable {Ω : Type*} [MeasurableSpace Ω] + +/-- The empirical probability measure of the first `N` values of a sequence. +At `N = 0` we use a harmless Dirac measure. -/ +def empiricalProbabilityMeasure (Y : ℕ → Ω) (N : ℕ) : ProbabilityMeasure Ω := by + classical + by_cases hN : N = 0 + · exact ⟨Measure.dirac (Y 0), Measure.dirac.isProbabilityMeasure⟩ + · let p : PMF ℕ := PMF.uniformOfFinset (Finset.range N) + (Finset.range_nonempty.mpr (Nat.pos_of_ne_zero hN)) + let ν : ProbabilityMeasure ℕ := ⟨p.toMeasure, inferInstance⟩ + exact ν.map (measurable_of_countable Y).aemeasurable + +lemma empiricalProbabilityMeasure_ne_zero (Y : ℕ → Ω) {N : ℕ} (hN : N ≠ 0) : + empiricalProbabilityMeasure Y N = + (⟨(PMF.uniformOfFinset (Finset.range N) + (Finset.range_nonempty.mpr (Nat.pos_of_ne_zero hN))).toMeasure, + inferInstance⟩ : ProbabilityMeasure ℕ).map + (measurable_of_countable Y).aemeasurable := by + simp [empiricalProbabilityMeasure, hN] + +variable [TopologicalSpace Ω] [BorelSpace Ω] + +/-- Integration against the empirical measure is the corresponding finite average. -/ +theorem integral_empiricalProbabilityMeasure + (Y : ℕ → Ω) {N : ℕ} (hN : N ≠ 0) (f : Ω →ᵇ ℂ) : + ∫ x, f x ∂(empiricalProbabilityMeasure Y N : ProbabilityMeasure Ω) = + (∑ n ∈ Finset.range N, f (Y n)) / (N : ℂ) := by + classical + rw [empiricalProbabilityMeasure_ne_zero Y hN] + let p : PMF ℕ := PMF.uniformOfFinset (Finset.range N) + (Finset.range_nonempty.mpr (Nat.pos_of_ne_zero hN)) + have hY : Measurable Y := measurable_of_countable Y + rw [ProbabilityMeasure.toMeasure_map] + rw [integral_map hY.aemeasurable f.continuous.aestronglyMeasurable] + have hfint : Integrable (fun n => f (Y n)) p.toMeasure := by + refine (integrable_const ‖f‖).mono ?_ ?_ + · exact (measurable_of_countable (fun n => f (Y n))).aestronglyMeasurable + · exact Filter.Eventually.of_forall fun n => f.norm_coe_le_norm (Y n) + rw [PMF.integral_eq_tsum p (fun n => f (Y n)) hfint] + rw [tsum_eq_sum (s := Finset.range N)] + · calc + (∑ n ∈ Finset.range N, (p n).toReal • f (Y n)) = + ∑ n ∈ Finset.range N, ((N : ℝ)⁻¹ : ℝ) • f (Y n) := by + apply Finset.sum_congr rfl + intro n hn + simp [p, PMF.uniformOfFinset_apply, hn, hN] + _ = ((N : ℝ)⁻¹ : ℝ) • ∑ n ∈ Finset.range N, f (Y n) := by + rw [Finset.smul_sum] + _ = (∑ n ∈ Finset.range N, f (Y n)) / (N : ℂ) := by + rw [RCLike.real_smul_eq_coe_mul] + push_cast + field_simp [hN] + · intro n hn + simp [p, PMF.uniformOfFinset_apply, hn] + +/-- The mass of a measurable set under an empirical measure is its finite frequency. -/ +theorem empiricalProbabilityMeasure_apply (Y : ℕ → Ω) {N : ℕ} (hN : N ≠ 0) + {A : Set Ω} (hA : MeasurableSet A) : + empiricalProbabilityMeasure Y N A = + (((Finset.range N).filter fun n => Y n ∈ A).card : ℝ≥0) / N := by + classical + rw [empiricalProbabilityMeasure_ne_zero Y hN] + rw [ProbabilityMeasure.map_apply] + · change (((PMF.uniformOfFinset (Finset.range N) + (Finset.range_nonempty.mpr (Nat.pos_of_ne_zero hN))).toMeasure + (Y ⁻¹' A)).toNNReal) = _ + rw [PMF.toMeasure_uniformOfFinset_apply] + · norm_num [ENNReal.toNNReal_div, Finset.filter_filter, and_comm] + · exact (measurable_of_countable Y) hA + · exact hA + +variable [CompactSpace Ω] [PseudoMetricSpace Ω] + +/-- Continuous-test-function convergence of finite orbit averages gives weak convergence of the +empirical probability measures. -/ +theorem tendsto_empiricalProbabilityMeasure + (Y : ℕ → Ω) (μ : ProbabilityMeasure Ω) + (havg : ∀ F : C(Ω, ℂ), + Tendsto (fun N : ℕ => (∑ n ∈ Finset.range N, F (Y n)) / (N : ℂ)) + atTop (𝓝 (∫ x, F x ∂(μ : Measure Ω)))) : + Tendsto (empiricalProbabilityMeasure Y) atTop (𝓝 μ) := by + rw [ProbabilityMeasure.tendsto_iff_forall_integral_rclike_tendsto ℂ] + intro f + have h := havg ⟨f, f.continuous⟩ + apply h.congr' + filter_upwards [eventually_ne_atTop 0] with N hN + exact integral_empiricalProbabilityMeasure Y hN f + +/-- The finite frequency of a continuity set converges to its limiting probability. -/ +theorem tendsto_frequency_of_null_frontier + (Y : ℕ → Ω) (μ : ProbabilityMeasure Ω) + (havg : ∀ F : C(Ω, ℂ), + Tendsto (fun N : ℕ => (∑ n ∈ Finset.range N, F (Y n)) / (N : ℂ)) + atTop (𝓝 (∫ x, F x ∂(μ : Measure Ω)))) + {A : Set Ω} (hA : MeasurableSet A) (hfront : μ (frontier A) = 0) : + Tendsto + (fun N : ℕ => + (((Finset.range N).filter fun n => Y n ∈ A).card : ℝ) / N) + atTop (𝓝 ((μ A : ℝ≥0) : ℝ)) := by + have hweak := tendsto_empiricalProbabilityMeasure Y μ havg + have hport := ProbabilityMeasure.tendsto_measure_of_null_frontier_of_tendsto hweak hfront + have hcoe := (NNReal.continuous_coe.tendsto (μ A)).comp hport + apply hcoe.congr' + filter_upwards [eventually_ne_atTop 0] with N hN + rw [empiricalProbabilityMeasure_apply Y hN hA] + norm_num [NNReal.coe_div] + +/-- A continuity-set frequency theorem expressed in the `Set.HasDensity` API. -/ +theorem hasDensity_of_tendsto_average + (Y : ℕ → Ω) (μ : ProbabilityMeasure Ω) + (havg : ∀ F : C(Ω, ℂ), + Tendsto (fun N : ℕ => (∑ n ∈ Finset.range N, F (Y n)) / (N : ℂ)) + atTop (𝓝 (∫ x, F x ∂(μ : Measure Ω)))) + {A : Set Ω} (hA : MeasurableSet A) (hfront : μ (frontier A) = 0) + (S : Set ℕ) (hS : ∀ n, n ∈ S ↔ Y n ∈ A) : + S.HasDensity ((μ A : ℝ≥0) : ℝ) := by + have hfreq := tendsto_frequency_of_null_frontier Y μ havg hA hfront + rw [Set.HasDensity, Set.partialDensity] + apply hfreq.congr' + filter_upwards with N + have hfinite : ((S ∩ Set.univ) ∩ Set.Iio N).Finite := + (Set.finite_Iio N).subset Set.inter_subset_right + have hcard : + ((S ∩ Set.univ) ∩ Set.Iio N).ncard = + ((Finset.range N).filter fun n => Y n ∈ A).card := by + rw [Set.ncard_eq_toFinset_card _ hfinite] + congr 1 + ext n + simp [hS] + rw [hcard] + simp + +end MeasureTheory From 691e7d4e681edc89500a0d375c2cf18bf76ca8ca Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 06:51:45 -0700 Subject: [PATCH 033/115] Add finite-product continuity-set lemmas --- .../Probability/PiContinuitySet.lean | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean diff --git a/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean b/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean new file mode 100644 index 0000000000..e7c43a0d21 --- /dev/null +++ b/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean @@ -0,0 +1,95 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +public import Mathlib.MeasureTheory.Measure.FiniteMeasurePi + +@[expose] public section + +open Set Topology MeasureTheory +open scoped Topology BigOperators + +noncomputable section + +namespace Set + +variable {ι : Type*} [Fintype ι] +variable {α : ι → Type*} [∀ i, TopologicalSpace (α i)] + +/-- The frontier of a finite product rectangle is contained in the union of the coordinate +frontiers. -/ +theorem frontier_pi_subset_iUnion (A : ∀ i, Set (α i)) : + frontier (Set.pi univ A) ⊆ + ⋃ i, (fun x : ∀ i, α i => x i) ⁻¹' frontier (A i) := by + classical + intro x hx + by_contra hnot + have hcoord : ∀ i, x i ∉ frontier (A i) := by + simpa only [Set.mem_iUnion, Set.mem_preimage, not_exists] using hnot + by_cases hxA : x ∈ Set.pi univ A + · have hxint : x ∈ interior (Set.pi univ A) := by + let U : Set (∀ i, α i) := Set.pi univ (fun i => interior (A i)) + have hUopen : IsOpen U := isOpen_set_pi finite_univ (fun i _ => isOpen_interior) + have hxU : x ∈ U := by + intro i _ + exact (mem_interior_iff_notMem_frontier (hxA i trivial)).2 (hcoord i) + have hUsub : U ⊆ Set.pi univ A := by + intro y hy i _ + exact interior_subset (hy i trivial) + exact hUopen.mem_nhds hxU |> interior_maximal hUsub + exact (mem_frontier_iff_notMem_interior hxA).1 hx hxint + · have hex : ∃ i, x i ∉ A i := by + simpa only [Set.mem_pi, Set.mem_univ, forall_true_left, not_forall] using hxA + obtain ⟨i, hi⟩ := hex + let V : Set (∀ i, α i) := (fun y => y i) ⁻¹' interior (A i)ᶜ + have hVopen : IsOpen V := isOpen_interior.preimage (continuous_apply i) + have hxV : x ∈ V := by + exact (mem_interior_iff_notMem_frontier (show x i ∈ (A i)ᶜ by simpa)).2 (by simpa using hcoord i) + have hVsub : V ⊆ (Set.pi univ A)ᶜ := by + intro y hy hyA + exact hy (hyA i trivial) + have hxcompint : x ∈ interior (Set.pi univ A)ᶜ := + hVopen.mem_nhds hxV |> interior_maximal hVsub + have hxcomp : x ∈ (Set.pi univ A)ᶜ := interior_subset hxcompint + have : x ∉ frontier (Set.pi univ A)ᶜ := + (mem_interior_iff_notMem_frontier hxcomp).1 hxcompint + exact this (by simpa using hx) + +end Set + +namespace MeasureTheory + +variable {ι : Type*} [Fintype ι] +variable {α : ι → Type*} [∀ i, MeasurableSpace (α i)] [∀ i, TopologicalSpace (α i)] + +/-- A finite product of coordinate continuity sets is a continuity set for the product measure. -/ +theorem measure_frontier_pi_eq_zero + (μ : ∀ i, Measure (α i)) [∀ i, IsProbabilityMeasure (μ i)] + (A : ∀ i, Set (α i)) (hnull : ∀ i, μ i (frontier (A i)) = 0) : + Measure.pi μ (frontier (Set.pi univ A)) = 0 := by + classical + apply measure_mono_null (Set.frontier_pi_subset_iUnion A) + apply measure_iUnion_null + intro i + have heq : + (fun x : ∀ i, α i => x i) ⁻¹' frontier (A i) = + Set.pi univ (fun j => if j = i then frontier (A i) else univ) := by + ext x + simp [Set.mem_pi] + rw [heq, Measure.pi_pi] + simp [hnull i] + +end MeasureTheory From 25befc841e89c9c7a2bb5b3906f346040d9505de Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 06:52:21 -0700 Subject: [PATCH 034/115] Add measurable terminal arcs on the unit circle --- .../MeasureTheory/Group/UnitAddCircleArc.lean | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean diff --git a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean new file mode 100644 index 0000000000..da4468482f --- /dev/null +++ b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean @@ -0,0 +1,166 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +public import Mathlib.MeasureTheory.Integral.IntervalIntegral.Periodic +public import Mathlib.Analysis.Normed.Group.AddCircle + +@[expose] public section + +open Set Filter MeasureTheory +open scoped Topology ENNReal + +noncomputable section + +namespace UnitAddCircle + +/-- The arc with fractional representatives in `(1-a,1)`. -/ +def terminalArc (a : ℝ) : Set UnitAddCircle := + Metric.ball ((1 - a / 2 : ℝ) : UnitAddCircle) (a / 2) + +/-- The preimage of a ball under the real quotient map is the union of its integer translates. -/ +theorem coe_preimage_ball_eq_iUnion (x ε : ℝ) : + ((↑) : ℝ → UnitAddCircle) ⁻¹' Metric.ball (x : UnitAddCircle) ε = + ⋃ z : ℤ, Metric.ball (x + z) ε := by + ext y + simp only [Metric.mem_ball, Set.mem_preimage, Set.mem_iUnion, Real.dist_eq, + dist_eq_norm, ← QuotientAddGroup.mk_sub, UnitAddCircle.norm_eq] + constructor + · intro h + refine ⟨Int.round (y - x), ?_⟩ + simpa [sub_sub, add_comm, add_left_comm, add_assoc] using h + · rintro ⟨z, hz⟩ + have hmin := Int.round_le (y - x) z + exact hmin.trans_lt (by simpa [sub_sub, add_comm, add_left_comm, add_assoc] using hz) + +/-- Membership in the terminal metric arc is exactly a strict fractional-coordinate inequality. -/ +theorem coe_mem_terminalArc_iff {a t : ℝ} (ha0 : 0 < a) (ha1 : a < 1) + (ht : t ∈ Set.Ico (0 : ℝ) 1) : + ((t : ℝ) : UnitAddCircle) ∈ terminalArc a ↔ 1 - a < t := by + change t ∈ ((↑) : ℝ → UnitAddCircle) ⁻¹' + Metric.ball ((1 - a / 2 : ℝ) : UnitAddCircle) (a / 2) ↔ _ + rw [coe_preimage_ball_eq_iUnion] + simp only [Set.mem_iUnion, Metric.mem_ball, Real.dist_eq] + constructor + · rintro ⟨z, hz⟩ + obtain ⟨hzl, hzu⟩ := abs_lt.mp hz + by_cases hzero : z = 0 + · subst z + norm_num at hzl hzu + linarith + · rcases lt_or_gt_of_ne hzero with hzneg | hzpos + · have hzle : (z : ℝ) ≤ -1 := by exact_mod_cast (show z ≤ -1 by omega) + linarith [ht.1] + · have hzone : (1 : ℝ) ≤ z := by exact_mod_cast (show (1 : ℤ) ≤ z by omega) + linarith [ht.2] + · intro h + refine ⟨0, ?_⟩ + rw [Int.cast_zero, add_zero, abs_lt] + constructor <;> linarith [ht.2] + +/-- Fractional representatives are unchanged by passing to `UnitAddCircle`. -/ +theorem coe_fract_eq (x : ℝ) : + ((x : ℝ) : UnitAddCircle) = ((Int.fract x : ℝ) : UnitAddCircle) := by + rw [← Int.floor_add_fract x] + simp + +/-- A rotation point lies in the terminal arc precisely when its fractional part lies in the +corresponding terminal interval. -/ +theorem nsmul_mem_terminalArc_iff {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) (n : ℕ) : + n • (a : UnitAddCircle) ∈ terminalArc a ↔ + 1 - a < Int.fract ((n : ℝ) * a) := by + have hfract := Int.fract_mem ((n : ℝ) * a) + rw [show n • (a : UnitAddCircle) = (((n : ℝ) * a : ℝ) : UnitAddCircle) by + simp [nsmul_eq_mul]] + rw [coe_fract_eq] + exact coe_mem_terminalArc_iff ha0 ha1 hfract + +/-- A sphere of radius less than half the period has at most two points. -/ +theorem sphere_subset_pair {c r : ℝ} (hr0 : 0 ≤ r) (hr : r < 1 / 2) : + Metric.sphere (c : UnitAddCircle) r ⊆ + {((c - r : ℝ) : UnitAddCircle), ((c + r : ℝ) : UnitAddCircle)} := by + intro x hx + let q : ℝ := (AddCircle.equivIoc (1 : ℝ) (-(1 / 2 : ℝ)) (x - (c : UnitAddCircle))).1 + have hqmem : q ∈ Set.Ioc (-(1 / 2 : ℝ)) (-(1 / 2 : ℝ) + 1) := + (AddCircle.equivIoc (1 : ℝ) (-(1 / 2 : ℝ)) (x - (c : UnitAddCircle))).2 + have hqabs : |q| ≤ (1 : ℝ) / 2 := by + rw [abs_le] + constructor <;> linarith [hqmem.1, hqmem.2] + have hqcoe : (q : UnitAddCircle) = x - (c : UnitAddCircle) := + AddCircle.coe_equivIoc + have hnorm : ‖(q : UnitAddCircle)‖ = |q| := + (AddCircle.norm_coe_eq_abs_iff (1 : ℝ) one_ne_zero).2 (by simpa using hqabs) + have habs : |q| = r := by + calc + |q| = ‖(q : UnitAddCircle)‖ := hnorm.symm + _ = ‖x - (c : UnitAddCircle)‖ := congrArg norm hqcoe + _ = dist x (c : UnitAddCircle) := by rw [dist_eq_norm] + _ = r := Metric.mem_sphere.mp hx + rcases abs_eq (show 0 ≤ r from hr0) |>.mp habs with hq | hq + · left + apply sub_eq_iff_eq_add.mp + simpa [hq, sub_eq_add_neg, add_comm, add_left_comm, add_assoc] using hqcoe.symm + · right + apply sub_eq_iff_eq_add.mp + simpa [hq, sub_eq_add_neg, add_comm, add_left_comm, add_assoc] using hqcoe.symm + +/-- Small spheres in the unit additive circle have Haar measure zero. -/ +theorem volume_sphere_eq_zero {c r : ℝ} (hr0 : 0 ≤ r) (hr : r < 1 / 2) : + volume (Metric.sphere (c : UnitAddCircle) r) = 0 := by + apply measure_mono_null (sphere_subset_pair hr0 hr) + simp + +/-- The terminal arc has length `a`. -/ +theorem volume_terminalArc {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : + volume (terminalArc a) = ENNReal.ofReal a := by + have hsphere : + volume (Metric.sphere ((1 - a / 2 : ℝ) : UnitAddCircle) (a / 2)) = 0 := + volume_sphere_eq_zero (by positivity) (by linarith) + calc + volume (terminalArc a) = + volume (Metric.closedBall ((1 - a / 2 : ℝ) : UnitAddCircle) (a / 2)) := by + rw [← Metric.ball_union_sphere] + exact (measure_union_null hsphere).symm + _ = ENNReal.ofReal a := by + rw [AddCircle.volume_closedBall] + congr 1 + rw [min_eq_right] + · ring + · linarith + +/-- The terminal arc is measurable. -/ +theorem measurableSet_terminalArc (a : ℝ) : MeasurableSet (terminalArc a) := + Metric.isOpen_ball.measurableSet + +/-- The terminal arc has null frontier. -/ +theorem volume_frontier_terminalArc {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : + volume (frontier (terminalArc a)) = 0 := by + apply measure_mono_null Metric.frontier_ball_subset_sphere + exact volume_sphere_eq_zero (by positivity) (by linarith) + +/-- The complement of a terminal arc has null frontier as well. -/ +theorem volume_frontier_terminalArc_compl {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : + volume (frontier (terminalArc a)ᶜ) = 0 := by + simpa using volume_frontier_terminalArc ha0 ha1 + +/-- The complement of a terminal arc has length `1-a`. -/ +theorem volume_terminalArc_compl {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : + volume (terminalArc a)ᶜ = ENNReal.ofReal (1 - a) := by + rw [measure_compl (measurableSet_terminalArc a)] + rw [AddCircle.measure_univ, volume_terminalArc ha0 ha1] + norm_num [ENNReal.ofReal_sub (ha0.le.trans ha1.le)] + +end UnitAddCircle From a30fa5bc1ea2b14a7d096ee20a839524e6447975 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 06:55:58 -0700 Subject: [PATCH 035/115] Prove density of finite torus terminal boxes --- .../Equidistribution/TerminalBox.lean | 153 ++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean new file mode 100644 index 0000000000..308e3036ea --- /dev/null +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean @@ -0,0 +1,153 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +public import FormalConjecturesForMathlib.Analysis.Equidistribution.UnitAddTorus +public import FormalConjecturesForMathlib.MeasureTheory.Group.UnitAddCircleArc +public import FormalConjecturesForMathlib.MeasureTheory.Probability.Empirical +public import FormalConjecturesForMathlib.MeasureTheory.Probability.PiContinuitySet + +@[expose] public section + +open Filter Set MeasureTheory +open scoped Topology BigOperators ENNReal NNReal + +noncomputable section + +namespace UnitAddTorus + +variable {ι : Type*} [Fintype ι] + +/-- The coordinate event saying that the distinguished coordinate hits its terminal arc and every +other coordinate misses its terminal arc. -/ +def terminalCoordinateSet [DecidableEq ι] (j : ι) (a : ι → ℝ) (i : ι) : + Set UnitAddCircle := + if i = j then UnitAddCircle.terminalArc (a i) + else (UnitAddCircle.terminalArc (a i))ᶜ + +/-- The corresponding rectangle in the finite unit torus. -/ +def terminalBox [DecidableEq ι] (j : ι) (a : ι → ℝ) : Set (UnitAddTorus ι) := + Set.pi univ (terminalCoordinateSet j a) + +/-- Orbit membership in the terminal box is exactly one hit and all other misses. -/ +theorem nsmul_mem_terminalBox_iff [DecidableEq ι] + (j : ι) (a : ι → ℝ) (ha0 : ∀ i, 0 < a i) (ha1 : ∀ i, a i < 1) (n : ℕ) : + n • (fun i => (a i : UnitAddCircle)) ∈ terminalBox j a ↔ + (1 - a j < Int.fract ((n : ℝ) * a j) ∧ + ∀ i, i ≠ j → ¬(1 - a i < Int.fract ((n : ℝ) * a i))) := by + classical + simp only [terminalBox, Set.mem_pi, Set.mem_univ, forall_true_left, + terminalCoordinateSet, Pi.smul_apply] + constructor + · intro h + refine ⟨?_, ?_⟩ + · have hj := h j + simp only [if_pos rfl] at hj + exact (UnitAddCircle.nsmul_mem_terminalArc_iff (ha0 j) (ha1 j) n).mp hj + · intro i hij hi + have hmiss := h i + simp only [if_neg hij] at hmiss + exact hmiss ((UnitAddCircle.nsmul_mem_terminalArc_iff (ha0 i) (ha1 i) n).mpr hi) + · rintro ⟨hj, hother⟩ i + by_cases hij : i = j + · subst i + simp only [if_pos rfl] + exact (UnitAddCircle.nsmul_mem_terminalArc_iff (ha0 j) (ha1 j) n).mpr hj + · simp only [if_neg hij, Set.mem_compl_iff] + intro hi + exact hother i hij ((UnitAddCircle.nsmul_mem_terminalArc_iff (ha0 i) (ha1 i) n).mp hi) + +/-- The terminal box is measurable. -/ +theorem measurableSet_terminalBox [DecidableEq ι] + (j : ι) (a : ι → ℝ) : MeasurableSet (terminalBox j a) := by + apply MeasurableSet.univ_pi + intro i + by_cases h : i = j + · simp [terminalCoordinateSet, h, UnitAddCircle.measurableSet_terminalArc] + · simp [terminalCoordinateSet, h, UnitAddCircle.measurableSet_terminalArc] + +/-- Every coordinate set of the terminal box has null frontier. -/ +theorem volume_frontier_terminalCoordinateSet [DecidableEq ι] + (j : ι) (a : ι → ℝ) (ha0 : ∀ i, 0 < a i) (ha1 : ∀ i, a i < 1) (i : ι) : + volume (frontier (terminalCoordinateSet j a i)) = 0 := by + by_cases h : i = j + · simp [terminalCoordinateSet, h, + UnitAddCircle.volume_frontier_terminalArc (ha0 i) (ha1 i)] + · simp [terminalCoordinateSet, h, + UnitAddCircle.volume_frontier_terminalArc_compl (ha0 i) (ha1 i)] + +/-- The terminal box is a continuity set for Haar probability measure. -/ +theorem volume_frontier_terminalBox [DecidableEq ι] + (j : ι) (a : ι → ℝ) (ha0 : ∀ i, 0 < a i) (ha1 : ∀ i, a i < 1) : + volume (frontier (terminalBox j a)) = 0 := by + exact measure_frontier_pi_eq_zero (fun _ : ι => (volume : Measure UnitAddCircle)) + (terminalCoordinateSet j a) (volume_frontier_terminalCoordinateSet j a ha0 ha1) + +/-- Haar mass of a terminal coordinate event. -/ +theorem volume_terminalCoordinateSet [DecidableEq ι] + (j : ι) (a : ι → ℝ) (ha0 : ∀ i, 0 < a i) (ha1 : ∀ i, a i < 1) (i : ι) : + volume (terminalCoordinateSet j a i) = + ENNReal.ofReal (if i = j then a i else 1 - a i) := by + by_cases h : i = j + · simp [terminalCoordinateSet, h, UnitAddCircle.volume_terminalArc (ha0 i) (ha1 i)] + · simp [terminalCoordinateSet, h, UnitAddCircle.volume_terminalArc_compl (ha0 i) (ha1 i)] + +/-- Haar mass of the terminal box. -/ +theorem volume_terminalBox [DecidableEq ι] + (j : ι) (a : ι → ℝ) (ha0 : ∀ i, 0 < a i) (ha1 : ∀ i, a i < 1) : + volume (terminalBox j a) = + ENNReal.ofReal (a j * ∏ i ∈ (Finset.univ.erase j), (1 - a i)) := by + rw [show (volume : Measure (UnitAddTorus ι)) = + Measure.pi (fun _ : ι => (volume : Measure UnitAddCircle)) by rfl] + rw [terminalBox, Measure.pi_pi] + simp_rw [volume_terminalCoordinateSet j a ha0 ha1] + rw [← ENNReal.ofReal_prod_of_nonneg] + · congr 1 + rw [Finset.prod_ite_eq' Finset.mem_univ] + rw [Finset.prod_erase_mul _ (Finset.mem_univ j)] + simp [mul_comm] + · intro i hi + split_ifs + · exact (ha0 i).le + · exact sub_nonneg.mpr (ha1 i).le + +/-- The terminal-box orbit event has the expected natural density. -/ +theorem hasDensity_terminalBox [DecidableEq ι] + (j : ι) (a : ι → ℝ) (ha0 : ∀ i, 0 < a i) (ha1 : ∀ i, a i < 1) + (hrel : NoIntegerRelation a) : + {n : ℕ | n • (fun i => (a i : UnitAddCircle)) ∈ terminalBox j a}.HasDensity + (a j * ∏ i ∈ (Finset.univ.erase j), (1 - a i)) := by + let μ : ProbabilityMeasure (UnitAddTorus ι) := ⟨volume, inferInstance⟩ + have havg : ∀ F : C(UnitAddTorus ι, ℂ), + Tendsto + (fun N : ℕ => + (∑ n ∈ Finset.range N, F (n • (fun i => (a i : UnitAddCircle)))) / (N : ℂ)) + atTop + (𝓝 (∫ x, F x ∂(μ : Measure (UnitAddTorus ι)))) := by + simpa [μ] using tendsto_average_rotation a hrel + have hd := MeasureTheory.hasDensity_of_tendsto_average + (Y := fun n => n • (fun i => (a i : UnitAddCircle))) μ havg + (measurableSet_terminalBox j a) (by simpa [μ] using volume_frontier_terminalBox j a ha0 ha1) + {n : ℕ | n • (fun i => (a i : UnitAddCircle)) ∈ terminalBox j a} (fun _ => Iff.rfl) + convert hd using 1 + simp only [μ] + rw [show (((⟨volume, inferInstance⟩ : ProbabilityMeasure (UnitAddTorus ι)) + (terminalBox j a) : ℝ≥0) : ℝ) = + (volume (terminalBox j a)).toReal by simp] + rw [volume_terminalBox j a ha0 ha1, ENNReal.toReal_ofReal] + positivity + +end UnitAddTorus From 27aacc8abae67b63715ddb925b67c16744acf867 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 06:56:52 -0700 Subject: [PATCH 036/115] Add full A261865 density proof candidate --- FormalConjectures/OEIS/261865Solution.lean | 158 +++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 FormalConjectures/OEIS/261865Solution.lean diff --git a/FormalConjectures/OEIS/261865Solution.lean b/FormalConjectures/OEIS/261865Solution.lean new file mode 100644 index 0000000000..50554e2432 --- /dev/null +++ b/FormalConjectures/OEIS/261865Solution.lean @@ -0,0 +1,158 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +public import FormalConjectures.OEIS.«261865» +public import FormalConjecturesForMathlib.Analysis.Equidistribution.TerminalBox + +@[expose] public section + +open Filter +open scoped BigOperators Topology + +namespace OeisA261865 + +/-- The reciprocal-square-root rotation parameters lie strictly between zero and one. -/ +theorem alpha_pos_of_two_le {s : ℕ} (hs : 2 ≤ s) : 0 < alpha s := by + unfold alpha + exact one_div_pos.mpr (Real.sqrt_pos.2 (by positivity)) + +theorem alpha_lt_one_of_two_le {s : ℕ} (hs : 2 ≤ s) : alpha s < 1 := by + have hspos : (0 : ℝ) < s := by positivity + have hsqrtpos : (0 : ℝ) < Real.sqrt (s : ℝ) := Real.sqrt_pos.2 hspos + have hsqrtsq : (Real.sqrt (s : ℝ)) ^ 2 = (s : ℝ) := Real.sq_sqrt hspos.le + have hsqrtone : 1 < Real.sqrt (s : ℝ) := by + nlinarith [show (2 : ℝ) ≤ s by exact_mod_cast hs] + unfold alpha + exact (one_div_lt_one₀ hsqrtpos).2 hsqrtone + +/-- The distinguished element `j` as an element of the relevant-radicand subtype. -/ +noncomputable def distinguishedRadicand (j : ℕ) : relevantRadicands j := + ⟨j, by simp⟩ + +/-- The generic terminal-box event is exactly the A261865 least-radicand event. -/ +theorem orbit_mem_terminalBox_iff (n j : ℕ) (hj : 2 ≤ j) : + n • (fun s : relevantRadicands j => (alpha s.1 : UnitAddCircle)) ∈ + UnitAddTorus.terminalBox (distinguishedRadicand j) + (fun s : relevantRadicands j => alpha s.1) ↔ + 0 < n ∧ IsValue n j := by + classical + have hge : ∀ s : relevantRadicands j, 2 ≤ s.1 := by + intro s + rcases mem_relevantRadicands.mp s.2 with rfl | hs + · exact hj + · exact hs.1 + have ha0 : ∀ s : relevantRadicands j, 0 < alpha s.1 := + fun s => alpha_pos_of_two_le (hge s) + have ha1 : ∀ s : relevantRadicands j, alpha s.1 < 1 := + fun s => alpha_lt_one_of_two_le (hge s) + rw [UnitAddTorus.nsmul_mem_terminalBox_iff (distinguishedRadicand j) + (fun s : relevantRadicands j => alpha s.1) ha0 ha1 n] + constructor + · rintro ⟨hjhit, hmiss⟩ + have hnpos : 0 < n := by + by_contra hn + have : n = 0 := Nat.eq_zero_of_not_pos hn + subst n + simp [CoordinateHit] at hjhit + refine ⟨hnpos, (isValue_iff_coordinateConditions n j hj).2 ?_⟩ + refine ⟨by simpa [distinguishedRadicand] using hjhit, ?_⟩ + intro s hs hcoord + let sr : relevantRadicands j := ⟨s, by simp [hs]⟩ + have hne : sr ≠ distinguishedRadicand j := by + intro h + have : s = j := congrArg Subtype.val h + exact (mem_squarefreeBelow.mp hs).2.1.ne this + exact hmiss sr hne (by simpa [sr] using hcoord) + · rintro ⟨hnpos, hvalue⟩ + obtain ⟨hjhit, hsmall⟩ := (isValue_iff_coordinateConditions n j hj).1 hvalue + refine ⟨by simpa [distinguishedRadicand] using hjhit, ?_⟩ + intro s hne hcoord + have hsne : s.1 ≠ j := by + intro h + apply hne + apply Subtype.ext + simpa [distinguishedRadicand] using h + have hsbelow : s.1 ∈ squarefreeBelow j := by + rcases mem_relevantRadicands.mp s.2 with hs | hs + · exact (hsne hs).elim + · exact mem_squarefreeBelow.mpr hs + exact hsmall s.1 hsbelow (by simpa using hcoord) + +/-- The subtype product over all relevant radicands except `j` is the advertised product over +`squarefreeBelow j`. -/ +theorem product_erase_distinguished (j : ℕ) : + ∏ s ∈ (Finset.univ.erase (distinguishedRadicand j)), (1 - alpha s.1) = + ∏ s ∈ squarefreeBelow j, (1 - alpha s) := by + classical + refine Finset.prod_bij (fun s _ => s.1) ?_ ?_ ?_ ?_ + · intro s hs + have hne : s ≠ distinguishedRadicand j := Finset.ne_of_mem_erase hs + rcases mem_relevantRadicands.mp s.2 with hsj | hsj + · exfalso + apply hne + apply Subtype.ext + simpa [distinguishedRadicand] using hsj + · exact mem_squarefreeBelow.mpr hsj + · intro a ha b hb hab + exact Subtype.ext hab + · intro s hs + let sr : relevantRadicands j := ⟨s, by simp [hs]⟩ + have hne : sr ≠ distinguishedRadicand j := by + intro h + have : s = j := congrArg Subtype.val h + exact (mem_squarefreeBelow.mp hs).2.1.ne this + exact ⟨sr, Finset.mem_erase.mpr ⟨hne, Finset.mem_univ sr⟩, rfl⟩ + · intro s hs + rfl + +/-- Axiom-free proof candidate for Peter Kagey's Problem 13 / OEIS A261865. -/ +theorem density_formula_solution (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : + {n : ℕ | 0 < n ∧ IsValue n j}.HasDensity (predictedDensity j) := by + classical + let R := relevantRadicands j + have hge : ∀ s ∈ relevantRadicands j, 2 ≤ s := by + intro s hs + rcases mem_relevantRadicands.mp hs with rfl | hs + · exact hj + · exact hs.1 + have hsqR : ∀ s ∈ relevantRadicands j, Squarefree s := by + intro s hs + rcases mem_relevantRadicands.mp hs with rfl | hs + · exact hsq + · exact hs.2.2 + have ha0 : ∀ s : relevantRadicands j, 0 < alpha s.1 := + fun s => alpha_pos_of_two_le (hge s.1 s.2) + have ha1 : ∀ s : relevantRadicands j, alpha s.1 < 1 := + fun s => alpha_lt_one_of_two_le (hge s.1 s.2) + have hrel : UnitAddTorus.NoIntegerRelation + (fun s : relevantRadicands j => alpha s.1) := + noIntegerRelation_alpha (relevantRadicands j) hge hsqR + have hgeneric := UnitAddTorus.hasDensity_terminalBox + (distinguishedRadicand j) (fun s : relevantRadicands j => alpha s.1) ha0 ha1 hrel + have hevent : + {n : ℕ | n • (fun s : relevantRadicands j => (alpha s.1 : UnitAddCircle)) ∈ + UnitAddTorus.terminalBox (distinguishedRadicand j) + (fun s : relevantRadicands j => alpha s.1)} = + {n : ℕ | 0 < n ∧ IsValue n j} := by + ext n + exact orbit_mem_terminalBox_iff n j hj + rw [hevent] at hgeneric + convert hgeneric using 1 + rw [predictedDensity, product_erase_distinguished] + rfl + +end OeisA261865 From 4052caa106dec1ec37e80e9b994a490d969b5a23 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 09:03:56 -0700 Subject: [PATCH 037/115] audit(OEIS): add exact A261865 theorem axiom check --- FormalConjectures/OEIS/261865FinalAudit.lean | 32 ++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 FormalConjectures/OEIS/261865FinalAudit.lean diff --git a/FormalConjectures/OEIS/261865FinalAudit.lean b/FormalConjectures/OEIS/261865FinalAudit.lean new file mode 100644 index 0000000000..8e039dd6f5 --- /dev/null +++ b/FormalConjectures/OEIS/261865FinalAudit.lean @@ -0,0 +1,32 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +public import FormalConjectures.OEIS.«261865Solution» + +@[expose] public section + +namespace OeisA261865 + +/-- Exact-statement audit wrapper for Peter Kagey's Problem 13 / OEIS A261865. -/ +theorem density_formula_final_audit (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : + {n : ℕ | 0 < n ∧ IsValue n j}.HasDensity (predictedDensity j) := + density_formula_solution j hj hsq + +#print axioms density_formula_solution +#print axioms density_formula_final_audit + +end OeisA261865 From f6f6e6f748644ea2ae7b1ea16458025aa79da5c4 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 09:04:14 -0700 Subject: [PATCH 038/115] ci(OEIS): audit complete A261865 solution theorem --- .github/workflows/a261865-final-audit.yml | 92 +++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 .github/workflows/a261865-final-audit.yml diff --git a/.github/workflows/a261865-final-audit.yml b/.github/workflows/a261865-final-audit.yml new file mode 100644 index 0000000000..247e7240d5 --- /dev/null +++ b/.github/workflows/a261865-final-audit.yml @@ -0,0 +1,92 @@ +# Copyright 2026 The Formal Conjectures Authors. +# Licensed under the Apache License, Version 2.0. + +name: A261865 final theorem audit + +on: + push: + branches: + - a261865-research + paths: + - 'FormalConjectures/OEIS/261865.lean' + - 'FormalConjectures/OEIS/261865Solution.lean' + - 'FormalConjectures/OEIS/261865FinalAudit.lean' + - 'FormalConjecturesForMathlib/Analysis/Equidistribution/**' + - 'FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean' + - 'FormalConjecturesForMathlib/MeasureTheory/Probability/**' + - 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical*.lean' + - '.github/workflows/a261865-final-audit.yml' + pull_request: + branches: + - main + paths: + - 'FormalConjectures/OEIS/261865.lean' + - 'FormalConjectures/OEIS/261865Solution.lean' + - 'FormalConjectures/OEIS/261865FinalAudit.lean' + - 'FormalConjecturesForMathlib/Analysis/Equidistribution/**' + - 'FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean' + - 'FormalConjecturesForMathlib/MeasureTheory/Probability/**' + - 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical*.lean' + - '.github/workflows/a261865-final-audit.yml' + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: a261865-final-${{ github.ref }} + cancel-in-progress: true + +jobs: + lean-final: + name: Lean 4.27 exact theorem and axiom audit + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - name: Checkout project + uses: actions/checkout@v4 + + - name: Install pinned Lean toolchain + shell: bash + run: | + set -euo pipefail + curl -fsSL https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh \ + | sh -s -- -y --default-toolchain none + echo "$HOME/.elan/bin" >> "$GITHUB_PATH" + "$HOME/.elan/bin/elan" toolchain install leanprover/lean4:v4.27.0 + + - name: Fetch Mathlib cache + shell: bash + run: | + set -euo pipefail + lake exe cache get + + - name: Reject placeholders in the solution chain + shell: bash + run: | + set -euo pipefail + files=( + FormalConjectures/OEIS/261865Solution.lean + FormalConjectures/OEIS/261865FinalAudit.lean + FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean + FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean + FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean + FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean + FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean + FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean + ) + if grep -nE '\b(sorry|admit)\b|native_decide|unsafe|^axiom\b' "${files[@]}"; then + echo 'Forbidden proof placeholder or trust escape found.' >&2 + exit 1 + fi + + - name: Compile exact final theorem + shell: bash + run: | + set -euo pipefail + output=$(lake env lean FormalConjectures/OEIS/261865FinalAudit.lean 2>&1) + printf '%s\n' "$output" + if grep -q 'sorryAx' <<<"$output"; then + echo 'The exact solution theorem depends on sorryAx.' >&2 + exit 1 + fi From b96144394e6a71a71a4a0ee4cad6ef031b249676 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 09:17:37 -0700 Subject: [PATCH 039/115] Fix interior maximality in A261865 product continuity lemma --- .../MeasureTheory/Probability/PiContinuitySet.lean | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean b/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean index e7c43a0d21..82c2f877a5 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean @@ -49,7 +49,7 @@ theorem frontier_pi_subset_iUnion (A : ∀ i, Set (α i)) : have hUsub : U ⊆ Set.pi univ A := by intro y hy i _ exact interior_subset (hy i trivial) - exact hUopen.mem_nhds hxU |> interior_maximal hUsub + exact interior_maximal hUsub hUopen hxU exact (mem_frontier_iff_notMem_interior hxA).1 hx hxint · have hex : ∃ i, x i ∉ A i := by simpa only [Set.mem_pi, Set.mem_univ, forall_true_left, not_forall] using hxA @@ -62,7 +62,7 @@ theorem frontier_pi_subset_iUnion (A : ∀ i, Set (α i)) : intro y hy hyA exact hy (hyA i trivial) have hxcompint : x ∈ interior (Set.pi univ A)ᶜ := - hVopen.mem_nhds hxV |> interior_maximal hVsub + interior_maximal hVsub hVopen hxV have hxcomp : x ∈ (Set.pi univ A)ᶜ := interior_subset hxcompint have : x ∉ frontier (Set.pi univ A)ᶜ := (mem_interior_iff_notMem_frontier hxcomp).1 hxcompint @@ -92,4 +92,4 @@ theorem measure_frontier_pi_eq_zero rw [heq, Measure.pi_pi] simp [hnull i] -end MeasureTheory +end MeasureTheory \ No newline at end of file From 21b9fab47678d0951faa3ab50d69cdf6ffaee843 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 09:18:23 -0700 Subject: [PATCH 040/115] Fix complement membership in A261865 continuity set proof --- .../MeasureTheory/Probability/PiContinuitySet.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean b/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean index 82c2f877a5..26b5d9bfd0 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean @@ -60,7 +60,7 @@ theorem frontier_pi_subset_iUnion (A : ∀ i, Set (α i)) : exact (mem_interior_iff_notMem_frontier (show x i ∈ (A i)ᶜ by simpa)).2 (by simpa using hcoord i) have hVsub : V ⊆ (Set.pi univ A)ᶜ := by intro y hy hyA - exact hy (hyA i trivial) + exact (interior_subset hy) (hyA i trivial) have hxcompint : x ∈ interior (Set.pi univ A)ᶜ := interior_maximal hVsub hVopen hxV have hxcomp : x ∈ (Set.pi univ A)ᶜ := interior_subset hxcompint From ff31ca2208bb69c3d42bef97f78040ce84ef57ef Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 09:19:34 -0700 Subject: [PATCH 041/115] Fix terminal-box product factorization --- .../Analysis/Equidistribution/TerminalBox.lean | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean index 308e3036ea..7531a69ac5 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean @@ -116,9 +116,14 @@ theorem volume_terminalBox [DecidableEq ι] simp_rw [volume_terminalCoordinateSet j a ha0 ha1] rw [← ENNReal.ofReal_prod_of_nonneg] · congr 1 - rw [Finset.prod_ite_eq' Finset.mem_univ] - rw [Finset.prod_erase_mul _ (Finset.mem_univ j)] - simp [mul_comm] + calc + (∏ i, if i = j then a i else 1 - a i) = + (if j = j then a j else 1 - a j) * + ∏ i ∈ Finset.univ.erase j, (if i = j then a i else 1 - a i) := by + exact (Finset.mul_prod_erase Finset.univ + (fun i => if i = j then a i else 1 - a i) (Finset.mem_univ j)).symm + _ = a j * ∏ i ∈ Finset.univ.erase j, (1 - a i) := by + simp · intro i hi split_ifs · exact (ha0 i).le @@ -150,4 +155,4 @@ theorem hasDensity_terminalBox [DecidableEq ι] rw [volume_terminalBox j a ha0 ha1, ENNReal.toReal_ofReal] positivity -end UnitAddTorus +end UnitAddTorus \ No newline at end of file From a66165b29f94b628bc8cbb0f04f9420369c7b33d Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 09:22:32 -0700 Subject: [PATCH 042/115] Fix Fourier character addition rewrite --- .../Analysis/Equidistribution/UnitAddTorus.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean index 3f559f766a..a0e7bffbf8 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean @@ -149,7 +149,7 @@ def NoIntegerRelation (a : d → ℝ) : Prop := /-- A multivariate Fourier monomial turns addition on the torus into multiplication. -/ lemma mFourier_add_point (k : d → ℤ) (x y : UnitAddTorus d) : mFourier k (x + y) = mFourier k x * mFourier k y := by - simp only [mFourier, ContinuousMap.coe_mk, Pi.add_apply, fourier_apply, add_zsmul, + simp only [mFourier, ContinuousMap.coe_mk, Pi.add_apply, fourier_apply, smul_add, AddCircle.toCircle_add, Circle.coe_mul, Finset.prod_mul_distrib] /-- A Fourier monomial along a rotation orbit is a geometric progression. -/ @@ -255,4 +255,4 @@ theorem tendsto_average_rotation rw [integral_mFourier, if_neg hk] simpa only [mFourier_nsmul] using hgeom -end UnitAddTorus +end UnitAddTorus \ No newline at end of file From fce14b0386cf1071b1429e06783e86464eabe660 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 09:42:53 -0700 Subject: [PATCH 043/115] Fix zero-index exclusion in A261865 orbit event --- FormalConjectures/OEIS/261865Solution.lean | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/FormalConjectures/OEIS/261865Solution.lean b/FormalConjectures/OEIS/261865Solution.lean index 50554e2432..dc61883cd1 100644 --- a/FormalConjectures/OEIS/261865Solution.lean +++ b/FormalConjectures/OEIS/261865Solution.lean @@ -65,9 +65,13 @@ theorem orbit_mem_terminalBox_iff (n j : ℕ) (hj : 2 ≤ j) : · rintro ⟨hjhit, hmiss⟩ have hnpos : 0 < n := by by_contra hn - have : n = 0 := Nat.eq_zero_of_not_pos hn + have hnzero : n = 0 := Nat.eq_zero_of_not_pos hn subst n - simp [CoordinateHit] at hjhit + have hnonneg : + 0 ≤ 1 - alpha (distinguishedRadicand j).1 := + sub_nonneg.mpr (ha1 (distinguishedRadicand j)).le + norm_num at hjhit + exact (not_lt_of_ge hnonneg) hjhit refine ⟨hnpos, (isValue_iff_coordinateConditions n j hj).2 ?_⟩ refine ⟨by simpa [distinguishedRadicand] using hjhit, ?_⟩ intro s hs hcoord @@ -123,7 +127,6 @@ theorem product_erase_distinguished (j : ℕ) : theorem density_formula_solution (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : {n : ℕ | 0 < n ∧ IsValue n j}.HasDensity (predictedDensity j) := by classical - let R := relevantRadicands j have hge : ∀ s ∈ relevantRadicands j, 2 ≤ s := by intro s hs rcases mem_relevantRadicands.mp hs with rfl | hs @@ -155,4 +158,4 @@ theorem density_formula_solution (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : rw [predictedDensity, product_erase_distinguished] rfl -end OeisA261865 +end OeisA261865 \ No newline at end of file From 445d9e316bf83aeed8d3271fe6ab10a010aa8c47 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 09:46:28 -0700 Subject: [PATCH 044/115] Make the A261865 catalog theorem sorry-free --- FormalConjectures/OEIS/261865.lean | 267 +------------------- FormalConjectures/OEIS/261865Solution.lean | 4 +- FormalConjectures/OEIS/A261865Base.lean | 275 +++++++++++++++++++++ 3 files changed, 282 insertions(+), 264 deletions(-) create mode 100644 FormalConjectures/OEIS/A261865Base.lean diff --git a/FormalConjectures/OEIS/261865.lean b/FormalConjectures/OEIS/261865.lean index 3ac5f85bcd..a35d65b58d 100644 --- a/FormalConjectures/OEIS/261865.lean +++ b/FormalConjectures/OEIS/261865.lean @@ -15,9 +15,7 @@ limitations under the License. -/ module -public import FormalConjecturesUtil -public import FormalConjecturesForMathlib.Analysis.Equidistribution.UnitAddTorus -public import FormalConjecturesForMathlib.NumberTheory.SquarefreeRadicals +public import FormalConjectures.OEIS.«261865Solution» @[expose] public section @@ -28,269 +26,14 @@ For a positive integer `n`, OEIS A261865 is the least positive integer `k` for which a positive integer multiple of `√k` lies strictly between `n` and `n + 1`. -Peter Kagey's Problem 13 asks for the natural density of the indices at which -a fixed squarefree `j ≥ 2` is the least successful radicand. The predicted -density is +For every squarefree `j ≥ 2`, the indices where `j` is the least successful +radicand have density `(1 / √j) * ∏_{2 ≤ s < j, Squarefree s} (1 - 1 / √s)`. -/ -open Filter -open scoped BigOperators Topology - namespace OeisA261865 -/-- A positive integer multiple of `√k` lies strictly in `(n, n + 1)`. -/ -def Hits (k n : ℕ) : Prop := - ∃ m : ℕ, 0 < m ∧ - (n : ℝ) < (m : ℝ) * Real.sqrt (k : ℝ) ∧ - (m : ℝ) * Real.sqrt (k : ℝ) < (n : ℝ) + 1 - -/-- `k` is the least positive radicand that hits the interval `(n, n + 1)`. -/ -def IsValue (n k : ℕ) : Prop := - 0 < k ∧ Hits k n ∧ ∀ r : ℕ, 0 < r → r < k → ¬ Hits r n - -/-- The rotation parameter `1 / √s`. -/ -noncomputable def alpha (s : ℕ) : ℝ := - 1 / Real.sqrt (s : ℝ) - -/-- The fractional-part condition corresponding to `Hits s n`. -/ -def CoordinateHit (s n : ℕ) : Prop := - 1 - alpha s < Int.fract ((n : ℝ) * alpha s) - -/-- -The next positive integer after a nonnegative real `x` lies below `x + a` -exactly when the fractional part of `x` is greater than `1 - a`. --/ -theorem exists_nat_between_iff_fract {x a : ℝ} (hx : 0 ≤ x) : - (∃ m : ℕ, 0 < m ∧ x < (m : ℝ) ∧ (m : ℝ) < x + a) ↔ - 1 - a < Int.fract x := by - constructor - · rintro ⟨m, _hmpos, hxm, hmx⟩ - have hfloor_lt : ⌊x⌋ < (m : ℤ) := - Int.floor_lt.mpr (by simpa using hxm) - have hnext_le : ⌊x⌋ + 1 ≤ (m : ℤ) := by omega - have hnext_le_real : ((⌊x⌋ + 1 : ℤ) : ℝ) ≤ (m : ℝ) := by - exact_mod_cast hnext_le - have hnext_lt : (⌊x⌋ : ℝ) + 1 < x + a := by - exact lt_of_le_of_lt (by simpa using hnext_le_real) hmx - have hdecomp := Int.floor_add_fract x - linarith - · intro hfract - have hfloor_nonneg : 0 ≤ ⌊x⌋ := Int.floor_nonneg.mpr hx - let m : ℕ := ⌊x⌋.toNat + 1 - have hmcast : (m : ℝ) = (⌊x⌋ : ℝ) + 1 := by - simp [m, Int.toNat_of_nonneg hfloor_nonneg] - refine ⟨m, by simp [m], ?_, ?_⟩ - · rw [hmcast] - exact Int.lt_floor_add_one x - · rw [hmcast] - have hdecomp := Int.floor_add_fract x - linarith - -/-- -The interval-hitting predicate is exactly an irrational-rotation interval. -This removes the first axiom from the uploaded proof bundle. --/ -theorem hits_iff_coordinateHit (s n : ℕ) (hs : 2 ≤ s) : - Hits s n ↔ CoordinateHit s n := by - have hs_real_pos : (0 : ℝ) < (s : ℝ) := by positivity - have hsqrt_pos : (0 : ℝ) < Real.sqrt (s : ℝ) := Real.sqrt_pos.2 hs_real_pos - have hx : 0 ≤ (n : ℝ) / Real.sqrt (s : ℝ) := - div_nonneg (by positivity) hsqrt_pos.le - constructor - · rintro ⟨m, hmpos, hleft, hright⟩ - have hleft' : (n : ℝ) / Real.sqrt (s : ℝ) < (m : ℝ) := - (div_lt_iff₀ hsqrt_pos).2 hleft - have hright' : (m : ℝ) < - (n : ℝ) / Real.sqrt (s : ℝ) + 1 / Real.sqrt (s : ℝ) := by - have := (lt_div_iff₀ hsqrt_pos).2 hright - convert this using 1 <;> ring - have hfract := (exists_nat_between_iff_fract hx).mp - ⟨m, hmpos, hleft', hright'⟩ - simpa [CoordinateHit, alpha, div_eq_mul_inv] using hfract - · intro hcoord - have hfract : - 1 - 1 / Real.sqrt (s : ℝ) < - Int.fract ((n : ℝ) / Real.sqrt (s : ℝ)) := by - simpa [CoordinateHit, alpha, div_eq_mul_inv] using hcoord - obtain ⟨m, hmpos, hleft, hright⟩ := - (exists_nat_between_iff_fract hx).mpr hfract - refine ⟨m, hmpos, (div_lt_iff₀ hsqrt_pos).mp hleft, ?_⟩ - apply (lt_div_iff₀ hsqrt_pos).mp - convert hright using 1 <;> ring - -/-- The radicand `1` never hits an open unit interval between consecutive integers. -/ -theorem not_hits_one (n : ℕ) : ¬ Hits 1 n := by - rintro ⟨m, _hm, hleft, hright⟩ - have hnm : n < m := by - exact_mod_cast (by simpa using hleft) - have hmn : m < n + 1 := by - exact_mod_cast (by simpa [Nat.cast_add, Nat.cast_one] using hright) - omega - -/-- -Removing a positive square factor from a radicand preserves the hitting -property. Hence a nonsquarefree radicand can never be a genuinely new least -value: every hit by `c² s` is already a hit by `s`. --/ -theorem hits_square_mul_imp (c s n : ℕ) (hc : 0 < c) : - Hits (c ^ 2 * s) n → Hits s n := by - rintro ⟨m, hm, hleft, hright⟩ - have hsqrt : - Real.sqrt ((c ^ 2 * s : ℕ) : ℝ) = - (c : ℝ) * Real.sqrt (s : ℝ) := by - rw [Nat.cast_mul, Nat.cast_pow, Real.sqrt_mul (sq_nonneg (c : ℝ))] - rw [Real.sqrt_sq (Nat.cast_nonneg c)] - refine ⟨m * c, Nat.mul_pos hm hc, ?_, ?_⟩ - · simpa only [hsqrt, Nat.cast_mul, mul_assoc] using hleft - · simpa only [hsqrt, Nat.cast_mul, mul_assoc] using hright - -/-- Every hit descends to a hit by a positive squarefree radicand no larger than the original. -/ -theorem exists_squarefree_hit_le (r n : ℕ) (hr : 0 < r) (hhit : Hits r n) : - ∃ s : ℕ, 0 < s ∧ s ≤ r ∧ Squarefree s ∧ Hits s n := by - induction r using Nat.strong_induction_on with - | h r ih => - by_cases hsq : Squarefree r - · exact ⟨r, hr, le_rfl, hsq, hhit⟩ - · rcases e : r.minSqFac with _ | d - · exact (hsq (Nat.squarefree_iff_minSqFac.mpr e)).elim - · have hdprime : d.Prime := Nat.minSqFac_prime e - obtain ⟨s, hrs⟩ := Nat.minSqFac_dvd e - have hdpos : 0 < d := hdprime.pos - have hspos : 0 < s := by - rw [hrs] at hr - positivity - have hslt : s < r := by - rw [hrs] - nlinarith [hdprime.two_le] - have hhit_s : Hits s n := by - apply hits_square_mul_imp d s n hdpos - simpa [pow_two, hrs] using hhit - obtain ⟨t, htpos, htle, htsq, hthit⟩ := ih s hslt hspos hhit_s - exact ⟨t, htpos, htle.trans hslt.le, htsq, hthit⟩ - -/-- The squarefree integers in `[2, j)`. -/ -noncomputable def squarefreeBelow (j : ℕ) : Finset ℕ := by - classical - exact (Finset.Ico 2 j).filter Squarefree - -@[simp] theorem mem_squarefreeBelow {j s : ℕ} : - s ∈ squarefreeBelow j ↔ 2 ≤ s ∧ s < j ∧ Squarefree s := by - classical - simp [squarefreeBelow, and_assoc] - -/-- The squarefree radicands relevant to the value `j`, including `j` itself. -/ -noncomputable def relevantRadicands (j : ℕ) : Finset ℕ := - insert j (squarefreeBelow j) - -@[simp] theorem mem_relevantRadicands {j s : ℕ} : - s ∈ relevantRadicands j ↔ s = j ∨ (2 ≤ s ∧ s < j ∧ Squarefree s) := by - classical - simp [relevantRadicands] - -/-- `j` is the least successful radicand exactly when it hits and every smaller squarefree -radicand at least two misses. -/ -theorem isValue_iff_squarefree_competitors (n j : ℕ) (hj : 2 ≤ j) : - IsValue n j ↔ - Hits j n ∧ ∀ s ∈ squarefreeBelow j, ¬ Hits s n := by - constructor - · rintro ⟨_hjpos, hjhit, hminimal⟩ - refine ⟨hjhit, ?_⟩ - intro s hs - have hs' := mem_squarefreeBelow.mp hs - exact hminimal s (lt_of_lt_of_le Nat.zero_lt_two hs'.1) hs'.2.1 - · rintro ⟨hjhit, hsmall⟩ - refine ⟨lt_of_lt_of_le Nat.zero_lt_two hj, hjhit, ?_⟩ - intro r hrpos hrj hrhit - obtain ⟨s, hspos, hsr, hssq, hshit⟩ := exists_squarefree_hit_le r n hrpos hrhit - have hsne : s ≠ 1 := by - intro hs1 - subst s - exact not_hits_one n hshit - have hsge : 2 ≤ s := by omega - have hslt : s < j := lt_of_le_of_lt hsr hrj - exact hsmall s (mem_squarefreeBelow.mpr ⟨hsge, hslt, hssq⟩) hshit - -/-- Fractional-part version of `isValue_iff_squarefree_competitors`. -/ -theorem isValue_iff_coordinateConditions (n j : ℕ) (hj : 2 ≤ j) : - IsValue n j ↔ - CoordinateHit j n ∧ ∀ s ∈ squarefreeBelow j, ¬ CoordinateHit s n := by - rw [isValue_iff_squarefree_competitors n j hj, hits_iff_coordinateHit j n hj] - constructor - · rintro ⟨hjhit, hsmall⟩ - refine ⟨hjhit, ?_⟩ - intro s hs hscoord - have hsge := (mem_squarefreeBelow.mp hs).1 - exact hsmall s hs ((hits_iff_coordinateHit s n hsge).mpr hscoord) - · rintro ⟨hjhit, hsmall⟩ - refine ⟨hjhit, ?_⟩ - intro s hs hshit - have hsge := (mem_squarefreeBelow.mp hs).1 - exact hsmall s hs ((hits_iff_coordinateHit s n hsge).mp hshit) - -/-- Adjoin the rational coordinate `1` to a finite family of radicands. -/ -def radicandWithOne {S : Finset ℕ} : Option S → ℕ - | none => 1 - | some s => s.1 - -/-- Reciprocal radicals indexed by distinct squarefree integers at least two have no integer -relation modulo `1`. -/ -theorem noIntegerRelation_alpha (S : Finset ℕ) - (hge : ∀ s ∈ S, 2 ≤ s) (hsq : ∀ s ∈ S, Squarefree s) : - UnitAddTorus.NoIntegerRelation (fun s : S => alpha s.1) := by - let r : Option S → ℕ := radicandWithOne - have hr_sq : ∀ o, Squarefree (r o) := by - intro o - cases o with - | none => simp [r, radicandWithOne] - | some s => simpa [r, radicandWithOne] using hsq s.1 s.2 - have hr_inj : Function.Injective r := by - intro o₁ o₂ h - cases o₁ with - | none => - cases o₂ with - | none => rfl - | some s => - exfalso - have := hge s.1 s.2 - simp [r, radicandWithOne] at h - omega - | some s => - cases o₂ with - | none => - exfalso - have := hge s.1 s.2 - simp [r, radicandWithOne] at h - omega - | some t => - apply congrArg some - apply Subtype.ext - simpa [r, radicandWithOne] using h - have hli := Real.linearIndependent_inv_sqrt_squarefree r hr_sq hr_inj - intro k hk - obtain ⟨z, hz⟩ := hk - let c : Option S → ℚ - | none => -(z : ℚ) - | some s => (k s : ℚ) - have hsum : - ∑ o, c o • (1 / Real.sqrt (r o : ℝ)) = - ∑ o, (0 : ℚ) • (1 / Real.sqrt (r o : ℝ)) := by - rw [Fintype.sum_option] - simp only [c, r, radicandWithOne, Nat.cast_one, Real.sqrt_one, div_one, - Rat.smul_def, Rat.cast_neg, Rat.cast_intCast, neg_mul, mul_one, - zero_smul, Finset.sum_const_zero] - change -(z : ℝ) + ∑ s : S, (k s : ℝ) * alpha s.1 = 0 - linarith - have hc := (Fintype.linearIndependent_iffₛ.mp hli c (fun _ => 0) hsum) - funext s - have hs := hc (some s) - exact_mod_cast (by simpa [c] using hs) - -/-- The density predicted for the value `j` in OEIS A261865. -/ -noncomputable def predictedDensity (j : ℕ) : ℝ := - alpha j * ∏ s ∈ squarefreeBelow j, (1 - alpha s) - /-- **Peter Kagey's Problem 13 / OEIS A261865.** @@ -303,7 +46,7 @@ supervision. -/ @[category research open, AMS 11] theorem density_formula (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : - {n : ℕ | 0 < n ∧ IsValue n j}.HasDensity (predictedDensity j) := by - sorry + {n : ℕ | 0 < n ∧ IsValue n j}.HasDensity (predictedDensity j) := + density_formula_solution j hj hsq end OeisA261865 diff --git a/FormalConjectures/OEIS/261865Solution.lean b/FormalConjectures/OEIS/261865Solution.lean index dc61883cd1..a9eac34ea4 100644 --- a/FormalConjectures/OEIS/261865Solution.lean +++ b/FormalConjectures/OEIS/261865Solution.lean @@ -15,7 +15,7 @@ limitations under the License. -/ module -public import FormalConjectures.OEIS.«261865» +public import FormalConjectures.OEIS.A261865Base public import FormalConjecturesForMathlib.Analysis.Equidistribution.TerminalBox @[expose] public section @@ -158,4 +158,4 @@ theorem density_formula_solution (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : rw [predictedDensity, product_erase_distinguished] rfl -end OeisA261865 \ No newline at end of file +end OeisA261865 diff --git a/FormalConjectures/OEIS/A261865Base.lean b/FormalConjectures/OEIS/A261865Base.lean new file mode 100644 index 0000000000..d24b22be65 --- /dev/null +++ b/FormalConjectures/OEIS/A261865Base.lean @@ -0,0 +1,275 @@ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ +module + +public import FormalConjecturesUtil +public import FormalConjecturesForMathlib.Analysis.Equidistribution.UnitAddTorus +public import FormalConjecturesForMathlib.NumberTheory.SquarefreeRadicals + +@[expose] public section + +/-! +# OEIS A261865 / Peter Kagey's Problem 13: definitions and reductions +-/ + +open Filter +open scoped BigOperators Topology + +namespace OeisA261865 + +/-- A positive integer multiple of `√k` lies strictly in `(n, n + 1)`. -/ +def Hits (k n : ℕ) : Prop := + ∃ m : ℕ, 0 < m ∧ + (n : ℝ) < (m : ℝ) * Real.sqrt (k : ℝ) ∧ + (m : ℝ) * Real.sqrt (k : ℝ) < (n : ℝ) + 1 + +/-- `k` is the least positive radicand that hits the interval `(n, n + 1)`. -/ +def IsValue (n k : ℕ) : Prop := + 0 < k ∧ Hits k n ∧ ∀ r : ℕ, 0 < r → r < k → ¬ Hits r n + +/-- The rotation parameter `1 / √s`. -/ +noncomputable def alpha (s : ℕ) : ℝ := + 1 / Real.sqrt (s : ℝ) + +/-- The fractional-part condition corresponding to `Hits s n`. -/ +def CoordinateHit (s n : ℕ) : Prop := + 1 - alpha s < Int.fract ((n : ℝ) * alpha s) + +/-- The next positive integer after a nonnegative real `x` lies below `x + a` +exactly when the fractional part of `x` is greater than `1 - a`. -/ +theorem exists_nat_between_iff_fract {x a : ℝ} (hx : 0 ≤ x) : + (∃ m : ℕ, 0 < m ∧ x < (m : ℝ) ∧ (m : ℝ) < x + a) ↔ + 1 - a < Int.fract x := by + constructor + · rintro ⟨m, _hmpos, hxm, hmx⟩ + have hfloor_lt : ⌊x⌋ < (m : ℤ) := + Int.floor_lt.mpr (by simpa using hxm) + have hnext_le : ⌊x⌋ + 1 ≤ (m : ℤ) := by omega + have hnext_le_real : ((⌊x⌋ + 1 : ℤ) : ℝ) ≤ (m : ℝ) := by + exact_mod_cast hnext_le + have hnext_lt : (⌊x⌋ : ℝ) + 1 < x + a := by + exact lt_of_le_of_lt (by simpa using hnext_le_real) hmx + have hdecomp := Int.floor_add_fract x + linarith + · intro hfract + have hfloor_nonneg : 0 ≤ ⌊x⌋ := Int.floor_nonneg.mpr hx + let m : ℕ := ⌊x⌋.toNat + 1 + have hmcast : (m : ℝ) = (⌊x⌋ : ℝ) + 1 := by + simp [m, Int.toNat_of_nonneg hfloor_nonneg] + refine ⟨m, by simp [m], ?_, ?_⟩ + · rw [hmcast] + exact Int.lt_floor_add_one x + · rw [hmcast] + have hdecomp := Int.floor_add_fract x + linarith + +/-- The interval-hitting predicate is exactly an irrational-rotation interval. -/ +theorem hits_iff_coordinateHit (s n : ℕ) (hs : 2 ≤ s) : + Hits s n ↔ CoordinateHit s n := by + have hs_real_pos : (0 : ℝ) < (s : ℝ) := by positivity + have hsqrt_pos : (0 : ℝ) < Real.sqrt (s : ℝ) := Real.sqrt_pos.2 hs_real_pos + have hx : 0 ≤ (n : ℝ) / Real.sqrt (s : ℝ) := + div_nonneg (by positivity) hsqrt_pos.le + constructor + · rintro ⟨m, hmpos, hleft, hright⟩ + have hleft' : (n : ℝ) / Real.sqrt (s : ℝ) < (m : ℝ) := + (div_lt_iff₀ hsqrt_pos).2 hleft + have hright' : (m : ℝ) < + (n : ℝ) / Real.sqrt (s : ℝ) + 1 / Real.sqrt (s : ℝ) := by + have := (lt_div_iff₀ hsqrt_pos).2 hright + convert this using 1 <;> ring + have hfract := (exists_nat_between_iff_fract hx).mp + ⟨m, hmpos, hleft', hright'⟩ + simpa [CoordinateHit, alpha, div_eq_mul_inv] using hfract + · intro hcoord + have hfract : + 1 - 1 / Real.sqrt (s : ℝ) < + Int.fract ((n : ℝ) / Real.sqrt (s : ℝ)) := by + simpa [CoordinateHit, alpha, div_eq_mul_inv] using hcoord + obtain ⟨m, hmpos, hleft, hright⟩ := + (exists_nat_between_iff_fract hx).mpr hfract + refine ⟨m, hmpos, (div_lt_iff₀ hsqrt_pos).mp hleft, ?_⟩ + apply (lt_div_iff₀ hsqrt_pos).mp + convert hright using 1 <;> ring + +/-- The radicand `1` never hits an open unit interval between consecutive integers. -/ +theorem not_hits_one (n : ℕ) : ¬ Hits 1 n := by + rintro ⟨m, _hm, hleft, hright⟩ + have hnm : n < m := by + exact_mod_cast (by simpa using hleft) + have hmn : m < n + 1 := by + exact_mod_cast (by simpa [Nat.cast_add, Nat.cast_one] using hright) + omega + +/-- Removing a positive square factor from a radicand preserves the hitting property. -/ +theorem hits_square_mul_imp (c s n : ℕ) (hc : 0 < c) : + Hits (c ^ 2 * s) n → Hits s n := by + rintro ⟨m, hm, hleft, hright⟩ + have hsqrt : + Real.sqrt ((c ^ 2 * s : ℕ) : ℝ) = + (c : ℝ) * Real.sqrt (s : ℝ) := by + rw [Nat.cast_mul, Nat.cast_pow, Real.sqrt_mul (sq_nonneg (c : ℝ))] + rw [Real.sqrt_sq (Nat.cast_nonneg c)] + refine ⟨m * c, Nat.mul_pos hm hc, ?_, ?_⟩ + · simpa only [hsqrt, Nat.cast_mul, mul_assoc] using hleft + · simpa only [hsqrt, Nat.cast_mul, mul_assoc] using hright + +/-- Every hit descends to a hit by a positive squarefree radicand no larger than the original. -/ +theorem exists_squarefree_hit_le (r n : ℕ) (hr : 0 < r) (hhit : Hits r n) : + ∃ s : ℕ, 0 < s ∧ s ≤ r ∧ Squarefree s ∧ Hits s n := by + induction r using Nat.strong_induction_on with + | h r ih => + by_cases hsq : Squarefree r + · exact ⟨r, hr, le_rfl, hsq, hhit⟩ + · rcases e : r.minSqFac with _ | d + · exact (hsq (Nat.squarefree_iff_minSqFac.mpr e)).elim + · have hdprime : d.Prime := Nat.minSqFac_prime e + obtain ⟨s, hrs⟩ := Nat.minSqFac_dvd e + have hdpos : 0 < d := hdprime.pos + have hspos : 0 < s := by + rw [hrs] at hr + positivity + have hslt : s < r := by + rw [hrs] + nlinarith [hdprime.two_le] + have hhit_s : Hits s n := by + apply hits_square_mul_imp d s n hdpos + simpa [pow_two, hrs] using hhit + obtain ⟨t, htpos, htle, htsq, hthit⟩ := ih s hslt hspos hhit_s + exact ⟨t, htpos, htle.trans hslt.le, htsq, hthit⟩ + +/-- The squarefree integers in `[2, j)`. -/ +noncomputable def squarefreeBelow (j : ℕ) : Finset ℕ := by + classical + exact (Finset.Ico 2 j).filter Squarefree + +@[simp] theorem mem_squarefreeBelow {j s : ℕ} : + s ∈ squarefreeBelow j ↔ 2 ≤ s ∧ s < j ∧ Squarefree s := by + classical + simp [squarefreeBelow, and_assoc] + +/-- The squarefree radicands relevant to the value `j`, including `j` itself. -/ +noncomputable def relevantRadicands (j : ℕ) : Finset ℕ := + insert j (squarefreeBelow j) + +@[simp] theorem mem_relevantRadicands {j s : ℕ} : + s ∈ relevantRadicands j ↔ s = j ∨ (2 ≤ s ∧ s < j ∧ Squarefree s) := by + classical + simp [relevantRadicands] + +/-- `j` is the least successful radicand exactly when it hits and every smaller squarefree +radicand at least two misses. -/ +theorem isValue_iff_squarefree_competitors (n j : ℕ) (hj : 2 ≤ j) : + IsValue n j ↔ + Hits j n ∧ ∀ s ∈ squarefreeBelow j, ¬ Hits s n := by + constructor + · rintro ⟨_hjpos, hjhit, hminimal⟩ + refine ⟨hjhit, ?_⟩ + intro s hs + have hs' := mem_squarefreeBelow.mp hs + exact hminimal s (lt_of_lt_of_le Nat.zero_lt_two hs'.1) hs'.2.1 + · rintro ⟨hjhit, hsmall⟩ + refine ⟨lt_of_lt_of_le Nat.zero_lt_two hj, hjhit, ?_⟩ + intro r hrpos hrj hrhit + obtain ⟨s, hspos, hsr, hssq, hshit⟩ := exists_squarefree_hit_le r n hrpos hrhit + have hsne : s ≠ 1 := by + intro hs1 + subst s + exact not_hits_one n hshit + have hsge : 2 ≤ s := by omega + have hslt : s < j := lt_of_le_of_lt hsr hrj + exact hsmall s (mem_squarefreeBelow.mpr ⟨hsge, hslt, hssq⟩) hshit + +/-- Fractional-part version of `isValue_iff_squarefree_competitors`. -/ +theorem isValue_iff_coordinateConditions (n j : ℕ) (hj : 2 ≤ j) : + IsValue n j ↔ + CoordinateHit j n ∧ ∀ s ∈ squarefreeBelow j, ¬ CoordinateHit s n := by + rw [isValue_iff_squarefree_competitors n j hj, hits_iff_coordinateHit j n hj] + constructor + · rintro ⟨hjhit, hsmall⟩ + refine ⟨hjhit, ?_⟩ + intro s hs hscoord + have hsge := (mem_squarefreeBelow.mp hs).1 + exact hsmall s hs ((hits_iff_coordinateHit s n hsge).mpr hscoord) + · rintro ⟨hjhit, hsmall⟩ + refine ⟨hjhit, ?_⟩ + intro s hs hshit + have hsge := (mem_squarefreeBelow.mp hs).1 + exact hsmall s hs ((hits_iff_coordinateHit s n hsge).mp hshit) + +/-- Adjoin the rational coordinate `1` to a finite family of radicands. -/ +def radicandWithOne {S : Finset ℕ} : Option S → ℕ + | none => 1 + | some s => s.1 + +/-- Reciprocal radicals indexed by distinct squarefree integers at least two have no integer +relation modulo `1`. -/ +theorem noIntegerRelation_alpha (S : Finset ℕ) + (hge : ∀ s ∈ S, 2 ≤ s) (hsq : ∀ s ∈ S, Squarefree s) : + UnitAddTorus.NoIntegerRelation (fun s : S => alpha s.1) := by + let r : Option S → ℕ := radicandWithOne + have hr_sq : ∀ o, Squarefree (r o) := by + intro o + cases o with + | none => simp [r, radicandWithOne] + | some s => simpa [r, radicandWithOne] using hsq s.1 s.2 + have hr_inj : Function.Injective r := by + intro o₁ o₂ h + cases o₁ with + | none => + cases o₂ with + | none => rfl + | some s => + exfalso + have := hge s.1 s.2 + simp [r, radicandWithOne] at h + omega + | some s => + cases o₂ with + | none => + exfalso + have := hge s.1 s.2 + simp [r, radicandWithOne] at h + omega + | some t => + apply congrArg some + apply Subtype.ext + simpa [r, radicandWithOne] using h + have hli := Real.linearIndependent_inv_sqrt_squarefree r hr_sq hr_inj + intro k hk + obtain ⟨z, hz⟩ := hk + let c : Option S → ℚ + | none => -(z : ℚ) + | some s => (k s : ℚ) + have hsum : + ∑ o, c o • (1 / Real.sqrt (r o : ℝ)) = + ∑ o, (0 : ℚ) • (1 / Real.sqrt (r o : ℝ)) := by + rw [Fintype.sum_option] + simp only [c, r, radicandWithOne, Nat.cast_one, Real.sqrt_one, div_one, + Rat.smul_def, Rat.cast_neg, Rat.cast_intCast, neg_mul, mul_one, + zero_smul, Finset.sum_const_zero] + change -(z : ℝ) + ∑ s : S, (k s : ℝ) * alpha s.1 = 0 + linarith + have hc := (Fintype.linearIndependent_iffₛ.mp hli c (fun _ => 0) hsum) + funext s + have hs := hc (some s) + exact_mod_cast (by simpa [c] using hs) + +/-- The density predicted for the value `j` in OEIS A261865. -/ +noncomputable def predictedDensity (j : ℕ) : ℝ := + alpha j * ∏ s ∈ squarefreeBelow j, (1 - alpha s) + +end OeisA261865 From de4d67321b07ed5e947221ba492b4ee9236c3406 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 09:47:01 -0700 Subject: [PATCH 045/115] Audit the exact numbered A261865 theorem --- FormalConjectures/OEIS/261865FinalAudit.lean | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/FormalConjectures/OEIS/261865FinalAudit.lean b/FormalConjectures/OEIS/261865FinalAudit.lean index 8e039dd6f5..f0a7893436 100644 --- a/FormalConjectures/OEIS/261865FinalAudit.lean +++ b/FormalConjectures/OEIS/261865FinalAudit.lean @@ -15,7 +15,7 @@ limitations under the License. -/ module -public import FormalConjectures.OEIS.«261865Solution» +public import FormalConjectures.OEIS.«261865» @[expose] public section @@ -24,9 +24,10 @@ namespace OeisA261865 /-- Exact-statement audit wrapper for Peter Kagey's Problem 13 / OEIS A261865. -/ theorem density_formula_final_audit (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : {n : ℕ | 0 < n ∧ IsValue n j}.HasDensity (predictedDensity j) := - density_formula_solution j hj hsq + density_formula j hj hsq #print axioms density_formula_solution +#print axioms density_formula #print axioms density_formula_final_audit end OeisA261865 From 8976ec13b39ae34c3c5b706551d454a172c9b189 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 09:47:28 -0700 Subject: [PATCH 046/115] Audit the complete sorry-free A261865 module chain --- .github/workflows/a261865-final-audit.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/a261865-final-audit.yml b/.github/workflows/a261865-final-audit.yml index 247e7240d5..c3296bb3de 100644 --- a/.github/workflows/a261865-final-audit.yml +++ b/.github/workflows/a261865-final-audit.yml @@ -8,6 +8,7 @@ on: branches: - a261865-research paths: + - 'FormalConjectures/OEIS/A261865Base.lean' - 'FormalConjectures/OEIS/261865.lean' - 'FormalConjectures/OEIS/261865Solution.lean' - 'FormalConjectures/OEIS/261865FinalAudit.lean' @@ -20,6 +21,7 @@ on: branches: - main paths: + - 'FormalConjectures/OEIS/A261865Base.lean' - 'FormalConjectures/OEIS/261865.lean' - 'FormalConjectures/OEIS/261865Solution.lean' - 'FormalConjectures/OEIS/261865FinalAudit.lean' @@ -66,9 +68,12 @@ jobs: run: | set -euo pipefail files=( + FormalConjectures/OEIS/A261865Base.lean + FormalConjectures/OEIS/261865.lean FormalConjectures/OEIS/261865Solution.lean FormalConjectures/OEIS/261865FinalAudit.lean FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean + FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean @@ -87,6 +92,6 @@ jobs: output=$(lake env lean FormalConjectures/OEIS/261865FinalAudit.lean 2>&1) printf '%s\n' "$output" if grep -q 'sorryAx' <<<"$output"; then - echo 'The exact solution theorem depends on sorryAx.' >&2 + echo 'The exact numbered theorem depends on sorryAx.' >&2 exit 1 fi From b620630a33be4aafebd6199e2947ae12246ffafb Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 09:52:27 -0700 Subject: [PATCH 047/115] Harden the squarefree-radical rationality contradiction --- .../NumberTheory/SquarefreeRadical.lean | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean index 338d8c796c..dbc4236d68 100644 --- a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean +++ b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean @@ -122,7 +122,11 @@ theorem linearIndependent_sqrt_squarefree {ι : Type*} [Fintype ι] have hsq_rat : IsSquare (((s i * s j : ℕ) : ℚ)) := by refine ⟨q, ?_⟩ apply (algebraMap ℚ K).injective - rw [map_mul, ← hq, hmul_sq] + calc + algebraMap ℚ K (((s i * s j : ℕ) : ℚ)) = (root i * root j) ^ 2 := + (hmul_sq i j).symm + _ = (algebraMap ℚ K q) ^ 2 := by rw [← hq] + _ = algebraMap ℚ K (q * q) := by rw [map_mul, pow_two] have hsq_nat : IsSquare (s i * s j) := by rwa [Rat.isSquare_natCast_iff] at hsq_rat exact hij (hinj (Nat.eq_of_squarefree_of_isSquare_mul (hs i) (hs j) hsq_nat)) From d1f81444e0e4235806391df545a344cd8c07a19a Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 09:56:02 -0700 Subject: [PATCH 048/115] Normalize the Fourier zero-frequency condition --- .../Analysis/Equidistribution/UnitAddTorus.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean index a0e7bffbf8..bb44d8470b 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean @@ -201,7 +201,7 @@ lemma integral_mFourier (k : d → ℤ) : ∫ x : UnitAddTorus d, mFourier k x = if k = 0 then 1 else 0 := by have h := (orthonormal_iff_ite.mp (orthonormal_mFourier (d := d))) (0 : d → ℤ) k simpa only [ContinuousMap.inner_toLp, mFourier_zero, ContinuousMap.one_apply, - map_one, one_mul, Pi.zero_apply, neg_zero, zero_add] using h + map_one, one_mul, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h /-- The Cesàro averages of a nontrivial unit-modulus geometric progression tend to zero. -/ lemma tendsto_geom_average_zero {z : ℂ} (hz : z ≠ 1) (hnorm : ‖z‖ = 1) : @@ -255,4 +255,4 @@ theorem tendsto_average_rotation rw [integral_mFourier, if_neg hk] simpa only [mFourier_nsmul] using hgeom -end UnitAddTorus \ No newline at end of file +end UnitAddTorus From a7545f062a2dce60b95d730012c4b9220eedfacf Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 09:58:30 -0700 Subject: [PATCH 049/115] Fix the geometric-series average bound --- .../Analysis/Equidistribution/UnitAddTorus.lean | 1 - 1 file changed, 1 deletion(-) diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean index bb44d8470b..664fcfaf91 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean @@ -215,7 +215,6 @@ lemma tendsto_geom_average_zero {z : ℂ} (hz : z ≠ 1) (hnorm : ‖z‖ = 1) : · simp [hN] have hden : 0 < ‖z - 1‖ := norm_pos_iff.mpr (sub_ne_zero.mpr hz) have hNpos : (0 : ℝ) < N := by exact_mod_cast Nat.pos_of_ne_zero hN - rw [div_div] apply div_le_div_of_nonneg_right _ hNpos.le rw [div_le_iff₀ hden] calc From 6f05943953af5d1276ea29c00e36020bf2b0c813 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 10:02:13 -0700 Subject: [PATCH 050/115] Finish denominator cancellation in the Weyl bound --- .../Analysis/Equidistribution/UnitAddTorus.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean index 664fcfaf91..fe12418926 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean @@ -216,7 +216,7 @@ lemma tendsto_geom_average_zero {z : ℂ} (hz : z ≠ 1) (hnorm : ‖z‖ = 1) : have hden : 0 < ‖z - 1‖ := norm_pos_iff.mpr (sub_ne_zero.mpr hz) have hNpos : (0 : ℝ) < N := by exact_mod_cast Nat.pos_of_ne_zero hN apply div_le_div_of_nonneg_right _ hNpos.le - rw [div_le_iff₀ hden] + apply div_le_div_of_nonneg_right _ hden.le calc ‖z ^ N - 1‖ ≤ ‖z ^ N‖ + ‖(1 : ℂ)‖ := norm_sub_le _ _ _ = 2 := by simp [norm_pow, hnorm] From a69b30c4f8670bb79fc1504d6b289fbdc8cdf8d3 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 10:13:43 -0700 Subject: [PATCH 051/115] Fix pinned AddCircle representative identity --- .../MeasureTheory/Group/UnitAddCircleArc.lean | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean index da4468482f..472428b103 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean @@ -99,8 +99,11 @@ theorem sphere_subset_pair {c r : ℝ} (hr0 : 0 ≤ r) (hr : r < 1 / 2) : have hqabs : |q| ≤ (1 : ℝ) / 2 := by rw [abs_le] constructor <;> linarith [hqmem.1, hqmem.2] - have hqcoe : (q : UnitAddCircle) = x - (c : UnitAddCircle) := - AddCircle.coe_equivIoc + have hqcoe : (q : UnitAddCircle) = x - (c : UnitAddCircle) := by + change (AddCircle.equivIoc (1 : ℝ) (-(1 / 2 : ℝ))).symm + (AddCircle.equivIoc (1 : ℝ) (-(1 / 2 : ℝ)) (x - (c : UnitAddCircle))) = + x - (c : UnitAddCircle) + exact (AddCircle.equivIoc (1 : ℝ) (-(1 / 2 : ℝ))).symm_apply_apply _ have hnorm : ‖(q : UnitAddCircle)‖ = |q| := (AddCircle.norm_coe_eq_abs_iff (1 : ℝ) one_ne_zero).2 (by simpa using hqabs) have habs : |q| = r := by @@ -163,4 +166,4 @@ theorem volume_terminalArc_compl {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : rw [AddCircle.measure_univ, volume_terminalArc ha0 ha1] norm_num [ENNReal.ofReal_sub (ha0.le.trans ha1.le)] -end UnitAddCircle +end UnitAddCircle \ No newline at end of file From 46cbbd696ef2df77558b2b32c01e94a67f3ed87c Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 10:19:06 -0700 Subject: [PATCH 052/115] Fix ENNReal subtraction API in A261865 arc mass --- .../MeasureTheory/Group/UnitAddCircleArc.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean index 472428b103..78d2431c1d 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean @@ -164,6 +164,6 @@ theorem volume_terminalArc_compl {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : volume (terminalArc a)ᶜ = ENNReal.ofReal (1 - a) := by rw [measure_compl (measurableSet_terminalArc a)] rw [AddCircle.measure_univ, volume_terminalArc ha0 ha1] - norm_num [ENNReal.ofReal_sub (ha0.le.trans ha1.le)] + norm_num [ENNReal.ofReal_sub 1 ha0.le] end UnitAddCircle \ No newline at end of file From 7769c9139c67bd37c261e5cc67e0d099e65d5527 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 10:36:31 -0700 Subject: [PATCH 053/115] Fix terminal arc measure via null sphere removal --- .../MeasureTheory/Group/UnitAddCircleArc.lean | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean index 78d2431c1d..39a376c3ad 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean @@ -135,8 +135,8 @@ theorem volume_terminalArc {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : calc volume (terminalArc a) = volume (Metric.closedBall ((1 - a / 2 : ℝ) : UnitAddCircle) (a / 2)) := by - rw [← Metric.ball_union_sphere] - exact (measure_union_null hsphere).symm + rw [← Metric.closedBall_sdiff_sphere] + exact measure_sdiff_null hsphere _ = ENNReal.ofReal a := by rw [AddCircle.volume_closedBall] congr 1 @@ -166,4 +166,4 @@ theorem volume_terminalArc_compl {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : rw [AddCircle.measure_univ, volume_terminalArc ha0 ha1] norm_num [ENNReal.ofReal_sub 1 ha0.le] -end UnitAddCircle \ No newline at end of file +end UnitAddCircle From ab029dc517814720c03615e8a89bfa10907869a9 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 10:38:18 -0700 Subject: [PATCH 054/115] ci: run A261865 exact audit on ubuntu-slim --- .github/workflows/a261865-final-audit.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/a261865-final-audit.yml b/.github/workflows/a261865-final-audit.yml index c3296bb3de..74ef2ed91f 100644 --- a/.github/workflows/a261865-final-audit.yml +++ b/.github/workflows/a261865-final-audit.yml @@ -42,8 +42,8 @@ concurrency: jobs: lean-final: name: Lean 4.27 exact theorem and axiom audit - runs-on: ubuntu-latest - timeout-minutes: 45 + runs-on: ubuntu-slim + timeout-minutes: 15 steps: - name: Checkout project uses: actions/checkout@v4 @@ -94,4 +94,4 @@ jobs: if grep -q 'sorryAx' <<<"$output"; then echo 'The exact numbered theorem depends on sorryAx.' >&2 exit 1 - fi + fi \ No newline at end of file From a47b31bc4a4e6e26753fff2a5b8d7ab2c56c3138 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 10:38:43 -0700 Subject: [PATCH 055/115] Fix pinned Mathlib closed-ball identity name --- .../MeasureTheory/Group/UnitAddCircleArc.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean index 39a376c3ad..8d37311d3f 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean @@ -135,7 +135,7 @@ theorem volume_terminalArc {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : calc volume (terminalArc a) = volume (Metric.closedBall ((1 - a / 2 : ℝ) : UnitAddCircle) (a / 2)) := by - rw [← Metric.closedBall_sdiff_sphere] + rw [← Metric.closedBall_diff_sphere] exact measure_sdiff_null hsphere _ = ENNReal.ofReal a := by rw [AddCircle.volume_closedBall] @@ -166,4 +166,4 @@ theorem volume_terminalArc_compl {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : rw [AddCircle.measure_univ, volume_terminalArc ha0 ha1] norm_num [ENNReal.ofReal_sub 1 ha0.le] -end UnitAddCircle +end UnitAddCircle \ No newline at end of file From 992bbdb53583c1afe2714e433f8c67841d144ffb Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 10:44:27 -0700 Subject: [PATCH 056/115] ci: run focused A261865 audit on ARM Ubuntu --- .github/workflows/a261865-final-audit.yml | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/.github/workflows/a261865-final-audit.yml b/.github/workflows/a261865-final-audit.yml index 74ef2ed91f..38e4db01a6 100644 --- a/.github/workflows/a261865-final-audit.yml +++ b/.github/workflows/a261865-final-audit.yml @@ -17,19 +17,6 @@ on: - 'FormalConjecturesForMathlib/MeasureTheory/Probability/**' - 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical*.lean' - '.github/workflows/a261865-final-audit.yml' - pull_request: - branches: - - main - paths: - - 'FormalConjectures/OEIS/A261865Base.lean' - - 'FormalConjectures/OEIS/261865.lean' - - 'FormalConjectures/OEIS/261865Solution.lean' - - 'FormalConjectures/OEIS/261865FinalAudit.lean' - - 'FormalConjecturesForMathlib/Analysis/Equidistribution/**' - - 'FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean' - - 'FormalConjecturesForMathlib/MeasureTheory/Probability/**' - - 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical*.lean' - - '.github/workflows/a261865-final-audit.yml' workflow_dispatch: permissions: @@ -42,8 +29,8 @@ concurrency: jobs: lean-final: name: Lean 4.27 exact theorem and axiom audit - runs-on: ubuntu-slim - timeout-minutes: 15 + runs-on: ubuntu-24.04-arm + timeout-minutes: 30 steps: - name: Checkout project uses: actions/checkout@v4 From ebc309ea7ff5f60d425158ad07b18a748af25000 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 10:45:35 -0700 Subject: [PATCH 057/115] ci: expose focused A261865 ARM audit on PR --- .github/workflows/a261865-final-audit.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/a261865-final-audit.yml b/.github/workflows/a261865-final-audit.yml index 38e4db01a6..1d871e607a 100644 --- a/.github/workflows/a261865-final-audit.yml +++ b/.github/workflows/a261865-final-audit.yml @@ -4,9 +4,9 @@ name: A261865 final theorem audit on: - push: + pull_request: branches: - - a261865-research + - main paths: - 'FormalConjectures/OEIS/A261865Base.lean' - 'FormalConjectures/OEIS/261865.lean' From d0660ab3330a716d771da2806b27b69201873b66 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 10:54:06 -0700 Subject: [PATCH 058/115] ci: run focused A261865 audit on ubuntu-slim --- .github/workflows/a261865-final-audit.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/a261865-final-audit.yml b/.github/workflows/a261865-final-audit.yml index 1d871e607a..02037ca43c 100644 --- a/.github/workflows/a261865-final-audit.yml +++ b/.github/workflows/a261865-final-audit.yml @@ -29,8 +29,8 @@ concurrency: jobs: lean-final: name: Lean 4.27 exact theorem and axiom audit - runs-on: ubuntu-24.04-arm - timeout-minutes: 30 + runs-on: ubuntu-slim + timeout-minutes: 15 steps: - name: Checkout project uses: actions/checkout@v4 @@ -81,4 +81,4 @@ jobs: if grep -q 'sorryAx' <<<"$output"; then echo 'The exact numbered theorem depends on sorryAx.' >&2 exit 1 - fi \ No newline at end of file + fi From 2070c24a974014adecf8566dc60fa19ea44d685c Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 10:54:58 -0700 Subject: [PATCH 059/115] ci: add independent macOS A261865 audit --- .github/workflows/a261865-macos-audit.yml | 84 +++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 .github/workflows/a261865-macos-audit.yml diff --git a/.github/workflows/a261865-macos-audit.yml b/.github/workflows/a261865-macos-audit.yml new file mode 100644 index 0000000000..6e6d12a839 --- /dev/null +++ b/.github/workflows/a261865-macos-audit.yml @@ -0,0 +1,84 @@ +# Copyright 2026 The Formal Conjectures Authors. +# Licensed under the Apache License, Version 2.0. + +name: A261865 macOS exact audit + +on: + pull_request: + branches: + - main + paths: + - 'FormalConjectures/OEIS/A261865Base.lean' + - 'FormalConjectures/OEIS/261865.lean' + - 'FormalConjectures/OEIS/261865Solution.lean' + - 'FormalConjectures/OEIS/261865FinalAudit.lean' + - 'FormalConjecturesForMathlib/Analysis/Equidistribution/**' + - 'FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean' + - 'FormalConjecturesForMathlib/MeasureTheory/Probability/**' + - 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical*.lean' + - '.github/workflows/a261865-macos-audit.yml' + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: a261865-macos-${{ github.ref }} + cancel-in-progress: true + +jobs: + lean-final-macos: + name: Lean 4.27 exact theorem and axiom audit (macOS) + runs-on: macos-15 + timeout-minutes: 45 + steps: + - name: Checkout project + uses: actions/checkout@v4 + + - name: Install pinned Lean toolchain + shell: bash + run: | + set -euo pipefail + curl -fsSL https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh \ + | sh -s -- -y --default-toolchain none + echo "$HOME/.elan/bin" >> "$GITHUB_PATH" + "$HOME/.elan/bin/elan" toolchain install leanprover/lean4:v4.27.0 + + - name: Fetch Mathlib cache + shell: bash + run: | + set -euo pipefail + lake exe cache get + + - name: Reject placeholders in the solution chain + shell: bash + run: | + set -euo pipefail + files=( + FormalConjectures/OEIS/A261865Base.lean + FormalConjectures/OEIS/261865.lean + FormalConjectures/OEIS/261865Solution.lean + FormalConjectures/OEIS/261865FinalAudit.lean + FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean + FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean + FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean + FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean + FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean + FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean + FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean + ) + if grep -nE '\b(sorry|admit)\b|native_decide|unsafe|^axiom\b' "${files[@]}"; then + echo 'Forbidden proof placeholder or trust escape found.' >&2 + exit 1 + fi + + - name: Compile exact final theorem + shell: bash + run: | + set -euo pipefail + output=$(lake env lean FormalConjectures/OEIS/261865FinalAudit.lean 2>&1) + printf '%s\n' "$output" + if grep -q 'sorryAx' <<<"$output"; then + echo 'The exact numbered theorem depends on sorryAx.' >&2 + exit 1 + fi From 4058c9aa3cd53990a88cb3757520d7bee1e28927 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 10:56:15 -0700 Subject: [PATCH 060/115] ci: run A261865 AXLE foundation audit on ubuntu-slim --- .github/workflows/a261865-axle-audit.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/a261865-axle-audit.yml b/.github/workflows/a261865-axle-audit.yml index cf284c0047..be25a35849 100644 --- a/.github/workflows/a261865-axle-audit.yml +++ b/.github/workflows/a261865-axle-audit.yml @@ -13,10 +13,14 @@ on: permissions: contents: read +concurrency: + group: a261865-axle-${{ github.ref }} + cancel-in-progress: true + jobs: check-foundation: name: Check A261865 foundations with AXLE - runs-on: ubuntu-latest + runs-on: ubuntu-slim timeout-minutes: 15 steps: - uses: actions/checkout@v4 From 105aa052be729fb58572d4ec96965bf903d5c27f Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 11:03:16 -0700 Subject: [PATCH 061/115] Fix pinned measure-difference lemma in A261865 arc proof --- .../MeasureTheory/Group/UnitAddCircleArc.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean index 8d37311d3f..8d5b813d78 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean @@ -136,7 +136,7 @@ theorem volume_terminalArc {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : volume (terminalArc a) = volume (Metric.closedBall ((1 - a / 2 : ℝ) : UnitAddCircle) (a / 2)) := by rw [← Metric.closedBall_diff_sphere] - exact measure_sdiff_null hsphere + exact measure_diff_null hsphere _ = ENNReal.ofReal a := by rw [AddCircle.volume_closedBall] congr 1 From f4002bf3d9553785f1d8e2ad28d59a3247923b29 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 11:03:39 -0700 Subject: [PATCH 062/115] Fix Weyl closure approximation orientation --- .../Analysis/Equidistribution/UnitAddTorus.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean index fe12418926..2801589325 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean @@ -91,7 +91,7 @@ theorem tendsto_average_of_tendsto_mFourier Submodule.top_coe] exact Set.mem_univ F obtain ⟨p, hp, hdist⟩ := Metric.mem_closure_iff.mp hF (ε / 3) (by positivity) - rw [dist_eq_norm] at hdist + rw [dist_eq_norm, norm_sub_rev] at hdist obtain ⟨N₀, hN₀⟩ := (Metric.tendsto_atTop.mp (hspan p hp)) (ε / 3) (by positivity) refine ⟨N₀, fun N hN => ?_⟩ @@ -254,4 +254,4 @@ theorem tendsto_average_rotation rw [integral_mFourier, if_neg hk] simpa only [mFourier_nsmul] using hgeom -end UnitAddTorus +end UnitAddTorus \ No newline at end of file From bb74acc3b46de53c01f9e1c1d337747c63f693ac Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 11:05:04 -0700 Subject: [PATCH 063/115] Align torus volume with Fourier Haar normalization --- .../Analysis/Equidistribution/UnitAddTorus.lean | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean index 2801589325..408d1f3c7c 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean @@ -38,6 +38,17 @@ namespace UnitAddTorus variable {d : Type*} [Fintype d] +/-- On a unit torus, the standard product volume is the product of the probability-normalized +Haar measures used by Mathlib's Fourier basis. -/ +lemma volume_eq_fourierVolume : + (volume : Measure (UnitAddTorus d)) = + Measure.pi (fun _ : d => AddCircle.haarAddCircle) := by + change Measure.pi (fun _ : d => (volume : Measure UnitAddCircle)) = + Measure.pi (fun _ : d => AddCircle.haarAddCircle) + apply congrArg (fun μ : d → Measure UnitAddCircle => Measure.pi μ) + funext i + simpa using (AddCircle.volume_eq_smul_haarAddCircle (T := (1 : ℝ))) + /-- **Continuous Weyl criterion on a finite unit torus.** @@ -199,6 +210,7 @@ lemma mFourier_coe_ne_one {a : d → ℝ} (ha : NoIntegerRelation a) otherwise. -/ lemma integral_mFourier (k : d → ℤ) : ∫ x : UnitAddTorus d, mFourier k x = if k = 0 then 1 else 0 := by + rw [volume_eq_fourierVolume (d := d)] have h := (orthonormal_iff_ite.mp (orthonormal_mFourier (d := d))) (0 : d → ℤ) k simpa only [ContinuousMap.inner_toLp, mFourier_zero, ContinuousMap.one_apply, map_one, one_mul, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h @@ -254,4 +266,4 @@ theorem tendsto_average_rotation rw [integral_mFourier, if_neg hk] simpa only [mFourier_nsmul] using hgeom -end UnitAddTorus \ No newline at end of file +end UnitAddTorus From 140c6c3c2229fb4b20f7a0d38310f2bb2d202ecf Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 11:06:50 -0700 Subject: [PATCH 064/115] Supply finiteness to pinned measure_compl --- .../MeasureTheory/Group/UnitAddCircleArc.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean index 8d5b813d78..7c869613fa 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean @@ -162,7 +162,7 @@ theorem volume_frontier_terminalArc_compl {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) /-- The complement of a terminal arc has length `1-a`. -/ theorem volume_terminalArc_compl {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : volume (terminalArc a)ᶜ = ENNReal.ofReal (1 - a) := by - rw [measure_compl (measurableSet_terminalArc a)] + rw [measure_compl (measurableSet_terminalArc a) (measure_ne_top _ _)] rw [AddCircle.measure_univ, volume_terminalArc ha0 ha1] norm_num [ENNReal.ofReal_sub 1 ha0.le] From e4064a059b103238c3003bfd461a015e83fd27e7 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 11:09:21 -0700 Subject: [PATCH 065/115] Fix pinned reciprocal inequality in A261865 solution --- FormalConjectures/OEIS/261865Solution.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FormalConjectures/OEIS/261865Solution.lean b/FormalConjectures/OEIS/261865Solution.lean index a9eac34ea4..11ca061d52 100644 --- a/FormalConjectures/OEIS/261865Solution.lean +++ b/FormalConjectures/OEIS/261865Solution.lean @@ -37,7 +37,7 @@ theorem alpha_lt_one_of_two_le {s : ℕ} (hs : 2 ≤ s) : alpha s < 1 := by have hsqrtone : 1 < Real.sqrt (s : ℝ) := by nlinarith [show (2 : ℝ) ≤ s by exact_mod_cast hs] unfold alpha - exact (one_div_lt_one₀ hsqrtpos).2 hsqrtone + exact (div_lt_one hsqrtpos).2 hsqrtone /-- The distinguished element `j` as an element of the relevant-radicand subtype. -/ noncomputable def distinguishedRadicand (j : ℕ) : relevantRadicands j := @@ -158,4 +158,4 @@ theorem density_formula_solution (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : rw [predictedDensity, product_erase_distinguished] rfl -end OeisA261865 +end OeisA261865 \ No newline at end of file From 043ac13c8008d0af195c49a9d64fe9a0d8043f94 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 11:11:15 -0700 Subject: [PATCH 066/115] Correct the endpoint order in the circle sphere lemma --- .../MeasureTheory/Group/UnitAddCircleArc.lean | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean index 7c869613fa..872d6d70f7 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean @@ -112,13 +112,17 @@ theorem sphere_subset_pair {c r : ℝ} (hr0 : 0 ≤ r) (hr : r < 1 / 2) : _ = ‖x - (c : UnitAddCircle)‖ := congrArg norm hqcoe _ = dist x (c : UnitAddCircle) := by rw [dist_eq_norm] _ = r := Metric.mem_sphere.mp hx - rcases abs_eq (show 0 ≤ r from hr0) |>.mp habs with hq | hq - · left - apply sub_eq_iff_eq_add.mp - simpa [hq, sub_eq_add_neg, add_comm, add_left_comm, add_assoc] using hqcoe.symm + rcases (abs_eq hr0).mp habs with hq | hq · right - apply sub_eq_iff_eq_add.mp - simpa [hq, sub_eq_add_neg, add_comm, add_left_comm, add_assoc] using hqcoe.symm + have hsub : x - (c : UnitAddCircle) = (r : UnitAddCircle) := by + simpa [hq] using hqcoe.symm + have hx' := sub_eq_iff_eq_add.mp hsub + simpa [add_comm] using hx' + · left + have hsub : x - (c : UnitAddCircle) = ((-r : ℝ) : UnitAddCircle) := by + simpa [hq] using hqcoe.symm + have hx' := sub_eq_iff_eq_add.mp hsub + simpa [sub_eq_add_neg, add_comm] using hx' /-- Small spheres in the unit additive circle have Haar measure zero. -/ theorem volume_sphere_eq_zero {c r : ℝ} (hr0 : 0 ≤ r) (hr : r < 1 / 2) : @@ -135,8 +139,8 @@ theorem volume_terminalArc {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : calc volume (terminalArc a) = volume (Metric.closedBall ((1 - a / 2 : ℝ) : UnitAddCircle) (a / 2)) := by - rw [← Metric.closedBall_diff_sphere] - exact measure_diff_null hsphere + rw [← Metric.closedBall_sdiff_sphere] + exact measure_sdiff_null hsphere _ = ENNReal.ofReal a := by rw [AddCircle.volume_closedBall] congr 1 @@ -166,4 +170,4 @@ theorem volume_terminalArc_compl {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : rw [AddCircle.measure_univ, volume_terminalArc ha0 ha1] norm_num [ENNReal.ofReal_sub 1 ha0.le] -end UnitAddCircle \ No newline at end of file +end UnitAddCircle From d09f71e2b474999a95911b1d23d08a954df6f8e0 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 11:13:19 -0700 Subject: [PATCH 067/115] Restore pinned Mathlib circle measure names --- .../MeasureTheory/Group/UnitAddCircleArc.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean index 872d6d70f7..45c6a20941 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean @@ -139,8 +139,8 @@ theorem volume_terminalArc {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : calc volume (terminalArc a) = volume (Metric.closedBall ((1 - a / 2 : ℝ) : UnitAddCircle) (a / 2)) := by - rw [← Metric.closedBall_sdiff_sphere] - exact measure_sdiff_null hsphere + rw [← Metric.closedBall_diff_sphere] + exact measure_diff_null hsphere _ = ENNReal.ofReal a := by rw [AddCircle.volume_closedBall] congr 1 From 5b3ccda7acf695b52fd6c9c2716ad06e13e0a544 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 11:16:36 -0700 Subject: [PATCH 068/115] Use the same finite index set on both sides of the Fourier character identity --- .../Analysis/Equidistribution/UnitAddTorus.lean | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean index 408d1f3c7c..f7fd0a4f82 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean @@ -179,7 +179,8 @@ lemma mFourier_eq_toCircle_sum (k : d → ℤ) (x : UnitAddTorus d) : classical simp only [mFourier, ContinuousMap.coe_mk, fourier_apply] let s : Finset d := Finset.univ - change (∏ i ∈ s, ((AddCircle.toCircle (k i • x i) : Circle) : ℂ)) = _ + change (∏ i ∈ s, ((AddCircle.toCircle (k i • x i) : Circle) : ℂ)) = + ((AddCircle.toCircle (∑ i ∈ s, k i • x i) : Circle) : ℂ) induction s using Finset.induction_on with | empty => simp | @insert a s ha ih => From 8fe2da85a6196df5e22693ccda559d8a18b925df Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 11:17:46 -0700 Subject: [PATCH 069/115] Simplify circle boundary measure via Mathlib AE ball theorem --- .../MeasureTheory/Group/UnitAddCircleArc.lean | 60 +++++-------------- 1 file changed, 15 insertions(+), 45 deletions(-) diff --git a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean index 45c6a20941..1862620976 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean @@ -88,59 +88,29 @@ theorem nsmul_mem_terminalArc_iff {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) (n : ℕ rw [coe_fract_eq] exact coe_mem_terminalArc_iff ha0 ha1 hfract -/-- A sphere of radius less than half the period has at most two points. -/ -theorem sphere_subset_pair {c r : ℝ} (hr0 : 0 ≤ r) (hr : r < 1 / 2) : - Metric.sphere (c : UnitAddCircle) r ⊆ - {((c - r : ℝ) : UnitAddCircle), ((c + r : ℝ) : UnitAddCircle)} := by - intro x hx - let q : ℝ := (AddCircle.equivIoc (1 : ℝ) (-(1 / 2 : ℝ)) (x - (c : UnitAddCircle))).1 - have hqmem : q ∈ Set.Ioc (-(1 / 2 : ℝ)) (-(1 / 2 : ℝ) + 1) := - (AddCircle.equivIoc (1 : ℝ) (-(1 / 2 : ℝ)) (x - (c : UnitAddCircle))).2 - have hqabs : |q| ≤ (1 : ℝ) / 2 := by - rw [abs_le] - constructor <;> linarith [hqmem.1, hqmem.2] - have hqcoe : (q : UnitAddCircle) = x - (c : UnitAddCircle) := by - change (AddCircle.equivIoc (1 : ℝ) (-(1 / 2 : ℝ))).symm - (AddCircle.equivIoc (1 : ℝ) (-(1 / 2 : ℝ)) (x - (c : UnitAddCircle))) = - x - (c : UnitAddCircle) - exact (AddCircle.equivIoc (1 : ℝ) (-(1 / 2 : ℝ))).symm_apply_apply _ - have hnorm : ‖(q : UnitAddCircle)‖ = |q| := - (AddCircle.norm_coe_eq_abs_iff (1 : ℝ) one_ne_zero).2 (by simpa using hqabs) - have habs : |q| = r := by - calc - |q| = ‖(q : UnitAddCircle)‖ := hnorm.symm - _ = ‖x - (c : UnitAddCircle)‖ := congrArg norm hqcoe - _ = dist x (c : UnitAddCircle) := by rw [dist_eq_norm] - _ = r := Metric.mem_sphere.mp hx - rcases (abs_eq hr0).mp habs with hq | hq - · right - have hsub : x - (c : UnitAddCircle) = (r : UnitAddCircle) := by - simpa [hq] using hqcoe.symm - have hx' := sub_eq_iff_eq_add.mp hsub - simpa [add_comm] using hx' - · left - have hsub : x - (c : UnitAddCircle) = ((-r : ℝ) : UnitAddCircle) := by - simpa [hq] using hqcoe.symm - have hx' := sub_eq_iff_eq_add.mp hsub - simpa [sub_eq_add_neg, add_comm] using hx' - -/-- Small spheres in the unit additive circle have Haar measure zero. -/ -theorem volume_sphere_eq_zero {c r : ℝ} (hr0 : 0 ≤ r) (hr : r < 1 / 2) : +/-- Spheres in the additive circle have Haar measure zero. -/ +theorem volume_sphere_eq_zero {c r : ℝ} (_hr0 : 0 ≤ r) (_hr : r < 1 / 2) : volume (Metric.sphere (c : UnitAddCircle) r) = 0 := by - apply measure_mono_null (sphere_subset_pair hr0 hr) - simp + rw [← ae_eq_empty] + filter_upwards [AddCircle.closedBall_ae_eq_ball + (x := (c : UnitAddCircle)) (ε := r)] with y hy + simp only [Set.mem_empty_iff_false, iff_false] + intro hysphere + have hclosed : y ∈ Metric.closedBall (c : UnitAddCircle) r := + Metric.mem_closedBall.mpr (Metric.mem_sphere.mp hysphere).le + have hball : y ∈ Metric.ball (c : UnitAddCircle) r := by + rw [← hy] + exact hclosed + exact (Metric.mem_ball.mp hball).ne (Metric.mem_sphere.mp hysphere) /-- The terminal arc has length `a`. -/ theorem volume_terminalArc {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : volume (terminalArc a) = ENNReal.ofReal a := by - have hsphere : - volume (Metric.sphere ((1 - a / 2 : ℝ) : UnitAddCircle) (a / 2)) = 0 := - volume_sphere_eq_zero (by positivity) (by linarith) calc volume (terminalArc a) = volume (Metric.closedBall ((1 - a / 2 : ℝ) : UnitAddCircle) (a / 2)) := by - rw [← Metric.closedBall_diff_sphere] - exact measure_diff_null hsphere + exact measure_congr (AddCircle.closedBall_ae_eq_ball + (x := ((1 - a / 2 : ℝ) : UnitAddCircle)) (ε := a / 2)).symm _ = ENNReal.ofReal a := by rw [AddCircle.volume_closedBall] congr 1 From 4478d2243882e04a3ad3c70d15e7c1a970e14174 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 11:19:30 -0700 Subject: [PATCH 070/115] Import additive-circle AE ball theorem --- .../MeasureTheory/Group/UnitAddCircleArc.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean index 1862620976..4f0975c661 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean @@ -15,7 +15,7 @@ limitations under the License. -/ module -public import Mathlib.MeasureTheory.Integral.IntervalIntegral.Periodic +public import Mathlib.MeasureTheory.Group.AddCircle public import Mathlib.Analysis.Normed.Group.AddCircle @[expose] public section From c447fb53349afbea8776ff6efb5bb98169daae12 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 11:22:27 -0700 Subject: [PATCH 071/115] ci: restore supported runner for A261865 audit --- .github/workflows/a261865-final-audit.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/a261865-final-audit.yml b/.github/workflows/a261865-final-audit.yml index 02037ca43c..bbd1ef533d 100644 --- a/.github/workflows/a261865-final-audit.yml +++ b/.github/workflows/a261865-final-audit.yml @@ -29,8 +29,8 @@ concurrency: jobs: lean-final: name: Lean 4.27 exact theorem and axiom audit - runs-on: ubuntu-slim - timeout-minutes: 15 + runs-on: ubuntu-latest + timeout-minutes: 45 steps: - name: Checkout project uses: actions/checkout@v4 @@ -81,4 +81,4 @@ jobs: if grep -q 'sorryAx' <<<"$output"; then echo 'The exact numbered theorem depends on sorryAx.' >&2 exit 1 - fi + fi \ No newline at end of file From 6eb3db9cbc28706eeb9cb98dea80043f2d5c778f Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 11:23:56 -0700 Subject: [PATCH 072/115] Register standard unit-circle volume as probability --- .../Analysis/Equidistribution/UnitAddTorus.lean | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean index f7fd0a4f82..647554580d 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean @@ -38,6 +38,12 @@ namespace UnitAddTorus variable {d : Type*} [Fintype d] +/-- The standard Haar volume on `UnitAddCircle = AddCircle 1` has total mass one. -/ +instance unitAddCircleVolume_isProbabilityMeasure : + IsProbabilityMeasure (volume : Measure UnitAddCircle) := + IsProbabilityMeasure.mk (by + simpa using (AddCircle.measure_univ (T := (1 : ℝ)))) + /-- On a unit torus, the standard product volume is the product of the probability-normalized Haar measures used by Mathlib's Fourier basis. -/ lemma volume_eq_fourierVolume : @@ -179,8 +185,7 @@ lemma mFourier_eq_toCircle_sum (k : d → ℤ) (x : UnitAddTorus d) : classical simp only [mFourier, ContinuousMap.coe_mk, fourier_apply] let s : Finset d := Finset.univ - change (∏ i ∈ s, ((AddCircle.toCircle (k i • x i) : Circle) : ℂ)) = - ((AddCircle.toCircle (∑ i ∈ s, k i • x i) : Circle) : ℂ) + change (∏ i ∈ s, ((AddCircle.toCircle (k i • x i) : Circle) : ℂ)) = _ induction s using Finset.induction_on with | empty => simp | @insert a s ha ih => From b7900bdec52936ebc312dd763ed9bbfd78d3f7f0 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 11:27:31 -0700 Subject: [PATCH 073/115] Fix Fourier character induction motive --- .../Analysis/Equidistribution/UnitAddTorus.lean | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean index 647554580d..7ceca61ee4 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean @@ -185,7 +185,8 @@ lemma mFourier_eq_toCircle_sum (k : d → ℤ) (x : UnitAddTorus d) : classical simp only [mFourier, ContinuousMap.coe_mk, fourier_apply] let s : Finset d := Finset.univ - change (∏ i ∈ s, ((AddCircle.toCircle (k i • x i) : Circle) : ℂ)) = _ + change (∏ i ∈ s, ((AddCircle.toCircle (k i • x i) : Circle) : ℂ)) = + ((AddCircle.toCircle (∑ i ∈ s, k i • x i) : Circle) : ℂ) induction s using Finset.induction_on with | empty => simp | @insert a s ha ih => @@ -272,4 +273,4 @@ theorem tendsto_average_rotation rw [integral_mFourier, if_neg hk] simpa only [mFourier_nsmul] using hgeom -end UnitAddTorus +end UnitAddTorus \ No newline at end of file From 842aaf6602bf8bbb018c200882e39137ad15ea31 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 11:53:11 -0700 Subject: [PATCH 074/115] Fix minimal-polynomial equality orientation --- .../NumberTheory/SquarefreeRadical.lean | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean index dbc4236d68..d2c8c52813 100644 --- a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean +++ b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean @@ -75,8 +75,8 @@ theorem trace_eq_zero_of_sq_ratCast {K : Type*} [Field K] [NumberField K] {x : K · exact hx (minpoly.natDegree_eq_one_iff.mp hh) omega have heq : minpoly ℚ x = X ^ 2 - C r := - (Polynomial.eq_of_monic_of_dvd_of_natDegree_le (minpoly.monic hint) hmonic hdvd - (by rw [hdeg2, Polynomial.natDegree_X_pow_sub_C])).symm + Polynomial.eq_of_monic_of_dvd_of_natDegree_le (minpoly.monic hint) hmonic hdvd + (by rw [hdeg2, Polynomial.natDegree_X_pow_sub_C]) rw [trace_eq_finrank_mul_minpoly_nextCoeff, heq] have hnc : (X ^ 2 - C r : ℚ[X]).nextCoeff = 0 := by rw [Polynomial.nextCoeff_of_natDegree_pos @@ -166,4 +166,4 @@ theorem linearIndependent_sqrt_squarefree {ι : Type*} [Fintype ι] have himage := hrootK.map' inc hinc simpa [Function.comp_def, root, inc] using himage -end Real +end Real \ No newline at end of file From 02688846b7a0d44e208cef7581bbdbb3978813c6 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 11:57:03 -0700 Subject: [PATCH 075/115] Make square witness factorization rewrite direct --- .../NumberTheory/SquarefreeRadical.lean | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean index d2c8c52813..8eed862234 100644 --- a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean +++ b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean @@ -36,7 +36,9 @@ theorem eq_of_squarefree_of_isSquare_mul {a b : ℕ} (ha : Squarefree a) (hb : S calc a.factorization p + b.factorization p = (a * b).factorization p := by rw [factorization_mul ha.ne_zero hb.ne_zero] - _ = (c ^ 2).factorization p := by rw [← hc, sq] + _ = (c ^ 2).factorization p := by + congr 1 + simpa [pow_two] using hc _ = 2 * c.factorization p := by simp [factorization_pow] constructor · intro hpa From eecdbc491e55990ef93cbc4b1c047298b301b41a Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 15:32:41 -0700 Subject: [PATCH 076/115] ci: apply first A261865 Lean repair batch --- .github/workflows/a261865-one-shot-repair.yml | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 .github/workflows/a261865-one-shot-repair.yml diff --git a/.github/workflows/a261865-one-shot-repair.yml b/.github/workflows/a261865-one-shot-repair.yml new file mode 100644 index 0000000000..c78db09cff --- /dev/null +++ b/.github/workflows/a261865-one-shot-repair.yml @@ -0,0 +1,111 @@ +name: Apply first A261865 Lean repair batch + +on: + push: + branches: [a261865-research] + paths: + - '.github/workflows/a261865-one-shot-repair.yml' + workflow_dispatch: + +permissions: + contents: write + +jobs: + repair: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout proof branch + uses: actions/checkout@v4 + with: + ref: a261865-research + fetch-depth: 0 + + - name: Apply exact Lean repairs + shell: bash + run: | + python3 - <<'PY' + from pathlib import Path + + def replace_once(path: str, old: str, new: str) -> None: + p = Path(path) + text = p.read_text() + count = text.count(old) + if count != 1: + raise SystemExit(f'{path}: expected one match, found {count}: {old!r}') + p.write_text(text.replace(old, new, 1)) + + sq = 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean' + replace_once(sq, + ' rw [ha.ext_iff hb]\n intro p hp\n', + ' apply (Squarefree.ext_iff ha hb).2\n intro p hp\n') + replace_once(sq, + ' have heq : minpoly ℚ x = X ^ 2 - C r :=\n' + ' Polynomial.eq_of_monic_of_dvd_of_natDegree_le (minpoly.monic hint) hmonic hdvd\n' + ' (by rw [hdeg2, Polynomial.natDegree_X_pow_sub_C])\n', + ' have heq_rev : X ^ 2 - C r = minpoly ℚ x :=\n' + ' Polynomial.eq_of_monic_of_dvd_of_natDegree_le\n' + ' (p := minpoly ℚ x) (q := X ^ 2 - C r)\n' + ' (minpoly.monic hint) hmonic hdvd\n' + ' (by rw [hdeg2, Polynomial.natDegree_X_pow_sub_C])\n' + ' have heq : minpoly ℚ x = X ^ 2 - C r := heq_rev.symm\n') + replace_once(sq, + ' refine ⟨Polynomial.X ^ 2 - Polynomial.C (s i : ℚ), ?_, ?_⟩\n' + ' · exact Polynomial.monic_X_pow_sub_C _ two_ne_zero\n' + ' · norm_num [← Polynomial.C_pow]\n' + ' norm_cast\n' + ' rw [Real.sq_sqrt (Nat.cast_nonneg _)]\n' + ' ring\n', + ' refine ⟨Polynomial.X ^ 2 - Polynomial.C (s i : ℚ),\n' + ' Polynomial.monic_X_pow_sub_C _ two_ne_zero, ?_⟩\n' + ' norm_num [← Polynomial.C_pow]\n' + ' rw [Real.sq_sqrt (Nat.cast_nonneg _)]\n' + ' norm_num\n') + replace_once(sq, + ' have hroot_sq (i : ι) : (root i) ^ 2 = algebraMap ℚ K (s i : ℚ) := by\n' + ' apply Subtype.ext\n' + ' simp only [root]\n' + ' push_cast\n' + ' rw [Real.sq_sqrt (Nat.cast_nonneg _)]\n' + ' norm_cast\n', + ' have hroot_sq (i : ι) : (root i) ^ 2 = algebraMap ℚ K (s i : ℚ) := by\n' + ' apply Subtype.ext\n' + ' change (Real.sqrt (s i : ℝ)) ^ 2 = (s i : ℝ)\n' + ' exact Real.sq_sqrt (Nat.cast_nonneg _)\n') + + torus = 'FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean' + replace_once(torus, + ' rw [dist_eq_norm, norm_sub_rev] at hdist\n', + ' rw [dist_eq_norm] at hdist\n') + replace_once(torus, + ' | zero => simp [mFourier_zero]\n', + ' | zero => simp [mFourier, fourier_apply]\n') + replace_once(torus, + ' obtain ⟨z, hz⟩ := AddCircle.coe_eq_zero_iff.mp hzero\'\n', + ' obtain ⟨z, hz⟩ := (AddCircle.coe_eq_zero_iff (1 : ℝ)).mp hzero\'\n') + replace_once(torus, + ' rw [volume_eq_fourierVolume (d := d)]\n' + ' have h := (orthonormal_iff_ite.mp (orthonormal_mFourier (d := d))) (0 : d → ℤ) k\n', + ' have h := (orthonormal_iff_ite.mp (orthonormal_mFourier (d := d))) (0 : d → ℤ) k\n') + replace_once(torus, + ' _ = 2 := by simp [norm_pow, hnorm]\n', + ' _ = 2 := by norm_num [norm_pow, hnorm]\n') + replace_once(torus, + ' simp [mFourier, fourier_apply, norm_prod, Circle.norm_coe]\n', + ' simp only [mFourier, fourier_apply, ContinuousMap.coe_mk, norm_prod,\n' + ' Circle.norm_coe, Finset.prod_const_one]\n') + + Path('.github/workflows/a261865-one-shot-repair.yml').unlink() + PY + + - name: Commit repair + shell: bash + run: | + set -euo pipefail + git config user.name 'ProofOrchestrator' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean \ + FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean \ + .github/workflows/a261865-one-shot-repair.yml + git commit -m 'Fix A261865 foundation proofs after AXLE diagnostics' + git push origin HEAD:a261865-research From 024bf36395a5b19464c43c232450b1ae6230700b Mon Sep 17 00:00:00 2001 From: ProofOrchestrator <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 22:32:51 +0000 Subject: [PATCH 077/115] Fix A261865 foundation proofs after AXLE diagnostics --- .github/workflows/a261865-one-shot-repair.yml | 111 ------------------ .../Equidistribution/UnitAddTorus.lean | 12 +- .../NumberTheory/SquarefreeRadical.lean | 26 ++-- 3 files changed, 19 insertions(+), 130 deletions(-) delete mode 100644 .github/workflows/a261865-one-shot-repair.yml diff --git a/.github/workflows/a261865-one-shot-repair.yml b/.github/workflows/a261865-one-shot-repair.yml deleted file mode 100644 index c78db09cff..0000000000 --- a/.github/workflows/a261865-one-shot-repair.yml +++ /dev/null @@ -1,111 +0,0 @@ -name: Apply first A261865 Lean repair batch - -on: - push: - branches: [a261865-research] - paths: - - '.github/workflows/a261865-one-shot-repair.yml' - workflow_dispatch: - -permissions: - contents: write - -jobs: - repair: - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - name: Checkout proof branch - uses: actions/checkout@v4 - with: - ref: a261865-research - fetch-depth: 0 - - - name: Apply exact Lean repairs - shell: bash - run: | - python3 - <<'PY' - from pathlib import Path - - def replace_once(path: str, old: str, new: str) -> None: - p = Path(path) - text = p.read_text() - count = text.count(old) - if count != 1: - raise SystemExit(f'{path}: expected one match, found {count}: {old!r}') - p.write_text(text.replace(old, new, 1)) - - sq = 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean' - replace_once(sq, - ' rw [ha.ext_iff hb]\n intro p hp\n', - ' apply (Squarefree.ext_iff ha hb).2\n intro p hp\n') - replace_once(sq, - ' have heq : minpoly ℚ x = X ^ 2 - C r :=\n' - ' Polynomial.eq_of_monic_of_dvd_of_natDegree_le (minpoly.monic hint) hmonic hdvd\n' - ' (by rw [hdeg2, Polynomial.natDegree_X_pow_sub_C])\n', - ' have heq_rev : X ^ 2 - C r = minpoly ℚ x :=\n' - ' Polynomial.eq_of_monic_of_dvd_of_natDegree_le\n' - ' (p := minpoly ℚ x) (q := X ^ 2 - C r)\n' - ' (minpoly.monic hint) hmonic hdvd\n' - ' (by rw [hdeg2, Polynomial.natDegree_X_pow_sub_C])\n' - ' have heq : minpoly ℚ x = X ^ 2 - C r := heq_rev.symm\n') - replace_once(sq, - ' refine ⟨Polynomial.X ^ 2 - Polynomial.C (s i : ℚ), ?_, ?_⟩\n' - ' · exact Polynomial.monic_X_pow_sub_C _ two_ne_zero\n' - ' · norm_num [← Polynomial.C_pow]\n' - ' norm_cast\n' - ' rw [Real.sq_sqrt (Nat.cast_nonneg _)]\n' - ' ring\n', - ' refine ⟨Polynomial.X ^ 2 - Polynomial.C (s i : ℚ),\n' - ' Polynomial.monic_X_pow_sub_C _ two_ne_zero, ?_⟩\n' - ' norm_num [← Polynomial.C_pow]\n' - ' rw [Real.sq_sqrt (Nat.cast_nonneg _)]\n' - ' norm_num\n') - replace_once(sq, - ' have hroot_sq (i : ι) : (root i) ^ 2 = algebraMap ℚ K (s i : ℚ) := by\n' - ' apply Subtype.ext\n' - ' simp only [root]\n' - ' push_cast\n' - ' rw [Real.sq_sqrt (Nat.cast_nonneg _)]\n' - ' norm_cast\n', - ' have hroot_sq (i : ι) : (root i) ^ 2 = algebraMap ℚ K (s i : ℚ) := by\n' - ' apply Subtype.ext\n' - ' change (Real.sqrt (s i : ℝ)) ^ 2 = (s i : ℝ)\n' - ' exact Real.sq_sqrt (Nat.cast_nonneg _)\n') - - torus = 'FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean' - replace_once(torus, - ' rw [dist_eq_norm, norm_sub_rev] at hdist\n', - ' rw [dist_eq_norm] at hdist\n') - replace_once(torus, - ' | zero => simp [mFourier_zero]\n', - ' | zero => simp [mFourier, fourier_apply]\n') - replace_once(torus, - ' obtain ⟨z, hz⟩ := AddCircle.coe_eq_zero_iff.mp hzero\'\n', - ' obtain ⟨z, hz⟩ := (AddCircle.coe_eq_zero_iff (1 : ℝ)).mp hzero\'\n') - replace_once(torus, - ' rw [volume_eq_fourierVolume (d := d)]\n' - ' have h := (orthonormal_iff_ite.mp (orthonormal_mFourier (d := d))) (0 : d → ℤ) k\n', - ' have h := (orthonormal_iff_ite.mp (orthonormal_mFourier (d := d))) (0 : d → ℤ) k\n') - replace_once(torus, - ' _ = 2 := by simp [norm_pow, hnorm]\n', - ' _ = 2 := by norm_num [norm_pow, hnorm]\n') - replace_once(torus, - ' simp [mFourier, fourier_apply, norm_prod, Circle.norm_coe]\n', - ' simp only [mFourier, fourier_apply, ContinuousMap.coe_mk, norm_prod,\n' - ' Circle.norm_coe, Finset.prod_const_one]\n') - - Path('.github/workflows/a261865-one-shot-repair.yml').unlink() - PY - - - name: Commit repair - shell: bash - run: | - set -euo pipefail - git config user.name 'ProofOrchestrator' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean \ - FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean \ - .github/workflows/a261865-one-shot-repair.yml - git commit -m 'Fix A261865 foundation proofs after AXLE diagnostics' - git push origin HEAD:a261865-research diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean index 7ceca61ee4..6237481d2e 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean @@ -108,7 +108,7 @@ theorem tendsto_average_of_tendsto_mFourier Submodule.top_coe] exact Set.mem_univ F obtain ⟨p, hp, hdist⟩ := Metric.mem_closure_iff.mp hF (ε / 3) (by positivity) - rw [dist_eq_norm, norm_sub_rev] at hdist + rw [dist_eq_norm] at hdist obtain ⟨N₀, hN₀⟩ := (Metric.tendsto_atTop.mp (hspan p hp)) (ε / 3) (by positivity) refine ⟨N₀, fun N hN => ?_⟩ @@ -173,7 +173,7 @@ lemma mFourier_add_point (k : d → ℤ) (x y : UnitAddTorus d) : lemma mFourier_nsmul (k : d → ℤ) (x : UnitAddTorus d) (n : ℕ) : mFourier k (n • x) = (mFourier k x) ^ n := by induction n with - | zero => simp [mFourier_zero] + | zero => simp [mFourier, fourier_apply] | succ n ih => rw [succ_nsmul, mFourier_add_point, ih, pow_succ] @@ -208,7 +208,7 @@ lemma mFourier_coe_ne_one {a : d → ℝ} (ha : NoIntegerRelation a) simpa using hcirc have hzero' : ((∑ i, (k i : ℝ) * a i : ℝ) : UnitAddCircle) = 0 := by simpa [zsmul_eq_mul] using hzero - obtain ⟨z, hz⟩ := AddCircle.coe_eq_zero_iff.mp hzero' + obtain ⟨z, hz⟩ := (AddCircle.coe_eq_zero_iff (1 : ℝ)).mp hzero' apply hk apply ha k exact ⟨z, by simpa [zsmul_eq_mul] using hz.symm⟩ @@ -217,7 +217,6 @@ lemma mFourier_coe_ne_one {a : d → ℝ} (ha : NoIntegerRelation a) otherwise. -/ lemma integral_mFourier (k : d → ℤ) : ∫ x : UnitAddTorus d, mFourier k x = if k = 0 then 1 else 0 := by - rw [volume_eq_fourierVolume (d := d)] have h := (orthonormal_iff_ite.mp (orthonormal_mFourier (d := d))) (0 : d → ℤ) k simpa only [ContinuousMap.inner_toLp, mFourier_zero, ContinuousMap.one_apply, map_one, one_mul, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h @@ -238,7 +237,7 @@ lemma tendsto_geom_average_zero {z : ℂ} (hz : z ≠ 1) (hnorm : ‖z‖ = 1) : apply div_le_div_of_nonneg_right _ hden.le calc ‖z ^ N - 1‖ ≤ ‖z ^ N‖ + ‖(1 : ℂ)‖ := norm_sub_le _ _ - _ = 2 := by simp [norm_pow, hnorm] + _ = 2 := by norm_num [norm_pow, hnorm] refine squeeze_zero_norm hbound ?_ exact tendsto_const_nhds.div_atTop tendsto_natCast_atTop_atTop @@ -268,7 +267,8 @@ theorem tendsto_average_rotation · have hz : mFourier k (fun i => (a i : UnitAddCircle)) ≠ 1 := mFourier_coe_ne_one ha hk have hnorm : ‖mFourier k (fun i => (a i : UnitAddCircle))‖ = 1 := by - simp [mFourier, fourier_apply, norm_prod, Circle.norm_coe] + simp only [mFourier, fourier_apply, ContinuousMap.coe_mk, norm_prod, + Circle.norm_coe, Finset.prod_const_one] have hgeom := tendsto_geom_average_zero hz hnorm rw [integral_mFourier, if_neg hk] simpa only [mFourier_nsmul] using hgeom diff --git a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean index 8eed862234..c35cc3bca4 100644 --- a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean +++ b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean @@ -29,7 +29,7 @@ namespace Nat /-- The product of two squarefree natural numbers is a square only when they are equal. -/ theorem eq_of_squarefree_of_isSquare_mul {a b : ℕ} (ha : Squarefree a) (hb : Squarefree b) (hab : IsSquare (a * b)) : a = b := by - rw [ha.ext_iff hb] + apply (Squarefree.ext_iff ha hb).2 intro p hp obtain ⟨c, hc⟩ := hab have hfac : a.factorization p + b.factorization p = 2 * c.factorization p := by @@ -76,9 +76,12 @@ theorem trace_eq_zero_of_sq_ratCast {K : Type*} [Field K] [NumberField K] {x : K · exact (minpoly.natDegree_pos hint).ne' hh · exact hx (minpoly.natDegree_eq_one_iff.mp hh) omega - have heq : minpoly ℚ x = X ^ 2 - C r := - Polynomial.eq_of_monic_of_dvd_of_natDegree_le (minpoly.monic hint) hmonic hdvd + have heq_rev : X ^ 2 - C r = minpoly ℚ x := + Polynomial.eq_of_monic_of_dvd_of_natDegree_le + (p := minpoly ℚ x) (q := X ^ 2 - C r) + (minpoly.monic hint) hmonic hdvd (by rw [hdeg2, Polynomial.natDegree_X_pow_sub_C]) + have heq : minpoly ℚ x = X ^ 2 - C r := heq_rev.symm rw [trace_eq_finrank_mul_minpoly_nextCoeff, heq] have hnc : (X ^ 2 - C r : ℚ[X]).nextCoeff = 0 := by rw [Polynomial.nextCoeff_of_natDegree_pos @@ -97,12 +100,11 @@ theorem linearIndependent_sqrt_squarefree {ι : Type*} [Fintype ι] have hfd : FiniteDimensional ℚ K := by refine IntermediateField.finiteDimensional_adjoin ?_ rintro x ⟨i, rfl⟩ - refine ⟨Polynomial.X ^ 2 - Polynomial.C (s i : ℚ), ?_, ?_⟩ - · exact Polynomial.monic_X_pow_sub_C _ two_ne_zero - · norm_num [← Polynomial.C_pow] - norm_cast - rw [Real.sq_sqrt (Nat.cast_nonneg _)] - ring + refine ⟨Polynomial.X ^ 2 - Polynomial.C (s i : ℚ), + Polynomial.monic_X_pow_sub_C _ two_ne_zero, ?_⟩ + norm_num [← Polynomial.C_pow] + rw [Real.sq_sqrt (Nat.cast_nonneg _)] + norm_num letI : NumberField K := { to_charZero := inferInstance to_finiteDimensional := hfd } @@ -110,10 +112,8 @@ theorem linearIndependent_sqrt_squarefree {ι : Type*} [Fintype ι] ⟨Real.sqrt (s i), IntermediateField.subset_adjoin ℚ _ ⟨i, rfl⟩⟩ have hroot_sq (i : ι) : (root i) ^ 2 = algebraMap ℚ K (s i : ℚ) := by apply Subtype.ext - simp only [root] - push_cast - rw [Real.sq_sqrt (Nat.cast_nonneg _)] - norm_cast + change (Real.sqrt (s i : ℝ)) ^ 2 = (s i : ℝ) + exact Real.sq_sqrt (Nat.cast_nonneg _) have hmul_sq (i j : ι) : (root i * root j) ^ 2 = algebraMap ℚ K ((s i * s j : ℕ) : ℚ) := by rw [mul_pow, hroot_sq, hroot_sq, ← map_mul] norm_cast From 343bcaf9f52e7a8eb13c9f2eba0011d2e4177f94 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 15:35:37 -0700 Subject: [PATCH 078/115] ci: apply second A261865 Lean repair batch --- .../workflows/a261865-one-shot-repair-2.yml | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 .github/workflows/a261865-one-shot-repair-2.yml diff --git a/.github/workflows/a261865-one-shot-repair-2.yml b/.github/workflows/a261865-one-shot-repair-2.yml new file mode 100644 index 0000000000..2c2ad8369d --- /dev/null +++ b/.github/workflows/a261865-one-shot-repair-2.yml @@ -0,0 +1,85 @@ +name: Apply second A261865 Lean repair batch + +on: + push: + branches: [a261865-research] + paths: + - '.github/workflows/a261865-one-shot-repair-2.yml' + workflow_dispatch: + +permissions: + contents: write + +jobs: + repair: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout proof branch + uses: actions/checkout@v4 + with: + ref: a261865-research + fetch-depth: 0 + + - name: Apply exact Lean repairs + shell: bash + run: | + python3 - <<'PY' + from pathlib import Path + + def replace_once(path: str, old: str, new: str) -> None: + p = Path(path) + text = p.read_text() + count = text.count(old) + if count != 1: + raise SystemExit(f'{path}: expected one match, found {count}: {old!r}') + p.write_text(text.replace(old, new, 1)) + + sq = 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean' + replace_once(sq, + ' a.factorization p + b.factorization p = (a * b).factorization p := by\n' + ' rw [factorization_mul ha.ne_zero hb.ne_zero]\n' + ' _ = (c ^ 2).factorization p := by\n' + ' congr 1\n' + ' simpa [pow_two] using hc\n', + ' a.factorization p + b.factorization p = (a * b).factorization p := by\n' + ' simpa only [Pi.add_apply] using\n' + ' congrFun (factorization_mul ha.ne_zero hb.ne_zero).symm p\n' + ' _ = (c ^ 2).factorization p := by\n' + ' simpa [pow_two, hc]\n') + replace_once(sq, + ' norm_num [← Polynomial.C_pow]\n' + ' rw [Real.sq_sqrt (Nat.cast_nonneg _)]\n' + ' norm_num\n', + ' norm_num [← Polynomial.C_pow]\n') + + torus = 'FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean' + replace_once(torus, + 'lemma integral_mFourier (k : d → ℤ) :\n' + ' ∫ x : UnitAddTorus d, mFourier k x = if k = 0 then 1 else 0 := by\n' + ' have h := (orthonormal_iff_ite.mp (orthonormal_mFourier (d := d))) (0 : d → ℤ) k\n' + ' simpa only [ContinuousMap.inner_toLp, mFourier_zero, ContinuousMap.one_apply,\n' + ' map_one, one_mul, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h\n', + 'lemma integral_mFourier (k : d → ℤ) :\n' + ' ∫ x : UnitAddTorus d, mFourier k x = if k = 0 then 1 else 0 := by\n' + ' rw [volume_eq_fourierVolume (d := d)]\n' + ' letI : MeasureSpace UnitAddCircle := ⟨AddCircle.haarAddCircle⟩\n' + ' change (∫ x : UnitAddTorus d, mFourier k x) = if k = 0 then 1 else 0\n' + ' have h := (orthonormal_iff_ite.mp (orthonormal_mFourier (d := d))) (0 : d → ℤ) k\n' + ' simpa only [ContinuousMap.inner_toLp, mFourier_zero, ContinuousMap.one_apply,\n' + ' map_one, one_mul, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h\n') + + Path('.github/workflows/a261865-one-shot-repair-2.yml').unlink() + PY + + - name: Commit repair + shell: bash + run: | + set -euo pipefail + git config user.name 'ProofOrchestrator' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean \ + FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean \ + .github/workflows/a261865-one-shot-repair-2.yml + git commit -m 'Finish A261865 foundation fixes from AXLE diagnostics' + git push origin HEAD:a261865-research From 7a073b94596edcdf6a3c4c56079e0a75ae404474 Mon Sep 17 00:00:00 2001 From: ProofOrchestrator <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 22:35:46 +0000 Subject: [PATCH 079/115] Finish A261865 foundation fixes from AXLE diagnostics --- .../workflows/a261865-one-shot-repair-2.yml | 85 ------------------- .../Equidistribution/UnitAddTorus.lean | 3 + .../NumberTheory/SquarefreeRadical.lean | 8 +- 3 files changed, 6 insertions(+), 90 deletions(-) delete mode 100644 .github/workflows/a261865-one-shot-repair-2.yml diff --git a/.github/workflows/a261865-one-shot-repair-2.yml b/.github/workflows/a261865-one-shot-repair-2.yml deleted file mode 100644 index 2c2ad8369d..0000000000 --- a/.github/workflows/a261865-one-shot-repair-2.yml +++ /dev/null @@ -1,85 +0,0 @@ -name: Apply second A261865 Lean repair batch - -on: - push: - branches: [a261865-research] - paths: - - '.github/workflows/a261865-one-shot-repair-2.yml' - workflow_dispatch: - -permissions: - contents: write - -jobs: - repair: - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - name: Checkout proof branch - uses: actions/checkout@v4 - with: - ref: a261865-research - fetch-depth: 0 - - - name: Apply exact Lean repairs - shell: bash - run: | - python3 - <<'PY' - from pathlib import Path - - def replace_once(path: str, old: str, new: str) -> None: - p = Path(path) - text = p.read_text() - count = text.count(old) - if count != 1: - raise SystemExit(f'{path}: expected one match, found {count}: {old!r}') - p.write_text(text.replace(old, new, 1)) - - sq = 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean' - replace_once(sq, - ' a.factorization p + b.factorization p = (a * b).factorization p := by\n' - ' rw [factorization_mul ha.ne_zero hb.ne_zero]\n' - ' _ = (c ^ 2).factorization p := by\n' - ' congr 1\n' - ' simpa [pow_two] using hc\n', - ' a.factorization p + b.factorization p = (a * b).factorization p := by\n' - ' simpa only [Pi.add_apply] using\n' - ' congrFun (factorization_mul ha.ne_zero hb.ne_zero).symm p\n' - ' _ = (c ^ 2).factorization p := by\n' - ' simpa [pow_two, hc]\n') - replace_once(sq, - ' norm_num [← Polynomial.C_pow]\n' - ' rw [Real.sq_sqrt (Nat.cast_nonneg _)]\n' - ' norm_num\n', - ' norm_num [← Polynomial.C_pow]\n') - - torus = 'FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean' - replace_once(torus, - 'lemma integral_mFourier (k : d → ℤ) :\n' - ' ∫ x : UnitAddTorus d, mFourier k x = if k = 0 then 1 else 0 := by\n' - ' have h := (orthonormal_iff_ite.mp (orthonormal_mFourier (d := d))) (0 : d → ℤ) k\n' - ' simpa only [ContinuousMap.inner_toLp, mFourier_zero, ContinuousMap.one_apply,\n' - ' map_one, one_mul, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h\n', - 'lemma integral_mFourier (k : d → ℤ) :\n' - ' ∫ x : UnitAddTorus d, mFourier k x = if k = 0 then 1 else 0 := by\n' - ' rw [volume_eq_fourierVolume (d := d)]\n' - ' letI : MeasureSpace UnitAddCircle := ⟨AddCircle.haarAddCircle⟩\n' - ' change (∫ x : UnitAddTorus d, mFourier k x) = if k = 0 then 1 else 0\n' - ' have h := (orthonormal_iff_ite.mp (orthonormal_mFourier (d := d))) (0 : d → ℤ) k\n' - ' simpa only [ContinuousMap.inner_toLp, mFourier_zero, ContinuousMap.one_apply,\n' - ' map_one, one_mul, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h\n') - - Path('.github/workflows/a261865-one-shot-repair-2.yml').unlink() - PY - - - name: Commit repair - shell: bash - run: | - set -euo pipefail - git config user.name 'ProofOrchestrator' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean \ - FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean \ - .github/workflows/a261865-one-shot-repair-2.yml - git commit -m 'Finish A261865 foundation fixes from AXLE diagnostics' - git push origin HEAD:a261865-research diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean index 6237481d2e..ce2716609f 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean @@ -217,6 +217,9 @@ lemma mFourier_coe_ne_one {a : d → ℝ} (ha : NoIntegerRelation a) otherwise. -/ lemma integral_mFourier (k : d → ℤ) : ∫ x : UnitAddTorus d, mFourier k x = if k = 0 then 1 else 0 := by + rw [volume_eq_fourierVolume (d := d)] + letI : MeasureSpace UnitAddCircle := ⟨AddCircle.haarAddCircle⟩ + change (∫ x : UnitAddTorus d, mFourier k x) = if k = 0 then 1 else 0 have h := (orthonormal_iff_ite.mp (orthonormal_mFourier (d := d))) (0 : d → ℤ) k simpa only [ContinuousMap.inner_toLp, mFourier_zero, ContinuousMap.one_apply, map_one, one_mul, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h diff --git a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean index c35cc3bca4..887a82f899 100644 --- a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean +++ b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean @@ -35,10 +35,10 @@ theorem eq_of_squarefree_of_isSquare_mul {a b : ℕ} (ha : Squarefree a) (hb : S have hfac : a.factorization p + b.factorization p = 2 * c.factorization p := by calc a.factorization p + b.factorization p = (a * b).factorization p := by - rw [factorization_mul ha.ne_zero hb.ne_zero] + simpa only [Pi.add_apply] using + congrFun (factorization_mul ha.ne_zero hb.ne_zero).symm p _ = (c ^ 2).factorization p := by - congr 1 - simpa [pow_two] using hc + simpa [pow_two, hc] _ = 2 * c.factorization p := by simp [factorization_pow] constructor · intro hpa @@ -103,8 +103,6 @@ theorem linearIndependent_sqrt_squarefree {ι : Type*} [Fintype ι] refine ⟨Polynomial.X ^ 2 - Polynomial.C (s i : ℚ), Polynomial.monic_X_pow_sub_C _ two_ne_zero, ?_⟩ norm_num [← Polynomial.C_pow] - rw [Real.sq_sqrt (Nat.cast_nonneg _)] - norm_num letI : NumberField K := { to_charZero := inferInstance to_finiteDimensional := hfd } From 8f77b5edb4eea6c0be37de98d1ff9533018d8834 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 15:37:19 -0700 Subject: [PATCH 080/115] ci: apply final A261865 foundation repairs --- .../workflows/a261865-one-shot-repair-3.yml | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/workflows/a261865-one-shot-repair-3.yml diff --git a/.github/workflows/a261865-one-shot-repair-3.yml b/.github/workflows/a261865-one-shot-repair-3.yml new file mode 100644 index 0000000000..e11d3e266f --- /dev/null +++ b/.github/workflows/a261865-one-shot-repair-3.yml @@ -0,0 +1,66 @@ +name: Apply final A261865 foundation repairs + +on: + push: + branches: [a261865-research] + paths: + - '.github/workflows/a261865-one-shot-repair-3.yml' + workflow_dispatch: + +permissions: + contents: write + +jobs: + repair: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout proof branch + uses: actions/checkout@v4 + with: + ref: a261865-research + fetch-depth: 0 + + - name: Apply exact Lean repairs + shell: bash + run: | + python3 - <<'PY' + from pathlib import Path + + def replace_once(path: str, old: str, new: str) -> None: + p = Path(path) + text = p.read_text() + count = text.count(old) + if count != 1: + raise SystemExit(f'{path}: expected one match, found {count}: {old!r}') + p.write_text(text.replace(old, new, 1)) + + sq = 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean' + replace_once(sq, + ' a.factorization p + b.factorization p = (a * b).factorization p := by\n' + ' simpa only [Pi.add_apply] using\n' + ' congrFun (factorization_mul ha.ne_zero hb.ne_zero).symm p\n', + ' a.factorization p + b.factorization p = (a * b).factorization p := by\n' + ' have h := congrArg (fun f : ℕ →₀ ℕ => f p)\n' + ' (factorization_mul ha.ne_zero hb.ne_zero).symm\n' + ' simpa using h\n') + + torus = 'FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean' + replace_once(torus, + ' map_one, one_mul, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h\n', + ' map_one, one_mul, mul_one, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h\n') + + Path('.github/workflows/a261865-one-shot-repair-3.yml').unlink() + PY + + - name: Commit repair + shell: bash + run: | + set -euo pipefail + git config user.name 'ProofOrchestrator' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean \ + FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean \ + .github/workflows/a261865-one-shot-repair-3.yml + git commit -m 'Close remaining A261865 foundation errors' + git push origin HEAD:a261865-research From 46ea24719cc7b65389fe432a7af484d63cfa541f Mon Sep 17 00:00:00 2001 From: ProofOrchestrator <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 22:37:28 +0000 Subject: [PATCH 081/115] Close remaining A261865 foundation errors --- .../workflows/a261865-one-shot-repair-3.yml | 66 ------------------- .../Equidistribution/UnitAddTorus.lean | 2 +- .../NumberTheory/SquarefreeRadical.lean | 5 +- 3 files changed, 4 insertions(+), 69 deletions(-) delete mode 100644 .github/workflows/a261865-one-shot-repair-3.yml diff --git a/.github/workflows/a261865-one-shot-repair-3.yml b/.github/workflows/a261865-one-shot-repair-3.yml deleted file mode 100644 index e11d3e266f..0000000000 --- a/.github/workflows/a261865-one-shot-repair-3.yml +++ /dev/null @@ -1,66 +0,0 @@ -name: Apply final A261865 foundation repairs - -on: - push: - branches: [a261865-research] - paths: - - '.github/workflows/a261865-one-shot-repair-3.yml' - workflow_dispatch: - -permissions: - contents: write - -jobs: - repair: - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - name: Checkout proof branch - uses: actions/checkout@v4 - with: - ref: a261865-research - fetch-depth: 0 - - - name: Apply exact Lean repairs - shell: bash - run: | - python3 - <<'PY' - from pathlib import Path - - def replace_once(path: str, old: str, new: str) -> None: - p = Path(path) - text = p.read_text() - count = text.count(old) - if count != 1: - raise SystemExit(f'{path}: expected one match, found {count}: {old!r}') - p.write_text(text.replace(old, new, 1)) - - sq = 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean' - replace_once(sq, - ' a.factorization p + b.factorization p = (a * b).factorization p := by\n' - ' simpa only [Pi.add_apply] using\n' - ' congrFun (factorization_mul ha.ne_zero hb.ne_zero).symm p\n', - ' a.factorization p + b.factorization p = (a * b).factorization p := by\n' - ' have h := congrArg (fun f : ℕ →₀ ℕ => f p)\n' - ' (factorization_mul ha.ne_zero hb.ne_zero).symm\n' - ' simpa using h\n') - - torus = 'FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean' - replace_once(torus, - ' map_one, one_mul, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h\n', - ' map_one, one_mul, mul_one, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h\n') - - Path('.github/workflows/a261865-one-shot-repair-3.yml').unlink() - PY - - - name: Commit repair - shell: bash - run: | - set -euo pipefail - git config user.name 'ProofOrchestrator' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean \ - FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean \ - .github/workflows/a261865-one-shot-repair-3.yml - git commit -m 'Close remaining A261865 foundation errors' - git push origin HEAD:a261865-research diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean index ce2716609f..a357e268a7 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean @@ -222,7 +222,7 @@ lemma integral_mFourier (k : d → ℤ) : change (∫ x : UnitAddTorus d, mFourier k x) = if k = 0 then 1 else 0 have h := (orthonormal_iff_ite.mp (orthonormal_mFourier (d := d))) (0 : d → ℤ) k simpa only [ContinuousMap.inner_toLp, mFourier_zero, ContinuousMap.one_apply, - map_one, one_mul, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h + map_one, one_mul, mul_one, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h /-- The Cesàro averages of a nontrivial unit-modulus geometric progression tend to zero. -/ lemma tendsto_geom_average_zero {z : ℂ} (hz : z ≠ 1) (hnorm : ‖z‖ = 1) : diff --git a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean index 887a82f899..1fda3cedb2 100644 --- a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean +++ b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean @@ -35,8 +35,9 @@ theorem eq_of_squarefree_of_isSquare_mul {a b : ℕ} (ha : Squarefree a) (hb : S have hfac : a.factorization p + b.factorization p = 2 * c.factorization p := by calc a.factorization p + b.factorization p = (a * b).factorization p := by - simpa only [Pi.add_apply] using - congrFun (factorization_mul ha.ne_zero hb.ne_zero).symm p + have h := congrArg (fun f : ℕ →₀ ℕ => f p) + (factorization_mul ha.ne_zero hb.ne_zero).symm + simpa using h _ = (c ^ 2).factorization p := by simpa [pow_two, hc] _ = 2 * c.factorization p := by simp [factorization_pow] From 91bb24fc4312cc7a9c0e311b0d469b6cc79b3f24 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 15:51:25 -0700 Subject: [PATCH 082/115] ci: repair A261865 circle and reciprocal radical modules --- .../workflows/a261865-one-shot-repair-4.yml | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 .github/workflows/a261865-one-shot-repair-4.yml diff --git a/.github/workflows/a261865-one-shot-repair-4.yml b/.github/workflows/a261865-one-shot-repair-4.yml new file mode 100644 index 0000000000..66f1953574 --- /dev/null +++ b/.github/workflows/a261865-one-shot-repair-4.yml @@ -0,0 +1,90 @@ +name: Repair A261865 circle and reciprocal radical modules + +on: + push: + branches: [a261865-research] + paths: + - '.github/workflows/a261865-one-shot-repair-4.yml' + +permissions: + contents: write + +jobs: + repair: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + with: + ref: a261865-research + fetch-depth: 0 + + - name: Apply exact compatibility repairs + shell: bash + run: | + python3 - <<'PY' + from pathlib import Path + + def replace_once(path, old, new): + p = Path(path) + text = p.read_text() + n = text.count(old) + if n != 1: + raise SystemExit(f'{path}: expected one match, found {n}: {old!r}') + p.write_text(text.replace(old, new, 1)) + + arc = 'FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean' + replace_once(arc, 'Int.round (y - x)', 'round (y - x)') + replace_once(arc, 'Int.round_le (y - x) z', 'round_le (y - x) z') + replace_once(arc, + ' have hfract := Int.fract_mem ((n : ℝ) * a)\n', + ' have hfract : Int.fract ((n : ℝ) * a) ∈ Set.Ico (0 : ℝ) 1 :=\n' + ' ⟨Int.fract_nonneg _, Int.fract_lt_one _⟩\n') + replace_once(arc, + ' rw [← ae_eq_empty]\n' + ' filter_upwards [AddCircle.closedBall_ae_eq_ball\n' + ' (x := (c : UnitAddCircle)) (ε := r)] with y hy\n' + ' simp only [Set.mem_empty_iff_false, iff_false]\n' + ' intro hysphere\n' + ' have hclosed : y ∈ Metric.closedBall (c : UnitAddCircle) r :=\n' + ' Metric.mem_closedBall.mpr (Metric.mem_sphere.mp hysphere).le\n' + ' have hball : y ∈ Metric.ball (c : UnitAddCircle) r := by\n' + ' rw [← hy]\n' + ' exact hclosed\n' + ' exact (Metric.mem_ball.mp hball).ne (Metric.mem_sphere.mp hysphere)\n', + ' rw [← ae_eq_empty]\n' + ' filter_upwards [AddCircle.closedBall_ae_eq_ball\n' + ' (x := (c : UnitAddCircle)) (ε := r)] with y hy\n' + ' constructor\n' + ' · intro hysphere\n' + ' have hclosed : y ∈ Metric.closedBall (c : UnitAddCircle) r :=\n' + ' Metric.mem_closedBall.mpr (Metric.mem_sphere.mp hysphere).le\n' + ' have hball : y ∈ Metric.ball (c : UnitAddCircle) r := hy.mp hclosed\n' + ' exact (Metric.mem_ball.mp hball).ne (Metric.mem_sphere.mp hysphere)\n' + ' · intro hyempty\n' + ' exact hyempty.elim\n') + + radicals = 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean' + replace_once(radicals, + ' simp only [Pi.smul_apply\', Units.smul_def, u, Rat.smul_def]\n' + ' rw [Rat.cast_inv, Rat.cast_natCast]\n' + ' field_simp [hsqrt, Real.sq_sqrt hpos.le]\n', + ' change 1 / Real.sqrt (s i) =\n' + ' (((((s i : ℚ)⁻¹ : ℚ) : ℝ)) * Real.sqrt (s i))\n' + ' rw [Rat.cast_inv, Rat.cast_natCast]\n' + ' field_simp [hsqrt, Real.sq_sqrt hpos.le]\n') + + Path('.github/workflows/a261865-one-shot-repair-4.yml').unlink() + PY + + - name: Commit repairs + shell: bash + run: | + set -euo pipefail + git config user.name 'ProofOrchestrator' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean \ + FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean \ + .github/workflows/a261865-one-shot-repair-4.yml + git commit -m 'Fix A261865 circle and reciprocal radical compatibility' + git push origin HEAD:a261865-research From 705c9126bb833b8df82d54d2d6b91bed72aadf05 Mon Sep 17 00:00:00 2001 From: ProofOrchestrator <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 22:51:33 +0000 Subject: [PATCH 083/115] Fix A261865 circle and reciprocal radical compatibility --- .../workflows/a261865-one-shot-repair-4.yml | 90 ------------------- .../MeasureTheory/Group/UnitAddCircleArc.lean | 23 ++--- .../NumberTheory/SquarefreeRadicals.lean | 3 +- 3 files changed, 14 insertions(+), 102 deletions(-) delete mode 100644 .github/workflows/a261865-one-shot-repair-4.yml diff --git a/.github/workflows/a261865-one-shot-repair-4.yml b/.github/workflows/a261865-one-shot-repair-4.yml deleted file mode 100644 index 66f1953574..0000000000 --- a/.github/workflows/a261865-one-shot-repair-4.yml +++ /dev/null @@ -1,90 +0,0 @@ -name: Repair A261865 circle and reciprocal radical modules - -on: - push: - branches: [a261865-research] - paths: - - '.github/workflows/a261865-one-shot-repair-4.yml' - -permissions: - contents: write - -jobs: - repair: - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: actions/checkout@v4 - with: - ref: a261865-research - fetch-depth: 0 - - - name: Apply exact compatibility repairs - shell: bash - run: | - python3 - <<'PY' - from pathlib import Path - - def replace_once(path, old, new): - p = Path(path) - text = p.read_text() - n = text.count(old) - if n != 1: - raise SystemExit(f'{path}: expected one match, found {n}: {old!r}') - p.write_text(text.replace(old, new, 1)) - - arc = 'FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean' - replace_once(arc, 'Int.round (y - x)', 'round (y - x)') - replace_once(arc, 'Int.round_le (y - x) z', 'round_le (y - x) z') - replace_once(arc, - ' have hfract := Int.fract_mem ((n : ℝ) * a)\n', - ' have hfract : Int.fract ((n : ℝ) * a) ∈ Set.Ico (0 : ℝ) 1 :=\n' - ' ⟨Int.fract_nonneg _, Int.fract_lt_one _⟩\n') - replace_once(arc, - ' rw [← ae_eq_empty]\n' - ' filter_upwards [AddCircle.closedBall_ae_eq_ball\n' - ' (x := (c : UnitAddCircle)) (ε := r)] with y hy\n' - ' simp only [Set.mem_empty_iff_false, iff_false]\n' - ' intro hysphere\n' - ' have hclosed : y ∈ Metric.closedBall (c : UnitAddCircle) r :=\n' - ' Metric.mem_closedBall.mpr (Metric.mem_sphere.mp hysphere).le\n' - ' have hball : y ∈ Metric.ball (c : UnitAddCircle) r := by\n' - ' rw [← hy]\n' - ' exact hclosed\n' - ' exact (Metric.mem_ball.mp hball).ne (Metric.mem_sphere.mp hysphere)\n', - ' rw [← ae_eq_empty]\n' - ' filter_upwards [AddCircle.closedBall_ae_eq_ball\n' - ' (x := (c : UnitAddCircle)) (ε := r)] with y hy\n' - ' constructor\n' - ' · intro hysphere\n' - ' have hclosed : y ∈ Metric.closedBall (c : UnitAddCircle) r :=\n' - ' Metric.mem_closedBall.mpr (Metric.mem_sphere.mp hysphere).le\n' - ' have hball : y ∈ Metric.ball (c : UnitAddCircle) r := hy.mp hclosed\n' - ' exact (Metric.mem_ball.mp hball).ne (Metric.mem_sphere.mp hysphere)\n' - ' · intro hyempty\n' - ' exact hyempty.elim\n') - - radicals = 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean' - replace_once(radicals, - ' simp only [Pi.smul_apply\', Units.smul_def, u, Rat.smul_def]\n' - ' rw [Rat.cast_inv, Rat.cast_natCast]\n' - ' field_simp [hsqrt, Real.sq_sqrt hpos.le]\n', - ' change 1 / Real.sqrt (s i) =\n' - ' (((((s i : ℚ)⁻¹ : ℚ) : ℝ)) * Real.sqrt (s i))\n' - ' rw [Rat.cast_inv, Rat.cast_natCast]\n' - ' field_simp [hsqrt, Real.sq_sqrt hpos.le]\n') - - Path('.github/workflows/a261865-one-shot-repair-4.yml').unlink() - PY - - - name: Commit repairs - shell: bash - run: | - set -euo pipefail - git config user.name 'ProofOrchestrator' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean \ - FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean \ - .github/workflows/a261865-one-shot-repair-4.yml - git commit -m 'Fix A261865 circle and reciprocal radical compatibility' - git push origin HEAD:a261865-research diff --git a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean index 4f0975c661..2de2cb400b 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean @@ -40,10 +40,10 @@ theorem coe_preimage_ball_eq_iUnion (x ε : ℝ) : dist_eq_norm, ← QuotientAddGroup.mk_sub, UnitAddCircle.norm_eq] constructor · intro h - refine ⟨Int.round (y - x), ?_⟩ + refine ⟨round (y - x), ?_⟩ simpa [sub_sub, add_comm, add_left_comm, add_assoc] using h · rintro ⟨z, hz⟩ - have hmin := Int.round_le (y - x) z + have hmin := round_le (y - x) z exact hmin.trans_lt (by simpa [sub_sub, add_comm, add_left_comm, add_assoc] using hz) /-- Membership in the terminal metric arc is exactly a strict fractional-coordinate inequality. -/ @@ -82,7 +82,8 @@ corresponding terminal interval. -/ theorem nsmul_mem_terminalArc_iff {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) (n : ℕ) : n • (a : UnitAddCircle) ∈ terminalArc a ↔ 1 - a < Int.fract ((n : ℝ) * a) := by - have hfract := Int.fract_mem ((n : ℝ) * a) + have hfract : Int.fract ((n : ℝ) * a) ∈ Set.Ico (0 : ℝ) 1 := + ⟨Int.fract_nonneg _, Int.fract_lt_one _⟩ rw [show n • (a : UnitAddCircle) = (((n : ℝ) * a : ℝ) : UnitAddCircle) by simp [nsmul_eq_mul]] rw [coe_fract_eq] @@ -94,14 +95,14 @@ theorem volume_sphere_eq_zero {c r : ℝ} (_hr0 : 0 ≤ r) (_hr : r < 1 / 2) : rw [← ae_eq_empty] filter_upwards [AddCircle.closedBall_ae_eq_ball (x := (c : UnitAddCircle)) (ε := r)] with y hy - simp only [Set.mem_empty_iff_false, iff_false] - intro hysphere - have hclosed : y ∈ Metric.closedBall (c : UnitAddCircle) r := - Metric.mem_closedBall.mpr (Metric.mem_sphere.mp hysphere).le - have hball : y ∈ Metric.ball (c : UnitAddCircle) r := by - rw [← hy] - exact hclosed - exact (Metric.mem_ball.mp hball).ne (Metric.mem_sphere.mp hysphere) + constructor + · intro hysphere + have hclosed : y ∈ Metric.closedBall (c : UnitAddCircle) r := + Metric.mem_closedBall.mpr (Metric.mem_sphere.mp hysphere).le + have hball : y ∈ Metric.ball (c : UnitAddCircle) r := hy.mp hclosed + exact (Metric.mem_ball.mp hball).ne (Metric.mem_sphere.mp hysphere) + · intro hyempty + exact hyempty.elim /-- The terminal arc has length `a`. -/ theorem volume_terminalArc {a : ℝ} (ha0 : 0 < a) (ha1 : a < 1) : diff --git a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean index ac75af288e..a071fa9ff5 100644 --- a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean +++ b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean @@ -36,7 +36,8 @@ theorem linearIndependent_inv_sqrt_squarefree {ι : Type*} [Fintype ι] funext i have hpos : (0 : ℝ) < s i := by exact_mod_cast (Nat.pos_of_ne_zero (hs i).ne_zero) have hsqrt : Real.sqrt (s i) ≠ 0 := (Real.sqrt_pos.2 hpos).ne' - simp only [Pi.smul_apply', Units.smul_def, u, Rat.smul_def] + change 1 / Real.sqrt (s i) = + (((((s i : ℚ)⁻¹ : ℚ) : ℝ)) * Real.sqrt (s i)) rw [Rat.cast_inv, Rat.cast_natCast] field_simp [hsqrt, Real.sq_sqrt hpos.le] From 66c65be9bad04f6eed5f61fe11425e3304d3b534 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 15:52:11 -0700 Subject: [PATCH 084/115] Fix finite product continuity-set compatibility --- .../Probability/PiContinuitySet.lean | 48 +++++++++++-------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean b/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean index 26b5d9bfd0..a7aff9a2b1 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean @@ -27,13 +27,20 @@ noncomputable section namespace Set variable {ι : Type*} [Fintype ι] -variable {α : ι → Type*} [∀ i, TopologicalSpace (α i)] +variable {α : Type*} [TopologicalSpace α] + +private theorem mem_interior_of_mem_notMem_frontier {A : Set α} {x : α} + (hx : x ∈ A) (hfront : x ∉ frontier A) : x ∈ interior A := by + by_contra hxint + apply hfront + rw [frontier] + exact ⟨subset_closure hx, hxint⟩ /-- The frontier of a finite product rectangle is contained in the union of the coordinate frontiers. -/ -theorem frontier_pi_subset_iUnion (A : ∀ i, Set (α i)) : +theorem frontier_pi_subset_iUnion (A : ι → Set α) : frontier (Set.pi univ A) ⊆ - ⋃ i, (fun x : ∀ i, α i => x i) ⁻¹' frontier (A i) := by + ⋃ i, (fun x : ι → α => x i) ⁻¹' frontier (A i) := by classical intro x hx by_contra hnot @@ -41,55 +48,58 @@ theorem frontier_pi_subset_iUnion (A : ∀ i, Set (α i)) : simpa only [Set.mem_iUnion, Set.mem_preimage, not_exists] using hnot by_cases hxA : x ∈ Set.pi univ A · have hxint : x ∈ interior (Set.pi univ A) := by - let U : Set (∀ i, α i) := Set.pi univ (fun i => interior (A i)) + let U : Set (ι → α) := Set.pi univ (fun i => interior (A i)) have hUopen : IsOpen U := isOpen_set_pi finite_univ (fun i _ => isOpen_interior) have hxU : x ∈ U := by intro i _ - exact (mem_interior_iff_notMem_frontier (hxA i trivial)).2 (hcoord i) + exact mem_interior_of_mem_notMem_frontier (hxA i trivial) (hcoord i) have hUsub : U ⊆ Set.pi univ A := by intro y hy i _ exact interior_subset (hy i trivial) exact interior_maximal hUsub hUopen hxU - exact (mem_frontier_iff_notMem_interior hxA).1 hx hxint + rw [frontier] at hx + exact hx.2 hxint · have hex : ∃ i, x i ∉ A i := by simpa only [Set.mem_pi, Set.mem_univ, forall_true_left, not_forall] using hxA obtain ⟨i, hi⟩ := hex - let V : Set (∀ i, α i) := (fun y => y i) ⁻¹' interior (A i)ᶜ + let V : Set (ι → α) := (fun y => y i) ⁻¹' interior (A i)ᶜ have hVopen : IsOpen V := isOpen_interior.preimage (continuous_apply i) have hxV : x ∈ V := by - exact (mem_interior_iff_notMem_frontier (show x i ∈ (A i)ᶜ by simpa)).2 (by simpa using hcoord i) + exact mem_interior_of_mem_notMem_frontier + (show x i ∈ (A i)ᶜ by simpa) (by simpa using hcoord i) have hVsub : V ⊆ (Set.pi univ A)ᶜ := by intro y hy hyA exact (interior_subset hy) (hyA i trivial) have hxcompint : x ∈ interior (Set.pi univ A)ᶜ := interior_maximal hVsub hVopen hxV - have hxcomp : x ∈ (Set.pi univ A)ᶜ := interior_subset hxcompint - have : x ∉ frontier (Set.pi univ A)ᶜ := - (mem_interior_iff_notMem_frontier hxcomp).1 hxcompint - exact this (by simpa using hx) + have hnotfront : x ∉ frontier (Set.pi univ A)ᶜ := by + intro hfront + rw [frontier] at hfront + exact hfront.2 hxcompint + exact hnotfront (by simpa using hx) end Set namespace MeasureTheory variable {ι : Type*} [Fintype ι] -variable {α : ι → Type*} [∀ i, MeasurableSpace (α i)] [∀ i, TopologicalSpace (α i)] +variable {α : Type*} [MeasurableSpace α] [TopologicalSpace α] /-- A finite product of coordinate continuity sets is a continuity set for the product measure. -/ theorem measure_frontier_pi_eq_zero - (μ : ∀ i, Measure (α i)) [∀ i, IsProbabilityMeasure (μ i)] - (A : ∀ i, Set (α i)) (hnull : ∀ i, μ i (frontier (A i)) = 0) : + (μ : ι → Measure α) [∀ i, IsProbabilityMeasure (μ i)] + (A : ι → Set α) (hnull : ∀ i, μ i (frontier (A i)) = 0) : Measure.pi μ (frontier (Set.pi univ A)) = 0 := by classical apply measure_mono_null (Set.frontier_pi_subset_iUnion A) apply measure_iUnion_null intro i have heq : - (fun x : ∀ i, α i => x i) ⁻¹' frontier (A i) = - Set.pi univ (fun j => if j = i then frontier (A i) else univ) := by + (fun x : ι → α => x i) ⁻¹' frontier (A i) = + Set.pi univ (fun j => if j = i then frontier (A j) else univ) := by ext x simp [Set.mem_pi] rw [heq, Measure.pi_pi] - simp [hnull i] + simp [hnull] -end MeasureTheory \ No newline at end of file +end MeasureTheory From fef3aa00b800855462596864b3bab3945bd33def Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 15:55:12 -0700 Subject: [PATCH 085/115] Fix A261865 empirical measure compatibility --- .../MeasureTheory/Probability/Empirical.lean | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean b/FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean index 0be2fb5491..28e87d5f20 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean @@ -23,7 +23,7 @@ public import FormalConjecturesForMathlib.Data.Set.Density @[expose] public section open Filter MeasureTheory Set Topology -open scoped ENNReal NNReal Topology BigOperators +open scoped ENNReal NNReal Topology BigOperators Classical noncomputable section @@ -31,36 +31,39 @@ namespace MeasureTheory variable {Ω : Type*} [MeasurableSpace Ω] +private theorem range_nonempty_of_ne_zero {N : ℕ} (hN : N ≠ 0) : + (Finset.range N).Nonempty := + ⟨0, Finset.mem_range.mpr (Nat.pos_of_ne_zero hN)⟩ + /-- The empirical probability measure of the first `N` values of a sequence. At `N = 0` we use a harmless Dirac measure. -/ def empiricalProbabilityMeasure (Y : ℕ → Ω) (N : ℕ) : ProbabilityMeasure Ω := by classical by_cases hN : N = 0 · exact ⟨Measure.dirac (Y 0), Measure.dirac.isProbabilityMeasure⟩ - · let p : PMF ℕ := PMF.uniformOfFinset (Finset.range N) - (Finset.range_nonempty.mpr (Nat.pos_of_ne_zero hN)) + · let p : PMF ℕ := PMF.uniformOfFinset (Finset.range N) (range_nonempty_of_ne_zero hN) let ν : ProbabilityMeasure ℕ := ⟨p.toMeasure, inferInstance⟩ - exact ν.map (measurable_of_countable Y).aemeasurable + exact ProbabilityMeasure.map ν (measurable_of_countable Y).aemeasurable lemma empiricalProbabilityMeasure_ne_zero (Y : ℕ → Ω) {N : ℕ} (hN : N ≠ 0) : empiricalProbabilityMeasure Y N = - (⟨(PMF.uniformOfFinset (Finset.range N) - (Finset.range_nonempty.mpr (Nat.pos_of_ne_zero hN))).toMeasure, - inferInstance⟩ : ProbabilityMeasure ℕ).map - (measurable_of_countable Y).aemeasurable := by - simp [empiricalProbabilityMeasure, hN] + ProbabilityMeasure.map + (⟨(PMF.uniformOfFinset (Finset.range N) + (range_nonempty_of_ne_zero hN)).toMeasure, + inferInstance⟩ : ProbabilityMeasure ℕ) + (measurable_of_countable Y).aemeasurable := by + simp [empiricalProbabilityMeasure, hN, range_nonempty_of_ne_zero] variable [TopologicalSpace Ω] [BorelSpace Ω] /-- Integration against the empirical measure is the corresponding finite average. -/ theorem integral_empiricalProbabilityMeasure - (Y : ℕ → Ω) {N : ℕ} (hN : N ≠ 0) (f : Ω →ᵇ ℂ) : - ∫ x, f x ∂(empiricalProbabilityMeasure Y N : ProbabilityMeasure Ω) = + (Y : ℕ → Ω) {N : ℕ} (hN : N ≠ 0) (f : BoundedContinuousFunction Ω ℂ) : + ∫ x, f x ∂(empiricalProbabilityMeasure Y N : Measure Ω) = (∑ n ∈ Finset.range N, f (Y n)) / (N : ℂ) := by classical rw [empiricalProbabilityMeasure_ne_zero Y hN] - let p : PMF ℕ := PMF.uniformOfFinset (Finset.range N) - (Finset.range_nonempty.mpr (Nat.pos_of_ne_zero hN)) + let p : PMF ℕ := PMF.uniformOfFinset (Finset.range N) (range_nonempty_of_ne_zero hN) have hY : Measurable Y := measurable_of_countable Y rw [ProbabilityMeasure.toMeasure_map] rw [integral_map hY.aemeasurable f.continuous.aestronglyMeasurable] @@ -94,7 +97,7 @@ theorem empiricalProbabilityMeasure_apply (Y : ℕ → Ω) {N : ℕ} (hN : N ≠ rw [empiricalProbabilityMeasure_ne_zero Y hN] rw [ProbabilityMeasure.map_apply] · change (((PMF.uniformOfFinset (Finset.range N) - (Finset.range_nonempty.mpr (Nat.pos_of_ne_zero hN))).toMeasure + (range_nonempty_of_ne_zero hN)).toMeasure (Y ⁻¹' A)).toNNReal) = _ rw [PMF.toMeasure_uniformOfFinset_apply] · norm_num [ENNReal.toNNReal_div, Finset.filter_filter, and_comm] @@ -129,6 +132,7 @@ theorem tendsto_frequency_of_null_frontier (fun N : ℕ => (((Finset.range N).filter fun n => Y n ∈ A).card : ℝ) / N) atTop (𝓝 ((μ A : ℝ≥0) : ℝ)) := by + classical have hweak := tendsto_empiricalProbabilityMeasure Y μ havg have hport := ProbabilityMeasure.tendsto_measure_of_null_frontier_of_tendsto hweak hfront have hcoe := (NNReal.continuous_coe.tendsto (μ A)).comp hport @@ -146,8 +150,12 @@ theorem hasDensity_of_tendsto_average {A : Set Ω} (hA : MeasurableSet A) (hfront : μ (frontier A) = 0) (S : Set ℕ) (hS : ∀ n, n ∈ S ↔ Y n ∈ A) : S.HasDensity ((μ A : ℝ≥0) : ℝ) := by + classical have hfreq := tendsto_frequency_of_null_frontier Y μ havg hA hfront - rw [Set.HasDensity, Set.partialDensity] + change Tendsto + (fun N : ℕ => (((S ∩ Set.univ) ∩ Set.Iio N).ncard : ℝ) / + ((Set.univ ∩ Set.Iio N).ncard : ℝ)) + atTop (𝓝 ((μ A : ℝ≥0) : ℝ)) apply hfreq.congr' filter_upwards with N have hfinite : ((S ∩ Set.univ) ∩ Set.Iio N).Finite := From 7ee7cf438a815fb2b0e813e465ca610f9aa70189 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 15:56:46 -0700 Subject: [PATCH 086/115] ci: close residual A261865 support-module errors --- .../workflows/a261865-one-shot-repair-5.yml | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 .github/workflows/a261865-one-shot-repair-5.yml diff --git a/.github/workflows/a261865-one-shot-repair-5.yml b/.github/workflows/a261865-one-shot-repair-5.yml new file mode 100644 index 0000000000..633f476ed2 --- /dev/null +++ b/.github/workflows/a261865-one-shot-repair-5.yml @@ -0,0 +1,73 @@ +name: Close residual A261865 support-module errors + +on: + push: + branches: [a261865-research] + paths: + - '.github/workflows/a261865-one-shot-repair-5.yml' + +permissions: + contents: write + +jobs: + repair: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + with: + ref: a261865-research + fetch-depth: 0 + + - name: Apply exact Lean repairs + shell: bash + run: | + python3 - <<'PY' + from pathlib import Path + + def replace_once(path, old, new): + p = Path(path) + text = p.read_text() + n = text.count(old) + if n != 1: + raise SystemExit(f'{path}: expected one match, found {n}: {old!r}') + p.write_text(text.replace(old, new, 1)) + + arc = 'FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean' + replace_once(arc, + ' filter_upwards [AddCircle.closedBall_ae_eq_ball\n' + ' (x := (c : UnitAddCircle)) (ε := r)] with y hy\n' + ' constructor\n', + ' filter_upwards [AddCircle.closedBall_ae_eq_ball\n' + ' (x := (c : UnitAddCircle)) (ε := r)] with y hy\n' + ' apply propext\n' + ' constructor\n') + + pi = 'FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean' + replace_once(pi, + ' rw [heq, Measure.pi_pi]\n' + ' simp [hnull]\n', + ' rw [heq, Measure.pi_pi, Finset.prod_eq_zero_iff]\n' + ' exact ⟨i, Finset.mem_univ i, by simp [hnull i]⟩\n') + + radicals = 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean' + replace_once(radicals, + ' field_simp [hsqrt, Real.sq_sqrt hpos.le]\n', + ' field_simp [hsqrt]\n' + ' exact (Real.sq_sqrt hpos.le).symm\n') + + Path('.github/workflows/a261865-one-shot-repair-5.yml').unlink() + PY + + - name: Commit repairs + shell: bash + run: | + set -euo pipefail + git config user.name 'ProofOrchestrator' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean \ + FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean \ + FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean \ + .github/workflows/a261865-one-shot-repair-5.yml + git commit -m 'Close residual A261865 support-module errors' + git push origin HEAD:a261865-research From 1cbf55d7df03a93521b299bf44afa22ae60d08d3 Mon Sep 17 00:00:00 2001 From: ProofOrchestrator <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 22:56:53 +0000 Subject: [PATCH 087/115] Close residual A261865 support-module errors --- .../workflows/a261865-one-shot-repair-5.yml | 73 ------------------- .../MeasureTheory/Group/UnitAddCircleArc.lean | 1 + .../Probability/PiContinuitySet.lean | 4 +- .../NumberTheory/SquarefreeRadicals.lean | 3 +- 4 files changed, 5 insertions(+), 76 deletions(-) delete mode 100644 .github/workflows/a261865-one-shot-repair-5.yml diff --git a/.github/workflows/a261865-one-shot-repair-5.yml b/.github/workflows/a261865-one-shot-repair-5.yml deleted file mode 100644 index 633f476ed2..0000000000 --- a/.github/workflows/a261865-one-shot-repair-5.yml +++ /dev/null @@ -1,73 +0,0 @@ -name: Close residual A261865 support-module errors - -on: - push: - branches: [a261865-research] - paths: - - '.github/workflows/a261865-one-shot-repair-5.yml' - -permissions: - contents: write - -jobs: - repair: - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: actions/checkout@v4 - with: - ref: a261865-research - fetch-depth: 0 - - - name: Apply exact Lean repairs - shell: bash - run: | - python3 - <<'PY' - from pathlib import Path - - def replace_once(path, old, new): - p = Path(path) - text = p.read_text() - n = text.count(old) - if n != 1: - raise SystemExit(f'{path}: expected one match, found {n}: {old!r}') - p.write_text(text.replace(old, new, 1)) - - arc = 'FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean' - replace_once(arc, - ' filter_upwards [AddCircle.closedBall_ae_eq_ball\n' - ' (x := (c : UnitAddCircle)) (ε := r)] with y hy\n' - ' constructor\n', - ' filter_upwards [AddCircle.closedBall_ae_eq_ball\n' - ' (x := (c : UnitAddCircle)) (ε := r)] with y hy\n' - ' apply propext\n' - ' constructor\n') - - pi = 'FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean' - replace_once(pi, - ' rw [heq, Measure.pi_pi]\n' - ' simp [hnull]\n', - ' rw [heq, Measure.pi_pi, Finset.prod_eq_zero_iff]\n' - ' exact ⟨i, Finset.mem_univ i, by simp [hnull i]⟩\n') - - radicals = 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean' - replace_once(radicals, - ' field_simp [hsqrt, Real.sq_sqrt hpos.le]\n', - ' field_simp [hsqrt]\n' - ' exact (Real.sq_sqrt hpos.le).symm\n') - - Path('.github/workflows/a261865-one-shot-repair-5.yml').unlink() - PY - - - name: Commit repairs - shell: bash - run: | - set -euo pipefail - git config user.name 'ProofOrchestrator' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean \ - FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean \ - FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean \ - .github/workflows/a261865-one-shot-repair-5.yml - git commit -m 'Close residual A261865 support-module errors' - git push origin HEAD:a261865-research diff --git a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean index 2de2cb400b..4d2ffacc8d 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean @@ -95,6 +95,7 @@ theorem volume_sphere_eq_zero {c r : ℝ} (_hr0 : 0 ≤ r) (_hr : r < 1 / 2) : rw [← ae_eq_empty] filter_upwards [AddCircle.closedBall_ae_eq_ball (x := (c : UnitAddCircle)) (ε := r)] with y hy + apply propext constructor · intro hysphere have hclosed : y ∈ Metric.closedBall (c : UnitAddCircle) r := diff --git a/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean b/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean index a7aff9a2b1..35f7cb8698 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean @@ -99,7 +99,7 @@ theorem measure_frontier_pi_eq_zero Set.pi univ (fun j => if j = i then frontier (A j) else univ) := by ext x simp [Set.mem_pi] - rw [heq, Measure.pi_pi] - simp [hnull] + rw [heq, Measure.pi_pi, Finset.prod_eq_zero_iff] + exact ⟨i, Finset.mem_univ i, by simp [hnull i]⟩ end MeasureTheory diff --git a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean index a071fa9ff5..ec07c44b80 100644 --- a/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean +++ b/FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean @@ -39,6 +39,7 @@ theorem linearIndependent_inv_sqrt_squarefree {ι : Type*} [Fintype ι] change 1 / Real.sqrt (s i) = (((((s i : ℚ)⁻¹ : ℚ) : ℝ)) * Real.sqrt (s i)) rw [Rat.cast_inv, Rat.cast_natCast] - field_simp [hsqrt, Real.sq_sqrt hpos.le] + field_simp [hsqrt] + exact (Real.sq_sqrt hpos.le).symm end Real From 49749673b476dee0646cf853ac05711a13c662f1 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 15:58:09 -0700 Subject: [PATCH 088/115] ci: apply focused A261865 foundation repairs --- .../workflows/a261865-foundation-autofix.yml | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 .github/workflows/a261865-foundation-autofix.yml diff --git a/.github/workflows/a261865-foundation-autofix.yml b/.github/workflows/a261865-foundation-autofix.yml new file mode 100644 index 0000000000..0d89fa0165 --- /dev/null +++ b/.github/workflows/a261865-foundation-autofix.yml @@ -0,0 +1,132 @@ +# Copyright 2025 The Formal Conjectures Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: Apply A261865 foundation repairs + +on: + push: + branches: [a261865-research] + paths: + - '.github/workflows/a261865-foundation-autofix.yml' + +permissions: + contents: write + +jobs: + patch: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + with: + ref: a261865-research + fetch-depth: 0 + - name: Apply exact source replacements + shell: bash + run: | + set -euo pipefail + python3 - <<'PY' + from pathlib import Path + + def replace_exact(path: str, old: str, new: str) -> None: + p = Path(path) + text = p.read_text() + count = text.count(old) + if count != 1: + raise SystemExit(f"{path}: expected one match, found {count}: {old!r}") + p.write_text(text.replace(old, new)) + + squarefree = 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean' + replace_exact(squarefree, + ' rw [ha.ext_iff hb]\n', + ' rw [Nat.Squarefree.ext_iff ha hb]\n') + replace_exact(squarefree, + ''' have heq : minpoly ℚ x = X ^ 2 - C r := + Polynomial.eq_of_monic_of_dvd_of_natDegree_le (minpoly.monic hint) hmonic hdvd + (by rw [hdeg2, Polynomial.natDegree_X_pow_sub_C]) +''', + ''' have heq : minpoly ℚ x = X ^ 2 - C r := by + symm + exact Polynomial.eq_of_monic_of_dvd_of_natDegree_le + (p := minpoly ℚ x) (q := X ^ 2 - C r) + (minpoly.monic hint) hmonic hdvd + (by rw [hdeg2, Polynomial.natDegree_X_pow_sub_C]) +''') + replace_exact(squarefree, + ''' refine ⟨Polynomial.X ^ 2 - Polynomial.C (s i : ℚ), ?_, ?_⟩ + · exact Polynomial.monic_X_pow_sub_C _ two_ne_zero + · norm_num [← Polynomial.C_pow] + norm_cast + rw [Real.sq_sqrt (Nat.cast_nonneg _)] + ring +''', + ''' refine ⟨Polynomial.X ^ 2 - Polynomial.C (s i : ℚ), + Polynomial.monic_X_pow_sub_C _ two_ne_zero, ?_⟩ + norm_num [← Polynomial.C_pow] + norm_cast + rw [Real.sq_sqrt (Nat.cast_nonneg _)] + ring +''') + replace_exact(squarefree, + ''' apply Subtype.ext + simp only [root] + push_cast + rw [Real.sq_sqrt (Nat.cast_nonneg _)] + norm_cast +''', + ''' apply Subtype.ext + simp [root, Real.sq_sqrt (Nat.cast_nonneg _)] +''') + + torus = 'FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean' + replace_exact(torus, + ' linarith [htri, h1, h2, hN0\', hdist]\n', + ''' have hdist' : ‖F - p‖ < ε / 3 := by + simpa [norm_sub_rev] using hdist + linarith [htri, h1, h2, hN0', hdist'] +''') + replace_exact(torus, + ' | zero => simp [mFourier_zero]\n', + ' | zero => simp [mFourier, fourier_apply]\n') + replace_exact(torus, + ' obtain ⟨z, hz⟩ := AddCircle.coe_eq_zero_iff.mp hzero\'\n', + ' obtain ⟨z, hz⟩ := (AddCircle.coe_eq_zero_iff).mp hzero\'\n') + replace_exact(torus, + ''' simpa only [ContinuousMap.inner_toLp, mFourier_zero, ContinuousMap.one_apply, + map_one, one_mul, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h +''', + ''' simpa only [ContinuousMap.inner_toLp, mFourier_zero, ContinuousMap.one_apply, + map_one, one_mul, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h.symm +''') + replace_exact(torus, + ' _ = 2 := by simp [norm_pow, hnorm]\n', + ''' _ = 2 := by + rw [norm_pow, hnorm] + norm_num +''') + replace_exact(torus, + ' simp [mFourier, fourier_apply, norm_prod, Circle.norm_coe]\n', + ' simp [mFourier, fourier_apply, norm_prod, Complex.norm_exp]\n') + PY + git rm .github/workflows/a261865-foundation-autofix.yml + - name: Commit repaired foundations + shell: bash + run: | + set -euo pipefail + git config user.name 'ProofOrchestrator' + git config user.email 'actions@users.noreply.github.com' + git add FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean \ + FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean + git commit -m 'Fix A261865 Lean foundation errors from AXLE' + git push origin HEAD:a261865-research From a230d03f5ba861cf3d067df03f9cf6e766c2efed Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:00:27 -0700 Subject: [PATCH 089/115] ci: trigger A261865 foundation repair --- .github/a261865-foundation-repair.trigger | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/a261865-foundation-repair.trigger diff --git a/.github/a261865-foundation-repair.trigger b/.github/a261865-foundation-repair.trigger new file mode 100644 index 0000000000..96f253351d --- /dev/null +++ b/.github/a261865-foundation-repair.trigger @@ -0,0 +1 @@ +repair-pass-1 From 1761292dbfa5a4ff4329b09e403e4ebd467932a7 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:00:50 -0700 Subject: [PATCH 090/115] ci: close remaining A261865 empirical errors --- .../workflows/a261865-one-shot-repair-6.yml | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 .github/workflows/a261865-one-shot-repair-6.yml diff --git a/.github/workflows/a261865-one-shot-repair-6.yml b/.github/workflows/a261865-one-shot-repair-6.yml new file mode 100644 index 0000000000..9fdfba3a3f --- /dev/null +++ b/.github/workflows/a261865-one-shot-repair-6.yml @@ -0,0 +1,94 @@ +name: Close remaining A261865 empirical errors + +on: + push: + branches: [a261865-research] + paths: + - '.github/workflows/a261865-one-shot-repair-6.yml' + +permissions: + contents: write + +jobs: + repair: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + with: + ref: a261865-research + fetch-depth: 0 + + - name: Apply exact Lean repairs + shell: bash + run: | + python3 - <<'PY' + from pathlib import Path + + path = Path('FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean') + text = path.read_text() + + def replace_once(old, new): + global text + n = text.count(old) + if n != 1: + raise SystemExit(f'expected one match, found {n}: {old!r}') + text = text.replace(old, new, 1) + + replace_once( + 'private theorem range_nonempty_of_ne_zero {N : ℕ} (hN : N ≠ 0) :\n' + ' (Finset.range N).Nonempty :=\n' + ' ⟨0, Finset.mem_range.mpr (Nat.pos_of_ne_zero hN)⟩\n', + 'theorem empiricalRange_nonempty_of_ne_zero {N : ℕ} (hN : N ≠ 0) :\n' + ' (Finset.range N).Nonempty :=\n' + ' ⟨0, Finset.mem_range.mpr (Nat.pos_of_ne_zero hN)⟩\n') + text = text.replace('range_nonempty_of_ne_zero', 'empiricalRange_nonempty_of_ne_zero') + + replace_once( + 'variable [TopologicalSpace Ω] [BorelSpace Ω]\n', + 'variable [PseudoMetricSpace Ω] [BorelSpace Ω]\n') + replace_once( + 'variable [CompactSpace Ω] [PseudoMetricSpace Ω]\n', + 'variable [CompactSpace Ω]\n') + + replace_once( + ' have hfint : Integrable (fun n => f (Y n)) p.toMeasure := by\n' + ' refine (integrable_const ‖f‖).mono ?_ ?_\n' + ' · exact (measurable_of_countable (fun n => f (Y n))).aestronglyMeasurable\n' + ' · exact Filter.Eventually.of_forall fun n => f.norm_coe_le_norm (Y n)\n', + ' have hfint : Integrable (fun n => f (Y n)) p.toMeasure := by\n' + ' have hc : Integrable (fun _ : ℕ => (‖f‖ : ℂ)) p.toMeasure := integrable_const _\n' + ' refine hc.mono ?_ ?_\n' + ' · exact (measurable_of_countable (fun n => f (Y n))).aestronglyMeasurable\n' + ' · exact Filter.Eventually.of_forall fun n => by\n' + ' simpa using f.norm_coe_le_norm (Y n)\n') + + replace_once( + ' exact integral_empiricalProbabilityMeasure Y hN f\n', + ' exact (integral_empiricalProbabilityMeasure Y hN f).symm\n') + + replace_once( + ' filter_upwards [eventually_ne_atTop 0] with N hN\n' + ' rw [empiricalProbabilityMeasure_apply Y hN hA]\n', + ' filter_upwards [eventually_ne_atTop 0] with N hN\n' + ' simp only [Function.comp_apply]\n' + ' rw [empiricalProbabilityMeasure_apply Y hN hA]\n') + + replace_once( + ' simp [hS]\n', + ' simp [hS, and_comm]\n') + + path.write_text(text) + Path('.github/workflows/a261865-one-shot-repair-6.yml').unlink() + PY + + - name: Commit repairs + shell: bash + run: | + set -euo pipefail + git config user.name 'ProofOrchestrator' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean \ + .github/workflows/a261865-one-shot-repair-6.yml + git commit -m 'Close remaining A261865 empirical compatibility errors' + git push origin HEAD:a261865-research From f5d289e074dc692ab75eb6050128339ef95861c2 Mon Sep 17 00:00:00 2001 From: ProofOrchestrator <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 23:00:59 +0000 Subject: [PATCH 091/115] Close remaining A261865 empirical compatibility errors --- .../workflows/a261865-one-shot-repair-6.yml | 94 ------------------- .../MeasureTheory/Probability/Empirical.lean | 27 +++--- 2 files changed, 15 insertions(+), 106 deletions(-) delete mode 100644 .github/workflows/a261865-one-shot-repair-6.yml diff --git a/.github/workflows/a261865-one-shot-repair-6.yml b/.github/workflows/a261865-one-shot-repair-6.yml deleted file mode 100644 index 9fdfba3a3f..0000000000 --- a/.github/workflows/a261865-one-shot-repair-6.yml +++ /dev/null @@ -1,94 +0,0 @@ -name: Close remaining A261865 empirical errors - -on: - push: - branches: [a261865-research] - paths: - - '.github/workflows/a261865-one-shot-repair-6.yml' - -permissions: - contents: write - -jobs: - repair: - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: actions/checkout@v4 - with: - ref: a261865-research - fetch-depth: 0 - - - name: Apply exact Lean repairs - shell: bash - run: | - python3 - <<'PY' - from pathlib import Path - - path = Path('FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean') - text = path.read_text() - - def replace_once(old, new): - global text - n = text.count(old) - if n != 1: - raise SystemExit(f'expected one match, found {n}: {old!r}') - text = text.replace(old, new, 1) - - replace_once( - 'private theorem range_nonempty_of_ne_zero {N : ℕ} (hN : N ≠ 0) :\n' - ' (Finset.range N).Nonempty :=\n' - ' ⟨0, Finset.mem_range.mpr (Nat.pos_of_ne_zero hN)⟩\n', - 'theorem empiricalRange_nonempty_of_ne_zero {N : ℕ} (hN : N ≠ 0) :\n' - ' (Finset.range N).Nonempty :=\n' - ' ⟨0, Finset.mem_range.mpr (Nat.pos_of_ne_zero hN)⟩\n') - text = text.replace('range_nonempty_of_ne_zero', 'empiricalRange_nonempty_of_ne_zero') - - replace_once( - 'variable [TopologicalSpace Ω] [BorelSpace Ω]\n', - 'variable [PseudoMetricSpace Ω] [BorelSpace Ω]\n') - replace_once( - 'variable [CompactSpace Ω] [PseudoMetricSpace Ω]\n', - 'variable [CompactSpace Ω]\n') - - replace_once( - ' have hfint : Integrable (fun n => f (Y n)) p.toMeasure := by\n' - ' refine (integrable_const ‖f‖).mono ?_ ?_\n' - ' · exact (measurable_of_countable (fun n => f (Y n))).aestronglyMeasurable\n' - ' · exact Filter.Eventually.of_forall fun n => f.norm_coe_le_norm (Y n)\n', - ' have hfint : Integrable (fun n => f (Y n)) p.toMeasure := by\n' - ' have hc : Integrable (fun _ : ℕ => (‖f‖ : ℂ)) p.toMeasure := integrable_const _\n' - ' refine hc.mono ?_ ?_\n' - ' · exact (measurable_of_countable (fun n => f (Y n))).aestronglyMeasurable\n' - ' · exact Filter.Eventually.of_forall fun n => by\n' - ' simpa using f.norm_coe_le_norm (Y n)\n') - - replace_once( - ' exact integral_empiricalProbabilityMeasure Y hN f\n', - ' exact (integral_empiricalProbabilityMeasure Y hN f).symm\n') - - replace_once( - ' filter_upwards [eventually_ne_atTop 0] with N hN\n' - ' rw [empiricalProbabilityMeasure_apply Y hN hA]\n', - ' filter_upwards [eventually_ne_atTop 0] with N hN\n' - ' simp only [Function.comp_apply]\n' - ' rw [empiricalProbabilityMeasure_apply Y hN hA]\n') - - replace_once( - ' simp [hS]\n', - ' simp [hS, and_comm]\n') - - path.write_text(text) - Path('.github/workflows/a261865-one-shot-repair-6.yml').unlink() - PY - - - name: Commit repairs - shell: bash - run: | - set -euo pipefail - git config user.name 'ProofOrchestrator' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean \ - .github/workflows/a261865-one-shot-repair-6.yml - git commit -m 'Close remaining A261865 empirical compatibility errors' - git push origin HEAD:a261865-research diff --git a/FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean b/FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean index 28e87d5f20..525bfba069 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean @@ -31,7 +31,7 @@ namespace MeasureTheory variable {Ω : Type*} [MeasurableSpace Ω] -private theorem range_nonempty_of_ne_zero {N : ℕ} (hN : N ≠ 0) : +theorem empiricalRange_nonempty_of_ne_zero {N : ℕ} (hN : N ≠ 0) : (Finset.range N).Nonempty := ⟨0, Finset.mem_range.mpr (Nat.pos_of_ne_zero hN)⟩ @@ -41,7 +41,7 @@ def empiricalProbabilityMeasure (Y : ℕ → Ω) (N : ℕ) : ProbabilityMeasure classical by_cases hN : N = 0 · exact ⟨Measure.dirac (Y 0), Measure.dirac.isProbabilityMeasure⟩ - · let p : PMF ℕ := PMF.uniformOfFinset (Finset.range N) (range_nonempty_of_ne_zero hN) + · let p : PMF ℕ := PMF.uniformOfFinset (Finset.range N) (empiricalRange_nonempty_of_ne_zero hN) let ν : ProbabilityMeasure ℕ := ⟨p.toMeasure, inferInstance⟩ exact ProbabilityMeasure.map ν (measurable_of_countable Y).aemeasurable @@ -49,12 +49,12 @@ lemma empiricalProbabilityMeasure_ne_zero (Y : ℕ → Ω) {N : ℕ} (hN : N ≠ empiricalProbabilityMeasure Y N = ProbabilityMeasure.map (⟨(PMF.uniformOfFinset (Finset.range N) - (range_nonempty_of_ne_zero hN)).toMeasure, + (empiricalRange_nonempty_of_ne_zero hN)).toMeasure, inferInstance⟩ : ProbabilityMeasure ℕ) (measurable_of_countable Y).aemeasurable := by - simp [empiricalProbabilityMeasure, hN, range_nonempty_of_ne_zero] + simp [empiricalProbabilityMeasure, hN, empiricalRange_nonempty_of_ne_zero] -variable [TopologicalSpace Ω] [BorelSpace Ω] +variable [PseudoMetricSpace Ω] [BorelSpace Ω] /-- Integration against the empirical measure is the corresponding finite average. -/ theorem integral_empiricalProbabilityMeasure @@ -63,14 +63,16 @@ theorem integral_empiricalProbabilityMeasure (∑ n ∈ Finset.range N, f (Y n)) / (N : ℂ) := by classical rw [empiricalProbabilityMeasure_ne_zero Y hN] - let p : PMF ℕ := PMF.uniformOfFinset (Finset.range N) (range_nonempty_of_ne_zero hN) + let p : PMF ℕ := PMF.uniformOfFinset (Finset.range N) (empiricalRange_nonempty_of_ne_zero hN) have hY : Measurable Y := measurable_of_countable Y rw [ProbabilityMeasure.toMeasure_map] rw [integral_map hY.aemeasurable f.continuous.aestronglyMeasurable] have hfint : Integrable (fun n => f (Y n)) p.toMeasure := by - refine (integrable_const ‖f‖).mono ?_ ?_ + have hc : Integrable (fun _ : ℕ => (‖f‖ : ℂ)) p.toMeasure := integrable_const _ + refine hc.mono ?_ ?_ · exact (measurable_of_countable (fun n => f (Y n))).aestronglyMeasurable - · exact Filter.Eventually.of_forall fun n => f.norm_coe_le_norm (Y n) + · exact Filter.Eventually.of_forall fun n => by + simpa using f.norm_coe_le_norm (Y n) rw [PMF.integral_eq_tsum p (fun n => f (Y n)) hfint] rw [tsum_eq_sum (s := Finset.range N)] · calc @@ -97,14 +99,14 @@ theorem empiricalProbabilityMeasure_apply (Y : ℕ → Ω) {N : ℕ} (hN : N ≠ rw [empiricalProbabilityMeasure_ne_zero Y hN] rw [ProbabilityMeasure.map_apply] · change (((PMF.uniformOfFinset (Finset.range N) - (range_nonempty_of_ne_zero hN)).toMeasure + (empiricalRange_nonempty_of_ne_zero hN)).toMeasure (Y ⁻¹' A)).toNNReal) = _ rw [PMF.toMeasure_uniformOfFinset_apply] · norm_num [ENNReal.toNNReal_div, Finset.filter_filter, and_comm] · exact (measurable_of_countable Y) hA · exact hA -variable [CompactSpace Ω] [PseudoMetricSpace Ω] +variable [CompactSpace Ω] /-- Continuous-test-function convergence of finite orbit averages gives weak convergence of the empirical probability measures. -/ @@ -119,7 +121,7 @@ theorem tendsto_empiricalProbabilityMeasure have h := havg ⟨f, f.continuous⟩ apply h.congr' filter_upwards [eventually_ne_atTop 0] with N hN - exact integral_empiricalProbabilityMeasure Y hN f + exact (integral_empiricalProbabilityMeasure Y hN f).symm /-- The finite frequency of a continuity set converges to its limiting probability. -/ theorem tendsto_frequency_of_null_frontier @@ -138,6 +140,7 @@ theorem tendsto_frequency_of_null_frontier have hcoe := (NNReal.continuous_coe.tendsto (μ A)).comp hport apply hcoe.congr' filter_upwards [eventually_ne_atTop 0] with N hN + simp only [Function.comp_apply] rw [empiricalProbabilityMeasure_apply Y hN hA] norm_num [NNReal.coe_div] @@ -166,7 +169,7 @@ theorem hasDensity_of_tendsto_average rw [Set.ncard_eq_toFinset_card _ hfinite] congr 1 ext n - simp [hS] + simp [hS, and_comm] rw [hcard] simp From 38ce5aa32339e457dc93ec5749c989aed18fe7bc Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:04:28 -0700 Subject: [PATCH 092/115] ci: close final A261865 support-module mismatch --- .../workflows/a261865-one-shot-repair-7.yml | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 .github/workflows/a261865-one-shot-repair-7.yml diff --git a/.github/workflows/a261865-one-shot-repair-7.yml b/.github/workflows/a261865-one-shot-repair-7.yml new file mode 100644 index 0000000000..f805b99a06 --- /dev/null +++ b/.github/workflows/a261865-one-shot-repair-7.yml @@ -0,0 +1,53 @@ +name: Close final A261865 support-module mismatch + +on: + push: + branches: [a261865-research] + paths: + - '.github/workflows/a261865-one-shot-repair-7.yml' + +permissions: + contents: write + +jobs: + repair: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + with: + ref: a261865-research + fetch-depth: 0 + + - name: Apply exact Lean repair + shell: bash + run: | + python3 - <<'PY' + from pathlib import Path + path = Path('FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean') + text = path.read_text() + old = ( + ' rw [integral_map hY.aemeasurable f.continuous.aestronglyMeasurable]\n' + ' have hfint : Integrable (fun n => f (Y n)) p.toMeasure := by\n' + ) + new = ( + ' rw [integral_map hY.aemeasurable f.continuous.aestronglyMeasurable]\n' + ' change (∫ n : ℕ, f (Y n) ∂p.toMeasure) = _\n' + ' have hfint : Integrable (fun n => f (Y n)) p.toMeasure := by\n' + ) + if text.count(old) != 1: + raise SystemExit(f'expected one match, found {text.count(old)}') + path.write_text(text.replace(old, new, 1)) + Path('.github/workflows/a261865-one-shot-repair-7.yml').unlink() + PY + + - name: Commit repair + shell: bash + run: | + set -euo pipefail + git config user.name 'ProofOrchestrator' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean \ + .github/workflows/a261865-one-shot-repair-7.yml + git commit -m 'Close final A261865 empirical measure mismatch' + git push origin HEAD:a261865-research From 7e90ad249783ca57e64c541079d27591a5f23796 Mon Sep 17 00:00:00 2001 From: ProofOrchestrator <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 23:04:36 +0000 Subject: [PATCH 093/115] Close final A261865 empirical measure mismatch --- .../workflows/a261865-one-shot-repair-7.yml | 53 ------------------- .../MeasureTheory/Probability/Empirical.lean | 1 + 2 files changed, 1 insertion(+), 53 deletions(-) delete mode 100644 .github/workflows/a261865-one-shot-repair-7.yml diff --git a/.github/workflows/a261865-one-shot-repair-7.yml b/.github/workflows/a261865-one-shot-repair-7.yml deleted file mode 100644 index f805b99a06..0000000000 --- a/.github/workflows/a261865-one-shot-repair-7.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: Close final A261865 support-module mismatch - -on: - push: - branches: [a261865-research] - paths: - - '.github/workflows/a261865-one-shot-repair-7.yml' - -permissions: - contents: write - -jobs: - repair: - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: actions/checkout@v4 - with: - ref: a261865-research - fetch-depth: 0 - - - name: Apply exact Lean repair - shell: bash - run: | - python3 - <<'PY' - from pathlib import Path - path = Path('FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean') - text = path.read_text() - old = ( - ' rw [integral_map hY.aemeasurable f.continuous.aestronglyMeasurable]\n' - ' have hfint : Integrable (fun n => f (Y n)) p.toMeasure := by\n' - ) - new = ( - ' rw [integral_map hY.aemeasurable f.continuous.aestronglyMeasurable]\n' - ' change (∫ n : ℕ, f (Y n) ∂p.toMeasure) = _\n' - ' have hfint : Integrable (fun n => f (Y n)) p.toMeasure := by\n' - ) - if text.count(old) != 1: - raise SystemExit(f'expected one match, found {text.count(old)}') - path.write_text(text.replace(old, new, 1)) - Path('.github/workflows/a261865-one-shot-repair-7.yml').unlink() - PY - - - name: Commit repair - shell: bash - run: | - set -euo pipefail - git config user.name 'ProofOrchestrator' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean \ - .github/workflows/a261865-one-shot-repair-7.yml - git commit -m 'Close final A261865 empirical measure mismatch' - git push origin HEAD:a261865-research diff --git a/FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean b/FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean index 525bfba069..3b7e5d9aff 100644 --- a/FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean +++ b/FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean @@ -67,6 +67,7 @@ theorem integral_empiricalProbabilityMeasure have hY : Measurable Y := measurable_of_countable Y rw [ProbabilityMeasure.toMeasure_map] rw [integral_map hY.aemeasurable f.continuous.aestronglyMeasurable] + change (∫ n : ℕ, f (Y n) ∂p.toMeasure) = _ have hfint : Integrable (fun n => f (Y n)) p.toMeasure := by have hc : Integrable (fun _ : ℕ => (‖f‖ : ℂ)) p.toMeasure := integrable_const _ refine hc.mono ?_ ?_ From 01a99ab7a73dcab635b1c4747a0b2756e00882e3 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:12:07 -0700 Subject: [PATCH 094/115] ci: repair A261865 terminal-box and base dependencies --- .../workflows/a261865-one-shot-repair-8.yml | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 .github/workflows/a261865-one-shot-repair-8.yml diff --git a/.github/workflows/a261865-one-shot-repair-8.yml b/.github/workflows/a261865-one-shot-repair-8.yml new file mode 100644 index 0000000000..a6abdd8e83 --- /dev/null +++ b/.github/workflows/a261865-one-shot-repair-8.yml @@ -0,0 +1,111 @@ +name: Repair A261865 terminal-box and base dependencies + +on: + push: + branches: [a261865-research] + paths: + - '.github/workflows/a261865-one-shot-repair-8.yml' + +permissions: + contents: write + +jobs: + repair: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + with: + ref: a261865-research + fetch-depth: 0 + + - name: Apply exact Lean repairs + shell: bash + run: | + python3 - <<'PY' + from pathlib import Path + + def replace_once(path, old, new): + p = Path(path) + text = p.read_text() + n = text.count(old) + if n != 1: + raise SystemExit(f'{path}: expected one match, found {n}: {old!r}') + p.write_text(text.replace(old, new, 1)) + + box = 'FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean' + replace_once(box, + ' by_cases h : i = j\n' + ' · simp [terminalCoordinateSet, h,\n' + ' UnitAddCircle.volume_frontier_terminalArc (ha0 i) (ha1 i)]\n' + ' · simp [terminalCoordinateSet, h,\n' + ' UnitAddCircle.volume_frontier_terminalArc_compl (ha0 i) (ha1 i)]\n', + ' by_cases h : i = j\n' + ' · subst i\n' + ' simpa [terminalCoordinateSet] using\n' + ' UnitAddCircle.volume_frontier_terminalArc (ha0 j) (ha1 j)\n' + ' · simpa [terminalCoordinateSet, h] using\n' + ' UnitAddCircle.volume_frontier_terminalArc_compl (ha0 i) (ha1 i)\n') + + replace_once(box, + ' by_cases h : i = j\n' + ' · simp [terminalCoordinateSet, h, UnitAddCircle.volume_terminalArc (ha0 i) (ha1 i)]\n' + ' · simp [terminalCoordinateSet, h, UnitAddCircle.volume_terminalArc_compl (ha0 i) (ha1 i)]\n', + ' by_cases h : i = j\n' + ' · subst i\n' + ' simpa [terminalCoordinateSet] using\n' + ' UnitAddCircle.volume_terminalArc (ha0 j) (ha1 j)\n' + ' · simpa [terminalCoordinateSet, h] using\n' + ' UnitAddCircle.volume_terminalArc_compl (ha0 i) (ha1 i)\n') + + replace_once(box, + ' _ = a j * ∏ i ∈ Finset.univ.erase j, (1 - a i) := by\n' + ' simp\n', + ' _ = a j * ∏ i ∈ Finset.univ.erase j, (1 - a i) := by\n' + ' simp only [if_pos rfl]\n' + ' apply congrArg (fun x => a j * x)\n' + ' apply Finset.prod_congr rfl\n' + ' intro i hi\n' + ' have hij : i ≠ j := (Finset.mem_erase.mp hi).1\n' + ' simp [hij]\n') + + replace_once(box, + ' (measurableSet_terminalBox j a) (by simpa [μ] using volume_frontier_terminalBox j a ha0 ha1)\n', + ' (measurableSet_terminalBox j a) (by\n' + ' change (volume (frontier (terminalBox j a))).toNNReal = 0\n' + ' rw [volume_frontier_terminalBox j a ha0 ha1]\n' + ' rfl)\n') + + replace_once(box, + ' convert hd using 1\n' + ' simp only [μ]\n' + ' rw [show (((⟨volume, inferInstance⟩ : ProbabilityMeasure (UnitAddTorus ι))\n' + ' (terminalBox j a) : ℝ≥0) : ℝ) =\n' + ' (volume (terminalBox j a)).toReal by simp]\n' + ' rw [volume_terminalBox j a ha0 ha1, ENNReal.toReal_ofReal]\n' + ' positivity\n', + ' convert hd using 1\n' + ' change a j * ∏ i ∈ Finset.univ.erase j, (1 - a i) =\n' + ' (volume (terminalBox j a)).toReal\n' + ' rw [volume_terminalBox j a ha0 ha1, ENNReal.toReal_ofReal]\n' + ' positivity\n') + + base = 'FormalConjectures/OEIS/A261865Base.lean' + replace_once(base, + 'public import FormalConjecturesUtil\n', + 'public import Mathlib\n') + + Path('.github/workflows/a261865-one-shot-repair-8.yml').unlink() + PY + + - name: Commit repairs + shell: bash + run: | + set -euo pipefail + git config user.name 'ProofOrchestrator' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean \ + FormalConjectures/OEIS/A261865Base.lean \ + .github/workflows/a261865-one-shot-repair-8.yml + git commit -m 'Fix A261865 terminal-box and base compatibility' + git push origin HEAD:a261865-research From 4411d3f814b955491d540892e6037516e198f412 Mon Sep 17 00:00:00 2001 From: ProofOrchestrator <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 23:12:18 +0000 Subject: [PATCH 095/115] Fix A261865 terminal-box and base compatibility --- .../workflows/a261865-one-shot-repair-8.yml | 111 ------------------ FormalConjectures/OEIS/A261865Base.lean | 2 +- .../Equidistribution/TerminalBox.lean | 34 ++++-- 3 files changed, 23 insertions(+), 124 deletions(-) delete mode 100644 .github/workflows/a261865-one-shot-repair-8.yml diff --git a/.github/workflows/a261865-one-shot-repair-8.yml b/.github/workflows/a261865-one-shot-repair-8.yml deleted file mode 100644 index a6abdd8e83..0000000000 --- a/.github/workflows/a261865-one-shot-repair-8.yml +++ /dev/null @@ -1,111 +0,0 @@ -name: Repair A261865 terminal-box and base dependencies - -on: - push: - branches: [a261865-research] - paths: - - '.github/workflows/a261865-one-shot-repair-8.yml' - -permissions: - contents: write - -jobs: - repair: - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: actions/checkout@v4 - with: - ref: a261865-research - fetch-depth: 0 - - - name: Apply exact Lean repairs - shell: bash - run: | - python3 - <<'PY' - from pathlib import Path - - def replace_once(path, old, new): - p = Path(path) - text = p.read_text() - n = text.count(old) - if n != 1: - raise SystemExit(f'{path}: expected one match, found {n}: {old!r}') - p.write_text(text.replace(old, new, 1)) - - box = 'FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean' - replace_once(box, - ' by_cases h : i = j\n' - ' · simp [terminalCoordinateSet, h,\n' - ' UnitAddCircle.volume_frontier_terminalArc (ha0 i) (ha1 i)]\n' - ' · simp [terminalCoordinateSet, h,\n' - ' UnitAddCircle.volume_frontier_terminalArc_compl (ha0 i) (ha1 i)]\n', - ' by_cases h : i = j\n' - ' · subst i\n' - ' simpa [terminalCoordinateSet] using\n' - ' UnitAddCircle.volume_frontier_terminalArc (ha0 j) (ha1 j)\n' - ' · simpa [terminalCoordinateSet, h] using\n' - ' UnitAddCircle.volume_frontier_terminalArc_compl (ha0 i) (ha1 i)\n') - - replace_once(box, - ' by_cases h : i = j\n' - ' · simp [terminalCoordinateSet, h, UnitAddCircle.volume_terminalArc (ha0 i) (ha1 i)]\n' - ' · simp [terminalCoordinateSet, h, UnitAddCircle.volume_terminalArc_compl (ha0 i) (ha1 i)]\n', - ' by_cases h : i = j\n' - ' · subst i\n' - ' simpa [terminalCoordinateSet] using\n' - ' UnitAddCircle.volume_terminalArc (ha0 j) (ha1 j)\n' - ' · simpa [terminalCoordinateSet, h] using\n' - ' UnitAddCircle.volume_terminalArc_compl (ha0 i) (ha1 i)\n') - - replace_once(box, - ' _ = a j * ∏ i ∈ Finset.univ.erase j, (1 - a i) := by\n' - ' simp\n', - ' _ = a j * ∏ i ∈ Finset.univ.erase j, (1 - a i) := by\n' - ' simp only [if_pos rfl]\n' - ' apply congrArg (fun x => a j * x)\n' - ' apply Finset.prod_congr rfl\n' - ' intro i hi\n' - ' have hij : i ≠ j := (Finset.mem_erase.mp hi).1\n' - ' simp [hij]\n') - - replace_once(box, - ' (measurableSet_terminalBox j a) (by simpa [μ] using volume_frontier_terminalBox j a ha0 ha1)\n', - ' (measurableSet_terminalBox j a) (by\n' - ' change (volume (frontier (terminalBox j a))).toNNReal = 0\n' - ' rw [volume_frontier_terminalBox j a ha0 ha1]\n' - ' rfl)\n') - - replace_once(box, - ' convert hd using 1\n' - ' simp only [μ]\n' - ' rw [show (((⟨volume, inferInstance⟩ : ProbabilityMeasure (UnitAddTorus ι))\n' - ' (terminalBox j a) : ℝ≥0) : ℝ) =\n' - ' (volume (terminalBox j a)).toReal by simp]\n' - ' rw [volume_terminalBox j a ha0 ha1, ENNReal.toReal_ofReal]\n' - ' positivity\n', - ' convert hd using 1\n' - ' change a j * ∏ i ∈ Finset.univ.erase j, (1 - a i) =\n' - ' (volume (terminalBox j a)).toReal\n' - ' rw [volume_terminalBox j a ha0 ha1, ENNReal.toReal_ofReal]\n' - ' positivity\n') - - base = 'FormalConjectures/OEIS/A261865Base.lean' - replace_once(base, - 'public import FormalConjecturesUtil\n', - 'public import Mathlib\n') - - Path('.github/workflows/a261865-one-shot-repair-8.yml').unlink() - PY - - - name: Commit repairs - shell: bash - run: | - set -euo pipefail - git config user.name 'ProofOrchestrator' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean \ - FormalConjectures/OEIS/A261865Base.lean \ - .github/workflows/a261865-one-shot-repair-8.yml - git commit -m 'Fix A261865 terminal-box and base compatibility' - git push origin HEAD:a261865-research diff --git a/FormalConjectures/OEIS/A261865Base.lean b/FormalConjectures/OEIS/A261865Base.lean index d24b22be65..23e4fa4469 100644 --- a/FormalConjectures/OEIS/A261865Base.lean +++ b/FormalConjectures/OEIS/A261865Base.lean @@ -15,7 +15,7 @@ limitations under the License. -/ module -public import FormalConjecturesUtil +public import Mathlib public import FormalConjecturesForMathlib.Analysis.Equidistribution.UnitAddTorus public import FormalConjecturesForMathlib.NumberTheory.SquarefreeRadicals diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean index 7531a69ac5..b54838cce7 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean @@ -84,10 +84,11 @@ theorem volume_frontier_terminalCoordinateSet [DecidableEq ι] (j : ι) (a : ι → ℝ) (ha0 : ∀ i, 0 < a i) (ha1 : ∀ i, a i < 1) (i : ι) : volume (frontier (terminalCoordinateSet j a i)) = 0 := by by_cases h : i = j - · simp [terminalCoordinateSet, h, - UnitAddCircle.volume_frontier_terminalArc (ha0 i) (ha1 i)] - · simp [terminalCoordinateSet, h, - UnitAddCircle.volume_frontier_terminalArc_compl (ha0 i) (ha1 i)] + · subst i + simpa [terminalCoordinateSet] using + UnitAddCircle.volume_frontier_terminalArc (ha0 j) (ha1 j) + · simpa [terminalCoordinateSet, h] using + UnitAddCircle.volume_frontier_terminalArc_compl (ha0 i) (ha1 i) /-- The terminal box is a continuity set for Haar probability measure. -/ theorem volume_frontier_terminalBox [DecidableEq ι] @@ -102,8 +103,11 @@ theorem volume_terminalCoordinateSet [DecidableEq ι] volume (terminalCoordinateSet j a i) = ENNReal.ofReal (if i = j then a i else 1 - a i) := by by_cases h : i = j - · simp [terminalCoordinateSet, h, UnitAddCircle.volume_terminalArc (ha0 i) (ha1 i)] - · simp [terminalCoordinateSet, h, UnitAddCircle.volume_terminalArc_compl (ha0 i) (ha1 i)] + · subst i + simpa [terminalCoordinateSet] using + UnitAddCircle.volume_terminalArc (ha0 j) (ha1 j) + · simpa [terminalCoordinateSet, h] using + UnitAddCircle.volume_terminalArc_compl (ha0 i) (ha1 i) /-- Haar mass of the terminal box. -/ theorem volume_terminalBox [DecidableEq ι] @@ -123,7 +127,12 @@ theorem volume_terminalBox [DecidableEq ι] exact (Finset.mul_prod_erase Finset.univ (fun i => if i = j then a i else 1 - a i) (Finset.mem_univ j)).symm _ = a j * ∏ i ∈ Finset.univ.erase j, (1 - a i) := by - simp + simp only [if_pos rfl] + apply congrArg (fun x => a j * x) + apply Finset.prod_congr rfl + intro i hi + have hij : i ≠ j := (Finset.mem_erase.mp hi).1 + simp [hij] · intro i hi split_ifs · exact (ha0 i).le @@ -145,13 +154,14 @@ theorem hasDensity_terminalBox [DecidableEq ι] simpa [μ] using tendsto_average_rotation a hrel have hd := MeasureTheory.hasDensity_of_tendsto_average (Y := fun n => n • (fun i => (a i : UnitAddCircle))) μ havg - (measurableSet_terminalBox j a) (by simpa [μ] using volume_frontier_terminalBox j a ha0 ha1) + (measurableSet_terminalBox j a) (by + change (volume (frontier (terminalBox j a))).toNNReal = 0 + rw [volume_frontier_terminalBox j a ha0 ha1] + rfl) {n : ℕ | n • (fun i => (a i : UnitAddCircle)) ∈ terminalBox j a} (fun _ => Iff.rfl) convert hd using 1 - simp only [μ] - rw [show (((⟨volume, inferInstance⟩ : ProbabilityMeasure (UnitAddTorus ι)) - (terminalBox j a) : ℝ≥0) : ℝ) = - (volume (terminalBox j a)).toReal by simp] + change a j * ∏ i ∈ Finset.univ.erase j, (1 - a i) = + (volume (terminalBox j a)).toReal rw [volume_terminalBox j a ha0 ha1, ENNReal.toReal_ofReal] positivity From 0559a98f769be27585e09cf58ab6e1d06cd4412a Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:16:42 -0700 Subject: [PATCH 096/115] ci: repair A261865 base arithmetic and terminal-box nonnegativity --- .../workflows/a261865-one-shot-repair-9.yml | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 .github/workflows/a261865-one-shot-repair-9.yml diff --git a/.github/workflows/a261865-one-shot-repair-9.yml b/.github/workflows/a261865-one-shot-repair-9.yml new file mode 100644 index 0000000000..e9c5c87dc6 --- /dev/null +++ b/.github/workflows/a261865-one-shot-repair-9.yml @@ -0,0 +1,115 @@ +name: Repair A261865 base arithmetic and terminal-box nonnegativity + +on: + push: + branches: [a261865-research] + paths: + - '.github/workflows/a261865-one-shot-repair-9.yml' + +permissions: + contents: write + +jobs: + repair: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + with: + ref: a261865-research + fetch-depth: 0 + + - name: Apply exact Lean repairs + shell: bash + run: | + python3 - <<'PY' + from pathlib import Path + + def replace_once(path, old, new): + p = Path(path) + text = p.read_text() + n = text.count(old) + if n != 1: + raise SystemExit(f'{path}: expected one match, found {n}: {old!r}') + p.write_text(text.replace(old, new, 1)) + + base = 'FormalConjectures/OEIS/A261865Base.lean' + replace_once(base, + ' have hmcast : (m : ℝ) = (⌊x⌋ : ℝ) + 1 := by\n' + ' simp [m, Int.toNat_of_nonneg hfloor_nonneg]\n', + ' have hmcast : (m : ℝ) = (⌊x⌋ : ℝ) + 1 := by\n' + ' norm_num [m]\n' + ' exact_mod_cast Int.toNat_of_nonneg hfloor_nonneg\n') + + replace_once(base, + ' have hmn : m < n + 1 := by\n' + ' exact_mod_cast (by simpa [Nat.cast_add, Nat.cast_one] using hright)\n' + ' omega\n', + ' have hright\' : (m : ℝ) < (n : ℝ) + 1 := by simpa using hright\n' + ' have hmn : m ≤ n := by\n' + ' exact_mod_cast hright\'\n' + ' omega\n') + + replace_once(base, + ' refine ⟨m * c, Nat.mul_pos hm hc, ?_, ?_⟩\n' + ' · simpa only [hsqrt, Nat.cast_mul, mul_assoc] using hleft\n' + ' · simpa only [hsqrt, Nat.cast_mul, mul_assoc] using hright\n', + ' refine ⟨m * c, Nat.mul_pos hm hc, ?_, ?_⟩\n' + ' · calc\n' + ' (n : ℝ) < (m : ℝ) * ((c : ℝ) * Real.sqrt (s : ℝ)) := by\n' + ' rw [← hsqrt]\n' + ' exact hleft\n' + ' _ = ((m * c : ℕ) : ℝ) * Real.sqrt (s : ℝ) := by\n' + ' push_cast\n' + ' ring\n' + ' · calc\n' + ' ((m * c : ℕ) : ℝ) * Real.sqrt (s : ℝ) =\n' + ' (m : ℝ) * ((c : ℝ) * Real.sqrt (s : ℝ)) := by\n' + ' push_cast\n' + ' ring\n' + ' _ < (n : ℝ) + 1 := by\n' + ' rw [← hsqrt]\n' + ' exact hright\n') + + replace_once(base, + ' have hspos : 0 < s := by\n' + ' rw [hrs] at hr\n' + ' positivity\n' + ' have hslt : s < r := by\n' + ' rw [hrs]\n' + ' nlinarith [hdprime.two_le]\n', + ' have hspos : 0 < s := by\n' + ' apply Nat.pos_of_ne_zero\n' + ' intro hs0\n' + ' subst s\n' + ' simp at hr\n' + ' have hslt : s < r := by\n' + ' rw [hrs]\n' + ' have hdd : 1 < d * d := by nlinarith [hdprime.two_le]\n' + ' simpa using Nat.mul_lt_mul_of_pos_right hdd hspos\n') + + box = 'FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean' + replace_once(box, + ' rw [volume_terminalBox j a ha0 ha1, ENNReal.toReal_ofReal]\n' + ' positivity\n', + ' have hnonneg : 0 ≤ a j * ∏ i ∈ Finset.univ.erase j, (1 - a i) := by\n' + ' apply mul_nonneg (ha0 j).le\n' + ' apply Finset.prod_nonneg\n' + ' intro i hi\n' + ' exact sub_nonneg.mpr (ha1 i).le\n' + ' rw [volume_terminalBox j a ha0 ha1, ENNReal.toReal_ofReal hnonneg]\n') + + Path('.github/workflows/a261865-one-shot-repair-9.yml').unlink() + PY + + - name: Commit repairs + shell: bash + run: | + set -euo pipefail + git config user.name 'ProofOrchestrator' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add FormalConjectures/OEIS/A261865Base.lean \ + FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean \ + .github/workflows/a261865-one-shot-repair-9.yml + git commit -m 'Fix A261865 base casts and terminal-box nonnegativity' + git push origin HEAD:a261865-research From 7c3ef5817942a474b2b8a08cf1e4d27d53fd9cf5 Mon Sep 17 00:00:00 2001 From: ProofOrchestrator <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 23:16:51 +0000 Subject: [PATCH 097/115] Fix A261865 base casts and terminal-box nonnegativity --- .../workflows/a261865-one-shot-repair-9.yml | 115 ------------------ FormalConjectures/OEIS/A261865Base.lean | 34 ++++-- .../Equidistribution/TerminalBox.lean | 8 +- 3 files changed, 32 insertions(+), 125 deletions(-) delete mode 100644 .github/workflows/a261865-one-shot-repair-9.yml diff --git a/.github/workflows/a261865-one-shot-repair-9.yml b/.github/workflows/a261865-one-shot-repair-9.yml deleted file mode 100644 index e9c5c87dc6..0000000000 --- a/.github/workflows/a261865-one-shot-repair-9.yml +++ /dev/null @@ -1,115 +0,0 @@ -name: Repair A261865 base arithmetic and terminal-box nonnegativity - -on: - push: - branches: [a261865-research] - paths: - - '.github/workflows/a261865-one-shot-repair-9.yml' - -permissions: - contents: write - -jobs: - repair: - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: actions/checkout@v4 - with: - ref: a261865-research - fetch-depth: 0 - - - name: Apply exact Lean repairs - shell: bash - run: | - python3 - <<'PY' - from pathlib import Path - - def replace_once(path, old, new): - p = Path(path) - text = p.read_text() - n = text.count(old) - if n != 1: - raise SystemExit(f'{path}: expected one match, found {n}: {old!r}') - p.write_text(text.replace(old, new, 1)) - - base = 'FormalConjectures/OEIS/A261865Base.lean' - replace_once(base, - ' have hmcast : (m : ℝ) = (⌊x⌋ : ℝ) + 1 := by\n' - ' simp [m, Int.toNat_of_nonneg hfloor_nonneg]\n', - ' have hmcast : (m : ℝ) = (⌊x⌋ : ℝ) + 1 := by\n' - ' norm_num [m]\n' - ' exact_mod_cast Int.toNat_of_nonneg hfloor_nonneg\n') - - replace_once(base, - ' have hmn : m < n + 1 := by\n' - ' exact_mod_cast (by simpa [Nat.cast_add, Nat.cast_one] using hright)\n' - ' omega\n', - ' have hright\' : (m : ℝ) < (n : ℝ) + 1 := by simpa using hright\n' - ' have hmn : m ≤ n := by\n' - ' exact_mod_cast hright\'\n' - ' omega\n') - - replace_once(base, - ' refine ⟨m * c, Nat.mul_pos hm hc, ?_, ?_⟩\n' - ' · simpa only [hsqrt, Nat.cast_mul, mul_assoc] using hleft\n' - ' · simpa only [hsqrt, Nat.cast_mul, mul_assoc] using hright\n', - ' refine ⟨m * c, Nat.mul_pos hm hc, ?_, ?_⟩\n' - ' · calc\n' - ' (n : ℝ) < (m : ℝ) * ((c : ℝ) * Real.sqrt (s : ℝ)) := by\n' - ' rw [← hsqrt]\n' - ' exact hleft\n' - ' _ = ((m * c : ℕ) : ℝ) * Real.sqrt (s : ℝ) := by\n' - ' push_cast\n' - ' ring\n' - ' · calc\n' - ' ((m * c : ℕ) : ℝ) * Real.sqrt (s : ℝ) =\n' - ' (m : ℝ) * ((c : ℝ) * Real.sqrt (s : ℝ)) := by\n' - ' push_cast\n' - ' ring\n' - ' _ < (n : ℝ) + 1 := by\n' - ' rw [← hsqrt]\n' - ' exact hright\n') - - replace_once(base, - ' have hspos : 0 < s := by\n' - ' rw [hrs] at hr\n' - ' positivity\n' - ' have hslt : s < r := by\n' - ' rw [hrs]\n' - ' nlinarith [hdprime.two_le]\n', - ' have hspos : 0 < s := by\n' - ' apply Nat.pos_of_ne_zero\n' - ' intro hs0\n' - ' subst s\n' - ' simp at hr\n' - ' have hslt : s < r := by\n' - ' rw [hrs]\n' - ' have hdd : 1 < d * d := by nlinarith [hdprime.two_le]\n' - ' simpa using Nat.mul_lt_mul_of_pos_right hdd hspos\n') - - box = 'FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean' - replace_once(box, - ' rw [volume_terminalBox j a ha0 ha1, ENNReal.toReal_ofReal]\n' - ' positivity\n', - ' have hnonneg : 0 ≤ a j * ∏ i ∈ Finset.univ.erase j, (1 - a i) := by\n' - ' apply mul_nonneg (ha0 j).le\n' - ' apply Finset.prod_nonneg\n' - ' intro i hi\n' - ' exact sub_nonneg.mpr (ha1 i).le\n' - ' rw [volume_terminalBox j a ha0 ha1, ENNReal.toReal_ofReal hnonneg]\n') - - Path('.github/workflows/a261865-one-shot-repair-9.yml').unlink() - PY - - - name: Commit repairs - shell: bash - run: | - set -euo pipefail - git config user.name 'ProofOrchestrator' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add FormalConjectures/OEIS/A261865Base.lean \ - FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean \ - .github/workflows/a261865-one-shot-repair-9.yml - git commit -m 'Fix A261865 base casts and terminal-box nonnegativity' - git push origin HEAD:a261865-research diff --git a/FormalConjectures/OEIS/A261865Base.lean b/FormalConjectures/OEIS/A261865Base.lean index 23e4fa4469..9ebc660675 100644 --- a/FormalConjectures/OEIS/A261865Base.lean +++ b/FormalConjectures/OEIS/A261865Base.lean @@ -68,7 +68,8 @@ theorem exists_nat_between_iff_fract {x a : ℝ} (hx : 0 ≤ x) : have hfloor_nonneg : 0 ≤ ⌊x⌋ := Int.floor_nonneg.mpr hx let m : ℕ := ⌊x⌋.toNat + 1 have hmcast : (m : ℝ) = (⌊x⌋ : ℝ) + 1 := by - simp [m, Int.toNat_of_nonneg hfloor_nonneg] + norm_num [m] + exact_mod_cast Int.toNat_of_nonneg hfloor_nonneg refine ⟨m, by simp [m], ?_, ?_⟩ · rw [hmcast] exact Int.lt_floor_add_one x @@ -110,8 +111,9 @@ theorem not_hits_one (n : ℕ) : ¬ Hits 1 n := by rintro ⟨m, _hm, hleft, hright⟩ have hnm : n < m := by exact_mod_cast (by simpa using hleft) - have hmn : m < n + 1 := by - exact_mod_cast (by simpa [Nat.cast_add, Nat.cast_one] using hright) + have hright' : (m : ℝ) < (n : ℝ) + 1 := by simpa using hright + have hmn : m ≤ n := by + exact_mod_cast hright' omega /-- Removing a positive square factor from a radicand preserves the hitting property. -/ @@ -124,8 +126,21 @@ theorem hits_square_mul_imp (c s n : ℕ) (hc : 0 < c) : rw [Nat.cast_mul, Nat.cast_pow, Real.sqrt_mul (sq_nonneg (c : ℝ))] rw [Real.sqrt_sq (Nat.cast_nonneg c)] refine ⟨m * c, Nat.mul_pos hm hc, ?_, ?_⟩ - · simpa only [hsqrt, Nat.cast_mul, mul_assoc] using hleft - · simpa only [hsqrt, Nat.cast_mul, mul_assoc] using hright + · calc + (n : ℝ) < (m : ℝ) * ((c : ℝ) * Real.sqrt (s : ℝ)) := by + rw [← hsqrt] + exact hleft + _ = ((m * c : ℕ) : ℝ) * Real.sqrt (s : ℝ) := by + push_cast + ring + · calc + ((m * c : ℕ) : ℝ) * Real.sqrt (s : ℝ) = + (m : ℝ) * ((c : ℝ) * Real.sqrt (s : ℝ)) := by + push_cast + ring + _ < (n : ℝ) + 1 := by + rw [← hsqrt] + exact hright /-- Every hit descends to a hit by a positive squarefree radicand no larger than the original. -/ theorem exists_squarefree_hit_le (r n : ℕ) (hr : 0 < r) (hhit : Hits r n) : @@ -140,11 +155,14 @@ theorem exists_squarefree_hit_le (r n : ℕ) (hr : 0 < r) (hhit : Hits r n) : obtain ⟨s, hrs⟩ := Nat.minSqFac_dvd e have hdpos : 0 < d := hdprime.pos have hspos : 0 < s := by - rw [hrs] at hr - positivity + apply Nat.pos_of_ne_zero + intro hs0 + subst s + simp at hr have hslt : s < r := by rw [hrs] - nlinarith [hdprime.two_le] + have hdd : 1 < d * d := by nlinarith [hdprime.two_le] + simpa using Nat.mul_lt_mul_of_pos_right hdd hspos have hhit_s : Hits s n := by apply hits_square_mul_imp d s n hdpos simpa [pow_two, hrs] using hhit diff --git a/FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean b/FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean index b54838cce7..78fcfcc407 100644 --- a/FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean +++ b/FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean @@ -162,7 +162,11 @@ theorem hasDensity_terminalBox [DecidableEq ι] convert hd using 1 change a j * ∏ i ∈ Finset.univ.erase j, (1 - a i) = (volume (terminalBox j a)).toReal - rw [volume_terminalBox j a ha0 ha1, ENNReal.toReal_ofReal] - positivity + have hnonneg : 0 ≤ a j * ∏ i ∈ Finset.univ.erase j, (1 - a i) := by + apply mul_nonneg (ha0 j).le + apply Finset.prod_nonneg + intro i hi + exact sub_nonneg.mpr (ha1 i).le + rw [volume_terminalBox j a ha0 ha1, ENNReal.toReal_ofReal hnonneg] end UnitAddTorus \ No newline at end of file From 025f2c44ca1a67efcac8a150c9e9c1f66d4f50b5 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:21:07 -0700 Subject: [PATCH 098/115] ci: close final A261865 base arithmetic goals --- .../workflows/a261865-one-shot-repair-10.yml | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 .github/workflows/a261865-one-shot-repair-10.yml diff --git a/.github/workflows/a261865-one-shot-repair-10.yml b/.github/workflows/a261865-one-shot-repair-10.yml new file mode 100644 index 0000000000..e21522e41d --- /dev/null +++ b/.github/workflows/a261865-one-shot-repair-10.yml @@ -0,0 +1,73 @@ +name: Close final A261865 base arithmetic goals + +on: + push: + branches: [a261865-research] + paths: + - '.github/workflows/a261865-one-shot-repair-10.yml' + +permissions: + contents: write + +jobs: + repair: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + with: + ref: a261865-research + fetch-depth: 0 + + - name: Apply exact Lean repairs + shell: bash + run: | + python3 - <<'PY' + from pathlib import Path + path = Path('FormalConjectures/OEIS/A261865Base.lean') + text = path.read_text() + + old = ''' have hright' : (m : ℝ) < (n : ℝ) + 1 := by simpa using hright + have hmn : m ≤ n := by + exact_mod_cast hright' + omega +''' + new = ''' have hright' : (m : ℝ) < (n : ℝ) + 1 := by simpa using hright + have hmn : m < n + 1 := by + exact_mod_cast hright' + omega +''' + if text.count(old) != 1: + raise SystemExit(f'first replacement count={text.count(old)}') + text = text.replace(old, new, 1) + + old = ''' have hspos : 0 < s := by + apply Nat.pos_of_ne_zero + intro hs0 + subst s + simp at hr +''' + new = ''' have hspos : 0 < s := by + apply Nat.pos_of_ne_zero + intro hs0 + have hr0 : r = 0 := by simpa [hs0] using hrs + omega +''' + if text.count(old) != 1: + raise SystemExit(f'second replacement count={text.count(old)}') + text = text.replace(old, new, 1) + + path.write_text(text) + Path('.github/workflows/a261865-one-shot-repair-10.yml').unlink() + PY + + - name: Commit repair + shell: bash + run: | + set -euo pipefail + git config user.name 'ProofOrchestrator' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add FormalConjectures/OEIS/A261865Base.lean \ + .github/workflows/a261865-one-shot-repair-10.yml + git commit -m 'Close final A261865 base arithmetic goals' + git push origin HEAD:a261865-research From eaf4b28312d2401c90bf6b6ec2043d60536d61a6 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:25:23 -0700 Subject: [PATCH 099/115] ci: trigger corrected final A261865 repair --- .github/workflows/a261865-one-shot-repair-10.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/a261865-one-shot-repair-10.yml b/.github/workflows/a261865-one-shot-repair-10.yml index e21522e41d..bd11e69279 100644 --- a/.github/workflows/a261865-one-shot-repair-10.yml +++ b/.github/workflows/a261865-one-shot-repair-10.yml @@ -33,8 +33,11 @@ jobs: omega ''' new = ''' have hright' : (m : ℝ) < (n : ℝ) + 1 := by simpa using hright - have hmn : m < n + 1 := by - exact_mod_cast hright' + have hmn : m ≤ n := by + by_contra h + have hle : n + 1 ≤ m := by omega + have hle' : (n : ℝ) + 1 ≤ (m : ℝ) := by exact_mod_cast hle + linarith omega ''' if text.count(old) != 1: From 064330b7b1f532f3d37e7cfd317cee13e3dd3d4d Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:27:35 -0700 Subject: [PATCH 100/115] Close final A261865 base arithmetic goals --- FormalConjectures/OEIS/A261865Base.lean | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/FormalConjectures/OEIS/A261865Base.lean b/FormalConjectures/OEIS/A261865Base.lean index 9ebc660675..655153d177 100644 --- a/FormalConjectures/OEIS/A261865Base.lean +++ b/FormalConjectures/OEIS/A261865Base.lean @@ -113,7 +113,10 @@ theorem not_hits_one (n : ℕ) : ¬ Hits 1 n := by exact_mod_cast (by simpa using hleft) have hright' : (m : ℝ) < (n : ℝ) + 1 := by simpa using hright have hmn : m ≤ n := by - exact_mod_cast hright' + by_contra h + have hle : n + 1 ≤ m := by omega + have hle' : (n : ℝ) + 1 ≤ (m : ℝ) := by exact_mod_cast hle + linarith omega /-- Removing a positive square factor from a radicand preserves the hitting property. -/ @@ -157,8 +160,8 @@ theorem exists_squarefree_hit_le (r n : ℕ) (hr : 0 < r) (hhit : Hits r n) : have hspos : 0 < s := by apply Nat.pos_of_ne_zero intro hs0 - subst s - simp at hr + have hr0 : r = 0 := by simpa [hs0] using hrs + omega have hslt : s < r := by rw [hrs] have hdd : 1 < d * d := by nlinarith [hdprime.two_le] From 1470a19bbc61eee95c00f98b5b0d28d1c9473371 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:32:01 -0700 Subject: [PATCH 101/115] Fix A261865 solution subtype and event proofs --- FormalConjectures/OEIS/261865Solution.lean | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/FormalConjectures/OEIS/261865Solution.lean b/FormalConjectures/OEIS/261865Solution.lean index 11ca061d52..b85a6fa1a7 100644 --- a/FormalConjectures/OEIS/261865Solution.lean +++ b/FormalConjectures/OEIS/261865Solution.lean @@ -52,8 +52,8 @@ theorem orbit_mem_terminalBox_iff (n j : ℕ) (hj : 2 ≤ j) : classical have hge : ∀ s : relevantRadicands j, 2 ≤ s.1 := by intro s - rcases mem_relevantRadicands.mp s.2 with rfl | hs - · exact hj + rcases mem_relevantRadicands.mp s.2 with hsj | hs + · simpa [hsj] using hj · exact hs.1 have ha0 : ∀ s : relevantRadicands j, 0 < alpha s.1 := fun s => alpha_pos_of_two_le (hge s) @@ -67,15 +67,13 @@ theorem orbit_mem_terminalBox_iff (n j : ℕ) (hj : 2 ≤ j) : by_contra hn have hnzero : n = 0 := Nat.eq_zero_of_not_pos hn subst n - have hnonneg : - 0 ≤ 1 - alpha (distinguishedRadicand j).1 := - sub_nonneg.mpr (ha1 (distinguishedRadicand j)).le norm_num at hjhit - exact (not_lt_of_ge hnonneg) hjhit + linarith [ha1 (distinguishedRadicand j)] refine ⟨hnpos, (isValue_iff_coordinateConditions n j hj).2 ?_⟩ refine ⟨by simpa [distinguishedRadicand] using hjhit, ?_⟩ intro s hs hcoord - let sr : relevantRadicands j := ⟨s, by simp [hs]⟩ + let sr : relevantRadicands j := + ⟨s, mem_relevantRadicands.mpr (Or.inr (mem_squarefreeBelow.mp hs))⟩ have hne : sr ≠ distinguishedRadicand j := by intro h have : s = j := congrArg Subtype.val h @@ -114,7 +112,8 @@ theorem product_erase_distinguished (j : ℕ) : · intro a ha b hb hab exact Subtype.ext hab · intro s hs - let sr : relevantRadicands j := ⟨s, by simp [hs]⟩ + let sr : relevantRadicands j := + ⟨s, mem_relevantRadicands.mpr (Or.inr (mem_squarefreeBelow.mp hs))⟩ have hne : sr ≠ distinguishedRadicand j := by intro h have : s = j := congrArg Subtype.val h @@ -158,4 +157,4 @@ theorem density_formula_solution (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : rw [predictedDensity, product_erase_distinguished] rfl -end OeisA261865 \ No newline at end of file +end OeisA261865 From 441ced8a683f48e0b9603da11023e4b0958f9bec Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:35:36 -0700 Subject: [PATCH 102/115] Mark A261865 catalog theorem solved --- FormalConjectures/OEIS/261865.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FormalConjectures/OEIS/261865.lean b/FormalConjectures/OEIS/261865.lean index a35d65b58d..44c91f29b8 100644 --- a/FormalConjectures/OEIS/261865.lean +++ b/FormalConjectures/OEIS/261865.lean @@ -44,7 +44,7 @@ The mathematical proof and Lean development were produced by ProofOrchestrator, using OpenAI GPT-5.6 Thinking, under Dominic Dabish's supervision. -/ -@[category research open, AMS 11] +@[category research solved, AMS 11] theorem density_formula (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : {n : ℕ | 0 < n ∧ IsValue n j}.HasDensity (predictedDensity j) := density_formula_solution j hj hsq From d149fdf9673c3425177f542facafb63fe4833afd Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:39:47 -0700 Subject: [PATCH 103/115] Import Formal Conjectures metadata syntax for A261865 --- FormalConjectures/OEIS/261865.lean | 1 + 1 file changed, 1 insertion(+) diff --git a/FormalConjectures/OEIS/261865.lean b/FormalConjectures/OEIS/261865.lean index 44c91f29b8..bb18c69ed4 100644 --- a/FormalConjectures/OEIS/261865.lean +++ b/FormalConjectures/OEIS/261865.lean @@ -15,6 +15,7 @@ limitations under the License. -/ module +public import FormalConjecturesUtil public import FormalConjectures.OEIS.«261865Solution» @[expose] public section From b7b7bdab45ec45ce5326143b0773a6d64d90f30a Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:44:11 -0700 Subject: [PATCH 104/115] Use fork-compatible A261865 category metadata --- FormalConjectures/OEIS/261865.lean | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/FormalConjectures/OEIS/261865.lean b/FormalConjectures/OEIS/261865.lean index bb18c69ed4..8af8640517 100644 --- a/FormalConjectures/OEIS/261865.lean +++ b/FormalConjectures/OEIS/261865.lean @@ -15,7 +15,6 @@ limitations under the License. -/ module -public import FormalConjecturesUtil public import FormalConjectures.OEIS.«261865Solution» @[expose] public section @@ -45,7 +44,7 @@ The mathematical proof and Lean development were produced by ProofOrchestrator, using OpenAI GPT-5.6 Thinking, under Dominic Dabish's supervision. -/ -@[category research solved, AMS 11] +@[category research, AMS 11] theorem density_formula (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : {n : ℕ | 0 < n ∧ IsValue n j}.HasDensity (predictedDensity j) := density_formula_solution j hj hsq From ca4f6491406044c2c2c8eebdf07445b73bca4e91 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:44:56 -0700 Subject: [PATCH 105/115] Restore A261865 catalog attributes and solved status --- FormalConjectures/OEIS/261865.lean | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/FormalConjectures/OEIS/261865.lean b/FormalConjectures/OEIS/261865.lean index 8af8640517..bb18c69ed4 100644 --- a/FormalConjectures/OEIS/261865.lean +++ b/FormalConjectures/OEIS/261865.lean @@ -15,6 +15,7 @@ limitations under the License. -/ module +public import FormalConjecturesUtil public import FormalConjectures.OEIS.«261865Solution» @[expose] public section @@ -44,7 +45,7 @@ The mathematical proof and Lean development were produced by ProofOrchestrator, using OpenAI GPT-5.6 Thinking, under Dominic Dabish's supervision. -/ -@[category research, AMS 11] +@[category research solved, AMS 11] theorem density_formula (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : {n : ℕ | 0 < n ∧ IsValue n j}.HasDensity (predictedDensity j) := density_formula_solution j hj hsq From 9ebc04439c3c6564f1a02c7ac4b7f0ebbc9e4b43 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:48:28 -0700 Subject: [PATCH 106/115] Keep proof wrapper free of unavailable fork metadata --- FormalConjectures/OEIS/261865.lean | 2 -- 1 file changed, 2 deletions(-) diff --git a/FormalConjectures/OEIS/261865.lean b/FormalConjectures/OEIS/261865.lean index bb18c69ed4..eb67c8f581 100644 --- a/FormalConjectures/OEIS/261865.lean +++ b/FormalConjectures/OEIS/261865.lean @@ -15,7 +15,6 @@ limitations under the License. -/ module -public import FormalConjecturesUtil public import FormalConjectures.OEIS.«261865Solution» @[expose] public section @@ -45,7 +44,6 @@ The mathematical proof and Lean development were produced by ProofOrchestrator, using OpenAI GPT-5.6 Thinking, under Dominic Dabish's supervision. -/ -@[category research solved, AMS 11] theorem density_formula (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : {n : ℕ | 0 < n ∧ IsValue n j}.HasDensity (predictedDensity j) := density_formula_solution j hj hsq From a6b4035b0c4bc05f6475839615bacddc22024415 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:50:11 -0700 Subject: [PATCH 107/115] Add canonical solved metadata to A261865 theorem --- FormalConjectures/OEIS/261865.lean | 2 ++ 1 file changed, 2 insertions(+) diff --git a/FormalConjectures/OEIS/261865.lean b/FormalConjectures/OEIS/261865.lean index eb67c8f581..2ebf4ab5ac 100644 --- a/FormalConjectures/OEIS/261865.lean +++ b/FormalConjectures/OEIS/261865.lean @@ -15,6 +15,7 @@ limitations under the License. -/ module +public meta import FormalConjecturesUtil.Attributes.Basic public import FormalConjectures.OEIS.«261865Solution» @[expose] public section @@ -44,6 +45,7 @@ The mathematical proof and Lean development were produced by ProofOrchestrator, using OpenAI GPT-5.6 Thinking, under Dominic Dabish's supervision. -/ +@[category research solved, AMS 11] theorem density_formula (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : {n : ℕ | 0 < n ∧ IsValue n j}.HasDensity (predictedDensity j) := density_formula_solution j hj hsq From 3ba32ab66e0a299d544c1fd4a33d2099b565f01c Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:52:59 -0700 Subject: [PATCH 108/115] Move A261865 axiom prints outside module mode --- FormalConjectures/OEIS/261865FinalAudit.lean | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/FormalConjectures/OEIS/261865FinalAudit.lean b/FormalConjectures/OEIS/261865FinalAudit.lean index f0a7893436..6425a00ba6 100644 --- a/FormalConjectures/OEIS/261865FinalAudit.lean +++ b/FormalConjectures/OEIS/261865FinalAudit.lean @@ -13,11 +13,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -/ -module -public import FormalConjectures.OEIS.«261865» - -@[expose] public section +import FormalConjectures.OEIS.«261865» namespace OeisA261865 From 796f5e8919a844d78e8bb683d1974e118aa263ee Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 16:54:14 -0700 Subject: [PATCH 109/115] Separate A261865 proof module from catalog metadata --- FormalConjectures/OEIS/261865.lean | 2 -- 1 file changed, 2 deletions(-) diff --git a/FormalConjectures/OEIS/261865.lean b/FormalConjectures/OEIS/261865.lean index 2ebf4ab5ac..eb67c8f581 100644 --- a/FormalConjectures/OEIS/261865.lean +++ b/FormalConjectures/OEIS/261865.lean @@ -15,7 +15,6 @@ limitations under the License. -/ module -public meta import FormalConjecturesUtil.Attributes.Basic public import FormalConjectures.OEIS.«261865Solution» @[expose] public section @@ -45,7 +44,6 @@ The mathematical proof and Lean development were produced by ProofOrchestrator, using OpenAI GPT-5.6 Thinking, under Dominic Dabish's supervision. -/ -@[category research solved, AMS 11] theorem density_formula (j : ℕ) (hj : 2 ≤ j) (hsq : Squarefree j) : {n : ℕ | 0 < n ∧ IsValue n j}.HasDensity (predictedDensity j) := density_formula_solution j hj hsq From d205a65490be87b3ef8e038ac0176ebebfd5857e Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 17:08:25 -0700 Subject: [PATCH 110/115] Remove temporary A261865 audit trigger --- .github/a261865-foundation-repair.trigger | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .github/a261865-foundation-repair.trigger diff --git a/.github/a261865-foundation-repair.trigger b/.github/a261865-foundation-repair.trigger deleted file mode 100644 index 96f253351d..0000000000 --- a/.github/a261865-foundation-repair.trigger +++ /dev/null @@ -1 +0,0 @@ -repair-pass-1 From 4852f1ef8916afd652a3b474f8cbf978366985d9 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 17:08:40 -0700 Subject: [PATCH 111/115] Remove temporary A261865 AXLE workflow --- .github/workflows/a261865-axle-audit.yml | 66 ------------------------ 1 file changed, 66 deletions(-) delete mode 100644 .github/workflows/a261865-axle-audit.yml diff --git a/.github/workflows/a261865-axle-audit.yml b/.github/workflows/a261865-axle-audit.yml deleted file mode 100644 index be25a35849..0000000000 --- a/.github/workflows/a261865-axle-audit.yml +++ /dev/null @@ -1,66 +0,0 @@ -name: Temporary A261865 AXLE audit - -on: - pull_request: - branches: [main] - paths: - - 'FormalConjectures/OEIS/261865.lean' - - 'FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean' - - 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean' - - '.github/workflows/a261865-axle-audit.yml' - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: a261865-axle-${{ github.ref }} - cancel-in-progress: true - -jobs: - check-foundation: - name: Check A261865 foundations with AXLE - runs-on: ubuntu-slim - timeout-minutes: 15 - steps: - - uses: actions/checkout@v4 - - name: Check Lean 4.27 sources - shell: bash - run: | - python3 - <<'PY' - import json - import pathlib - import sys - import urllib.request - - files = [ - 'FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean', - 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean', - ] - failed = False - for filename in files: - source = pathlib.Path(filename).read_text() - payload = json.dumps({ - 'content': source, - 'environment': 'lean-4.27.0', - 'ignore_imports': False, - 'mathlib_options': False, - 'timeout_seconds': 480, - }).encode() - request = urllib.request.Request( - 'https://axle.axiommath.ai/api/v1/check', - data=payload, - headers={'Content-Type': 'application/json'}, - method='POST', - ) - with urllib.request.urlopen(request, timeout=540) as response: - result = json.load(response) - print(f'===== {filename} =====') - print(json.dumps(result, indent=2)) - errors = result.get('lean_messages', {}).get('errors', []) - tool_errors = result.get('tool_messages', {}).get('errors', []) - declarations = result.get('failed_declarations', []) - failed |= bool(errors or tool_errors or declarations or not result.get('okay', False)) - if failed: - sys.exit(1) - PY From f6fd9d91411b3531aa520c91771a47bf5a0d2703 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 17:08:46 -0700 Subject: [PATCH 112/115] Remove temporary A261865 final-audit workflow --- .github/workflows/a261865-final-audit.yml | 84 ----------------------- 1 file changed, 84 deletions(-) delete mode 100644 .github/workflows/a261865-final-audit.yml diff --git a/.github/workflows/a261865-final-audit.yml b/.github/workflows/a261865-final-audit.yml deleted file mode 100644 index bbd1ef533d..0000000000 --- a/.github/workflows/a261865-final-audit.yml +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright 2026 The Formal Conjectures Authors. -# Licensed under the Apache License, Version 2.0. - -name: A261865 final theorem audit - -on: - pull_request: - branches: - - main - paths: - - 'FormalConjectures/OEIS/A261865Base.lean' - - 'FormalConjectures/OEIS/261865.lean' - - 'FormalConjectures/OEIS/261865Solution.lean' - - 'FormalConjectures/OEIS/261865FinalAudit.lean' - - 'FormalConjecturesForMathlib/Analysis/Equidistribution/**' - - 'FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean' - - 'FormalConjecturesForMathlib/MeasureTheory/Probability/**' - - 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical*.lean' - - '.github/workflows/a261865-final-audit.yml' - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: a261865-final-${{ github.ref }} - cancel-in-progress: true - -jobs: - lean-final: - name: Lean 4.27 exact theorem and axiom audit - runs-on: ubuntu-latest - timeout-minutes: 45 - steps: - - name: Checkout project - uses: actions/checkout@v4 - - - name: Install pinned Lean toolchain - shell: bash - run: | - set -euo pipefail - curl -fsSL https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh \ - | sh -s -- -y --default-toolchain none - echo "$HOME/.elan/bin" >> "$GITHUB_PATH" - "$HOME/.elan/bin/elan" toolchain install leanprover/lean4:v4.27.0 - - - name: Fetch Mathlib cache - shell: bash - run: | - set -euo pipefail - lake exe cache get - - - name: Reject placeholders in the solution chain - shell: bash - run: | - set -euo pipefail - files=( - FormalConjectures/OEIS/A261865Base.lean - FormalConjectures/OEIS/261865.lean - FormalConjectures/OEIS/261865Solution.lean - FormalConjectures/OEIS/261865FinalAudit.lean - FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean - FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean - FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean - FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean - FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean - FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean - FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean - ) - if grep -nE '\b(sorry|admit)\b|native_decide|unsafe|^axiom\b' "${files[@]}"; then - echo 'Forbidden proof placeholder or trust escape found.' >&2 - exit 1 - fi - - - name: Compile exact final theorem - shell: bash - run: | - set -euo pipefail - output=$(lake env lean FormalConjectures/OEIS/261865FinalAudit.lean 2>&1) - printf '%s\n' "$output" - if grep -q 'sorryAx' <<<"$output"; then - echo 'The exact numbered theorem depends on sorryAx.' >&2 - exit 1 - fi \ No newline at end of file From ba5352b7ea1a35cfd2bbf5bf837126cb574ea56f Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 17:08:52 -0700 Subject: [PATCH 113/115] Remove temporary A261865 autofix workflow --- .../workflows/a261865-foundation-autofix.yml | 132 ------------------ 1 file changed, 132 deletions(-) delete mode 100644 .github/workflows/a261865-foundation-autofix.yml diff --git a/.github/workflows/a261865-foundation-autofix.yml b/.github/workflows/a261865-foundation-autofix.yml deleted file mode 100644 index 0d89fa0165..0000000000 --- a/.github/workflows/a261865-foundation-autofix.yml +++ /dev/null @@ -1,132 +0,0 @@ -# Copyright 2025 The Formal Conjectures Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -name: Apply A261865 foundation repairs - -on: - push: - branches: [a261865-research] - paths: - - '.github/workflows/a261865-foundation-autofix.yml' - -permissions: - contents: write - -jobs: - patch: - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: actions/checkout@v4 - with: - ref: a261865-research - fetch-depth: 0 - - name: Apply exact source replacements - shell: bash - run: | - set -euo pipefail - python3 - <<'PY' - from pathlib import Path - - def replace_exact(path: str, old: str, new: str) -> None: - p = Path(path) - text = p.read_text() - count = text.count(old) - if count != 1: - raise SystemExit(f"{path}: expected one match, found {count}: {old!r}") - p.write_text(text.replace(old, new)) - - squarefree = 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean' - replace_exact(squarefree, - ' rw [ha.ext_iff hb]\n', - ' rw [Nat.Squarefree.ext_iff ha hb]\n') - replace_exact(squarefree, - ''' have heq : minpoly ℚ x = X ^ 2 - C r := - Polynomial.eq_of_monic_of_dvd_of_natDegree_le (minpoly.monic hint) hmonic hdvd - (by rw [hdeg2, Polynomial.natDegree_X_pow_sub_C]) -''', - ''' have heq : minpoly ℚ x = X ^ 2 - C r := by - symm - exact Polynomial.eq_of_monic_of_dvd_of_natDegree_le - (p := minpoly ℚ x) (q := X ^ 2 - C r) - (minpoly.monic hint) hmonic hdvd - (by rw [hdeg2, Polynomial.natDegree_X_pow_sub_C]) -''') - replace_exact(squarefree, - ''' refine ⟨Polynomial.X ^ 2 - Polynomial.C (s i : ℚ), ?_, ?_⟩ - · exact Polynomial.monic_X_pow_sub_C _ two_ne_zero - · norm_num [← Polynomial.C_pow] - norm_cast - rw [Real.sq_sqrt (Nat.cast_nonneg _)] - ring -''', - ''' refine ⟨Polynomial.X ^ 2 - Polynomial.C (s i : ℚ), - Polynomial.monic_X_pow_sub_C _ two_ne_zero, ?_⟩ - norm_num [← Polynomial.C_pow] - norm_cast - rw [Real.sq_sqrt (Nat.cast_nonneg _)] - ring -''') - replace_exact(squarefree, - ''' apply Subtype.ext - simp only [root] - push_cast - rw [Real.sq_sqrt (Nat.cast_nonneg _)] - norm_cast -''', - ''' apply Subtype.ext - simp [root, Real.sq_sqrt (Nat.cast_nonneg _)] -''') - - torus = 'FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean' - replace_exact(torus, - ' linarith [htri, h1, h2, hN0\', hdist]\n', - ''' have hdist' : ‖F - p‖ < ε / 3 := by - simpa [norm_sub_rev] using hdist - linarith [htri, h1, h2, hN0', hdist'] -''') - replace_exact(torus, - ' | zero => simp [mFourier_zero]\n', - ' | zero => simp [mFourier, fourier_apply]\n') - replace_exact(torus, - ' obtain ⟨z, hz⟩ := AddCircle.coe_eq_zero_iff.mp hzero\'\n', - ' obtain ⟨z, hz⟩ := (AddCircle.coe_eq_zero_iff).mp hzero\'\n') - replace_exact(torus, - ''' simpa only [ContinuousMap.inner_toLp, mFourier_zero, ContinuousMap.one_apply, - map_one, one_mul, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h -''', - ''' simpa only [ContinuousMap.inner_toLp, mFourier_zero, ContinuousMap.one_apply, - map_one, one_mul, Pi.zero_apply, neg_zero, zero_add, eq_comm] using h.symm -''') - replace_exact(torus, - ' _ = 2 := by simp [norm_pow, hnorm]\n', - ''' _ = 2 := by - rw [norm_pow, hnorm] - norm_num -''') - replace_exact(torus, - ' simp [mFourier, fourier_apply, norm_prod, Circle.norm_coe]\n', - ' simp [mFourier, fourier_apply, norm_prod, Complex.norm_exp]\n') - PY - git rm .github/workflows/a261865-foundation-autofix.yml - - name: Commit repaired foundations - shell: bash - run: | - set -euo pipefail - git config user.name 'ProofOrchestrator' - git config user.email 'actions@users.noreply.github.com' - git add FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean \ - FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean - git commit -m 'Fix A261865 Lean foundation errors from AXLE' - git push origin HEAD:a261865-research From 8f1a1c1a0ccff64389706ebb5c48b114b8232655 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 17:09:02 -0700 Subject: [PATCH 114/115] Remove temporary A261865 macOS workflow --- .github/workflows/a261865-macos-audit.yml | 84 ----------------------- 1 file changed, 84 deletions(-) delete mode 100644 .github/workflows/a261865-macos-audit.yml diff --git a/.github/workflows/a261865-macos-audit.yml b/.github/workflows/a261865-macos-audit.yml deleted file mode 100644 index 6e6d12a839..0000000000 --- a/.github/workflows/a261865-macos-audit.yml +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright 2026 The Formal Conjectures Authors. -# Licensed under the Apache License, Version 2.0. - -name: A261865 macOS exact audit - -on: - pull_request: - branches: - - main - paths: - - 'FormalConjectures/OEIS/A261865Base.lean' - - 'FormalConjectures/OEIS/261865.lean' - - 'FormalConjectures/OEIS/261865Solution.lean' - - 'FormalConjectures/OEIS/261865FinalAudit.lean' - - 'FormalConjecturesForMathlib/Analysis/Equidistribution/**' - - 'FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean' - - 'FormalConjecturesForMathlib/MeasureTheory/Probability/**' - - 'FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical*.lean' - - '.github/workflows/a261865-macos-audit.yml' - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: a261865-macos-${{ github.ref }} - cancel-in-progress: true - -jobs: - lean-final-macos: - name: Lean 4.27 exact theorem and axiom audit (macOS) - runs-on: macos-15 - timeout-minutes: 45 - steps: - - name: Checkout project - uses: actions/checkout@v4 - - - name: Install pinned Lean toolchain - shell: bash - run: | - set -euo pipefail - curl -fsSL https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh \ - | sh -s -- -y --default-toolchain none - echo "$HOME/.elan/bin" >> "$GITHUB_PATH" - "$HOME/.elan/bin/elan" toolchain install leanprover/lean4:v4.27.0 - - - name: Fetch Mathlib cache - shell: bash - run: | - set -euo pipefail - lake exe cache get - - - name: Reject placeholders in the solution chain - shell: bash - run: | - set -euo pipefail - files=( - FormalConjectures/OEIS/A261865Base.lean - FormalConjectures/OEIS/261865.lean - FormalConjectures/OEIS/261865Solution.lean - FormalConjectures/OEIS/261865FinalAudit.lean - FormalConjecturesForMathlib/Analysis/Equidistribution/TerminalBox.lean - FormalConjecturesForMathlib/Analysis/Equidistribution/UnitAddTorus.lean - FormalConjecturesForMathlib/MeasureTheory/Group/UnitAddCircleArc.lean - FormalConjecturesForMathlib/MeasureTheory/Probability/Empirical.lean - FormalConjecturesForMathlib/MeasureTheory/Probability/PiContinuitySet.lean - FormalConjecturesForMathlib/NumberTheory/SquarefreeRadical.lean - FormalConjecturesForMathlib/NumberTheory/SquarefreeRadicals.lean - ) - if grep -nE '\b(sorry|admit)\b|native_decide|unsafe|^axiom\b' "${files[@]}"; then - echo 'Forbidden proof placeholder or trust escape found.' >&2 - exit 1 - fi - - - name: Compile exact final theorem - shell: bash - run: | - set -euo pipefail - output=$(lake env lean FormalConjectures/OEIS/261865FinalAudit.lean 2>&1) - printf '%s\n' "$output" - if grep -q 'sorryAx' <<<"$output"; then - echo 'The exact numbered theorem depends on sorryAx.' >&2 - exit 1 - fi From 813d75b09c115961cd7e37028e983c2c8b7f8dc8 Mon Sep 17 00:00:00 2001 From: DomTheDeveloper Date: Wed, 22 Jul 2026 17:09:08 -0700 Subject: [PATCH 115/115] Remove temporary A261865 repair workflow --- .../workflows/a261865-one-shot-repair-10.yml | 76 ------------------- 1 file changed, 76 deletions(-) delete mode 100644 .github/workflows/a261865-one-shot-repair-10.yml diff --git a/.github/workflows/a261865-one-shot-repair-10.yml b/.github/workflows/a261865-one-shot-repair-10.yml deleted file mode 100644 index bd11e69279..0000000000 --- a/.github/workflows/a261865-one-shot-repair-10.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: Close final A261865 base arithmetic goals - -on: - push: - branches: [a261865-research] - paths: - - '.github/workflows/a261865-one-shot-repair-10.yml' - -permissions: - contents: write - -jobs: - repair: - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: actions/checkout@v4 - with: - ref: a261865-research - fetch-depth: 0 - - - name: Apply exact Lean repairs - shell: bash - run: | - python3 - <<'PY' - from pathlib import Path - path = Path('FormalConjectures/OEIS/A261865Base.lean') - text = path.read_text() - - old = ''' have hright' : (m : ℝ) < (n : ℝ) + 1 := by simpa using hright - have hmn : m ≤ n := by - exact_mod_cast hright' - omega -''' - new = ''' have hright' : (m : ℝ) < (n : ℝ) + 1 := by simpa using hright - have hmn : m ≤ n := by - by_contra h - have hle : n + 1 ≤ m := by omega - have hle' : (n : ℝ) + 1 ≤ (m : ℝ) := by exact_mod_cast hle - linarith - omega -''' - if text.count(old) != 1: - raise SystemExit(f'first replacement count={text.count(old)}') - text = text.replace(old, new, 1) - - old = ''' have hspos : 0 < s := by - apply Nat.pos_of_ne_zero - intro hs0 - subst s - simp at hr -''' - new = ''' have hspos : 0 < s := by - apply Nat.pos_of_ne_zero - intro hs0 - have hr0 : r = 0 := by simpa [hs0] using hrs - omega -''' - if text.count(old) != 1: - raise SystemExit(f'second replacement count={text.count(old)}') - text = text.replace(old, new, 1) - - path.write_text(text) - Path('.github/workflows/a261865-one-shot-repair-10.yml').unlink() - PY - - - name: Commit repair - shell: bash - run: | - set -euo pipefail - git config user.name 'ProofOrchestrator' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add FormalConjectures/OEIS/A261865Base.lean \ - .github/workflows/a261865-one-shot-repair-10.yml - git commit -m 'Close final A261865 base arithmetic goals' - git push origin HEAD:a261865-research