mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
This squashes all local history (768 commits) onto the scrubbed PR #90 baseline. Individual commits were lost during filter-repo corruption; the working tree content is preserved intact. Build: N/A (working tree state only)
3143 lines
145 KiB
Text
3143 lines
145 KiB
Text
import Mathlib.Data.Set.Basic
|
||
import Mathlib.Data.Finset.Basic
|
||
import Mathlib.Data.Finset.Sort
|
||
import Mathlib.Analysis.SpecialFunctions.Pow.Real
|
||
import Mathlib.Algebra.Order.Chebyshev
|
||
import Mathlib.Tactic.Zify
|
||
import Mathlib.FieldTheory.Finite.GaloisField
|
||
import Mathlib.FieldTheory.Finite.Trace
|
||
import Mathlib.FieldTheory.Finite.Basic
|
||
import Mathlib.FieldTheory.Minpoly.Field
|
||
import Mathlib.FieldTheory.IntermediateField.Basic
|
||
import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic
|
||
import Mathlib.RingTheory.Trace.Basic
|
||
import Mathlib.RingTheory.PowerBasis
|
||
import Mathlib.LinearAlgebra.FiniteDimensional.Lemmas
|
||
import Mathlib.LinearAlgebra.Dimension.RankNullity
|
||
import Mathlib.LinearAlgebra.LinearIndependent.Defs
|
||
import Mathlib.LinearAlgebra.LinearIndependent.Lemmas
|
||
import Mathlib.LinearAlgebra.Span.Basic
|
||
import Mathlib.GroupTheory.SpecificGroups.Cyclic
|
||
import Mathlib.GroupTheory.QuotientGroup.Basic
|
||
import Mathlib.GroupTheory.Index
|
||
import Mathlib.GroupTheory.OrderOfElement
|
||
import Mathlib.Tactic.LinearCombination
|
||
import Mathlib.Tactic.FieldSimp
|
||
import Mathlib.NumberTheory.Bertrand
|
||
import Semantics.SidonSet
|
||
|
||
/-!
|
||
# Sidon Sets — Singer Construction Infrastructure
|
||
|
||
Port of the reusable Sidon-set infrastructure from Hulak–Ramos–de Queiroz (2026),
|
||
"Formalizing Singer Sidon Constructions and Sidon Set Infrastructure in Lean 4"
|
||
(arXiv: 2605.03274).
|
||
|
||
Original Lean 4 source: https://github.com/d0d1/singer-theorem-lean
|
||
Commit: 0c890589afc58e8955a5d7c3a609daff6447da31
|
||
License: GPL-3.0-only
|
||
|
||
This module ports the key reusable definitions and theorem statements from the
|
||
Erdos30 development into the Semantics namespace. The heavy algebraic proofs
|
||
(Singer construction, Lindström inequality, unconditional bounds) are left as
|
||
`sorry` with `TODO(lean-port)` markers, since the original code targets
|
||
Mathlib v4.29.0 while this project uses v4.30.0-rc2.
|
||
|
||
## Reusable components ported
|
||
|
||
1. **IsSidon** — Finset ℤ Sidon predicate (compatible with paper's Erdos30.Sidon)
|
||
2. **IsSidonMod** — Modular Sidon predicate
|
||
3. **IsIntervalSidon** — Interval Sidon predicate with containment
|
||
4. **IsSidonMaximum / sidonMaximum** — Extremal function h(N)
|
||
5. **Singer construction** — sidon set mod p²+p+1 of size p+1
|
||
6. **Lindström's cross-difference inequality** — (m-k)·k ≤ N-1
|
||
7. **h(N) = Θ(√N) bounds** — unconditional two-sided bounds
|
||
8. **Erdos30Statement** — formal Erdős Problem 30
|
||
|
||
## Relationship to existing Semantics.SidonSet
|
||
|
||
The existing `Semantics.SidonSet` uses a greedy `List Nat` generator with a
|
||
computable `isSidon : List Nat → Prop` check. This module provides the
|
||
mathematically rigorous `Finset ℤ` version used in the paper's proofs.
|
||
Both coexist: the List Nat version for computation, the Finset ℤ version
|
||
for formal combinatorics.
|
||
|
||
## References
|
||
|
||
- Singer, J. (1938). A theorem in finite projective geometry and some applications.
|
||
*Trans. Amer. Math. Soc.*, 43, 377–385.
|
||
- Lindström, B. (1969). An inequality for B₂-sequences.
|
||
*J. Combin. Theory*, 6(2), 211–212.
|
||
- Erdős, P. (1976). Problems and results in combinatorial number theory.
|
||
*Astérisque*, 24–25, 295–310. (Problem 30)
|
||
-/
|
||
|
||
namespace Semantics.SidonSets
|
||
|
||
open Finset
|
||
|
||
/-! ## Core Sidon Definitions (Finset ℤ) -/
|
||
|
||
/-- The Sidon property for a finite set of integers: all pairwise sums a + b
|
||
(with a, b ∈ A) are distinct up to reordering. This is the standard
|
||
combinatorial definition used in the Erdős Problem 30 literature. -/
|
||
def IsSidon (A : Finset ℤ) : Prop :=
|
||
∀ ⦃a b c d : ℤ⦄,
|
||
a ∈ A → b ∈ A → c ∈ A → d ∈ A →
|
||
a + b = c + d →
|
||
(a = c ∧ b = d) ∨ (a = d ∧ b = c)
|
||
|
||
/-- The Sidon property for a list of natural numbers (computable version).
|
||
Compatible with `Semantics.SidonSet.isSidon`. -/
|
||
def IsSidonNat (s : List Nat) : Prop :=
|
||
Semantics.SidonSet.isSidon s
|
||
|
||
/-! ## Modular Sidon Sets -/
|
||
|
||
/-- `IsSidonMod M A` means A is Sidon modulo M: for any a, b, c, d ∈ A,
|
||
M ∣ ((a + b) - (c + d)) implies {a, b} = {c, d} as unordered pairs.
|
||
This is the form needed for Singer's construction, which produces
|
||
Sidon sets in Z/(q²+q+1)Z. -/
|
||
def IsSidonMod (M : ℤ) (A : Finset ℤ) : Prop :=
|
||
∀ ⦃a b c d : ℤ⦄,
|
||
a ∈ A → b ∈ A → c ∈ A → d ∈ A →
|
||
(M ∣ ((a + b) - (c + d))) →
|
||
(a = c ∧ b = d) ∨ (a = d ∧ b = c)
|
||
|
||
/-- Modular Sidon implies integer Sidon. -/
|
||
theorem IsSidonMod.toIsSidon {M : ℤ} {A : Finset ℤ} (h : IsSidonMod M A) :
|
||
IsSidon A := by
|
||
intro a b c d ha hb hc hd hsum
|
||
exact h ha hb hc hd (by rw [hsum, sub_self]; exact dvd_zero M)
|
||
|
||
/-! ## Interval Sidon Sets -/
|
||
|
||
/-- The interval {1, ..., N} as a Finset ℤ. Empty when N < 1. -/
|
||
noncomputable def interval (N : ℤ) : Finset ℤ := Finset.Icc 1 N
|
||
|
||
/-- A Sidon subset of {1, ..., N}. -/
|
||
structure IsIntervalSidon (N : ℤ) (A : Finset ℤ) : Prop where
|
||
subset : ∀ x ∈ A, 1 ≤ x ∧ x ≤ N
|
||
sidon : IsSidon A
|
||
|
||
/-- Enlarging the ambient interval preserves IsIntervalSidon. -/
|
||
theorem IsIntervalSidon.mono {A : Finset ℤ} {N M : ℤ}
|
||
(h : IsIntervalSidon N A) (hle : N ≤ M) : IsIntervalSidon M A where
|
||
subset x hx := ⟨(h.subset x hx).1, le_trans (h.subset x hx).2 hle⟩
|
||
sidon := h.sidon
|
||
|
||
/-! ## Translation -/
|
||
|
||
/-- Translate a finset by t. -/
|
||
def translate (A : Finset ℤ) (t : ℤ) : Finset ℤ :=
|
||
A.map (⟨fun x => x + t, fun _ _ h => add_right_cancel h⟩ : ℤ ↪ ℤ)
|
||
|
||
@[simp] theorem card_translate (A : Finset ℤ) (t : ℤ) :
|
||
(translate A t).card = A.card := by
|
||
simp [translate]
|
||
|
||
/-- Translation preserves the Sidon property. -/
|
||
theorem IsSidon.translate {A : Finset ℤ} (hA : IsSidon A) (t : ℤ) :
|
||
IsSidon (translate A t) := by
|
||
intro a b c d ha hb hc hd hsum
|
||
rcases Finset.mem_map.1 ha with ⟨a', ha', ha_eq⟩
|
||
rcases Finset.mem_map.1 hb with ⟨b', hb', hb_eq⟩
|
||
rcases Finset.mem_map.1 hc with ⟨c', hc', hc_eq⟩
|
||
rcases Finset.mem_map.1 hd with ⟨d', hd', hd_eq⟩
|
||
have ha_val : a' + t = a := by simpa using ha_eq
|
||
have hb_val : b' + t = b := by simpa using hb_eq
|
||
have hc_val : c' + t = c := by simpa using hc_eq
|
||
have hd_val : d' + t = d := by simpa using hd_eq
|
||
have hsum' : a' + b' = c' + d' := by
|
||
calc
|
||
a' + b' = (a' + t) + (b' + t) - (t + t) := by ring
|
||
_ = a + b - (t + t) := by simp [ha_val, hb_val]
|
||
_ = c + d - (t + t) := by rw [hsum]
|
||
_ = (c' + t) + (d' + t) - (t + t) := by simp [hc_val, hd_val]
|
||
_ = c' + d' := by ring
|
||
rcases hA ha' hb' hc' hd' hsum' with (⟨hac, hbd⟩ | ⟨had, hbc⟩)
|
||
· left
|
||
constructor
|
||
· calc
|
||
a = a' + t := ha_val.symm
|
||
_ = c' + t := by rw [hac]
|
||
_ = c := hc_val
|
||
· calc
|
||
b = b' + t := hb_val.symm
|
||
_ = d' + t := by rw [hbd]
|
||
_ = d := hd_val
|
||
· right
|
||
constructor
|
||
· calc
|
||
a = a' + t := ha_val.symm
|
||
_ = d' + t := by rw [had]
|
||
_ = d := hd_val
|
||
· calc
|
||
b = b' + t := hb_val.symm
|
||
_ = c' + t := by rw [hbc]
|
||
_ = c := hc_val
|
||
|
||
/-! ## Extremal Function h(N) -/
|
||
|
||
/-- `IsSidonMaximum N h` states that h is the maximum cardinality of an
|
||
interval Sidon subset of {1, ..., N}. -/
|
||
def IsSidonMaximum (N h : ℕ) : Prop :=
|
||
(∃ A : Finset ℤ, IsIntervalSidon (N : ℤ) A ∧ A.card = h) ∧
|
||
∀ {A : Finset ℤ}, IsIntervalSidon (N : ℤ) A → A.card ≤ h
|
||
|
||
/-- Helper: the maximum Sidon cardinality exists for every N. -/
|
||
private theorem sidonMaximum_exists (N : ℕ) : ∃ h, IsSidonMaximum N h := by
|
||
let Z := Finset.Icc 1 (N : ℤ)
|
||
let cards : Set ℕ := {k | ∃ (A : Finset ℤ), A ⊆ Z ∧ IsSidon A ∧ A.card = k}
|
||
have h_nonempty : cards.Nonempty := by
|
||
refine ⟨0, ∅, Finset.empty_subset Z, ?_, Finset.card_empty⟩
|
||
intro a b c d ha hb hc hd hsum
|
||
simp at ha
|
||
have h_fin : Set.Finite cards := by
|
||
have h_fin_img : Set.Finite ((Z.powerset.image Finset.card : Finset ℕ) : Set ℕ) :=
|
||
Finset.finite_toSet _
|
||
apply Set.Finite.subset h_fin_img
|
||
intro k hk
|
||
rcases hk with ⟨A, hA_sub, hA_sidon, hcard⟩
|
||
refine Finset.mem_image.mpr ⟨A, ?_, hcard⟩
|
||
exact Finset.mem_powerset.mpr hA_sub
|
||
have h_finset_nonempty : h_fin.toFinset.Nonempty := by
|
||
rcases h_nonempty with ⟨k, hk⟩
|
||
refine ⟨k, h_fin.mem_toFinset.mpr hk⟩
|
||
let m := h_fin.toFinset.max' h_finset_nonempty
|
||
have hm_cards : m ∈ cards :=
|
||
h_fin.mem_toFinset.mp (Finset.max'_mem _ h_finset_nonempty)
|
||
rcases hm_cards with ⟨A, hA_sub, hA_sidon, hcard⟩
|
||
refine ⟨m, ?_⟩
|
||
constructor
|
||
· refine ⟨A, ?_, hcard⟩
|
||
refine { subset := λ x hx => ?_, sidon := hA_sidon }
|
||
have hx_mem_icc : x ∈ Z := hA_sub hx
|
||
rcases Finset.mem_Icc.1 hx_mem_icc with ⟨hx1, hx2⟩
|
||
exact ⟨hx1, hx2⟩
|
||
· intro B hB
|
||
have hB_sub : B ⊆ Z := by
|
||
intro x hx; rcases hB.subset x hx with ⟨hx1, hx2⟩
|
||
exact Finset.mem_Icc.mpr ⟨hx1, hx2⟩
|
||
have hB_card : B.card ∈ cards := ⟨B, hB_sub, hB.sidon, rfl⟩
|
||
have hB_fin : B.card ∈ h_fin.toFinset := h_fin.mem_toFinset.mpr hB_card
|
||
exact Finset.le_max' h_fin.toFinset (B.card) hB_fin
|
||
|
||
/-- The extremal Sidon function h(N) = max{|A| : A ⊆ {1,...,N} is Sidon}. -/
|
||
noncomputable def sidonMaximum (N : ℕ) : ℕ :=
|
||
Classical.choose (sidonMaximum_exists N)
|
||
|
||
/-- The maximum exists for every N. -/
|
||
theorem sidonMaximum_isSidonMaximum (N : ℕ) :
|
||
IsSidonMaximum N (sidonMaximum N) :=
|
||
Classical.choose_spec (sidonMaximum_exists N)
|
||
|
||
/-- The maximum cardinality is unique. -/
|
||
theorem isSidonMaximum_unique {N h k : ℕ}
|
||
(hh : IsSidonMaximum N h) (hk : IsSidonMaximum N k) :
|
||
h = k := by
|
||
rcases hh.1 with ⟨A, hA, hAcard⟩
|
||
rcases hk.1 with ⟨B, hB, hBcard⟩
|
||
have hle : h ≤ k := by rw [← hAcard]; exact hk.2 hA
|
||
have hge : k ≤ h := by rw [← hBcard]; exact hh.2 hB
|
||
omega
|
||
|
||
/-! ## Difference-Counting Upper Bound -/
|
||
|
||
/-- First upper bound: for any interval Sidon set A ⊆ {1,...,N},
|
||
|A| ≤ √(2N) + 1. This follows from pair-difference counting. -/
|
||
theorem IsIntervalSidon.card_le {A : Finset ℤ} {N : ℕ}
|
||
(h : IsIntervalSidon (N : ℤ) A) (hN : 1 ≤ N) :
|
||
A.card ≤ Nat.sqrt (2 * N) + 1 := by
|
||
set m := A.card with hm
|
||
have hA_sidon : IsSidon A := h.sidon
|
||
have hbound : ∀ x ∈ A, 1 ≤ x ∧ x ≤ N := h.subset
|
||
-- All positive differences a-b (a,b ∈ A, a > b) are distinct by the Sidon property
|
||
have h_diff_unique : ∀ a b c d : ℤ, a ∈ A → b ∈ A → c ∈ A → d ∈ A → a > b → c > d →
|
||
a - b = c - d → a = c ∧ b = d := by
|
||
intro a b c d ha hb hc hd ha_gt hc_gt h_eq
|
||
have hsum : a + d = b + c := by omega
|
||
rcases hA_sidon ha hd hb hc hsum with (⟨h1, h2⟩ | ⟨h1, h2⟩)
|
||
· omega
|
||
· exact ⟨h1, h2.symm⟩
|
||
-- P = ordered pairs (a,b) ∈ A×A with a > b
|
||
let P := (A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 > ab.2)
|
||
have hP_injOn : Set.InjOn (λ (ab : ℤ × ℤ) => ab.1 - ab.2) (P : Set (ℤ × ℤ)) := by
|
||
intro x hx y hy h
|
||
rcases x with ⟨a,b⟩; rcases y with ⟨c,d⟩
|
||
have haA : a ∈ A := (Finset.mem_product.1 ((Finset.mem_filter.1 hx).1)).1
|
||
have hbA : b ∈ A := (Finset.mem_product.1 ((Finset.mem_filter.1 hx).1)).2
|
||
have hcA : c ∈ A := (Finset.mem_product.1 ((Finset.mem_filter.1 hy).1)).1
|
||
have hdA : d ∈ A := (Finset.mem_product.1 ((Finset.mem_filter.1 hy).1)).2
|
||
have ha_gt_b : a > b := (Finset.mem_filter.1 hx).2
|
||
have hc_gt_d : c > d := (Finset.mem_filter.1 hy).2
|
||
rcases h_diff_unique a b c d haA hbA hcA hdA ha_gt_b hc_gt_d h with ⟨hac, hbd⟩
|
||
ext <;> assumption
|
||
have hP_card_diffs : (Finset.image (λ (ab : ℤ × ℤ) => ab.1 - ab.2) P).card = P.card :=
|
||
Finset.card_image_of_injOn hP_injOn
|
||
have hP_card : P.card = m * (m - 1) / 2 := by
|
||
have h_total : (A.product A).card = m * m := by simp [hm, Finset.card_product]
|
||
have h_swap_card : (Finset.image Prod.swap P).card = P.card :=
|
||
Finset.card_image_of_injective _ Prod.swap_injective
|
||
have h_swap_eq : Finset.image Prod.swap P = ((A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 < ab.2)) := by
|
||
ext ⟨a, b⟩
|
||
constructor
|
||
· intro hmem
|
||
rcases Finset.mem_image.1 hmem with ⟨⟨x, y⟩, hxy, hswap⟩
|
||
rcases Finset.mem_filter.1 hxy with ⟨hprod, hgt⟩
|
||
rcases Finset.mem_product.1 hprod with ⟨hx, hy⟩
|
||
have h1 : y = a := congrArg Prod.fst hswap
|
||
have h2 : x = b := congrArg Prod.snd hswap
|
||
subst h1; subst h2
|
||
exact Finset.mem_filter.2 ⟨Finset.mem_product.2 ⟨hy, hx⟩, hgt⟩
|
||
· intro hmem
|
||
rcases Finset.mem_filter.1 hmem with ⟨hprod, hlt⟩
|
||
rcases Finset.mem_product.1 hprod with ⟨ha, hb⟩
|
||
exact Finset.mem_image.2 ⟨(b, a),
|
||
Finset.mem_filter.2 ⟨Finset.mem_product.2 ⟨hb, ha⟩, hlt⟩, rfl⟩
|
||
have h_diag_card : ((A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 = ab.2)).card = m := by
|
||
have himg : ((A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 = ab.2)) =
|
||
A.image (λ (x : ℤ) => (x, x)) := by
|
||
ext ⟨a, b⟩
|
||
constructor
|
||
· intro hmem
|
||
rcases Finset.mem_filter.1 hmem with ⟨hprod, heq⟩
|
||
have ha : a ∈ A := (Finset.mem_product.1 hprod).1
|
||
have heq' : a = b := heq
|
||
subst heq'
|
||
exact Finset.mem_image.2 ⟨a, ha, rfl⟩
|
||
· intro hmem
|
||
rcases Finset.mem_image.1 hmem with ⟨x, hx, hxy⟩
|
||
have h1 : x = a := congrArg Prod.fst hxy
|
||
have h2 : x = b := congrArg Prod.snd hxy
|
||
subst h1; subst h2
|
||
exact Finset.mem_filter.2 ⟨Finset.mem_product.2 ⟨hx, hx⟩, rfl⟩
|
||
rw [himg, Finset.card_image_of_injective _ (fun x y hxy => congrArg Prod.fst hxy)]
|
||
-- Partition product into >, <, =
|
||
have h_partition : (A.product A) = P ∪ ((A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 < ab.2)) ∪
|
||
((A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 = ab.2)) := by
|
||
ext ⟨a, b⟩
|
||
constructor
|
||
· intro hmem
|
||
rcases lt_trichotomy a b with hlt | heq | hgt
|
||
· exact Finset.mem_union.2 (Or.inl (Finset.mem_union.2 (Or.inr
|
||
(Finset.mem_filter.2 ⟨hmem, hlt⟩))))
|
||
· exact Finset.mem_union.2 (Or.inr (Finset.mem_filter.2 ⟨hmem, heq⟩))
|
||
· exact Finset.mem_union.2 (Or.inl (Finset.mem_union.2 (Or.inl
|
||
(Finset.mem_filter.2 ⟨hmem, hgt⟩))))
|
||
· intro hmem
|
||
rcases Finset.mem_union.1 hmem with h | h
|
||
· rcases Finset.mem_union.1 h with h' | h'
|
||
· exact (Finset.mem_filter.1 h').1
|
||
· exact (Finset.mem_filter.1 h').1
|
||
· exact (Finset.mem_filter.1 h).1
|
||
have h_disjoint_gt_lt : Disjoint P ((A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 < ab.2)) := by
|
||
rw [Finset.disjoint_left]
|
||
rintro ⟨a, b⟩ hP hlt
|
||
have h1 : a > b := (Finset.mem_filter.1 hP).2
|
||
have h2 : a < b := (Finset.mem_filter.1 hlt).2
|
||
omega
|
||
have h_disjoint_union_eq : Disjoint (P ∪ ((A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 < ab.2)))
|
||
((A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 = ab.2)) := by
|
||
rw [Finset.disjoint_left]
|
||
rintro ⟨a, b⟩ hmem heq
|
||
have h2 : a = b := (Finset.mem_filter.1 heq).2
|
||
rcases Finset.mem_union.1 hmem with h | h
|
||
· have h1 : a > b := (Finset.mem_filter.1 h).2
|
||
omega
|
||
· have h1 : a < b := (Finset.mem_filter.1 h).2
|
||
omega
|
||
-- Count: |P| + |<| + |=| = m*m, and |P| = |<|
|
||
have h_lt_card : ((A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 < ab.2)).card = P.card := by
|
||
calc
|
||
((A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 < ab.2)).card =
|
||
(Finset.image Prod.swap P).card := by rw [h_swap_eq]
|
||
_ = P.card := h_swap_card
|
||
have h_total_card : P.card + ((A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 < ab.2)).card +
|
||
((A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 = ab.2)).card = m * m := by
|
||
calc
|
||
P.card + ((A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 < ab.2)).card +
|
||
((A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 = ab.2)).card =
|
||
(P ∪ ((A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 < ab.2)) ∪
|
||
((A.product A).filter (λ (ab : ℤ × ℤ) => ab.1 = ab.2))).card := by
|
||
rw [Finset.card_union_of_disjoint h_disjoint_union_eq,
|
||
Finset.card_union_of_disjoint h_disjoint_gt_lt]
|
||
_ = (A.product A).card := by conv_lhs => rw [← h_partition]
|
||
_ = m * m := h_total
|
||
rw [h_lt_card, h_diag_card] at h_total_card
|
||
have hmm : m * (m - 1) + m = m * m := by
|
||
rcases Nat.eq_zero_or_pos m with hm0 | hm0
|
||
· simp [hm0]
|
||
· calc m * (m - 1) + m = m * (m - 1 + 1) := by ring
|
||
_ = m * m := by rw [Nat.sub_add_cancel hm0]
|
||
omega
|
||
have hD_bound : Finset.image (λ (ab : ℤ × ℤ) => ab.1 - ab.2) P ⊆ Finset.Icc 1 (N - 1 : ℤ) := by
|
||
intro d hd
|
||
rcases Finset.mem_image.1 hd with ⟨⟨a, b⟩, hP, hd_eq⟩
|
||
have haA : a ∈ A := (Finset.mem_product.1 ((Finset.mem_filter.1 hP).1)).1
|
||
have hbA : b ∈ A := (Finset.mem_product.1 ((Finset.mem_filter.1 hP).1)).2
|
||
have ha_gt_b : a > b := (Finset.mem_filter.1 hP).2
|
||
rcases hbound a haA with ⟨ha1, haN⟩
|
||
rcases hbound b hbA with ⟨hb1, hbN⟩
|
||
rw [← hd_eq]
|
||
have h_pos : 1 ≤ a - b := by omega
|
||
have h_le : a - b ≤ (N : ℤ) - 1 := by omega
|
||
exact Finset.mem_Icc.mpr ⟨h_pos, h_le⟩
|
||
have h_icc_card : (Finset.Icc 1 (N - 1 : ℤ) : Finset ℤ).card = N - 1 := by
|
||
simp
|
||
have hP_card_le : m * (m - 1) / 2 ≤ N - 1 := by
|
||
calc
|
||
m * (m - 1) / 2 = P.card := hP_card.symm
|
||
_ = (Finset.image (λ (ab : ℤ × ℤ) => ab.1 - ab.2) P).card := hP_card_diffs.symm
|
||
_ ≤ (Finset.Icc 1 (N - 1 : ℤ) : Finset ℤ).card := Finset.card_le_card hD_bound
|
||
_ = N - 1 := h_icc_card
|
||
-- From m*(m-1)/2 ≤ N-1, prove m ≤ √(2N) + 1 by contradiction
|
||
have hpar : 2 ∣ m * (m - 1) := by
|
||
rcases Nat.even_or_odd m with he | ho
|
||
· exact he.two_dvd.mul_right _
|
||
· exact ((Nat.Odd.sub_odd ho odd_one).two_dvd).mul_left _
|
||
have hm_sq_sub_m_le : m * (m - 1) ≤ 2 * (N - 1) := by omega
|
||
by_contra! H
|
||
have hm_gt : m > Nat.sqrt (2 * N) + 1 := H
|
||
set s := Nat.sqrt (2 * N) with hs
|
||
have hm_ge : m ≥ s + 2 := by omega
|
||
have hm_sq_sub_m_gt : m * (m - 1) > 2 * (N - 1) := by
|
||
have h_sq_lt : 2 * N < (s + 1) * (s + 1) := Nat.lt_succ_sqrt (2 * N)
|
||
have hm_m_hm1_ge : m * (m - 1) ≥ (s + 2) * (s + 1) :=
|
||
Nat.mul_le_mul hm_ge (by omega)
|
||
have h_gt : (s + 2) * (s + 1) > 2 * (N - 1) := by
|
||
have hexp : (s + 2) * (s + 1) = (s + 1) * (s + 1) + (s + 1) := by ring
|
||
omega
|
||
omega
|
||
omega
|
||
|
||
/-- The quadratic upper bound on sidonMaximum: h(N) ≤ √(2N) + 1. -/
|
||
theorem sidonMaximum_le_sqrt_two (N : ℕ) (hN : 1 ≤ N) :
|
||
sidonMaximum N ≤ Nat.sqrt (2 * N) + 1 := by
|
||
have hmax := sidonMaximum_isSidonMaximum N
|
||
rcases hmax.1 with ⟨A, hA, hAcard⟩
|
||
have hcard := hA.card_le hN
|
||
rw [hAcard] at hcard
|
||
exact hcard
|
||
|
||
/-! ## Lindström's Cross-Difference Inequality -/
|
||
|
||
/-- In a strictly sorted list, elements from `take k` are strictly less than
|
||
elements from `drop k`. -/
|
||
private lemma sortedLT_take_lt_drop (l : List ℤ) (hs : l.SortedLT)
|
||
{k : ℕ} (hk_lt : k < l.length) :
|
||
∀ a ∈ l.take k, ∀ b ∈ l.drop k, a < b := by
|
||
intro a ha b hb
|
||
rw [List.mem_take_iff_getElem] at ha
|
||
rw [List.mem_drop_iff_getElem] at hb
|
||
obtain ⟨i, hi, rfl⟩ := ha
|
||
obtain ⟨j, hj, rfl⟩ := hb
|
||
have hi' : i < l.length := by omega
|
||
have hkj : k + j < l.length := by omega
|
||
exact hs (show (⟨i, hi'⟩ : Fin l.length) < ⟨k + j, hkj⟩ from by
|
||
simp [Fin.lt_def]; omega)
|
||
|
||
/-- In a Sidon set, cross-differences between disjoint subsets are distinct.
|
||
If `L, R ⊆ A` are disjoint and `b - a = d - c` with `a, c ∈ L`, `b, d ∈ R`,
|
||
then `a = c` and `b = d`. -/
|
||
theorem IsSidon.cross_diff_eq {A : Finset ℤ}
|
||
(hA : IsSidon A) {L R : Finset ℤ}
|
||
(hL : L ⊆ A) (hR : R ⊆ A) (hLR : Disjoint L R)
|
||
{a b c d : ℤ} (ha : a ∈ L) (hb : b ∈ R)
|
||
(hc : c ∈ L) (hd : d ∈ R)
|
||
(heq : b - a = d - c) :
|
||
a = c ∧ b = d := by
|
||
have hsum : b + c = d + a := by linarith
|
||
rcases hA (hR hb) (hL hc) (hR hd) (hL ha) hsum with h | h
|
||
· exact ⟨h.2.symm, h.1⟩
|
||
· exfalso
|
||
have hba : b = a := h.1
|
||
rw [hba] at hb
|
||
exact Finset.disjoint_left.mp hLR ha hb
|
||
|
||
/-- If `L` and `R` are disjoint subsets of an interval Sidon set in `{1,...,N}`,
|
||
and every element of `L` is strictly less than every element of `R`, then
|
||
the cross-difference map `(a, b) ↦ b - a` is injective from `L × R` into
|
||
`{1, ..., N-1}`, giving `|L| · |R| ≤ N - 1`. -/
|
||
theorem IsIntervalSidon.ordered_cross_diff_le {A : Finset ℤ} {N : ℤ}
|
||
(hIS : IsIntervalSidon N A) {L R : Finset ℤ}
|
||
(hL : L ⊆ A) (hR : R ⊆ A) (hLR : Disjoint L R)
|
||
(hord : ∀ a ∈ L, ∀ b ∈ R, a < b)
|
||
(hN : 1 ≤ N) (_hLne : L.Nonempty) (_hRne : R.Nonempty) :
|
||
(L.card : ℤ) * R.card ≤ N - 1 := by
|
||
let f : L × R → ℤ := fun ⟨⟨a, _⟩, ⟨b, _⟩⟩ => b - a
|
||
have hf_inj : Function.Injective f := by
|
||
intro ⟨⟨a, ha⟩, ⟨b, hb⟩⟩ ⟨⟨c, hc⟩, ⟨d, hd⟩⟩ heq
|
||
simp only [f] at heq
|
||
have := hIS.sidon.cross_diff_eq hL hR hLR ha hb hc hd heq
|
||
simp [this.1, this.2]
|
||
have hf_pos : ∀ x : L × R, 1 ≤ f x := by
|
||
intro ⟨⟨a, ha⟩, ⟨b, hb⟩⟩
|
||
simp only [f]
|
||
linarith [hord a ha b hb]
|
||
have hf_le : ∀ x : L × R, f x ≤ N - 1 := by
|
||
intro ⟨⟨a, ha⟩, ⟨b, hb⟩⟩
|
||
simp only [f]
|
||
have ha_bound := hIS.subset a (hL ha)
|
||
have hb_bound := hIS.subset b (hR hb)
|
||
linarith
|
||
have himage_sub : Finset.univ.image f ⊆ Finset.Icc 1 (N - 1) := by
|
||
intro z hz
|
||
rcases Finset.mem_image.mp hz with ⟨x, _, rfl⟩
|
||
exact Finset.mem_Icc.mpr ⟨hf_pos x, hf_le x⟩
|
||
have hcard : Fintype.card (L × R) = L.card * R.card := by
|
||
simp [Fintype.card_prod, Fintype.card_coe]
|
||
have himage_card : (Finset.univ.image f).card = L.card * R.card := by
|
||
rw [Finset.card_image_of_injective _ hf_inj]
|
||
simp [Fintype.card_prod, Fintype.card_coe]
|
||
have hprod_le : L.card * R.card ≤ (N - 1).toNat := by
|
||
calc L.card * R.card
|
||
= (Finset.univ.image f).card := himage_card.symm
|
||
_ ≤ (Finset.Icc 1 (N - 1)).card := Finset.card_le_card himage_sub
|
||
_ ≤ (N - 1).toNat := by simp
|
||
have hN1 : (0 : ℤ) ≤ N - 1 := by linarith
|
||
calc (L.card : ℤ) * R.card
|
||
= ↑(L.card * R.card) := by push_cast; ring
|
||
_ ≤ ↑(N - 1).toNat := by exact_mod_cast hprod_le
|
||
_ = N - 1 := Int.toNat_of_nonneg hN1
|
||
|
||
/-- **Lindström's cross-difference inequality.** For a Sidon set in {1,...,N}
|
||
of cardinality m, and any k with 1 ≤ k ≤ m, we have (m - k) * k ≤ N - 1.
|
||
|
||
This follows from splitting the sorted set into bottom-`k` and top-`(m-k)`
|
||
elements and applying `ordered_cross_diff_le`.
|
||
|
||
Reference: Lindström, B. (1969). An inequality for B₂-sequences.
|
||
*J. Combin. Theory*, 6(2), 211–212. -/
|
||
theorem IsIntervalSidon.lindstrom_cross_ineq {A : Finset ℤ} {N : ℕ}
|
||
(hIS : IsIntervalSidon (N : ℤ) A) (hN : 1 ≤ N)
|
||
{k : ℕ} (hk : 1 ≤ k) (hkm : k ≤ A.card) :
|
||
(A.card - k) * k ≤ N - 1 := by
|
||
by_cases hkm_eq : k = A.card
|
||
· simp [hkm_eq]
|
||
have hk_lt : k < A.card := lt_of_le_of_ne hkm hkm_eq
|
||
set sorted := A.sort (· ≤ ·)
|
||
have hnd : sorted.Nodup := A.sort_nodup (· ≤ ·)
|
||
have hlen : sorted.length = A.card := Finset.length_sort _
|
||
have hst : sorted.SortedLT := Finset.sortedLT_sort A
|
||
set L := (sorted.take k).toFinset
|
||
set R := (sorted.drop k).toFinset
|
||
have hLA : L ⊆ A := by
|
||
intro x hx; rw [List.mem_toFinset] at hx
|
||
have := List.mem_of_mem_take hx; rwa [Finset.mem_sort] at this
|
||
have hRA : R ⊆ A := by
|
||
intro x hx; rw [List.mem_toFinset] at hx
|
||
have := List.mem_of_mem_drop hx; rwa [Finset.mem_sort] at this
|
||
have hLR : Disjoint L R := by
|
||
rw [Finset.disjoint_left]; intro x hxL hxR
|
||
rw [List.mem_toFinset] at hxL hxR
|
||
exact absurd hxR ((List.disjoint_take_drop hnd (le_refl k)) hxL)
|
||
have hLcard : L.card = k := by
|
||
rw [List.toFinset_card_of_nodup (hnd.sublist (List.take_sublist k sorted))]
|
||
rw [List.length_take, hlen]; exact Nat.min_eq_left (le_of_lt hk_lt)
|
||
have hRcard : R.card = A.card - k := by
|
||
rw [List.toFinset_card_of_nodup (hnd.sublist (List.drop_sublist k sorted))]
|
||
rw [List.length_drop, hlen]
|
||
have hord : ∀ a ∈ L, ∀ b ∈ R, a < b := by
|
||
intro a ha b hb; rw [List.mem_toFinset] at ha hb
|
||
exact sortedLT_take_lt_drop sorted hst (by rw [hlen]; omega) a ha b hb
|
||
have hLne : L.Nonempty := by
|
||
rw [Finset.nonempty_iff_ne_empty]; intro h; simp [h] at hLcard; omega
|
||
have hRne : R.Nonempty := by
|
||
rw [Finset.nonempty_iff_ne_empty]; intro h; simp [h] at hRcard; omega
|
||
have hN_int : (1 : ℤ) ≤ (N : ℤ) := by exact_mod_cast hN
|
||
have hint : (L.card : ℤ) * R.card ≤ (N : ℤ) - 1 :=
|
||
hIS.ordered_cross_diff_le hLA hRA hLR hord hN_int hLne hRne
|
||
rw [hLcard, hRcard] at hint
|
||
zify [hN, show k ≤ A.card from le_of_lt hk_lt]
|
||
have hconv : (↑(A.card - k) : ℤ) = (↑A.card : ℤ) - ↑k :=
|
||
Nat.cast_sub (le_of_lt hk_lt)
|
||
rw [hconv] at hint
|
||
linarith
|
||
|
||
/-! ## Lindström Improved Bound — Johnson/Cauchy-Schwarz machinery -/
|
||
|
||
/-- For a Sidon set A, the shifted copies A+h₁ and A+h₂ intersect in at most
|
||
one element when h₁ ≠ h₂. -/
|
||
theorem IsSidon.shift_inter_le_one {A : Finset ℤ} (hA : IsSidon A)
|
||
{h₁ h₂ : ℤ} (hne : h₁ ≠ h₂) :
|
||
((A.image (· + h₁)) ∩ (A.image (· + h₂))).card ≤ 1 := by
|
||
by_contra hgt
|
||
push_neg at hgt
|
||
obtain ⟨x, hx, y, hy, hxy⟩ := Finset.one_lt_card.mp (by omega : 1 < ((A.image (· + h₁)) ∩ (A.image (· + h₂))).card)
|
||
rw [Finset.mem_inter, Finset.mem_image, Finset.mem_image] at hx hy
|
||
obtain ⟨⟨a₁, ha₁, rfl⟩, ⟨b₁, hb₁, hx_eq⟩⟩ := hx
|
||
obtain ⟨⟨a₂, ha₂, rfl⟩, ⟨b₂, hb₂, hy_eq⟩⟩ := hy
|
||
have heq1 : a₁ - b₁ = h₂ - h₁ := by linarith [hx_eq]
|
||
have heq2 : a₂ - b₂ = h₂ - h₁ := by linarith [hy_eq]
|
||
have hsum : a₁ + b₂ = a₂ + b₁ := by linarith
|
||
rcases hA ha₁ hb₂ ha₂ hb₁ hsum with ⟨h1, h2⟩ | ⟨h1, h2⟩
|
||
· have : a₁ + h₁ = a₂ + h₁ := by rw [h1]
|
||
exact hxy this
|
||
· have : h₁ = h₂ := by linarith [heq1, h1]
|
||
exact hne this
|
||
|
||
/-- **Johnson's bound (numerical form).** If (km)² ≤ v·m·(m+k-1), then
|
||
k²·m ≤ v·(m+k-1). -/
|
||
theorem johnson_numerical {k m v : ℕ} (hm : 0 < m)
|
||
(hcs_moment : (k * m) ^ 2 ≤ v * (m * (m + k - 1))) :
|
||
k ^ 2 * m ≤ v * (m + k - 1) := by
|
||
have hrw1 : (k * m) ^ 2 = k ^ 2 * m * m := by ring
|
||
have hrw2 : v * (m * (m + k - 1)) = v * (m + k - 1) * m := by ring
|
||
rw [hrw1, hrw2] at hcs_moment
|
||
exact Nat.le_of_mul_le_mul_right hcs_moment hm
|
||
|
||
/-- **Incidence inequality.** For any family of finsets S₁,...,Sₘ all contained
|
||
in a universe U, (∑ᵢ |Sᵢ|)² ≤ |U| · ∑ᵢ ∑ⱼ |Sᵢ ∩ Sⱼ|.
|
||
Uses Cauchy-Schwarz via the degree function d(x) = #{i : x ∈ Sᵢ}. -/
|
||
theorem incidence_inequality {α : Type*} [DecidableEq α] (m : ℕ)
|
||
(shifts : Fin m → Finset α) (U : Finset α)
|
||
(hsub : ∀ i, shifts i ⊆ U) :
|
||
(∑ i : Fin m, (shifts i).card) ^ 2 ≤
|
||
U.card * ∑ i : Fin m, ∑ j : Fin m, ((shifts i) ∩ (shifts j)).card := by
|
||
set deg : α → ℕ := fun x => (Finset.univ.filter (fun i : Fin m => x ∈ shifts i)).card
|
||
have hfilt_eq : ∀ i : Fin m, shifts i = U.filter (· ∈ shifts i) := by
|
||
intro i; ext x; simp only [Finset.mem_filter]
|
||
exact ⟨fun h => ⟨hsub i h, h⟩, fun h => h.2⟩
|
||
have h_dc : ∑ i : Fin m, (shifts i).card = ∑ x ∈ U, deg x := by
|
||
simp only [deg]
|
||
trans ∑ i : Fin m, ∑ x ∈ U, if x ∈ shifts i then 1 else 0
|
||
· congr 1; ext i
|
||
conv_lhs => rw [hfilt_eq i, Finset.card_eq_sum_ones, Finset.sum_filter]
|
||
· rw [Finset.sum_comm]
|
||
congr 1; ext x; rw [Finset.card_eq_sum_ones, Finset.sum_filter]
|
||
have hinter_eq : ∀ i j : Fin m, (shifts i) ∩ (shifts j) =
|
||
U.filter (fun x => x ∈ shifts i ∧ x ∈ shifts j) := by
|
||
intro i j; ext x; simp only [Finset.mem_inter, Finset.mem_filter]
|
||
exact ⟨fun ⟨hi, hj⟩ => ⟨hsub i hi, hi, hj⟩, fun ⟨_, hi, hj⟩ => ⟨hi, hj⟩⟩
|
||
have h_sm : ∑ i : Fin m, ∑ j : Fin m, ((shifts i) ∩ (shifts j)).card =
|
||
∑ x ∈ U, deg x ^ 2 := by
|
||
simp only [deg, sq]
|
||
trans ∑ x ∈ U, ∑ i : Fin m, ∑ j : Fin m,
|
||
if x ∈ shifts i ∧ x ∈ shifts j then (1 : ℕ) else 0
|
||
· trans ∑ i : Fin m, ∑ j : Fin m, ∑ x ∈ U,
|
||
if x ∈ shifts i ∧ x ∈ shifts j then (1 : ℕ) else 0
|
||
· congr 1; ext i; congr 1; ext j
|
||
conv_lhs => rw [hinter_eq i j, Finset.card_eq_sum_ones, Finset.sum_filter]
|
||
· conv_lhs => arg 2; ext i; rw [Finset.sum_comm]
|
||
exact Finset.sum_comm
|
||
· congr 1; ext x
|
||
trans (∑ i : Fin m, if x ∈ shifts i then (1 : ℕ) else 0) *
|
||
(∑ j : Fin m, if x ∈ shifts j then 1 else 0)
|
||
· rw [Finset.sum_mul]; congr 1; ext i; rw [Finset.mul_sum]
|
||
congr 1; ext j
|
||
by_cases h1 : x ∈ shifts i <;> by_cases h2 : x ∈ shifts j <;> simp [h1, h2]
|
||
· congr 1 <;> rw [Finset.card_eq_sum_ones, Finset.sum_filter]
|
||
have h_cs : (∑ x ∈ U, deg x) ^ 2 ≤ U.card * ∑ x ∈ U, deg x ^ 2 := by
|
||
suffices h : (∑ x ∈ U, (deg x : ℤ)) ^ 2 ≤ ↑U.card * ∑ x ∈ U, (deg x : ℤ) ^ 2 by
|
||
exact_mod_cast h
|
||
exact sq_sum_le_card_mul_sum_sq
|
||
calc (∑ i : Fin m, (shifts i).card) ^ 2
|
||
= (∑ x ∈ U, deg x) ^ 2 := by rw [h_dc]
|
||
_ ≤ U.card * ∑ x ∈ U, deg x ^ 2 := h_cs
|
||
_ = U.card * ∑ i : Fin m, ∑ j : Fin m, ((shifts i) ∩ (shifts j)).card := by rw [h_sm]
|
||
|
||
/-- The intersection matrix row-sum bound for shifted Sidon copies.
|
||
Diagonal terms contribute k each, off-diagonal ≤ 1 each,
|
||
total ≤ mk + m(m-1) = m(m+k-1). -/
|
||
theorem sidon_intersection_sum_bound {A : Finset ℤ} (hA : IsSidon A) (m : ℕ) :
|
||
∑ i : Fin m, ∑ j : Fin m,
|
||
((A.image (· + (↑(i : ℕ) : ℤ))) ∩ (A.image (· + (↑(j : ℕ) : ℤ)))).card
|
||
≤ m * (m + A.card - 1) := by
|
||
set k := A.card
|
||
have hrow : ∀ i : Fin m,
|
||
∑ j : Fin m,
|
||
((A.image (· + (↑(i : ℕ) : ℤ))) ∩ (A.image (· + (↑(j : ℕ) : ℤ)))).card
|
||
≤ m + k - 1 := by
|
||
intro i
|
||
have hi_mem : i ∈ (Finset.univ : Finset (Fin m)) := Finset.mem_univ i
|
||
rw [← Finset.sum_erase_add _ _ hi_mem]
|
||
have hdiag : ((A.image (· + (↑(i : ℕ) : ℤ))) ∩ (A.image (· + (↑(i : ℕ) : ℤ)))).card = k := by
|
||
rw [Finset.inter_self]
|
||
exact Finset.card_image_of_injective _ (fun a b h => by linarith)
|
||
have hoff : ∑ j ∈ Finset.univ.erase i,
|
||
((A.image (· + (↑(i : ℕ) : ℤ))) ∩ (A.image (· + (↑(j : ℕ) : ℤ)))).card ≤ m - 1 := by
|
||
calc ∑ j ∈ Finset.univ.erase i, _
|
||
≤ ∑ j ∈ Finset.univ.erase i, 1 := Finset.sum_le_sum (fun j hj => by
|
||
have hjmem := Finset.mem_erase.mp hj
|
||
have hne : (↑(i : ℕ) : ℤ) ≠ ↑(j : ℕ) := by
|
||
exact_mod_cast Fin.val_ne_of_ne (Ne.symm hjmem.1)
|
||
exact hA.shift_inter_le_one hne)
|
||
_ = (Finset.univ.erase i).card := by simp
|
||
_ = m - 1 := by simp [Finset.card_erase_of_mem hi_mem, Fintype.card_fin]
|
||
have hm_pos : 0 < m := Fin.pos i
|
||
omega
|
||
calc ∑ i : Fin m, ∑ j : Fin m, _
|
||
≤ ∑ i : Fin m, (m + k - 1) := Finset.sum_le_sum (fun i _ => hrow i)
|
||
_ = m * (m + k - 1) := by simp [Finset.sum_const, Finset.card_univ, Fintype.card_fin]
|
||
|
||
/-- **Johnson bound for shifted Sidon sets.** For a Sidon set A ⊆ {1,...,N}
|
||
with |A| = k, the m shifted copies A, A+1, ..., A+(m-1) satisfy
|
||
k²·m ≤ (N+m-1)·(m+k-1). -/
|
||
theorem IsIntervalSidon.sidon_johnson_bound {A : Finset ℤ} {N : ℕ}
|
||
(hIS : IsIntervalSidon (N : ℤ) A) (hN : 1 ≤ N)
|
||
(m : ℕ) (hm : 0 < m) :
|
||
A.card ^ 2 * m ≤ (N + m - 1) * (m + A.card - 1) := by
|
||
set k := A.card
|
||
have hA := hIS.sidon
|
||
set shifts : Fin m → Finset ℤ := fun i => A.image (· + (↑(i : ℕ) : ℤ))
|
||
set U := Finset.Icc (1 : ℤ) (↑N + ↑m - 1)
|
||
have hshift_card : ∀ i : Fin m, (shifts i).card = k := fun i =>
|
||
Finset.card_image_of_injective _ (fun a b h => by linarith)
|
||
have hsub : ∀ i : Fin m, shifts i ⊆ U := by
|
||
intro i x hx
|
||
simp only [shifts, Finset.mem_image] at hx
|
||
obtain ⟨a, ha, rfl⟩ := hx
|
||
have hAint := hIS.subset a ha
|
||
simp only [U, Finset.mem_Icc]
|
||
constructor
|
||
· linarith [hAint.1, (i : ℕ).zero_le]
|
||
· have hi : (↑(i : ℕ) : ℤ) ≤ ↑m - 1 := by
|
||
have := i.isLt
|
||
omega
|
||
linarith [hAint.2]
|
||
have hU_card : U.card = N + m - 1 := by
|
||
simp only [U, Int.card_Icc]
|
||
omega
|
||
have hinc := incidence_inequality m shifts U hsub
|
||
have hsum_card : ∑ i : Fin m, (shifts i).card = m * k := by
|
||
simp [hshift_card, Finset.sum_const, Finset.card_univ, Fintype.card_fin]
|
||
have hint : ∑ i : Fin m, ∑ j : Fin m, ((shifts i) ∩ (shifts j)).card
|
||
≤ m * (m + k - 1) := sidon_intersection_sum_bound hA m
|
||
have hkey : (k * m) ^ 2 ≤ (N + m - 1) * (m * (m + k - 1)) :=
|
||
calc (k * m) ^ 2 = (m * k) ^ 2 := by ring
|
||
_ = (∑ i : Fin m, (shifts i).card) ^ 2 := by rw [hsum_card]
|
||
_ ≤ U.card * ∑ i : Fin m, ∑ j : Fin m, ((shifts i) ∩ (shifts j)).card := hinc
|
||
_ ≤ U.card * (m * (m + k - 1)) := Nat.mul_le_mul_left _ hint
|
||
_ = (N + m - 1) * (m * (m + k - 1)) := by rw [hU_card]
|
||
exact johnson_numerical hm hkey
|
||
|
||
/-- Johnson bound with Nat subtraction implies the cleaner relaxed bound. -/
|
||
theorem lindstrom_monotone {k m n : ℕ}
|
||
(hjohnson : k ^ 2 * m ≤ (n + m - 1) * (m + k - 1)) :
|
||
k ^ 2 * m ≤ (n + m) * (m + k) :=
|
||
hjohnson.trans (Nat.mul_le_mul (Nat.sub_le _ _) (Nat.sub_le _ _))
|
||
|
||
set_option maxHeartbeats 1600000 in
|
||
/-- **Lindström's upper bound.** For a Sidon set A ⊆ {1,...,N} with N ≥ 16,
|
||
|A| ≤ √N + ⁴√N + 2.
|
||
Uses the Johnson bound with optimal choice m = √N · ⁴√N ≈ N^{3/4}. -/
|
||
theorem IsIntervalSidon.lindstrom_bound {A : Finset ℤ} {N : ℕ}
|
||
(hIS : IsIntervalSidon (N : ℤ) A) (hN : 16 ≤ N) :
|
||
A.card ≤ Nat.sqrt N + Nat.sqrt (Nat.sqrt N) + 2 := by
|
||
by_contra h_bad
|
||
push_neg at h_bad
|
||
set k := A.card
|
||
set s := Nat.sqrt N
|
||
set t := Nat.sqrt s
|
||
set m := s * t
|
||
have hs_ge : 4 ≤ s := Nat.le_sqrt.mpr (by omega : 4 ^ 2 ≤ N)
|
||
have ht_ge : 2 ≤ t := Nat.le_sqrt.mpr (by omega : 2 ^ 2 ≤ s)
|
||
have hm_pos : 0 < m := by positivity
|
||
have hk_ge : s + t + 3 ≤ k := by omega
|
||
have hN_lt : N < (s + 1) ^ 2 := Nat.lt_succ_sqrt' N
|
||
have hs_lt : s < (t + 1) ^ 2 := Nat.lt_succ_sqrt' s
|
||
have hN_le : N ≤ s ^ 2 + 2 * s := by nlinarith [hN_lt]
|
||
have hs_le : s ≤ t ^ 2 + 2 * t := by nlinarith [hs_lt]
|
||
have hJ := hIS.sidon_johnson_bound (by omega : 1 ≤ N) m hm_pos
|
||
have hJz : (k : ℤ) ^ 2 * ((s : ℤ) * t) ≤
|
||
((N : ℤ) + s * t - 1) * (s * t + k - 1) := by
|
||
have h : k ^ 2 * (s * t) ≤ (N + s * t - 1) * (s * t + k - 1) := hJ
|
||
have hge1 : 1 ≤ N + s * t := by omega
|
||
have hge2 : 1 ≤ s * t + k := by omega
|
||
zify [hge1, hge2] at h
|
||
linarith
|
||
have hs_z : (s : ℤ) ≤ (t : ℤ) ^ 2 + 2 * t := by exact_mod_cast hs_le
|
||
have hN_z : (N : ℤ) ≤ (s : ℤ) ^ 2 + 2 * s := by exact_mod_cast hN_le
|
||
have hk_z : (s : ℤ) + t + 3 ≤ (k : ℤ) := by exact_mod_cast hk_ge
|
||
have hs_pos : (0 : ℤ) < (s : ℤ) := by
|
||
linarith [show (4 : ℤ) ≤ (s : ℤ) from by exact_mod_cast hs_ge]
|
||
have ht_pos : (0 : ℤ) < (t : ℤ) := by
|
||
linarith [show (2 : ℤ) ≤ (t : ℤ) from by exact_mod_cast ht_ge]
|
||
have hD0 : ((s : ℤ) + t + 3) ^ 2 * (s * t) >
|
||
((N : ℤ) + s * t - 1) * (s * t + s + t + 2) := by
|
||
have h_id : ((s : ℤ) + t + 3) ^ 2 * (s * t) -
|
||
((s : ℤ) ^ 2 + 2 * s + s * t - 1) * (s * t + s + t + 2)
|
||
= ((s : ℤ) ^ 2 + 4 * s) * ((t : ℤ) ^ 2 + 2 * t - s)
|
||
+ s * ((t : ℤ) ^ 3 + t ^ 2 - 2 * t - 3) + t + 2 := by ring
|
||
have h1 : (0 : ℤ) ≤ ((s : ℤ) ^ 2 + 4 * s) * ((t : ℤ) ^ 2 + 2 * t - s) := by
|
||
apply mul_nonneg <;> nlinarith
|
||
have h2 : (0 : ℤ) < (s : ℤ) * ((t : ℤ) ^ 3 + t ^ 2 - 2 * t - 3) + t + 2 := by
|
||
have ht_cube : (0 : ℤ) < (t : ℤ) ^ 3 + t ^ 2 - 2 * t - 3 := by
|
||
nlinarith [mul_nonneg (show (0 : ℤ) ≤ t from by linarith)
|
||
(sq_nonneg ((t : ℤ) - 2))]
|
||
nlinarith
|
||
have h_stpos : (0 : ℤ) ≤ (s : ℤ) * t + s + t + 2 := by positivity
|
||
have h_mono : ((N : ℤ) + s * t - 1) * (s * t + s + t + 2) ≤
|
||
((s : ℤ) ^ 2 + 2 * s + s * t - 1) * (s * t + s + t + 2) := by
|
||
apply mul_le_mul_of_nonneg_right <;> linarith
|
||
nlinarith
|
||
have hDeriv : (0 : ℤ) ≤ (s : ℤ) * t * (k + s + t + 3) - ((N : ℤ) + s * t - 1) := by
|
||
have ht1 : (1 : ℤ) ≤ t := ht_pos
|
||
have h1 : (s : ℤ) * t * (2 * s + 2 * t + 6) ≤ s * t * (k + s + t + 3) :=
|
||
mul_le_mul_of_nonneg_left (by linarith) (mul_nonneg hs_pos.le ht_pos.le)
|
||
have h2 : (s : ℤ) ^ 2 ≤ s ^ 2 * t := le_mul_of_one_le_right (sq_nonneg _) ht1
|
||
have h3 : (s : ℤ) * t ≤ s * t * t :=
|
||
le_mul_of_one_le_right (mul_nonneg hs_pos.le ht_pos.le) ht1
|
||
have h4 : (s : ℤ) ≤ s * t := le_mul_of_one_le_right hs_pos.le ht1
|
||
nlinarith [h1, h2, h3, h4, hN_z]
|
||
have hFact : (k : ℤ) ^ 2 * (s * t) - ((N : ℤ) + s * t - 1) * (s * t + k - 1)
|
||
= ((s : ℤ) + t + 3) ^ 2 * (s * t) - ((N : ℤ) + s * t - 1) * (s * t + s + t + 2)
|
||
+ ((k : ℤ) - s - t - 3) *
|
||
((s : ℤ) * t * (k + s + t + 3) - ((N : ℤ) + s * t - 1)) := by ring
|
||
have hknn : (0 : ℤ) ≤ (k : ℤ) - s - t - 3 := by linarith
|
||
have hprod : (0 : ℤ) ≤ ((k : ℤ) - s - t - 3) *
|
||
((s : ℤ) * t * (k + s + t + 3) - ((N : ℤ) + s * t - 1)) :=
|
||
mul_nonneg hknn hDeriv
|
||
linarith
|
||
|
||
/-- The Lindström upper bound: h(N) ≤ √N + √(√N) + 2 for N ≥ 16. -/
|
||
theorem sidonMaximum_le_lindstrom (N : ℕ) (hN : 16 ≤ N) :
|
||
sidonMaximum N ≤ Nat.sqrt N + Nat.sqrt (Nat.sqrt N) + 2 := by
|
||
rcases (sidonMaximum_isSidonMaximum N).1 with ⟨A, hA, hAcard⟩
|
||
have h := hA.lindstrom_bound hN
|
||
omega
|
||
|
||
/-! ## Singer's Construction -/
|
||
|
||
/-!
|
||
Port of the Singer construction from Erdos30/{Singer, SingerBridge, SingerSidon,
|
||
SingerTheorem}.lean (Hulak–Ramos–de Queiroz, arXiv:2605.03274), adapted from
|
||
Mathlib v4.29.0 to v4.30.0-rc2 and renamespaced into `Semantics.SidonSets.Singer`.
|
||
-/
|
||
|
||
namespace Singer
|
||
|
||
set_option maxHeartbeats 8000000
|
||
set_option linter.unusedSimpArgs false
|
||
|
||
open Module Submodule Polynomial LinearMap
|
||
|
||
variable (p : ℕ) [hp : Fact (Nat.Prime p)]
|
||
|
||
/-! ### Dimension facts (Erdos30/Singer.lean) -/
|
||
|
||
theorem finrank_ext : finrank (ZMod p) (GaloisField p 3) = 3 :=
|
||
@GaloisField.finrank p hp 3 (by norm_num)
|
||
|
||
theorem trace_surjective :
|
||
Function.Surjective (Algebra.trace (ZMod p) (GaloisField p 3)) :=
|
||
Algebra.trace_surjective (ZMod p) (GaloisField p 3)
|
||
|
||
/-- ker(Tr) has dimension 2 (rank-nullity). -/
|
||
theorem finrank_ker_trace :
|
||
finrank (ZMod p) (Algebra.trace (ZMod p) (GaloisField p 3)).ker = 2 := by
|
||
have h_rn := LinearMap.finrank_range_add_finrank_ker
|
||
(Algebra.trace (ZMod p) (GaloisField p 3))
|
||
rw [@GaloisField.finrank p hp 3 (by norm_num)] at h_rn
|
||
have htop : (Algebra.trace (ZMod p) (GaloisField p 3)).range = ⊤ :=
|
||
LinearMap.range_eq_top_of_surjective _ (trace_surjective p)
|
||
rw [show finrank (ZMod p) ↥(Algebra.trace (ZMod p) (GaloisField p 3)).range =
|
||
finrank (ZMod p) (ZMod p) from by rw [htop]; exact finrank_top (ZMod p) (ZMod p),
|
||
finrank_self] at h_rn
|
||
omega
|
||
|
||
/-! ### Minimal polynomial and linear independence -/
|
||
|
||
theorem minpoly_degree_eq_three (α : GaloisField p 3)
|
||
(hα : α ∉ Set.range (algebraMap (ZMod p) (GaloisField p 3))) :
|
||
(minpoly (ZMod p) α).natDegree = 3 := by
|
||
have hint : IsIntegral (ZMod p) α := Algebra.IsIntegral.isIntegral α
|
||
have hdvd : (minpoly (ZMod p) α).natDegree ∣ 3 := by
|
||
have h := minpoly.degree_dvd hint
|
||
rwa [@GaloisField.finrank p hp 3 (by norm_num)] at h
|
||
have hne1 : (minpoly (ZMod p) α).natDegree ≠ 1 := by
|
||
intro h1
|
||
exact hα (IntermediateField.mem_bot.mp (by
|
||
rw [← IntermediateField.finrank_eq_one_iff.mp
|
||
(by rw [IntermediateField.adjoin.finrank hint]; exact h1)]
|
||
exact IntermediateField.subset_adjoin (ZMod p) {α} (Set.mem_singleton α)))
|
||
exact (Nat.Prime.eq_one_or_self_of_dvd (by decide) _ hdvd).resolve_left hne1
|
||
|
||
/-- {α⁰·v, α¹·v, α²·v} are GF(p)-linearly independent when α ∉ GF(p) and v ≠ 0. -/
|
||
theorem linIndep_smul_v (α v : GaloisField p 3)
|
||
(hα : α ∉ Set.range (algebraMap (ZMod p) (GaloisField p 3)))
|
||
(hv : v ≠ 0) :
|
||
LinearIndependent (ZMod p) (fun i : Fin 3 => α ^ (i : ℕ) * v) := by
|
||
rw [Fintype.linearIndependent_iff]
|
||
intro g hg
|
||
have hfactor : (∑ i : Fin 3, g i • α ^ (i : ℕ)) * v = 0 := by
|
||
have heq : ∑ i : Fin 3, g i • (α ^ (i : ℕ) * v) =
|
||
(∑ i : Fin 3, g i • α ^ (i : ℕ)) * v := by
|
||
simp [Finset.sum_mul, Algebra.smul_mul_assoc]
|
||
rw [← heq]; exact hg
|
||
have hsum : ∑ i : Fin 3, g i • α ^ (i : ℕ) = 0 :=
|
||
(mul_eq_zero.mp hfactor).resolve_right hv
|
||
have hdeg := minpoly_degree_eq_three p α hα
|
||
have hli := @linearIndependent_pow _ _ (ZMod p) _ _ α
|
||
rw [Fintype.linearIndependent_iff] at hli
|
||
intro i
|
||
have hsum_t : ∑ j : Fin (minpoly (ZMod p) α).natDegree,
|
||
(g ∘ Fin.cast hdeg) j • α ^ (j : ℕ) = 0 := by
|
||
convert hsum using 1
|
||
exact Fintype.sum_equiv (Fin.castOrderIso hdeg).toEquiv _ _
|
||
(fun j => by simp [Function.comp, Fin.castOrderIso, Fin.cast])
|
||
have h := hli _ hsum_t (Fin.cast hdeg.symm i)
|
||
simp [Function.comp, Fin.cast] at h; exact h
|
||
|
||
/-! ### No proper invariant subspace -/
|
||
|
||
/-- Multiplication by α ∉ GF(p) has no proper invariant subspace in GF(p³)/GF(p). -/
|
||
theorem no_proper_invariant_subspace (α : GaloisField p 3)
|
||
(hα : α ∉ Set.range (algebraMap (ZMod p) (GaloisField p 3)))
|
||
(V : Submodule (ZMod p) (GaloisField p 3)) (hVbot : V ≠ ⊥) (hVtop : V ≠ ⊤)
|
||
(hinv : ∀ v : GaloisField p 3, v ∈ V → α • v ∈ V) : False := by
|
||
have hinv_pow : ∀ (n : ℕ) (v : GaloisField p 3), v ∈ V → α ^ n • v ∈ V := by
|
||
intro n; induction n with
|
||
| zero => intro v hv; simpa using hv
|
||
| succ n ih => intro v hv; have h := ih _ (hinv v hv); rwa [← mul_smul, ← pow_succ] at h
|
||
obtain ⟨v, hv_mem, hv_ne⟩ := Submodule.exists_mem_ne_zero_of_ne_bot hVbot
|
||
have hVlt : finrank (ZMod p) V < 3 := by
|
||
have := finrank_lt_finrank_of_lt (lt_top_iff_ne_top.mpr hVtop)
|
||
rw [finrank_top, @GaloisField.finrank p hp 3 (by norm_num)] at this; exact this
|
||
have hmem : ∀ i : Fin 3, α ^ (i : ℕ) * v ∈ V := fun i => by
|
||
have h := hinv_pow i v hv_mem; rwa [Algebra.smul_def] at h
|
||
have hli : LinearIndependent (ZMod p) (fun i : Fin 3 => α ^ (i : ℕ) * v) :=
|
||
linIndep_smul_v p α v hα hv_ne
|
||
have hli_V : LinearIndependent (ZMod p) (fun i : Fin 3 =>
|
||
(⟨α ^ (i : ℕ) * v, hmem i⟩ : V)) := by
|
||
rw [Fintype.linearIndependent_iff]; intro g hg
|
||
rw [Fintype.linearIndependent_iff] at hli
|
||
apply hli g
|
||
have := congr_arg Subtype.val hg
|
||
simpa using this
|
||
exact absurd hVlt (not_lt.mpr
|
||
(le_of_eq (Fintype.card_fin 3).symm |>.trans hli_V.fintype_card_le_finrank))
|
||
|
||
/-! ### Intersection dimension -/
|
||
|
||
/-- Two distinct 2-dim subspaces of GF(p³)/GF(p) intersect in dimension 1. -/
|
||
theorem finrank_inf_of_distinct_twodim
|
||
(V W : Submodule (ZMod p) (GaloisField p 3))
|
||
(hV : finrank (ZMod p) V = 2) (hW : finrank (ZMod p) W = 2) (hne : V ≠ W) :
|
||
finrank (ZMod p) ↥(V ⊓ W) = 1 := by
|
||
have hgrass := Submodule.finrank_sup_add_finrank_inf_eq V W
|
||
have h_sup_le : finrank (ZMod p) ↥(V ⊔ W) ≤ 3 := by
|
||
have := Submodule.finrank_le (V ⊔ W)
|
||
rw [@GaloisField.finrank p hp 3 (by norm_num)] at this; exact this
|
||
have hV_lt_sup : V < V ⊔ W := lt_of_le_of_ne le_sup_left (fun heq =>
|
||
hne (eq_of_le_of_finrank_le (heq ▸ le_sup_right) (by omega)).symm)
|
||
have h_sup_gt : 2 < finrank (ZMod p) ↥(V ⊔ W) := by
|
||
have := finrank_lt_finrank_of_lt hV_lt_sup; rw [hV] at this; exact this
|
||
rw [hV, hW] at hgrass; omega
|
||
|
||
/-! ### Multiplication linear equivalence (Erdos30/SingerBridge.lean) -/
|
||
|
||
noncomputable instance instFintypeGF3 : Fintype (GaloisField p 3) := Fintype.ofFinite _
|
||
noncomputable instance instFintypeGF3units : Fintype (GaloisField p 3)ˣ := Fintype.ofFinite _
|
||
noncomputable instance instFintypeZModUnits : Fintype (ZMod p)ˣ := Fintype.ofFinite _
|
||
|
||
/-- Multiplication by a nonzero element is a GF(p)-linear automorphism. -/
|
||
noncomputable def mulLinearEquiv (α : GaloisField p 3) (hα : α ≠ 0) :
|
||
GaloisField p 3 ≃ₗ[ZMod p] GaloisField p 3 where
|
||
toFun := fun x => α * x
|
||
map_add' := mul_add α
|
||
map_smul' := fun r x => by simp [Algebra.smul_def, mul_left_comm]
|
||
invFun := fun x => α⁻¹ * x
|
||
left_inv := fun x => by
|
||
show α⁻¹ * (α * x) = x; rw [← mul_assoc, inv_mul_cancel₀ hα, one_mul]
|
||
right_inv := fun x => by
|
||
show α * (α⁻¹ * x) = x; rw [← mul_assoc, mul_inv_cancel₀ hα, one_mul]
|
||
|
||
/-- The scaled submodule αV = {αv : v ∈ V}. -/
|
||
noncomputable def scaledSubmodule (α : GaloisField p 3) (hα : α ≠ 0)
|
||
(V : Submodule (ZMod p) (GaloisField p 3)) :
|
||
Submodule (ZMod p) (GaloisField p 3) :=
|
||
V.map (mulLinearEquiv p α hα).toLinearMap
|
||
|
||
lemma mem_scaledSubmodule_iff (α : GaloisField p 3) (hα : α ≠ 0)
|
||
(V : Submodule (ZMod p) (GaloisField p 3)) (x : GaloisField p 3) :
|
||
x ∈ scaledSubmodule p α hα V ↔ ∃ v ∈ V, α * v = x := by
|
||
simp [scaledSubmodule, Submodule.mem_map, mulLinearEquiv]
|
||
|
||
lemma finrank_scaledSubmodule (α : GaloisField p 3) (hα : α ≠ 0)
|
||
(V : Submodule (ZMod p) (GaloisField p 3)) :
|
||
finrank (ZMod p) (scaledSubmodule p α hα V) = finrank (ZMod p) V :=
|
||
LinearEquiv.finrank_eq ((mulLinearEquiv p α hα).submoduleMap V |>.symm)
|
||
|
||
/-! ### Trace kernel basic properties -/
|
||
|
||
private lemma ker_trace_ne_bot :
|
||
(Algebra.trace (ZMod p) (GaloisField p 3)).ker ≠ ⊥ :=
|
||
fun h => by have := finrank_ker_trace p; rw [h, finrank_bot (R := ZMod p) (M := GaloisField p 3)] at this; omega
|
||
|
||
private lemma ker_trace_ne_top :
|
||
(Algebra.trace (ZMod p) (GaloisField p 3)).ker ≠ ⊤ :=
|
||
fun h => by
|
||
have h2 := finrank_ker_trace p
|
||
have h3 := @GaloisField.finrank p hp 3 (by norm_num)
|
||
rw [h, finrank_top, h3] at h2; omega
|
||
|
||
/-! ### Non-invariance of trace kernel under non-base multiplication -/
|
||
|
||
/-- The scaled trace kernel αV ≠ V when α ∉ GF(p). -/
|
||
lemma scaledSubmodule_ne_ker_trace (α : GaloisField p 3) (hα_ne : α ≠ 0)
|
||
(hα : α ∉ Set.range (algebraMap (ZMod p) (GaloisField p 3))) :
|
||
scaledSubmodule p α hα_ne (Algebra.trace (ZMod p) (GaloisField p 3)).ker ≠
|
||
(Algebra.trace (ZMod p) (GaloisField p 3)).ker := by
|
||
set V := (Algebra.trace (ZMod p) (GaloisField p 3)).ker
|
||
intro heq
|
||
have hinv : ∀ v : GaloisField p 3, v ∈ V → α • v ∈ V := by
|
||
intro v hv
|
||
have hmem : α * v ∈ scaledSubmodule p α hα_ne V :=
|
||
(mem_scaledSubmodule_iff p α hα_ne V (α * v)).mpr ⟨v, hv, rfl⟩
|
||
rw [heq] at hmem
|
||
rwa [Algebra.smul_def]
|
||
exact no_proper_invariant_subspace p α hα V (ker_trace_ne_bot p) (ker_trace_ne_top p) hinv
|
||
|
||
/-- α⁻¹ ∉ GF(p) when α ∉ GF(p). -/
|
||
lemma inv_not_in_range (α : GaloisField p 3) (hα_ne : α ≠ 0)
|
||
(hα : α ∉ Set.range (algebraMap (ZMod p) (GaloisField p 3))) :
|
||
α⁻¹ ∉ Set.range (algebraMap (ZMod p) (GaloisField p 3)) := by
|
||
intro ⟨a, ha⟩
|
||
apply hα
|
||
exact ⟨a⁻¹, by rw [map_inv₀, ha, inv_inv]⟩
|
||
|
||
/-! ### Intersection dimension (geometric core of Sidon proof) -/
|
||
|
||
/-- When α ∉ GF(p), V ∩ α⁻¹V has dimension 1.
|
||
This is the key geometric fact for Singer's Sidon argument. -/
|
||
theorem finrank_inf_scaled_ker_trace (α : GaloisField p 3) (hα_ne : α ≠ 0)
|
||
(hα : α ∉ Set.range (algebraMap (ZMod p) (GaloisField p 3))) :
|
||
finrank (ZMod p) ↥((Algebra.trace (ZMod p) (GaloisField p 3)).ker ⊓
|
||
scaledSubmodule p α⁻¹ (inv_ne_zero hα_ne)
|
||
(Algebra.trace (ZMod p) (GaloisField p 3)).ker) = 1 := by
|
||
set V := (Algebra.trace (ZMod p) (GaloisField p 3)).ker
|
||
have hV2 : finrank (ZMod p) V = 2 := finrank_ker_trace p
|
||
have hαinv_ne := inv_ne_zero hα_ne
|
||
have hαinv_not_base := inv_not_in_range p α hα_ne hα
|
||
have hW2 : finrank (ZMod p) (scaledSubmodule p α⁻¹ hαinv_ne V) = 2 := by
|
||
rw [finrank_scaledSubmodule, hV2]
|
||
have hne : V ≠ scaledSubmodule p α⁻¹ hαinv_ne V :=
|
||
fun h => scaledSubmodule_ne_ker_trace p α⁻¹ hαinv_ne hαinv_not_base h.symm
|
||
exact finrank_inf_of_distinct_twodim p V _ hV2 hW2 hne
|
||
|
||
/-! ### Base units subgroup and index -/
|
||
|
||
/-- GF(p)× embedded in GF(p³)× via algebraMap. -/
|
||
noncomputable def baseUnitsSubgroup : Subgroup (GaloisField p 3)ˣ :=
|
||
(Units.map (algebraMap (ZMod p) (GaloisField p 3)).toMonoidHom).range
|
||
|
||
instance : (baseUnitsSubgroup p).Normal := inferInstance
|
||
|
||
private lemma units_map_injective :
|
||
Function.Injective (Units.map (algebraMap (ZMod p) (GaloisField p 3)).toMonoidHom) := by
|
||
apply Units.map_injective
|
||
exact (algebraMap (ZMod p) (GaloisField p 3)).injective
|
||
|
||
lemma baseUnitsSubgroup_card : Nat.card (baseUnitsSubgroup p) = p - 1 := by
|
||
exact (Nat.card_congr
|
||
((Units.map (algebraMap (ZMod p) (GaloisField p 3)).toMonoidHom).ofInjective
|
||
(units_map_injective p)).toEquiv.symm).trans
|
||
(by rw [Nat.card_units, Nat.card_zmod])
|
||
|
||
lemma gf3_units_card : Nat.card (GaloisField p 3)ˣ = p ^ 3 - 1 := by
|
||
rw [Nat.card_units, GaloisField.card p 3 (by norm_num)]
|
||
|
||
/-- The index [GF(p³)× : GF(p)×] = p²+p+1. -/
|
||
lemma baseUnitsSubgroup_index (hp' : Nat.Prime p) :
|
||
(baseUnitsSubgroup p).index = p ^ 2 + p + 1 := by
|
||
have hmul := Subgroup.card_mul_index (baseUnitsSubgroup p)
|
||
rw [baseUnitsSubgroup_card, gf3_units_card] at hmul
|
||
have hp1 : 0 < p - 1 := Nat.sub_pos_of_lt hp'.one_lt
|
||
have hfact : p ^ 3 - 1 = (p - 1) * (p ^ 2 + p + 1) := by
|
||
zify [Nat.one_le_pow 3 p hp'.pos, hp'.pos]; ring
|
||
rw [hfact] at hmul
|
||
exact Nat.eq_of_mul_eq_mul_left hp1 hmul
|
||
|
||
/-- Membership characterization: u ∈ baseUnitsSubgroup iff ↑u ∈ range(algebraMap). -/
|
||
lemma mem_baseUnitsSubgroup_iff (u : (GaloisField p 3)ˣ) :
|
||
u ∈ baseUnitsSubgroup p ↔
|
||
(↑u : GaloisField p 3) ∈ Set.range (algebraMap (ZMod p) (GaloisField p 3)) := by
|
||
simp only [baseUnitsSubgroup, MonoidHom.mem_range]
|
||
constructor
|
||
· rintro ⟨v, rfl⟩; exact ⟨v.val, by simp [Units.coe_map]⟩
|
||
· rintro ⟨a, ha⟩
|
||
have ha_ne : a ≠ 0 := by
|
||
intro h; simp [h] at ha; exact Units.ne_zero u ha.symm
|
||
exact ⟨Units.mk0 a ha_ne, Units.ext (by simp [Units.coe_map, ha])⟩
|
||
|
||
/-! ### Quotient Sidon property (Erdos30/SingerSidon.lean) -/
|
||
|
||
/-- Map a nonzero element of GF(p³) to its class in the quotient group
|
||
(GaloisField p 3)ˣ / baseUnitsSubgroup p. -/
|
||
noncomputable def singerMk (x : GaloisField p 3) (hx : x ≠ 0) :
|
||
(GaloisField p 3)ˣ ⧸ baseUnitsSubgroup p :=
|
||
QuotientGroup.mk (Units.mk0 x hx)
|
||
|
||
lemma singerMk_eq_iff (a b : GaloisField p 3) (ha : a ≠ 0) (hb : b ≠ 0) :
|
||
singerMk p a ha = singerMk p b hb ↔
|
||
a⁻¹ * b ∈ Set.range (algebraMap (ZMod p) (GaloisField p 3)) := by
|
||
unfold singerMk; rw [QuotientGroup.eq, mem_baseUnitsSubgroup_iff]
|
||
simp [Units.val_inv_eq_inv_val, Units.val_mul, Units.val_mk0]
|
||
|
||
private lemma proportional_of_finrank_one
|
||
(W : Submodule (ZMod p) (GaloisField p 3))
|
||
(hW : finrank (ZMod p) W = 1)
|
||
(w₁ w₂ : GaloisField p 3) (hw₁ : w₁ ∈ W) (hw₂ : w₂ ∈ W)
|
||
(hw₁_ne : w₁ ≠ 0) (hw₂_ne : w₂ ≠ 0) :
|
||
∃ c : ZMod p, c ≠ 0 ∧ w₂ = c • w₁ := by
|
||
have hsub : span (ZMod p) {w₁} ≤ W :=
|
||
span_le.mpr (Set.singleton_subset_iff.mpr hw₁)
|
||
have heq' : W = span (ZMod p) ({w₁} : Set (GaloisField p 3)) :=
|
||
(eq_of_le_of_finrank_le hsub (by rw [finrank_span_singleton hw₁_ne]; omega)).symm
|
||
have hmem : w₂ ∈ span (ZMod p) ({w₁} : Set (GaloisField p 3)) := heq' ▸ hw₂
|
||
rw [mem_span_singleton] at hmem
|
||
obtain ⟨c, hc⟩ := hmem
|
||
exact ⟨c, fun h => hw₂_ne (by simp [h] at hc; exact hc.symm), hc.symm⟩
|
||
|
||
/-- **Singer Sidon property in the quotient group.**
|
||
If u*v = α*(w*x) with u,v,w,x nonzero elements of ker(Tr) and α ∈ (ZMod p)×,
|
||
then in the quotient (GaloisField p 3)ˣ / (ZMod p)ˣ we have either
|
||
mk u = mk w ∧ mk v = mk x, or mk u = mk x ∧ mk v = mk w. -/
|
||
theorem singer_quotient_sidon
|
||
(u v w x : GaloisField p 3)
|
||
(hu : u ∈ (Algebra.trace (ZMod p) (GaloisField p 3)).ker)
|
||
(hv : v ∈ (Algebra.trace (ZMod p) (GaloisField p 3)).ker)
|
||
(hw : w ∈ (Algebra.trace (ZMod p) (GaloisField p 3)).ker)
|
||
(hx : x ∈ (Algebra.trace (ZMod p) (GaloisField p 3)).ker)
|
||
(hu0 : u ≠ 0) (hv0 : v ≠ 0) (hw0 : w ≠ 0) (hx0 : x ≠ 0)
|
||
(α : ZMod p) (hα : α ≠ 0)
|
||
(hmul : u * v = (algebraMap (ZMod p) (GaloisField p 3) α) * (w * x)) :
|
||
(singerMk p u hu0 = singerMk p w hw0 ∧ singerMk p v hv0 = singerMk p x hx0) ∨
|
||
(singerMk p u hu0 = singerMk p x hx0 ∧ singerMk p v hv0 = singerMk p w hw0) := by
|
||
set V := (Algebra.trace (ZMod p) (GaloisField p 3)).ker
|
||
have hαF_ne : (algebraMap (ZMod p) (GaloisField p 3) α) ≠ 0 := by simp [hα]
|
||
have hβ_ne : u * w⁻¹ ≠ 0 := mul_ne_zero hu0 (inv_ne_zero hw0)
|
||
have h_key : (u * w⁻¹) * v = (algebraMap (ZMod p) (GaloisField p 3) α) * x := by
|
||
have h := hmul; field_simp at h ⊢; linear_combination h
|
||
by_cases hβ_base : (u * w⁻¹) ∈ Set.range (algebraMap (ZMod p) (GaloisField p 3))
|
||
case pos =>
|
||
left; constructor
|
||
· rw [singerMk_eq_iff]; obtain ⟨c, hc⟩ := hβ_base
|
||
refine ⟨c⁻¹, ?_⟩
|
||
simp only [map_inv₀]; rw [hc]; field_simp
|
||
· rw [singerMk_eq_iff]; obtain ⟨c, hc⟩ := hβ_base
|
||
have hcF_ne : (algebraMap (ZMod p) (GaloisField p 3) c) ≠ 0 :=
|
||
fun heq => hβ_ne (by rw [← hc, heq])
|
||
refine ⟨α⁻¹ * c, ?_⟩
|
||
simp only [map_mul, map_inv₀]
|
||
have h := h_key; rw [← hc] at h
|
||
generalize algebraMap (ZMod p) (GaloisField p 3) α = αF at h hαF_ne ⊢
|
||
generalize algebraMap (ZMod p) (GaloisField p 3) c = cF at h hcF_ne ⊢
|
||
field_simp; linear_combination h
|
||
case neg =>
|
||
right
|
||
have h1dim : finrank (ZMod p) ↥(V ⊓ scaledSubmodule p (u * w⁻¹)⁻¹ (inv_ne_zero hβ_ne) V) = 1 :=
|
||
finrank_inf_scaled_ker_trace p (u * w⁻¹) hβ_ne hβ_base
|
||
have hw_inf : w ∈ V ⊓ scaledSubmodule p (u * w⁻¹)⁻¹ (inv_ne_zero hβ_ne) V := by
|
||
refine Submodule.mem_inf.mpr ⟨hw, ?_⟩
|
||
rw [mem_scaledSubmodule_iff]
|
||
exact ⟨u, hu, by field_simp⟩
|
||
have hv_inf : v ∈ V ⊓ scaledSubmodule p (u * w⁻¹)⁻¹ (inv_ne_zero hβ_ne) V := by
|
||
refine Submodule.mem_inf.mpr ⟨hv, ?_⟩
|
||
rw [mem_scaledSubmodule_iff]
|
||
refine ⟨(u * w⁻¹) * v, ?_, by field_simp⟩
|
||
rw [h_key, show (algebraMap (ZMod p) (GaloisField p 3) α) * x = α • x
|
||
from (Algebra.smul_def α x).symm]
|
||
exact V.smul_mem α hx
|
||
obtain ⟨c, hc_ne, hvc⟩ := proportional_of_finrank_one p _ h1dim w v hw_inf hv_inf hw0 hv0
|
||
have hcF_ne : (algebraMap (ZMod p) (GaloisField p 3) c) ≠ 0 := by simp [hc_ne]
|
||
have hvc' : v = (algebraMap (ZMod p) (GaloisField p 3) c) * w := by
|
||
rw [hvc, Algebra.smul_def]
|
||
have hcu : (algebraMap (ZMod p) (GaloisField p 3) c) * u =
|
||
(algebraMap (ZMod p) (GaloisField p 3) α) * x := by
|
||
have h := h_key; rw [hvc'] at h
|
||
generalize algebraMap (ZMod p) (GaloisField p 3) α = αF at h hαF_ne ⊢
|
||
generalize algebraMap (ZMod p) (GaloisField p 3) c = cF at h hcF_ne hvc' ⊢
|
||
field_simp at h ⊢; linear_combination h
|
||
constructor
|
||
· rw [singerMk_eq_iff]; refine ⟨c * α⁻¹, ?_⟩
|
||
simp only [map_mul, map_inv₀]
|
||
generalize algebraMap (ZMod p) (GaloisField p 3) α = αF at hαF_ne hcu ⊢
|
||
generalize algebraMap (ZMod p) (GaloisField p 3) c = cF at hcF_ne hcu ⊢
|
||
field_simp; linear_combination hcu
|
||
· rw [singerMk_eq_iff]; refine ⟨c⁻¹, ?_⟩
|
||
simp only [map_inv₀]
|
||
rw [hvc']
|
||
generalize algebraMap (ZMod p) (GaloisField p 3) c = cF at hcF_ne ⊢
|
||
field_simp
|
||
|
||
/-! ### Combinatorial bridge (Erdos30/SingerTheorem.lean) -/
|
||
|
||
noncomputable section
|
||
|
||
private abbrev V' := (Algebra.trace (ZMod p) (GaloisField p 3)).ker
|
||
private abbrev Q' := (GaloisField p 3)ˣ ⧸ baseUnitsSubgroup p
|
||
|
||
private def kerBasis' :=
|
||
(Module.finBasis (ZMod p) ↥(V' p)).reindex
|
||
((Fin.castOrderIso (finrank_ker_trace p)).toEquiv)
|
||
|
||
private def repV (i : Option (ZMod p)) : V' p :=
|
||
match i with
|
||
| none => (kerBasis' p) ⟨0, by omega⟩
|
||
| some c => (kerBasis' p) ⟨1, by omega⟩ + c • (kerBasis' p) ⟨0, by omega⟩
|
||
|
||
private def rep (i : Option (ZMod p)) : GaloisField p 3 := (repV p i).val
|
||
|
||
private lemma rep_mem (i : Option (ZMod p)) :
|
||
rep p i ∈ (Algebra.trace (ZMod p) (GaloisField p 3)).ker := (repV p i).2
|
||
|
||
private lemma rep_ne_zero (i : Option (ZMod p)) : rep p i ≠ 0 := by
|
||
intro h; have hV : repV p i = 0 := Subtype.ext h
|
||
cases i with
|
||
| none => exact (kerBasis' p).ne_zero ⟨0, by omega⟩ hV
|
||
| some c =>
|
||
have heq := congr_arg (kerBasis' p).repr hV
|
||
simp only [repV, map_add, map_smul, (kerBasis' p).repr_self, map_zero] at heq
|
||
have h1 := DFunLike.congr_fun heq ⟨1, by omega⟩
|
||
simp only [Finsupp.add_apply, Finsupp.smul_apply, Finsupp.single_apply, smul_eq_mul,
|
||
Finsupp.zero_apply,
|
||
show (⟨1, by omega⟩ : Fin 2) = (⟨1, by omega⟩ : Fin 2) from rfl,
|
||
show ((⟨0, by omega⟩ : Fin 2) = (⟨1, by omega⟩ : Fin 2)) = False from by simp [Fin.ext_iff],
|
||
ite_true, ite_false, mul_zero, add_zero] at h1
|
||
exact one_ne_zero h1
|
||
|
||
private lemma rep_proportional_imp_eq (i j : Option (ZMod p)) (α : ZMod p)
|
||
(hprop : repV p j = α • repV p i) : i = j := by
|
||
have heq := congr_arg (kerBasis' p).repr hprop
|
||
cases i with
|
||
| none =>
|
||
cases j with
|
||
| none => rfl
|
||
| some c =>
|
||
simp only [repV, map_add, map_smul, (kerBasis' p).repr_self] at heq
|
||
have h1 := DFunLike.congr_fun heq ⟨1, by omega⟩
|
||
simp only [Finsupp.add_apply, Finsupp.smul_apply, Finsupp.single_apply, smul_eq_mul,
|
||
show (⟨1, by omega⟩ : Fin 2) = (⟨1, by omega⟩ : Fin 2) from rfl,
|
||
show ((⟨0, by omega⟩ : Fin 2) = (⟨1, by omega⟩ : Fin 2)) = False from by simp [Fin.ext_iff],
|
||
ite_true, ite_false, mul_zero, add_zero, mul_one] at h1
|
||
exact absurd h1 one_ne_zero
|
||
| some a =>
|
||
cases j with
|
||
| none =>
|
||
simp only [repV, map_add, map_smul, (kerBasis' p).repr_self] at heq
|
||
have h1 := DFunLike.congr_fun heq ⟨1, by omega⟩
|
||
simp only [Finsupp.add_apply, Finsupp.smul_apply, Finsupp.single_apply, smul_eq_mul,
|
||
show (⟨1, by omega⟩ : Fin 2) = (⟨1, by omega⟩ : Fin 2) from rfl,
|
||
show ((⟨0, by omega⟩ : Fin 2) = (⟨1, by omega⟩ : Fin 2)) = False from by simp [Fin.ext_iff],
|
||
ite_true, ite_false, mul_zero, add_zero, mul_one] at h1
|
||
exfalso; exact rep_ne_zero p none (show rep p none = 0 from by
|
||
show (repV p none).val = 0
|
||
have := hprop; rw [show α = 0 from h1.symm, zero_smul] at this
|
||
exact congrArg Subtype.val this)
|
||
| some b =>
|
||
simp only [repV, map_add, map_smul, (kerBasis' p).repr_self] at heq
|
||
have h1 := DFunLike.congr_fun heq ⟨1, by omega⟩
|
||
have h0 := DFunLike.congr_fun heq ⟨0, by omega⟩
|
||
simp only [Finsupp.add_apply, Finsupp.smul_apply, Finsupp.single_apply, smul_eq_mul,
|
||
show (⟨1, by omega⟩ : Fin 2) = (⟨1, by omega⟩ : Fin 2) from rfl,
|
||
show ((⟨0, by omega⟩ : Fin 2) = (⟨1, by omega⟩ : Fin 2)) = False from by simp [Fin.ext_iff],
|
||
show (⟨0, by omega⟩ : Fin 2) = (⟨0, by omega⟩ : Fin 2) from rfl,
|
||
show ((⟨1, by omega⟩ : Fin 2) = (⟨0, by omega⟩ : Fin 2)) = False from by simp [Fin.ext_iff],
|
||
ite_true, ite_false, mul_zero, add_zero, mul_one, zero_add] at h1 h0
|
||
congr 1; rw [← h1, one_mul] at h0; exact h0.symm
|
||
|
||
private lemma singerMk_rep_injective :
|
||
Function.Injective (fun i => singerMk p (rep p i) (rep_ne_zero p i)) := by
|
||
intro i j hij
|
||
rw [singerMk_eq_iff] at hij
|
||
obtain ⟨α, hα⟩ := hij
|
||
have hri := rep_ne_zero p i
|
||
have hprop_field : rep p j = (algebraMap (ZMod p) (GaloisField p 3) α) * rep p i := by
|
||
have h1 : (rep p i) * ((rep p i)⁻¹ * rep p j) = rep p j := by
|
||
rw [← mul_assoc, mul_inv_cancel₀ hri, one_mul]
|
||
rw [← h1, hα]; ring
|
||
have hV : repV p j = α • repV p i := by
|
||
apply Subtype.ext
|
||
change rep p j = (α • repV p i).val
|
||
rw [show (α • repV p i).val = α • (repV p i).val from rfl]
|
||
rw [show α • (repV p i).val = (algebraMap (ZMod p) (GaloisField p 3) α) * (repV p i).val
|
||
from Algebra.smul_def α _]
|
||
exact hprop_field
|
||
exact rep_proportional_imp_eq p i j α hV
|
||
|
||
/-! ### Cyclic group isomorphism -/
|
||
|
||
private lemma Q_card_eq (hp' : Nat.Prime p) : Nat.card (Q' p) = p ^ 2 + p + 1 := by
|
||
rw [show Nat.card (Q' p) = (baseUnitsSubgroup p).index from
|
||
(Subgroup.index_eq_card _).symm]
|
||
exact baseUnitsSubgroup_index p hp'
|
||
|
||
private noncomputable def mulEquivQ (hp' : Nat.Prime p) :
|
||
Multiplicative (ZMod (p ^ 2 + p + 1)) ≃* Q' p := by
|
||
haveI : NeZero (p ^ 2 + p + 1) := ⟨by omega⟩
|
||
haveI : IsCyclic (Q' p) :=
|
||
isCyclic_of_surjective (QuotientGroup.mk' (baseUnitsSubgroup p))
|
||
(QuotientGroup.mk'_surjective _)
|
||
let g := Classical.choose (IsCyclic.exists_generator (α := Q' p))
|
||
have hg : ∀ x : Q' p, x ∈ Subgroup.zpowers g :=
|
||
Classical.choose_spec (IsCyclic.exists_generator (α := Q' p))
|
||
have htop : Subgroup.zpowers g = ⊤ := by ext x; exact ⟨fun _ => trivial, fun _ => hg x⟩
|
||
have hord : orderOf g = p ^ 2 + p + 1 := by
|
||
have h1 : Nat.card ↥(Subgroup.zpowers g) = orderOf g := Nat.card_zpowers g
|
||
have h2 : Nat.card ↥(Subgroup.zpowers g) = Nat.card (Q' p) := by
|
||
rw [htop]; exact Nat.card_congr Subgroup.topEquiv.toEquiv
|
||
have := Q_card_eq p hp'; omega
|
||
let φ : Multiplicative (ZMod (p ^ 2 + p + 1)) →* Q' p :=
|
||
MonoidHom.mk' (fun k => g ^ (ZMod.val (Multiplicative.toAdd k))) (fun a b => by
|
||
show g ^ ZMod.val (Multiplicative.toAdd a + Multiplicative.toAdd b) =
|
||
g ^ ZMod.val (Multiplicative.toAdd a) * g ^ ZMod.val (Multiplicative.toAdd b)
|
||
rw [← pow_add, pow_eq_pow_iff_modEq, hord]
|
||
unfold Nat.ModEq; rw [ZMod.val_add]
|
||
exact Nat.mod_mod_of_dvd _ (dvd_refl _))
|
||
have hφ_apply : ∀ k, φ k = g ^ (ZMod.val (Multiplicative.toAdd k)) := fun _ => rfl
|
||
exact MulEquiv.ofBijective φ ⟨by
|
||
intro a b hab
|
||
have hab' : g ^ (ZMod.val (Multiplicative.toAdd a)) =
|
||
g ^ (ZMod.val (Multiplicative.toAdd b)) := by rw [← hφ_apply, ← hφ_apply]; exact hab
|
||
have hinj := @pow_injOn_Iio_orderOf (Q' p) _ g
|
||
have ha : ZMod.val (Multiplicative.toAdd a) ∈ Set.Iio (orderOf g) := by
|
||
rw [Set.mem_Iio, hord]; exact ZMod.val_lt _
|
||
have hb : ZMod.val (Multiplicative.toAdd b) ∈ Set.Iio (orderOf g) := by
|
||
rw [Set.mem_Iio, hord]; exact ZMod.val_lt _
|
||
cases a; cases b; exact congrArg _ (ZMod.val_injective _ (hinj ha hb hab')),
|
||
by
|
||
intro x
|
||
obtain ⟨m, hm⟩ := (hg x : ∃ m : ℤ, g ^ m = x)
|
||
have hpos : (0 : ℤ) < ((p ^ 2 + p + 1 : ℕ) : ℤ) := by positivity
|
||
have hmod_nn : 0 ≤ m % ((p ^ 2 + p + 1 : ℕ) : ℤ) := Int.emod_nonneg _ (by linarith)
|
||
have hmod_lt : (m % ((p ^ 2 + p + 1 : ℕ) : ℤ)).toNat < p ^ 2 + p + 1 := by
|
||
have := Int.emod_lt_of_pos m hpos; omega
|
||
let k : Multiplicative (ZMod (p ^ 2 + p + 1)) :=
|
||
Multiplicative.ofAdd ((m % ((p ^ 2 + p + 1 : ℕ) : ℤ)).toNat : ZMod (p ^ 2 + p + 1))
|
||
refine ⟨k, ?_⟩
|
||
have hφk : φ k = g ^ (m % ((p ^ 2 + p + 1 : ℕ) : ℤ)).toNat := by
|
||
rw [hφ_apply]; congr 1; exact ZMod.val_natCast_of_lt hmod_lt
|
||
have key : g ^ ((m % ((p ^ 2 + p + 1 : ℕ) : ℤ)).toNat : ℤ) = g ^ m := by
|
||
rw [zpow_eq_zpow_iff_modEq, hord]
|
||
change ((m % ((p ^ 2 + p + 1 : ℕ) : ℤ)).toNat : ℤ) % ((p ^ 2 + p + 1 : ℕ) : ℤ) =
|
||
m % ((p ^ 2 + p + 1 : ℕ) : ℤ)
|
||
rw [Int.toNat_of_nonneg hmod_nn, Int.emod_emod_of_dvd _ dvd_rfl]
|
||
calc φ k = g ^ (m % ((p ^ 2 + p + 1 : ℕ) : ℤ)).toNat := hφk
|
||
_ = g ^ ((m % ((p ^ 2 + p + 1 : ℕ) : ℤ)).toNat : ℤ) := (zpow_natCast g _).symm
|
||
_ = g ^ m := key
|
||
_ = x := hm⟩
|
||
|
||
/-! ### Finset construction and IsSidonMod proof -/
|
||
|
||
set_option maxHeartbeats 200000000 in
|
||
/-- The Singer Sidon set: a Finset ℤ of size p+1 that is IsSidonMod (p²+p+1). -/
|
||
theorem singer_sidon_set_of (hp' : Nat.Prime p) :
|
||
∃ S : Finset ℤ, IsSidonMod (↑p * ↑p + ↑p + 1 : ℤ) S ∧ S.card = p + 1 := by
|
||
haveI : NeZero (p ^ 2 + p + 1) := ⟨by omega⟩
|
||
-- Cyclic isomorphism
|
||
let φ := mulEquivQ p hp'
|
||
-- Map each representative to its ZMod coordinate via φ⁻¹
|
||
let f : Option (ZMod p) → ℤ := fun i =>
|
||
↑(ZMod.val (Multiplicative.toAdd (φ.symm (singerMk p (rep p i) (rep_ne_zero p i)))))
|
||
let S : Finset ℤ := Finset.univ.image f
|
||
refine ⟨S, ?_, ?_⟩
|
||
· -- IsSidonMod
|
||
intro a b c d ha hb hc hd hdvd
|
||
-- a, b, c, d ∈ S = image of f
|
||
rw [Finset.mem_image] at ha hb hc hd
|
||
obtain ⟨ia, _, rfl⟩ := ha; obtain ⟨ib, _, rfl⟩ := hb
|
||
obtain ⟨ic, _, rfl⟩ := hc; obtain ⟨id, _, rfl⟩ := hd
|
||
-- Abbreviations for the four quotient elements
|
||
set qa := singerMk p (rep p ia) (rep_ne_zero p ia)
|
||
set qb := singerMk p (rep p ib) (rep_ne_zero p ib)
|
||
set qc := singerMk p (rep p ic) (rep_ne_zero p ic)
|
||
set qd := singerMk p (rep p id) (rep_ne_zero p id)
|
||
-- Step 1: divisibility → ZMod equality
|
||
have hzmod : Multiplicative.toAdd (φ.symm qa) + Multiplicative.toAdd (φ.symm qb) =
|
||
Multiplicative.toAdd (φ.symm qc) + Multiplicative.toAdd (φ.symm qd) := by
|
||
have h0 : ((((ZMod.val (Multiplicative.toAdd (φ.symm qa)) : ℤ) +
|
||
(ZMod.val (Multiplicative.toAdd (φ.symm qb)) : ℤ)) -
|
||
((ZMod.val (Multiplicative.toAdd (φ.symm qc)) : ℤ) +
|
||
(ZMod.val (Multiplicative.toAdd (φ.symm qd)) : ℤ)) : ℤ) : ZMod (p ^ 2 + p + 1)) = 0 := by
|
||
rw [ZMod.intCast_zmod_eq_zero_iff_dvd]
|
||
convert hdvd using 1
|
||
push_cast; ring
|
||
simp only [Int.cast_sub, Int.cast_add, Int.cast_natCast, ZMod.natCast_zmod_val] at h0
|
||
exact sub_eq_zero.mp h0
|
||
-- Step 2: ZMod equality → Multiplicative equality → Q' product equality
|
||
have hQ : qa * qb = qc * qd := by
|
||
have hmult : φ.symm qa * φ.symm qb = φ.symm qc * φ.symm qd := by
|
||
show Multiplicative.ofAdd (Multiplicative.toAdd (φ.symm qa) +
|
||
Multiplicative.toAdd (φ.symm qb)) =
|
||
Multiplicative.ofAdd (Multiplicative.toAdd (φ.symm qc) +
|
||
Multiplicative.toAdd (φ.symm qd))
|
||
exact congrArg _ hzmod
|
||
have hφ := congrArg φ hmult
|
||
simp only [map_mul, MulEquiv.apply_symm_apply] at hφ
|
||
exact hφ
|
||
-- Step 3: Products become singerMk of field products
|
||
have hmul_l : qa * qb = singerMk p (rep p ia * rep p ib)
|
||
(mul_ne_zero (rep_ne_zero p ia) (rep_ne_zero p ib)) := by
|
||
show QuotientGroup.mk (Units.mk0 _ _) * QuotientGroup.mk (Units.mk0 _ _) =
|
||
QuotientGroup.mk (Units.mk0 _ _)
|
||
rw [← QuotientGroup.mk_mul]; congr 1; ext; rfl
|
||
have hmul_r : qc * qd = singerMk p (rep p ic * rep p id)
|
||
(mul_ne_zero (rep_ne_zero p ic) (rep_ne_zero p id)) := by
|
||
show QuotientGroup.mk (Units.mk0 _ _) * QuotientGroup.mk (Units.mk0 _ _) =
|
||
QuotientGroup.mk (Units.mk0 _ _)
|
||
rw [← QuotientGroup.mk_mul]; congr 1; ext; rfl
|
||
-- Step 4: singerMk equality → algebraMap factor via singerMk_eq_iff
|
||
rw [hmul_l, hmul_r] at hQ
|
||
rw [singerMk_eq_iff] at hQ
|
||
obtain ⟨α, hα⟩ := hQ
|
||
have hab_ne : rep p ia * rep p ib ≠ 0 := mul_ne_zero (rep_ne_zero p ia) (rep_ne_zero p ib)
|
||
have hcd_ne : rep p ic * rep p id ≠ 0 := mul_ne_zero (rep_ne_zero p ic) (rep_ne_zero p id)
|
||
have hα_ne : α ≠ 0 := by
|
||
intro h0; rw [h0, map_zero] at hα
|
||
exact mul_ne_zero (inv_ne_zero hab_ne) hcd_ne hα.symm
|
||
have hcd_eq : rep p ic * rep p id =
|
||
(algebraMap (ZMod p) (GaloisField p 3)) α * (rep p ia * rep p ib) := by
|
||
calc rep p ic * rep p id
|
||
= (rep p ia * rep p ib) * ((rep p ia * rep p ib)⁻¹ * (rep p ic * rep p id)) := by
|
||
rw [← mul_assoc, mul_inv_cancel₀ hab_ne, one_mul]
|
||
_ = (rep p ia * rep p ib) * (algebraMap (ZMod p) (GaloisField p 3)) α := by rw [hα]
|
||
_ = (algebraMap (ZMod p) (GaloisField p 3)) α * (rep p ia * rep p ib) := mul_comm _ _
|
||
-- Step 5: Apply singer_quotient_sidon
|
||
have hsq := singer_quotient_sidon p (rep p ic) (rep p id) (rep p ia) (rep p ib)
|
||
(rep_mem p ic) (rep_mem p id) (rep_mem p ia) (rep_mem p ib)
|
||
(rep_ne_zero p ic) (rep_ne_zero p id) (rep_ne_zero p ia) (rep_ne_zero p ib)
|
||
α hα_ne hcd_eq
|
||
-- Step 6: From singerMk equality to index equality via injectivity
|
||
cases hsq with
|
||
| inl h =>
|
||
left; constructor
|
||
· exact congrArg f (singerMk_rep_injective p h.1.symm)
|
||
· exact congrArg f (singerMk_rep_injective p h.2.symm)
|
||
| inr h =>
|
||
right; constructor
|
||
· exact congrArg f (singerMk_rep_injective p h.2.symm)
|
||
· exact congrArg f (singerMk_rep_injective p h.1.symm)
|
||
· -- card S = p + 1
|
||
rw [Finset.card_image_of_injective _ (by
|
||
intro i j hij
|
||
-- f(i) = f(j) means val(toAdd(φ⁻¹(singerMk(rep i)))) = val(toAdd(φ⁻¹(singerMk(rep j))))
|
||
-- nat→int cast is injective, val is injective, toAdd is bijective, φ⁻¹ is bijective
|
||
-- So singerMk(rep i) = singerMk(rep j), hence i = j by singerMk_rep_injective
|
||
have h1 : (ZMod.val (Multiplicative.toAdd (φ.symm (singerMk p (rep p i) (rep_ne_zero p i)))) : ℤ) =
|
||
↑(ZMod.val (Multiplicative.toAdd (φ.symm (singerMk p (rep p j) (rep_ne_zero p j))))) := hij
|
||
have h2 := Nat.cast_injective h1
|
||
have h3 := ZMod.val_injective _ h2
|
||
-- h3 : toAdd(φ⁻¹(singerMk(rep i))) = toAdd(φ⁻¹(singerMk(rep j)))
|
||
have h4 : φ.symm (singerMk p (rep p i) (rep_ne_zero p i)) =
|
||
φ.symm (singerMk p (rep p j) (rep_ne_zero p j)) :=
|
||
Multiplicative.toAdd.injective h3
|
||
have h5 := φ.symm.injective h4
|
||
exact singerMk_rep_injective p h5)]
|
||
simp [Finset.card_univ, Fintype.card_option, ZMod.card]
|
||
|
||
end
|
||
end Singer
|
||
|
||
/-- **Singer's theorem.** For each prime p, there exists a Sidon set
|
||
modulo p² + p + 1 of cardinality p + 1.
|
||
|
||
This is the classical algebraic construction using the trace kernel
|
||
of GF(p³)/GF(p). The proof proceeds through:
|
||
1. Construction of GF(p) and its degree-3 extension GF(p³)
|
||
2. Analysis of ker(Tr) as a 2-dimensional subspace
|
||
3. Geometric argument via subspace intersections
|
||
4. Transfer from quotient multiplication to modular integer addition
|
||
|
||
Reference: Singer, J. (1938). A theorem in finite projective geometry
|
||
and some applications. *Trans. Amer. Math. Soc.*, 43, 377–385. -/
|
||
theorem singer_sidon_set (p : ℕ) (hp : Nat.Prime p) :
|
||
∃ S : Finset ℤ, IsSidonMod (↑p * ↑p + ↑p + 1 : ℤ) S ∧ S.card = p + 1 := by
|
||
haveI : Fact (Nat.Prime p) := ⟨hp⟩
|
||
exact Singer.singer_sidon_set_of p hp
|
||
|
||
/-- The Singer family hypothesis: for every prime p, there exists a
|
||
Sidon set mod (p²+p+1) of size p+1. -/
|
||
def SingerFamilyHypothesis : Prop :=
|
||
∀ p : ℕ, Nat.Prime p →
|
||
∃ S : Finset ℤ, IsSidonMod (↑p * ↑p + ↑p + 1 : ℤ) S ∧ S.card = p + 1
|
||
|
||
/-- Singer's theorem establishes the Singer family hypothesis. -/
|
||
theorem singerFamilyHypothesis_holds : SingerFamilyHypothesis :=
|
||
fun p hp => singer_sidon_set p hp
|
||
|
||
/-! ## Unconditional h(N) = Θ(√N) Bounds -/
|
||
|
||
/-- Bounded-lift lemma: an IsSidonMod M set whose elements all lie in [0, M-1]
|
||
is automatically an IsSidon set in ℤ (no wraparound can occur).
|
||
|
||
Proof: If a+b = c+d + M, then a+b ≡ c+d (mod M), so IsSidonMod gives
|
||
{a,b} = {c,d}. But then a+b = a+b + M ⇒ M = 0 — contradiction.
|
||
Therefore a+b = c+d in ℤ, which is the Sidon property. -/
|
||
theorem IsSidonMod.isSidon_of_bounded {M : ℤ} {S : Finset ℤ}
|
||
(hS : IsSidonMod M S) (h_bound : ∀ x ∈ S, 0 ≤ x ∧ x < M) : IsSidon S := by
|
||
intro a b c d ha hb hc hd hsum
|
||
have ha_bound := h_bound a ha; have hb_bound := h_bound b hb
|
||
have hc_bound := h_bound c hc; have hd_bound := h_bound d hd
|
||
have ha_nonneg : 0 ≤ a := ha_bound.1; have ha_lt : a < M := ha_bound.2
|
||
have hb_nonneg : 0 ≤ b := hb_bound.1; have hb_lt : b < M := hb_bound.2
|
||
have hc_nonneg : 0 ≤ c := hc_bound.1; have hc_lt : c < M := hc_bound.2
|
||
have hd_nonneg : 0 ≤ d := hd_bound.1; have hd_lt : d < M := hd_bound.2
|
||
-- From IsSidonMod, a+b ≡ c+d (mod M)
|
||
have hmod : M ∣ (a + b) - (c + d) := by
|
||
-- hsum states a + b = c + d in ℤ, so (a+b) - (c+d) = 0 which is divisible by M
|
||
rw [hsum, sub_self]
|
||
exact dvd_zero M
|
||
-- If a+b = c+d, Sidon property follows directly
|
||
rcases hS ha hb hc hd hmod with (⟨hac, hbd⟩ | ⟨had, hbc⟩)
|
||
· left; exact ⟨hac, hbd⟩
|
||
· right; exact ⟨had, hbc⟩
|
||
|
||
|
||
|
||
/-- The Sidon maximum is positive for N ≥ 1. -/
|
||
theorem sidonMaximum_pos (N : ℕ) (hN : 1 ≤ N) : 1 ≤ sidonMaximum N := by
|
||
have hmax := sidonMaximum_isSidonMaximum N
|
||
have hSidon : IsSidon ({1} : Finset ℤ) := by
|
||
intro a b c d ha hb hc hd _; simp at ha hb hc hd
|
||
left; exact ⟨ha ▸ hc.symm, hb ▸ hd.symm⟩
|
||
have h1 : IsIntervalSidon (N : ℤ) ({1} : Finset ℤ) := by
|
||
constructor
|
||
· intro x hx; simp at hx; subst hx; exact ⟨le_refl 1, by exact_mod_cast hN⟩
|
||
· exact hSidon
|
||
have hle := hmax.2 h1; simp at hle; exact hle
|
||
|
||
/-- The Sidon maximum function is monotone non-decreasing. -/
|
||
theorem sidonMaximum_mono {N M : ℕ} (hNM : N ≤ M) :
|
||
sidonMaximum N ≤ sidonMaximum M := by
|
||
have hmax_N := sidonMaximum_isSidonMaximum N
|
||
have hmax_M := sidonMaximum_isSidonMaximum M
|
||
rcases hmax_N.1 with ⟨A, hA, hAcard⟩
|
||
have hA_M : IsIntervalSidon (M : ℤ) A := hA.mono (by exact_mod_cast hNM)
|
||
have hle := hmax_M.2 hA_M; omega
|
||
|
||
/-! ## Erdős Problem 30 Statement -/
|
||
|
||
/-- The formal Erdős Problem 30 statement: h(N) = √N + O_ε(N^ε) for every ε > 0. -/
|
||
def Erdos30Statement : Prop :=
|
||
∀ ε : ℝ, 0 < ε →
|
||
∃ C : ℝ, ∃ N0 : ℕ,
|
||
0 ≤ C ∧
|
||
∀ {N h : ℕ}, N0 ≤ N → IsSidonMaximum N h →
|
||
abs ((h : ℝ) - Real.sqrt (N : ℝ)) ≤ C * Real.rpow (N : ℝ) ε
|
||
|
||
/-- **Partial discharge for ε ≥ 1/2** (unconditional).
|
||
For all ε ≥ 1/2, |h(N) - √N| ≤ 2·N^ε for all N ≥ 5. -/
|
||
theorem erdos30_partial_half :
|
||
∀ ε : ℝ, (1 : ℝ) / 2 ≤ ε → 0 < ε →
|
||
∃ C : ℝ, ∃ N0 : ℕ,
|
||
0 ≤ C ∧
|
||
∀ {N h : ℕ}, N0 ≤ N → IsSidonMaximum N h →
|
||
abs ((h : ℝ) - Real.sqrt (N : ℝ)) ≤ C * Real.rpow (N : ℝ) ε :=
|
||
by
|
||
intro ε hε_ge_half hε_pos
|
||
have h_two_nonneg : 0 ≤ (2 : ℝ) := by norm_num
|
||
have hC_nonneg : 0 ≤ Real.sqrt 2 := Real.sqrt_nonneg _
|
||
refine ⟨Real.sqrt 2, 1, hC_nonneg, ?_⟩
|
||
intro N h hN1 hmax
|
||
have hN_pos : 1 ≤ N := hN1
|
||
have hN_pos_real : (1 : ℝ) ≤ (N : ℝ) := by exact_mod_cast hN_pos
|
||
-- Quadratic upper bound: h ≤ √(2N) + 1
|
||
have h_bound_nat : h ≤ Nat.sqrt (2 * N) + 1 := by
|
||
rcases hmax.1 with ⟨A, hA, hAcard⟩
|
||
have hcard := hA.card_le hN_pos
|
||
rw [hAcard] at hcard
|
||
exact hcard
|
||
have h_bound_real : (h : ℝ) ≤ (Nat.sqrt (2 * N) : ℝ) + 1 := by exact_mod_cast h_bound_nat
|
||
-- (Nat.sqrt (2*N) : ℝ) ≤ Real.sqrt (2*(N:ℝ))
|
||
have h_sqrt_nat_sq : (Nat.sqrt (2 * N) : ℝ) * (Nat.sqrt (2 * N) : ℝ) ≤ 2 * (N : ℝ) := by
|
||
have h_sq_nat : (Nat.sqrt (2 * N)) * (Nat.sqrt (2 * N)) ≤ 2 * N :=
|
||
(Nat.le_sqrt.1 (le_refl (Nat.sqrt (2 * N))))
|
||
exact_mod_cast h_sq_nat
|
||
have h_nat_sqrt_nonneg : 0 ≤ (Nat.sqrt (2 * N) : ℝ) := by exact_mod_cast Nat.zero_le _
|
||
have h_nat_sqrt_le_real_sqrt : (Nat.sqrt (2 * N) : ℝ) ≤ Real.sqrt (2 * (N : ℝ)) := by
|
||
calc
|
||
(Nat.sqrt (2 * N) : ℝ) = Real.sqrt (((Nat.sqrt (2 * N) : ℝ)) * ((Nat.sqrt (2 * N) : ℝ))) := by
|
||
rw [Real.sqrt_mul_self h_nat_sqrt_nonneg]
|
||
_ ≤ Real.sqrt (2 * (N : ℝ)) := Real.sqrt_le_sqrt h_sqrt_nat_sq
|
||
have h_upper_real_sqrt : (h : ℝ) ≤ Real.sqrt (2 * (N : ℝ)) + 1 := by
|
||
linarith
|
||
have h_pos_nat : 1 ≤ h := by
|
||
have h_eq : h = sidonMaximum N :=
|
||
isSidonMaximum_unique hmax (sidonMaximum_isSidonMaximum N)
|
||
rw [h_eq]; exact sidonMaximum_pos N hN_pos
|
||
have h_lower_one : (1 : ℝ) ≤ (h : ℝ) := by exact_mod_cast h_pos_nat
|
||
have h_N_ge_one_sqrt : 1 ≤ Real.sqrt (N : ℝ) := by
|
||
calc
|
||
(1 : ℝ) = Real.sqrt ((1 : ℝ)) := by norm_num
|
||
_ ≤ Real.sqrt (N : ℝ) := Real.sqrt_le_sqrt (by exact_mod_cast hN_pos)
|
||
have h_sqrt_eq_rpow : Real.sqrt (N : ℝ) = Real.rpow (N : ℝ) ((1 : ℝ) / 2) :=
|
||
Real.sqrt_eq_rpow _
|
||
have h_sqrt_N_le_N_pow_eps : Real.sqrt (N : ℝ) ≤ Real.rpow (N : ℝ) ε := by
|
||
rw [h_sqrt_eq_rpow]
|
||
exact Real.rpow_le_rpow_of_exponent_le hN_pos_real hε_ge_half
|
||
have h_one_le_N_pow_eps : (1 : ℝ) ≤ Real.rpow (N : ℝ) ε := by
|
||
have : (1 : ℝ) ^ ε = (1 : ℝ) := by simp
|
||
have h_rpow_mono : (1 : ℝ) ^ ε ≤ (N : ℝ) ^ ε :=
|
||
Real.rpow_le_rpow (by norm_num) hN_pos_real (hε_pos.le)
|
||
simpa [this] using h_rpow_mono
|
||
have ha_nonneg : 0 ≤ Real.sqrt 2 - 1 := by
|
||
have : 1 ≤ Real.sqrt 2 := by
|
||
calc
|
||
(1 : ℝ) = Real.sqrt (1 : ℝ) := by norm_num
|
||
_ ≤ Real.sqrt 2 := Real.sqrt_le_sqrt (by norm_num)
|
||
linarith
|
||
-- Case 1: h - √N ≥ 0
|
||
by_cases h_nonneg_diff : (h : ℝ) - Real.sqrt (N : ℝ) ≥ 0
|
||
· rw [abs_of_nonneg h_nonneg_diff]
|
||
have h_diff_upper : (h : ℝ) - Real.sqrt (N : ℝ) ≤ Real.sqrt 2 * Real.rpow (N : ℝ) ε := by
|
||
calc
|
||
(h : ℝ) - Real.sqrt (N : ℝ) ≤ (Real.sqrt (2 * (N : ℝ)) + 1) - Real.sqrt (N : ℝ) := by
|
||
linarith
|
||
_ = Real.sqrt (2 * (N : ℝ)) - Real.sqrt (N : ℝ) + 1 := by ring
|
||
_ = Real.sqrt 2 * Real.sqrt (N : ℝ) - Real.sqrt (N : ℝ) + 1 := by
|
||
rw [Real.sqrt_mul (by norm_num : 0 ≤ (2 : ℝ))]
|
||
_ = (Real.sqrt 2 - 1) * Real.sqrt (N : ℝ) + 1 := by ring
|
||
_ ≤ (Real.sqrt 2 - 1) * Real.rpow (N : ℝ) ε + Real.rpow (N : ℝ) ε := by
|
||
nlinarith
|
||
_ = Real.sqrt 2 * Real.rpow (N : ℝ) ε := by ring
|
||
exact h_diff_upper
|
||
· rw [abs_of_neg (by linarith), neg_sub]
|
||
have h_diff_lower : Real.sqrt (N : ℝ) - (h : ℝ) ≤ Real.sqrt 2 * Real.rpow (N : ℝ) ε := by
|
||
calc
|
||
Real.sqrt (N : ℝ) - (h : ℝ) ≤ Real.sqrt (N : ℝ) - 1 := by nlinarith
|
||
_ ≤ Real.sqrt (N : ℝ) := by nlinarith
|
||
_ ≤ Real.rpow (N : ℝ) ε := h_sqrt_N_le_N_pow_eps
|
||
_ ≤ Real.sqrt 2 * Real.rpow (N : ℝ) ε := by nlinarith
|
||
exact h_diff_lower
|
||
|
||
/-- **Lindström upper bound for ε ≥ 1/4** (unconditional).
|
||
For all ε ≥ 1/4, h(N) ≤ √N + 2·N^ε for all N ≥ 16. -/
|
||
theorem sidonUpperBound_quarter :
|
||
∀ ε : ℝ, (1 : ℝ) / 4 ≤ ε → 0 < ε →
|
||
∃ C : ℝ, ∃ N0 : ℕ,
|
||
0 ≤ C ∧
|
||
∀ {N h : ℕ}, N0 ≤ N → IsSidonMaximum N h →
|
||
(h : ℝ) ≤ Real.sqrt (N : ℝ) + C * Real.rpow (N : ℝ) ε :=
|
||
by
|
||
intro ε hε_ge_quarter hε_pos
|
||
by_cases hε_ge_half : (1 : ℝ) / 2 ≤ ε
|
||
· -- For ε ≥ 1/2, use the stronger bilateral bound from erdos30_partial_half
|
||
rcases erdos30_partial_half ε hε_ge_half hε_pos with ⟨C, N0, hC_nonneg, hC⟩
|
||
refine ⟨C, N0, hC_nonneg, ?_⟩
|
||
intro N h hN hmax
|
||
have h_abs := hC hN hmax
|
||
have h_abs_le := abs_le.mp h_abs
|
||
nlinarith
|
||
· -- For 1/4 ≤ ε < 1/2, use the Lindström bound h(N) ≤ √N + ⁴√N + 2
|
||
refine ⟨3, 16, by norm_num, ?_⟩
|
||
intro N h hN hmax
|
||
have hN16 : 16 ≤ N := hN
|
||
have hNpos : 1 ≤ N := by omega
|
||
have hN_real : (1 : ℝ) ≤ (N : ℝ) := by exact_mod_cast hNpos
|
||
have hN_nonneg : 0 ≤ (N : ℝ) := by exact_mod_cast Nat.zero_le _
|
||
have h_bound_nat : h ≤ Nat.sqrt N + Nat.sqrt (Nat.sqrt N) + 2 := by
|
||
have h_eq : h = sidonMaximum N :=
|
||
isSidonMaximum_unique hmax (sidonMaximum_isSidonMaximum N)
|
||
rw [h_eq]; exact sidonMaximum_le_lindstrom N hN16
|
||
have h_bound_real : (h : ℝ) ≤ (Nat.sqrt N : ℝ) + (Nat.sqrt (Nat.sqrt N) : ℝ) + 2 :=
|
||
by exact_mod_cast h_bound_nat
|
||
have h_sq_s : (Nat.sqrt N : ℝ)^2 ≤ (N : ℝ) := by
|
||
have h := Nat.sqrt_le' N
|
||
exact_mod_cast h
|
||
have h_sqrt_nat_le_real : (Nat.sqrt N : ℝ) ≤ Real.sqrt (N : ℝ) := by
|
||
calc
|
||
(Nat.sqrt N : ℝ) = Real.sqrt (((Nat.sqrt N : ℝ))^2) := by
|
||
rw [Real.sqrt_sq (show 0 ≤ (Nat.sqrt N : ℝ) from by exact_mod_cast Nat.zero_le _)]
|
||
_ ≤ Real.sqrt (N : ℝ) := Real.sqrt_le_sqrt h_sq_s
|
||
have h_t_sq_s : ((Nat.sqrt (Nat.sqrt N) : ℝ))^2 ≤ Real.sqrt (N : ℝ) := by
|
||
calc
|
||
((Nat.sqrt (Nat.sqrt N) : ℝ))^2 ≤ (Nat.sqrt N : ℝ) := by
|
||
have h := Nat.sqrt_le' (Nat.sqrt N)
|
||
exact_mod_cast h
|
||
_ ≤ Real.sqrt (N : ℝ) := h_sqrt_nat_le_real
|
||
have h_sqrt_sqrt_rpow : Real.sqrt (Real.sqrt (N : ℝ)) = (N : ℝ) ^ ((1 : ℝ) / 4) := by
|
||
calc
|
||
Real.sqrt (Real.sqrt (N : ℝ)) = ((N : ℝ) ^ ((1 : ℝ) / 2)) ^ ((1 : ℝ) / 2) := by
|
||
simp [Real.sqrt_eq_rpow]
|
||
_ = (N : ℝ) ^ (((1 : ℝ) / 2) * ((1 : ℝ) / 2)) := by
|
||
rw [Real.rpow_mul hN_nonneg]
|
||
_ = (N : ℝ) ^ ((1 : ℝ) / 4) := by ring
|
||
have h_t_le_rpow : (Nat.sqrt (Nat.sqrt N) : ℝ) ≤ (N : ℝ) ^ ε := by
|
||
calc
|
||
(Nat.sqrt (Nat.sqrt N) : ℝ) = Real.sqrt (((Nat.sqrt (Nat.sqrt N) : ℝ))^2) := by
|
||
rw [Real.sqrt_sq (show 0 ≤ (Nat.sqrt (Nat.sqrt N) : ℝ) from by exact_mod_cast Nat.zero_le _)]
|
||
_ ≤ Real.sqrt (Real.sqrt (N : ℝ)) := Real.sqrt_le_sqrt h_t_sq_s
|
||
_ = (N : ℝ) ^ ((1 : ℝ) / 4) := h_sqrt_sqrt_rpow
|
||
_ ≤ (N : ℝ) ^ ε := Real.rpow_le_rpow_of_exponent_le hN_real hε_ge_quarter
|
||
have h_two_le_rpow : (2 : ℝ) ≤ 2 * (N : ℝ) ^ ε := by
|
||
have h_one_le : (1 : ℝ) ≤ (N : ℝ) ^ ε := by
|
||
have h_one_rpow : (1 : ℝ) ^ ε = (1 : ℝ) := by simp
|
||
have h_rpow_mono : (1 : ℝ) ^ ε ≤ (N : ℝ) ^ ε :=
|
||
Real.rpow_le_rpow (by norm_num) hN_real (hε_pos.le)
|
||
simpa [h_one_rpow] using h_rpow_mono
|
||
nlinarith
|
||
calc
|
||
(h : ℝ) ≤ (Nat.sqrt N : ℝ) + (Nat.sqrt (Nat.sqrt N) : ℝ) + 2 := h_bound_real
|
||
_ ≤ Real.sqrt (N : ℝ) + (Nat.sqrt (Nat.sqrt N) : ℝ) + 2 := by nlinarith
|
||
_ ≤ Real.sqrt (N : ℝ) + (N : ℝ) ^ ε + 2 := by nlinarith
|
||
_ ≤ Real.sqrt (N : ℝ) + (N : ℝ) ^ ε + 2 * (N : ℝ) ^ ε := by nlinarith
|
||
_ = Real.sqrt (N : ℝ) + 3 * (N : ℝ) ^ ε := by ring
|
||
|
||
/-! ## Conditional Erdős Problem 30 Reduction
|
||
|
||
`conditional_erdos30` appears later in this file (after `singerIntervalSidon`),
|
||
since its lower-bound side is discharged via the Singer interval construction. -/
|
||
|
||
/-! ## Representation Function -/
|
||
|
||
/-- For a Sidon set, the representation function is bounded by 2:
|
||
at most 2 ordered pairs (a,b) ∈ A×A satisfy a + b = n.
|
||
Uses Finset.product instead of the ×ˢ notation. -/
|
||
theorem IsSidon.repr_le_two {A : Finset ℤ} (hA : IsSidon A) (n : ℤ) :
|
||
((A.product A).filter (fun ab : ℤ × ℤ => ab.1 + ab.2 = n)).card ≤ 2 := by
|
||
set S := (A.product A).filter (λ ab : ℤ × ℤ => ab.1 + ab.2 = n) with hS
|
||
by_cases h_empty : S.Nonempty
|
||
· rcases h_empty with ⟨⟨a, b⟩, hab⟩
|
||
have ha_mem_filter : (a, b) ∈ (A.product A).filter (λ ab : ℤ × ℤ => ab.1 + ab.2 = n) := by
|
||
simpa [hS] using hab
|
||
have ha_mem_product : (a, b) ∈ A.product A :=
|
||
(Finset.mem_filter.1 ha_mem_filter).1
|
||
have ha_all : a ∈ A ∧ b ∈ A := Finset.mem_product.1 ha_mem_product
|
||
have ha : a ∈ A := ha_all.1
|
||
have hb : b ∈ A := ha_all.2
|
||
have hsum : a + b = n := by
|
||
simpa using (Finset.mem_filter.1 ha_mem_filter).2
|
||
have h_sub : S ⊆ {(a, b), (b, a)} := by
|
||
intro ⟨x, y⟩ hxy
|
||
have hx_mem_filter : (x, y) ∈ (A.product A).filter (λ ab : ℤ × ℤ => ab.1 + ab.2 = n) := by
|
||
simpa [hS] using hxy
|
||
have hx_mem_product : (x, y) ∈ A.product A :=
|
||
(Finset.mem_filter.1 hx_mem_filter).1
|
||
have hx_all : x ∈ A ∧ y ∈ A := Finset.mem_product.1 hx_mem_product
|
||
have hx : x ∈ A := hx_all.1
|
||
have hy : y ∈ A := hx_all.2
|
||
have hsum_xy : x + y = n := by
|
||
simpa using (Finset.mem_filter.1 hx_mem_filter).2
|
||
have hab_eq : a + b = x + y := by
|
||
calc
|
||
a + b = n := hsum
|
||
_ = x + y := hsum_xy.symm
|
||
rcases hA ha hb hx hy hab_eq with (⟨hac, hbd⟩ | ⟨had, hbc⟩)
|
||
· simp [hac, hbd]
|
||
· simp [had, hbc]
|
||
have h_card_sub : S.card ≤ ({(a, b), (b, a)} : Finset (ℤ × ℤ)).card :=
|
||
Finset.card_le_card h_sub
|
||
have h_card_two : ({(a, b), (b, a)} : Finset (ℤ × ℤ)).card ≤ 2 := by
|
||
by_cases h_eq : (a, b) = (b, a)
|
||
· simp [h_eq]
|
||
· simp [h_eq]
|
||
omega
|
||
· have h_card_zero : S.card = 0 := by
|
||
apply Finset.card_eq_zero.mpr
|
||
ext x; simp; intro hx; exact h_empty ⟨x, hx⟩
|
||
omega
|
||
|
||
/-! ## No-Wraparound Lemma -/
|
||
|
||
/-- **No-wraparound lemma.** If all elements of A are in {1,...,N} and
|
||
M ≥ 2N - 1, then IsSidon A → IsSidonMod M A. This is the key step
|
||
that lets interval Sidon sets be embedded into a cyclic ambient group
|
||
without creating new sum collisions. -/
|
||
theorem IsSidon.isSidonMod_of_interval {A : Finset ℤ} {N M : ℤ}
|
||
(hA : IsSidon A)
|
||
(hbound : ∀ x ∈ A, 1 ≤ x ∧ x ≤ N)
|
||
(hM : 2 * N - 1 ≤ M) : IsSidonMod M A := by
|
||
intro a b c d ha hb hc hd hdiv
|
||
have ha_bound := hbound a ha
|
||
have hb_bound := hbound b hb
|
||
have hc_bound := hbound c hc
|
||
have hd_bound := hbound d hd
|
||
have hN_pos : 1 ≤ N := le_trans ha_bound.1 ha_bound.2
|
||
have hM_nonneg : 0 ≤ M := by omega
|
||
have hdiff_bound : |(a + b) - (c + d)| ≤ 2 * N - 2 := by
|
||
apply abs_le.mpr
|
||
constructor <;> omega
|
||
have hlt : |(a + b) - (c + d)| < M := by
|
||
have : 2 * N - 2 < 2 * N - 1 := by omega
|
||
omega
|
||
rcases hdiv with ⟨k, hk⟩
|
||
by_cases hk0 : k = 0
|
||
· rw [hk0, mul_zero] at hk
|
||
have hsum_eq : a + b = c + d := by omega
|
||
exact hA ha hb hc hd hsum_eq
|
||
· have hk_abs_ge_one : 1 ≤ |k| := by
|
||
have hk_ne_zero : k ≠ 0 := hk0
|
||
have hk_abs_pos : 0 < |k| := abs_pos.mpr hk_ne_zero
|
||
omega
|
||
have hM_eq_abs : |M| = M := abs_of_nonneg hM_nonneg
|
||
have hdiff_bound_M : M ≤ |(a + b) - (c + d)| := by
|
||
calc
|
||
M = |M| := hM_eq_abs.symm
|
||
_ ≤ |M| * |k| := by
|
||
calc
|
||
|M| = |M| * 1 := by simp
|
||
_ ≤ |M| * |k| :=
|
||
mul_le_mul_of_nonneg_left hk_abs_ge_one (abs_nonneg _)
|
||
_ = |M * k| := by rw [abs_mul]
|
||
_ = |(a + b) - (c + d)| := by rw [hk]
|
||
linarith
|
||
|
||
/-! ## Singer ↔ Golden Angle Connection -/
|
||
|
||
/-- The Singer construction modulus for prime p: q² + q + 1 where q = p.
|
||
For p = 2: 2² + 2 + 1 = 7. For p = 3: 3² + 3 + 1 = 13.
|
||
These are the orders of the cyclic difference sets. -/
|
||
def singerModulus (p : ℕ) : ℕ := p * p + p + 1
|
||
|
||
/-- The Singer set cardinality for prime p: p + 1 elements. -/
|
||
def singerCardinality (p : ℕ) : ℕ := p + 1
|
||
|
||
/-- The Singer Sidon density ratio: numerator = p+1, denominator = p²+p+1.
|
||
For large p, this ratio ≈ 1/p → 0, while the golden angle density
|
||
1/φ ≈ 0.618 exceeds all finite Singer densities. -/
|
||
def singerDensityNum (p : ℕ) : ℕ := p + 1
|
||
def singerDensityDen (p : ℕ) : ℕ := p * p + p + 1
|
||
|
||
-- Executable witnesses for small primes
|
||
#eval singerModulus 2 -- 7
|
||
#eval singerCardinality 2 -- 3
|
||
#eval singerModulus 3 -- 13
|
||
#eval singerCardinality 3 -- 4
|
||
#eval singerModulus 5 -- 31
|
||
#eval singerCardinality 5 -- 6
|
||
|
||
/-! ## Cyclic Window Infrastructure (from SidonGap.lean) -/
|
||
|
||
/-!
|
||
Port of the cyclic gap infrastructure from Hulak–Ramos–de Queiroz (2026),
|
||
Erdos30/SidonGap.lean. This provides the bridge from modular Sidon sets to
|
||
interval Sidon sets via the cyclic gap structure.
|
||
|
||
Key results:
|
||
1. residueImageNat — the natural-number residue image of a modular Sidon set
|
||
2. sortedResidues — the sorted residues indexed by Fin S.card
|
||
3. sortedResidueWitness — a chosen element realizing each sorted residue
|
||
4. cyclicGapAt — the cyclic gap function on sorted residues
|
||
5. exists_full_intervalSidon_of_quantitative_gap_bound — the main theorem
|
||
-/
|
||
|
||
-- ============================================================
|
||
-- Part 1: Residue image and injectivity
|
||
-- ============================================================
|
||
|
||
/-- The natural-number residue image of `S` modulo `M`. -/
|
||
noncomputable def residueImageNat (M : ℤ) (S : Finset ℤ) : Finset ℕ :=
|
||
S.image fun s => Int.toNat (s % M)
|
||
|
||
theorem mem_residueImageNat {M : ℤ} {S : Finset ℤ} {n : ℕ} :
|
||
n ∈ residueImageNat M S ↔ ∃ s ∈ S, Int.toNat (s % M) = n := by
|
||
simp [residueImageNat]
|
||
|
||
private theorem exists_mem_modEq_of_mem_residueImageNat
|
||
{M_int : ℤ} {S : Finset ℤ} (hM : 0 < M_int) {n : ℕ}
|
||
(hn : n ∈ residueImageNat M_int S) :
|
||
∃ s ∈ S, (n : ℤ) = s % M_int := by
|
||
rcases mem_residueImageNat.mp hn with ⟨s, hs, hsmod⟩
|
||
refine ⟨s, hs, ?_⟩
|
||
have hnonneg : 0 ≤ s % M_int := Int.emod_nonneg _ (ne_of_gt hM)
|
||
simpa [Int.toNat_of_nonneg hnonneg] using
|
||
(congrArg (fun m : ℕ => (m : ℤ)) hsmod).symm
|
||
|
||
/-- The residue map `s ↦ s % M` is injective on any modular Sidon set. -/
|
||
theorem IsSidonMod.residue_injOn {M_int : ℤ} {S : Finset ℤ}
|
||
(hS : IsSidonMod M_int S) (hM : 0 < M_int) :
|
||
Set.InjOn (· % M_int) (↑S : Set ℤ) := by
|
||
intro a ha b hb heq
|
||
have ha' : a ∈ S := by exact ha
|
||
have hb' : b ∈ S := by exact hb
|
||
have hdvd : M_int ∣ (a - b) := by
|
||
have ha_mod := Int.emod_def a M_int
|
||
have hb_mod := Int.emod_def b M_int
|
||
have heq' : a % M_int = b % M_int := heq
|
||
rw [heq'] at ha_mod
|
||
exact ⟨a / M_int - b / M_int, by linarith⟩
|
||
have hS' : M_int ∣ ((a + a) - (b + a)) := by
|
||
convert hdvd using 1; ring
|
||
have hresult := hS (a := a) (b := a) (c := b) (d := a) ha' ha' hb' ha' hS'
|
||
rcases hresult with h | h
|
||
· exact h.1
|
||
· exact h.2
|
||
|
||
/-- The residue map to natural representatives preserves cardinality on a
|
||
modular Sidon set. -/
|
||
theorem IsSidonMod.residueImageNat_card {M_int : ℤ} {S : Finset ℤ}
|
||
(hS : IsSidonMod M_int S) (hM : 0 < M_int) :
|
||
(residueImageNat M_int S).card = S.card := by
|
||
unfold residueImageNat
|
||
apply Finset.card_image_of_injOn
|
||
intro a ha b hb hab
|
||
have hcast : (Int.toNat (a % M_int) : ℤ) = Int.toNat (b % M_int) := by
|
||
exact congrArg (fun n : ℕ => (n : ℤ)) hab
|
||
have ha_nonneg : 0 ≤ a % M_int := Int.emod_nonneg _ (ne_of_gt hM)
|
||
have hb_nonneg : 0 ≤ b % M_int := Int.emod_nonneg _ (ne_of_gt hM)
|
||
have hmod : a % M_int = b % M_int := by
|
||
simpa [Int.toNat_of_nonneg ha_nonneg, Int.toNat_of_nonneg hb_nonneg] using hcast
|
||
exact hS.residue_injOn hM (by exact ha) (by exact hb) hmod
|
||
|
||
theorem residueImageNat_lt_modulus {M_int : ℤ} {S : Finset ℤ}
|
||
(hM : 0 < M_int) {n : ℕ} (hn : n ∈ residueImageNat M_int S) :
|
||
n < M_int.toNat := by
|
||
rcases mem_residueImageNat.mp hn with ⟨s, _hs, hsmod⟩
|
||
have hnonneg : 0 ≤ s % M_int := Int.emod_nonneg _ (ne_of_gt hM)
|
||
have hlt : s % M_int < M_int := Int.emod_lt_of_pos _ hM
|
||
have hcast : ((Int.toNat (s % M_int) : ℤ) : ℤ) < (M_int.toNat : ℤ) := by
|
||
rw [Int.toNat_of_nonneg hnonneg, Int.toNat_of_nonneg (le_of_lt hM)]
|
||
exact hlt
|
||
have hnat : Int.toNat (s % M_int) < M_int.toNat := by
|
||
exact_mod_cast hcast
|
||
simpa [hsmod] using hnat
|
||
|
||
private theorem IsSidonMod.card_le_modulus {M_int : ℤ} {S : Finset ℤ}
|
||
(hS : IsSidonMod M_int S) (hM : 0 < M_int) :
|
||
S.card ≤ M_int.toNat := by
|
||
calc
|
||
S.card = (residueImageNat M_int S).card := by
|
||
symm
|
||
exact hS.residueImageNat_card hM
|
||
_ ≤ (Finset.range M_int.toNat).card := by
|
||
apply Finset.card_le_card
|
||
intro n hn
|
||
exact Finset.mem_range.mpr (residueImageNat_lt_modulus hM hn)
|
||
_ = M_int.toNat := by
|
||
simp
|
||
|
||
-- ============================================================
|
||
-- Part 2: Sorted residues and witnesses
|
||
-- ============================================================
|
||
|
||
/-- The sorted residues of a modular Sidon set, indexed by `Fin S.card`. -/
|
||
noncomputable def IsSidonMod.sortedResidues {M_int : ℤ} {S : Finset ℤ}
|
||
(hS : IsSidonMod M_int S) (hM : 0 < M_int) :
|
||
Fin S.card ↪o ℕ :=
|
||
(residueImageNat M_int S).orderEmbOfFin (hS.residueImageNat_card hM)
|
||
|
||
theorem IsSidonMod.sortedResidues_mem {M_int : ℤ} {S : Finset ℤ}
|
||
(hS : IsSidonMod M_int S) (hM : 0 < M_int) (i : Fin S.card) :
|
||
hS.sortedResidues hM i ∈ residueImageNat M_int S := by
|
||
simpa [IsSidonMod.sortedResidues] using
|
||
(residueImageNat M_int S).orderEmbOfFin_mem
|
||
(hS.residueImageNat_card hM) i
|
||
|
||
/-- A chosen element of `S` realizing the `i`th sorted residue. -/
|
||
noncomputable def IsSidonMod.sortedResidueWitness {M_int : ℤ} {S : Finset ℤ}
|
||
(hS : IsSidonMod M_int S) (hM : 0 < M_int) (i : Fin S.card) : ℤ :=
|
||
Classical.choose <|
|
||
exists_mem_modEq_of_mem_residueImageNat hM <|
|
||
hS.sortedResidues_mem hM i
|
||
|
||
theorem IsSidonMod.sortedResidueWitness_mem {M_int : ℤ} {S : Finset ℤ}
|
||
(hS : IsSidonMod M_int S) (hM : 0 < M_int) (i : Fin S.card) :
|
||
hS.sortedResidueWitness hM i ∈ S :=
|
||
(Classical.choose_spec <|
|
||
exists_mem_modEq_of_mem_residueImageNat hM <|
|
||
hS.sortedResidues_mem hM i).1
|
||
|
||
theorem IsSidonMod.sortedResidueWitness_mod {M_int : ℤ} {S : Finset ℤ}
|
||
(hS : IsSidonMod M_int S) (hM : 0 < M_int) (i : Fin S.card) :
|
||
((hS.sortedResidues hM i : ℕ) : ℤ) = hS.sortedResidueWitness hM i % M_int :=
|
||
(Classical.choose_spec <|
|
||
exists_mem_modEq_of_mem_residueImageNat hM <|
|
||
hS.sortedResidues_mem hM i).2
|
||
|
||
-- ============================================================
|
||
-- Part 3: Cyclic gap function
|
||
-- ============================================================
|
||
|
||
/-- Cyclic gap at position `i` for sorted residues `r : ℕ → ℕ` of a set
|
||
of `k` elements in `{0, …, M−1}`. For `i + 1 < k` this is the forward
|
||
step `r(i+1) − r(i)`; for the last index it is the wraparound step
|
||
`M − r(k−1) + r(0)`. -/
|
||
def cyclicGapAt (M k : ℕ) (r : ℕ → ℕ) (i : ℕ) : ℕ :=
|
||
if i + 1 < k then r (i + 1) - r i
|
||
else M - r (k - 1) + r 0
|
||
|
||
-- ============================================================
|
||
-- Part 4: Gap existence lemmas
|
||
-- ============================================================
|
||
|
||
private theorem no_mem_between_orderEmbOfFin {s : Finset ℕ} {k : ℕ}
|
||
(h : s.card = k) {i : Fin k} (hi : (i : ℕ) + 1 < k) {n : ℕ} (hn : n ∈ s)
|
||
(hleft : s.orderEmbOfFin h i < n)
|
||
(hright : n < s.orderEmbOfFin h ⟨(i : ℕ) + 1, hi⟩) : False := by
|
||
have hn_range : n ∈ Set.range (s.orderEmbOfFin h) := by
|
||
rw [Finset.range_orderEmbOfFin]
|
||
exact hn
|
||
rcases hn_range with ⟨j, rfl⟩
|
||
have hij_left : i < j := by
|
||
by_contra hij_left
|
||
exact not_lt_of_ge ((s.orderEmbOfFin h).monotone (le_of_not_gt hij_left)) hleft
|
||
have hij_right : j < ⟨(i : ℕ) + 1, hi⟩ := by
|
||
by_contra hij_right
|
||
exact not_lt_of_ge ((s.orderEmbOfFin h).monotone (le_of_not_gt hij_right)) hright
|
||
have hij_left' : (i : ℕ) + 1 ≤ (j : ℕ) := Nat.succ_le_of_lt hij_left
|
||
have hij_right' : (j : ℕ) < (i : ℕ) + 1 := hij_right
|
||
omega
|
||
|
||
private theorem IsSidonMod.no_residue_between_successive_sortedResidues
|
||
{M_int : ℤ} {S : Finset ℤ} (hS : IsSidonMod M_int S) (hM : 0 < M_int)
|
||
{i : Fin S.card} (hi : (i : ℕ) + 1 < S.card) {n : ℕ}
|
||
(hn : n ∈ residueImageNat M_int S)
|
||
(hleft : hS.sortedResidues hM i < n)
|
||
(hright : n < hS.sortedResidues hM ⟨(i : ℕ) + 1, hi⟩) : False := by
|
||
exact no_mem_between_orderEmbOfFin (hS.residueImageNat_card hM) hi hn hleft hright
|
||
|
||
/-- **Difference distinctness.** In a modular Sidon set, if
|
||
`a − b ≡ c − d (mod M)` and `a ≠ b`, then `a = c` and `b = d`. -/
|
||
theorem IsSidonMod.diff_eq {M : ℤ} {S : Finset ℤ}
|
||
(hS : IsSidonMod M S) {a b c d : ℤ}
|
||
(ha : a ∈ S) (hb : b ∈ S) (hc : c ∈ S) (hd : d ∈ S)
|
||
(hab : a ≠ b)
|
||
(hdiff : M ∣ ((a - b) - (c - d))) :
|
||
a = c ∧ b = d := by
|
||
have hconv : M ∣ ((a + d) - (b + c)) := by convert hdiff using 1; ring
|
||
rcases hS ha hd hb hc hconv with h | h
|
||
· exact absurd h.1 hab
|
||
· exact ⟨h.1, h.2.symm⟩
|
||
|
||
/-- If `M` divides the difference of residues of two pairs, then `M`
|
||
divides the difference of the original pairs. -/
|
||
theorem dvd_diff_of_residue_diff {M a b c d : ℤ}
|
||
(h : M ∣ ((b % M - a % M) - (d % M - c % M))) :
|
||
M ∣ ((b - a) - (d - c)) := by
|
||
have key : (b - a) - (d - c) =
|
||
M * (b / M - a / M - (d / M - c / M)) +
|
||
((b % M - a % M) - (d % M - c % M)) := by
|
||
have hb := Int.emod_def b M
|
||
have ha := Int.emod_def a M
|
||
have hd := Int.emod_def d M
|
||
have hc := Int.emod_def c M
|
||
linarith
|
||
rw [key]
|
||
exact dvd_add (dvd_mul_right M _) h
|
||
|
||
-- ============================================================
|
||
-- Part 5: Window Sidon property (needed for gap lemmas)
|
||
-- ============================================================
|
||
|
||
/-- The cyclic-window relabeling map. For a window starting at `u` in
|
||
`ℤ/Mℤ`, sends representative `x` to position `(x − u) % M + 1`.
|
||
Elements in a window of length `N` land in `{1, …, N}`. -/
|
||
def windowRelabel (M u x : ℤ) : ℤ := (x - u) % M + 1
|
||
|
||
theorem windowRelabel_bounds {M u x N : ℤ} (hM : 0 < M)
|
||
(hw : (x - u) % M < N) :
|
||
1 ≤ windowRelabel M u x ∧ windowRelabel M u x ≤ N := by
|
||
have hnn : 0 ≤ (x - u) % M := Int.emod_nonneg _ (ne_of_gt hM)
|
||
exact ⟨by unfold windowRelabel; linarith,
|
||
by unfold windowRelabel; linarith⟩
|
||
|
||
/-- The restriction of `S` to the cyclic window of length `N` starting at
|
||
`u`, relabeled into `{1, …, N}`. An element `s ∈ S` is kept iff
|
||
`(s − u) % M < N`. -/
|
||
def windowImage (M u N : ℤ) (S : Finset ℤ) : Finset ℤ :=
|
||
(S.filter (fun s => (s - u) % M < N)).image (windowRelabel M u)
|
||
|
||
/-- In a modular Sidon set, `M ∣ (x − y)` forces `x = y`. -/
|
||
theorem IsSidonMod.eq_of_dvd {M : ℤ} {S : Finset ℤ}
|
||
(hS : IsSidonMod M S) {x y : ℤ} (hx : x ∈ S) (hy : y ∈ S)
|
||
(hdvd : M ∣ (x - y)) : x = y := by
|
||
have hdvd' : M ∣ ((x + x) - (y + x)) := by
|
||
convert hdvd using 1; ring
|
||
rcases hS hx hx hy hx hdvd' with h | h
|
||
· exact h.1
|
||
· exact h.2
|
||
|
||
/-- Two elements of a modular Sidon set that relabel to the same value
|
||
must be equal. -/
|
||
theorem IsSidonMod.windowRelabel_injective {M : ℤ} {S : Finset ℤ} {u : ℤ}
|
||
(hS : IsSidonMod M S)
|
||
{x y : ℤ} (hx : x ∈ S) (hy : y ∈ S)
|
||
(heq : windowRelabel M u x = windowRelabel M u y) : x = y := by
|
||
unfold windowRelabel at heq
|
||
have heq' : (x - u) % M = (y - u) % M := by linarith
|
||
have hdvd : M ∣ (x - y) :=
|
||
⟨(x - u) / M - (y - u) / M, by
|
||
have hx_mod := Int.emod_def (x - u) M
|
||
have hy_mod := Int.emod_def (y - u) M
|
||
linarith⟩
|
||
exact hS.eq_of_dvd hx hy hdvd
|
||
|
||
/-- **Sum-transfer lemma.** If the relabeled sums of two pairs are equal
|
||
as integers, then the original sums are congruent modulo `M`. -/
|
||
theorem windowRelabel_sum_dvd {M u x y z w : ℤ}
|
||
(hsum : windowRelabel M u x + windowRelabel M u y =
|
||
windowRelabel M u z + windowRelabel M u w) :
|
||
M ∣ ((x + y) - (z + w)) := by
|
||
unfold windowRelabel at hsum
|
||
have hx_mod := Int.emod_def (x - u) M
|
||
have hy_mod := Int.emod_def (y - u) M
|
||
have hz_mod := Int.emod_def (z - u) M
|
||
have hw_mod := Int.emod_def (w - u) M
|
||
exact ⟨(x - u) / M + (y - u) / M - (z - u) / M - (w - u) / M,
|
||
by linarith⟩
|
||
|
||
/-- **Cyclic-window Sidon theorem.** The relabeled window restriction of
|
||
a modular Sidon set is an interval Sidon set. -/
|
||
theorem IsSidonMod.windowSidon {M : ℤ} {S : Finset ℤ} {u N : ℤ}
|
||
(hS : IsSidonMod M S) (hM : 0 < M) (_hN : 0 < N) (_hNM : N ≤ M) :
|
||
IsIntervalSidon N (windowImage M u N S) where
|
||
subset := by
|
||
intro a ha
|
||
simp only [windowImage, mem_image, mem_filter] at ha
|
||
obtain ⟨s, ⟨_, hsw⟩, rfl⟩ := ha
|
||
exact windowRelabel_bounds hM (by simpa using hsw)
|
||
sidon := by
|
||
intro a b c d ha hb hc hd hsum
|
||
simp only [windowImage, mem_image, mem_filter] at ha hb hc hd
|
||
obtain ⟨x, ⟨hxS, _⟩, rfl⟩ := ha
|
||
obtain ⟨y, ⟨hyS, _⟩, rfl⟩ := hb
|
||
obtain ⟨z, ⟨hzS, _⟩, rfl⟩ := hc
|
||
obtain ⟨w, ⟨hwS, _⟩, rfl⟩ := hd
|
||
have hdvd := windowRelabel_sum_dvd hsum
|
||
rcases hS hxS hyS hzS hwS hdvd with h | h
|
||
· left
|
||
exact ⟨congrArg (windowRelabel M u) h.1, congrArg (windowRelabel M u) h.2⟩
|
||
· right
|
||
exact ⟨congrArg (windowRelabel M u) h.1, congrArg (windowRelabel M u) h.2⟩
|
||
|
||
/-- The relabeled image has the same cardinality as the window
|
||
restriction, because `windowRelabel` is injective on any modular
|
||
Sidon set. -/
|
||
theorem IsSidonMod.windowImage_card {M : ℤ} {S : Finset ℤ} {u N : ℤ}
|
||
(hS : IsSidonMod M S) :
|
||
(windowImage M u N S).card =
|
||
(S.filter (fun s => (s - u) % M < N)).card := by
|
||
simp only [windowImage]
|
||
apply Finset.card_image_of_injOn
|
||
intro x hx y hy heq
|
||
rw [Finset.mem_coe, Finset.mem_filter] at hx hy
|
||
exact hS.windowRelabel_injective hx.1 hy.1 heq
|
||
|
||
-- ============================================================
|
||
-- Part 6: Gap existence from sorted residues
|
||
-- ============================================================
|
||
|
||
/-- **Zero-loss window existence.** If a modular Sidon set of size `k`
|
||
in `ℤ/Mℤ` has a cyclic gap of length at least `L`, then the window
|
||
of length `N = M − L` starting just past that gap captures all `k`
|
||
elements, giving an interval Sidon set of full size `k`. -/
|
||
theorem IsSidonMod.exists_full_intervalSidon_of_gap
|
||
{M : ℤ} {S : Finset ℤ} {L : ℤ}
|
||
(hS : IsSidonMod M S) (hM : 0 < M) (hL : 0 ≤ L) (hLM : L < M)
|
||
(hgap : ∃ u : ℤ, ∀ s ∈ S, ¬((s - u) % M < L)) :
|
||
∃ A : Finset ℤ, IsIntervalSidon (M - L) A ∧ A.card = S.card := by
|
||
obtain ⟨u, hu⟩ := hgap
|
||
have hN_pos : 0 < M - L := by omega
|
||
have hNM : M - L ≤ M := by omega
|
||
refine ⟨windowImage M (u + L) (M - L) S,
|
||
hS.windowSidon hM hN_pos hNM, ?_⟩
|
||
have hcard_filter : (S.filter (fun s => (s - (u + L)) % M < M - L)).card = S.card := by
|
||
have hall : ∀ s ∈ S, (s - (u + L)) % M < M - L := by
|
||
intro s hs
|
||
have hu_gap : ¬((s - u) % M < L) := hu s hs
|
||
have hge : L ≤ (s - u) % M := not_lt.mp hu_gap
|
||
have hmod_bound : (s - u) % M < M := Int.emod_lt_of_pos _ hM
|
||
have hkey : (s - (u + L)) % M = ((s - u) % M - L) % M := by
|
||
have := Int.emod_def (s - u) M
|
||
have h_eq : s - (u + L) = (s - u) % M - L + M * ((s - u) / M) := by linarith
|
||
rw [h_eq, Int.add_mul_emod_self_left]
|
||
rw [hkey]
|
||
have hsub_nonneg : 0 ≤ (s - u) % M - L := by omega
|
||
have hsub_lt : (s - u) % M - L < M - L := by omega
|
||
have hmod_result : ((s - u) % M - L) % M = (s - u) % M - L := by
|
||
exact Int.emod_eq_of_lt hsub_nonneg (by omega : (s - u) % M - L < M)
|
||
rw [hmod_result]
|
||
omega
|
||
have hsub : S.filter (fun s => (s - (u + L)) % M < M - L) = S := by
|
||
ext s
|
||
constructor
|
||
· intro h; exact (Finset.mem_filter.mp h).1
|
||
· intro hs; exact Finset.mem_filter.mpr ⟨hs, hall s hs⟩
|
||
rw [hsub]
|
||
rw [hS.windowImage_card, hcard_filter]
|
||
|
||
/-- A forward cyclic gap between consecutive sorted residues yields a full-size
|
||
interval Sidon set in the complementary interval. -/
|
||
theorem IsSidonMod.exists_full_intervalSidon_of_forward_sortedGap
|
||
{M_int : ℤ} {S : Finset ℤ} (hS : IsSidonMod M_int S) (hM : 0 < M_int)
|
||
{i : Fin S.card} (hi : (i : ℕ) + 1 < S.card) :
|
||
∃ A : Finset ℤ,
|
||
IsIntervalSidon
|
||
(M_int
|
||
- (hS.sortedResidues hM ⟨(i : ℕ) + 1, hi⟩ : ℕ)
|
||
+ hS.sortedResidues hM i + 1) A
|
||
∧ A.card = S.card := by
|
||
classical
|
||
let j : Fin S.card := ⟨(i : ℕ) + 1, hi⟩
|
||
let aNat : ℕ := hS.sortedResidues hM i
|
||
let bNat : ℕ := hS.sortedResidues hM j
|
||
let a : ℤ := aNat
|
||
let b : ℤ := bNat
|
||
let L : ℤ := b - a - 1
|
||
have hab : aNat < bNat := by
|
||
simpa [aNat, bNat, j] using
|
||
((hS.sortedResidues hM).strictMono (show i < j by
|
||
rw [Fin.lt_def]
|
||
dsimp [j]
|
||
omega))
|
||
have hb_lt_M : bNat < M_int.toNat := by
|
||
exact residueImageNat_lt_modulus hM (hS.sortedResidues_mem hM j)
|
||
have hL_nonneg : 0 ≤ L := by
|
||
dsimp [L, a, b]
|
||
omega
|
||
have hLM : L < M_int := by
|
||
dsimp [L, a, b]
|
||
omega
|
||
have hgap : ∃ u : ℤ, ∀ s ∈ S, ¬((s - u) % M_int < L) := by
|
||
refine ⟨a + 1, ?_⟩
|
||
intro s hs hslt
|
||
set n : ℕ := Int.toNat (s % M_int)
|
||
have hsmod_nonneg : 0 ≤ s % M_int := Int.emod_nonneg _ (ne_of_gt hM)
|
||
have hn_cast : (n : ℤ) = s % M_int := by
|
||
dsimp [n]
|
||
rw [Int.toNat_of_nonneg hsmod_nonneg]
|
||
have hn_mem : n ∈ residueImageNat M_int S := by
|
||
refine mem_residueImageNat.mpr ⟨s, hs, ?_⟩
|
||
simp [n]
|
||
have hn_lt_M : n < M_int.toNat := residueImageNat_lt_modulus hM hn_mem
|
||
have hslt' : (((n : ℤ) - (a + 1)) % M_int) < L := by
|
||
have hshift : (s - (a + 1)) % M_int = (((n : ℤ) - (a + 1)) % M_int) := by
|
||
rw [hn_cast]
|
||
have h_eq : s - (a + 1) = (s % M_int - (a + 1)) + M_int * (s / M_int) := by
|
||
have hsdef := Int.emod_def s M_int
|
||
linarith
|
||
rw [h_eq, Int.add_mul_emod_self_left]
|
||
rwa [hshift] at hslt
|
||
by_cases hna : n < aNat + 1
|
||
· have hmod_nonneg : 0 ≤ M_int + n - (a + 1) := by
|
||
dsimp [a]
|
||
omega
|
||
have hmod_lt : M_int + n - (a + 1) < M_int := by
|
||
dsimp [a]
|
||
omega
|
||
have hrewrite : (((n : ℤ) - (a + 1)) % M_int) = M_int + n - (a + 1) := by
|
||
calc
|
||
(((n : ℤ) - (a + 1)) % M_int)
|
||
= ((((n : ℤ) - (a + 1)) + 1 * M_int) % M_int) := by
|
||
simpa [sub_eq_add_neg, add_assoc, add_left_comm, add_comm] using
|
||
(Int.add_mul_emod_self_right ((n : ℤ) - (a + 1)) (1 : ℤ) M_int).symm
|
||
_ = M_int + n - (a + 1) := by
|
||
have hsum :
|
||
(((n : ℤ) - (a + 1)) + 1 * M_int) = M_int + n - (a + 1) := by
|
||
ring
|
||
rw [hsum, Int.emod_eq_of_lt hmod_nonneg hmod_lt]
|
||
have : M_int + n - (a + 1) < L := by
|
||
simpa [hrewrite] using hslt'
|
||
omega
|
||
· have hna' : aNat + 1 ≤ n := le_of_not_gt hna
|
||
have hmod_nonneg : 0 ≤ (n : ℤ) - (a + 1) := by
|
||
dsimp [a]
|
||
omega
|
||
have hmod_lt : (n : ℤ) - (a + 1) < M_int := by
|
||
dsimp [a]
|
||
omega
|
||
have hrewrite : (((n : ℤ) - (a + 1)) % M_int) = (n : ℤ) - (a + 1) := by
|
||
rw [Int.emod_eq_of_lt hmod_nonneg hmod_lt]
|
||
have hnb : n < bNat := by
|
||
have : (n : ℤ) - (a + 1) < L := by
|
||
simpa [hrewrite] using hslt'
|
||
dsimp [L, a, b] at this
|
||
omega
|
||
have hna_lt : aNat < n := by
|
||
omega
|
||
exact hS.no_residue_between_successive_sortedResidues hM hi hn_mem hna_lt hnb
|
||
have htransfer := hS.exists_full_intervalSidon_of_gap hM hL_nonneg hLM hgap
|
||
have hlen :
|
||
M_int - L =
|
||
M_int - (hS.sortedResidues hM ⟨(i : ℕ) + 1, hi⟩ : ℕ) + hS.sortedResidues hM i + 1 := by
|
||
dsimp [L, a, b, aNat, bNat, j]
|
||
ring
|
||
simpa [hlen] using htransfer
|
||
|
||
/-- The wraparound cyclic gap between the last and first sorted residues yields
|
||
a full-size interval Sidon set in the complementary interval. -/
|
||
theorem IsSidonMod.exists_full_intervalSidon_of_wraparound_sortedGap
|
||
{M_int : ℤ} {S : Finset ℤ} (hS : IsSidonMod M_int S) (hM : 0 < M_int)
|
||
(hk : 2 ≤ S.card) :
|
||
let first : Fin S.card := ⟨0, by omega⟩
|
||
let last : Fin S.card := ⟨S.card - 1, Nat.sub_lt (by omega) (Nat.succ_pos 0)⟩
|
||
∃ A : Finset ℤ,
|
||
IsIntervalSidon ((hS.sortedResidues hM last : ℕ) - hS.sortedResidues hM first + 1) A
|
||
∧ A.card = S.card := by
|
||
classical
|
||
have hcard_pos : 0 < S.card := by omega
|
||
let firstIdx : Fin S.card := ⟨0, hcard_pos⟩
|
||
let lastIdx : Fin S.card := ⟨S.card - 1, Nat.sub_lt hcard_pos (Nat.succ_pos 0)⟩
|
||
let aNat : ℕ := hS.sortedResidues hM firstIdx
|
||
let bNat : ℕ := hS.sortedResidues hM lastIdx
|
||
let a : ℤ := aNat
|
||
let b : ℤ := bNat
|
||
let L : ℤ := M_int - b + a - 1
|
||
have hb_lt_M : bNat < M_int.toNat := by
|
||
exact residueImageNat_lt_modulus hM (hS.sortedResidues_mem hM lastIdx)
|
||
have hab : aNat < bNat := by
|
||
simpa [aNat, bNat, firstIdx, lastIdx] using
|
||
((hS.sortedResidues hM).strictMono (show firstIdx < lastIdx by
|
||
rw [Fin.lt_def]
|
||
dsimp [firstIdx, lastIdx]
|
||
omega))
|
||
have hL_nonneg : 0 ≤ L := by
|
||
dsimp [L, a, b]
|
||
omega
|
||
have hLM : L < M_int := by
|
||
dsimp [L, a, b]
|
||
omega
|
||
have hfirst_min :
|
||
aNat = (residueImageNat M_int S).min' (Finset.card_pos.mp <| by
|
||
simpa [hS.residueImageNat_card hM] using hcard_pos) := by
|
||
simpa [aNat, firstIdx, IsSidonMod.sortedResidues] using
|
||
(Finset.orderEmbOfFin_zero (s := residueImageNat M_int S)
|
||
(h := hS.residueImageNat_card hM) hcard_pos)
|
||
have hlast_max :
|
||
bNat = (residueImageNat M_int S).max' (Finset.card_pos.mp <| by
|
||
simpa [hS.residueImageNat_card hM] using hcard_pos) := by
|
||
simpa [bNat, lastIdx, IsSidonMod.sortedResidues] using
|
||
(Finset.orderEmbOfFin_last (s := residueImageNat M_int S)
|
||
(h := hS.residueImageNat_card hM) hcard_pos)
|
||
have hgap : ∃ u : ℤ, ∀ s ∈ S, ¬((s - u) % M_int < L) := by
|
||
refine ⟨b + 1, ?_⟩
|
||
intro s hs hslt
|
||
set n : ℕ := Int.toNat (s % M_int)
|
||
have hsmod_nonneg : 0 ≤ s % M_int := Int.emod_nonneg _ (ne_of_gt hM)
|
||
have hn_cast : (n : ℤ) = s % M_int := by
|
||
dsimp [n]
|
||
rw [Int.toNat_of_nonneg hsmod_nonneg]
|
||
have hn_mem : n ∈ residueImageNat M_int S := by
|
||
refine mem_residueImageNat.mpr ⟨s, hs, ?_⟩
|
||
simp [n]
|
||
have hmin_le : aNat ≤ n := by
|
||
rw [hfirst_min]
|
||
exact (residueImageNat M_int S).min'_le _ hn_mem
|
||
have hmax_ge : n ≤ bNat := by
|
||
rw [hlast_max]
|
||
exact (residueImageNat M_int S).le_max' n hn_mem
|
||
have hslt' : (((n : ℤ) - (b + 1)) % M_int) < L := by
|
||
have hshift : (s - (b + 1)) % M_int = (((n : ℤ) - (b + 1)) % M_int) := by
|
||
rw [hn_cast]
|
||
have h_eq : s - (b + 1) = (s % M_int - (b + 1)) + M_int * (s / M_int) := by
|
||
have hsdef := Int.emod_def s M_int
|
||
linarith
|
||
rw [h_eq, Int.add_mul_emod_self_left]
|
||
rwa [hshift] at hslt
|
||
by_cases hbn : bNat < n
|
||
· exact absurd hbn (not_lt_of_ge hmax_ge)
|
||
· have hnb : n ≤ bNat := le_of_not_gt hbn
|
||
have hmod_nonneg : 0 ≤ M_int + n - (b + 1) := by
|
||
dsimp [b]
|
||
omega
|
||
have hmod_lt : M_int + n - (b + 1) < M_int := by
|
||
dsimp [b]
|
||
omega
|
||
have hrewrite : (((n : ℤ) - (b + 1)) % M_int) = M_int + n - (b + 1) := by
|
||
calc
|
||
(((n : ℤ) - (b + 1)) % M_int)
|
||
= ((((n : ℤ) - (b + 1)) + 1 * M_int) % M_int) := by
|
||
simpa [sub_eq_add_neg, add_assoc, add_left_comm, add_comm] using
|
||
(Int.add_mul_emod_self_right ((n : ℤ) - (b + 1)) (1 : ℤ) M_int).symm
|
||
_ = M_int + n - (b + 1) := by
|
||
have hsum :
|
||
(((n : ℤ) - (b + 1)) + 1 * M_int) = M_int + n - (b + 1) := by
|
||
ring
|
||
rw [hsum, Int.emod_eq_of_lt hmod_nonneg hmod_lt]
|
||
have hna : n < aNat := by
|
||
have : M_int + n - (b + 1) < L := by
|
||
simpa [hrewrite] using hslt'
|
||
dsimp [L, a, b] at this
|
||
omega
|
||
exact absurd hna (not_lt_of_ge hmin_le)
|
||
have htransfer := hS.exists_full_intervalSidon_of_gap hM hL_nonneg hLM hgap
|
||
have hlen :
|
||
M_int - L = b - a + 1 := by
|
||
dsimp [L]
|
||
ring
|
||
simpa [firstIdx, lastIdx, aNat, bNat, a, b, hlen] using htransfer
|
||
|
||
/-- Any cyclic gap in the sorted residue model yields a full-size interval
|
||
Sidon set in the complementary interval of length `M - gap + 1`. -/
|
||
theorem IsSidonMod.exists_full_intervalSidon_of_cyclicGapAt
|
||
{M_int : ℤ} {S : Finset ℤ} (hS : IsSidonMod M_int S) (hM : 0 < M_int)
|
||
(hk : 2 ≤ S.card) (i : Fin S.card) :
|
||
let r : ℕ → ℕ := fun n =>
|
||
if hn : n < S.card then hS.sortedResidues hM ⟨n, hn⟩ else 0
|
||
∃ A : Finset ℤ,
|
||
IsIntervalSidon (M_int - cyclicGapAt M_int.toNat S.card r i + 1) A ∧ A.card = S.card := by
|
||
classical
|
||
let r : ℕ → ℕ := fun n =>
|
||
if hn : n < S.card then hS.sortedResidues hM ⟨n, hn⟩ else 0
|
||
by_cases hi_wrap : (i : ℕ) + 1 < S.card
|
||
· let j : Fin S.card := ⟨(i : ℕ) + 1, hi_wrap⟩
|
||
have hforward := hS.exists_full_intervalSidon_of_forward_sortedGap hM (i := i) hi_wrap
|
||
have hij : i < j := by
|
||
rw [Fin.lt_def]
|
||
dsimp [j]
|
||
omega
|
||
have hri_le : hS.sortedResidues hM i ≤ hS.sortedResidues hM j :=
|
||
le_of_lt ((hS.sortedResidues hM).strictMono hij)
|
||
have hcyc :
|
||
(cyclicGapAt M_int.toNat S.card r i : ℤ) =
|
||
(hS.sortedResidues hM j : ℕ) - hS.sortedResidues hM i := by
|
||
simp [cyclicGapAt, r, hi_wrap, i.2, j, Nat.cast_sub hri_le]
|
||
have hlen :
|
||
M_int - (cyclicGapAt M_int.toNat S.card r i : ℕ) + 1 =
|
||
M_int - (hS.sortedResidues hM j : ℕ) + hS.sortedResidues hM i + 1 := by
|
||
rw [hcyc]
|
||
ring
|
||
simpa [r, j, hlen] using hforward
|
||
· have hcard_pos : 0 < S.card := by omega
|
||
let firstIdx : Fin S.card := ⟨0, hcard_pos⟩
|
||
let lastIdx : Fin S.card := ⟨S.card - 1, Nat.sub_lt hcard_pos (Nat.succ_pos 0)⟩
|
||
have hi_last : i = lastIdx := by
|
||
apply Fin.ext
|
||
dsimp [lastIdx]
|
||
omega
|
||
have hwrap := hS.exists_full_intervalSidon_of_wraparound_sortedGap hM hk
|
||
have hb_lt_M :
|
||
hS.sortedResidues hM lastIdx < M_int.toNat := by
|
||
exact residueImageNat_lt_modulus hM (hS.sortedResidues_mem hM lastIdx)
|
||
have hlast_le : hS.sortedResidues hM lastIdx ≤ M_int.toNat := le_of_lt hb_lt_M
|
||
have hM_cast : (M_int.toNat : ℤ) = M_int := by
|
||
rw [Int.toNat_of_nonneg (le_of_lt hM)]
|
||
have hcyc :
|
||
(cyclicGapAt M_int.toNat S.card r i : ℤ) =
|
||
M_int - hS.sortedResidues hM lastIdx + hS.sortedResidues hM firstIdx := by
|
||
rw [hi_last]
|
||
have hnot_last_succ : ¬((S.card - 1 : ℕ) + 1 < S.card) := by omega
|
||
simp [cyclicGapAt, r, hnot_last_succ, hcard_pos, firstIdx, lastIdx,
|
||
Nat.cast_sub hlast_le, hM_cast]
|
||
have hlen :
|
||
M_int - (cyclicGapAt M_int.toNat S.card r i : ℕ) + 1 =
|
||
(hS.sortedResidues hM lastIdx : ℕ) - hS.sortedResidues hM firstIdx + 1 := by
|
||
rw [hcyc]
|
||
ring
|
||
simpa [r, firstIdx, lastIdx, hlen] using hwrap
|
||
|
||
-- ============================================================
|
||
-- Part 7: Gap-distinctness structure
|
||
-- ============================================================
|
||
|
||
/-- A finset of positive naturals summing to `M` models the cyclic gap
|
||
structure of a Sidon set. -/
|
||
structure DistinctPosPartsOf (M : ℕ) (k : ℕ) where
|
||
parts : Finset ℕ
|
||
card_eq : parts.card = k
|
||
pos : 0 ∉ parts
|
||
sum_eq : ∑ x ∈ parts, x = M
|
||
|
||
theorem DistinctPosPartsOf.nonempty {M k : ℕ}
|
||
(g : DistinctPosPartsOf M k) (hk : 0 < k) : g.parts.Nonempty := by
|
||
rw [Finset.nonempty_iff_ne_empty]
|
||
intro h
|
||
have h1 : g.parts.card = 0 := by rw [h, Finset.card_empty]
|
||
have h2 := g.card_eq
|
||
omega
|
||
|
||
/-- The sum of the elements of any `Finset ℕ` is at least the
|
||
`card`-th triangular number `card * (card − 1) / 2`. -/
|
||
theorem sum_finset_nat_ge_tri (s : Finset ℕ) :
|
||
s.card * (s.card - 1) / 2 ≤ ∑ x ∈ s, x := by
|
||
suffices h : s.card * (s.card - 1) ≤ 2 * ∑ x ∈ s, x by omega
|
||
have key : ∀ n, ∀ t : Finset ℕ, t.card = n →
|
||
n * (n - 1) ≤ 2 * ∑ x ∈ t, x := by
|
||
intro n
|
||
induction n using Nat.strongRecOn with
|
||
| ind n ih =>
|
||
intro t ht
|
||
cases n with
|
||
| zero => simp [Finset.card_eq_zero.mp ht]
|
||
| succ n =>
|
||
have hne : t.Nonempty := Finset.card_pos.mp (by omega)
|
||
set m := t.max' hne
|
||
have hm_mem : m ∈ t := Finset.max'_mem t hne
|
||
set t' := t.erase m
|
||
have ht'_card : t'.card = n := by
|
||
rw [Finset.card_erase_of_mem hm_mem]; omega
|
||
have hm_ge : n ≤ m := by
|
||
have hle : t.card ≤ t.max' hne + 1 := by
|
||
calc t.card
|
||
≤ (Finset.range (t.max' hne + 1)).card := by
|
||
apply Finset.card_le_card
|
||
intro x hx
|
||
exact Finset.mem_range.mpr (Nat.lt_succ_of_le (t.le_max' x hx))
|
||
_ = t.max' hne + 1 := Finset.card_range _
|
||
omega
|
||
have ih_t' : n * (n - 1) ≤ 2 * ∑ x ∈ t', x :=
|
||
ih n (by omega) t' ht'_card
|
||
have hsum : ∑ x ∈ t, x = ∑ x ∈ t', x + m :=
|
||
(Finset.sum_erase_add t (fun x => x) hm_mem).symm
|
||
rw [hsum]
|
||
simp only [Nat.succ_sub_one]
|
||
have hrec : n * (n - 1) + 2 * n = (n + 1) * n := by
|
||
cases n with
|
||
| zero => simp
|
||
| succ n => simp only [Nat.succ_sub_one]; ring
|
||
linarith
|
||
exact key s.card s rfl
|
||
|
||
/-- **Complement-max bound.** For a nonempty `Finset ℕ` with `0 ∉ s`,
|
||
the sum plus `card*(card − 1)/2` is at most `card * max`. -/
|
||
theorem sum_add_tri_le_card_mul_max (s : Finset ℕ) (hne : s.Nonempty) (_hpos : 0 ∉ s) :
|
||
(∑ x ∈ s, x) + s.card * (s.card - 1) / 2 ≤ s.card * s.max' hne := by
|
||
set m := s.max' hne
|
||
have hinj : Set.InjOn (fun x => m - x) ↑s := by
|
||
intro a ha b hb hab
|
||
have ha' : a ≤ m := s.le_max' a (show a ∈ s from ha)
|
||
have hb' : b ≤ m := s.le_max' b (show b ∈ s from hb)
|
||
have h1 : m - a + a = m := Nat.sub_add_cancel ha'
|
||
have h2 : m - b + b = m := Nat.sub_add_cancel hb'
|
||
have hab' : m - a = m - b := hab
|
||
omega
|
||
set t := s.image (fun x => m - x)
|
||
have ht_card : t.card = s.card := Finset.card_image_of_injOn hinj
|
||
have hsum_rel : ∑ y ∈ t, y + ∑ x ∈ s, x = s.card * m := by
|
||
show ∑ y ∈ s.image (fun x => m - x), y + ∑ x ∈ s, x = s.card * m
|
||
rw [Finset.sum_image hinj, ← Finset.sum_add_distrib]
|
||
rw [show s.card * m = ∑ _ ∈ s, m from
|
||
(Finset.sum_const_nat (fun _ _ => rfl)).symm]
|
||
apply Finset.sum_congr rfl
|
||
intro x hx
|
||
exact Nat.sub_add_cancel (s.le_max' x hx)
|
||
have htri := sum_finset_nat_ge_tri t
|
||
rw [ht_card] at htri
|
||
linarith
|
||
|
||
/-- **Gap lower bound.** If `M` is partitioned into `k ≥ 1` distinct
|
||
positive parts, the largest part is at least `(M + k(k−1)/2) / k`. -/
|
||
theorem max_gap_lower_bound {M k : ℕ} (g : DistinctPosPartsOf M k)
|
||
(hk : 0 < k) :
|
||
(M + k * (k - 1) / 2) / k ≤ g.parts.max' (g.nonempty hk) := by
|
||
have hbound := sum_add_tri_le_card_mul_max g.parts (g.nonempty hk) g.pos
|
||
rw [g.card_eq, g.sum_eq] at hbound
|
||
exact Nat.div_le_of_le_mul hbound
|
||
|
||
-- ============================================================
|
||
-- Part 8: Sidon gaps to DistinctPosPartsOf
|
||
-- ============================================================
|
||
|
||
private theorem mono_le_of_step (n : ℕ) (f : ℕ → ℕ)
|
||
(hf : ∀ i, i < n → f i ≤ f (i + 1)) : f 0 ≤ f n := by
|
||
induction n with
|
||
| zero => omega
|
||
| succ n ih =>
|
||
exact le_trans (ih (fun i hi => hf i (by omega))) (hf n (by omega))
|
||
|
||
private theorem nat_telescope (n : ℕ) (f : ℕ → ℕ)
|
||
(hf : ∀ i, i < n → f i ≤ f (i + 1)) :
|
||
(∑ i ∈ Finset.range n, (f (i + 1) - f i)) + f 0 = f n := by
|
||
induction n with
|
||
| zero => simp
|
||
| succ n ih =>
|
||
rw [Finset.sum_range_succ]
|
||
have h0n := mono_le_of_step n f (fun i hi => hf i (by omega))
|
||
have hnn1 : f n ≤ f (n + 1) := hf n (by omega)
|
||
have := ih (fun i hi => hf i (by omega))
|
||
omega
|
||
|
||
private theorem mono_le_of_adjacent {k : ℕ} {r : ℕ → ℕ}
|
||
(hr_mono : ∀ i, i + 1 < k → r i < r (i + 1))
|
||
{a b : ℕ} (hab : a ≤ b) (hb : b < k) :
|
||
r a ≤ r b := by
|
||
let g : ℕ → ℕ := fun t => r (a + t)
|
||
have hstep : ∀ i, i < b - a → g i ≤ g (i + 1) := by
|
||
intro i hi
|
||
dsimp [g]
|
||
exact le_of_lt (hr_mono (a + i) (by omega))
|
||
have hmono := mono_le_of_step (b - a) g hstep
|
||
dsimp [g] at hmono
|
||
simpa [Nat.add_sub_of_le hab] using hmono
|
||
|
||
theorem cyclicGapAt_pos {M k : ℕ} {r : ℕ → ℕ} (_hk : 2 ≤ k)
|
||
(hMono : ∀ i, i + 1 < k → r i < r (i + 1))
|
||
(hBound : r (k - 1) < M)
|
||
{i : ℕ} (_hi : i < k) :
|
||
0 < cyclicGapAt M k r i := by
|
||
simp only [cyclicGapAt]
|
||
split
|
||
· have := hMono i (by omega); omega
|
||
· omega
|
||
|
||
theorem cyclicGapAt_sum {M k : ℕ} {r : ℕ → ℕ} (hk : 2 ≤ k)
|
||
(hMono : ∀ i, i + 1 < k → r i < r (i + 1))
|
||
(hBound : r (k - 1) < M) :
|
||
∑ i ∈ Finset.range k, cyclicGapAt M k r i = M := by
|
||
have hsplit : ∑ i ∈ Finset.range k, cyclicGapAt M k r i =
|
||
(∑ i ∈ Finset.range (k - 1), cyclicGapAt M k r i) +
|
||
cyclicGapAt M k r (k - 1) := by
|
||
have h := Finset.sum_range_succ (cyclicGapAt M k r) (k - 1)
|
||
rwa [show k - 1 + 1 = k from by omega] at h
|
||
rw [hsplit]
|
||
have hlast : cyclicGapAt M k r (k - 1) = M - r (k - 1) + r 0 := by
|
||
simp only [cyclicGapAt]; split <;> omega
|
||
rw [hlast]
|
||
have hfirst : ∀ i ∈ Finset.range (k - 1),
|
||
cyclicGapAt M k r i = r (i + 1) - r i := by
|
||
intro i hi
|
||
simp only [cyclicGapAt]
|
||
have him : i < k - 1 := Finset.mem_range.mp hi
|
||
split
|
||
· rfl
|
||
· omega
|
||
rw [Finset.sum_congr rfl hfirst]
|
||
have hle : ∀ i, i < k - 1 → r i ≤ r (i + 1) :=
|
||
fun i hi => le_of_lt (hMono i (by omega))
|
||
have := nat_telescope (k - 1) r hle
|
||
have := mono_le_of_step (k - 1) r hle
|
||
omega
|
||
|
||
/-- **Gap injectivity.** If a sorted sequence of residues comes from a
|
||
modular Sidon set, then the cyclic gap function is injective. -/
|
||
theorem cyclicGapAt_injective_of_sidon
|
||
{M_int : ℤ} {S : Finset ℤ}
|
||
(hS : IsSidonMod M_int S) (hM : 0 < M_int)
|
||
{k : ℕ} (hk : 2 ≤ k)
|
||
(f : ℕ → ℤ)
|
||
(hf_mem : ∀ i, i < k → f i ∈ S)
|
||
(hf_inj : ∀ i j, i < k → j < k → f i = f j → i = j)
|
||
(r : ℕ → ℕ)
|
||
(hr_def : ∀ i, i < k → (r i : ℤ) = f i % M_int)
|
||
(hr_mono : ∀ i, i + 1 < k → r i < r (i + 1))
|
||
(hr_bound : r (k - 1) < M_int.toNat) :
|
||
∀ i j, i < k → j < k →
|
||
cyclicGapAt M_int.toNat k r i = cyclicGapAt M_int.toNat k r j → i = j := by
|
||
set M := M_int.toNat
|
||
intro i j hi hj heq
|
||
have hM_cast : M_int = (M : ℤ) := (Int.toNat_of_nonneg (le_of_lt hM)).symm
|
||
have hf_ne : ∀ a b, a < k → b < k → a ≠ b → f a ≠ f b :=
|
||
fun a b ha hb hab hf => absurd (hf_inj a b ha hb hf) hab
|
||
by_cases hi_wrap : i + 1 < k <;> by_cases hj_wrap : j + 1 < k
|
||
· simp only [cyclicGapAt, hi_wrap, hj_wrap, ↓reduceIte] at heq
|
||
have hri_le : r i ≤ r (i + 1) := le_of_lt (hr_mono i hi_wrap)
|
||
have hrj_le : r j ≤ r (j + 1) := le_of_lt (hr_mono j hj_wrap)
|
||
have h_resid : f (i + 1) % M_int - f i % M_int =
|
||
f (j + 1) % M_int - f j % M_int := by
|
||
rw [← hr_def i (by omega), ← hr_def (i + 1) (by omega),
|
||
← hr_def j (by omega), ← hr_def (j + 1) (by omega)]
|
||
have h1 : (↑(r (i + 1) - r i) : ℤ) = ↑(r (i + 1)) - ↑(r i) :=
|
||
Nat.cast_sub hri_le
|
||
have h2 : (↑(r (j + 1) - r j) : ℤ) = ↑(r (j + 1)) - ↑(r j) :=
|
||
Nat.cast_sub hrj_le
|
||
have h3 : (r (i + 1) - r i : ℕ) = r (j + 1) - r j := heq
|
||
have h3_cast : (↑(r (i + 1) - r i) : ℤ) = ↑(r (j + 1) - r j) := by exact_mod_cast h3
|
||
linarith [h3_cast]
|
||
have hdvd : M_int ∣ ((f (i + 1) - f i) - (f (j + 1) - f j)) :=
|
||
dvd_diff_of_residue_diff (by rw [h_resid, sub_self]; exact dvd_zero _)
|
||
have hab : f i ≠ f (i + 1) := hf_ne i (i + 1) (by omega) (by omega) (by omega)
|
||
have ⟨_, h2⟩ := hS.diff_eq (hf_mem (i + 1) (by omega)) (hf_mem i (by omega))
|
||
(hf_mem (j + 1) (by omega)) (hf_mem j (by omega))
|
||
(Ne.symm hab) hdvd
|
||
exact hf_inj i j (by omega) (by omega) h2
|
||
· have hj_eq : j = k - 1 := by omega
|
||
subst hj_eq
|
||
simp only [cyclicGapAt, hi_wrap, show ¬(k - 1 + 1 < k) from by omega,
|
||
↓reduceIte] at heq
|
||
have hri_le : r i ≤ r (i + 1) := le_of_lt (hr_mono i hi_wrap)
|
||
have hrk_le : r (k - 1) ≤ M := le_of_lt hr_bound
|
||
have h_resid : (f (i + 1) % M_int - f i % M_int) -
|
||
(f 0 % M_int - f (k - 1) % M_int) = M_int := by
|
||
rw [← hr_def i (by omega), ← hr_def (i + 1) (by omega),
|
||
← hr_def 0 (by omega), ← hr_def (k - 1) (by omega)]
|
||
have h1 : (↑(r (i + 1) - r i) : ℤ) = ↑(r (i + 1)) - ↑(r i) :=
|
||
Nat.cast_sub hri_le
|
||
have h2 : (↑(M - r (k - 1)) : ℤ) = ↑M - ↑(r (k - 1)) :=
|
||
Nat.cast_sub hrk_le
|
||
have heq_cast : (↑(r (i + 1) - r i) : ℤ) = ↑(M - r (k - 1) + r 0) := by exact_mod_cast heq
|
||
linarith [heq_cast, hM_cast]
|
||
have hdvd : M_int ∣ ((f (i + 1) - f i) - (f 0 - f (k - 1))) :=
|
||
dvd_diff_of_residue_diff ⟨1, by linarith [h_resid]⟩
|
||
have hab : f i ≠ f (i + 1) := hf_ne i (i + 1) (by omega) (by omega) (by omega)
|
||
have ⟨h1, _⟩ := hS.diff_eq (hf_mem (i + 1) (by omega)) (hf_mem i (by omega))
|
||
(hf_mem 0 (by omega)) (hf_mem (k - 1) (by omega))
|
||
(Ne.symm hab) hdvd
|
||
exact absurd (hf_inj (i + 1) 0 (by omega) (by omega) h1) (by omega)
|
||
· have hi_eq : i = k - 1 := by omega
|
||
subst hi_eq
|
||
simp only [cyclicGapAt, show ¬(k - 1 + 1 < k) from by omega, hj_wrap,
|
||
↓reduceIte] at heq
|
||
have hrj_le : r j ≤ r (j + 1) := le_of_lt (hr_mono j hj_wrap)
|
||
have hrk_le : r (k - 1) ≤ M := le_of_lt hr_bound
|
||
have h_resid : (f 0 % M_int - f (k - 1) % M_int) -
|
||
(f (j + 1) % M_int - f j % M_int) = -M_int := by
|
||
rw [← hr_def 0 (by omega), ← hr_def (k - 1) (by omega),
|
||
← hr_def j (by omega), ← hr_def (j + 1) (by omega)]
|
||
have h1 : (↑(r (j + 1) - r j) : ℤ) = ↑(r (j + 1)) - ↑(r j) :=
|
||
Nat.cast_sub hrj_le
|
||
have h2 : (↑(M - r (k - 1)) : ℤ) = ↑M - ↑(r (k - 1)) :=
|
||
Nat.cast_sub hrk_le
|
||
have heq_cast : (↑(M - r (k - 1) + r 0) : ℤ) = ↑(r (j + 1) - r j) := by exact_mod_cast heq
|
||
linarith [heq_cast, hM_cast]
|
||
have hdvd : M_int ∣ ((f 0 - f (k - 1)) - (f (j + 1) - f j)) :=
|
||
dvd_diff_of_residue_diff ⟨-1, by linarith [h_resid]⟩
|
||
have hab : f (k - 1) ≠ f 0 :=
|
||
hf_ne (k - 1) 0 (by omega) (by omega) (by omega)
|
||
have ⟨h1, _⟩ := hS.diff_eq (hf_mem 0 (by omega)) (hf_mem (k - 1) (by omega))
|
||
(hf_mem (j + 1) (by omega)) (hf_mem j (by omega))
|
||
(Ne.symm hab) hdvd
|
||
exact absurd (hf_inj 0 (j + 1) (by omega) (by omega) h1) (by omega)
|
||
· omega
|
||
|
||
/-- **Sidon gap-distinctness bridge.** Given a modular Sidon set `S` of
|
||
size `k ≥ 2` in `ℤ/Mℤ`, together with an explicit sorted enumeration of
|
||
its residues, the cyclic gaps form a `DistinctPosPartsOf M k`. -/
|
||
noncomputable def sidon_gaps_to_distinctPosPartsOf
|
||
{M_int : ℤ} {S : Finset ℤ}
|
||
(hS : IsSidonMod M_int S) (hM : 0 < M_int)
|
||
{k : ℕ} (hk : 2 ≤ k) (_hcard : S.card = k)
|
||
(f : ℕ → ℤ)
|
||
(hf_mem : ∀ i, i < k → f i ∈ S)
|
||
(hf_inj : ∀ i j, i < k → j < k → f i = f j → i = j)
|
||
(r : ℕ → ℕ)
|
||
(hr_def : ∀ i, i < k → (r i : ℤ) = f i % M_int)
|
||
(hr_mono : ∀ i, i + 1 < k → r i < r (i + 1))
|
||
(hr_bound : r (k - 1) < M_int.toNat) :
|
||
DistinctPosPartsOf M_int.toNat k where
|
||
parts := (Finset.range k).image (cyclicGapAt M_int.toNat k r)
|
||
card_eq := by
|
||
apply Eq.trans (Finset.card_image_of_injOn _) (Finset.card_range k)
|
||
intro i hi j hj heq
|
||
have hi' : i < k := Finset.mem_range.mp (Finset.mem_coe.mp hi)
|
||
have hj' : j < k := Finset.mem_range.mp (Finset.mem_coe.mp hj)
|
||
exact cyclicGapAt_injective_of_sidon hS hM hk f hf_mem hf_inj
|
||
r hr_def hr_mono hr_bound i j hi' hj' heq
|
||
pos := by
|
||
intro h0
|
||
rw [Finset.mem_image] at h0
|
||
obtain ⟨i, hi, hgap⟩ := h0
|
||
rw [Finset.mem_range] at hi
|
||
have := cyclicGapAt_pos hk hr_mono hr_bound hi
|
||
omega
|
||
sum_eq := by
|
||
rw [Finset.sum_image]
|
||
· exact cyclicGapAt_sum hk hr_mono hr_bound
|
||
· intro i hi j hj heq
|
||
exact cyclicGapAt_injective_of_sidon hS hM hk f hf_mem hf_inj
|
||
r hr_def hr_mono hr_bound i j (Finset.mem_range.mp hi) (Finset.mem_range.mp hj) heq
|
||
|
||
-- ============================================================
|
||
-- Part 9: Main theorem — exists_full_intervalSidon_of_quantitative_gap_bound
|
||
-- ============================================================
|
||
|
||
|
||
/-- Residue map s % M is injective on an IsSidonMod M set. -/
|
||
theorem IsSidonMod.residue_inj_on {M : ℤ} {S : Finset ℤ} (hS : IsSidonMod M S) (hM : M ≠ 0) (x y : ℤ) (hx : x ∈ S) (hy : y ∈ S) (hres : x % M = y % M) : x = y := by
|
||
by_contra hne
|
||
have hsub : x - y = M * (x / M - y / M) := by
|
||
nlinarith [Int.ediv_add_emod x M, Int.ediv_add_emod y M, hres]
|
||
have hmod : M ∣ (x + x) - (x + y) := by
|
||
have : (x + x) - (x + y) = x - y := by ring
|
||
rw [this, hsub]
|
||
exact ⟨x / M - y / M, by ring⟩
|
||
have hS' := hS hx hx hx hy hmod
|
||
rcases hS' with ⟨hac, hbd⟩ | ⟨had, hbc⟩
|
||
· exact hne hbd
|
||
· exact hne had
|
||
|
||
/-- Singer set via residues: A = {s % M + 1 : s ∈ S} is IsIntervalSidon N, |A| = p+1. -/
|
||
theorem singerIntervalSidon (p N : ℕ) (hp : Nat.Prime p) (hN : p * p + p + 1 ≤ N) :
|
||
∃ A : Finset ℤ, IsIntervalSidon (N : ℤ) A ∧ A.card = p + 1 := by
|
||
rcases singerFamilyHypothesis_holds p hp with ⟨S, hS, hcard⟩
|
||
set M := (p * p + p + 1 : ℤ) with hM_def
|
||
have hp_pos : 0 < p := hp.pos
|
||
have hM_pos : M ≠ 0 := by positivity
|
||
have hM_N : M ≤ (N : ℤ) := by
|
||
simpa [hM_def] using mod_cast hN
|
||
have hinj_on : ∀ (x y : ℤ), x ∈ S → y ∈ S → x % M = y % M → x = y :=
|
||
hS.residue_inj_on hM_pos
|
||
let A := Finset.image (fun (s : ℤ) => s % M + 1) S
|
||
have hA_card : A.card = p + 1 := by
|
||
have hinj_on_S : Set.InjOn (fun (s : ℤ) => s % M + 1) (S : Set ℤ) := by
|
||
intro x hxS y hyS h
|
||
apply hinj_on x y hxS hyS
|
||
-- h : (x % M + 1) = (y % M + 1), so x % M = y % M
|
||
linarith
|
||
calc
|
||
A.card = S.card := Finset.card_image_of_injOn hinj_on_S
|
||
_ = p + 1 := hcard
|
||
have hA_sub : ∀ a ∈ A, 1 ≤ a ∧ a ≤ (N : ℤ) := by
|
||
intro a ha
|
||
rcases Finset.mem_image.mp ha with ⟨s, hs, rfl⟩
|
||
have h_nonneg : 0 ≤ s % M := Int.emod_nonneg s (by intro h; exact hM_pos (h.symm ▸ rfl))
|
||
have h_lt : s % M < M := Int.emod_lt s hM_pos
|
||
have h_bound : s % M + 1 ≤ (N : ℤ) := by
|
||
have : s % M + 1 ≤ M := by omega
|
||
omega
|
||
exact ⟨by omega, h_bound⟩
|
||
have hA_sidon : IsSidon A := by
|
||
intro a b c d ha hb hc hd hsum
|
||
rcases Finset.mem_image.mp ha with ⟨s₁, hs₁, rfl⟩
|
||
rcases Finset.mem_image.mp hb with ⟨s₂, hs₂, rfl⟩
|
||
rcases Finset.mem_image.mp hc with ⟨s₃, hs₃, rfl⟩
|
||
rcases Finset.mem_image.mp hd with ⟨s₄, hs₄, rfl⟩
|
||
have hsum_mod : s₁ % M + s₂ % M = s₃ % M + s₄ % M := by
|
||
linarith
|
||
have hM_dvd_each : ∀ (s : ℤ), M ∣ s - s % M := by
|
||
intro s
|
||
have : s - s % M = M * (s / M) := by
|
||
nlinarith [Int.ediv_add_emod s M]
|
||
rw [this]
|
||
exact ⟨s / M, by ring⟩
|
||
have hM_dvd : M ∣ (s₁ + s₂) - (s₃ + s₄) := by
|
||
have h_sub : M ∣ (s₁ - s₁ % M) + (s₂ - s₂ % M) - (s₃ - s₃ % M) - (s₄ - s₄ % M) := by
|
||
have h_sum : M ∣ (s₁ - s₁ % M) + (s₂ - s₂ % M) := dvd_add (hM_dvd_each s₁) (hM_dvd_each s₂)
|
||
have h_sum' : M ∣ (s₃ - s₃ % M) + (s₄ - s₄ % M) := dvd_add (hM_dvd_each s₃) (hM_dvd_each s₄)
|
||
have h_sub' : M ∣ (s₁ - s₁ % M) + (s₂ - s₂ % M) - ((s₃ - s₃ % M) + (s₄ - s₄ % M)) :=
|
||
dvd_sub h_sum h_sum'
|
||
simpa [sub_sub] using h_sub'
|
||
have h_mod_zero : s₁ % M + s₂ % M - s₃ % M - s₄ % M = 0 := by
|
||
rw [hsum_mod]; ring
|
||
have h_eq : (s₁ + s₂) - (s₃ + s₄) = ((s₁ - s₁ % M) + (s₂ - s₂ % M) - (s₃ - s₃ % M) - (s₄ - s₄ % M)) := by
|
||
calc
|
||
(s₁ + s₂) - (s₃ + s₄) = ((s₁ - s₁ % M) + (s₂ - s₂ % M) - (s₃ - s₃ % M) - (s₄ - s₄ % M))
|
||
+ (s₁ % M + s₂ % M - s₃ % M - s₄ % M) := by ring
|
||
_ = ((s₁ - s₁ % M) + (s₂ - s₂ % M) - (s₃ - s₃ % M) - (s₄ - s₄ % M)) + 0 := by rw [h_mod_zero]
|
||
_ = ((s₁ - s₁ % M) + (s₂ - s₂ % M) - (s₃ - s₃ % M) - (s₄ - s₄ % M)) := by ring
|
||
rw [h_eq]
|
||
exact h_sub
|
||
have hS' := hS hs₁ hs₂ hs₃ hs₄ hM_dvd
|
||
rcases hS' with (⟨h₁, h₂⟩ | ⟨h₁, h₂⟩)
|
||
· left; constructor
|
||
· apply congrArg (fun x : ℤ => x % M + 1) h₁
|
||
· apply congrArg (fun x : ℤ => x % M + 1) h₂
|
||
· right; constructor
|
||
· apply congrArg (fun x : ℤ => x % M + 1) h₁
|
||
· apply congrArg (fun x : ℤ => x % M + 1) h₂
|
||
exact ⟨A, ⟨hA_sub, hA_sidon⟩, hA_card⟩
|
||
|
||
/-! ## Conditional Erdős Problem 30 -/
|
||
|
||
/-- Helper: `Nat.sqrt N` is a lower bound for the real square root. -/
|
||
private lemma natSqrt_le_real_sqrt (N : ℕ) :
|
||
(Nat.sqrt N : ℝ) ≤ Real.sqrt (N : ℝ) := by
|
||
have hs : Nat.sqrt N * Nat.sqrt N ≤ N := Nat.le_sqrt.1 (le_refl (Nat.sqrt N))
|
||
calc
|
||
(Nat.sqrt N : ℝ) = Real.sqrt ((Nat.sqrt N : ℝ) * (Nat.sqrt N : ℝ)) :=
|
||
(Real.sqrt_mul_self (Nat.cast_nonneg _)).symm
|
||
_ ≤ Real.sqrt (N : ℝ) := Real.sqrt_le_sqrt (by exact_mod_cast hs)
|
||
|
||
/-- Helper: the real square root lies strictly below `Nat.sqrt N + 1`. -/
|
||
private lemma real_sqrt_lt_natSqrt_add_one (N : ℕ) :
|
||
Real.sqrt (N : ℝ) < (Nat.sqrt N : ℝ) + 1 := by
|
||
have hlt : N < (Nat.sqrt N + 1) * (Nat.sqrt N + 1) := Nat.lt_succ_sqrt N
|
||
have hpos : (0 : ℝ) ≤ (Nat.sqrt N : ℝ) + 1 := by positivity
|
||
calc
|
||
Real.sqrt (N : ℝ)
|
||
< Real.sqrt (((Nat.sqrt N : ℝ) + 1) * ((Nat.sqrt N : ℝ) + 1)) :=
|
||
Real.sqrt_lt_sqrt (Nat.cast_nonneg N) (by exact_mod_cast hlt)
|
||
_ = (Nat.sqrt N : ℝ) + 1 := Real.sqrt_mul_self hpos
|
||
|
||
/-- Helper: a prime `p` with `p + 2 ≤ Nat.sqrt N` has its Singer modulus
|
||
`p² + p + 1` below `N`, so the Singer set fits inside `{1, …, N}`. -/
|
||
private lemma singer_modulus_fits {p N : ℕ}
|
||
(hpN : p + 2 ≤ Nat.sqrt N) : p * p + p + 1 ≤ N := by
|
||
have hs : Nat.sqrt N * Nat.sqrt N ≤ N := Nat.le_sqrt.1 (le_refl (Nat.sqrt N))
|
||
have h2 : (p + 2) * (p + 2) ≤ Nat.sqrt N * Nat.sqrt N := Nat.mul_le_mul hpN hpN
|
||
nlinarith
|
||
|
||
/-- **Conditional Erdős Problem 30.** A subpolynomial prime-gap hypothesis
|
||
around `√N`, together with an upper-bound hypothesis
|
||
`h(N) ≤ √N + C·N^ε`, implies the full Erdős Problem 30 statement.
|
||
|
||
For ε ≥ 1/2 the bilateral bound is already unconditional
|
||
(`erdos30_partial_half`). For ε < 1/2 the lower side is supplied by the
|
||
Singer construction: the prime-gap hypothesis is applied at the shifted
|
||
perfect square `(Nat.sqrt N - t)²` with `t = ⌈N^ε⌉ + 2`, which forces the
|
||
resulting prime `p` to satisfy `p + 2 ≤ Nat.sqrt N` — so Singer's Sidon
|
||
set mod `p² + p + 1` fits inside `{1, …, N}` — while still keeping
|
||
`p ≥ √N - O(N^ε)`. -/
|
||
theorem conditional_erdos30
|
||
(h_prime_gap : ∀ ε : ℝ, 0 < ε →
|
||
∃ N₀ : ℕ, ∀ N ≥ N₀, ∃ p : ℕ, Nat.Prime p ∧
|
||
|(p : ℝ) - Real.sqrt (N : ℝ)| ≤ Real.rpow (N : ℝ) ε)
|
||
(h_upper : ∀ ε : ℝ, 0 < ε →
|
||
∃ C : ℝ, ∃ N0 : ℕ, 0 < C ∧
|
||
∀ {N h : ℕ}, N0 ≤ N → IsSidonMaximum N h →
|
||
(h : ℝ) ≤ Real.sqrt (N : ℝ) + C * Real.rpow (N : ℝ) ε) :
|
||
Erdos30Statement := by
|
||
intro ε hε_pos
|
||
by_cases hε_half : (1 : ℝ) / 2 ≤ ε
|
||
· -- For ε ≥ 1/2 the bilateral bound is unconditional.
|
||
exact erdos30_partial_half ε hε_half hε_pos
|
||
push_neg at hε_half
|
||
-- ε < 1/2: combine the upper hypothesis with the Singer/prime-gap lower bound.
|
||
obtain ⟨C_up, N_up, hC_up_pos, hC_up⟩ := h_upper ε hε_pos
|
||
obtain ⟨N_gap, hgap⟩ := h_prime_gap ε hε_pos
|
||
have hγ_pos : (0 : ℝ) < 1 / 2 - ε := by linarith
|
||
-- Threshold beyond which N^(1/2 - ε) ≥ 2, i.e. N^ε ≤ √N / 2.
|
||
obtain ⟨n1, hn1⟩ := exists_nat_ge ((2 : ℝ) ^ ((1 : ℝ) / (1 / 2 - ε)))
|
||
obtain ⟨B, hB_def⟩ : ∃ B : ℕ, B = N_gap + 1 := ⟨_, rfl⟩
|
||
refine ⟨C_up + 5, n1 + (2 * B + 8) * (2 * B + 8) + N_up + 1, by linarith, ?_⟩
|
||
intro N h hN hmax
|
||
-- Write `Real.rpow` multiplicatively as `^` throughout.
|
||
have hrpow_def : ∀ x y : ℝ, Real.rpow x y = x ^ y := fun _ _ => rfl
|
||
simp only [hrpow_def] at hgap hC_up ⊢
|
||
-- Basic bounds packaged into the chosen N₀.
|
||
have hN_up : N_up ≤ N := by omega
|
||
have hN1 : 1 ≤ N := by omega
|
||
have hn1N : n1 ≤ N := by omega
|
||
have hB_sq_le : (2 * B + 8) * (2 * B + 8) ≤ N := by omega
|
||
have hN_real_one : (1 : ℝ) ≤ (N : ℝ) := by exact_mod_cast hN1
|
||
have hN_real_pos : (0 : ℝ) < (N : ℝ) := by linarith
|
||
have hrpow_pos : (0 : ℝ) < (N : ℝ) ^ ε := Real.rpow_pos_of_pos hN_real_pos ε
|
||
have hrpow_ge_one : (1 : ℝ) ≤ (N : ℝ) ^ ε := by
|
||
have h1 : (1 : ℝ) ^ ε ≤ (N : ℝ) ^ ε :=
|
||
Real.rpow_le_rpow (by norm_num) hN_real_one hε_pos.le
|
||
simpa using h1
|
||
-- Step 1: 2 · N^ε ≤ √N once N ≥ n1.
|
||
have h_two_le_rpow_gap : (2 : ℝ) ≤ (N : ℝ) ^ (1 / 2 - ε) := by
|
||
have h2pos : (0 : ℝ) ≤ (2 : ℝ) ^ ((1 : ℝ) / (1 / 2 - ε)) := by positivity
|
||
have hbase : (2 : ℝ) ^ ((1 : ℝ) / (1 / 2 - ε)) ≤ (N : ℝ) :=
|
||
le_trans hn1 (by exact_mod_cast hn1N)
|
||
have hmono : ((2 : ℝ) ^ ((1 : ℝ) / (1 / 2 - ε))) ^ (1 / 2 - ε) ≤
|
||
(N : ℝ) ^ (1 / 2 - ε) :=
|
||
Real.rpow_le_rpow h2pos hbase hγ_pos.le
|
||
have heq : ((2 : ℝ) ^ ((1 : ℝ) / (1 / 2 - ε))) ^ (1 / 2 - ε) = 2 := by
|
||
rw [← Real.rpow_mul (by norm_num : (0 : ℝ) ≤ 2),
|
||
one_div_mul_cancel (ne_of_gt hγ_pos), Real.rpow_one]
|
||
linarith [hmono, heq.le, heq.symm.le]
|
||
have h_rpow_le_half_sqrt : 2 * (N : ℝ) ^ ε ≤ Real.sqrt (N : ℝ) := by
|
||
have hsplit : Real.sqrt (N : ℝ) = (N : ℝ) ^ ε * (N : ℝ) ^ (1 / 2 - ε) := by
|
||
rw [Real.sqrt_eq_rpow, ← Real.rpow_add hN_real_pos]
|
||
congr 1
|
||
ring
|
||
calc
|
||
2 * (N : ℝ) ^ ε = (N : ℝ) ^ ε * 2 := by ring
|
||
_ ≤ (N : ℝ) ^ ε * (N : ℝ) ^ (1 / 2 - ε) :=
|
||
mul_le_mul_of_nonneg_left h_two_le_rpow_gap hrpow_pos.le
|
||
_ = Real.sqrt (N : ℝ) := hsplit.symm
|
||
-- Step 2: 2B + 8 ≤ √N once N ≥ (2B + 8)².
|
||
have h_B_le_sqrt : 2 * (B : ℝ) + 8 ≤ Real.sqrt (N : ℝ) := by
|
||
have hcast : ((2 * B + 8 : ℕ) : ℝ) ≤ Real.sqrt (N : ℝ) := by
|
||
calc
|
||
((2 * B + 8 : ℕ) : ℝ)
|
||
= Real.sqrt (((2 * B + 8 : ℕ) : ℝ) * ((2 * B + 8 : ℕ) : ℝ)) :=
|
||
(Real.sqrt_mul_self (Nat.cast_nonneg _)).symm
|
||
_ ≤ Real.sqrt (N : ℝ) := Real.sqrt_le_sqrt (by exact_mod_cast hB_sq_le)
|
||
have hpush : ((2 * B + 8 : ℕ) : ℝ) = 2 * (B : ℝ) + 8 := by push_cast; ring
|
||
linarith [hcast, hpush.le, hpush.symm.le]
|
||
-- The shift amount t and the shifted square target M = (Nat.sqrt N − t)².
|
||
obtain ⟨t, ht_def⟩ : ∃ t : ℕ, t = ⌈(N : ℝ) ^ ε⌉₊ + 2 := ⟨_, rfl⟩
|
||
have ht_le : (t : ℝ) ≤ (N : ℝ) ^ ε + 3 := by
|
||
have hceil : (⌈(N : ℝ) ^ ε⌉₊ : ℝ) < (N : ℝ) ^ ε + 1 :=
|
||
Nat.ceil_lt_add_one hrpow_pos.le
|
||
rw [ht_def]
|
||
push_cast
|
||
linarith
|
||
have ht_ge : (N : ℝ) ^ ε + 2 ≤ (t : ℝ) := by
|
||
have hceil : (N : ℝ) ^ ε ≤ (⌈(N : ℝ) ^ ε⌉₊ : ℝ) := Nat.le_ceil _
|
||
rw [ht_def]
|
||
push_cast
|
||
linarith
|
||
have hs_le_sqrt : (Nat.sqrt N : ℝ) ≤ Real.sqrt (N : ℝ) := natSqrt_le_real_sqrt N
|
||
have hsqrt_lt : Real.sqrt (N : ℝ) < (Nat.sqrt N : ℝ) + 1 :=
|
||
real_sqrt_lt_natSqrt_add_one N
|
||
have h_tB_le_s : t + B ≤ Nat.sqrt N := by
|
||
have hreal : (t : ℝ) + (B : ℝ) ≤ (Nat.sqrt N : ℝ) := by linarith
|
||
exact_mod_cast hreal
|
||
obtain ⟨m, hm_def⟩ : ∃ m : ℕ, m = Nat.sqrt N - t := ⟨_, rfl⟩
|
||
have hm_add : m + t = Nat.sqrt N := by omega
|
||
have hm_B : B ≤ m := by omega
|
||
obtain ⟨M, hM_def⟩ : ∃ M : ℕ, M = m * m := ⟨_, rfl⟩
|
||
-- The target M is large enough for the prime-gap hypothesis…
|
||
have hM_gap : N_gap ≤ M := by
|
||
have hB1 : 1 ≤ B := by omega
|
||
have h1 : B ≤ B * B := by nlinarith
|
||
have h2 : B * B ≤ m * m := Nat.mul_le_mul hm_B hm_B
|
||
omega
|
||
-- …and sits below N.
|
||
have hM_le_N : M ≤ N := by
|
||
have h1 : m ≤ Nat.sqrt N := by omega
|
||
have h2 : m * m ≤ Nat.sqrt N * Nat.sqrt N := Nat.mul_le_mul h1 h1
|
||
have h3 : Nat.sqrt N * Nat.sqrt N ≤ N := Nat.le_sqrt.1 (le_refl (Nat.sqrt N))
|
||
omega
|
||
obtain ⟨p, hp_prime, hp_gap⟩ := hgap M hM_gap
|
||
have hsqrtM : Real.sqrt (M : ℝ) = (m : ℝ) := by
|
||
rw [hM_def]
|
||
push_cast
|
||
exact Real.sqrt_mul_self (Nat.cast_nonneg m)
|
||
have hMrpow_le : (M : ℝ) ^ ε ≤ (N : ℝ) ^ ε :=
|
||
Real.rpow_le_rpow (Nat.cast_nonneg M) (by exact_mod_cast hM_le_N) hε_pos.le
|
||
have hp_abs : |(p : ℝ) - (m : ℝ)| ≤ (N : ℝ) ^ ε := by
|
||
rw [← hsqrtM]
|
||
exact le_trans hp_gap hMrpow_le
|
||
have hp_bounds := abs_le.mp hp_abs
|
||
have hm_real : (m : ℝ) + (t : ℝ) = (Nat.sqrt N : ℝ) := by exact_mod_cast hm_add
|
||
-- The prime sits safely below Nat.sqrt N…
|
||
have hp_add_two_le_s : p + 2 ≤ Nat.sqrt N := by
|
||
have hreal : (p : ℝ) + 2 ≤ (Nat.sqrt N : ℝ) := by
|
||
have h1 : (p : ℝ) - (m : ℝ) ≤ (N : ℝ) ^ ε := hp_bounds.2
|
||
linarith [ht_ge]
|
||
exact_mod_cast hreal
|
||
-- …so the Singer construction at p fits inside {1, …, N}.
|
||
have h_fits : p * p + p + 1 ≤ N := singer_modulus_fits hp_add_two_le_s
|
||
obtain ⟨A, hA_sidon, hA_card⟩ := singerIntervalSidon p N hp_prime h_fits
|
||
have hp_succ_le_h : p + 1 ≤ h := by
|
||
have hcard_le := hmax.2 hA_sidon
|
||
omega
|
||
-- Lower side: √N − h ≤ 5 · N^ε.
|
||
have h_lower_abs : Real.sqrt (N : ℝ) - (h : ℝ) ≤ 5 * (N : ℝ) ^ ε := by
|
||
have hp_ge : (m : ℝ) - (N : ℝ) ^ ε ≤ (p : ℝ) := by
|
||
have h1 : -((N : ℝ) ^ ε) ≤ (p : ℝ) - (m : ℝ) := hp_bounds.1
|
||
linarith
|
||
have hh_real : (p : ℝ) + 1 ≤ (h : ℝ) := by exact_mod_cast hp_succ_le_h
|
||
linarith [hsqrt_lt, ht_le, hrpow_ge_one]
|
||
-- Upper side from the hypothesis.
|
||
have h_upper_abs : (h : ℝ) - Real.sqrt (N : ℝ) ≤ C_up * (N : ℝ) ^ ε := by
|
||
have hup := hC_up hN_up hmax
|
||
linarith
|
||
have hCupR_pos : (0 : ℝ) < C_up * (N : ℝ) ^ ε := mul_pos hC_up_pos hrpow_pos
|
||
rw [abs_le]
|
||
constructor
|
||
· linarith
|
||
· linarith
|
||
|
||
/-- **Lower bound on sidonMaximum: (√N + 1) / 2 < sidonMaximum N for N ≥ 5.** -/
|
||
theorem sidonMaximum_gt_sqrt_div_two (N : ℕ) (hN : 5 ≤ N) :
|
||
(Nat.sqrt N + 1) / 2 < sidonMaximum N := by
|
||
by_cases h9 : 9 ≤ N
|
||
· -- N ≥ 9: use Singer + Bertrand
|
||
set m := Nat.sqrt N with hm_def
|
||
set n := (m - 1) / 2 with hn_def
|
||
have hm3 : 3 ≤ m := by
|
||
rw [hm_def]
|
||
exact Nat.le_sqrt.2 h9
|
||
have hn_ne : n ≠ 0 := by
|
||
intro hnz
|
||
have hm_lt3 : m < 3 := by
|
||
rw [hn_def] at hnz
|
||
omega
|
||
have : 3 ≤ m := hm3
|
||
omega
|
||
rcases Nat.exists_prime_lt_and_le_two_mul n hn_ne with ⟨p, hp, hnp, hp2n⟩
|
||
have hpn : p ≤ m := by
|
||
have h2n_plus1 : 2 * n + 1 ≤ m := by
|
||
rw [hn_def]
|
||
omega
|
||
omega
|
||
have hp_bound : p * p + p + 1 ≤ N := by
|
||
have hN_sq : m * m ≤ N := by
|
||
have := Nat.sqrt_le' N
|
||
simpa [hm_def, pow_two] using this
|
||
have hpm1 : p ≤ m - 1 := by
|
||
have h2n_plus1 : 2 * n + 1 ≤ m := by
|
||
rw [hn_def]; omega
|
||
omega
|
||
have hp_sq : p * p ≤ (m - 1) * (m - 1) := Nat.mul_le_mul hpm1 hpm1
|
||
have : p * p + p + 1 ≤ m * m := by
|
||
have hm_pos : 0 < m := by
|
||
have : 3 ≤ m := hm3
|
||
omega
|
||
have h_le : p * p + p + 1 ≤ (m - 1) * (m - 1) + (m - 1) + 1 := by
|
||
nlinarith
|
||
have h_bound : (m - 1) * (m - 1) + (m - 1) + 1 ≤ m * m := by
|
||
have hm_pos : 0 < m := by
|
||
have : 3 ≤ m := hm3
|
||
omega
|
||
have h_eq : (m - 1) * (m - 1) + (m - 1) = (m - 1) * m := by
|
||
calc
|
||
(m - 1) * (m - 1) + (m - 1) = (m - 1) * ((m - 1) + 1) := by ring
|
||
_ = (m - 1) * m := by
|
||
have hm1 : 1 ≤ m := by omega
|
||
calc
|
||
(m - 1) * ((m - 1) + 1) = (m - 1) * m := by
|
||
rw [Nat.sub_add_cancel hm1]
|
||
_ = (m - 1) * m := rfl
|
||
calc
|
||
(m - 1) * (m - 1) + (m - 1) + 1 = (m - 1) * m + 1 := by rw [h_eq]
|
||
_ ≤ m * m := by
|
||
have hlt : (m - 1) * m < m * m := Nat.mul_lt_mul_of_pos_right (by omega) hm_pos
|
||
omega
|
||
omega
|
||
omega
|
||
rcases singerIntervalSidon p N hp hp_bound with ⟨A, hA, hA_card⟩
|
||
have hmax := sidonMaximum_isSidonMaximum N
|
||
have hle : A.card ≤ sidonMaximum N := hmax.2 hA
|
||
have hp_gt : (m + 1) / 2 < A.card := by
|
||
have : (m + 1) / 2 ≤ n + 1 := by
|
||
rw [hn_def]
|
||
omega
|
||
have hn_lt_p : n < p := hnp
|
||
calc
|
||
(m + 1) / 2 ≤ n + 1 := by
|
||
rw [hn_def]
|
||
omega
|
||
_ ≤ p := by omega
|
||
_ < p + 1 := by omega
|
||
_ = A.card := by symm; exact hA_card
|
||
have hm_card : (Nat.sqrt N + 1) / 2 < A.card := by
|
||
simpa [hm_def] using hp_gt
|
||
omega
|
||
· -- 5 ≤ N < 9: direct verification
|
||
have hN_range : N = 5 ∨ N = 6 ∨ N = 7 ∨ N = 8 := by omega
|
||
rcases hN_range with rfl | rfl | rfl | rfl
|
||
· -- N = 5: (√5 + 1) / 2 = 1 < sidonMaximum 5
|
||
have h5 : (Nat.sqrt 5 + 1) / 2 = 1 := by native_decide
|
||
have h_gt_1 : sidonMaximum 5 > 1 := by
|
||
have h_exists : ∃ A : Finset ℤ, IsIntervalSidon (5 : ℤ) A ∧ A.card = 2 := by
|
||
refine ⟨{1, 2}, ?_, by simp⟩
|
||
refine ⟨?_, ?_⟩
|
||
· intro a ha; simp at ha; rcases ha with rfl | rfl <;> norm_num
|
||
· intro a b c d ha hb hc hd hsum
|
||
simp at ha hb hc hd
|
||
rcases ha with rfl | rfl <;> rcases hb with rfl | rfl <;>
|
||
rcases hc with rfl | rfl <;> rcases hd with rfl | rfl <;> omega
|
||
rcases h_exists with ⟨A, hA, hA_card⟩
|
||
have hmax := sidonMaximum_isSidonMaximum 5
|
||
have hle' : 2 ≤ sidonMaximum 5 := by
|
||
have : A.card = 2 := hA_card
|
||
have hle'' : A.card ≤ sidonMaximum 5 := hmax.2 hA
|
||
omega
|
||
omega
|
||
rw [h5]
|
||
exact h_gt_1
|
||
· -- N = 6: (√6 + 1) / 2 = 1 < sidonMaximum 6
|
||
have h6 : (Nat.sqrt 6 + 1) / 2 = 1 := by native_decide
|
||
have h_gt_1 : sidonMaximum 6 > 1 := by
|
||
have h_exists : ∃ A : Finset ℤ, IsIntervalSidon (6 : ℤ) A ∧ A.card = 2 := by
|
||
refine ⟨{1, 2}, ?_, by simp⟩
|
||
refine ⟨?_, ?_⟩
|
||
· intro a ha; simp at ha; rcases ha with rfl | rfl <;> norm_num
|
||
· intro a b c d ha hb hc hd hsum
|
||
simp at ha hb hc hd
|
||
rcases ha with rfl | rfl <;> rcases hb with rfl | rfl <;>
|
||
rcases hc with rfl | rfl <;> rcases hd with rfl | rfl <;> omega
|
||
rcases h_exists with ⟨A, hA, hA_card⟩
|
||
have hmax := sidonMaximum_isSidonMaximum 6
|
||
have hle' : 2 ≤ sidonMaximum 6 := by
|
||
have : A.card = 2 := hA_card
|
||
have hle'' : A.card ≤ sidonMaximum 6 := hmax.2 hA
|
||
omega
|
||
omega
|
||
rw [h6]
|
||
exact h_gt_1
|
||
· -- N = 7: use Singer p=2
|
||
have hp2 : Nat.Prime 2 := by decide
|
||
have h_bound : 2 * 2 + 2 + 1 ≤ 7 := by norm_num
|
||
rcases singerIntervalSidon 2 7 hp2 h_bound with ⟨A, hA, hA_card⟩
|
||
have hA_card_eq : A.card = 2 + 1 := hA_card
|
||
have hmax := sidonMaximum_isSidonMaximum 7
|
||
have hle : A.card ≤ sidonMaximum 7 := hmax.2 hA
|
||
have h_small_case : (Nat.sqrt 7 + 1) / 2 < A.card := by
|
||
-- (Nat.sqrt 7 + 1) / 2 = (2 + 1) / 2 = 1, A.card = 3
|
||
have : A.card = 3 := by omega
|
||
rw [this]
|
||
native_decide
|
||
omega
|
||
· -- N = 8: use Singer p=2
|
||
have hp2 : Nat.Prime 2 := by decide
|
||
have h_bound : 2 * 2 + 2 + 1 ≤ 8 := by norm_num
|
||
rcases singerIntervalSidon 2 8 hp2 h_bound with ⟨A, hA, hA_card⟩
|
||
have hA_card_eq : A.card = 2 + 1 := hA_card
|
||
have hmax := sidonMaximum_isSidonMaximum 8
|
||
have hle : A.card ≤ sidonMaximum 8 := hmax.2 hA
|
||
have h_small_case : (Nat.sqrt 8 + 1) / 2 < A.card := by
|
||
have : A.card = 3 := by omega
|
||
rw [this]
|
||
native_decide
|
||
omega
|
||
|
||
/-- Combined unconditional two-sided bound on sidonMaximum:
|
||
(√N + 1) / 2 < h(N) ≤ √(2N) + 1 for all N ≥ 5. -/
|
||
theorem sidonMaximum_bounds (N : ℕ) (hN : 5 ≤ N) :
|
||
(Nat.sqrt N + 1) / 2 < sidonMaximum N ∧
|
||
sidonMaximum N ≤ Nat.sqrt (2 * N) + 1 := by
|
||
constructor
|
||
· exact sidonMaximum_gt_sqrt_div_two N hN
|
||
· exact sidonMaximum_le_sqrt_two N (by omega)
|
||
|
||
end Semantics.SidonSets
|