From f62b2f0072bc38ef45ed4a78436e705d7728b61d Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 4 Sep 2026 13:20:11 +0000 Subject: [PATCH 1/7] Port Wallace problem formalization to Lean 4.34 --- LeanPool/Wallace.lean | 21 + LeanPool/Wallace/BlockFilters.lean | 406 +++++++++ LeanPool/Wallace/BlockLimit.lean | 83 ++ LeanPool/Wallace/BoundedIndependentMap.lean | 54 ++ LeanPool/Wallace/ConcreteClosure.lean | 92 ++ LeanPool/Wallace/ConcreteData.lean | 146 ++++ LeanPool/Wallace/ConcreteFusionRun.lean | 212 +++++ LeanPool/Wallace/ConcreteLocalSetup.lean | 318 +++++++ LeanPool/Wallace/CountableClosure.lean | 100 +++ .../Wallace/CountableDisjointization.lean | 52 ++ LeanPool/Wallace/FiniteCombinatorics.lean | 556 ++++++++++++ LeanPool/Wallace/FullTopology.lean | 307 +++++++ LeanPool/Wallace/FullTopologyMain.lean | 58 ++ LeanPool/Wallace/FusionLimit.lean | 83 ++ LeanPool/Wallace/FusionSchedule.lean | 243 ++++++ LeanPool/Wallace/FusionStage.lean | 257 ++++++ LeanPool/Wallace/GeneralMain.lean | 92 ++ LeanPool/Wallace/GlobalAssembly.lean | 110 +++ LeanPool/Wallace/InitialCharacter.lean | 53 ++ LeanPool/Wallace/LocalEnumeration.lean | 42 + LeanPool/Wallace/LocalFusion.lean | 665 +++++++++++++++ LeanPool/Wallace/Main.lean | 59 ++ LeanPool/Wallace/MathlibFoundations.lean | 419 +++++++++ LeanPool/Wallace/NontrivialSequences.lean | 162 ++++ LeanPool/Wallace/PackageTransport.lean | 92 ++ LeanPool/Wallace/RationalAssembly.lean | 101 +++ LeanPool/Wallace/RationalClosure.lean | 87 ++ LeanPool/Wallace/RationalData.lean | 129 +++ LeanPool/Wallace/RationalFusionRun.lean | 267 ++++++ LeanPool/Wallace/RationalLocalSetup.lean | 305 +++++++ .../Wallace/RationalTransfiniteExtension.lean | 280 ++++++ .../Wallace/RationalTriangularPreprocess.lean | 173 ++++ LeanPool/Wallace/RealMain.lean | 59 ++ LeanPool/Wallace/Result.lean | 249 ++++++ LeanPool/Wallace/SeparationInterface.lean | 154 ++++ LeanPool/Wallace/TorsionFreeCoordinate.lean | 196 +++++ LeanPool/Wallace/TransfiniteExtension.lean | 267 ++++++ LeanPool/Wallace/TriangularPreprocess.lean | 633 ++++++++++++++ LeanPool/Wallace/TychonoffWallace.lean | 87 ++ LeanPool/Wallace/UniformKronecker.lean | 795 ++++++++++++++++++ 40 files changed, 8464 insertions(+) create mode 100644 LeanPool/Wallace.lean create mode 100644 LeanPool/Wallace/BlockFilters.lean create mode 100644 LeanPool/Wallace/BlockLimit.lean create mode 100644 LeanPool/Wallace/BoundedIndependentMap.lean create mode 100644 LeanPool/Wallace/ConcreteClosure.lean create mode 100644 LeanPool/Wallace/ConcreteData.lean create mode 100644 LeanPool/Wallace/ConcreteFusionRun.lean create mode 100644 LeanPool/Wallace/ConcreteLocalSetup.lean create mode 100644 LeanPool/Wallace/CountableClosure.lean create mode 100644 LeanPool/Wallace/CountableDisjointization.lean create mode 100644 LeanPool/Wallace/FiniteCombinatorics.lean create mode 100644 LeanPool/Wallace/FullTopology.lean create mode 100644 LeanPool/Wallace/FullTopologyMain.lean create mode 100644 LeanPool/Wallace/FusionLimit.lean create mode 100644 LeanPool/Wallace/FusionSchedule.lean create mode 100644 LeanPool/Wallace/FusionStage.lean create mode 100644 LeanPool/Wallace/GeneralMain.lean create mode 100644 LeanPool/Wallace/GlobalAssembly.lean create mode 100644 LeanPool/Wallace/InitialCharacter.lean create mode 100644 LeanPool/Wallace/LocalEnumeration.lean create mode 100644 LeanPool/Wallace/LocalFusion.lean create mode 100644 LeanPool/Wallace/Main.lean create mode 100644 LeanPool/Wallace/MathlibFoundations.lean create mode 100644 LeanPool/Wallace/NontrivialSequences.lean create mode 100644 LeanPool/Wallace/PackageTransport.lean create mode 100644 LeanPool/Wallace/RationalAssembly.lean create mode 100644 LeanPool/Wallace/RationalClosure.lean create mode 100644 LeanPool/Wallace/RationalData.lean create mode 100644 LeanPool/Wallace/RationalFusionRun.lean create mode 100644 LeanPool/Wallace/RationalLocalSetup.lean create mode 100644 LeanPool/Wallace/RationalTransfiniteExtension.lean create mode 100644 LeanPool/Wallace/RationalTriangularPreprocess.lean create mode 100644 LeanPool/Wallace/RealMain.lean create mode 100644 LeanPool/Wallace/Result.lean create mode 100644 LeanPool/Wallace/SeparationInterface.lean create mode 100644 LeanPool/Wallace/TorsionFreeCoordinate.lean create mode 100644 LeanPool/Wallace/TransfiniteExtension.lean create mode 100644 LeanPool/Wallace/TriangularPreprocess.lean create mode 100644 LeanPool/Wallace/TychonoffWallace.lean create mode 100644 LeanPool/Wallace/UniformKronecker.lean diff --git a/LeanPool/Wallace.lean b/LeanPool/Wallace.lean new file mode 100644 index 000000000..912db42f9 --- /dev/null +++ b/LeanPool/Wallace.lean @@ -0,0 +1,21 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.GeneralMain +import LeanPool.Wallace.RealMain +import LeanPool.Wallace.TychonoffWallace + +/-! +# Countably compact groups and the Wallace counterexample + +This library proves the paper's main theorem for every torsion-free Abelian group of cardinality +continuum. It also exposes the free, rational, real, and Baer--Specker specializations. The +nonnegative cone in the free Abelian group gives a commutative Tychonoff countably compact +cancellative topological additive monoid which is not a group. The internal Section 10 +propositions on large closures and suitable sets are included as well. + +The public entry point exposes the three principal statements from the paper. +-/ diff --git a/LeanPool/Wallace/BlockFilters.lean b/LeanPool/Wallace/BlockFilters.lean new file mode 100644 index 000000000..9e8cdc5e7 --- /dev/null +++ b/LeanPool/Wallace/BlockFilters.lean @@ -0,0 +1,406 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.MathlibFoundations +import LeanPool.Wallace.TriangularPreprocess + +/-! +# Block-density filters for the Wallace construction + +This file packages the density-one filter used in the paper. The formulation is deliberately +abstract in the finite blocks: the later scheduling module only has to provide nonempty blocks +which eventually avoid every finite set and a deletion bound whose relative size tends to zero. +-/ + +open Filter Set Topology +open scoped Topology + +namespace Wallace + +noncomputable section + +/-- Finite blocks which move to infinity. -/ +structure BlockSystem where + block : ℕ → Finset ℕ + block_nonempty : ∀ l, (block l).Nonempty + eventually_disjoint_finite : + ∀ K : Finset ℕ, {l | Disjoint (block l) K} ∈ (atTop : Filter ℕ) + +namespace BlockSystem + +/-- The concrete block system supplied by the triangular preprocessing enumeration. Its blocks +have the prescribed cardinalities and partition `ℕ`; in particular, every finite set of positions +meets only finitely many block labels. -/ +def ofBlockPositions (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) : BlockSystem where + block := TriangularPreprocess.blockPositions N hN + block_nonempty := by + intro l + apply Finset.card_pos.mp + simpa only [TriangularPreprocess.blockPositions_card] using hN l + eventually_disjoint_finite := by + intro K + rw [← Nat.cofinite_eq_atTop] + filter_upwards [ + (K.image (TriangularPreprocess.blockOf N hN)).finite_toSet.compl_mem_cofinite + ] with l hl + rw [Finset.disjoint_left] + intro n hnblock hnK + apply hl + simp only [Finset.mem_coe, Finset.mem_image] + exact ⟨n, hnK, (TriangularPreprocess.mem_blockPositions_iff N hN).mp hnblock⟩ + +@[simp] +theorem ofBlockPositions_block (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (l : ℕ) : + (ofBlockPositions N hN).block l = TriangularPreprocess.blockPositions N hN l := + rfl + +@[simp] +theorem ofBlockPositions_card (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (l : ℕ) : + ((ofBlockPositions N hN).block l).card = N l := + TriangularPreprocess.blockPositions_card N hN l + +/-- Proportion of a block missing from a set. -/ +noncomputable def missingRatio (B : BlockSystem) (A : Set ℕ) (l : ℕ) : ℝ := by + classical + exact (((B.block l).filter fun n ↦ n ∉ A).card : ℝ) / ((B.block l).card : ℝ) + +theorem missingRatio_nonneg (B : BlockSystem) (A : Set ℕ) (l : ℕ) : + 0 ≤ B.missingRatio A l := by + unfold missingRatio + positivity + +@[simp] +theorem missingRatio_univ (B : BlockSystem) (l : ℕ) : + B.missingRatio Set.univ l = 0 := by + classical + simp [missingRatio] + +@[simp] +theorem missingRatio_empty (B : BlockSystem) (l : ℕ) : + B.missingRatio ∅ l = 1 := by + classical + unfold missingRatio + simp only [Set.mem_empty_iff_false, not_false_eq_true, Finset.filter_true] + exact div_self (by + exact_mod_cast (B.block_nonempty l).card_pos.ne') + +theorem missingRatio_mono (B : BlockSystem) {A C : Set ℕ} (hAC : A ⊆ C) (l : ℕ) : + B.missingRatio C l ≤ B.missingRatio A l := by + classical + unfold missingRatio + apply div_le_div_of_nonneg_right _ (by positivity) + exact_mod_cast Finset.card_le_card (by + intro n hn + simp only [Finset.mem_filter] at hn ⊢ + exact ⟨hn.1, fun hnA ↦ hn.2 (hAC hnA)⟩) + +theorem missingRatio_inter_le (B : BlockSystem) (A C : Set ℕ) (l : ℕ) : + B.missingRatio (A ∩ C) l ≤ B.missingRatio A l + B.missingRatio C l := by + classical + letI (n : ℕ) : Decidable (n ∈ A ∩ C) := Classical.propDecidable _ + have hsubset : + (B.block l).filter (fun n ↦ n ∉ A ∩ C) ⊆ + (B.block l).filter (fun n ↦ n ∉ A) ∪ + (B.block l).filter (fun n ↦ n ∉ C) := by + intro n hn + simp only [Finset.mem_filter, Finset.mem_union] at hn ⊢ + rcases hn with ⟨hnb, hnAC⟩ + by_cases hnA : n ∈ A + · exact Or.inr ⟨hnb, fun hnC ↦ hnAC ⟨hnA, hnC⟩⟩ + · exact Or.inl ⟨hnb, hnA⟩ + have hcard : + ((B.block l).filter (fun n ↦ n ∉ A ∩ C)).card ≤ + ((B.block l).filter (fun n ↦ n ∉ A)).card + + ((B.block l).filter (fun n ↦ n ∉ C)).card := by + exact (Finset.card_le_card hsubset).trans + ((Finset.card_union_le _ _).trans_eq rfl) + unfold missingRatio + rw [← add_div] + apply (div_le_div_iff_of_pos_right (by + exact_mod_cast (B.block_nonempty l).card_pos)).mpr + norm_cast + +/-- Sets having block density one along the labels in `a`. -/ +def IsLarge (B : BlockSystem) (a A : Set ℕ) : Prop := + Tendsto (B.missingRatio A) (atTop ⊓ Filter.principal a) (nhds 0) + +/-- The block-density-one sets form a filter. -/ +def densityFilter (B : BlockSystem) (a : Set ℕ) : Filter ℕ where + sets := {A | B.IsLarge a A} + univ_sets := by + exact tendsto_congr' (Eventually.of_forall (B.missingRatio_univ)) |>.mpr tendsto_const_nhds + sets_of_superset := by + intro A C hA hAC + apply squeeze_zero' (Eventually.of_forall (B.missingRatio_nonneg C)) + (Eventually.of_forall fun l ↦ B.missingRatio_mono hAC l) hA + inter_sets := by + intro A C hA hC + apply squeeze_zero' (Eventually.of_forall (B.missingRatio_nonneg (A ∩ C))) + (Eventually.of_forall fun l ↦ B.missingRatio_inter_le A C l) + simpa using hA.add hC + +@[simp] +theorem mem_densityFilter_iff (B : BlockSystem) (a A : Set ℕ) : + A ∈ B.densityFilter a ↔ B.IsLarge a A := + Iff.rfl + +/-- Every cofinite set has block density one. In mathlib's reverse-inclusion order on filters, +this says that the density filter lies below the cofinite filter. -/ +theorem densityFilter_le_cofinite (B : BlockSystem) (a : Set ℕ) : + B.densityFilter a ≤ cofinite := by + classical + rw [le_cofinite_iff_compl_singleton_mem] + intro n + letI (k : ℕ) : Decidable (k ∈ ({n} : Set ℕ)ᶜ) := Classical.propDecidable _ + rw [mem_densityFilter_iff] + unfold IsLarge + apply tendsto_congr' ?_ |>.mpr tendsto_const_nhds + have hdisjoint := B.eventually_disjoint_finite {n} + filter_upwards [(inf_le_left : atTop ⊓ Filter.principal a ≤ atTop) hdisjoint] with l hl + unfold missingRatio + have hempty : (B.block l).filter (fun k ↦ k ∉ ({n} : Set ℕ)ᶜ) = ∅ := by + apply Finset.filter_eq_empty_iff.mpr + intro k hkblock + simp only [Set.mem_compl_iff, Set.mem_singleton_iff, not_not] + intro hkn + subst k + exact Finset.disjoint_left.mp hl hkblock (Finset.mem_singleton_self n) + have hcardzero : + ((B.block l).filter (fun k ↦ k ∉ ({n} : Set ℕ)ᶜ)).card = 0 := + Finset.card_eq_zero.mpr hempty + have hcastzero : + (((B.block l).filter (fun k ↦ k ∉ ({n} : Set ℕ)ᶜ)).card : ℝ) = 0 := by + exact_mod_cast hcardzero + rw [hcastzero] + exact zero_div _ + +/-- If the label set is infinite, the block-density filter is proper. -/ +theorem densityFilter_neBot (B : BlockSystem) {a : Set ℕ} (ha : a.Infinite) : + (B.densityFilter a).NeBot := by + rw [Filter.neBot_iff] + intro hbot + have hempty : (∅ : Set ℕ) ∈ B.densityFilter a := by + rw [hbot] + exact Filter.mem_bot + rw [mem_densityFilter_iff] at hempty + unfold IsLarge at hempty + haveI : NeBot (atTop ⊓ Filter.principal a) := by + rw [← Nat.cofinite_eq_atTop] + exact ha.cofinite_inf_principal_neBot + have hone_tendsto : + Tendsto (fun _ : ℕ ↦ (1 : ℝ)) (atTop ⊓ Filter.principal a) (nhds 0) := by + convert hempty using 1 + funext l + exact (B.missingRatio_empty l).symm + have hone : (1 : ℝ) = 0 := tendsto_const_nhds_iff.mp hone_tendsto + exact one_ne_zero hone + +/-- The density filter along an infinite almost-disjoint label set has a free ultrafilter +extension. Both refinement inequalities are recorded explicitly. -/ +theorem exists_free_ultrafilter_le_densityFilter + (B : BlockSystem) {a : Set ℕ} (ha : a.Infinite) : + ∃ p : Ultrafilter ℕ, + (p : Filter ℕ) ≤ B.densityFilter a ∧ (p : Filter ℕ) ≤ cofinite := by + letI : (B.densityFilter a).NeBot := B.densityFilter_neBot ha + exact exists_free_ultrafilter_le_filter (B.densityFilter a) + (B.densityFilter_le_cofinite a) + +end BlockSystem + +namespace AlmostDisjoint + +variable {ι α : Type*} + +/-- The union of the members that occur strictly before `j` in an enumeration. -/ +def earlierUnion [Preorder ι] (family : ι → Set α) (j : ι) : Set α := + ⋃ i ∈ Set.Iio j, family i + +/-- The standard recursive disjointization from the paper: +`b_j = a_j \ \bigcup_{i.2 + +theorem prepared_support_lt (a : ContinuumIndex) (n : ℕ) (i : ContinuumIndex) + (hi : i ∈ (prepared N hN M a n).support) : i < codeIndex a := by + exact (Classical.choose_spec (triangular_block_preprocess a N hN M)).2.2 n i hi + +theorem prepared_injective (a : ContinuumIndex) : + Function.Injective (prepared N hN M a) := + (codedSequence_injective a).comp (selector_strictMono N hN M a).injective + +/-- Translating a prepared sequence by its prescribed basis point preserves injectivity. -/ +theorem preparedDifference_injective (a : ContinuumIndex) : + Function.Injective + (fun n ↦ prepared N hN M a n - codeBasisVector a) := by + intro m n hmn + apply prepared_injective N hN M a + exact sub_left_injective hmn + +/-- Each shifted block has exactly the scheduled cardinality `N l`, as in +Lemma 5.3 of the paper. -/ +theorem differenceBlock_card (a : ContinuumIndex) (l : ℕ) : + (differenceBlock N hN M a l).card = N l := by + rw [differenceBlock, + Finset.card_image_iff.mpr (preparedDifference_injective N hN M a).injOn, + blockPositions_card] + +theorem differenceBlock_subset_range (a : ContinuumIndex) (l : ℕ) : + ↑(differenceBlock N hN M a l) ⊆ + Set.range (fun n ↦ prepared N hN M a n - codeBasisVector a) := by + intro x hx + simp only [differenceBlock, Finset.mem_coe, Finset.mem_image] at hx + obtain ⟨n, _hn, rfl⟩ := hx + exact Set.mem_range_self n + +/-! ## The fixed free ultrafilters -/ + +/-- The block system determined by the prescribed sizes. -/ +abbrev blocks : BlockSystem := BlockSystem.ofBlockPositions N hN + +/-- A free ultrafilter extending the density filter assigned to code `a`. -/ +def ultrafilter (a : ContinuumIndex) : Ultrafilter ℕ := + Classical.choose ((blocks N hN).exists_free_ultrafilter_le_densityFilter (label_infinite a)) + +theorem ultrafilter_le_density (a : ContinuumIndex) : + (ultrafilter N hN a : Filter ℕ) ≤ (blocks N hN).densityFilter (label a) := + (Classical.choose_spec + ((blocks N hN).exists_free_ultrafilter_le_densityFilter (label_infinite a))).1 + +theorem ultrafilter_free (a : ContinuumIndex) : + (ultrafilter N hN a : Filter ℕ) ≤ cofinite := + (Classical.choose_spec + ((blocks N hN).exists_free_ultrafilter_le_densityFilter (label_infinite a))).2 + +/-! ## Packaging for the transfinite extension -/ + +/-- The concrete triangular data used by the transfinite recursion. -/ +def transfiniteData : TransfiniteExtension.ContinuumData where + Code := ContinuumIndex + codeIndex := codeIndex + prepared := prepared N hN M + support_lt := prepared_support_lt N hN M + p := ultrafilter N hN + +end + +end ConcreteData +end Wallace diff --git a/LeanPool/Wallace/ConcreteFusionRun.lean b/LeanPool/Wallace/ConcreteFusionRun.lean new file mode 100644 index 000000000..e13aa01c4 --- /dev/null +++ b/LeanPool/Wallace/ConcreteFusionRun.lean @@ -0,0 +1,212 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.LocalEnumeration +import LeanPool.Wallace.LocalFusion + +/-! +# The unconditional concrete local fusion + +For each nonzero vector this module instantiates the generic scheduling recursion with the +prepared local blocks. It then converts the bounded deletion at every stage into a +block-density certificate for every relevant code. No marker sequence is used. +-/ + +open Filter Set Topology + +namespace Wallace +namespace ConcreteFusionRun + +noncomputable section + +open TriangularPreprocess +open ConcreteData +open ConcreteClosure +open ConcreteLocalSetup +open FiniteCombinatorics +open LocalFusion + +/-! ## Specialization of the numerical schedule -/ + +abbrev blockSize : ℕ → ℕ := FusionSchedule.blockSize + +theorem blockSize_pos (l : ℕ) : 0 < blockSize l := + FusionSchedule.blockSize_pos l + +abbrev independenceBound : ℕ → ℕ := FusionSchedule.stageIndependenceBound + +abbrev localCarrier (x : ContinuumFreeGroup) : Set ContinuumIndex := + closure blockSize blockSize_pos independenceBound x + +abbrev LocalGroup (x : ContinuumFreeGroup) := localCarrier x →₀ ℤ + +abbrev fresh (x : ContinuumFreeGroup) : ℕ → Finset (LocalGroup x) := + localActiveBlock blockSize blockSize_pos independenceBound x + +abbrev enumeration (x : ContinuumFreeGroup) : ℕ → LocalGroup x := + groupEnumeration blockSize blockSize_pos independenceBound x + +def distinguished (x : ContinuumFreeGroup) : LocalGroup x := by + classical + exact Finsupp.subtypeDomain (localCarrier x) x + +theorem distinguished_ne_zero {x : ContinuumFreeGroup} (hx : x ≠ 0) : + distinguished x ≠ 0 := by + classical + intro hzero + apply hx + exact (Finsupp.subtypeDomain_eq_zero_iff + (support_subset_closure blockSize blockSize_pos independenceBound x)).mp hzero + +/-! ## The scheduled run -/ + +/-- The generic recursion, instantiated with the concrete local blocks. -/ +def scheduledCertificate (x : {x : ContinuumFreeGroup // x ≠ 0}) : + ScheduledRunCertificate (fresh x.1) (distinguished x.1) := + Classical.choice <| exists_scheduledRunCertificate + (fresh x.1) (enumeration x.1) (distinguished x.1) + (distinguished_ne_zero x.2) + (localActiveBlock_card_le blockSize blockSize_pos independenceBound x.1) + (localActiveBlock_boundedIndependent blockSize blockSize_pos independenceBound x.1) + (groupEnumeration_surjective blockSize blockSize_pos independenceBound x.1) + +abbrev run (x : {x : ContinuumFreeGroup // x ≠ 0}) : + FusionRun (LocalGroup x.1) := + (scheduledCertificate x).run + +/-! ## Deleted positions and their density estimate -/ + +/-- Positions discarded from the block of a relevant code. Away from that code's refined +label this definition is harmless; only labelled stages enter its density certificate. -/ +def deletedPositions (x : {x : ContinuumFreeGroup // x ≠ 0}) + (a : RelevantCode blockSize blockSize_pos independenceBound x.1) (l : ℕ) : + Finset ℕ := + (blockPositions blockSize blockSize_pos l).filter fun n ↦ + localDifference blockSize blockSize_pos independenceBound x.1 a n ∉ + (run x).retained l + +theorem deletedPositions_subset_block (x : {x : ContinuumFreeGroup // x ≠ 0}) + (a : RelevantCode blockSize blockSize_pos independenceBound x.1) (l : ℕ) : + deletedPositions x a l ⊆ blockPositions blockSize blockSize_pos l := by + intro n hn + exact (Finset.mem_filter.mp hn).1 + +private theorem image_deletedPositions (x : {x : ContinuumFreeGroup // x ≠ 0}) + (a : RelevantCode blockSize blockSize_pos independenceBound x.1) (l : ℕ) : + (deletedPositions x a l).image + (localDifference blockSize blockSize_pos independenceBound x.1 a) = + localDifferenceBlock blockSize blockSize_pos independenceBound x.1 a l \ + (run x).retained l := by + classical + ext g + constructor + · intro hg + obtain ⟨n, hn, rfl⟩ := Finset.mem_image.mp hg + have hn' := Finset.mem_filter.mp hn + exact Finset.mem_sdiff.mpr + ⟨Finset.mem_image_of_mem _ hn'.1, hn'.2⟩ + · intro hg + have hg' := Finset.mem_sdiff.mp hg + obtain ⟨n, hn, hng⟩ := Finset.mem_image.mp hg'.1 + subst g + exact Finset.mem_image.mpr + ⟨n, Finset.mem_filter.mpr ⟨hn, hg'.2⟩, rfl⟩ + +theorem deletedPositions_card_le (x : {x : ContinuumFreeGroup // x ≠ 0}) + (a : RelevantCode blockSize blockSize_pos independenceBound x.1) + (l : ℕ) + (hl : l ∈ refinedLabel blockSize blockSize_pos independenceBound x.1 a) : + (deletedPositions x a l).card ≤ FusionSchedule.protectedBound l := by + classical + let f := localDifference blockSize blockSize_pos independenceBound x.1 a + have hinj : Function.Injective f := + localDifference_injective blockSize blockSize_pos independenceBound x.1 a + calc + (deletedPositions x a l).card = + ((deletedPositions x a l).image f).card := by + exact (Finset.card_image_of_injective _ hinj).symm + _ = (localDifferenceBlock blockSize blockSize_pos independenceBound x.1 a l \ + (run x).retained l).card := by + rw [image_deletedPositions] + _ = (fresh x.1 l \ (run x).retained l).card := by + change (localDifferenceBlock blockSize blockSize_pos independenceBound x.1 a l \ + (run x).retained l).card = + (localActiveBlock blockSize blockSize_pos independenceBound x.1 l \ + (run x).retained l).card + rw [localActiveBlock_eq_of_mem blockSize blockSize_pos independenceBound x.1 l a hl] + _ ≤ ((run x).guardSet l).card := + (scheduledCertificate x).deleted_card_le l + _ ≤ FusionSchedule.protectedBound l := + (scheduledCertificate x).guard_card_le l + +theorem retainedPositions_mem_ultrafilter + (x : {x : ContinuumFreeGroup // x ≠ 0}) + (a : RelevantCode blockSize blockSize_pos independenceBound x.1) : + (BlockSystem.ofBlockPositions blockSize blockSize_pos).retainedBlocks + (refinedLabel blockSize blockSize_pos independenceBound x.1 a) + (deletedPositions x a) ∈ + ultrafilter blockSize blockSize_pos a.1 := by + apply ultrafilter_le_density blockSize blockSize_pos a.1 + apply BlockSystem.retainedBlocks_mem_densityFilter_ofBlockPositions + blockSize blockSize_pos (deletedPositions x a) + FusionSchedule.protectedBound + · exact label_diff_refinedLabel_finite + blockSize blockSize_pos independenceBound x.1 a + · exact deletedPositions_subset_block x a + · exact deletedPositions_card_le x a + · exact FusionSchedule.tendsto_protectedBound_div_blockSize + +/-! ## Concrete block certificates and the local output -/ + +def codeBlocks (x : {x : ContinuumFreeGroup // x ≠ 0}) + (a : RelevantCode blockSize blockSize_pos independenceBound x.1) : + ConcreteCodeBlocks blockSize blockSize_pos independenceBound x.1 (run x) a where + blocks := { + p := ultrafilter blockSize blockSize_pos a.1 + block := blockPositions blockSize blockSize_pos + labels := refinedLabel blockSize blockSize_pos independenceBound x.1 a + deletions := deletedPositions x a + difference := localDifference blockSize blockSize_pos independenceBound x.1 a + retained_mem := by + simpa only [BlockSystem.retainedBlocks, + BlockSystem.ofBlockPositions_block] using + retainedPositions_mem_ultrafilter x a + retained_in_stage := by + intro l n hl hn + have hnparts := Finset.mem_sdiff.mp hn + by_contra hnot + exact hnparts.2 (Finset.mem_filter.mpr ⟨hnparts.1, hnot⟩) + } + p_eq := rfl + block_eq := fun _ ↦ rfl + difference_eq := fun _ ↦ rfl + +/-- A complete local fusion certificate for a fixed nonzero vector. -/ +def localRunCertificate (x : {x : ContinuumFreeGroup // x ≠ 0}) : + LocalRunCertificate blockSize blockSize_pos independenceBound x where + run := run x + self_ne_zero := by + apply (run x).limitCharacter_ne_zero_of_initial_half + · exact (scheduledCertificate x).initial_half + · exact (scheduledCertificate x).distinguished_protected + codeBlocks := codeBlocks x + +theorem exists_localRunCertificate + (x : {x : ContinuumFreeGroup // x ≠ 0}) : + Nonempty (LocalRunCertificate blockSize blockSize_pos independenceBound x) := + ⟨localRunCertificate x⟩ + +/-- The local character required by the transfinite extension exists for every nonzero vector. -/ +theorem hasLocalSeparatingCharacters : + GlobalAssembly.HasLocalSeparatingCharacters + blockSize blockSize_pos independenceBound := + hasLocalSeparatingCharacters_of_certificates + blockSize blockSize_pos independenceBound exists_localRunCertificate + +end + +end ConcreteFusionRun +end Wallace diff --git a/LeanPool/Wallace/ConcreteLocalSetup.lean b/LeanPool/Wallace/ConcreteLocalSetup.lean new file mode 100644 index 000000000..73b8db718 --- /dev/null +++ b/LeanPool/Wallace/ConcreteLocalSetup.lean @@ -0,0 +1,318 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.ConcreteClosure +import LeanPool.Wallace.CountableDisjointization +import LeanPool.Wallace.FusionSchedule +import LeanPool.Wallace.BoundedIndependentMap + +/-! +# The concrete countable block schedule around one nonzero vector + +For one nonzero vector `x`, only codes whose fresh coordinates lie in its dependency closure +matter to the local fusion. They form a countable type. This module disjointizes their fixed +almost-disjoint labels, selects the unique active code at each block label, and defines the +finite independent set presented to bounded deletion at that stage. +-/ + +open Set + +namespace Wallace +namespace ConcreteLocalSetup + +noncomputable section + +open TriangularPreprocess +open ConcreteData +open ConcreteClosure +open FiniteCombinatorics + +variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) + +/-- Codes whose prescribed basis coordinate belongs to the local dependency closure of `x`. -/ +abbrev RelevantCode (x : ContinuumFreeGroup) := + {a : ContinuumIndex // codeIndex a ∈ closure N hN M x} + +theorem relevantCode_countable (x : ContinuumFreeGroup) : + Countable (RelevantCode N hN M x) := by + apply Countable.to_subtype + exact countable_preimage_of_injective codeIndex (closure_countable N hN M x) + +private theorem relevantLabels_pairwise (x : ContinuumFreeGroup) : + Pairwise fun a b : RelevantCode N hN M x ↦ + (label a.1 ∩ label b.1).Finite := by + intro a b hab + apply label_inter_finite + intro heq + apply hab + exact Subtype.ext heq + +/-- Pairwise disjoint labels obtained by deleting finitely many points from each relevant +almost-disjoint label. -/ +def refinedLabel (x : ContinuumFreeGroup) : RelevantCode N hN M x → Set ℕ := by + letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x + exact Classical.choose + (exists_disjoint_refinement_countable + (fun a : RelevantCode N hN M x ↦ label a.1) + (relevantLabels_pairwise N hN M x)) + +theorem refinedLabel_pairwise (x : ContinuumFreeGroup) : + Pairwise fun a b : RelevantCode N hN M x ↦ + Disjoint (refinedLabel N hN M x a) (refinedLabel N hN M x b) := by + letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x + exact (Classical.choose_spec + (exists_disjoint_refinement_countable + (fun a : RelevantCode N hN M x ↦ label a.1) + (relevantLabels_pairwise N hN M x))).1 + +theorem refinedLabel_subset (x : ContinuumFreeGroup) (a : RelevantCode N hN M x) : + refinedLabel N hN M x a ⊆ label a.1 := by + letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x + exact (Classical.choose_spec + (exists_disjoint_refinement_countable + (fun a : RelevantCode N hN M x ↦ label a.1) + (relevantLabels_pairwise N hN M x))).2 a |>.1 + +theorem label_diff_refinedLabel_finite + (x : ContinuumFreeGroup) (a : RelevantCode N hN M x) : + (label a.1 \ refinedLabel N hN M x a).Finite := by + letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x + exact (Classical.choose_spec + (exists_disjoint_refinement_countable + (fun a : RelevantCode N hN M x ↦ label a.1) + (relevantLabels_pairwise N hN M x))).2 a |>.2 + +theorem refinedLabel_unique (x : ContinuumFreeGroup) {l : ℕ} + {a b : RelevantCode N hN M x} + (ha : l ∈ refinedLabel N hN M x a) + (hb : l ∈ refinedLabel N hN M x b) : a = b := by + by_contra hab + exact Set.disjoint_left.mp (refinedLabel_pairwise N hN M x hab) ha hb + +/-- The unique relevant code scheduled at label `l`, if there is one. -/ +def activeCode (x : ContinuumFreeGroup) (l : ℕ) : + Option (RelevantCode N hN M x) := by + classical + exact if h : ∃ a, l ∈ refinedLabel N hN M x a then + some (Classical.choose h) else none + +theorem activeCode_eq_some_of_mem (x : ContinuumFreeGroup) (l : ℕ) + (a : RelevantCode N hN M x) (ha : l ∈ refinedLabel N hN M x a) : + activeCode N hN M x l = some a := by + classical + unfold activeCode + split + · rename_i h + congr 1 + exact refinedLabel_unique N hN M x (Classical.choose_spec h) ha + · rename_i h + exact (h ⟨a, ha⟩).elim + +theorem mem_refinedLabel_of_activeCode_eq_some + (x : ContinuumFreeGroup) (l : ℕ) (a : RelevantCode N hN M x) + (h : activeCode N hN M x l = some a) : + l ∈ refinedLabel N hN M x a := by + classical + unfold activeCode at h + split at h + · rename_i hex + have hchosen : Classical.choose hex = a := Option.some.inj h + simpa only [hchosen] using Classical.choose_spec hex + · simp at h + +theorem activeCode_eq_some_iff + (x : ContinuumFreeGroup) (l : ℕ) (a : RelevantCode N hN M x) : + activeCode N hN M x l = some a ↔ l ∈ refinedLabel N hN M x a := + ⟨mem_refinedLabel_of_activeCode_eq_some N hN M x l a, + activeCode_eq_some_of_mem N hN M x l a⟩ + +/-- The fresh shifted set presented to bounded deletion at stage `l`. -/ +def activeBlock (x : ContinuumFreeGroup) (l : ℕ) : Finset ContinuumFreeGroup := + match activeCode N hN M x l with + | none => ∅ + | some a => differenceBlock N hN M a.1 l + +theorem activeBlock_eq_of_mem (x : ContinuumFreeGroup) (l : ℕ) + (a : RelevantCode N hN M x) (ha : l ∈ refinedLabel N hN M x a) : + activeBlock N hN M x l = differenceBlock N hN M a.1 l := by + simp [activeBlock, activeCode_eq_some_of_mem N hN M x l a ha] + +theorem activeBlock_boundedIndependent (x : ContinuumFreeGroup) (l : ℕ) : + BoundedIndependent (M l) (activeBlock N hN M x l) := by + unfold activeBlock + split + · simp [BoundedIndependent] + · rename_i a hactive + exact differenceBlock_boundedIndependent N hN M a.1 l + +theorem activeBlock_card_le (x : ContinuumFreeGroup) (l : ℕ) : + (activeBlock N hN M x l).card ≤ N l := by + unfold activeBlock + split + · simp + · rename_i a hactive + calc + (differenceBlock N hN M a.1 l).card ≤ (blockPositions N hN l).card := by + exact Finset.card_image_le + _ = N l := blockPositions_card N hN l + +/-! ## Restriction to the countable local free group -/ + +/-- Inclusion of the free group on the closure coordinates into the ambient free group. -/ +def closureInclusion (x : ContinuumFreeGroup) : + (closure N hN M x →₀ ℤ) →+ ContinuumFreeGroup := + by + classical + exact Finsupp.embDomain.addMonoidHom + (.subtype (closure N hN M x : ContinuumIndex → Prop)) + +theorem closureInclusion_apply (x : ContinuumFreeGroup) + (z : closure N hN M x →₀ ℤ) : + closureInclusion N hN M x z = + Finsupp.embDomain + (.subtype (closure N hN M x : ContinuumIndex → Prop)) z := by + classical + rfl + +theorem closureInclusion_injective (x : ContinuumFreeGroup) : + Function.Injective (closureInclusion N hN M x) := by + classical + intro y z h + apply Finsupp.embDomain_injective + (.subtype (closure N hN M x : ContinuumIndex → Prop)) + change Finsupp.embDomain + (.subtype (closure N hN M x : ContinuumIndex → Prop)) y = + Finsupp.embDomain + (.subtype (closure N hN M x : ContinuumIndex → Prop)) z at h + exact h + +/-- The shifted prepared value, restricted to the local closure. -/ +def localDifference (x : ContinuumFreeGroup) + (a : RelevantCode N hN M x) (n : ℕ) : closure N hN M x →₀ ℤ := + by + classical + exact Finsupp.subtypeDomain (closure N hN M x) + (prepared N hN M a.1 n - codeBasisVector a.1) + +private theorem difference_support_subset_closure + (x : ContinuumFreeGroup) (a : RelevantCode N hN M x) (n : ℕ) : + ∀ i ∈ (prepared N hN M a.1 n - codeBasisVector a.1).support, + i ∈ closure N hN M x := by + intro i hi + by_contra hiD + have hprep0 : prepared N hN M a.1 n i = 0 := by + by_contra hne + apply hiD + exact prepared_support_mem_closure N hN M x a.1 a.2 n i + (Finsupp.mem_support_iff.mpr hne) + have hbasis0 : codeBasisVector a.1 i = 0 := by + by_cases hai : codeIndex a.1 = i + · apply (hiD (hai ▸ a.2)).elim + · simp [codeBasisVector, hai] + have hne : + (prepared N hN M a.1 n - codeBasisVector a.1) i ≠ 0 := + Finsupp.mem_support_iff.mp hi + exact hne (by simp [hprep0, hbasis0]) + +theorem closureInclusion_localDifference + (x : ContinuumFreeGroup) (a : RelevantCode N hN M x) (n : ℕ) : + closureInclusion N hN M x (localDifference N hN M x a n) = + prepared N hN M a.1 n - codeBasisVector a.1 := by + classical + letI : DecidablePred (closure N hN M x : ContinuumIndex → Prop) := + fun _ ↦ Classical.propDecidable _ + rw [closureInclusion_apply] + change Finsupp.embDomain + (.subtype (closure N hN M x : ContinuumIndex → Prop)) + (Finsupp.subtypeDomain (closure N hN M x) + (prepared N hN M a.1 n - codeBasisVector a.1)) = _ + exact + (Finsupp.extendDomain_eq_embDomain_subtype + (P := (closure N hN M x : ContinuumIndex → Prop)) + (Finsupp.subtypeDomain (closure N hN M x) + (prepared N hN M a.1 n - codeBasisVector a.1))).symm.trans + (Finsupp.extendDomain_subtypeDomain + (prepared N hN M a.1 n - codeBasisVector a.1) + (difference_support_subset_closure N hN M x a n)) + +theorem localDifference_injective + (x : ContinuumFreeGroup) (a : RelevantCode N hN M x) : + Function.Injective (localDifference N hN M x a) := by + intro m n hmn + apply preparedDifference_injective N hN M a.1 + change prepared N hN M a.1 m - codeBasisVector a.1 = + prepared N hN M a.1 n - codeBasisVector a.1 + rw [← closureInclusion_localDifference N hN M x a m, + ← closureInclusion_localDifference N hN M x a n, hmn] + +/-- The independent shifted set in one block, now inside the countable local group. -/ +def localDifferenceBlock (x : ContinuumFreeGroup) + (a : RelevantCode N hN M x) (l : ℕ) : + Finset (closure N hN M x →₀ ℤ) := + (blockPositions N hN l).image (localDifference N hN M x a) + +theorem localDifferenceBlock_card + (x : ContinuumFreeGroup) (a : RelevantCode N hN M x) (l : ℕ) : + (localDifferenceBlock N hN M x a l).card = N l := by + rw [localDifferenceBlock, + Finset.card_image_iff.mpr (localDifference_injective N hN M x a).injOn, + blockPositions_card] + +theorem localDifferenceBlock_image_inclusion + (x : ContinuumFreeGroup) (a : RelevantCode N hN M x) (l : ℕ) : + (localDifferenceBlock N hN M x a l).image (closureInclusion N hN M x) = + differenceBlock N hN M a.1 l := by + rw [localDifferenceBlock, differenceBlock, Finset.image_image] + apply Finset.image_congr + intro n hn + exact closureInclusion_localDifference N hN M x a n + +theorem localDifferenceBlock_boundedIndependent + (x : ContinuumFreeGroup) (a : RelevantCode N hN M x) (l : ℕ) : + BoundedIndependent (M l) (localDifferenceBlock N hN M x a l) := by + apply boundedIndependent_of_image (closureInclusion N hN M x) + (closureInclusion_injective N hN M x) + rw [localDifferenceBlock_image_inclusion] + exact differenceBlock_boundedIndependent N hN M a.1 l + +/-- The active finite set inside the local free group. -/ +def localActiveBlock (x : ContinuumFreeGroup) (l : ℕ) : + Finset (closure N hN M x →₀ ℤ) := + match activeCode N hN M x l with + | none => ∅ + | some a => localDifferenceBlock N hN M x a l + +theorem localActiveBlock_eq_of_mem (x : ContinuumFreeGroup) (l : ℕ) + (a : RelevantCode N hN M x) (ha : l ∈ refinedLabel N hN M x a) : + localActiveBlock N hN M x l = localDifferenceBlock N hN M x a l := by + simp [localActiveBlock, activeCode_eq_some_of_mem N hN M x l a ha] + +theorem localActiveBlock_boundedIndependent (x : ContinuumFreeGroup) (l : ℕ) : + BoundedIndependent (M l) (localActiveBlock N hN M x l) := by + unfold localActiveBlock + split + · simp [BoundedIndependent] + · rename_i a hactive + exact localDifferenceBlock_boundedIndependent N hN M x a l + +theorem localActiveBlock_card_le (x : ContinuumFreeGroup) (l : ℕ) : + (localActiveBlock N hN M x l).card ≤ N l := by + unfold localActiveBlock + split + · simp + · rename_i a hactive + rw [localDifferenceBlock_card] + +theorem localActiveBlock_card_eq_of_mem (x : ContinuumFreeGroup) (l : ℕ) + (a : RelevantCode N hN M x) (ha : l ∈ refinedLabel N hN M x a) : + (localActiveBlock N hN M x l).card = N l := by + rw [localActiveBlock_eq_of_mem N hN M x l a ha, + localDifferenceBlock_card] + +end + +end ConcreteLocalSetup +end Wallace diff --git a/LeanPool/Wallace/CountableClosure.lean b/LeanPool/Wallace/CountableClosure.lean new file mode 100644 index 000000000..1d0331d27 --- /dev/null +++ b/LeanPool/Wallace/CountableClosure.lean @@ -0,0 +1,100 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import Mathlib.Data.Set.Countable + +/-! +# Countable closure under triangular dependencies + +For a code `c`, `dependency c` is the countable set of basis coordinates occurring in its +prepared sequence. Because code indices are injective, closing a countable set under all codes +whose indices it contains still takes only countably many new coordinates at each finite stage. +-/ + +open Set + +universe u v + +namespace Wallace + +noncomputable section + +variable {I : Type u} {Code : Type v} + +/-- One closure step under a family of countable dependencies. -/ +def dependencyClosureStep (index : Code ↪ I) (dependency : Code → Set I) + (D : Set I) : Set I := + D ∪ ⋃ c, ⋃ (_h : index c ∈ D), dependency c + +/-- Finite stages of the dependency closure. -/ +def dependencyClosureStages (index : Code ↪ I) (dependency : Code → Set I) + (D₀ : Set I) : ℕ → Set I + | 0 => D₀ + | n + 1 => dependencyClosureStep index dependency (dependencyClosureStages index dependency D₀ n) + +/-- Closure after all finite stages. -/ +def dependencyClosure (index : Code ↪ I) (dependency : Code → Set I) + (D₀ : Set I) : Set I := + ⋃ n, dependencyClosureStages index dependency D₀ n + +theorem subset_dependencyClosureStep (index : Code ↪ I) (dependency : Code → Set I) + (D : Set I) : D ⊆ dependencyClosureStep index dependency D := + subset_union_left + +theorem dependencyClosureStages_mono (index : Code ↪ I) (dependency : Code → Set I) + (D₀ : Set I) : Monotone (dependencyClosureStages index dependency D₀) := by + intro m n hmn + induction n, hmn using Nat.le_induction with + | base => exact Subset.rfl + | succ n _ ih => + exact ih.trans (subset_dependencyClosureStep index dependency _) + +theorem subset_dependencyClosure (index : Code ↪ I) (dependency : Code → Set I) + (D₀ : Set I) : D₀ ⊆ dependencyClosure index dependency D₀ := by + intro x hx + exact Set.mem_iUnion.mpr ⟨0, hx⟩ + +/-- The closure is closed under every dependency whose code index it contains. -/ +theorem dependency_subset_closure_of_index_mem + (index : Code ↪ I) (dependency : Code → Set I) (D₀ : Set I) + {c : Code} (hc : index c ∈ dependencyClosure index dependency D₀) : + dependency c ⊆ dependencyClosure index dependency D₀ := by + obtain ⟨n, hcn⟩ := Set.mem_iUnion.mp hc + intro x hx + refine Set.mem_iUnion.mpr ⟨n + 1, ?_⟩ + exact Or.inr (Set.mem_iUnion.mpr ⟨c, Set.mem_iUnion.mpr ⟨hcn, hx⟩⟩) + +theorem countable_preimage_of_injective + (index : Code ↪ I) {D : Set I} (hD : D.Countable) : + {c : Code | index c ∈ D}.Countable := by + exact hD.preimage index.injective + +/-- A countable set remains countable after one dependency-closure step. -/ +theorem countable_dependencyClosureStep + (index : Code ↪ I) (dependency : Code → Set I) + (hdep : ∀ c, (dependency c).Countable) + {D : Set I} (hD : D.Countable) : + (dependencyClosureStep index dependency D).Countable := by + apply hD.union + have hcodes : {c : Code | index c ∈ D}.Countable := + countable_preimage_of_injective index hD + exact hcodes.biUnion fun c _hc ↦ hdep c + +/-- Closing a countable set under countable triangular dependencies is countable. -/ +theorem countable_dependencyClosure + (index : Code ↪ I) (dependency : Code → Set I) + (hdep : ∀ c, (dependency c).Countable) + {D₀ : Set I} (hD₀ : D₀.Countable) : + (dependencyClosure index dependency D₀).Countable := by + apply Set.countable_iUnion + intro n + induction n with + | zero => exact hD₀ + | succ n ih => exact countable_dependencyClosureStep index dependency hdep ih + +end + +end Wallace diff --git a/LeanPool/Wallace/CountableDisjointization.lean b/LeanPool/Wallace/CountableDisjointization.lean new file mode 100644 index 000000000..76da3c4dd --- /dev/null +++ b/LeanPool/Wallace/CountableDisjointization.lean @@ -0,0 +1,52 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.BlockFilters + +/-! +# Disjointizing a countable almost-disjoint family + +The block fusion uses a countable subfamily of the fixed almost-disjoint family. This module +orders any countable index type by an injection into `ℕ` and applies the standard predecessor +deletion. Each label loses only finitely many points. +-/ + +open Set + +namespace Wallace + +noncomputable section + +open AlmostDisjoint + +universe u v + +/-- Every countable almost-disjoint family has a pairwise disjoint refinement modulo finite +sets. Unlike an enumeration by a surjection, this statement also handles finite and empty +index types without duplicate indices. -/ +theorem exists_disjoint_refinement_countable + {ι : Type u} {α : Type v} [Countable ι] + (family : ι → Set α) + (had : Pairwise fun i j ↦ (family i ∩ family j).Finite) : + ∃ refined : ι → Set α, + (Pairwise fun i j ↦ Disjoint (refined i) (refined j)) ∧ + ∀ i, refined i ⊆ family i ∧ (family i \ refined i).Finite := by + let rank : ι → ℕ := Classical.choose (exists_injective_nat ι) + have hrank : Function.Injective rank := Classical.choose_spec (exists_injective_nat ι) + letI : LinearOrder ι := LinearOrder.lift' rank hrank + have hpred (i : ι) : (Set.Iio i).Finite := by + have heq : Set.Iio i = rank ⁻¹' Set.Iio (rank i) := by + ext j + rfl + rw [heq] + exact (Set.finite_Iio (rank i)).preimage hrank.injOn + refine ⟨disjointize family, pairwise_disjoint_disjointize family, ?_⟩ + intro i + exact ⟨disjointize_subset family i, disjointize_loss_finite family had i (hpred i)⟩ + +end + +end Wallace diff --git a/LeanPool/Wallace/FiniteCombinatorics.lean b/LeanPool/Wallace/FiniteCombinatorics.lean new file mode 100644 index 000000000..60693c395 --- /dev/null +++ b/LeanPool/Wallace/FiniteCombinatorics.lean @@ -0,0 +1,556 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import Mathlib + +/-! +# Finite combinatorics used in the Wallace construction + +This file formalizes the finite torsion-free-group bookkeeping used in Sections 4 and 5 of the +current paper: + +* the reindexing part of the triangular enumeration; +* extraction of finite bounded-independent sets; +* uniform integer dependence for bounded finite vectors; +* bounded deletion of at most `|A|` points. + +The paper writes integer bounds as `|c| ≤ M`. We use `Int.natAbs c ≤ M`, which is +definitionally the corresponding natural-number inequality. +-/ + +open scoped BigOperators +open Set + +universe u v + +namespace Wallace +namespace FiniteCombinatorics + +noncomputable section + +section Triangular + +variable {I : Type u} {T : Type v} [LinearOrder I] + +/-- The support condition in the triangular enumeration: every coordinate occurring in a term of +the sequence lies strictly below its assigned index. -/ +def SupportedBelow (s : ℕ → I →₀ ℤ) (i : I) : Prop := + ∀ n j, j ∈ (s n).support → j < i + +/-- Reindex a family by the range of an injective assignment of fresh upper bounds. + +This is the final reindexing step of the triangular-coding lemma in the paper. The genuinely +set-theoretic input of that lemma—that continuum many countable supports admit distinct upper +bounds below the initial ordinal of the continuum—is deliberately visible as `hbound`; it is not +silently postulated here. -/ +theorem triangular_reindex + (t : T → ℕ → I →₀ ℤ) (index : T ↪ I) + (ht : Function.Injective t) + (hbound : ∀ a, SupportedBelow (t a) (index a)) : + ∃ (Λ : Set I) (s : Λ → ℕ → I →₀ ℤ), + Function.Injective s ∧ Set.range s = Set.range t ∧ + ∀ α : Λ, SupportedBelow (s α) α := by + let Λ : Set I := Set.range index + let e : T ≃ Λ := Equiv.ofInjective index index.injective + let s : Λ → ℕ → I →₀ ℤ := t ∘ e.symm + refine ⟨Λ, s, ?_, ?_, ?_⟩ + · exact ht.comp e.symm.injective + · ext z + constructor + · rintro ⟨a, rfl⟩ + exact ⟨e.symm a, rfl⟩ + · rintro ⟨a, rfl⟩ + exact ⟨e a, by simp [s]⟩ + · intro α + have hα : (index (e.symm α) : I) = α := by + exact Subtype.ext_iff.mp (e.apply_symm_apply α) + simpa [s, SupportedBelow, hα] using hbound (e.symm α) + +end Triangular + +section Relations + +variable {G : Type u} [AddCommGroup G] + +/-- A finite set is `M`-independent if every integer relation whose coefficients have absolute +value at most `M` is trivial. This is the paper's definition, specialized to a finite set. -/ +def BoundedIndependent (M : ℕ) (X : Finset G) : Prop := + ∀ c : G → ℤ, (∀ x ∈ X, Int.natAbs (c x) ≤ M) → + (∑ x ∈ X, c x • x) = 0 → ∀ x ∈ X, c x = 0 + +/-- A point is forbidden over `B` if it satisfies one of the finitely many bounded equations used +in the bounded-independence extraction argument. -/ +def Forbidden (M : ℕ) (B : Finset G) (x : G) : Prop := + ∃ (q : ℤ) (c : B → ℤ), q ≠ 0 ∧ Int.natAbs q ≤ M ∧ + (∀ b, Int.natAbs (c b) ≤ M) ∧ + q • x + ∑ b, c b • (b : G) = 0 + +/-- The finite interval of integer coefficients of absolute value at most `M`. -/ +def boundedIntFinset (M : ℕ) : Finset ℤ := + Finset.Icc (-(M : ℤ)) (M : ℤ) + +@[simp] +theorem mem_boundedIntFinset_iff {M : ℕ} {z : ℤ} : + z ∈ boundedIntFinset M ↔ Int.natAbs z ≤ M := by + simp only [boundedIntFinset, Finset.mem_Icc] + constructor + · intro h + have habs : |z| ≤ (M : ℤ) := abs_le.mpr h + have hcast : (Int.natAbs z : ℤ) ≤ (M : ℤ) := by + rw [Int.abs_eq_natAbs] at habs + exact habs + exact Int.ofNat_le.mp hcast + · intro h + apply abs_le.mp + have hcast : (Int.natAbs z : ℤ) ≤ (M : ℤ) := Int.ofNat_le.mpr h + rw [Int.abs_eq_natAbs] + exact hcast + +/-- All bounded coefficient functions on a finite set. -/ +def coefficientPatterns (M : ℕ) (B : Finset G) : Finset (B → ℤ) := by + classical + exact Fintype.piFinset fun _ ↦ boundedIntFinset M + +omit [AddCommGroup G] in +@[simp] theorem mem_coefficientPatterns_iff {M : ℕ} {B : Finset G} {c : B → ℤ} : + c ∈ coefficientPatterns M B ↔ ∀ b, Int.natAbs (c b) ≤ M := by + classical + rw [coefficientPatterns, Fintype.mem_piFinset] + simp only [mem_boundedIntFinset_iff] + +noncomputable def equationSolution (B : Finset G) (q : ℤ) (c : B → ℤ) : G := + by + classical + exact if h : ∃ x : G, q • x + ∑ b, c b • (b : G) = 0 then Classical.choose h else 0 + +theorem equationSolution_spec {B : Finset G} {q : ℤ} {c : B → ℤ} + (h : ∃ x : G, q • x + ∑ b, c b • (b : G) = 0) : + q • equationSolution B q c + ∑ b, c b • (b : G) = 0 := by + classical + simp only [equationSolution, dif_pos h] + exact Classical.choose_spec h + +/-- A concrete finite set containing every forbidden point. -/ +noncomputable def forbiddenFinset (M : ℕ) (B : Finset G) : Finset G := + by + classical + exact ((boundedIntFinset M).erase 0 ×ˢ coefficientPatterns M B).image + (fun p ↦ equationSolution B p.1 p.2) + +theorem forbidden_mem_forbiddenFinset [IsAddTorsionFree G] + {M : ℕ} {B : Finset G} {x : G} (hx : Forbidden M B x) : + x ∈ forbiddenFinset M B := by + classical + rcases hx with ⟨q, c, hq0, hqM, hcM, hx⟩ + have hqmem : q ∈ (boundedIntFinset M).erase 0 := by + simp [hq0, hqM] + have hcmem : c ∈ coefficientPatterns M B := + mem_coefficientPatterns_iff.mpr hcM + have hw := equationSolution_spec (B := B) (q := q) (c := c) ⟨x, hx⟩ + have hqx : q • x = q • equationSolution B q c := by + calc + q • x = -(∑ b, c b • (b : G)) := eq_neg_of_add_eq_zero_left hx + _ = q • equationSolution B q c := (eq_neg_of_add_eq_zero_left hw).symm + have hxeq : x = equationSolution B q c := + zsmul_right_injective hq0 hqx + rw [hxeq] + exact Finset.mem_image.mpr ⟨(q, c), Finset.mem_product.mpr ⟨hqmem, hcmem⟩, rfl⟩ + +theorem boundedIndependent_insert_of_not_forbidden [IsAddTorsionFree G] [DecidableEq G] + {M : ℕ} {Y : Finset G} {x : G} + (hY : BoundedIndependent M Y) (hxY : x ∉ Y) + (hx : ¬ Forbidden M Y x) : BoundedIndependent M (insert x Y) := by + classical + intro c hc hsum + have hsum' : c x • x + ∑ y ∈ Y, c y • y = 0 := by + simpa [Finset.sum_insert, hxY] using hsum + have hcx : c x = 0 := by + by_contra hcx0 + apply hx + let cY : Y → ℤ := fun y ↦ c y + refine ⟨c x, cY, hcx0, hc x (Finset.mem_insert_self x Y), ?_, ?_⟩ + · intro y + exact hc y (Finset.mem_insert_of_mem y.property) + · rw [← Finset.sum_finset_coe] at hsum' + exact hsum' + have hsumY : ∑ y ∈ Y, c y • y = 0 := by + simpa [hcx] using hsum' + have hcY : ∀ y ∈ Y, c y = 0 := + hY c (fun y hy ↦ hc y (Finset.mem_insert_of_mem hy)) hsumY + intro z hz + rcases Finset.mem_insert.mp hz with rfl | hzY + · exact hcx + · exact hcY z hzY + +/-- **Bounded-independence extraction** (Lemma `lem:finite-extraction` in the paper). + +Every infinite subset of a torsion-free Abelian group contains an `M`-independent finite subset +of any prescribed cardinality `N`. -/ +theorem exists_boundedIndependent_finset [IsAddTorsionFree G] + {S : Set G} (hS : S.Infinite) (M N : ℕ) : + ∃ X : Finset G, (X : Set G) ⊆ S ∧ X.card = N ∧ BoundedIndependent M X := by + classical + induction N with + | zero => + refine ⟨∅, by simp, by simp, ?_⟩ + intro c _ _ x hx + simp at hx + | succ N ih => + obtain ⟨Y, hYS, hYcard, hYind⟩ := ih + obtain ⟨x, hxS, hxout⟩ := + hS.exists_notMem_finset (Y ∪ forbiddenFinset M Y) + have hxY : x ∉ Y := fun hx ↦ hxout (Finset.mem_union_left _ hx) + have hxforbidden : ¬ Forbidden M Y x := by + intro hx + exact hxout (Finset.mem_union_right _ (forbidden_mem_forbiddenFinset hx)) + refine ⟨insert x Y, ?_, ?_, + boundedIndependent_insert_of_not_forbidden hYind hxY hxforbidden⟩ + · intro z hz + rcases Finset.mem_insert.mp hz with rfl | hz + · exact hxS + · exact hYS hz + · simp [Finset.card_insert_of_notMem hxY, hYcard] + +section IntegerDependence + +/-- `s+1` integer vectors in `ℤ^s` have a nontrivial integer dependence. + +We first obtain a rational dependence by the dimension theorem and then clear all denominators +using mathlib's localization API. -/ +theorem exists_integer_dependence (s : ℕ) (b : Fin (s + 1) → Fin s → ℤ) : + ∃ coeff : Fin (s + 1) → ℤ, + (∃ i, coeff i ≠ 0) ∧ ∀ j, ∑ i, coeff i * b i j = 0 := by + classical + let v : Fin (s + 1) → (Fin s → ℚ) := fun i j ↦ (b i j : ℚ) + have hv : ¬ LinearIndependent ℚ v := by + intro hli + have hcard := hli.fintype_card_le_finrank + simp at hcard + obtain ⟨g, hgsum, i₀, hgi₀⟩ := Fintype.not_linearIndependent_iff.mp hv + let D : Submonoid.pos ℤ := + IsLocalization.commonDenom (Submonoid.pos ℤ) Finset.univ g + let coeff : Fin (s + 1) → ℤ := fun i ↦ + IsLocalization.integerMultiple (Submonoid.pos ℤ) Finset.univ g + ⟨i, Finset.mem_univ i⟩ + have hcoeffCast (i : Fin (s + 1)) : (coeff i : ℚ) = (D : ℤ) • g i := by + exact IsLocalization.map_integerMultiple (Submonoid.pos ℤ) Finset.univ g + ⟨i, Finset.mem_univ i⟩ + have hD0 : (D : ℤ) ≠ 0 := ne_of_gt D.property + have hcoeffi₀ : coeff i₀ ≠ 0 := by + intro hzero + have hz : (D : ℤ) • g i₀ = 0 := by + rw [← hcoeffCast] + simp [hzero] + have : g i₀ = 0 := by + simpa [hD0] using hz + exact hgi₀ this + refine ⟨coeff, ⟨i₀, hcoeffi₀⟩, ?_⟩ + intro j + have hcoord : ∑ i, g i * (b i j : ℚ) = 0 := by + have := congrFun hgsum j + simpa [v, smul_eq_mul] using this + have hcast : ((∑ i, coeff i * b i j : ℤ) : ℚ) = 0 := by + simp only [Int.cast_sum, Int.cast_mul] + simp_rw [hcoeffCast] + simp_rw [← Int.cast_smul_eq_zsmul ℚ, smul_eq_mul] + simp_rw [mul_assoc] + rw [← Finset.mul_sum] + simp [hcoord] + exact_mod_cast hcast + +/-- Integer coefficients in `[-Q,Q]`, as a finite type. -/ +abbrev BoundedInt (Q : ℕ) := ↑(boundedIntFinset Q) + +/-- All bounded vector families of every dimension at most `r`. -/ +structure BoundedVectorFamily (r Q : ℕ) where + size : Fin (r + 1) + vec : Fin (size + 1) → Fin size → BoundedInt Q +deriving Fintype + +noncomputable def chosenIntegerDependence {r Q : ℕ} (B : BoundedVectorFamily r Q) : + Fin (B.size + 1) → ℤ := + Classical.choose <| exists_integer_dependence B.size fun i j ↦ B.vec i j + +theorem chosenIntegerDependence_spec {r Q : ℕ} (B : BoundedVectorFamily r Q) : + (∃ i, chosenIntegerDependence B i ≠ 0) ∧ + ∀ j, ∑ i, chosenIntegerDependence B i * (B.vec i j : ℤ) = 0 := + Classical.choose_spec <| exists_integer_dependence B.size fun i j ↦ B.vec i j + +noncomputable def familyDependenceBound {r Q : ℕ} (B : BoundedVectorFamily r Q) : ℕ := + Finset.univ.sup fun i ↦ Int.natAbs (chosenIntegerDependence B i) + +/-- A uniform bound for an integer dependence among any `s+1` vectors in `ℤ^s`, for `s ≤ r`, +whose entries have absolute value at most `Q`. Finiteness of the parameter space gives the +uniformity; no unproved determinant estimate is used. -/ +noncomputable def integerDependenceBound (r Q : ℕ) : ℕ := + Finset.univ.sup fun B : BoundedVectorFamily r Q ↦ familyDependenceBound B + +theorem exists_uniform_integer_dependence + {r Q s : ℕ} (hs : s ≤ r) (b : Fin (s + 1) → Fin s → ℤ) + (hb : ∀ i j, Int.natAbs (b i j) ≤ Q) : + ∃ coeff : Fin (s + 1) → ℤ, + (∃ i, coeff i ≠ 0) ∧ + (∀ j, ∑ i, coeff i * b i j = 0) ∧ + ∀ i, Int.natAbs (coeff i) ≤ integerDependenceBound r Q := by + classical + let B : BoundedVectorFamily r Q := + { size := ⟨s, Nat.lt_succ_iff.mpr hs⟩ + vec := fun i j ↦ ⟨b i j, mem_boundedIntFinset_iff.mpr (hb i j)⟩ } + let coeff : Fin (s + 1) → ℤ := chosenIntegerDependence B + have hspec := chosenIntegerDependence_spec B + refine ⟨coeff, hspec.1, ?_, ?_⟩ + · intro j + exact hspec.2 j + · intro i + apply le_trans (Finset.le_sup (s := Finset.univ) (f := fun k ↦ + Int.natAbs (chosenIntegerDependence B k)) (Finset.mem_univ i)) + exact Finset.le_sup (s := Finset.univ) (f := familyDependenceBound) + (Finset.mem_univ B) + +end IntegerDependence + +section BoundedDeletion + +/-- A bounded relation using both the finite families `A` and `Y`. -/ +def HasMixedRelation (Q : ℕ) (A Y : Finset G) : Prop := + ∃ (b c : G → ℤ), + (∀ a ∈ A, Int.natAbs (b a) ≤ Q) ∧ + (∀ y ∈ Y, Int.natAbs (c y) ≤ Q) ∧ + (∃ a ∈ A, b a ≠ 0) ∧ + (∃ y ∈ Y, c y ≠ 0) ∧ + (∑ a ∈ A, b a • a) + ∑ y ∈ Y, c y • y = 0 + +def MixedRelationFree (Q : ℕ) (A Y : Finset G) : Prop := + ¬ HasMixedRelation Q A Y + +theorem mixedRelationFree_empty (Q : ℕ) (A : Finset G) : + MixedRelationFree Q A ∅ := by + rintro ⟨b, c, hb, hc, hb0, hc0, hsum⟩ + simp at hc0 + +/-- A maximal relation-free subset of `X`. Maximality is by cardinality and therefore implies +that adjoining any omitted point creates a mixed relation. -/ +theorem exists_maximal_mixedRelationFree [DecidableEq G] (Q : ℕ) (A X : Finset G) : + ∃ Y : Finset G, Y ⊆ X ∧ MixedRelationFree Q A Y ∧ + ∀ x ∈ X, x ∉ Y → HasMixedRelation Q A (insert x Y) := by + classical + let candidates : Finset (Finset G) := + X.powerset.filter fun Y ↦ MixedRelationFree Q A Y + have hempty : ∅ ∈ candidates := by + simp [candidates, mixedRelationFree_empty] + have hne : candidates.Nonempty := ⟨∅, hempty⟩ + obtain ⟨Y, hYmem, hYmax⟩ := candidates.exists_mem_eq_sup hne Finset.card + have hYX : Y ⊆ X := by + exact Finset.mem_powerset.mp (Finset.mem_filter.mp hYmem).1 + have hYfree : MixedRelationFree Q A Y := (Finset.mem_filter.mp hYmem).2 + refine ⟨Y, hYX, hYfree, ?_⟩ + intro x hxX hxY + by_contra hfree + have hinsertX : insert x Y ⊆ X := by + intro z hz + rcases Finset.mem_insert.mp hz with rfl | hzY + · exact hxX + · exact hYX hzY + have hinsertMem : insert x Y ∈ candidates := by + exact Finset.mem_filter.mpr + ⟨Finset.mem_powerset.mpr hinsertX, hfree⟩ + have hle : (insert x Y).card ≤ candidates.sup Finset.card := + Finset.le_sup (s := candidates) (f := Finset.card) hinsertMem + rw [hYmax, Finset.card_insert_of_notMem hxY] at hle + omega + +theorem mixedRelation_insert_witness [DecidableEq G] + {Q : ℕ} {A Y : Finset G} {x : G} + (hY : MixedRelationFree Q A Y) (hxY : x ∉ Y) + (hrel : HasMixedRelation Q A (insert x Y)) : + ∃ (b c : G → ℤ), + (∀ a ∈ A, Int.natAbs (b a) ≤ Q) ∧ + (∀ z ∈ insert x Y, Int.natAbs (c z) ≤ Q) ∧ + (∃ a ∈ A, b a ≠ 0) ∧ c x ≠ 0 ∧ + (∑ a ∈ A, b a • a) + ∑ z ∈ insert x Y, c z • z = 0 := by + rcases hrel with ⟨b, c, hbQ, hcQ, hb0, hc0, hsum⟩ + have hcx : c x ≠ 0 := by + intro hcx0 + apply hY + refine ⟨b, c, hbQ, ?_, hb0, ?_, ?_⟩ + · intro y hy + exact hcQ y (Finset.mem_insert_of_mem hy) + · rcases hc0 with ⟨z, hz, hcz⟩ + rcases Finset.mem_insert.mp hz with rfl | hzY + · exact (hcz hcx0).elim + · exact ⟨z, hzY, hcz⟩ + · simpa [Finset.sum_insert, hxY, hcx0] using hsum + exact ⟨b, c, hbQ, hcQ, hb0, hcx, hsum⟩ + +/-- The independence threshold from the current paper. Here `integerDependenceBound r Q` is +the finite maximum denoted by `B(r,Q)`, so this is exactly `M(r,Q) = (r+1) B(r,Q) Q`. -/ +noncomputable def deletionIndependenceBound (r Q : ℕ) : ℕ := + (r + 1) * (integerDependenceBound r Q * Q) + +/-- **Bounded deletion** (Lemma `lem:bounded-deletion` in the paper). + +From an adequately bounded-independent finite set `X`, delete at most `|A|` points so that no +bounded relation uses both `A` and the retained set. The threshold and the conclusion—including +the sharp deletion count `|X \ Y| ≤ |A|`—are the ones in the paper. -/ +theorem bounded_deletion [IsAddTorsionFree G] [DecidableEq G] + (r Q : ℕ) (A X : Finset G) (hAr : A.card ≤ r) + (hX : BoundedIndependent (deletionIndependenceBound r Q) X) : + ∃ Y : Finset G, Y ⊆ X ∧ (X \ Y).card ≤ A.card ∧ MixedRelationFree Q A Y := by + classical + obtain ⟨Y, hYX, hYfree, hYmax⟩ := exists_maximal_mixedRelationFree Q A X + refine ⟨Y, hYX, ?_, hYfree⟩ + by_contra hcard + have hlarge : A.card + 1 ≤ (X \ Y).card := by omega + obtain ⟨D, hDsub, hDcard⟩ := + Finset.exists_subset_card_eq hlarge + let s := A.card + let eA : Fin s ≃ A := A.equivFin.symm + let eD : Fin (s + 1) ≃ D := + (finCongr hDcard.symm).trans D.equivFin.symm + let point : Fin (s + 1) → G := fun i ↦ (eD i : G) + have hpointD (i : Fin (s + 1)) : point i ∈ D := (eD i).property + have hpointX (i : Fin (s + 1)) : point i ∈ X := + (Finset.mem_sdiff.mp (hDsub (hpointD i))).1 + have hpointY (i : Fin (s + 1)) : point i ∉ Y := + (Finset.mem_sdiff.mp (hDsub (hpointD i))).2 + have hwitness (i : Fin (s + 1)) := + mixedRelation_insert_witness hYfree (hpointY i) + (hYmax (point i) (hpointX i) (hpointY i)) + choose b c hbQ hcQ hb0 hcx hsum using hwitness + obtain ⟨coeff, hcoeff0, hcoeffDep, hcoeffBound⟩ := + exists_uniform_integer_dependence hAr + (fun i j ↦ b i (eA j)) + (fun i j ↦ hbQ i (eA j) (eA j).property) + let cN : Fin (s + 1) → G → ℤ := fun i z ↦ + if z ∈ insert (point i) Y then c i z else 0 + have hcNBound (i : Fin (s + 1)) (z : G) : Int.natAbs (cN i z) ≤ Q := by + by_cases hz : z ∈ insert (point i) Y + · rw [show cN i z = c i z by simp only [cN, if_pos hz]] + exact hcQ i z hz + · rw [show cN i z = 0 by simp only [cN, if_neg hz]] + simp + have hcNPoint (i : Fin (s + 1)) : cN i (point i) ≠ 0 := by + simpa [cN] using hcx i + have hsumN (i : Fin (s + 1)) : + (∑ a ∈ A, b i a • a) + + ∑ z ∈ insert (point i) Y, cN i z • z = 0 := by + rw [← hsum i] + congr 1 + apply Finset.sum_congr rfl + intro z hz + rw [show cN i z = c i z by simp only [cN, if_pos hz]] + let k : G → ℤ := fun z ↦ ∑ i, coeff i * cN i z + have hkBound : ∀ z ∈ X, + Int.natAbs (k z) ≤ deletionIndependenceBound r Q := by + intro z hzX + calc + Int.natAbs (k z) ≤ ∑ i ∈ (Finset.univ : Finset (Fin (s + 1))), + Int.natAbs (coeff i * cN i z) := by + simpa [k] using Int.natAbs_sum_le + (Finset.univ : Finset (Fin (s + 1))) + (fun i ↦ coeff i * cN i z) + _ = ∑ i : Fin (s + 1), Int.natAbs (coeff i) * Int.natAbs (cN i z) := by + simp [Int.natAbs_mul] + _ ≤ ∑ _i : Fin (s + 1), integerDependenceBound r Q * Q := by + exact Finset.sum_le_sum fun i _ ↦ + Nat.mul_le_mul (hcoeffBound i) (hcNBound i z) + _ = (s + 1) * (integerDependenceBound r Q * Q) := by simp + _ ≤ (r + 1) * (integerDependenceBound r Q * Q) := by + exact Nat.mul_le_mul_right _ (Nat.add_le_add_right hAr 1) + _ = deletionIndependenceBound r Q := rfl + have hApart : + ∑ i, coeff i • (∑ a ∈ A, b i a • a) = 0 := by + calc + ∑ i, coeff i • (∑ a ∈ A, b i a • a) = + ∑ a ∈ A, (∑ i, coeff i * b i a) • a := by + simp_rw [Finset.smul_sum, smul_smul] + rw [Finset.sum_comm] + apply Finset.sum_congr rfl + intro a ha + exact (Finset.sum_smul (s := Finset.univ) + (f := fun i ↦ coeff i * b i a) (x := a)).symm + _ = 0 := by + apply Finset.sum_eq_zero + intro a ha + have hdep := hcoeffDep (eA.symm ⟨a, ha⟩) + have hea : (eA (eA.symm ⟨a, ha⟩) : G) = a := by simp + simp only [hea] at hdep + rw [hdep, zero_zsmul] + have htotal : + ∑ i, coeff i • + ((∑ a ∈ A, b i a • a) + + ∑ z ∈ insert (point i) Y, cN i z • z) = 0 := by + apply Finset.sum_eq_zero + intro i _ + rw [hsumN i, smul_zero] + have hXpart : + ∑ i, coeff i • + (∑ z ∈ insert (point i) Y, cN i z • z) = 0 := by + have hsplit := htotal + simp only [smul_add, Finset.sum_add_distrib] at hsplit + rw [hApart, zero_add] at hsplit + exact hsplit + have hinsertX (i : Fin (s + 1)) : insert (point i) Y ⊆ X := by + intro z hz + rcases Finset.mem_insert.mp hz with rfl | hzY + · exact hpointX i + · exact hYX hzY + have hkSumEq : + (∑ z ∈ X, k z • z) = + ∑ i, coeff i • + (∑ z ∈ insert (point i) Y, cN i z • z) := by + calc + (∑ z ∈ X, k z • z) = + ∑ z ∈ X, ∑ i, (coeff i * cN i z) • z := by + apply Finset.sum_congr rfl + intro z hz + change (∑ i, coeff i * cN i z) • z = + ∑ i, (coeff i * cN i z) • z + exact Finset.sum_smul (s := Finset.univ) + (f := fun i ↦ coeff i * cN i z) (x := z) + _ = ∑ i, ∑ z ∈ X, (coeff i * cN i z) • z := by + rw [Finset.sum_comm] + _ = ∑ i, ∑ z ∈ insert (point i) Y, + (coeff i * cN i z) • z := by + apply Finset.sum_congr rfl + intro i hi + symm + apply Finset.sum_subset (hinsertX i) + intro z hzX hznot + have hcz : cN i z = 0 := by simp only [cN, if_neg hznot] + simp [hcz] + _ = ∑ i, coeff i • + (∑ z ∈ insert (point i) Y, cN i z • z) := by + apply Finset.sum_congr rfl + intro i hi + simp_rw [Finset.smul_sum, smul_smul] + have hkSum : ∑ z ∈ X, k z • z = 0 := hkSumEq.trans hXpart + have hkZero : ∀ z ∈ X, k z = 0 := hX k hkBound hkSum + obtain ⟨i₀, hi₀⟩ := hcoeff0 + have hcNOther (i : Fin (s + 1)) (hi : i ≠ i₀) : cN i (point i₀) = 0 := by + have hne : point i₀ ≠ point i := by + intro heq + apply hi + exact eD.injective (Subtype.ext heq.symm) + simp [cN, hne, hpointY i₀] + have hkPoint : k (point i₀) = coeff i₀ * cN i₀ (point i₀) := by + dsimp [k] + rw [Fintype.sum_eq_single i₀] + intro i hi + rw [hcNOther i hi] + simp + have hkPointNe : k (point i₀) ≠ 0 := by + rw [hkPoint] + exact mul_ne_zero hi₀ (hcNPoint i₀) + exact hkPointNe (hkZero (point i₀) (hpointX i₀)) + +end BoundedDeletion + +end Relations + +end +end FiniteCombinatorics +end Wallace diff --git a/LeanPool/Wallace/FullTopology.lean b/LeanPool/Wallace/FullTopology.lean new file mode 100644 index 000000000..6abcadf91 --- /dev/null +++ b/LeanPool/Wallace/FullTopology.lean @@ -0,0 +1,307 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.NontrivialSequences + +/-! +# Full topological consequences of the character construction + +This file isolates the exact output needed to obtain the group theorem, rather than only its +nonnegative-cone consequence. A `FullCharacterPackage` codes every injective sequence, assigns +it a genuine subsequence and a free ultrafilter, and supplies a point-separating family of +circle-valued characters for which that subsequence has a prescribed nonzero limit. + +The initial topology of such a package is Hausdorff, is a group topology, is countably compact, +and has no non-eventually-constant convergent sequences. Its canonical induced uniformity is +totally bounded, which is the uniform formulation of precompactness used here. +-/ + +open Filter Set Topology + +universe u v + +namespace Wallace + +noncomputable section + +/-! ## Countable compactness from the nonzero-limit property -/ + +/-- The nonzero ultrafilter-limit property gives an accumulation point for every infinite set. -/ +theorem infiniteSet_accumulation_of_nonzero_ultrafilter_limits + {X : Type u} [TopologicalSpace X] [Zero X] + (hlimits : HasNonzeroLimitProperty X) : + HasInfiniteSetAccumulationProperty X := by + intro B hBinf + let e : ℕ ↪ B := hBinf.natEmbedding + let s : ℕ → X := fun n ↦ e n + have sinj : Function.Injective s := Subtype.val_injective.comp e.injective + obtain ⟨φ, x, p, hφ, _hx, hfree, htendsto⟩ := hlimits s sinj + have uinj : Function.Injective (s ∘ φ) := sinj.comp hφ.injective + have hacc : AccPt x (Filter.principal (Set.range (s ∘ φ))) := + accPt_range_of_free_ultrafilter_limit uinj hfree htendsto + refine ⟨x, hacc.mono <| Filter.principal_mono.2 ?_⟩ + intro y hy + obtain ⟨n, rfl⟩ := hy + exact (e (φ n)).property + +/-- In a `T₁` space, the package's ultrafilter limits imply countable compactness. -/ +theorem countablyCompact_of_nonzero_ultrafilter_limits + {X : Type u} [TopologicalSpace X] [Zero X] [T1Space X] + (hlimits : HasNonzeroLimitProperty X) : + CountablyCompactSpace X := + countablyCompact_of_infiniteSet_accumulation + (infiniteSet_accumulation_of_nonzero_ultrafilter_limits hlimits) + +/-! ## A group-independent character package -/ + +/-- The exact character data from which all conclusions of the group theorem follow. This +interface applies without change to free Abelian groups and rational vector groups. -/ +structure FullCharacterPackage (G : Type u) [AddCommGroup G] where + Code : Type v + codeEquiv : Code ≃ InjectiveSequence' G + subsequence : Code → ℕ → ℕ + subsequence_strictMono : ∀ c, StrictMono (subsequence c) + ultrafilter : Code → Ultrafilter ℕ + ultrafilter_free : ∀ c, (ultrafilter c : Filter ℕ) ≤ cofinite + limitPoint : Code → G + limitPoint_ne_zero : ∀ c, limitPoint c ≠ 0 + CharacterIndex : Type v + character : CharacterIndex → G →+ UnitAddCircle + character_detects : ∀ x : G, x ≠ 0 → ∃ j, character j x ≠ 0 + character_limit : + ∀ (c : Code) (j : CharacterIndex), + Tendsto + (fun n ↦ character j ((codeEquiv c).1 (subsequence c n))) + (ultrafilter c) + (𝓝 (character j (limitPoint c))) + +namespace FullCharacterPackage + +variable {G : Type u} [AddCommGroup G] + +/-- Simultaneous evaluation by all characters in the package. -/ +def evaluation (C : FullCharacterPackage G) : + G →+ (C.CharacterIndex → UnitAddCircle) where + toFun x j := C.character j x + map_zero' := by ext j; simp + map_add' x y := by ext j; simp + +/-- The initial topology generated by the package's characters. -/ +@[reducible] def initialTopology (C : FullCharacterPackage G) : TopologicalSpace G := + TopologicalSpace.induced C.evaluation inferInstance + +/-- The uniformity pulled back from the compact power of the circle. -/ +@[reducible] def initialUniformSpace (C : FullCharacterPackage G) : UniformSpace G := + UniformSpace.comap C.evaluation inferInstance + +theorem initialUniformSpace_toTopology (C : FullCharacterPackage G) : + C.initialUniformSpace.toTopologicalSpace = C.initialTopology := rfl + +/-- The pulled-back uniformity is the canonical uniform group structure induced by the diagonal +homomorphism. -/ +theorem initial_isUniformAddGroup (C : FullCharacterPackage G) : + @IsUniformAddGroup G C.initialUniformSpace _ := + IsUniformAddGroup.comap C.evaluation + +theorem evaluation_injective (C : FullCharacterPackage G) : + Function.Injective C.evaluation := by + intro x y hxy + apply sub_eq_zero.mp + by_contra hsub + obtain ⟨j, hj⟩ := C.character_detects (x - y) hsub + apply hj + rw [map_sub] + have hcoord : C.character j x = C.character j y := congrFun hxy j + rw [hcoord, sub_self] + +theorem initial_isTopologicalAddGroup (C : FullCharacterPackage G) : + @IsTopologicalAddGroup G C.initialTopology _ := + topologicalAddGroup_induced C.evaluation + +theorem initial_t2Space (C : FullCharacterPackage G) : + @T2Space G C.initialTopology := by + letI : TopologicalSpace G := C.initialTopology + exact C.evaluation_injective.isEmbedding_induced.t2Space + +/-- The selected subsequence converges to its prescribed point in the initial topology. -/ +theorem prepared_tendsto_limitPoint (C : FullCharacterPackage G) (c : C.Code) : + Tendsto + (fun n ↦ (C.codeEquiv c).1 (C.subsequence c n)) + (C.ultrafilter c) + (@nhds G C.initialTopology (C.limitPoint c)) := by + letI : TopologicalSpace G := C.initialTopology + have hinducing : IsInducing C.evaluation := ⟨rfl⟩ + refine hinducing.tendsto_nhds_iff.mpr ?_ + refine tendsto_pi_nhds.2 fun j ↦ ?_ + simpa [evaluation, Function.comp_def] using C.character_limit c j + +theorem hasNonzeroLimitProperty (C : FullCharacterPackage G) : + @HasNonzeroLimitProperty G C.initialTopology _ := by + intro s hs + let encoded : InjectiveSequence' G := ⟨s, hs⟩ + let c : C.Code := C.codeEquiv.symm encoded + have hcoded : (C.codeEquiv c).1 = s := + congrArg Subtype.val (C.codeEquiv.apply_symm_apply encoded) + refine ⟨C.subsequence c, C.limitPoint c, C.ultrafilter c, + C.subsequence_strictMono c, C.limitPoint_ne_zero c, + C.ultrafilter_free c, ?_⟩ + change Tendsto (fun n ↦ s (C.subsequence c n)) (C.ultrafilter c) _ + rw [← hcoded] + exact C.prepared_tendsto_limitPoint c + +theorem initial_countablyCompactSpace (C : FullCharacterPackage G) : + @CountablyCompactSpace G C.initialTopology := by + letI : TopologicalSpace G := C.initialTopology + letI : T2Space G := C.initial_t2Space + exact countablyCompact_of_nonzero_ultrafilter_limits + C.hasNonzeroLimitProperty + +theorem initial_noInjectiveConvergentSequences (C : FullCharacterPackage G) : + ∀ s : ℕ → G, Function.Injective s → + ¬ ∃ x : G, Tendsto s atTop (@nhds G C.initialTopology x) := by + letI : TopologicalSpace G := C.initialTopology + letI : IsTopologicalAddGroup G := C.initial_isTopologicalAddGroup + letI : T2Space G := C.initial_t2Space + exact no_injective_sequence_converges_of_nonzeroLimitProperty + C.hasNonzeroLimitProperty + +theorem initial_onlyEventuallyConstantConvergentSequences + (C : FullCharacterPackage G) : + ∀ (s : ℕ → G) (x : G), + Tendsto s atTop (@nhds G C.initialTopology x) → + ∀ᶠ n in atTop, s n = x := by + letI : TopologicalSpace G := C.initialTopology + letI : T2Space G := C.initial_t2Space + intro s x hs + exact eventually_eq_limit_of_no_injective_sequence_converges + C.initial_noInjectiveConvergentSequences hs + +/-- The induced uniformity is totally bounded because the target is a compact power of the +circle. -/ +theorem initial_totallyBounded (C : FullCharacterPackage G) : + @TotallyBounded G C.initialUniformSpace Set.univ := by + letI : UniformSpace G := C.initialUniformSpace + have hinducing : IsUniformInducing C.evaluation := ⟨rfl⟩ + have htarget : TotallyBounded + (Set.univ : Set (C.CharacterIndex → UnitAddCircle)) := + isCompact_univ.totallyBounded + simpa using totallyBounded_preimage hinducing htarget + +end FullCharacterPackage + +/-! ## The package already constructed for the free Abelian group -/ + +namespace SeparationPackage + +variable {I : Type u} + +/-- Regard the existing free-Abelian separation package as a full character package. -/ +def toFullCharacterPackage (C : SeparationPackage I) : + FullCharacterPackage (I →₀ ℤ) where + Code := C.Code + codeEquiv := C.codeEquiv + subsequence := C.subsequence + subsequence_strictMono := C.subsequence_strictMono + ultrafilter := C.ultrafilter + ultrafilter_free := C.ultrafilter_free + limitPoint c := Finsupp.single (C.codeIndex c) 1 + limitPoint_ne_zero _ := Finsupp.single_ne_zero.mpr one_ne_zero + CharacterIndex := {x : I →₀ ℤ // x ≠ 0} + character := C.character + character_detects x hx := ⟨⟨x, hx⟩, C.character_self_ne_zero ⟨x, hx⟩⟩ + character_limit := C.character_limit + +theorem full_initialTopology_eq (C : SeparationPackage I) : + C.toFullCharacterPackage.initialTopology = C.initialTopology := rfl + +theorem initial_countablyCompactSpace (C : SeparationPackage I) : + @CountablyCompactSpace (I →₀ ℤ) C.initialTopology := by + rw [← C.full_initialTopology_eq] + exact C.toFullCharacterPackage.initial_countablyCompactSpace + +theorem initial_noInjectiveConvergentSequences (C : SeparationPackage I) : + ∀ s : ℕ → (I →₀ ℤ), Function.Injective s → + ¬ ∃ x : I →₀ ℤ, + Tendsto s atTop (@nhds (I →₀ ℤ) C.initialTopology x) := by + rw [← C.full_initialTopology_eq] + exact C.toFullCharacterPackage.initial_noInjectiveConvergentSequences + +theorem initial_onlyEventuallyConstantConvergentSequences + (C : SeparationPackage I) : + ∀ (s : ℕ → (I →₀ ℤ)) (x : I →₀ ℤ), + Tendsto s atTop (@nhds (I →₀ ℤ) C.initialTopology x) → + ∀ᶠ n in atTop, s n = x := by + rw [← C.full_initialTopology_eq] + exact C.toFullCharacterPackage.initial_onlyEventuallyConstantConvergentSequences + +@[reducible] def initialUniformSpace (C : SeparationPackage I) : + UniformSpace (I →₀ ℤ) := + C.toFullCharacterPackage.initialUniformSpace + +theorem initialUniformSpace_toTopology (C : SeparationPackage I) : + C.initialUniformSpace.toTopologicalSpace = C.initialTopology := by + exact C.toFullCharacterPackage.initialUniformSpace_toTopology + +theorem initial_isUniformAddGroup (C : SeparationPackage I) : + @IsUniformAddGroup (I →₀ ℤ) C.initialUniformSpace _ := + C.toFullCharacterPackage.initial_isUniformAddGroup + +theorem initial_totallyBounded (C : SeparationPackage I) : + @TotallyBounded (I →₀ ℤ) C.initialUniformSpace Set.univ := + C.toFullCharacterPackage.initial_totallyBounded + +end SeparationPackage + +/-! ## Publication-level theorem interfaces -/ + +/-- The exact topological conclusion shared by the free-Abelian and rational-vector-group +results. Total boundedness is stated for a compatible uniformity inducing the displayed +topology. -/ +def HasMainGroupTopology (G : Type u) [AddCommGroup G] : Prop := + ∃ (topology : TopologicalSpace G) (uniformity : UniformSpace G), + uniformity.toTopologicalSpace = topology ∧ + @IsUniformAddGroup G uniformity _ ∧ + @IsTopologicalAddGroup G topology _ ∧ + @T2Space G topology ∧ + @CountablyCompactSpace G topology ∧ + @TotallyBounded G uniformity Set.univ ∧ + (∀ (s : ℕ → G) (x : G), + Tendsto s atTop (@nhds G topology x) → ∀ᶠ n in atTop, s n = x) + +/-- A full character package proves the complete group-topology conclusion. -/ +theorem FullCharacterPackage.hasMainGroupTopology + {G : Type u} [AddCommGroup G] (C : FullCharacterPackage G) : + HasMainGroupTopology G := by + refine ⟨C.initialTopology, C.initialUniformSpace, + C.initialUniformSpace_toTopology, C.initial_isUniformAddGroup, + C.initial_isTopologicalAddGroup, + C.initial_t2Space, C.initial_countablyCompactSpace, + C.initial_totallyBounded, + C.initial_onlyEventuallyConstantConvergentSequences⟩ + +/-- Exact statement of the free-Abelian group theorem for an arbitrary index type. -/ +abbrev FreeAbelianGroupConclusion (I : Type u) : Prop := + HasMainGroupTopology (I →₀ ℤ) + +/-- Exact statement of the rational-vector-group proposition for an arbitrary index type. -/ +abbrev RationalVectorGroupConclusion (I : Type u) : Prop := + HasMainGroupTopology (I →₀ ℚ) + +theorem SeparationPackage.freeAbelianGroupConclusion + {I : Type u} (C : SeparationPackage I) : + FreeAbelianGroupConclusion I := + C.toFullCharacterPackage.hasMainGroupTopology + +/-- Once the construction is instantiated on the rational direct sum, the rational proposition +follows through exactly the same topology argument. -/ +theorem FullCharacterPackage.rationalVectorGroupConclusion + {I : Type u} (C : FullCharacterPackage (I →₀ ℚ)) : + RationalVectorGroupConclusion I := + C.hasMainGroupTopology + +end + +end Wallace diff --git a/LeanPool/Wallace/FullTopologyMain.lean b/LeanPool/Wallace/FullTopologyMain.lean new file mode 100644 index 000000000..8ecd4fac1 --- /dev/null +++ b/LeanPool/Wallace/FullTopologyMain.lean @@ -0,0 +1,58 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.ConcreteFusionRun +import LeanPool.Wallace.FullTopology + +/-! +# The full free-Abelian group theorem + +This module applies the unconditional fusion construction to the generic topological results in +`Wallace.FullTopology`. The resulting theorem has no hypotheses. +-/ + +namespace Wallace + +noncomputable section + +open TriangularPreprocess +open Filter Topology + +/-- The fully constructed character package on the canonical free Abelian group of rank +continuum. -/ +def continuumFullSeparationPackage : SeparationPackage ContinuumIndex := + GlobalAssembly.separationPackage + ConcreteFusionRun.blockSize ConcreteFusionRun.blockSize_pos + ConcreteFusionRun.independenceBound + ConcreteFusionRun.hasLocalSeparatingCharacters + +/-- **Free-Abelian specialization of the main theorem.** The free Abelian group of rank +continuum admits a Hausdorff +precompact countably compact group topology in which every convergent sequence is eventually +constant. Precompactness is certified by a compatible totally bounded uniform group +structure. -/ +theorem continuumFreeAbelianGroup_mainTheorem : + FreeAbelianGroupConclusion ContinuumIndex := + continuumFullSeparationPackage.freeAbelianGroupConclusion + +/-- The witness-level form of the free-Abelian specialization, kept as a convenient public API. -/ +theorem continuumFreeAbelianGroup_mainTheorem_explicit : + ∃ (topology : TopologicalSpace ContinuumFreeGroup) + (uniformity : UniformSpace ContinuumFreeGroup), + uniformity.toTopologicalSpace = topology ∧ + @IsUniformAddGroup ContinuumFreeGroup uniformity _ ∧ + @IsTopologicalAddGroup ContinuumFreeGroup topology _ ∧ + @T2Space ContinuumFreeGroup topology ∧ + @CountablyCompactSpace ContinuumFreeGroup topology ∧ + @TotallyBounded ContinuumFreeGroup uniformity Set.univ ∧ + (∀ (s : ℕ → ContinuumFreeGroup) (x : ContinuumFreeGroup), + Tendsto s Filter.atTop (@nhds ContinuumFreeGroup topology x) → + ∀ᶠ n in Filter.atTop, s n = x) := + continuumFreeAbelianGroup_mainTheorem + +end + +end Wallace diff --git a/LeanPool/Wallace/FusionLimit.lean b/LeanPool/Wallace/FusionLimit.lean new file mode 100644 index 000000000..951d4ddb5 --- /dev/null +++ b/LeanPool/Wallace/FusionLimit.lean @@ -0,0 +1,83 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import Mathlib.Analysis.Normed.Group.AddCircle +import Mathlib.Analysis.SpecificLimits.Basic + +/-! +# Pointwise limits of character fusions + +The fusion construction produces a sequence of circle-valued homomorphisms. Every group +element is eventually protected, so its values form a Cauchy sequence. This file isolates the +complete metric argument: the pointwise limit is again a homomorphism, and a geometric bound on +a tail gives an explicit bound from the first point of that tail to the limit. +-/ + +open Filter Topology +open scoped ENNReal + +universe u + +namespace Wallace + +noncomputable section + +variable {G : Type u} [AddGroup G] + +/-- A geometric estimate after deleting a finite initial segment implies that the original +sequence is Cauchy. -/ +theorem cauchySeq_of_tail_edist_le_geometric_two + {X : Type*} [PseudoEMetricSpace X] {u : ℕ → X} + (N : ℕ) (C : ℝ≥0∞) (hC : C ≠ ∞) + (hstep : ∀ n, edist (u (N + n)) (u (N + n + 1)) ≤ C / 2 ^ n) : + CauchySeq u := by + rw [← cauchySeq_shift N] + apply cauchySeq_of_edist_le_geometric_two C hC + intro n + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hstep n + +/-- Explicit distance from the beginning of a geometrically controlled tail to its limit. -/ +theorem edist_le_of_tail_geometric_two_of_tendsto + {X : Type*} [PseudoEMetricSpace X] {u : ℕ → X} {a : X} + (N : ℕ) (C : ℝ≥0∞) + (hstep : ∀ n, edist (u (N + n)) (u (N + n + 1)) ≤ C / 2 ^ n) + (hu : Tendsto u atTop (nhds a)) : + edist (u N) a ≤ 2 * C := by + let v : ℕ → X := fun n ↦ u (N + n) + have hvstep : ∀ n, edist (v n) (v (n + 1)) ≤ C / 2 ^ n := by + intro n + simpa [v, Nat.add_assoc] using hstep n + have hvlim : Tendsto v atTop (nhds a) := by + have hshift := hu.comp (tendsto_add_atTop_nat N) + change Tendsto (fun n ↦ u (n + N)) atTop (nhds a) at hshift + simpa only [v, Nat.add_comm] using hshift + simpa [v] using + edist_le_of_edist_le_geometric_two_of_tendsto₀ C hvstep hvlim + +/-- The pointwise limit of a pointwise-Cauchy sequence of additive characters. -/ +def pointwiseLimitCharacter + (f : ℕ → G →+ UnitAddCircle) + (hf : ∀ x, CauchySeq (fun n ↦ f n x)) : G →+ UnitAddCircle where + toFun x := limUnder atTop (fun n ↦ f n x) + map_zero' := by + apply tendsto_nhds_unique (hf 0).tendsto_limUnder + simp + map_add' x y := by + apply tendsto_nhds_unique (hf (x + y)).tendsto_limUnder + have hx := (hf x).tendsto_limUnder + have hy := (hf y).tendsto_limUnder + simpa only [map_add] using hx.add hy + +/-- The defining sequence converges pointwise to `pointwiseLimitCharacter`. -/ +theorem tendsto_pointwiseLimitCharacter + (f : ℕ → G →+ UnitAddCircle) + (hf : ∀ x, CauchySeq (fun n ↦ f n x)) (x : G) : + Tendsto (fun n ↦ f n x) atTop (nhds (pointwiseLimitCharacter f hf x)) := + (hf x).tendsto_limUnder + +end + +end Wallace diff --git a/LeanPool/Wallace/FusionSchedule.lean b/LeanPool/Wallace/FusionSchedule.lean new file mode 100644 index 000000000..240d77809 --- /dev/null +++ b/LeanPool/Wallace/FusionSchedule.lean @@ -0,0 +1,243 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import Mathlib.Analysis.SpecificLimits.Basic +import LeanPool.Wallace.FiniteCombinatorics +import LeanPool.Wallace.UniformKronecker + +/-! +# A concrete schedule for the Wallace fusion + +This file fixes, once and for all, the numerical parameters used by the character-fusion +construction. At stage `l`, `accumulatedSize l` is the total size allotted to all earlier +blocks, `protectedBound l` bounds the finite set whose character values must be protected, and +`blockSize l` is the size of the new block. The identity + +`blockSize l = (l + 2) * protectedBound l` + +makes the discarded proportion tend to zero. The errors form a geometric series of total mass +`1 / 32`, leaving a large margin around an initial character value of `1 / 2`. +-/ + +open Filter Topology + +namespace Wallace +namespace FusionSchedule + +noncomputable section + +open FiniteCombinatorics + +/-- Total number of positions allotted to blocks strictly before stage `l`. -/ +def accumulatedSize : ℕ → ℕ + | 0 => 0 + | l + 1 => + accumulatedSize l + (l + 2) * (accumulatedSize l + 2 * l + 2) + +/-- Cardinality bound for the protected set at stage `l`. -/ +def protectedBound (l : ℕ) : ℕ := + accumulatedSize l + 2 * l + 2 + +/-- Size of the fresh finite block at stage `l`. -/ +def blockSize (l : ℕ) : ℕ := + (l + 2) * protectedBound l + +@[simp] +theorem accumulatedSize_zero : accumulatedSize 0 = 0 := rfl + +@[simp] +theorem accumulatedSize_succ (l : ℕ) : + accumulatedSize (l + 1) = accumulatedSize l + blockSize l := by + rfl + +/-- `accumulatedSize` is exactly the sum of all preceding block sizes. -/ +theorem sum_blockSize (l : ℕ) : + ∑ i ∈ Finset.range l, blockSize i = accumulatedSize l := by + induction l with + | zero => simp + | succ l ih => + rw [Finset.sum_range_succ, ih, accumulatedSize_succ] + +theorem protectedBound_pos (l : ℕ) : 0 < protectedBound l := by + simp only [protectedBound] + omega + +theorem accumulatedSize_add_le_protectedBound (l : ℕ) : + accumulatedSize l + l + 2 ≤ protectedBound l := by + simp only [protectedBound] + omega + +theorem protectedBound_ne_zero (l : ℕ) : protectedBound l ≠ 0 := + Nat.ne_of_gt (protectedBound_pos l) + +theorem blockSize_pos (l : ℕ) : 0 < blockSize l := by + simp only [blockSize] + exact Nat.mul_pos (by omega) (protectedBound_pos l) + +theorem blockSize_ne_zero (l : ℕ) : blockSize l ≠ 0 := + Nat.ne_of_gt (blockSize_pos l) + +/-- The exact discarded-proportion identity behind the density-one argument. -/ +theorem protectedBound_div_blockSize (l : ℕ) : + (protectedBound l : ℝ) / (blockSize l : ℝ) = + 1 / ((l : ℝ) + 2) := by + rw [blockSize, Nat.cast_mul, Nat.cast_add, Nat.cast_ofNat] + field_simp [protectedBound_ne_zero l] + +/-- The proportion of a block which bounded deletion may discard tends to zero. -/ +theorem tendsto_protectedBound_div_blockSize : + Tendsto (fun l : ℕ ↦ (protectedBound l : ℝ) / (blockSize l : ℝ)) + atTop (nhds 0) := by + have hshift := (tendsto_one_div_add_atTop_nhds_zero_nat (𝕜 := ℝ)).comp + (tendsto_add_atTop_nat 1) + have hmain : Tendsto (fun l : ℕ ↦ 1 / ((l : ℝ) + 2)) atTop (nhds 0) := by + convert hshift using 1 + ext l + simp only [Function.comp_def, Nat.cast_add, Nat.cast_one] + ring + exact hmain.congr' (Eventually.of_forall fun l ↦ (protectedBound_div_blockSize l).symm) + +/-- Stage error. In elementary notation this is `2^(-(l+6))`. -/ +def stageError (l : ℕ) : ℝ := + (1 / 32 : ℝ) / 2 / 2 ^ l + +theorem stageError_pos (l : ℕ) : 0 < stageError l := by + simp only [stageError] + positivity + +theorem stageError_ne_zero (l : ℕ) : stageError l ≠ 0 := + ne_of_gt (stageError_pos l) + +/-- Exact geometric-tail identity, convenient for the completeness estimate. -/ +theorem stageError_add (L n : ℕ) : + stageError (L + n) = stageError L / 2 ^ n := by + simp only [stageError, pow_add] + ring + +/-- The tail beginning at stage `L` has total mass exactly `2 * stageError L`. -/ +theorem hasSum_stageError_add (L : ℕ) : + HasSum (fun n : ℕ ↦ stageError (L + n)) (2 * stageError L) := by + convert hasSum_geometric_two' (2 * stageError L) using 1 + ext n + rw [stageError_add] + ring + +theorem summable_stageError_add (L : ℕ) : + Summable (fun n : ℕ ↦ stageError (L + n)) := + (hasSum_stageError_add L).summable + +theorem tsum_stageError_add (L : ℕ) : + ∑' n : ℕ, stageError (L + n) = 2 * stageError L := + (hasSum_stageError_add L).tsum_eq + +theorem summable_stageError : Summable stageError := by + change Summable (fun n : ℕ ↦ (1 / 32 : ℝ) / 2 / 2 ^ n) + exact summable_geometric_two' (1 / 32 : ℝ) + +theorem tendsto_stageError : Tendsto stageError atTop (nhds 0) := + summable_stageError.tendsto_atTop_zero + +/-- The total perturbation budget of the entire fusion is `1/32`. -/ +theorem tsum_stageError : ∑' l : ℕ, stageError l = (1 / 32 : ℝ) := by + change (∑' n : ℕ, (1 / 32 : ℝ) / 2 / 2 ^ n) = 1 / 32 + exact tsum_geometric_two' (1 / 32 : ℝ) + +theorem tsum_stageError_pos : 0 < ∑' l : ℕ, stageError l := by + rw [tsum_stageError] + norm_num + +/-- Even twice the full error budget is far below the initial value `1/2`. -/ +theorem two_mul_tsum_stageError_lt_half : + 2 * (∑' l : ℕ, stageError l) < (1 / 2 : ℝ) := by + rw [tsum_stageError] + norm_num + +/-- The pointwise-limit estimate from the zeroth stage also preserves a nonzero half-turn. -/ +theorem two_mul_stageError_zero_lt_half : + 2 * stageError 0 < (1 / 2 : ℝ) := by + norm_num [stageError] + +/-- Independence threshold used before the bounded-deletion step. -/ +def independenceBound (l Q : ℕ) : ℕ := + deletionIndependenceBound (protectedBound l) Q + +/-! ## Uniform Kronecker and deletion bounds -/ + +/-- Maximum tuple length which can occur at stage `l`. -/ +def tupleLengthBound (l : ℕ) : ℕ := + protectedBound l + blockSize l + +/-- One uniform Kronecker bound for a fixed tuple length. All groups in the Wallace +construction live in universe zero, so fixing that universe here makes the numerical schedule +literally a single sequence of natural numbers. -/ +noncomputable def rawKroneckerBound (l m : ℕ) : ℕ := + Classical.choose (exists_uniformKroneckerBound.{0} m (stageError_pos l)) + +theorem rawKroneckerBound_spec (l m : ℕ) : + IsUniformKroneckerBound.{0} m (stageError l) (rawKroneckerBound l m) := + Classical.choose_spec (exists_uniformKroneckerBound.{0} m (stageError_pos l)) + +/-- A single relation-height bound which works for every *positive* tuple length possible at +stage `l`. This is the paper's maximum over `1 ≤ m ≤ R_l + N_l`; the maximum with `1` is used +by the finite disjointness argument. The empty-tuple case is handled separately below and does +not enter the numerical schedule. -/ +noncomputable def kroneckerBound (l : ℕ) : ℕ := + max 1 ((Finset.Icc 1 (tupleLengthBound l)).sup (rawKroneckerBound l)) + +theorem one_le_kroneckerBound (l : ℕ) : 1 ≤ kroneckerBound l := by + exact Nat.le_max_left _ _ + +theorem rawKroneckerBound_le (l m : ℕ) (hm0 : 0 < m) + (hm : m ≤ tupleLengthBound l) : + rawKroneckerBound l m ≤ kroneckerBound l := by + apply le_trans _ (Nat.le_max_right 1 _) + apply Finset.le_sup + exact Finset.mem_Icc.mpr ⟨hm0, hm⟩ + +/-- The uniform Kronecker assertion is vacuous for an empty tuple, so no value `q(0, ε_l)` is +needed in the paper's maximum. -/ +theorem kroneckerBound_spec_zero (l : ℕ) : + IsUniformKroneckerBound.{0} 0 (stageError l) (kroneckerBound l) := by + intro G _inst z t _ht + exact ⟨0, fun i ↦ Fin.elim0 i⟩ + +/-- The scheduled height bound is valid for every tuple that can occur at this stage. -/ +theorem kroneckerBound_spec (l m : ℕ) (hm : m ≤ tupleLengthBound l) : + IsUniformKroneckerBound.{0} m (stageError l) (kroneckerBound l) := + by + rcases m with _ | m + · exact kroneckerBound_spec_zero l + · exact IsUniformKroneckerBound.mono (rawKroneckerBound_spec l (m + 1)) + (rawKroneckerBound_le l (m + 1) (Nat.succ_pos m) hm) + +/-- The independence threshold `M_l` used in the preprocessing of stage `l`. -/ +noncomputable def stageIndependenceBound (l : ℕ) : ℕ := + independenceBound l (kroneckerBound l) + +theorem card_union_le_tupleLengthBound {G : Type*} [DecidableEq G] + {l : ℕ} {A Y : Finset G} + (hA : A.card ≤ protectedBound l) (hY : Y.card ≤ blockSize l) : + (A ∪ Y).card ≤ tupleLengthBound l := by + calc + (A ∪ Y).card ≤ A.card + Y.card := Finset.card_union_le A Y + _ ≤ protectedBound l + blockSize l := Nat.add_le_add hA hY + _ = tupleLengthBound l := rfl + +/-- The bounded-deletion lemma specialized to the numerical schedule. -/ +theorem exists_stage_deletion {G : Type*} [AddCommGroup G] [IsAddTorsionFree G] + [DecidableEq G] + {l : ℕ} (A X : Finset G) (hA : A.card ≤ protectedBound l) + (hX : BoundedIndependent (stageIndependenceBound l) X) : + ∃ Y : Finset G, Y ⊆ X ∧ (X \ Y).card ≤ A.card ∧ + MixedRelationFree (kroneckerBound l) A Y := by + classical + simpa only [stageIndependenceBound, independenceBound] using + bounded_deletion (protectedBound l) (kroneckerBound l) A X hA hX + +end + +end FusionSchedule +end Wallace diff --git a/LeanPool/Wallace/FusionStage.lean b/LeanPool/Wallace/FusionStage.lean new file mode 100644 index 000000000..bef9eac3a --- /dev/null +++ b/LeanPool/Wallace/FusionStage.lean @@ -0,0 +1,257 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.FiniteCombinatorics +import LeanPool.Wallace.UniformKronecker +import Mathlib.Data.Finset.Lattice.Basic + +/-! +# One finite character-fusion stage + +This module turns the bounded-deletion conclusion into the exact short-relation compatibility +required by the uniform Kronecker lemma. It is the finite algebraic heart of one fusion stage. +-/ + +open scoped BigOperators + +universe u + +namespace Wallace + +noncomputable section + +open FiniteCombinatorics + +variable {G : Type u} [AddCommGroup G] [DecidableEq G] + +/-- A short-relation-free old/new pair is disjoint as soon as the height bound contains `1`. -/ +theorem disjoint_of_mixedRelationFree {A Y : Finset G} {Q : ℕ} (hQ : 1 ≤ Q) + (hfree : MixedRelationFree Q A Y) : Disjoint A Y := by + classical + rw [Finset.disjoint_left] + intro x hxA hxY + apply hfree + let b : G → ℤ := fun z ↦ if z = x then 1 else 0 + let c : G → ℤ := fun z ↦ if z = x then -1 else 0 + refine ⟨b, c, ?_, ?_, ⟨x, hxA, by simp [b]⟩, ⟨x, hxY, by simp [c]⟩, ?_⟩ + · intro a _ha + by_cases hax : a = x <;> simp [b, hax, hQ] + · intro y _hy + by_cases hyx : y = x <;> simp [c, hyx, hQ] + · simp [b, c, hxA, hxY] + +section Coefficients + +variable (A Y : Finset G) + +private abbrev unionEquiv : Fin (A ∪ Y).card ≃ (A ∪ Y : Finset G) := + (A ∪ Y).equivFin.symm + +private def unionTuple : Fin (A ∪ Y).card → G := + fun i ↦ (unionEquiv A Y i : G) + +private def unionCoefficient (a : Fin (A ∪ Y).card → ℤ) (x : G) : ℤ := by + classical + exact if hx : x ∈ A ∪ Y then a ((unionEquiv A Y).symm ⟨x, hx⟩) else 0 + +omit [AddCommGroup G] in +private theorem unionCoefficient_of_mem + (a : Fin (A ∪ Y).card → ℤ) {x : G} (hx : x ∈ A ∪ Y) : + unionCoefficient A Y a x = a ((unionEquiv A Y).symm ⟨x, hx⟩) := by + classical + simp only [unionCoefficient, dif_pos hx] + +omit [AddCommGroup G] in +private theorem unionCoefficient_tuple + (a : Fin (A ∪ Y).card → ℤ) (i : Fin (A ∪ Y).card) : + unionCoefficient A Y a (unionTuple A Y i) = a i := by + classical + have hm : ((unionEquiv A Y i : (A ∪ Y : Finset G)) : G) ∈ A ∪ Y := + (unionEquiv A Y i).property + unfold unionTuple + rw [unionCoefficient_of_mem A Y a hm] + simp + +private theorem sum_unionCoefficient + (a : Fin (A ∪ Y).card → ℤ) : + ∑ i, a i • unionTuple A Y i = + ∑ x ∈ A ∪ Y, unionCoefficient A Y a x • x := by + classical + calc + ∑ i, a i • unionTuple A Y i = + ∑ i, unionCoefficient A Y a (unionTuple A Y i) • unionTuple A Y i := by + simp only [unionCoefficient_tuple] + _ = ∑ x : (A ∪ Y : Finset G), unionCoefficient A Y a x • (x : G) := by + exact (unionEquiv A Y).sum_comp + (fun x : (A ∪ Y : Finset G) ↦ unionCoefficient A Y a x • (x : G)) + _ = ∑ x ∈ A ∪ Y, unionCoefficient A Y a x • x := by + simpa only using Finset.sum_coe_sort (A ∪ Y) + (fun x ↦ unionCoefficient A Y a x • x) + +end Coefficients + +/-- The target which keeps the old character on `A` and is zero on the new set `Y`. -/ +private def stageTarget (A Y : Finset G) (old : G →+ UnitAddCircle) : + Fin (A ∪ Y).card → UnitAddCircle := by + classical + exact fun i ↦ if unionTuple A Y i ∈ A then old (unionTuple A Y i) else 0 + +/-- Reindexing the target sum over `A ∪ Y` leaves only the contribution from `A`. -/ +private theorem sum_stageTarget_eq_sum_old + (A Y : Finset G) (old : G →+ UnitAddCircle) (hdisj : Disjoint A Y) + (a : Fin (A ∪ Y).card → ℤ) : + ∑ i, a i • stageTarget A Y old i = + ∑ x ∈ A, unionCoefficient A Y a x • old x := by + classical + calc + ∑ i, a i • stageTarget A Y old i = + ∑ i, unionCoefficient A Y a (unionTuple A Y i) • + (if unionTuple A Y i ∈ A then old (unionTuple A Y i) else 0) := by + simp only [unionCoefficient_tuple, stageTarget] + _ = ∑ x : (A ∪ Y : Finset G), + unionCoefficient A Y a (x : G) • + (if (x : G) ∈ A then old (x : G) else 0) := by + exact (unionEquiv A Y).sum_comp + (fun x : (A ∪ Y : Finset G) ↦ + unionCoefficient A Y a (x : G) • + (if (x : G) ∈ A then old (x : G) else 0)) + _ = ∑ x ∈ A ∪ Y, unionCoefficient A Y a x • + (if x ∈ A then old x else 0) := by + simpa only using Finset.sum_coe_sort (A ∪ Y) + (fun x ↦ unionCoefficient A Y a x • + (if x ∈ A then old x else 0)) + _ = ∑ x ∈ A, unionCoefficient A Y a x • old x := by + rw [Finset.sum_union hdisj] + have hYA : ∀ y ∈ Y, y ∉ A := by + intro y hyY hyA + exact Finset.disjoint_left.mp hdisj hyA hyY + have hsumA : + (∑ x ∈ A, unionCoefficient A Y a x • + (if x ∈ A then old x else 0)) = + ∑ x ∈ A, unionCoefficient A Y a x • old x := by + apply Finset.sum_congr rfl + intro x hx + rw [if_pos hx] + have hsumY : + (∑ x ∈ Y, unionCoefficient A Y a x • + (if x ∈ A then old x else 0)) = 0 := by + apply Finset.sum_eq_zero + intro y hy + rw [if_neg (hYA y hy), smul_zero] + rw [hsumA, hsumY, add_zero] + +/-- Bounded deletion makes the finite fusion target compatible with every relation up to `Q`. -/ +theorem stageTarget_respectsRelationsUpTo + {A Y : Finset G} {Q : ℕ} (hQ : 1 ≤ Q) + (hfree : MixedRelationFree Q A Y) (old : G →+ UnitAddCircle) : + RespectsRelationsUpTo Q (unionTuple A Y) (stageTarget A Y old) := by + classical + have hdisj : Disjoint A Y := disjoint_of_mixedRelationFree hQ hfree + intro a haQ hrel + have hcoeffQ (x : G) (hx : x ∈ A ∪ Y) : + Int.natAbs (unionCoefficient A Y a x) ≤ Q := by + rw [unionCoefficient_of_mem A Y a hx] + exact (natAbs_le_intVectorHeight a _).trans haQ + have hsumUnion : + (∑ x ∈ A, unionCoefficient A Y a x • x) + + ∑ y ∈ Y, unionCoefficient A Y a y • y = 0 := by + rw [← Finset.sum_union hdisj] + rw [← sum_unionCoefficient A Y a] + exact hrel + by_cases hold : ∃ x ∈ A, unionCoefficient A Y a x ≠ 0 + · by_cases hnew : ∃ y ∈ Y, unionCoefficient A Y a y ≠ 0 + · exfalso + apply hfree + exact ⟨unionCoefficient A Y a, unionCoefficient A Y a, + fun x hx ↦ hcoeffQ x (Finset.mem_union_left Y hx), + fun y hy ↦ hcoeffQ y (Finset.mem_union_right A hy), hold, hnew, hsumUnion⟩ + · push Not at hnew + have hsumY : ∑ y ∈ Y, unionCoefficient A Y a y • y = 0 := by + apply Finset.sum_eq_zero + intro y hy + simp [hnew y hy] + have hsumA : ∑ x ∈ A, unionCoefficient A Y a x • x = 0 := by + simpa [hsumY] using hsumUnion + change ∑ i, a i • stageTarget A Y old i = 0 + calc + ∑ i, a i • stageTarget A Y old i = + old (∑ x ∈ A, unionCoefficient A Y a x • x) := by + rw [sum_stageTarget_eq_sum_old A Y old hdisj] + rw [map_sum] + simp_rw [map_zsmul] + _ = 0 := by rw [hsumA, map_zero] + · push Not at hold + change ∑ i, a i • stageTarget A Y old i = 0 + rw [sum_stageTarget_eq_sum_old A Y old hdisj] + apply Finset.sum_eq_zero + intro x hx + simp [hold x hx] + +/-- One application of uniform Kronecker performs a finite fusion stage. -/ +theorem exists_character_fusion_stage + {A Y : Finset G} {Q : ℕ} (hQ : 1 ≤ Q) + (hfree : MixedRelationFree Q A Y) (old : G →+ UnitAddCircle) + {eps : ℝ} (hbound : IsUniformKroneckerBound.{u} (A ∪ Y).card eps Q) : + ∃ next : G →+ UnitAddCircle, + (∀ x ∈ A, ‖next x - old x‖ < eps) ∧ + (∀ y ∈ Y, ‖next y‖ < eps) := by + classical + obtain ⟨next, hnext⟩ := hbound (unionTuple A Y) (stageTarget A Y old) + (stageTarget_respectsRelationsUpTo hQ hfree old) + refine ⟨next, ?_, ?_⟩ + · intro x hxA + have hxU : x ∈ A ∪ Y := Finset.mem_union_left Y hxA + let i : Fin (A ∪ Y).card := (unionEquiv A Y).symm ⟨x, hxU⟩ + have hzi : unionTuple A Y i = x := by simp [i, unionTuple, unionEquiv] + simpa [stageTarget, hzi, hxA] using hnext i + · intro y hyY + have hyU : y ∈ A ∪ Y := Finset.mem_union_right A hyY + let i : Fin (A ∪ Y).card := (unionEquiv A Y).symm ⟨y, hyU⟩ + have hzi : unionTuple A Y i = y := by simp [i, unionTuple, unionEquiv] + have hyA : y ∉ A := fun hyA ↦ Finset.disjoint_left.mp + (disjoint_of_mixedRelationFree hQ hfree) hyA hyY + simpa [stageTarget, hzi, hyA, norm_eq_zero] using hnext i + +/-- **One fusion step** (the complete form used in Section 4 of the paper). + +`Q` is a uniform Kronecker bound for every positive tuple length that can occur. Bounded +deletion first produces `Y`, including the no-mixed-relation certificate, and one application +of the uniform Kronecker lemma then produces the next homomorphism. The empty union is handled +directly, exactly as in the paper, so no artificial bound for zero-length tuples is required. -/ +theorem exists_one_fusion_step + [IsAddTorsionFree G] + (r Q : ℕ) (hQ : 1 ≤ Q) (A X : Finset G) (hAr : A.card ≤ r) + (hX : BoundedIndependent (deletionIndependenceBound r Q) X) + (old : G →+ UnitAddCircle) {eps : ℝ} + (hbound : ∀ m, 0 < m → m ≤ r + X.card → + IsUniformKroneckerBound.{u} m eps Q) : + ∃ (Y : Finset G) (next : G →+ UnitAddCircle), + Y ⊆ X ∧ + (X \ Y).card ≤ A.card ∧ + MixedRelationFree Q A Y ∧ + (∀ a ∈ A, ‖next a - old a‖ < eps) ∧ + (∀ y ∈ Y, ‖next y‖ < eps) := by + classical + obtain ⟨Y, hYX, hdeleted, hfree⟩ := bounded_deletion r Q A X hAr hX + by_cases hempty : A ∪ Y = ∅ + · have hA : A = ∅ := (Finset.union_eq_empty.mp hempty).1 + have hY : Y = ∅ := (Finset.union_eq_empty.mp hempty).2 + subst A + subst Y + exact ⟨∅, old, by simp, hdeleted, hfree, by simp, by simp⟩ + · have hcardPos : 0 < (A ∪ Y).card := + Finset.card_pos.mpr (Finset.nonempty_iff_ne_empty.mpr hempty) + have hcardLe : (A ∪ Y).card ≤ r + X.card := by + calc + (A ∪ Y).card ≤ A.card + Y.card := Finset.card_union_le A Y + _ ≤ r + X.card := Nat.add_le_add hAr (Finset.card_le_card hYX) + obtain ⟨next, hold, hnew⟩ := exists_character_fusion_stage + hQ hfree old (hbound (A ∪ Y).card hcardPos hcardLe) + exact ⟨Y, next, hYX, hdeleted, hfree, hold, hnew⟩ + +end + +end Wallace diff --git a/LeanPool/Wallace/GeneralMain.lean b/LeanPool/Wallace/GeneralMain.lean new file mode 100644 index 000000000..2c3425d2f --- /dev/null +++ b/LeanPool/Wallace/GeneralMain.lean @@ -0,0 +1,92 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.TorsionFreeCoordinate +import LeanPool.Wallace.RationalAssembly +import LeanPool.Wallace.PackageTransport + +/-! +# The main theorem for every torsion-free Abelian group of cardinality continuum + +This module closes the scope gap between the canonical rational construction and the exact main +theorem stated in the paper. The rational character package is pulled back along the +coordinatization embedding from Section 2. Its prescribed basis limits lie in the embedded +group by construction, so no new fusion or set-theoretic hypothesis is needed. +-/ + +open Cardinal + +namespace Wallace + +noncomputable section + +namespace RationalCoordinatization + +variable {G : Type} [AddCommGroup G] + +/-- Pull the fully constructed rational character package back to a coordinatized group. -/ +def fullCharacterPackage (K : RationalCoordinatization G) : FullCharacterPackage G := + RationalAssembly.fullCharacterPackage.pullback + K.embedding K.embedding_injective + (fun s ↦ K.basisPreimage + (RationalTriangularPreprocess.codeIndex + (RationalAssembly.fullCharacterPackage.embeddedCode + K.embedding K.embedding_injective s))) + (fun s ↦ by + simpa [RationalAssembly.fullCharacterPackage, + RationalTriangularPreprocess.codeBasisVector] using + K.embedding_basisPreimage + (RationalTriangularPreprocess.codeIndex + (RationalAssembly.fullCharacterPackage.embeddedCode + K.embedding K.embedding_injective s))) + +/-- Every group with the paper's rational coordinatization inherits the complete topology +conclusion from the unconditional rational construction. -/ +theorem hasMainGroupTopology (K : RationalCoordinatization G) : + HasMainGroupTopology G := + K.fullCharacterPackage.hasMainGroupTopology + +end RationalCoordinatization + +/-- **Formal counterpart of the paper's main theorem.** Every torsion-free Abelian group of +cardinality continuum admits a Hausdorff countably compact group topology in which every +convergent sequence is eventually constant. The formal conclusion additionally records a +compatible totally bounded uniform group structure. `Wallace.Audit` records the standard +classical Lean foundations used by the proof. -/ +theorem torsionFreeAbelianGroup_mainTheorem + (G : Type) [AddCommGroup G] [IsAddTorsionFree G] + (hcard : #G = 𝔠) : HasMainGroupTopology G := + (RationalCoordinatization.ofCardinalityContinuum hcard).hasMainGroupTopology + +/-- The exact paper-level projection of the main theorem, with only the properties printed in +the theorem statement and no additional uniform-space fields exposed. -/ +theorem torsionFreeAbelianGroup_mainTheorem_exact + (G : Type) [AddCommGroup G] [IsAddTorsionFree G] + (hcard : #G = 𝔠) : + ∃ topology : TopologicalSpace G, + @IsTopologicalAddGroup G topology _ ∧ + @T2Space G topology ∧ + @CountablyCompactSpace G topology ∧ + (∀ (s : ℕ → G) (x : G), + Filter.Tendsto s Filter.atTop (@nhds G topology x) → + ∀ᶠ n in Filter.atTop, s n = x) := by + obtain ⟨topology, _uniformity, _hcompat, _huniformGroup, + htopologicalGroup, hT2, hcompact, _htotallyBounded, hsequences⟩ := + torsionFreeAbelianGroup_mainTheorem G hcard + exact ⟨topology, htopologicalGroup, hT2, hcompact, hsequences⟩ + +/-- The Baer--Specker group has cardinality continuum. -/ +theorem mk_baerSpeckerGroup : #(ℕ → ℤ) = 𝔠 := by + rw [Cardinal.mk_arrow, Cardinal.mk_int, Cardinal.mk_nat] + simp + +/-- The Baer--Specker specialization highlighted in the abstract and introduction. -/ +theorem baerSpeckerGroup_mainTheorem : HasMainGroupTopology (ℕ → ℤ) := + torsionFreeAbelianGroup_mainTheorem (ℕ → ℤ) mk_baerSpeckerGroup + +end + +end Wallace diff --git a/LeanPool/Wallace/GlobalAssembly.lean b/LeanPool/Wallace/GlobalAssembly.lean new file mode 100644 index 000000000..77e7d6610 --- /dev/null +++ b/LeanPool/Wallace/GlobalAssembly.lean @@ -0,0 +1,110 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.ConcreteClosure +import LeanPool.Wallace.SeparationInterface + +/-! +# From the local fusions to the Wallace counterexample + +This module performs the final global assembly. Its only input is the output of the countable +fusion: for each nonzero vector, a character on its concrete countable dependency closure which +detects that vector and satisfies the prescribed ultrafilter limits for all codes internal to the +closure. The transfinite recursion extends each such character to the whole free group and +makes it admissible at every code. The resulting characters form a separating family, so the +minimal construction interface yields the Wallace semigroup. +-/ + +open Filter Set Topology + +namespace Wallace +namespace GlobalAssembly + +noncomputable section + +open TriangularPreprocess +open ConcreteData +open ConcreteClosure +open TransfiniteExtension + +variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) + +/-- The exact local output required from the countable fusion. -/ +def HasLocalSeparatingCharacters : Prop := + ∀ x : {x : ContinuumFreeGroup // x ≠ 0}, + ∃ χD : (closure N hN M x.1 →₀ ℤ) →+ UnitAddCircle, + χD (Finsupp.subtypeDomain (closure N hN M x.1) x.1) ≠ 0 ∧ + LocallyAdmissible (transfiniteData N hN M) (closure N hN M x.1) χD + +variable (H : HasLocalSeparatingCharacters N hN M) + +/-- The chosen local character for a nonzero vector. -/ +def localCharacter (x : {x : ContinuumFreeGroup // x ≠ 0}) : + (closure N hN M x.1 →₀ ℤ) →+ UnitAddCircle := + Classical.choose (H x) + +theorem localCharacter_self_ne_zero (x : {x : ContinuumFreeGroup // x ≠ 0}) : + localCharacter N hN M H x + (Finsupp.subtypeDomain (closure N hN M x.1) x.1) ≠ 0 := + (Classical.choose_spec (H x)).1 + +theorem localCharacter_admissible (x : {x : ContinuumFreeGroup // x ≠ 0}) : + LocallyAdmissible (transfiniteData N hN M) (closure N hN M x.1) + (localCharacter N hN M H x) := + (Classical.choose_spec (H x)).2 + +/-- Extend the chosen local character by the well-founded triangular recursion. -/ +def globalCharacter (x : {x : ContinuumFreeGroup // x ≠ 0}) : + ContinuumFreeGroup →+ UnitAddCircle := + TransfiniteExtension.globalCharacter (transfiniteData N hN M) + (closure N hN M x.1) (localCharacter N hN M H x) + +theorem globalCharacter_self_ne_zero (x : {x : ContinuumFreeGroup // x ≠ 0}) : + globalCharacter N hN M H x x.1 ≠ 0 := by + rw [globalCharacter, + TransfiniteExtension.globalCharacter_eq_local_restriction] + · exact localCharacter_self_ne_zero N hN M H x + · exact support_subset_closure N hN M x.1 + +theorem globalCharacter_admissible (x : {x : ContinuumFreeGroup // x ≠ 0}) + (a : ContinuumIndex) : + Tendsto + (fun n ↦ globalCharacter N hN M H x (prepared N hN M a n)) + (ultrafilter N hN a) + (nhds (globalCharacter N hN M H x (codeBasisVector a))) := by + exact TransfiniteExtension.globalCharacter_admissible + (transfiniteData N hN M) (closure N hN M x.1) + (localCharacter N hN M H x) + (closure_closedUnderPreparedSupports N hN M x.1) + (localCharacter_admissible N hN M H x) a + +/-- The completely concrete separating package obtained from the local fusion theorem. -/ +def separationPackage : SeparationPackage ContinuumIndex where + Code := ContinuumIndex + codeEquiv := sequenceCodeEquiv + codeIndex := codeIndex + subsequence := selector N hN M + subsequence_strictMono := selector_strictMono N hN M + ultrafilter := ultrafilter N hN + ultrafilter_free := ultrafilter_free N hN + character := globalCharacter N hN M H + character_self_ne_zero := globalCharacter_self_ne_zero N hN M H + character_limit := by + intro a x + exact globalCharacter_admissible N hN M H x a + +/-- Once the local fusion has been proved for the concrete schedule, the existential Wallace +counterexample follows without any additional topological or set-theoretic assumption. -/ +theorem wallaceCounterexampleExists_of_local + (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) + (H : HasLocalSeparatingCharacters N hN M) : WallaceCounterexampleExists := by + letI : Infinite ContinuumIndex := continuumIndex_infinite + exact (separationPackage N hN M H).wallaceCounterexampleExists + +end + +end GlobalAssembly +end Wallace diff --git a/LeanPool/Wallace/InitialCharacter.lean b/LeanPool/Wallace/InitialCharacter.lean new file mode 100644 index 000000000..02d9c7dcb --- /dev/null +++ b/LeanPool/Wallace/InitialCharacter.lean @@ -0,0 +1,53 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.UniformKronecker + +/-! +# A character with a prescribed half-turn value + +The local fusion starts from a character taking a chosen nonzero element to the half-turn of the +circle. Torsion-freeness makes this one-point prescription compatible with every integer +relation, and divisibility of the circle extends it to the ambient group. +-/ + +namespace Wallace + +noncomputable section + +universe u + +/-- Every nonzero element of a torsion-free Abelian group can be sent exactly to `1/2` in the +unit additive circle. -/ +theorem exists_character_apply_eq_half + {G : Type u} [AddCommGroup G] [IsAddTorsionFree G] + {x : G} (hx : x ≠ 0) : + ∃ χ : G →+ UnitAddCircle, χ x = ((1 / 2 : ℝ) : UnitAddCircle) := by + let z : Fin 1 → G := fun _ ↦ x + let t : Fin 1 → UnitAddCircle := fun _ ↦ ((1 / 2 : ℝ) : UnitAddCircle) + have hrel : RespectsRelations z t := by + rw [respectsRelations_iff] + intro a ha + have ha0 : a 0 = 0 := by + have : a 0 • x = 0 := by simpa [z] using ha + exact (IsAddTorsionFree.zsmul_eq_zero_iff_left hx).mp this + simp [t, ha0] + obtain ⟨χ, hχ⟩ := exists_character_of_respectsRelations z t hrel + exact ⟨χ, by simpa [z, t] using hχ 0⟩ + +/-- The half-turn is nonzero. -/ +theorem half_ne_zero : (((1 / 2 : ℝ) : UnitAddCircle)) ≠ 0 := by + intro hzero + rw [AddCircle.coe_eq_zero_iff] at hzero + obtain ⟨n, hn⟩ := hzero + have hnR : (n : ℝ) = 1 / 2 := by simpa using hn + have hn' : (2 : ℝ) * (n : ℝ) = 1 := by linarith + have hnInt : (2 : ℤ) * n = 1 := by exact_mod_cast hn' + omega + +end + +end Wallace diff --git a/LeanPool/Wallace/LocalEnumeration.lean b/LeanPool/Wallace/LocalEnumeration.lean new file mode 100644 index 000000000..6fac0e508 --- /dev/null +++ b/LeanPool/Wallace/LocalEnumeration.lean @@ -0,0 +1,42 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.ConcreteClosure + +/-! +# Enumeration of a countable local free group +-/ + +namespace Wallace +namespace ConcreteClosure + +noncomputable section + +open TriangularPreprocess + +variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) + +/-- The free Abelian group on a countable coordinate closure is countable. -/ +theorem localFreeGroup_countable (x : ContinuumFreeGroup) : + Countable (closure N hN M x →₀ ℤ) := by + letI : Countable (closure N hN M x) := (closure_countable N hN M x).to_subtype + infer_instance + +/-- A fixed surjective enumeration of every local free group. -/ +def groupEnumeration (x : ContinuumFreeGroup) : + ℕ → (closure N hN M x →₀ ℤ) := by + letI : Countable (closure N hN M x) := (closure_countable N hN M x).to_subtype + exact Classical.choose (exists_surjective_nat (closure N hN M x →₀ ℤ)) + +theorem groupEnumeration_surjective (x : ContinuumFreeGroup) : + Function.Surjective (groupEnumeration N hN M x) := by + letI : Countable (closure N hN M x) := (closure_countable N hN M x).to_subtype + exact Classical.choose_spec (exists_surjective_nat (closure N hN M x →₀ ℤ)) + +end + +end ConcreteClosure +end Wallace diff --git a/LeanPool/Wallace/LocalFusion.lean b/LeanPool/Wallace/LocalFusion.lean new file mode 100644 index 000000000..2a544f14f --- /dev/null +++ b/LeanPool/Wallace/LocalFusion.lean @@ -0,0 +1,665 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.ConcreteLocalSetup +import LeanPool.Wallace.BlockLimit +import LeanPool.Wallace.GlobalAssembly +import LeanPool.Wallace.FusionSchedule +import LeanPool.Wallace.FusionStage +import LeanPool.Wallace.FusionLimit +import LeanPool.Wallace.InitialCharacter +import Mathlib.Data.Finset.Lattice.Basic +import Mathlib.Data.Finset.SDiff + +/-! +# A local character-fusion core + +This file packages the analytic part of the countable fusion separately from the finite stage +constructor. A `FusionRun` records exactly the output of successive applications of bounded +deletion and `exists_character_fusion_stage`: characters, protected finite sets, and retained +new sets. From these *proved finite-stage certificates* we construct the pointwise limit +character and derive: + +* extension/detection of the distinguished element; +* estimates on every retained block; +* local ultrafilter admissibility. + +The second half of the file carries out the scheduling induction for the concrete Wallace data. +-/ + +open Filter Set Topology + +namespace Wallace +namespace LocalFusion + +noncomputable section + +universe u + +open FiniteCombinatorics + +/-! ## The bounded-deletion input to one stage -/ + +/-- A retained finite subset of `X` supplied by the bounded-deletion theorem. -/ +structure DeletionStage {G : Type u} [AddCommGroup G] [DecidableEq G] + (A X : Finset G) (Q : ℕ) where + retained : Finset G + retained_subset : retained ⊆ X + deleted_card_le : (X \ retained).card ≤ A.card + mixedRelationFree : MixedRelationFree Q A retained + +/-- The existing bounded-deletion theorem produces a complete stage certificate. -/ +theorem exists_deletionStage {G : Type u} [AddCommGroup G] [IsAddTorsionFree G] + [DecidableEq G] + (r Q : ℕ) (A X : Finset G) (hAr : A.card ≤ r) + (hX : BoundedIndependent (deletionIndependenceBound r Q) X) : + Nonempty (DeletionStage A X Q) := by + classical + obtain ⟨Y, hYX, hcard, hfree⟩ := bounded_deletion r Q A X hAr hX + exact ⟨⟨Y, hYX, hcard, hfree⟩⟩ + +/-- A scheduled bounded-deletion and finite-fusion stage. -/ +theorem exists_character_after_deletion + {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] + (l : ℕ) (A X : Finset G) + (hA : A.card ≤ FusionSchedule.protectedBound l) + (hXcard : X.card ≤ FusionSchedule.blockSize l) + (hX : BoundedIndependent (FusionSchedule.stageIndependenceBound l) X) + (old : G →+ UnitAddCircle) : + ∃ (Y : Finset G) (next : G →+ UnitAddCircle), + Y ⊆ X ∧ (X \ Y).card ≤ A.card ∧ + (∀ a ∈ A, ‖next a - old a‖ < FusionSchedule.stageError l) ∧ + (∀ y ∈ Y, ‖next y‖ < FusionSchedule.stageError l) := by + classical + obtain ⟨Y, hYX, hcard, hfree⟩ := FusionSchedule.exists_stage_deletion A X hA hX + have hYcard : Y.card ≤ FusionSchedule.blockSize l := by + exact (Finset.card_le_card hYX).trans hXcard + have htuple := FusionSchedule.card_union_le_tupleLengthBound hA hYcard + obtain ⟨next, hold, hzero⟩ := exists_character_fusion_stage + (FusionSchedule.one_le_kroneckerBound l) hfree old + (FusionSchedule.kroneckerBound_spec l (A ∪ Y).card htuple) + exact ⟨Y, next, hYX, hcard, hold, hzero⟩ + +/-! ## Certified countable runs and their pointwise limits -/ + +/-- Data produced by the local fusion induction. Every field is a checkable mathematical +certificate: there is no assertion that an arbitrary run exists. The finite scheduling +induction and the uniform Kronecker theorem populate these fields directly. -/ +structure FusionRun (G : Type u) [AddCommGroup G] where + /-- The character after stage `l`. -/ + character : ℕ → G →+ UnitAddCircle + /-- The finite set protected while passing from stage `l` to `l+1`. -/ + guardSet : ℕ → Finset G + /-- New points retained after bounded deletion at stage `l`. -/ + retained : ℕ → Finset G + /-- Every element is protected at all sufficiently late stages. -/ + eventually_protected : ∀ g : G, ∀ᶠ l in atTop, g ∈ guardSet l + /-- Consecutive characters are close on protected points. -/ + protected_step : ∀ l g, g ∈ guardSet l → + dist (character l g) (character (l + 1) g) ≤ FusionSchedule.stageError l + /-- A retained point is nearly annihilated when it is introduced. -/ + retained_at_stage : ∀ l g, g ∈ retained l → + ‖character (l + 1) g‖ ≤ FusionSchedule.stageError l + /-- Once introduced, retained points are protected forever. -/ + retained_protected : ∀ l g, g ∈ retained l → + ∀ k, l + 1 ≤ k → g ∈ guardSet k + +namespace FusionRun + +variable {G : Type u} [AddCommGroup G] + +/-- A pointwise tail of a certified fusion has the geometric step estimate. -/ +theorem tail_step_le (R : FusionRun G) (g : G) : + ∃ L : ℕ, ∀ n : ℕ, + dist (R.character (L + n) g) (R.character (L + n + 1) g) ≤ + FusionSchedule.stageError (L + n) := by + obtain ⟨L, hL⟩ := eventually_atTop.1 (R.eventually_protected g) + refine ⟨L, fun n ↦ ?_⟩ + have hmem : g ∈ R.guardSet (L + n) := hL _ (Nat.le_add_right L n) + simpa only [Nat.add_assoc] using R.protected_step (L + n) g hmem + +/-- Every coordinate of a certified fusion is Cauchy. -/ +theorem cauchySeq (R : FusionRun G) (g : G) : + CauchySeq (fun l ↦ R.character l g) := by + obtain ⟨L, hstep⟩ := R.tail_step_le g + rw [← cauchySeq_shift L] + have hcauchy : CauchySeq (fun n ↦ R.character (L + n) g) := + cauchySeq_of_dist_le_of_summable + (fun n ↦ FusionSchedule.stageError (L + n)) hstep + (FusionSchedule.summable_stageError_add L) + simpa only [Nat.add_comm] using hcauchy + +/-- The local character obtained as the pointwise limit of a certified run. -/ +def limitCharacter (R : FusionRun G) : G →+ UnitAddCircle := + pointwiseLimitCharacter R.character R.cauchySeq + +theorem tendsto_limitCharacter (R : FusionRun G) (g : G) : + Tendsto (fun l ↦ R.character l g) atTop (nhds (R.limitCharacter g)) := + tendsto_pointwiseLimitCharacter R.character R.cauchySeq g + +/-- The final value of a retained point is bounded by twice the stage error: one stage error +when the point is introduced, plus the subsequent geometric tail. -/ +theorem norm_limitCharacter_le_of_mem_retained (R : FusionRun G) + (l : ℕ) {g : G} (hg : g ∈ R.retained l) : + ‖R.limitCharacter g‖ ≤ 2 * FusionSchedule.stageError l := by + have htail : ∀ n : ℕ, + dist (R.character (l + 1 + n) g) (R.character (l + 1 + n + 1) g) ≤ + FusionSchedule.stageError (l + 1 + n) := by + intro n + apply R.protected_step + apply R.retained_protected l g hg + omega + have hconv : Tendsto (fun n ↦ R.character (l + 1 + n) g) atTop + (nhds (R.limitCharacter g)) := by + have hshift := + (R.tendsto_limitCharacter g).comp (tendsto_add_atTop_nat (l + 1)) + change Tendsto (fun n ↦ R.character (n + (l + 1)) g) atTop + (nhds (R.limitCharacter g)) at hshift + simpa only [Nat.add_comm] using hshift + have hdist : dist (R.character (l + 1) g) (R.limitCharacter g) ≤ + 2 * FusionSchedule.stageError (l + 1) := by + have := dist_le_tsum_of_dist_le_of_tendsto₀ + (fun n ↦ FusionSchedule.stageError (l + 1 + n)) htail + (FusionSchedule.summable_stageError_add (l + 1)) hconv + simpa only [FusionSchedule.tsum_stageError_add] using this + calc + ‖R.limitCharacter g‖ ≤ + ‖R.character (l + 1) g‖ + + dist (R.character (l + 1) g) (R.limitCharacter g) := by + simpa [dist_eq_norm, norm_sub_rev] using + norm_add_le (R.character (l + 1) g) + (R.limitCharacter g - R.character (l + 1) g) + _ ≤ FusionSchedule.stageError l + + 2 * FusionSchedule.stageError (l + 1) := + add_le_add (R.retained_at_stage l g hg) hdist + _ = 2 * FusionSchedule.stageError l := by + have herr : FusionSchedule.stageError (l + 1) = + FusionSchedule.stageError l / 2 := by + simpa using FusionSchedule.stageError_add l 1 + rw [herr] + ring + +/-! ## Initial detection -/ + +/-- If a distinguished point is protected at every stage and has prescribed initial value, its +limit remains close to that value. -/ +theorem dist_limitCharacter_le_initial (R : FusionRun G) (x : G) + (hprotect : ∀ l, x ∈ R.guardSet l) : + dist (R.character 0 x) (R.limitCharacter x) ≤ + ∑' l, FusionSchedule.stageError l := by + have h := dist_le_tsum_of_dist_le_of_tendsto + FusionSchedule.stageError (fun l ↦ R.protected_step l x (hprotect l)) + FusionSchedule.summable_stageError (R.tendsto_limitCharacter x) 0 + simpa only [zero_add] using h + +/-- Starting at the half-period and protecting `x` throughout makes the limiting character +nonzero. -/ +theorem limitCharacter_ne_zero_of_initial_half (R : FusionRun G) {x : G} + (hhalf : R.character 0 x = ((1 / 2 : ℝ) : UnitAddCircle)) + (hprotect : ∀ l, x ∈ R.guardSet l) : + R.limitCharacter x ≠ 0 := by + intro hzero + have hdist := R.dist_limitCharacter_le_initial x hprotect + rw [hhalf, hzero, dist_zero_right, AddCircle.norm_half_period_eq, + FusionSchedule.tsum_stageError] at hdist + norm_num at hdist + +/-! ## Retained blocks imply local ultrafilter admissibility -/ + +/-- Abstract block data associated with one relevant code in the local closure. -/ +structure CodeBlocks (R : FusionRun G) where + p : Ultrafilter ℕ + block : ℕ → Finset ℕ + labels : Set ℕ + deletions : ℕ → Finset ℕ + difference : ℕ → G + retained_mem : (⋃ l ∈ labels, ↑(block l \ deletions l)) ∈ p + retained_in_stage : ∀ l n, l ∈ labels → n ∈ block l \ deletions l → + difference n ∈ R.retained l + +/-- On every retained index, the norm of the limiting character is controlled by twice the +stage error of the unique block containing that index. -/ +theorem norm_limit_difference_le_on_retained (R : FusionRun G) (B : CodeBlocks R) + {n : ℕ} (hn : n ∈ ⋃ l ∈ B.labels, ↑(B.block l \ B.deletions l)) : + ∃ l ∈ B.labels, n ∈ B.block l \ B.deletions l ∧ + ‖R.limitCharacter (B.difference n)‖ ≤ + 2 * FusionSchedule.stageError l := by + simp only [Set.mem_iUnion] at hn + obtain ⟨l, hl⟩ := hn + obtain ⟨hlab, hnblock⟩ := hl + refine ⟨l, hlab, hnblock, ?_⟩ + exact R.norm_limitCharacter_le_of_mem_retained + l (B.retained_in_stage l n hlab hnblock) + +/-- If retained indices determine block labels tending to infinity, the limiting character of +the difference sequence tends to zero along the fixed ultrafilter. -/ +theorem tendsto_limit_difference_zero (R : FusionRun G) (B : CodeBlocks R) + (blockOf : ℕ → ℕ) + (hblockOf : ∀ l n, n ∈ B.block l → blockOf n = l) + (hblockTendsto : Tendsto blockOf B.p atTop) : + Tendsto (fun n ↦ R.limitCharacter (B.difference n)) B.p (nhds 0) := by + rw [Metric.tendsto_nhds] + intro ε hε + have herr : Tendsto (fun l ↦ 2 * FusionSchedule.stageError l) atTop (nhds 0) := by + simpa using FusionSchedule.tendsto_stageError.const_mul 2 + have hevent : ∀ᶠ l in atTop, 2 * FusionSchedule.stageError l < ε := + (Metric.tendsto_nhds.mp herr ε hε).mono fun l hl ↦ by + simpa [abs_of_pos (FusionSchedule.stageError_pos l)] using hl + have heventP : ∀ᶠ n in B.p, 2 * FusionSchedule.stageError (blockOf n) < ε := + hblockTendsto hevent + filter_upwards [B.retained_mem, heventP] with n hnret hnerr + obtain ⟨l, _hlab, hnblock, hnorm⟩ := + R.norm_limit_difference_le_on_retained B hnret + have hlabel : blockOf n = l := hblockOf l n (Finset.mem_sdiff.mp hnblock).1 + rw [dist_zero_right] + exact hnorm.trans_lt (by simpa [hlabel] using hnerr) + +/-- Concrete block-position version of `tendsto_limit_difference_zero`. Here freeness of the +ultrafilter and the partition theorem for `blockPositions` supply the required divergence of +block labels automatically. -/ +theorem tendsto_limit_difference_zero_of_blockPositions (R : FusionRun G) + (B : CodeBlocks R) (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) + (hp : (B.p : Filter ℕ) ≤ cofinite) + (hblock : ∀ l, B.block l = TriangularPreprocess.blockPositions N hN l) : + Tendsto (fun n ↦ R.limitCharacter (B.difference n)) B.p (nhds 0) := by + apply tendsto_zero_of_norm_le_stageError_on_mem N hN hp B.retained_mem + intro n hn + obtain ⟨l, _hlab, hnblock, hnorm⟩ := + R.norm_limit_difference_le_on_retained B hn + have hnposition : n ∈ TriangularPreprocess.blockPositions N hN l := by + simpa only [← hblock l] using (Finset.mem_sdiff.mp hnblock).1 + have hlabel : TriangularPreprocess.blockOf N hN n = l := + (TriangularPreprocess.mem_blockPositions_iff N hN).mp hnposition + simpa only [hlabel] using hnorm + +/-- Additivity turns convergence of the differences into the required local admissibility +equation. -/ +theorem tendsto_limit_prepared (R : FusionRun G) (B : CodeBlocks R) + (prepared : ℕ → G) (basis : G) + (hdifference : ∀ n, B.difference n = prepared n - basis) + (hzero : Tendsto (fun n ↦ R.limitCharacter (B.difference n)) B.p (nhds 0)) : + Tendsto (fun n ↦ R.limitCharacter (prepared n)) B.p + (nhds (R.limitCharacter basis)) := by + have heq : ∀ n, R.limitCharacter (prepared n) = + R.limitCharacter (B.difference n) + R.limitCharacter basis := by + intro n + have hgroup : prepared n = B.difference n + basis := by + rw [hdifference] + abel + rw [hgroup, map_add] + have hadd : Tendsto + (fun n ↦ R.limitCharacter (B.difference n) + R.limitCharacter basis) B.p + (nhds (R.limitCharacter basis)) := by + simpa using hzero.add_const (R.limitCharacter basis) + exact hadd.congr' (Eventually.of_forall fun n ↦ (heq n).symm) + +end FusionRun + +/-! ## A generic concrete scheduling recursion -/ + +/-- The finite state before stage `l`: its character and the union of every set retained at +earlier stages. The cardinality invariant is the exact invariant used by `protectedBound`. -/ +structure FusionState (G : Type) [AddCommGroup G] (l : ℕ) where + character : G →+ UnitAddCircle + pastRetained : Finset G + pastRetained_card_le : pastRetained.card ≤ FusionSchedule.accumulatedSize l + +/-- The stage guard contains the distinguished point, an initial segment of a surjective +enumeration, and every point retained before the stage. -/ +def stageGuard {G : Type} [AddCommGroup G] [DecidableEq G] + (enumeration : ℕ → G) (x : G) (l : ℕ) (S : FusionState G l) : Finset G := + S.pastRetained ∪ {x} ∪ (Finset.range (l + 1)).image enumeration + +theorem stageGuard_card_le {G : Type} [AddCommGroup G] [DecidableEq G] + (enumeration : ℕ → G) (x : G) (l : ℕ) (S : FusionState G l) : + (stageGuard enumeration x l S).card ≤ FusionSchedule.protectedBound l := by + calc + (stageGuard enumeration x l S).card ≤ + (S.pastRetained ∪ {x}).card + + ((Finset.range (l + 1)).image enumeration).card := + Finset.card_union_le _ _ + _ ≤ (S.pastRetained.card + 1) + (l + 1) := by + apply Nat.add_le_add + · exact (Finset.card_union_le S.pastRetained {x}).trans_eq (by simp) + · exact (Finset.card_image_le.trans_eq (Finset.card_range (l + 1))) + _ = S.pastRetained.card + l + 2 := by omega + _ ≤ FusionSchedule.accumulatedSize l + l + 2 := by + exact Nat.add_le_add_right + (Nat.add_le_add_right S.pastRetained_card_le l) 2 + _ ≤ FusionSchedule.protectedBound l := + FusionSchedule.accumulatedSize_add_le_protectedBound l + +/-- All data selected at one fusion stage. -/ +structure FusionStep {G : Type} [AddCommGroup G] [DecidableEq G] + (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) + (l : ℕ) (S : FusionState G l) where + retained : Finset G + next : G →+ UnitAddCircle + retained_subset : retained ⊆ fresh l + deleted_card_le : (fresh l \ retained).card ≤ (stageGuard enumeration x l S).card + protected_closeness : ∀ g ∈ stageGuard enumeration x l S, + dist (S.character g) (next g) ≤ FusionSchedule.stageError l + retained_small : ∀ g ∈ retained, ‖next g‖ ≤ FusionSchedule.stageError l + +/-- The finite deletion/fusion theorem supplies the next state at every stage. -/ +theorem fusionStep_nonempty + {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] + (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) + (hfresh_card : ∀ l, (fresh l).card ≤ FusionSchedule.blockSize l) + (hfresh_independent : ∀ l, + BoundedIndependent (FusionSchedule.stageIndependenceBound l) (fresh l)) + (l : ℕ) (S : FusionState G l) : + Nonempty (FusionStep fresh enumeration x l S) := by + classical + obtain ⟨Y, next, hsubset, hdeleted, hprotected, hsmall⟩ := + exists_character_after_deletion l (stageGuard enumeration x l S) (fresh l) + (stageGuard_card_le enumeration x l S) (hfresh_card l) + (hfresh_independent l) S.character + exact ⟨⟨Y, next, hsubset, hdeleted, + fun g hg ↦ by + simpa [dist_eq_norm, norm_sub_rev] using le_of_lt (hprotected g hg), + fun g hg ↦ le_of_lt (hsmall g hg)⟩⟩ + +/-- A stage choice, fixed once and reused by both the state recursion and its certificate. -/ +def chosenFusionStep + {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] + (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) + (hfresh_card : ∀ l, (fresh l).card ≤ FusionSchedule.blockSize l) + (hfresh_independent : ∀ l, + BoundedIndependent (FusionSchedule.stageIndependenceBound l) (fresh l)) + (l : ℕ) (S : FusionState G l) : FusionStep fresh enumeration x l S := + Classical.choice + (fusionStep_nonempty fresh enumeration x hfresh_card hfresh_independent l S) + +/-- Update the state using the single chosen stage certificate. -/ +def nextFusionState + {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] + (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) + (hfresh_card : ∀ l, (fresh l).card ≤ FusionSchedule.blockSize l) + (hfresh_independent : ∀ l, + BoundedIndependent (FusionSchedule.stageIndependenceBound l) (fresh l)) + (l : ℕ) (S : FusionState G l) : FusionState G (l + 1) where + character := + (chosenFusionStep fresh enumeration x hfresh_card hfresh_independent l S).next + pastRetained := S.pastRetained ∪ + (chosenFusionStep fresh enumeration x hfresh_card hfresh_independent l S).retained + pastRetained_card_le := by + calc + (S.pastRetained ∪ + (chosenFusionStep fresh enumeration x hfresh_card hfresh_independent l S).retained).card + ≤ S.pastRetained.card + + (chosenFusionStep fresh enumeration x hfresh_card hfresh_independent l S).retained.card := + Finset.card_union_le _ _ + _ ≤ FusionSchedule.accumulatedSize l + FusionSchedule.blockSize l := by + apply Nat.add_le_add S.pastRetained_card_le + exact (Finset.card_le_card + (chosenFusionStep fresh enumeration x hfresh_card hfresh_independent l S).retained_subset).trans + (hfresh_card l) + _ = FusionSchedule.accumulatedSize (l + 1) := + (FusionSchedule.accumulatedSize_succ l).symm + +/-- The dependent natural-number recursion starting from `initial`. -/ +def fusionStates + {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] + (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) + (hfresh_card : ∀ l, (fresh l).card ≤ FusionSchedule.blockSize l) + (hfresh_independent : ∀ l, + BoundedIndependent (FusionSchedule.stageIndependenceBound l) (fresh l)) + (initial : G →+ UnitAddCircle) : (l : ℕ) → FusionState G l + | 0 => ⟨initial, ∅, by simp⟩ + | l + 1 => nextFusionState fresh enumeration x hfresh_card hfresh_independent l + (fusionStates fresh enumeration x hfresh_card hfresh_independent initial l) + +@[simp] theorem fusionStates_zero + {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] + (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) + (hfresh_card : ∀ l, (fresh l).card ≤ FusionSchedule.blockSize l) + (hfresh_independent : ∀ l, + BoundedIndependent (FusionSchedule.stageIndependenceBound l) (fresh l)) + (initial : G →+ UnitAddCircle) : + (fusionStates fresh enumeration x hfresh_card hfresh_independent initial 0).character = + initial := rfl + +@[simp] theorem fusionStates_succ + {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] + (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) + (hfresh_card : ∀ l, (fresh l).card ≤ FusionSchedule.blockSize l) + (hfresh_independent : ∀ l, + BoundedIndependent (FusionSchedule.stageIndependenceBound l) (fresh l)) + (initial : G →+ UnitAddCircle) (l : ℕ) : + fusionStates fresh enumeration x hfresh_card hfresh_independent initial (l + 1) = + nextFusionState fresh enumeration x hfresh_card hfresh_independent l + (fusionStates fresh enumeration x hfresh_card hfresh_independent initial l) := rfl + +/- The rest of the construction uses shorter local names. -/ +section ScheduledConstruction + +variable {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] +variable (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) +variable (hfresh_card : ∀ l, (fresh l).card ≤ FusionSchedule.blockSize l) +variable (hfresh_independent : ∀ l, + BoundedIndependent (FusionSchedule.stageIndependenceBound l) (fresh l)) +variable (initial : G →+ UnitAddCircle) + +private abbrev states (l : ℕ) : FusionState G l := + fusionStates fresh enumeration x hfresh_card hfresh_independent initial l + +private abbrev step (l : ℕ) : FusionStep fresh enumeration x l (states fresh enumeration x + hfresh_card hfresh_independent initial l) := + chosenFusionStep fresh enumeration x hfresh_card hfresh_independent l + (states fresh enumeration x hfresh_card hfresh_independent initial l) + +theorem fusionStates_pastRetained_subset_succ (l : ℕ) : + (states fresh enumeration x hfresh_card hfresh_independent initial l).pastRetained ⊆ + (states fresh enumeration x hfresh_card hfresh_independent initial (l + 1)).pastRetained := by + intro g hg + change g ∈ (nextFusionState fresh enumeration x hfresh_card hfresh_independent l + (states fresh enumeration x hfresh_card hfresh_independent initial l)).pastRetained + exact Finset.mem_union_left _ hg + +theorem fusionStates_pastRetained_mono : Monotone fun l ↦ + (states fresh enumeration x hfresh_card hfresh_independent initial l).pastRetained := + monotone_nat_of_le_succ + (fusionStates_pastRetained_subset_succ fresh enumeration x hfresh_card + hfresh_independent initial) + +/-- The fully scheduled run associated with a chosen initial character. -/ +def scheduledRun (henumeration : Function.Surjective enumeration) : FusionRun G where + character := fun l ↦ (states fresh enumeration x hfresh_card hfresh_independent initial l).character + guardSet := fun l ↦ stageGuard enumeration x l + (states fresh enumeration x hfresh_card hfresh_independent initial l) + retained := fun l ↦ (step fresh enumeration x hfresh_card hfresh_independent initial l).retained + eventually_protected := by + intro g + obtain ⟨n, rfl⟩ := henumeration g + rw [eventually_atTop] + refine ⟨n, fun l hl ↦ ?_⟩ + exact Finset.mem_union_right _ + (Finset.mem_image.mpr + ⟨n, Finset.mem_range.mpr (Nat.lt_succ_of_le hl), rfl⟩) + protected_step := by + intro l g hg + change dist + ((states fresh enumeration x hfresh_card hfresh_independent initial l).character g) + ((step fresh enumeration x hfresh_card hfresh_independent initial l).next g) ≤ _ + exact (step fresh enumeration x hfresh_card hfresh_independent initial l).protected_closeness g hg + retained_at_stage := by + intro l g hg + change ‖(step fresh enumeration x hfresh_card hfresh_independent initial l).next g‖ ≤ _ + exact (step fresh enumeration x hfresh_card hfresh_independent initial l).retained_small g hg + retained_protected := by + intro l g hg k hlk + have hgNext : g ∈ + (states fresh enumeration x hfresh_card hfresh_independent initial (l + 1)).pastRetained := by + change g ∈ + (states fresh enumeration x hfresh_card hfresh_independent initial l).pastRetained ∪ + (step fresh enumeration x hfresh_card hfresh_independent initial l).retained + exact Finset.mem_union_right _ hg + have hgPast : g ∈ + (states fresh enumeration x hfresh_card hfresh_independent initial k).pastRetained := + fusionStates_pastRetained_mono fresh enumeration x hfresh_card + hfresh_independent initial hlk hgNext + exact Finset.mem_union_left _ (Finset.mem_union_left _ hgPast) + +/-- Public certificate exported by the scheduling recursion. -/ +structure ScheduledRunCertificate where + run : FusionRun G + initial_half : run.character 0 x = ((1 / 2 : ℝ) : UnitAddCircle) + distinguished_protected : ∀ l, x ∈ run.guardSet l + retained_subset : ∀ l, run.retained l ⊆ fresh l + deleted_card_le : ∀ l, + (fresh l \ run.retained l).card ≤ (run.guardSet l).card + guard_card_le : ∀ l, + (run.guardSet l).card ≤ FusionSchedule.protectedBound l + +/-- Starting with the exact half-turn character and applying the dependent recursion produces a +complete certified run; no run is assumed as input. -/ +theorem exists_scheduledRunCertificate_of_initial_half + (hfresh_card : ∀ l, (fresh l).card ≤ FusionSchedule.blockSize l) + (hfresh_independent : ∀ l, + BoundedIndependent (FusionSchedule.stageIndependenceBound l) (fresh l)) + (hinitial : initial x = ((1 / 2 : ℝ) : UnitAddCircle)) + (henumeration : Function.Surjective enumeration) : + Nonempty (ScheduledRunCertificate fresh x) := by + classical + -- The parameter `initial` is replaced below by the character chosen from `hx`; this theorem + -- is stated in its more useful existential form just after the section. + exact ⟨{ + run := scheduledRun fresh enumeration x hfresh_card hfresh_independent initial henumeration + initial_half := by + simpa only [scheduledRun, fusionStates_zero] using hinitial + distinguished_protected := by + intro l + exact Finset.mem_union_left _ (Finset.mem_union_right _ (Finset.mem_singleton_self x)) + retained_subset := by + intro l + exact (step fresh enumeration x hfresh_card hfresh_independent initial l).retained_subset + deleted_card_le := by + intro l + exact (step fresh enumeration x hfresh_card hfresh_independent initial l).deleted_card_le + guard_card_le := by + intro l + exact stageGuard_card_le enumeration x l + (states fresh enumeration x hfresh_card hfresh_independent initial l) }⟩ + +end ScheduledConstruction + +/-- Fully existential form of the generic scheduling recursion. -/ +theorem exists_scheduledRunCertificate + {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] + (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) + (hx : x ≠ 0) + (hfresh_card : ∀ l, (fresh l).card ≤ FusionSchedule.blockSize l) + (hfresh_independent : ∀ l, + BoundedIndependent (FusionSchedule.stageIndependenceBound l) (fresh l)) + (henumeration : Function.Surjective enumeration) : + Nonempty (ScheduledRunCertificate fresh x) := by + obtain ⟨initial, hinitial⟩ := exists_character_apply_eq_half hx + exact exists_scheduledRunCertificate_of_initial_half + (fresh := fresh) (enumeration := enumeration) (x := x) + (initial := initial) hfresh_card hfresh_independent hinitial henumeration + +/-! ## Interface from concrete runs to the global assembly -/ + +open TriangularPreprocess ConcreteData ConcreteClosure ConcreteLocalSetup + +/-- The block certificate for one code in the countable closure. In addition to the analytic +`CodeBlocks` data it identifies the abstract fields with the concrete prepared sequence, +ultrafilter, and block partition. -/ +structure ConcreteCodeBlocks + (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) + (x : ContinuumFreeGroup) + (R : FusionRun (closure N hN M x →₀ ℤ)) + (a : RelevantCode N hN M x) where + blocks : R.CodeBlocks + p_eq : blocks.p = ultrafilter N hN a.1 + block_eq : ∀ l, blocks.block l = blockPositions N hN l + difference_eq : ∀ n, + blocks.difference n = localDifference N hN M x a n + +namespace ConcreteCodeBlocks + +/-- A concrete retained-block certificate gives precisely the local admissibility equation for +its relevant code. -/ +theorem tendsto_prepared + {N : ℕ → ℕ} {hN : ∀ l, 0 < N l} {M : ℕ → ℕ} + {x : ContinuumFreeGroup} + {R : FusionRun (closure N hN M x →₀ ℤ)} + {a : RelevantCode N hN M x} + (C : ConcreteCodeBlocks N hN M x R a) : + Tendsto + (fun n ↦ R.limitCharacter + (Finsupp.subtypeDomain (closure N hN M x) (prepared N hN M a.1 n))) + (ultrafilter N hN a.1) + (nhds (R.limitCharacter (Finsupp.single ⟨codeIndex a.1, a.2⟩ 1))) := by + have hp : (C.blocks.p : Filter ℕ) ≤ cofinite := by + rw [C.p_eq] + exact ultrafilter_free N hN a.1 + have hzero := R.tendsto_limit_difference_zero_of_blockPositions + C.blocks N hN hp C.block_eq + have hdifference : ∀ n, C.blocks.difference n = + Finsupp.subtypeDomain (closure N hN M x) (prepared N hN M a.1 n) - + Finsupp.single ⟨codeIndex a.1, a.2⟩ 1 := by + intro n + rw [C.difference_eq] + simp only [localDifference] + ext i + change prepared N hN M a.1 n i.val - codeBasisVector a.1 i.val = + prepared N hN M a.1 n i.val - + Finsupp.single ⟨codeIndex a.1, a.2⟩ 1 i + by_cases hi : i.val = codeIndex a.1 + · have hisub : i = ⟨codeIndex a.1, a.2⟩ := Subtype.ext hi + subst i + simp [codeBasisVector] + · have hisub : i ≠ ⟨codeIndex a.1, a.2⟩ := by + intro heq + exact hi (congrArg Subtype.val heq) + simp [codeBasisVector, hi, hisub] + have hprepared := R.tendsto_limit_prepared C.blocks + (fun n ↦ Finsupp.subtypeDomain (closure N hN M x) (prepared N hN M a.1 n)) + (Finsupp.single ⟨codeIndex a.1, a.2⟩ 1) hdifference hzero + simpa only [C.p_eq] using hprepared + +end ConcreteCodeBlocks + +/-- Complete local output for one distinguished nonzero vector. This is a deliberately small +interface: a concrete scheduling recursion supplies the run and one block certificate for each +relevant code; all limiting arguments are discharged above. -/ +structure LocalRunCertificate + (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) + (x : {x : ContinuumFreeGroup // x ≠ 0}) where + run : FusionRun (closure N hN M x.1 →₀ ℤ) + self_ne_zero : + run.limitCharacter + (Finsupp.subtypeDomain (closure N hN M x.1) x.1) ≠ 0 + codeBlocks : ∀ a : RelevantCode N hN M x.1, + ConcreteCodeBlocks N hN M x.1 run a + +/-- The concrete run certificate satisfies the exact local interface consumed by the +transfinite-extension and global-assembly modules. -/ +theorem LocalRunCertificate.locallyAdmissible + {N : ℕ → ℕ} {hN : ∀ l, 0 < N l} {M : ℕ → ℕ} + {x : {x : ContinuumFreeGroup // x ≠ 0}} + (C : LocalRunCertificate N hN M x) : + TransfiniteExtension.LocallyAdmissible + (transfiniteData N hN M) (closure N hN M x.1) C.run.limitCharacter := by + intro a ha + exact (C.codeBlocks ⟨a, ha⟩).tendsto_prepared + +/-- It is enough to construct a certified concrete fusion run for every nonzero vector. -/ +theorem hasLocalSeparatingCharacters_of_certificates + (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) + (H : ∀ x : {x : ContinuumFreeGroup // x ≠ 0}, + Nonempty (LocalRunCertificate N hN M x)) : + GlobalAssembly.HasLocalSeparatingCharacters N hN M := by + intro x + let C : LocalRunCertificate N hN M x := Classical.choice (H x) + exact ⟨C.run.limitCharacter, C.self_ne_zero, C.locallyAdmissible⟩ + +end + +end LocalFusion +end Wallace diff --git a/LeanPool/Wallace/Main.lean b/LeanPool/Wallace/Main.lean new file mode 100644 index 000000000..ad6db8fda --- /dev/null +++ b/LeanPool/Wallace/Main.lean @@ -0,0 +1,59 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.FullTopologyMain + +/-! +# The concrete Wallace counterexample + +This file closes the construction. All numerical parameters, subsequences, filters, +ultrafilters, finite character approximations, countable fusions, transfinite extensions, and +the final topology have been constructed in the imported modules. The theorem below has no +mathematical hypothesis. +-/ + +namespace Wallace + +open TriangularPreprocess + +/-- A closed, witness-level form of the main construction. + +There is a Hausdorff group topology on the canonical free Abelian group of rank continuum for +which the nonnegative cone, with its induced topology, is countably compact and is a Wallace +semigroup. The explicit `CountablyCompactSpace` conjunct records the principal topological +conclusion separately, although it is also contained in `IsWallaceSemigroup`. -/ +theorem continuumFreeGroup_positiveCone_isWallace : + ∃ topology : TopologicalSpace ContinuumFreeGroup, + @IsTopologicalAddGroup ContinuumFreeGroup topology _ ∧ + @T2Space ContinuumFreeGroup topology ∧ + @CountablyCompactSpace (positiveCone ContinuumIndex) + (TopologicalSpace.induced + (fun z : positiveCone ContinuumIndex ↦ (z : ContinuumFreeGroup)) topology) ∧ + @IsWallaceSemigroup (positiveCone ContinuumIndex) + (TopologicalSpace.induced + (fun z : positiveCone ContinuumIndex ↦ (z : ContinuumFreeGroup)) topology) _ := by + let C : SeparationPackage ContinuumIndex := continuumFullSeparationPackage + let topology : TopologicalSpace ContinuumFreeGroup := C.initialTopology + letI : TopologicalSpace ContinuumFreeGroup := topology + letI : IsTopologicalAddGroup ContinuumFreeGroup := C.initial_isTopologicalAddGroup + letI : T2Space ContinuumFreeGroup := C.initial_t2Space + letI : Infinite ContinuumIndex := continuumIndex_infinite + let i : ContinuumIndex := Classical.choice inferInstance + have hwallace : IsWallaceSemigroup (positiveCone ContinuumIndex) := + positiveCone_isWallace_of_limitProperty ContinuumIndex i + C.positiveCone_hasWallaceLimitProperty + refine ⟨topology, C.initial_isTopologicalAddGroup, C.initial_t2Space, ?_, hwallace⟩ + exact hwallace.2.2.2.1 + +/-- There exists a Hausdorff countably compact cancellative topological additive monoid which is +not a group. The stronger public theorem in `TychonoffWallace.lean` also exposes commutativity +and Tychonoffness in its proposition. -/ +theorem wallaceCounterexampleExists : WallaceCounterexampleExists := + by + letI : Infinite ContinuumIndex := continuumIndex_infinite + exact continuumFullSeparationPackage.wallaceCounterexampleExists + +end Wallace diff --git a/LeanPool/Wallace/MathlibFoundations.lean b/LeanPool/Wallace/MathlibFoundations.lean new file mode 100644 index 000000000..45f69f6a7 --- /dev/null +++ b/LeanPool/Wallace/MathlibFoundations.lean @@ -0,0 +1,419 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import Mathlib + +/-! +# ZFC foundations used by the Wallace construction + +This file records the parts of the set-theoretic and topological construction that can be +checked directly against mathlib. In particular, it proves the ultrafilter extension step and +the basic facts about the initial topology generated by a family of circle-valued characters. + +No declaration in this file is an axiom and no proof is omitted. +-/ + +open Filter Set Topology +open scoped Cardinal + +universe u v w + +namespace Wallace + +noncomputable section + +/-! ## Families with the finite-intersection property -/ + +/-- A family of sets has the finite-intersection property when every finite subfamily has +nonempty intersection. The empty finite subfamily is included, so this also records that the +underlying type is nonempty whenever the property holds. -/ +def HasFiniteIntersectionProperty {α : Type u} (𝒜 : Set (Set α)) : Prop := + ∀ T : Finset (Set α), (↑T : Set (Set α)) ⊆ 𝒜 → + (⋂₀ (↑T : Set (Set α))).Nonempty + +/-- The ultrafilter lemma in the exact finite-intersection form needed in the construction. -/ +theorem exists_ultrafilter_extending_fip {α : Type u} {𝒜 : Set (Set α)} + (h𝒜 : HasFiniteIntersectionProperty 𝒜) : + ∃ p : Ultrafilter α, 𝒜 ⊆ (p : Filter α).sets := + Ultrafilter.exists_ultrafilter_of_finite_inter_nonempty 𝒜 h𝒜 + +/-- If a finite-intersection family contains every cofinite set, its ultrafilter extension is +free (expressed by lying below the cofinite filter in the filter order). -/ +theorem exists_free_ultrafilter_extending_fip {α : Type u} {𝒜 : Set (Set α)} + (h𝒜 : HasFiniteIntersectionProperty 𝒜) + (hcofinite : (cofinite : Filter α).sets ⊆ 𝒜) : + ∃ p : Ultrafilter α, + 𝒜 ⊆ (p : Filter α).sets ∧ (p : Filter α) ≤ cofinite := by + obtain ⟨p, hp⟩ := exists_ultrafilter_extending_fip h𝒜 + refine ⟨p, hp, ?_⟩ + intro s hs + exact hp (hcofinite hs) + +/-- Any proper filter extending the cofinite filter admits a free ultrafilter refinement. -/ +theorem exists_free_ultrafilter_le_filter {α : Type u} (l : Filter α) [l.NeBot] + (hl : l ≤ cofinite) : + ∃ p : Ultrafilter α, + (p : Filter α) ≤ l ∧ (p : Filter α) ≤ cofinite := by + refine ⟨Ultrafilter.of l, Ultrafilter.of_le l, ?_⟩ + exact (Ultrafilter.of_le l).trans hl + +/-- A filter below the cofinite filter contains no finite set. -/ +theorem finite_not_mem_of_le_cofinite {α : Type u} {l : Filter α} + [l.NeBot] (hl : l ≤ cofinite) {s : Set α} (hs : s.Finite) : s ∉ l := by + intro hsl + exact compl_notMem hsl (hl hs.compl_mem_cofinite) + +/-! ## Characters of a free Abelian group -/ + +/-- The homomorphism out of a free Abelian group determined by its values on the standard +basis. -/ +def finsuppAddHomOfBasis {ι : Type u} {A : Type v} [AddCommGroup A] + (z : ι → A) : (ι →₀ ℤ) →+ A := + Finsupp.liftAddHom fun i => (zmultiplesHom A) (z i) + +@[simp] +theorem finsuppAddHomOfBasis_single {ι : Type u} {A : Type v} [AddCommGroup A] + (z : ι → A) (i : ι) (n : ℤ) : + finsuppAddHomOfBasis z (Finsupp.single i n) = n • z i := by + simp [finsuppAddHomOfBasis] + +@[simp] +theorem finsuppAddHomOfBasis_single_one {ι : Type u} {A : Type v} [AddCommGroup A] + (z : ι → A) (i : ι) : + finsuppAddHomOfBasis z (Finsupp.single i 1) = z i := by + simp + +/-! ## The initial topology generated by circle-valued characters -/ + +/-- The diagonal homomorphism associated to a family of characters. -/ +def characterDiagonal {G : Type u} {I : Type v} [AddGroup G] + (χ : I → G →+ UnitAddCircle) : G →+ (I → UnitAddCircle) where + toFun x i := χ i x + map_zero' := by ext i; simp + map_add' x y := by ext i; simp + +@[simp] +theorem characterDiagonal_apply {G : Type u} {I : Type v} [AddGroup G] + (χ : I → G →+ UnitAddCircle) (x : G) (i : I) : + characterDiagonal χ x i = χ i x := + rfl + +/-- Point-separation stated at zero, the natural form for additive characters. -/ +def CharactersSeparatePoints {G : Type u} {I : Type v} [AddGroup G] + (χ : I → G →+ UnitAddCircle) : Prop := + ∀ x : G, (∀ i, χ i x = 0) → x = 0 + +theorem characterDiagonal_injective {G : Type u} {I : Type v} [AddGroup G] + {χ : I → G →+ UnitAddCircle} (hχ : CharactersSeparatePoints χ) : + Function.Injective (characterDiagonal χ) := by + intro x y hxy + apply sub_eq_zero.mp + apply hχ (x - y) + intro i + have hi : χ i x = χ i y := by + simpa only [characterDiagonal_apply] using congrFun hxy i + rw [map_sub, hi, sub_self] + +/-- The initial topology generated by all members of `χ`. Equivalently, this is the topology +induced by the diagonal map into the corresponding power of the circle. -/ +@[reducible] +def characterTopology {G : Type u} {I : Type v} [AddGroup G] + (χ : I → G →+ UnitAddCircle) : TopologicalSpace G := + TopologicalSpace.induced (characterDiagonal χ) inferInstance + +/-- The uniformity induced by the same diagonal map. -/ +@[reducible] +def characterUniformSpace {G : Type u} {I : Type v} [AddGroup G] + (χ : I → G →+ UnitAddCircle) : UniformSpace G := + UniformSpace.comap (characterDiagonal χ) inferInstance + +theorem characterUniformSpace_toTopology {G : Type u} {I : Type v} [AddGroup G] + (χ : I → G →+ UnitAddCircle) : + (characterUniformSpace χ).toTopologicalSpace = characterTopology χ := + rfl + +/-- The diagonal description really is the infimum of the topologies induced by the individual +characters. -/ +theorem characterTopology_eq_iInf {G : Type u} {I : Type v} [AddGroup G] + (χ : I → G →+ UnitAddCircle) : + characterTopology χ = + ⨅ i, TopologicalSpace.induced (χ i : G → UnitAddCircle) inferInstance := by + change TopologicalSpace.induced (fun x i => χ i x) Pi.topologicalSpace = _ + exact induced_to_pi fun x i => χ i x + +/-- Universal property of the initial character topology. -/ +theorem le_characterTopology_iff {G : Type u} {I : Type v} [AddGroup G] + (χ : I → G →+ UnitAddCircle) (t : TopologicalSpace G) : + t ≤ characterTopology χ ↔ + ∀ i, @Continuous G UnitAddCircle t inferInstance (χ i) := by + change t ≤ TopologicalSpace.induced (characterDiagonal χ) inferInstance ↔ _ + rw [← continuous_iff_le_induced] + exact continuous_pi_iff + +/-- Every generating character is continuous for the initial topology. -/ +theorem continuous_character {G : Type u} {I : Type v} [AddGroup G] + (χ : I → G →+ UnitAddCircle) (i : I) : + @Continuous G UnitAddCircle (characterTopology χ) inferInstance (χ i) := by + exact (le_characterTopology_iff χ (characterTopology χ)).1 le_rfl i + +/-- The initial character topology is a topological group topology. -/ +theorem characterTopology_isTopologicalAddGroup + {G : Type u} {I : Type v} [AddGroup G] + (χ : I → G →+ UnitAddCircle) : + @IsTopologicalAddGroup G (characterTopology χ) _ := by + exact topologicalAddGroup_induced (characterDiagonal χ) + +/-- A point-separating family of characters makes its initial topology Hausdorff. -/ +theorem characterTopology_t2Space + {G : Type u} {I : Type v} [AddGroup G] + {χ : I → G →+ UnitAddCircle} (hχ : CharactersSeparatePoints χ) : + @T2Space G (characterTopology χ) := by + letI : TopologicalSpace G := characterTopology χ + exact (characterDiagonal_injective hχ).isEmbedding_induced.t2Space + +/-- The diagonal map is uniformly inducing for the pulled-back uniformity. -/ +theorem characterDiagonal_isUniformInducing + {G : Type u} {I : Type v} [AddGroup G] + (χ : I → G →+ UnitAddCircle) : + @IsUniformInducing G (I → UnitAddCircle) + (characterUniformSpace χ) inferInstance (characterDiagonal χ) := + by + letI : UniformSpace G := characterUniformSpace χ + exact ⟨rfl⟩ + +/-- The pulled-back character uniformity is totally bounded: it is induced from a compact +power of the circle. This is the precise uniform-space content of precompactness here. -/ +theorem characterUniformSpace_totallyBounded + {G : Type u} {I : Type v} [AddGroup G] + (χ : I → G →+ UnitAddCircle) : + @TotallyBounded G (characterUniformSpace χ) Set.univ := by + letI : UniformSpace G := characterUniformSpace χ + have htarget : TotallyBounded (Set.univ : Set (I → UnitAddCircle)) := + isCompact_univ.totallyBounded + simpa using totallyBounded_preimage (characterDiagonal_isUniformInducing χ) htarget + +/-! ## Cardinal bookkeeping for the continuum-indexed free group -/ + +/-- The free Abelian group on `ℝ` has cardinality continuum. -/ +theorem mk_continuumFreeAbelianGroup : #(ℝ →₀ ℤ) = 𝔠 := by + rw [Cardinal.mk_finsupp_of_infinite, Cardinal.mk_real, Cardinal.mk_int] + exact max_eq_left Cardinal.aleph0_le_continuum + +/-- The collection of all sequences in the continuum-indexed free group still has cardinality +continuum. -/ +theorem mk_continuumFreeAbelianGroup_sequences : #(ℕ → (ℝ →₀ ℤ)) = 𝔠 := by + rw [Cardinal.mk_arrow, mk_continuumFreeAbelianGroup, Cardinal.mk_nat] + simpa only [Cardinal.lift_id] using Cardinal.continuum_power_aleph0 + +/-- König's theorem gives the strict uncountable cofinality of the continuum. This is the +precise fact used to bound a countable union of supports below the initial ordinal of `𝔠`. -/ +theorem aleph0_lt_cof_continuum : ℵ₀ < (𝔠 : Cardinal).ord.cof := by + rw [← Cardinal.two_power_aleph0] + exact Cardinal.lt_cof_ord_power le_rfl (by simp) + +/-- A countable supremum of cardinals strictly below the continuum remains below the +continuum. -/ +theorem iSup_nat_lt_continuum {f : ℕ → Cardinal.{0}} + (hf : ∀ n, f n < 𝔠) : ⨆ n, f n < 𝔠 := by + apply Cardinal.iSup_lt_of_lt_cof_ord + · simpa only [Cardinal.mk_nat] using aleph0_lt_cof_continuum + · exact hf + +/-- Ordinal form of the same boundedness fact: countably many ordinals below the initial +ordinal of the continuum have supremum below it. -/ +theorem iSup_nat_ordinal_lt_continuum {f : ℕ → Ordinal.{0}} + (hf : ∀ n, f n < (𝔠 : Cardinal).ord) : + ⨆ n, f n < (𝔠 : Cardinal).ord := by + apply Ordinal.iSup_lt_of_lt_cof + · simpa only [Cardinal.mk_nat] using aleph0_lt_cof_continuum + · exact hf + +/-- An explicit injective sequence in the free group, supported on one basis vector. -/ +def basisRaySequence (r : ℝ) (n : ℕ) : ℝ →₀ ℤ := + Finsupp.single r (n : ℤ) + +theorem basisRaySequence_injective (r : ℝ) : + Function.Injective (basisRaySequence r) := by + intro m n hmn + have := congrArg (fun z : ℝ →₀ ℤ => z r) hmn + simpa [basisRaySequence] using this + +/-- Distinct basis vectors give distinct injective sequences. -/ +theorem basisRaySequence_family_injective : + Function.Injective (fun r : ℝ => + (⟨basisRaySequence r, basisRaySequence_injective r⟩ : + {s : ℕ → (ℝ →₀ ℤ) // Function.Injective s})) := by + intro r s hrs + have hfun : basisRaySequence r = basisRaySequence s := + congrArg Subtype.val hrs + have hzero := congrArg (fun q : ℕ → (ℝ →₀ ℤ) => q 1 r) hfun + by_contra hrs' + simp [basisRaySequence, hrs'] at hzero + +/-- Hence every subtype of sequences, in particular the injective sequences used by the paper, +has cardinality at most continuum. -/ +theorem mk_injective_continuumFreeAbelianGroup_sequences_le : + #({s : ℕ → (ℝ →₀ ℤ) // Function.Injective s}) ≤ 𝔠 := by + exact (Cardinal.mk_subtype_le _).trans_eq mk_continuumFreeAbelianGroup_sequences + +/-- The injective sequences in the continuum-indexed free group have cardinality exactly +continuum. -/ +theorem mk_injective_continuumFreeAbelianGroup_sequences : + #({s : ℕ → (ℝ →₀ ℤ) // Function.Injective s}) = 𝔠 := by + apply le_antisymm mk_injective_continuumFreeAbelianGroup_sequences_le + rw [← Cardinal.mk_real] + exact Cardinal.mk_le_of_injective basisRaySequence_family_injective + +/-- A genuine enumeration (equivalence), not merely a cardinal upper bound, of the injective +sequences by a continuum-sized index type. -/ +def injectiveSequenceEnumeration : + ℝ ≃ {s : ℕ → (ℝ →₀ ℤ) // Function.Injective s} := + Classical.choice <| Cardinal.eq.mp <| + Cardinal.mk_real.trans mk_injective_continuumFreeAbelianGroup_sequences.symm + +/-! ## A continuum-sized almost-disjoint family -/ + +/-- A concrete node on the binary tree: a level and the values below that level. -/ +abbrev BinaryTreeNode := Σ n : ℕ, Fin n → Bool + +/-- The length-`n` initial segment of a binary stream. -/ +def binaryPrefix (x : ℕ → Bool) (n : ℕ) : BinaryTreeNode := + ⟨n, fun i => x i⟩ + +/-- The branch through the binary tree associated to a stream. -/ +def binaryBranch (x : ℕ → Bool) : Set BinaryTreeNode := + Set.range (binaryPrefix x) + +theorem binaryPrefix_injective (x : ℕ → Bool) : + Function.Injective (binaryPrefix x) := by + intro m n h + exact congrArg Sigma.fst h + +/-- Every branch is infinite. -/ +theorem binaryBranch_infinite (x : ℕ → Bool) : (binaryBranch x).Infinite := by + exact Set.infinite_range_of_injective (binaryPrefix_injective x) + +/-- If two branches share a node at level `n`, then their streams agree below `n`. -/ +theorem eq_on_Iio_of_binaryPrefix_eq {x y : ℕ → Bool} {m n : ℕ} + (h : binaryPrefix x m = binaryPrefix y n) : + m = n ∧ ∀ k < m, x k = y k := by + have hmn : m = n := congrArg Sigma.fst h + subst n + refine ⟨rfl, ?_⟩ + have hfun : (fun i : Fin m => x i) = fun i : Fin m => y i := + eq_of_heq (Sigma.mk.inj_iff.mp h).2 + intro k hk + exact congrFun hfun ⟨k, hk⟩ + +/-- Distinct binary streams define branches with finite intersection. -/ +theorem binaryBranch_inter_finite {x y : ℕ → Bool} (hxy : x ≠ y) : + (binaryBranch x ∩ binaryBranch y).Finite := by + obtain ⟨k, hk⟩ : ∃ k, x k ≠ y k := by + simpa only [Function.ne_iff] using hxy + refine (Set.finite_Iic k).image (binaryPrefix x) |>.subset ?_ + intro z hz + rcases hz.1 with ⟨m, rfl⟩ + rcases hz.2 with ⟨n, hmn⟩ + have hmn' := (eq_on_Iio_of_binaryPrefix_eq hmn).1 + subst n + refine ⟨m, ?_, rfl⟩ + by_contra hmk + have hkm : k < m := Nat.lt_of_not_ge hmk + exact hk ((eq_on_Iio_of_binaryPrefix_eq hmn).2 k hkm).symm + +/-- The branch assignment is injective. -/ +theorem binaryBranch_injective : Function.Injective binaryBranch := by + intro x y hxy + by_contra hne + have hfinite := binaryBranch_inter_finite hne + rw [hxy, inter_self] at hfinite + exact (binaryBranch_infinite y) hfinite + +/-- The concrete almost-disjoint family of binary-tree branches has cardinality continuum. -/ +theorem mk_binaryBranch_family : #(Set.range binaryBranch) = 𝔠 := by + rw [Cardinal.mk_range_eq binaryBranch binaryBranch_injective, Cardinal.mk_arrow, + Cardinal.mk_bool, Cardinal.mk_nat] + simp only [Cardinal.lift_id, Cardinal.two_power_aleph0] + +/-- A packaged continuum-sized almost-disjoint family: every member is infinite, distinct +members have finite intersection, and the family itself has cardinality continuum. -/ +theorem binaryBranch_family_spec : + (∀ A ∈ Set.range binaryBranch, A.Infinite) ∧ + ((Set.range binaryBranch).Pairwise fun A B => (A ∩ B).Finite) ∧ + #(Set.range binaryBranch) = 𝔠 := by + refine ⟨?_, ?_, mk_binaryBranch_family⟩ + · rintro A ⟨x, rfl⟩ + exact binaryBranch_infinite x + · rintro A ⟨x, rfl⟩ B ⟨y, rfl⟩ hAB + apply binaryBranch_inter_finite + intro hxy + exact hAB (congrArg binaryBranch hxy) + +/-- The binary-tree node type used above is countable. -/ +theorem binaryTreeNode_countable : Countable BinaryTreeNode := + inferInstance + +/-- The binary-tree node type is infinite. -/ +theorem binaryTreeNode_infinite : Infinite BinaryTreeNode := + Infinite.of_injective (binaryPrefix fun _ => false) + (binaryPrefix_injective fun _ => false) + +/-- A fixed identification of the countably infinite binary tree with `ℕ`. -/ +def binaryTreeNodeEquivNat : BinaryTreeNode ≃ ℕ := by + letI : Infinite BinaryTreeNode := binaryTreeNode_infinite + letI : Denumerable BinaryTreeNode := + Denumerable.ofEncodableOfInfinite BinaryTreeNode + exact Denumerable.eqv BinaryTreeNode + +/-- The same branch family, transported to an almost-disjoint family literally on `ℕ`. -/ +def binaryBranchOnNat (x : ℕ → Bool) : Set ℕ := + binaryTreeNodeEquivNat '' binaryBranch x + +theorem binaryBranchOnNat_infinite (x : ℕ → Bool) : + (binaryBranchOnNat x).Infinite := by + exact (binaryBranch_infinite x).image binaryTreeNodeEquivNat.injective.injOn + +theorem binaryBranchOnNat_inter_finite {x y : ℕ → Bool} (hxy : x ≠ y) : + (binaryBranchOnNat x ∩ binaryBranchOnNat y).Finite := by + change (binaryTreeNodeEquivNat '' binaryBranch x ∩ + binaryTreeNodeEquivNat '' binaryBranch y).Finite + rw [← Set.image_inter binaryTreeNodeEquivNat.injective] + exact (binaryBranch_inter_finite hxy).image binaryTreeNodeEquivNat + +theorem binaryBranchOnNat_injective : Function.Injective binaryBranchOnNat := + binaryTreeNodeEquivNat.injective.image_injective.comp binaryBranch_injective + +/-- Standard ZFC form: there is an explicit almost-disjoint family on `ℕ` of cardinality +continuum. -/ +theorem binaryBranchOnNat_family_spec : + (∀ A ∈ Set.range binaryBranchOnNat, A.Infinite) ∧ + ((Set.range binaryBranchOnNat).Pairwise fun A B => (A ∩ B).Finite) ∧ + #(Set.range binaryBranchOnNat) = 𝔠 := by + refine ⟨?_, ?_, ?_⟩ + · rintro A ⟨x, rfl⟩ + exact binaryBranchOnNat_infinite x + · rintro A ⟨x, rfl⟩ B ⟨y, rfl⟩ hAB + apply binaryBranchOnNat_inter_finite + intro hxy + exact hAB (congrArg binaryBranchOnNat hxy) + · rw [Cardinal.mk_range_eq binaryBranchOnNat binaryBranchOnNat_injective, + Cardinal.mk_arrow, Cardinal.mk_bool, Cardinal.mk_nat] + simp only [Cardinal.lift_id, Cardinal.two_power_aleph0] + +/-! ## A reusable transfinite-iteration fact -/ + +/-- Inflationary transfinite iteration is monotone in the ordinal-like index. This records the +mathlib recursion principle used for monotone bookkeeping constructions. -/ +theorem transfiniteIterate_mono + {L : Type u} [CompleteLattice L] + {J : Type v} [LinearOrder J] [OrderBot J] [SuccOrder J] [WellFoundedLT J] + (φ : L → L) (x : L) (hφ : ∀ y, y ≤ φ y) : + Monotone (fun j : J => transfiniteIterate φ j x) := + monotone_transfiniteIterate φ x hφ + +end + +end Wallace diff --git a/LeanPool/Wallace/NontrivialSequences.lean b/LeanPool/Wallace/NontrivialSequences.lean new file mode 100644 index 000000000..94963db9b --- /dev/null +++ b/LeanPool/Wallace/NontrivialSequences.lean @@ -0,0 +1,162 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.SeparationInterface +import Mathlib.Data.Nat.Nth + +/-! +# Excluding nontrivial convergent sequences + +The separating package constructed for the Wallace semigroup has a stronger consequence than +point separation. Every injective sequence has a genuine subsequence which converges, along a +free ultrafilter, to a nonzero basis vector. In a Hausdorff topological group this rules out +convergence of the original injective sequence: after translation by its alleged limit, the +same subsequence would converge to zero along the free ultrafilter. + +This observation avoids any separate oscillating-marker construction. +-/ + +open Filter Set Topology + +universe u + +namespace Wallace + +noncomputable section + +/-- Every injective sequence has a strictly reindexed subsequence with a nonzero limit along a +free ultrafilter. -/ +def HasNonzeroLimitProperty + (G : Type u) [TopologicalSpace G] [Zero G] : Prop := + ∀ s : ℕ → G, Function.Injective s → + ∃ (φ : ℕ → ℕ) (x : G) (p : Ultrafilter ℕ), + StrictMono φ ∧ x ≠ 0 ∧ (p : Filter ℕ) ≤ cofinite ∧ + Tendsto (s ∘ φ) p (nhds x) + +/-- A separation package has the nonzero ultrafilter-limit property: its prescribed limit is +the fresh basis vector attached to the code of the sequence. -/ +theorem SeparationPackage.hasNonzeroLimitProperty + {I : Type u} (C : SeparationPackage I) : + @HasNonzeroLimitProperty (I →₀ ℤ) C.initialTopology _ := by + intro s hs + let encoded : InjectiveSequence' (I →₀ ℤ) := ⟨s, hs⟩ + let c : C.Code := C.codeEquiv.symm encoded + have hcoded : (C.codeEquiv c).1 = s := by + exact congrArg Subtype.val (C.codeEquiv.apply_symm_apply encoded) + refine ⟨C.subsequence c, Finsupp.single (C.codeIndex c) 1, C.ultrafilter c, + C.subsequence_strictMono c, ?_, C.ultrafilter_free c, ?_⟩ + · exact Finsupp.single_ne_zero.mpr one_ne_zero + · change Tendsto (fun n ↦ s (C.subsequence c n)) (C.ultrafilter c) _ + rw [← hcoded] + exact C.prepared_tendsto_basis c + +/-- In a Hausdorff topological group, the nonzero ultrafilter-limit property prevents every +injective sequence from converging. -/ +theorem no_injective_sequence_converges_of_nonzeroLimitProperty + {G : Type u} [TopologicalSpace G] [AddGroup G] + [IsTopologicalAddGroup G] [T2Space G] + (hlimits : HasNonzeroLimitProperty G) : + ∀ s : ℕ → G, Function.Injective s → + ¬ ∃ x : G, Tendsto s atTop (nhds x) := by + intro s hs + rintro ⟨x, hsx⟩ + let t : ℕ → G := fun n ↦ s n - x + have htinj : Function.Injective t := by + intro m n hmn + have h := congrArg (fun z : G ↦ z + x) hmn + apply hs + simpa [t] using h + obtain ⟨φ, y, p, hφ, hy, hfree, hpy⟩ := hlimits t htinj + have ht0 : Tendsto t atTop (nhds 0) := by + simpa [t] using hsx.sub + (tendsto_const_nhds : Tendsto (fun _ : ℕ ↦ x) atTop (nhds x)) + have hsub0 : Tendsto (t ∘ φ) atTop (nhds 0) := + ht0.comp hφ.tendsto_atTop + have hfree' : (p : Filter ℕ) ≤ atTop := by + simpa only [Nat.cofinite_eq_atTop] using hfree + have hp0 : Tendsto (t ∘ φ) p (nhds 0) := hsub0.mono_left hfree' + exact hy (tendsto_nhds_unique hpy hp0) + +/-- The nonzero limits supplied by a separation package rule out convergence of every injective +sequence in its initial topology. -/ +theorem SeparationPackage.no_injective_sequence_converges + {I : Type u} (C : SeparationPackage I) : + ∀ s : ℕ → (I →₀ ℤ), Function.Injective s → + ¬ ∃ x : I →₀ ℤ, + Tendsto s atTop (@nhds (I →₀ ℤ) C.initialTopology x) := by + letI : TopologicalSpace (I →₀ ℤ) := C.initialTopology + letI : IsTopologicalAddGroup (I →₀ ℤ) := C.initial_isTopologicalAddGroup + letI : T2Space (I →₀ ℤ) := C.initial_t2Space + exact no_injective_sequence_converges_of_nonzeroLimitProperty + C.hasNonzeroLimitProperty + +/-- Any sequence with infinite range has a strictly reindexed injective subsequence. -/ +theorem exists_injective_subsequence_of_infinite_range + {X : Type u} {s : ℕ → X} (hinf : (Set.range s).Infinite) : + ∃ φ : ℕ → ℕ, StrictMono φ ∧ Function.Injective (s ∘ φ) := by + let e : ℕ ↪ Set.range s := hinf.natEmbedding + let pick : ℕ → ℕ := fun n ↦ Classical.choose (e n).property + have hpick : ∀ n, s (pick n) = e n := fun n ↦ Classical.choose_spec (e n).property + have hpickinj : Function.Injective pick := by + intro m n hmn + apply e.injective + apply Subtype.val_injective + rw [← hpick m, ← hpick n, hmn] + have hrange : (Set.range pick).Infinite := Set.infinite_range_of_injective hpickinj + let φ : ℕ → ℕ := Nat.nth (fun k ↦ k ∈ Set.range pick) + have hφ : StrictMono φ := Nat.nth_strictMono hrange + refine ⟨φ, hφ, ?_⟩ + intro m n hmn + have hm : φ m ∈ Set.range pick := Nat.nth_mem_of_infinite hrange m + have hn : φ n ∈ Set.range pick := Nat.nth_mem_of_infinite hrange n + obtain ⟨i, hi⟩ := hm + obtain ⟨j, hj⟩ := hn + have heij : e i = e j := by + apply Subtype.val_injective + rw [← hpick i, ← hpick j, hi, hj] + exact hmn + have hij : i = j := e.injective heij + apply hφ.injective + rw [← hi, ← hj, hij] + +/-- In a T1 space where no injective sequence converges, every convergent sequence is eventually +equal to its limit. -/ +theorem eventually_eq_limit_of_no_injective_sequence_converges + {X : Type u} [TopologicalSpace X] [T1Space X] + (hno : ∀ s : ℕ → X, Function.Injective s → + ¬ ∃ x : X, Tendsto s atTop (nhds x)) + {s : ℕ → X} {x : X} (hs : Tendsto s atTop (nhds x)) : + ∀ᶠ n in atTop, s n = x := by + by_cases hfinite : (Set.range s).Finite + · let A : Set X := Set.range s \ {x} + have hA : A.Finite := hfinite.diff + have hAc : IsClosed A := hA.isClosed + have hxA : x ∈ Aᶜ := by simp [A] + have hnhds : Aᶜ ∈ nhds x := hAc.isOpen_compl.mem_nhds hxA + filter_upwards [hs.eventually hnhds] with n hn + have hrange : s n ∈ Set.range s := Set.mem_range_self n + by_contra hne + exact hn ⟨hrange, by simpa using hne⟩ + · have hinf : (Set.range s).Infinite := hfinite + obtain ⟨φ, hφ, hinj⟩ := exists_injective_subsequence_of_infinite_range hinf + exact ((hno (s ∘ φ) hinj) ⟨x, hs.comp hφ.tendsto_atTop⟩).elim + +/-- Consequently every convergent sequence in the initial topology of a separation package is +eventually constant at its limit. -/ +theorem SeparationPackage.every_convergent_sequence_eventually_constant + {I : Type u} (C : SeparationPackage I) + {s : ℕ → (I →₀ ℤ)} {x : I →₀ ℤ} + (hs : Tendsto s atTop (@nhds (I →₀ ℤ) C.initialTopology x)) : + ∀ᶠ n in atTop, s n = x := by + letI : TopologicalSpace (I →₀ ℤ) := C.initialTopology + letI : IsTopologicalAddGroup (I →₀ ℤ) := C.initial_isTopologicalAddGroup + letI : T2Space (I →₀ ℤ) := C.initial_t2Space + exact eventually_eq_limit_of_no_injective_sequence_converges + C.no_injective_sequence_converges hs + +end + +end Wallace diff --git a/LeanPool/Wallace/PackageTransport.lean b/LeanPool/Wallace/PackageTransport.lean new file mode 100644 index 000000000..b56d4f7ce --- /dev/null +++ b/LeanPool/Wallace/PackageTransport.lean @@ -0,0 +1,92 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.FullTopology + +/-! +# Pulling a character package back along an embedding + +This module records a reusable transport principle for the topology construction. If an +additive group `G` embeds in a group `H` carrying a full character package, and every prescribed +limit point for an embedded injective sequence has a chosen preimage in `G`, then the entire +package pulls back to `G`. +-/ + +open Filter Topology + +universe u v w + +namespace Wallace + +noncomputable section + +namespace FullCharacterPackage + +variable {G : Type u} {H : Type v} [AddCommGroup G] [AddCommGroup H] + +/-- The code in an ambient character package corresponding to an injective sequence after it is +mapped along an additive embedding. -/ +def embeddedCode (C : FullCharacterPackage H) (e : G →+ H) + (he : Function.Injective e) (s : InjectiveSequence' G) : C.Code := + C.codeEquiv.symm ⟨fun n ↦ e (s.1 n), he.comp s.2⟩ + +/-- Pull a full character package back along an additive embedding. The only extra datum needed +is a preimage, in `G`, of the ambient package's prescribed limit point for every embedded +injective sequence. -/ +def pullback + (C : FullCharacterPackage H) (e : G →+ H) (he : Function.Injective e) + (limitPreimage : InjectiveSequence' G → G) + (map_limitPreimage : ∀ s, + e (limitPreimage s) = C.limitPoint (C.embeddedCode e he s)) : + FullCharacterPackage G where + Code := InjectiveSequence' G + codeEquiv := Equiv.refl _ + subsequence s := C.subsequence (C.embeddedCode e he s) + subsequence_strictMono s := C.subsequence_strictMono (C.embeddedCode e he s) + ultrafilter s := C.ultrafilter (C.embeddedCode e he s) + ultrafilter_free s := C.ultrafilter_free (C.embeddedCode e he s) + limitPoint := limitPreimage + limitPoint_ne_zero s := by + intro hs + have hambient := C.limitPoint_ne_zero (C.embeddedCode e he s) + apply hambient + rw [← map_limitPreimage s, hs, map_zero] + CharacterIndex := C.CharacterIndex + character j := (C.character j).comp e + character_detects x hx := by + have hex : e x ≠ 0 := by + intro hzero + exact hx (he (by simpa using hzero)) + obtain ⟨j, hj⟩ := C.character_detects (e x) hex + exact ⟨j, hj⟩ + character_limit s j := by + have hambient := C.character_limit (C.embeddedCode e he s) j + have hcode : + (C.codeEquiv (C.embeddedCode e he s)).1 = fun n ↦ e (s.1 n) := by + exact congrArg Subtype.val (C.codeEquiv.apply_symm_apply + ⟨fun n ↦ e (s.1 n), he.comp s.2⟩) + rw [hcode] at hambient + change Tendsto + (fun n ↦ C.character j + (e (s.1 (C.subsequence (C.embeddedCode e he s) n)))) + (C.ultrafilter (C.embeddedCode e he s)) + (nhds (C.character j (e (limitPreimage s)))) + rw [map_limitPreimage s] + exact hambient + +/-- Pulling a character package back along an additive equivalence requires no separate choice +of limit-point preimages. -/ +def comapAddEquiv (C : FullCharacterPackage H) (e : G ≃+ H) : + FullCharacterPackage G := + C.pullback e.toAddMonoidHom e.injective + (fun s ↦ e.symm (C.limitPoint (C.embeddedCode e.toAddMonoidHom e.injective s))) + (fun _ ↦ e.apply_symm_apply _) + +end FullCharacterPackage + +end + +end Wallace diff --git a/LeanPool/Wallace/RationalAssembly.lean b/LeanPool/Wallace/RationalAssembly.lean new file mode 100644 index 000000000..5ccd23463 --- /dev/null +++ b/LeanPool/Wallace/RationalAssembly.lean @@ -0,0 +1,101 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.RationalFusionRun +import LeanPool.Wallace.FullTopology + +/-! +# Global assembly for the rational vector group + +The local fusion around each nonzero vector is extended by the rational transfinite recursion. +The resulting compatible characters separate points and realize the nonzero ultrafilter limit +attached to every injective rational sequence. +-/ + +open Filter Set Topology + +namespace Wallace +namespace RationalAssembly + +noncomputable section + +open RationalTriangularPreprocess +open RationalData +open RationalClosure +open RationalFusionRun +open RationalTransfiniteExtension + +abbrev N : ℕ → ℕ := RationalFusionRun.blockSize +theorem hN (l : ℕ) : 0 < N l := RationalFusionRun.blockSize_pos l +abbrev M : ℕ → ℕ := RationalFusionRun.independenceBound + +/-- The local limiting character supplied by the concrete fusion. -/ +def localCharacter (x : {x : ContinuumRationalGroup // x ≠ 0}) : + (closure N hN M x.1 →₀ ℚ) →+ UnitAddCircle := + (localRunCertificate x).run.limitCharacter + +theorem localCharacter_self_ne_zero + (x : {x : ContinuumRationalGroup // x ≠ 0}) : + localCharacter x (Finsupp.subtypeDomain (closure N hN M x.1) x.1) ≠ 0 := + (localRunCertificate x).self_ne_zero + +theorem localCharacter_admissible + (x : {x : ContinuumRationalGroup // x ≠ 0}) : + LocallyAdmissible (transfiniteData N hN M) (closure N hN M x.1) + (localCharacter x) := + (localRunCertificate x).locallyAdmissible + +/-- Extend the local character to all continuum coordinates. -/ +def globalCharacter (x : {x : ContinuumRationalGroup // x ≠ 0}) : + ContinuumRationalGroup →+ UnitAddCircle := + RationalTransfiniteExtension.globalCharacter (transfiniteData N hN M) + (closure N hN M x.1) (localCharacter x) + +theorem globalCharacter_self_ne_zero + (x : {x : ContinuumRationalGroup // x ≠ 0}) : + globalCharacter x x.1 ≠ 0 := by + rw [globalCharacter, + RationalTransfiniteExtension.globalCharacter_eq_local_restriction] + · exact localCharacter_self_ne_zero x + · exact support_subset_closure N hN M x.1 + +theorem globalCharacter_admissible + (x : {x : ContinuumRationalGroup // x ≠ 0}) (a : ContinuumIndex) : + Tendsto + (fun n ↦ globalCharacter x (prepared N hN M a n)) + (ultrafilter N hN a) + (nhds (globalCharacter x (codeBasisVector a))) := by + exact RationalTransfiniteExtension.globalCharacter_admissible + (transfiniteData N hN M) (closure N hN M x.1) (localCharacter x) + (closure_closedUnderPreparedSupports N hN M x.1) + (localCharacter_admissible x) a + +/-- The complete character package for the rational direct sum of rank continuum. -/ +def fullCharacterPackage : FullCharacterPackage ContinuumRationalGroup where + Code := ContinuumIndex + codeEquiv := rationalSequenceCodeEquiv + subsequence := selector N hN M + subsequence_strictMono := selector_strictMono N hN M + ultrafilter := ultrafilter N hN + ultrafilter_free := ultrafilter_free N hN + limitPoint := codeBasisVector + limitPoint_ne_zero := fun _ ↦ Finsupp.single_ne_zero.mpr one_ne_zero + CharacterIndex := {x : ContinuumRationalGroup // x ≠ 0} + character := globalCharacter + character_detects x hx := ⟨⟨x, hx⟩, globalCharacter_self_ne_zero ⟨x, hx⟩⟩ + character_limit := by + intro a x + exact globalCharacter_admissible x a + +/-- The rational vector group of continuum rank has the full constructed topology: Hausdorff, +countably compact, totally bounded, and with only eventually constant convergent sequences. -/ +theorem continuumRationalGroup_mainTheorem : + RationalVectorGroupConclusion ContinuumIndex := + fullCharacterPackage.rationalVectorGroupConclusion + +end +end RationalAssembly +end Wallace diff --git a/LeanPool/Wallace/RationalClosure.lean b/LeanPool/Wallace/RationalClosure.lean new file mode 100644 index 000000000..964e8caac --- /dev/null +++ b/LeanPool/Wallace/RationalClosure.lean @@ -0,0 +1,87 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.RationalData +import LeanPool.Wallace.CountableClosure + +/-! +# Countable dependency closures for the rational direct sum + +Starting from the finite support of a vector, close under the supports of every prepared +sequence whose code coordinate has entered the set. +-/ + +open Set + +namespace Wallace +namespace RationalClosure + +noncomputable section + +open RationalTriangularPreprocess +open RationalData + +variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) + +/-- Coordinates occurring in the prepared sequence represented by `a`. -/ +def dependency (a : ContinuumIndex) : Set ContinuumIndex := + ⋃ n, ↑(prepared N hN M a n).support + +theorem dependency_countable (a : ContinuumIndex) : + (dependency N hN M a).Countable := by + apply Set.countable_iUnion + intro n + exact (prepared N hN M a n).support.finite_toSet.countable + +/-- Least finite-stage dependency closure of the support of `x`. -/ +def closure (x : ContinuumRationalGroup) : Set ContinuumIndex := + dependencyClosure codeIndex (dependency N hN M) ↑x.support + +theorem support_subset_closure (x : ContinuumRationalGroup) : + ↑x.support ⊆ closure N hN M x := + subset_dependencyClosure codeIndex (dependency N hN M) ↑x.support + +theorem closure_countable (x : ContinuumRationalGroup) : + (closure N hN M x).Countable := by + apply countable_dependencyClosure codeIndex (dependency N hN M) + · exact dependency_countable N hN M + · exact x.support.finite_toSet.countable + +theorem prepared_support_mem_closure (x : ContinuumRationalGroup) + (a : ContinuumIndex) (ha : codeIndex a ∈ closure N hN M x) + (n : ℕ) (i : ContinuumIndex) (hi : i ∈ (prepared N hN M a n).support) : + i ∈ closure N hN M x := by + apply dependency_subset_closure_of_index_mem + codeIndex (dependency N hN M) ↑x.support ha + exact Set.mem_iUnion_of_mem n hi + +theorem closure_closedUnderPreparedSupports (x : ContinuumRationalGroup) : + RationalTransfiniteExtension.ClosedUnderPreparedSupports + (transfiniteData N hN M) (closure N hN M x) := by + intro a ha n i hi + exact prepared_support_mem_closure N hN M x a ha n i hi + +theorem closure_nonempty {x : ContinuumRationalGroup} (hx : x ≠ 0) : + (closure N hN M x).Nonempty := by + obtain ⟨i, hi⟩ := Finsupp.support_nonempty_iff.mpr hx + exact ⟨i, support_subset_closure N hN M x hi⟩ + +/-- A fixed enumeration of the nonempty countable closure. -/ +def enumeration {x : ContinuumRationalGroup} (hx : x ≠ 0) : + ℕ → closure N hN M x := by + letI : Countable (closure N hN M x) := (closure_countable N hN M x).to_subtype + letI : Nonempty (closure N hN M x) := (closure_nonempty N hN M hx).to_subtype + exact Classical.choose (exists_surjective_nat (closure N hN M x)) + +theorem enumeration_surjective {x : ContinuumRationalGroup} (hx : x ≠ 0) : + Function.Surjective (enumeration N hN M hx) := by + letI : Countable (closure N hN M x) := (closure_countable N hN M x).to_subtype + letI : Nonempty (closure N hN M x) := (closure_nonempty N hN M hx).to_subtype + exact Classical.choose_spec (exists_surjective_nat (closure N hN M x)) + +end +end RationalClosure +end Wallace diff --git a/LeanPool/Wallace/RationalData.lean b/LeanPool/Wallace/RationalData.lean new file mode 100644 index 000000000..bbd10fe53 --- /dev/null +++ b/LeanPool/Wallace/RationalData.lean @@ -0,0 +1,129 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.BlockFilters +import LeanPool.Wallace.RationalTransfiniteExtension + +/-! +# Concrete triangular data for the rational direct sum + +This module chooses, uniformly for every coded injective rational sequence, its prepared +subsequence and its free block-density ultrafilter. +-/ + +open Filter Set Topology + +namespace Wallace +namespace RationalData + +noncomputable section + +open RationalTriangularPreprocess +open FiniteCombinatorics + +/-- The canonical continuum index is in bijection with binary streams. -/ +def continuumIndexEquivBinaryStream : ContinuumIndex ≃ (ℕ → Bool) := by + apply Classical.choice + apply Cardinal.eq.mp + rw [mk_continuumIndex, Cardinal.mk_arrow, Cardinal.mk_bool, Cardinal.mk_nat] + simp only [Cardinal.lift_id, Cardinal.two_power_aleph0] + +/-- Almost-disjoint block label assigned to a rational sequence code. -/ +def label (a : ContinuumIndex) : Set ℕ := + binaryBranchOnNat (continuumIndexEquivBinaryStream a) + +theorem label_infinite (a : ContinuumIndex) : (label a).Infinite := + binaryBranchOnNat_infinite _ + +theorem label_inter_finite {a b : ContinuumIndex} (hab : a ≠ b) : + (label a ∩ label b).Finite := by + apply binaryBranchOnNat_inter_finite + exact continuumIndexEquivBinaryStream.injective.ne hab + +theorem label_pairwise : + Pairwise fun a b : ContinuumIndex ↦ (label a ∩ label b).Finite := by + intro a b hab + exact label_inter_finite hab + +variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) + +/-- Strictly increasing selector supplied by rational block preprocessing. -/ +def selector (a : ContinuumIndex) : ℕ → ℕ := + Classical.choose (triangular_block_preprocess a N hN M) + +theorem selector_strictMono (a : ContinuumIndex) : StrictMono (selector N hN M a) := + (Classical.choose_spec (triangular_block_preprocess a N hN M)).1 + +/-- Prepared subsequence represented by code `a`. -/ +def prepared (a : ContinuumIndex) (n : ℕ) : ContinuumRationalGroup := + codedSequence a (selector N hN M a n) + +/-- Shifted finite set in block `l`. -/ +def differenceBlock (a : ContinuumIndex) (l : ℕ) : Finset ContinuumRationalGroup := + (TriangularPreprocess.blockPositions N hN l).image fun n ↦ + prepared N hN M a n - codeBasisVector a + +theorem differenceBlock_boundedIndependent (a : ContinuumIndex) (l : ℕ) : + BoundedIndependent (M l) (differenceBlock N hN M a l) := by + exact (Classical.choose_spec (triangular_block_preprocess a N hN M)).2.1 l |>.2 + +theorem prepared_support_lt (a : ContinuumIndex) (n : ℕ) (i : ContinuumIndex) + (hi : i ∈ (prepared N hN M a n).support) : i < codeIndex a := by + exact (Classical.choose_spec (triangular_block_preprocess a N hN M)).2.2 n i hi + +theorem prepared_injective (a : ContinuumIndex) : + Function.Injective (prepared N hN M a) := + (codedSequence_injective a).comp (selector_strictMono N hN M a).injective + +theorem preparedDifference_injective (a : ContinuumIndex) : + Function.Injective (fun n ↦ prepared N hN M a n - codeBasisVector a) := by + intro m n hmn + apply prepared_injective N hN M a + exact sub_left_injective hmn + +/-- Each shifted rational block has exactly the scheduled cardinality `N l`, as in +Lemma 5.3 of the paper. -/ +theorem differenceBlock_card (a : ContinuumIndex) (l : ℕ) : + (differenceBlock N hN M a l).card = N l := by + rw [differenceBlock, + Finset.card_image_iff.mpr (preparedDifference_injective N hN M a).injOn, + TriangularPreprocess.blockPositions_card] + +theorem differenceBlock_subset_range (a : ContinuumIndex) (l : ℕ) : + ↑(differenceBlock N hN M a l) ⊆ + Set.range (fun n ↦ prepared N hN M a n - codeBasisVector a) := by + intro x hx + simp only [differenceBlock, Finset.mem_coe, Finset.mem_image] at hx + obtain ⟨n, _hn, rfl⟩ := hx + exact Set.mem_range_self n + +abbrev blocks : BlockSystem := BlockSystem.ofBlockPositions N hN + +/-- A free ultrafilter refining the block-density filter for code `a`. -/ +def ultrafilter (a : ContinuumIndex) : Ultrafilter ℕ := + Classical.choose ((blocks N hN).exists_free_ultrafilter_le_densityFilter (label_infinite a)) + +theorem ultrafilter_le_density (a : ContinuumIndex) : + (ultrafilter N hN a : Filter ℕ) ≤ (blocks N hN).densityFilter (label a) := + (Classical.choose_spec + ((blocks N hN).exists_free_ultrafilter_le_densityFilter (label_infinite a))).1 + +theorem ultrafilter_free (a : ContinuumIndex) : + (ultrafilter N hN a : Filter ℕ) ≤ cofinite := + (Classical.choose_spec + ((blocks N hN).exists_free_ultrafilter_le_densityFilter (label_infinite a))).2 + +/-- Concrete input for the rational transfinite recursion. -/ +def transfiniteData : RationalTransfiniteExtension.ContinuumData where + Code := ContinuumIndex + codeIndex := codeIndex + prepared := prepared N hN M + support_lt := prepared_support_lt N hN M + p := ultrafilter N hN + +end +end RationalData +end Wallace diff --git a/LeanPool/Wallace/RationalFusionRun.lean b/LeanPool/Wallace/RationalFusionRun.lean new file mode 100644 index 000000000..07a5fbcd2 --- /dev/null +++ b/LeanPool/Wallace/RationalFusionRun.lean @@ -0,0 +1,267 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.RationalLocalSetup +import LeanPool.Wallace.LocalFusion + +/-! +# The unconditional local fusion for the rational direct sum + +For each nonzero rational vector this module instantiates the generic fusion recursion with the +prepared local blocks, proves the density bound for deleted positions, and packages the +resulting separating, locally admissible character. +-/ + +open Filter Set Topology + +namespace Wallace +namespace RationalFusionRun + +noncomputable section + +open RationalTriangularPreprocess +open RationalData +open RationalClosure +open RationalLocalSetup +open FiniteCombinatorics +open LocalFusion + +abbrev blockSize : ℕ → ℕ := FusionSchedule.blockSize +theorem blockSize_pos (l : ℕ) : 0 < blockSize l := FusionSchedule.blockSize_pos l +abbrev independenceBound : ℕ → ℕ := FusionSchedule.stageIndependenceBound + +abbrev localCarrier (x : ContinuumRationalGroup) : Set ContinuumIndex := + closure blockSize blockSize_pos independenceBound x + +abbrev LocalGroup (x : ContinuumRationalGroup) := localCarrier x →₀ ℚ + +abbrev fresh (x : ContinuumRationalGroup) : ℕ → Finset (LocalGroup x) := + localActiveBlock blockSize blockSize_pos independenceBound x + +theorem localGroup_countable (x : ContinuumRationalGroup) : Countable (LocalGroup x) := by + letI : Countable (localCarrier x) := + (closure_countable blockSize blockSize_pos independenceBound x).to_subtype + infer_instance + +/-- A fixed surjection used to make every local point eventually protected. -/ +def localEnumeration (x : ContinuumRationalGroup) : ℕ → LocalGroup x := by + letI : Countable (localCarrier x) := + (closure_countable blockSize blockSize_pos independenceBound x).to_subtype + exact Classical.choose (exists_surjective_nat (LocalGroup x)) + +theorem localEnumeration_surjective (x : ContinuumRationalGroup) : + Function.Surjective (localEnumeration x) := by + letI : Countable (localCarrier x) := + (closure_countable blockSize blockSize_pos independenceBound x).to_subtype + exact Classical.choose_spec (exists_surjective_nat (LocalGroup x)) + +def distinguished (x : ContinuumRationalGroup) : LocalGroup x := by + classical + exact Finsupp.subtypeDomain (localCarrier x) x + +theorem distinguished_ne_zero {x : ContinuumRationalGroup} (hx : x ≠ 0) : + distinguished x ≠ 0 := by + classical + intro hzero + apply hx + exact (Finsupp.subtypeDomain_eq_zero_iff + (support_subset_closure blockSize blockSize_pos independenceBound x)).mp hzero + +/-- The generic scheduling recursion instantiated on the rational local group. -/ +def scheduledCertificate (x : {x : ContinuumRationalGroup // x ≠ 0}) : + ScheduledRunCertificate (fresh x.1) (distinguished x.1) := + Classical.choice <| exists_scheduledRunCertificate + (fresh x.1) (localEnumeration x.1) (distinguished x.1) + (distinguished_ne_zero x.2) + (localActiveBlock_card_le blockSize blockSize_pos independenceBound x.1) + (localActiveBlock_boundedIndependent blockSize blockSize_pos independenceBound x.1) + (localEnumeration_surjective x.1) + +abbrev run (x : {x : ContinuumRationalGroup // x ≠ 0}) : + FusionRun (LocalGroup x.1) := (scheduledCertificate x).run + +def deletedPositions (x : {x : ContinuumRationalGroup // x ≠ 0}) + (a : RelevantCode blockSize blockSize_pos independenceBound x.1) (l : ℕ) : + Finset ℕ := + (TriangularPreprocess.blockPositions blockSize blockSize_pos l).filter fun n ↦ + localDifference blockSize blockSize_pos independenceBound x.1 a n ∉ (run x).retained l + +theorem deletedPositions_subset_block + (x : {x : ContinuumRationalGroup // x ≠ 0}) + (a : RelevantCode blockSize blockSize_pos independenceBound x.1) (l : ℕ) : + deletedPositions x a l ⊆ TriangularPreprocess.blockPositions blockSize blockSize_pos l := by + intro n hn + exact (Finset.mem_filter.mp hn).1 + +private theorem image_deletedPositions + (x : {x : ContinuumRationalGroup // x ≠ 0}) + (a : RelevantCode blockSize blockSize_pos independenceBound x.1) (l : ℕ) : + (deletedPositions x a l).image + (localDifference blockSize blockSize_pos independenceBound x.1 a) = + localDifferenceBlock blockSize blockSize_pos independenceBound x.1 a l \ + (run x).retained l := by + classical + ext g + constructor + · intro hg + obtain ⟨n, hn, rfl⟩ := Finset.mem_image.mp hg + have hn' := Finset.mem_filter.mp hn + exact Finset.mem_sdiff.mpr ⟨Finset.mem_image_of_mem _ hn'.1, hn'.2⟩ + · intro hg + have hg' := Finset.mem_sdiff.mp hg + obtain ⟨n, hn, hng⟩ := Finset.mem_image.mp hg'.1 + subst g + exact Finset.mem_image.mpr + ⟨n, Finset.mem_filter.mpr ⟨hn, hg'.2⟩, rfl⟩ + +theorem deletedPositions_card_le + (x : {x : ContinuumRationalGroup // x ≠ 0}) + (a : RelevantCode blockSize blockSize_pos independenceBound x.1) (l : ℕ) + (hl : l ∈ refinedLabel blockSize blockSize_pos independenceBound x.1 a) : + (deletedPositions x a l).card ≤ FusionSchedule.protectedBound l := by + classical + let f := localDifference blockSize blockSize_pos independenceBound x.1 a + have hinj : Function.Injective f := + localDifference_injective blockSize blockSize_pos independenceBound x.1 a + calc + (deletedPositions x a l).card = ((deletedPositions x a l).image f).card := by + exact (Finset.card_image_of_injective _ hinj).symm + _ = (localDifferenceBlock blockSize blockSize_pos independenceBound x.1 a l \ + (run x).retained l).card := by rw [image_deletedPositions] + _ = (fresh x.1 l \ (run x).retained l).card := by + change (localDifferenceBlock blockSize blockSize_pos independenceBound x.1 a l \ + (run x).retained l).card = + (localActiveBlock blockSize blockSize_pos independenceBound x.1 l \ + (run x).retained l).card + rw [localActiveBlock_eq_of_mem blockSize blockSize_pos independenceBound x.1 l a hl] + _ ≤ ((run x).guardSet l).card := (scheduledCertificate x).deleted_card_le l + _ ≤ FusionSchedule.protectedBound l := (scheduledCertificate x).guard_card_le l + +theorem retainedPositions_mem_ultrafilter + (x : {x : ContinuumRationalGroup // x ≠ 0}) + (a : RelevantCode blockSize blockSize_pos independenceBound x.1) : + (BlockSystem.ofBlockPositions blockSize blockSize_pos).retainedBlocks + (refinedLabel blockSize blockSize_pos independenceBound x.1 a) + (deletedPositions x a) ∈ ultrafilter blockSize blockSize_pos a.1 := by + apply ultrafilter_le_density blockSize blockSize_pos a.1 + apply BlockSystem.retainedBlocks_mem_densityFilter_ofBlockPositions + blockSize blockSize_pos (deletedPositions x a) FusionSchedule.protectedBound + · exact label_diff_refinedLabel_finite + blockSize blockSize_pos independenceBound x.1 a + · exact deletedPositions_subset_block x a + · exact deletedPositions_card_le x a + · exact FusionSchedule.tendsto_protectedBound_div_blockSize + +/-! ## Rational block and run certificates -/ + +structure RationalCodeBlocks + (x : ContinuumRationalGroup) (R : FusionRun (LocalGroup x)) + (a : RelevantCode blockSize blockSize_pos independenceBound x) where + blocks : R.CodeBlocks + p_eq : blocks.p = ultrafilter blockSize blockSize_pos a.1 + block_eq : ∀ l, blocks.block l = + TriangularPreprocess.blockPositions blockSize blockSize_pos l + difference_eq : ∀ n, + blocks.difference n = localDifference blockSize blockSize_pos independenceBound x a n + +namespace RationalCodeBlocks + +theorem tendsto_prepared + {x : ContinuumRationalGroup} {R : FusionRun (LocalGroup x)} + {a : RelevantCode blockSize blockSize_pos independenceBound x} + (C : RationalCodeBlocks x R a) : + Tendsto + (fun n ↦ R.limitCharacter + (Finsupp.subtypeDomain (localCarrier x) + (prepared blockSize blockSize_pos independenceBound a.1 n))) + (ultrafilter blockSize blockSize_pos a.1) + (nhds (R.limitCharacter (Finsupp.single ⟨codeIndex a.1, a.2⟩ 1))) := by + have hp : (C.blocks.p : Filter ℕ) ≤ cofinite := by + rw [C.p_eq] + exact ultrafilter_free blockSize blockSize_pos a.1 + have hzero := R.tendsto_limit_difference_zero_of_blockPositions + C.blocks blockSize blockSize_pos hp C.block_eq + have hdifference : ∀ n, C.blocks.difference n = + Finsupp.subtypeDomain (localCarrier x) + (prepared blockSize blockSize_pos independenceBound a.1 n) - + Finsupp.single ⟨codeIndex a.1, a.2⟩ 1 := by + intro n + rw [C.difference_eq] + simp only [localDifference] + ext i + change prepared blockSize blockSize_pos independenceBound a.1 n i.val - + codeBasisVector a.1 i.val = + prepared blockSize blockSize_pos independenceBound a.1 n i.val - + Finsupp.single ⟨codeIndex a.1, a.2⟩ 1 i + by_cases hi : i.val = codeIndex a.1 + · have hisub : i = ⟨codeIndex a.1, a.2⟩ := Subtype.ext hi + subst i + simp [codeBasisVector] + · have hisub : i ≠ ⟨codeIndex a.1, a.2⟩ := by + intro heq + exact hi (congrArg Subtype.val heq) + simp [codeBasisVector, hi, hisub] + have hprepared := R.tendsto_limit_prepared C.blocks + (fun n ↦ Finsupp.subtypeDomain (localCarrier x) + (prepared blockSize blockSize_pos independenceBound a.1 n)) + (Finsupp.single ⟨codeIndex a.1, a.2⟩ 1) hdifference hzero + simpa only [C.p_eq] using hprepared + +end RationalCodeBlocks + +structure LocalRunCertificate (x : {x : ContinuumRationalGroup // x ≠ 0}) where + run : FusionRun (LocalGroup x.1) + self_ne_zero : run.limitCharacter (Finsupp.subtypeDomain (localCarrier x.1) x.1) ≠ 0 + codeBlocks : ∀ a : RelevantCode blockSize blockSize_pos independenceBound x.1, + RationalCodeBlocks x.1 run a + +theorem LocalRunCertificate.locallyAdmissible + {x : {x : ContinuumRationalGroup // x ≠ 0}} (C : LocalRunCertificate x) : + RationalTransfiniteExtension.LocallyAdmissible + (transfiniteData blockSize blockSize_pos independenceBound) + (localCarrier x.1) C.run.limitCharacter := by + intro a ha + exact (C.codeBlocks ⟨a, ha⟩).tendsto_prepared + +def codeBlocks (x : {x : ContinuumRationalGroup // x ≠ 0}) + (a : RelevantCode blockSize blockSize_pos independenceBound x.1) : + RationalCodeBlocks x.1 (run x) a where + blocks := { + p := ultrafilter blockSize blockSize_pos a.1 + block := TriangularPreprocess.blockPositions blockSize blockSize_pos + labels := refinedLabel blockSize blockSize_pos independenceBound x.1 a + deletions := deletedPositions x a + difference := localDifference blockSize blockSize_pos independenceBound x.1 a + retained_mem := by + simpa only [BlockSystem.retainedBlocks, BlockSystem.ofBlockPositions_block] using + retainedPositions_mem_ultrafilter x a + retained_in_stage := by + intro l n hl hn + have hnparts := Finset.mem_sdiff.mp hn + by_contra hnot + exact hnparts.2 (Finset.mem_filter.mpr ⟨hnparts.1, hnot⟩) + } + p_eq := rfl + block_eq := fun _ ↦ rfl + difference_eq := fun _ ↦ rfl + +/-- Complete local separating and admissibility certificate. -/ +def localRunCertificate (x : {x : ContinuumRationalGroup // x ≠ 0}) : + LocalRunCertificate x where + run := run x + self_ne_zero := by + apply (run x).limitCharacter_ne_zero_of_initial_half + · exact (scheduledCertificate x).initial_half + · exact (scheduledCertificate x).distinguished_protected + codeBlocks := codeBlocks x + +theorem exists_localRunCertificate + (x : {x : ContinuumRationalGroup // x ≠ 0}) : + Nonempty (LocalRunCertificate x) := ⟨localRunCertificate x⟩ + +end +end RationalFusionRun +end Wallace diff --git a/LeanPool/Wallace/RationalLocalSetup.lean b/LeanPool/Wallace/RationalLocalSetup.lean new file mode 100644 index 000000000..0b8dc3bd3 --- /dev/null +++ b/LeanPool/Wallace/RationalLocalSetup.lean @@ -0,0 +1,305 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.RationalClosure +import LeanPool.Wallace.CountableDisjointization +import LeanPool.Wallace.FusionSchedule +import LeanPool.Wallace.BoundedIndependentMap + +/-! +# The countable block schedule around one rational vector + +Relevant codes are countable. Their almost-disjoint labels are disjointized, so every block +has at most one active code, and its shifted prepared terms form the finite independent set +used by the fusion. +-/ + +open Set + +namespace Wallace +namespace RationalLocalSetup + +noncomputable section + +open RationalTriangularPreprocess +open RationalData +open RationalClosure +open FiniteCombinatorics + +variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) + +abbrev RelevantCode (x : ContinuumRationalGroup) := + {a : ContinuumIndex // codeIndex a ∈ closure N hN M x} + +theorem relevantCode_countable (x : ContinuumRationalGroup) : + Countable (RelevantCode N hN M x) := by + apply Countable.to_subtype + exact countable_preimage_of_injective codeIndex (closure_countable N hN M x) + +private theorem relevantLabels_pairwise (x : ContinuumRationalGroup) : + Pairwise fun a b : RelevantCode N hN M x ↦ + (label a.1 ∩ label b.1).Finite := by + intro a b hab + apply label_inter_finite + intro heq + apply hab + exact Subtype.ext heq + +def refinedLabel (x : ContinuumRationalGroup) : + RelevantCode N hN M x → Set ℕ := by + letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x + exact Classical.choose + (exists_disjoint_refinement_countable + (fun a : RelevantCode N hN M x ↦ label a.1) + (relevantLabels_pairwise N hN M x)) + +theorem refinedLabel_pairwise (x : ContinuumRationalGroup) : + Pairwise fun a b : RelevantCode N hN M x ↦ + Disjoint (refinedLabel N hN M x a) (refinedLabel N hN M x b) := by + letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x + exact (Classical.choose_spec + (exists_disjoint_refinement_countable + (fun a : RelevantCode N hN M x ↦ label a.1) + (relevantLabels_pairwise N hN M x))).1 + +theorem refinedLabel_subset (x : ContinuumRationalGroup) + (a : RelevantCode N hN M x) : + refinedLabel N hN M x a ⊆ label a.1 := by + letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x + exact (Classical.choose_spec + (exists_disjoint_refinement_countable + (fun a : RelevantCode N hN M x ↦ label a.1) + (relevantLabels_pairwise N hN M x))).2 a |>.1 + +theorem label_diff_refinedLabel_finite (x : ContinuumRationalGroup) + (a : RelevantCode N hN M x) : + (label a.1 \ refinedLabel N hN M x a).Finite := by + letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x + exact (Classical.choose_spec + (exists_disjoint_refinement_countable + (fun a : RelevantCode N hN M x ↦ label a.1) + (relevantLabels_pairwise N hN M x))).2 a |>.2 + +theorem refinedLabel_unique (x : ContinuumRationalGroup) {l : ℕ} + {a b : RelevantCode N hN M x} + (ha : l ∈ refinedLabel N hN M x a) + (hb : l ∈ refinedLabel N hN M x b) : a = b := by + by_contra hab + exact Set.disjoint_left.mp (refinedLabel_pairwise N hN M x hab) ha hb + +def activeCode (x : ContinuumRationalGroup) (l : ℕ) : + Option (RelevantCode N hN M x) := by + classical + exact if h : ∃ a, l ∈ refinedLabel N hN M x a then + some (Classical.choose h) else none + +theorem activeCode_eq_some_of_mem (x : ContinuumRationalGroup) (l : ℕ) + (a : RelevantCode N hN M x) (ha : l ∈ refinedLabel N hN M x a) : + activeCode N hN M x l = some a := by + classical + unfold activeCode + split + · rename_i h + congr 1 + exact refinedLabel_unique N hN M x (Classical.choose_spec h) ha + · rename_i h + exact (h ⟨a, ha⟩).elim + +theorem mem_refinedLabel_of_activeCode_eq_some (x : ContinuumRationalGroup) (l : ℕ) + (a : RelevantCode N hN M x) (h : activeCode N hN M x l = some a) : + l ∈ refinedLabel N hN M x a := by + classical + unfold activeCode at h + split at h + · rename_i hex + have hchosen : Classical.choose hex = a := Option.some.inj h + simpa only [hchosen] using Classical.choose_spec hex + · simp at h + +theorem activeCode_eq_some_iff (x : ContinuumRationalGroup) (l : ℕ) + (a : RelevantCode N hN M x) : + activeCode N hN M x l = some a ↔ l ∈ refinedLabel N hN M x a := + ⟨mem_refinedLabel_of_activeCode_eq_some N hN M x l a, + activeCode_eq_some_of_mem N hN M x l a⟩ + +def activeBlock (x : ContinuumRationalGroup) (l : ℕ) : + Finset ContinuumRationalGroup := + match activeCode N hN M x l with + | none => ∅ + | some a => differenceBlock N hN M a.1 l + +theorem activeBlock_eq_of_mem (x : ContinuumRationalGroup) (l : ℕ) + (a : RelevantCode N hN M x) (ha : l ∈ refinedLabel N hN M x a) : + activeBlock N hN M x l = differenceBlock N hN M a.1 l := by + simp [activeBlock, activeCode_eq_some_of_mem N hN M x l a ha] + +theorem activeBlock_boundedIndependent (x : ContinuumRationalGroup) (l : ℕ) : + BoundedIndependent (M l) (activeBlock N hN M x l) := by + unfold activeBlock + split + · simp [BoundedIndependent] + · rename_i a hactive + exact differenceBlock_boundedIndependent N hN M a.1 l + +theorem activeBlock_card_le (x : ContinuumRationalGroup) (l : ℕ) : + (activeBlock N hN M x l).card ≤ N l := by + unfold activeBlock + split + · simp + · rename_i a hactive + calc + (differenceBlock N hN M a.1 l).card ≤ + (TriangularPreprocess.blockPositions N hN l).card := Finset.card_image_le + _ = N l := TriangularPreprocess.blockPositions_card N hN l + +/-! ## The countable local rational group -/ + +def closureInclusion (x : ContinuumRationalGroup) : + (closure N hN M x →₀ ℚ) →+ ContinuumRationalGroup := by + classical + exact Finsupp.embDomain.addMonoidHom + (.subtype (closure N hN M x : ContinuumIndex → Prop)) + +theorem closureInclusion_apply (x : ContinuumRationalGroup) + (z : closure N hN M x →₀ ℚ) : + closureInclusion N hN M x z = + Finsupp.embDomain + (.subtype (closure N hN M x : ContinuumIndex → Prop)) z := by + classical + rfl + +theorem closureInclusion_injective (x : ContinuumRationalGroup) : + Function.Injective (closureInclusion N hN M x) := by + classical + intro y z h + apply Finsupp.embDomain_injective + (.subtype (closure N hN M x : ContinuumIndex → Prop)) + change Finsupp.embDomain + (.subtype (closure N hN M x : ContinuumIndex → Prop)) y = + Finsupp.embDomain + (.subtype (closure N hN M x : ContinuumIndex → Prop)) z at h + exact h + +def localDifference (x : ContinuumRationalGroup) + (a : RelevantCode N hN M x) (n : ℕ) : closure N hN M x →₀ ℚ := by + classical + exact Finsupp.subtypeDomain (closure N hN M x) + (prepared N hN M a.1 n - codeBasisVector a.1) + +private theorem difference_support_subset_closure + (x : ContinuumRationalGroup) (a : RelevantCode N hN M x) (n : ℕ) : + ∀ i ∈ (prepared N hN M a.1 n - codeBasisVector a.1).support, + i ∈ closure N hN M x := by + intro i hi + by_contra hiD + have hprep0 : prepared N hN M a.1 n i = 0 := by + by_contra hne + apply hiD + exact prepared_support_mem_closure N hN M x a.1 a.2 n i + (Finsupp.mem_support_iff.mpr hne) + have hbasis0 : codeBasisVector a.1 i = 0 := by + by_cases hai : codeIndex a.1 = i + · exact (hiD (hai ▸ a.2)).elim + · simp [codeBasisVector, hai] + have hne : (prepared N hN M a.1 n - codeBasisVector a.1) i ≠ 0 := + Finsupp.mem_support_iff.mp hi + exact hne (by simp [hprep0, hbasis0]) + +theorem closureInclusion_localDifference + (x : ContinuumRationalGroup) (a : RelevantCode N hN M x) (n : ℕ) : + closureInclusion N hN M x (localDifference N hN M x a n) = + prepared N hN M a.1 n - codeBasisVector a.1 := by + classical + letI : DecidablePred (closure N hN M x : ContinuumIndex → Prop) := + fun _ ↦ Classical.propDecidable _ + rw [closureInclusion_apply] + change Finsupp.embDomain + (.subtype (closure N hN M x : ContinuumIndex → Prop)) + (Finsupp.subtypeDomain (closure N hN M x) + (prepared N hN M a.1 n - codeBasisVector a.1)) = _ + exact + (Finsupp.extendDomain_eq_embDomain_subtype + (P := (closure N hN M x : ContinuumIndex → Prop)) + (Finsupp.subtypeDomain (closure N hN M x) + (prepared N hN M a.1 n - codeBasisVector a.1))).symm.trans + (Finsupp.extendDomain_subtypeDomain + (prepared N hN M a.1 n - codeBasisVector a.1) + (difference_support_subset_closure N hN M x a n)) + +theorem localDifference_injective (x : ContinuumRationalGroup) + (a : RelevantCode N hN M x) : + Function.Injective (localDifference N hN M x a) := by + intro m n hmn + apply preparedDifference_injective N hN M a.1 + change prepared N hN M a.1 m - codeBasisVector a.1 = + prepared N hN M a.1 n - codeBasisVector a.1 + rw [← closureInclusion_localDifference N hN M x a m, + ← closureInclusion_localDifference N hN M x a n, hmn] + +def localDifferenceBlock (x : ContinuumRationalGroup) + (a : RelevantCode N hN M x) (l : ℕ) : + Finset (closure N hN M x →₀ ℚ) := + (TriangularPreprocess.blockPositions N hN l).image (localDifference N hN M x a) + +theorem localDifferenceBlock_card (x : ContinuumRationalGroup) + (a : RelevantCode N hN M x) (l : ℕ) : + (localDifferenceBlock N hN M x a l).card = N l := by + rw [localDifferenceBlock, + Finset.card_image_iff.mpr (localDifference_injective N hN M x a).injOn, + TriangularPreprocess.blockPositions_card] + +theorem localDifferenceBlock_image_inclusion (x : ContinuumRationalGroup) + (a : RelevantCode N hN M x) (l : ℕ) : + (localDifferenceBlock N hN M x a l).image (closureInclusion N hN M x) = + differenceBlock N hN M a.1 l := by + rw [localDifferenceBlock, differenceBlock, Finset.image_image] + apply Finset.image_congr + intro n hn + exact closureInclusion_localDifference N hN M x a n + +theorem localDifferenceBlock_boundedIndependent (x : ContinuumRationalGroup) + (a : RelevantCode N hN M x) (l : ℕ) : + BoundedIndependent (M l) (localDifferenceBlock N hN M x a l) := by + apply boundedIndependent_of_image (closureInclusion N hN M x) + (closureInclusion_injective N hN M x) + rw [localDifferenceBlock_image_inclusion] + exact differenceBlock_boundedIndependent N hN M a.1 l + +def localActiveBlock (x : ContinuumRationalGroup) (l : ℕ) : + Finset (closure N hN M x →₀ ℚ) := + match activeCode N hN M x l with + | none => ∅ + | some a => localDifferenceBlock N hN M x a l + +theorem localActiveBlock_eq_of_mem (x : ContinuumRationalGroup) (l : ℕ) + (a : RelevantCode N hN M x) (ha : l ∈ refinedLabel N hN M x a) : + localActiveBlock N hN M x l = localDifferenceBlock N hN M x a l := by + simp [localActiveBlock, activeCode_eq_some_of_mem N hN M x l a ha] + +theorem localActiveBlock_boundedIndependent (x : ContinuumRationalGroup) (l : ℕ) : + BoundedIndependent (M l) (localActiveBlock N hN M x l) := by + unfold localActiveBlock + split + · simp [BoundedIndependent] + · rename_i a hactive + exact localDifferenceBlock_boundedIndependent N hN M x a l + +theorem localActiveBlock_card_le (x : ContinuumRationalGroup) (l : ℕ) : + (localActiveBlock N hN M x l).card ≤ N l := by + unfold localActiveBlock + split + · simp + · rename_i a hactive + rw [localDifferenceBlock_card] + +theorem localActiveBlock_card_eq_of_mem (x : ContinuumRationalGroup) (l : ℕ) + (a : RelevantCode N hN M x) (ha : l ∈ refinedLabel N hN M x a) : + (localActiveBlock N hN M x l).card = N l := by + rw [localActiveBlock_eq_of_mem N hN M x l a ha, localDifferenceBlock_card] + +end +end RationalLocalSetup +end Wallace diff --git a/LeanPool/Wallace/RationalTransfiniteExtension.lean b/LeanPool/Wallace/RationalTransfiniteExtension.lean new file mode 100644 index 000000000..7420e9f20 --- /dev/null +++ b/LeanPool/Wallace/RationalTransfiniteExtension.lean @@ -0,0 +1,280 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.RationalTriangularPreprocess +import Mathlib.Algebra.Category.Grp.Injective + +/-! +# Transfinite extension for the rational direct sum + +The recursive datum at a coordinate is an additive homomorphism `ℚ →+ 𝕋`, rather than a +single point of the circle. At a new code coordinate, Baer's extension theorem extends the +homomorphism `n ↦ n • t` from `ℤ` to `ℚ`, where `t` is the compact ultrafilter limit chosen at +that stage. This is the coefficient-sensitive step in the rational construction. +-/ + +open Filter Set Topology + +namespace Wallace +namespace RationalTransfiniteExtension + +noncomputable section + +universe u v + +/-- The minimal triangular input for rational-valued prepared sequences. -/ +structure Data (I : Type u) [LT I] where + Code : Type v + codeIndex : Code ↪ I + prepared : Code → ℕ → I →₀ ℚ + support_lt : ∀ c n i, i ∈ (prepared c n).support → i < codeIndex c + p : Code → Ultrafilter ℕ + +/-- Closure under all supports needed by a code whose distinguished coordinate is local. -/ +def ClosedUnderPreparedSupports {I : Type u} [LT I] (E : Data I) (D : Set I) : Prop := + ∀ c, E.codeIndex c ∈ D → ∀ n i, i ∈ (E.prepared c n).support → i ∈ D + +/-- The local character already realizes every limit whose code coordinate belongs to `D`. -/ +def LocallyAdmissible {I : Type u} [LT I] (E : Data I) (D : Set I) + (χD : (D →₀ ℚ) →+ UnitAddCircle) : Prop := + ∀ (c : E.Code) (hc : E.codeIndex c ∈ D), + Tendsto (fun n ↦ χD (Finsupp.subtypeDomain D (E.prepared c n))) (E.p c) + (nhds (χD (Finsupp.single ⟨E.codeIndex c, hc⟩ 1))) + +/-! ## Extending one rational coordinate -/ + +/-- The integer character with prescribed value at one. -/ +def integerCircleHom (t : UnitAddCircle) : ℤ →+ UnitAddCircle := + (zmultiplesHom UnitAddCircle) t + +theorem intCastAddHom_rational_injective : + Function.Injective (Int.castAddHom ℚ) := by + intro m n h + exact Rat.intCast_injective h + +/-- An additive homomorphism on `ℚ` extending `n ↦ n • t` on `ℤ`. + +Only its value at `1` is constrained at the current stage; the chosen full homomorphism is then +used coherently when later prepared sequences are evaluated. -/ +def extendRationalCoordinate (t : UnitAddCircle) : ℚ →+ UnitAddCircle := + Classical.choose <| + (Module.Baer.of_divisible UnitAddCircle).extension_property_addMonoidHom + (Int.castAddHom ℚ) intCastAddHom_rational_injective (integerCircleHom t) + +theorem extendRationalCoordinate_comp_intCast (t : UnitAddCircle) : + (extendRationalCoordinate t).comp (Int.castAddHom ℚ) = integerCircleHom t := + Classical.choose_spec <| + (Module.Baer.of_divisible UnitAddCircle).extension_property_addMonoidHom + (Int.castAddHom ℚ) intCastAddHom_rational_injective (integerCircleHom t) + +@[simp] +theorem extendRationalCoordinate_one (t : UnitAddCircle) : + extendRationalCoordinate t 1 = t := by + have h := DFunLike.congr_fun (extendRationalCoordinate_comp_intCast t) 1 + simpa [integerCircleHom] using h + +/-! ## Evaluation below a recursive stage -/ + +/-- The homomorphism out of a rational direct sum determined coordinatewise. -/ +def rationalFinsuppAddHom {I : Type u} + (θ : I → (ℚ →+ UnitAddCircle)) : (I →₀ ℚ) →+ UnitAddCircle := + Finsupp.liftAddHom θ + +@[simp] +theorem rationalFinsuppAddHom_single {I : Type u} + (θ : I → (ℚ →+ UnitAddCircle)) (i : I) (q : ℚ) : + rationalFinsuppAddHom θ (Finsupp.single i q) = θ i q := by + simp [rationalFinsuppAddHom] + +/-- Totalize the coordinate homomorphisms already available below `i`. -/ +def stageCoordinates {I : Type u} [LT I] [DecidableRel ((· < ·) : I → I → Prop)] + (i : I) (previous : ∀ j, j < i → (ℚ →+ UnitAddCircle)) : + I → (ℚ →+ UnitAddCircle) := + fun j ↦ if h : j < i then previous j h else 0 + +/-- Evaluate a prepared term using only coordinates below the current stage. -/ +def stageEvaluation {I : Type u} [LT I] [DecidableRel ((· < ·) : I → I → Prop)] + (E : Data I) (i : I) + (previous : ∀ j, j < i → (ℚ →+ UnitAddCircle)) + (c : E.Code) (n : ℕ) : UnitAddCircle := + rationalFinsuppAddHom (stageCoordinates i previous) (E.prepared c n) + +/-- Compact ultrafilter limit selected at a code coordinate. -/ +def compactStageLimit {I : Type u} [LT I] [DecidableRel ((· < ·) : I → I → Prop)] + (E : Data I) (i : I) + (previous : ∀ j, j < i → (ℚ →+ UnitAddCircle)) + (c : E.Code) : UnitAddCircle := + (Ultrafilter.map (stageEvaluation E i previous c) (E.p c)).lim + +theorem rationalFinsuppAddHom_eq_of_eq_on_support {I : Type u} + {z w : I → (ℚ →+ UnitAddCircle)} {x : I →₀ ℚ} + (h : ∀ i ∈ x.support, z i = w i) : + rationalFinsuppAddHom z x = rationalFinsuppAddHom w x := by + simp only [rationalFinsuppAddHom, Finsupp.liftAddHom_apply] + apply Finsupp.sum_congr + intro i hi + rw [h i hi] + +/-! ## Well-founded construction -/ + +/-- One step of the coordinate recursion. -/ +def coordinateStep {I : Type u} [LinearOrder I] (E : Data I) (D : Set I) + (χD : (D →₀ ℚ) →+ UnitAddCircle) (i : I) + (previous : ∀ j, j < i → (ℚ →+ UnitAddCircle)) : + ℚ →+ UnitAddCircle := by + classical + exact if hi : i ∈ D then + χD.comp (Finsupp.singleAddHom ⟨i, hi⟩) + else if hcode : ∃ c : E.Code, E.codeIndex c = i then + extendRationalCoordinate + (compactStageLimit E i previous (Classical.choose hcode)) + else + 0 + +/-- The recursively constructed additive homomorphism on each rational coordinate. -/ +def globalCoordinate {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) : + I → (ℚ →+ UnitAddCircle) := + WellFoundedLT.fix fun i previous ↦ coordinateStep E D χD i previous + +theorem globalCoordinate_eq {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) (i : I) : + globalCoordinate E D χD i = + coordinateStep E D χD i (fun j _ ↦ globalCoordinate E D χD j) := by + rw [globalCoordinate, WellFoundedLT.fix_eq] + +theorem globalCoordinate_of_mem {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) + {i : I} (hi : i ∈ D) : + globalCoordinate E D χD i = χD.comp (Finsupp.singleAddHom ⟨i, hi⟩) := by + rw [globalCoordinate_eq] + simp [coordinateStep, hi] + +theorem globalCoordinate_codeIndex_of_not_mem + {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) + (c : E.Code) (hc : E.codeIndex c ∉ D) : + globalCoordinate E D χD (E.codeIndex c) = + extendRationalCoordinate + (compactStageLimit E (E.codeIndex c) + (fun j _ ↦ globalCoordinate E D χD j) c) := by + rw [globalCoordinate_eq] + simp only [coordinateStep, hc, dite_false] + let hex : ∃ d : E.Code, E.codeIndex d = E.codeIndex c := ⟨c, rfl⟩ + rw [dif_pos hex] + have hchosen : Classical.choose hex = c := by + apply E.codeIndex.injective + exact Classical.choose_spec hex + rw [hchosen] + +/-! ## Global character, extension, and admissibility -/ + +def globalCharacter {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) : + (I →₀ ℚ) →+ UnitAddCircle := + rationalFinsuppAddHom (globalCoordinate E D χD) + +@[simp] +theorem globalCharacter_single {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) + (i : I) (q : ℚ) : + globalCharacter E D χD (Finsupp.single i q) = globalCoordinate E D χD i q := by + simp [globalCharacter] + +theorem globalCharacter_extendDomain {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) + (x : D →₀ ℚ) : + globalCharacter E D χD (Finsupp.embDomain (.subtype D) x) = χD x := by + let inclusion : (D →₀ ℚ) →+ (I →₀ ℚ) := + Finsupp.embDomain.addMonoidHom (.subtype (D : I → Prop)) + have hhom : (globalCharacter E D χD).comp inclusion = χD := by + apply Finsupp.addHom_ext + intro i q + rcases i with ⟨i, hi⟩ + change globalCharacter E D χD + (Finsupp.embDomain (.subtype (D : I → Prop)) (Finsupp.single ⟨i, hi⟩ q)) = + χD (Finsupp.single ⟨i, hi⟩ q) + rw [Finsupp.embDomain_single, globalCharacter_single] + have hcoord := globalCoordinate_of_mem E D χD (i := i) hi + have happly := DFunLike.congr_fun hcoord q + change globalCoordinate E D χD i q = χD (Finsupp.single ⟨i, hi⟩ q) + simpa only [AddMonoidHom.comp_apply, Finsupp.singleAddHom_apply] using happly + exact DFunLike.congr_fun hhom x + +theorem globalCharacter_eq_local_restriction {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) + (x : I →₀ ℚ) (hx : ∀ i ∈ x.support, i ∈ D) : + globalCharacter E D χD x = χD (Finsupp.subtypeDomain D x) := by + have hxrange : (↑x.support : Set I) ⊆ Set.range (Function.Embedding.subtype D) := by + intro i hi + exact ⟨⟨i, hx i hi⟩, rfl⟩ + obtain ⟨y, rfl⟩ := + (Finsupp.mem_range_embDomain_iff (Function.Embedding.subtype D) x).2 hxrange + rw [globalCharacter_extendDomain E D χD y] + congr 1 + ext i + exact (Finsupp.embDomain_apply_self (Function.Embedding.subtype D) y i).symm + +theorem stageEvaluation_eq_globalCharacter + {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) + (c : E.Code) (n : ℕ) : + stageEvaluation E (E.codeIndex c) + (fun j _ ↦ globalCoordinate E D χD j) c n = + globalCharacter E D χD (E.prepared c n) := by + apply rationalFinsuppAddHom_eq_of_eq_on_support + intro i hi + simp [stageCoordinates, E.support_lt c n i hi] + +theorem tendsto_stageEvaluation_compactLimit + {I : Type u} [LinearOrder I] (E : Data I) (i : I) + (previous : ∀ j, j < i → (ℚ →+ UnitAddCircle)) (c : E.Code) : + Tendsto (stageEvaluation E i previous c) (E.p c) + (nhds (compactStageLimit E i previous c)) := by + exact (Ultrafilter.map (stageEvaluation E i previous c) (E.p c)).le_nhds_lim + +/-- The rational transfinite extension realizes every prescribed ultrafilter limit. -/ +theorem globalCharacter_admissible + {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) + (hclosed : ClosedUnderPreparedSupports E D) + (hlocal : LocallyAdmissible E D χD) : + ∀ c : E.Code, + Tendsto (fun n ↦ globalCharacter E D χD (E.prepared c n)) (E.p c) + (nhds (globalCharacter E D χD (Finsupp.single (E.codeIndex c) 1))) := by + intro c + by_cases hc : E.codeIndex c ∈ D + · have heval : + (fun n ↦ globalCharacter E D χD (E.prepared c n)) = + (fun n ↦ χD (Finsupp.subtypeDomain D (E.prepared c n))) := by + funext n + exact globalCharacter_eq_local_restriction E D χD (E.prepared c n) + (hclosed c hc n) + have hbasis : + globalCharacter E D χD (Finsupp.single (E.codeIndex c) 1) = + χD (Finsupp.single ⟨E.codeIndex c, hc⟩ 1) := by + rw [globalCharacter_single, globalCoordinate_of_mem E D χD hc] + rfl + rw [heval, hbasis] + exact hlocal c hc + · have hlim := tendsto_stageEvaluation_compactLimit E (E.codeIndex c) + (fun j _ ↦ globalCoordinate E D χD j) c + have heval : + (fun n ↦ globalCharacter E D χD (E.prepared c n)) = + stageEvaluation E (E.codeIndex c) + (fun j _ ↦ globalCoordinate E D χD j) c := by + funext n + exact (stageEvaluation_eq_globalCharacter E D χD c n).symm + rw [heval, globalCharacter_single, + globalCoordinate_codeIndex_of_not_mem E D χD c hc, + extendRationalCoordinate_one] + exact hlim + +abbrev ContinuumData := Data RationalTriangularPreprocess.ContinuumIndex + +end +end RationalTransfiniteExtension +end Wallace diff --git a/LeanPool/Wallace/RationalTriangularPreprocess.lean b/LeanPool/Wallace/RationalTriangularPreprocess.lean new file mode 100644 index 000000000..49c8ea96f --- /dev/null +++ b/LeanPool/Wallace/RationalTriangularPreprocess.lean @@ -0,0 +1,173 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.TriangularPreprocess +import Mathlib.Data.Rat.Cardinal + +/-! +# Triangular preprocessing for the rational direct sum + +This module repeats only the coefficient-dependent part of the triangular bookkeeping for +`ContinuumIndex →₀ ℚ`. It enumerates all injective rational sequences, assigns each code a +fresh coordinate strictly above the support of its sequence, and applies the generic bounded +independence selector from `Wallace.TriangularPreprocess`. + +No topology or character is assumed. +-/ + +open Set +open scoped Cardinal + +namespace Wallace +namespace RationalTriangularPreprocess + +noncomputable section + +open FiniteCombinatorics + +abbrev ContinuumIndex := TriangularPreprocess.ContinuumIndex + +/-- The direct sum of continuum many copies of the additive group of rationals. -/ +abbrev ContinuumRationalGroup := ContinuumIndex →₀ ℚ + +/-- All injective sequences in the rational direct sum. -/ +abbrev RationalInjectiveSequences := + {s : ℕ → ContinuumRationalGroup // Function.Injective s} + +/-- The triangular support condition for rational-valued finitely supported sequences. -/ +def RationalSupportedBelow (s : ℕ → ContinuumRationalGroup) (i : ContinuumIndex) : Prop := + ∀ n j, j ∈ (s n).support → j < i + +@[simp] +theorem mk_continuumIndex : #ContinuumIndex = 𝔠 := + TriangularPreprocess.mk_continuumIndex + +theorem continuumIndex_infinite : Infinite ContinuumIndex := + TriangularPreprocess.continuumIndex_infinite + +theorem mk_continuumRationalGroup : #ContinuumRationalGroup = 𝔠 := by + letI : Infinite ContinuumIndex := continuumIndex_infinite + change #(ContinuumIndex →₀ ℚ) = 𝔠 + rw [Cardinal.mk_finsupp_of_infinite, mk_continuumIndex, Cardinal.mkRat] + exact max_eq_left Cardinal.aleph0_le_continuum + +theorem mk_continuumRationalGroup_sequences : + #(ℕ → ContinuumRationalGroup) = 𝔠 := by + rw [Cardinal.mk_arrow, mk_continuumRationalGroup, Cardinal.mk_nat] + simpa only [Cardinal.lift_id] using Cardinal.continuum_power_aleph0 + +/-- An injective ray in a rational basis coordinate. -/ +def rationalBasisRay (i : ContinuumIndex) (n : ℕ) : ContinuumRationalGroup := + Finsupp.single i (n : ℚ) + +theorem rationalBasisRay_injective (i : ContinuumIndex) : + Function.Injective (rationalBasisRay i) := by + intro m n h + have hi := congrArg (fun z : ContinuumRationalGroup => z i) h + exact_mod_cast (by simpa [rationalBasisRay] using hi) + +theorem rationalBasisRay_family_injective : + Function.Injective (fun i : ContinuumIndex => + (⟨rationalBasisRay i, rationalBasisRay_injective i⟩ : RationalInjectiveSequences)) := by + intro i j hij + have hfun : rationalBasisRay i = rationalBasisRay j := congrArg Subtype.val hij + have hi := congrArg (fun s : ℕ → ContinuumRationalGroup => s 1 i) hfun + by_contra hne + simp [rationalBasisRay, hne] at hi + +theorem mk_rationalInjectiveSequences : #RationalInjectiveSequences = 𝔠 := by + apply le_antisymm + · exact (Cardinal.mk_subtype_le _).trans_eq mk_continuumRationalGroup_sequences + · rw [← mk_continuumIndex] + exact Cardinal.mk_le_of_injective rationalBasisRay_family_injective + +/-- A fixed enumeration of every injective rational sequence. -/ +def rationalSequenceCodeEquiv : ContinuumIndex ≃ RationalInjectiveSequences := + Classical.choice <| Cardinal.eq.mp <| + mk_continuumIndex.trans mk_rationalInjectiveSequences.symm + +def codedSequence (a : ContinuumIndex) : ℕ → ContinuumRationalGroup := + (rationalSequenceCodeEquiv a).1 + +theorem codedSequence_injective (a : ContinuumIndex) : + Function.Injective (codedSequence a) := + (rationalSequenceCodeEquiv a).2 + +theorem codedSequence_code_injective : Function.Injective codedSequence := by + intro a b hab + apply rationalSequenceCodeEquiv.injective + exact Subtype.ext hab + +/-- The union of the finite supports of a rational sequence. -/ +def sequenceSupport (s : ℕ → ContinuumRationalGroup) : Set ContinuumIndex := + {i | ∃ n, i ∈ (s n).support} + +theorem sequenceSupport_countable (s : ℕ → ContinuumRationalGroup) : + (sequenceSupport s).Countable := by + rw [show sequenceSupport s = ⋃ n, ((s n).support : Set ContinuumIndex) by + ext i + simp [sequenceSupport]] + exact Set.countable_iUnion fun n => (s n).support.finite_toSet.countable + +/-- A strict bound for every coordinate occurring in the coded sequence. -/ +def supportBound (a : ContinuumIndex) : ContinuumIndex := + Classical.choose <| TriangularPreprocess.exists_strict_upperBound_of_countable + (sequenceSupport_countable (codedSequence a)) + +theorem support_lt_supportBound (a : ContinuumIndex) {n : ℕ} {i : ContinuumIndex} + (hi : i ∈ (codedSequence a n).support) : i < supportBound a := by + exact (Classical.choose_spec <| + TriangularPreprocess.exists_strict_upperBound_of_countable + (sequenceSupport_countable (codedSequence a))) i ⟨n, hi⟩ + +/-- The fresh-coordinate embedding for rational sequence codes. -/ +def codeIndex : ContinuumIndex ↪ ContinuumIndex := + ⟨TriangularPreprocess.freshIndex supportBound, + TriangularPreprocess.freshIndex_injective supportBound⟩ + +theorem codedSequence_supportedBelow (a : ContinuumIndex) : + RationalSupportedBelow (codedSequence a) (codeIndex a) := by + intro n i hi + exact (support_lt_supportBound a hi).trans + (TriangularPreprocess.freshIndex_spec supportBound a).1 + +/-- The rational basis point assigned to a code. -/ +def codeBasisVector (a : ContinuumIndex) : ContinuumRationalGroup := + Finsupp.single (codeIndex a) 1 + +/-- The translated sequence used for bounded-independence preprocessing. -/ +def codedDifference (a : ContinuumIndex) (n : ℕ) : ContinuumRationalGroup := + codedSequence a n - codeBasisVector a + +theorem codedDifference_injective (a : ContinuumIndex) : + Function.Injective (codedDifference a) := by + intro m n hmn + apply codedSequence_injective a + have h := congrArg (fun z => z + codeBasisVector a) hmn + simpa [codedDifference] using h + +/-- Full block preprocessing for rational sequences. -/ +theorem triangular_block_preprocess + (a : ContinuumIndex) + (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) : + ∃ φ : ℕ → ℕ, StrictMono φ ∧ + (∀ l, (TriangularPreprocess.blockPositions N hN l).card = N l ∧ + BoundedIndependent (M l) + ((TriangularPreprocess.blockPositions N hN l).image fun n => + codedSequence a (φ n) - codeBasisVector a)) ∧ + RationalSupportedBelow (codedSequence a ∘ φ) (codeIndex a) := by + obtain ⟨φ, hφ, hblocks⟩ := + TriangularPreprocess.exists_boundedIndependent_subsequence_for_sizes + (codedDifference a) (codedDifference_injective a) N hN M + refine ⟨φ, hφ, ?_, ?_⟩ + · simpa only [codedDifference] using hblocks + · intro n i hi + exact codedSequence_supportedBelow a (φ n) i hi + +end + +end RationalTriangularPreprocess +end Wallace diff --git a/LeanPool/Wallace/RealMain.lean b/LeanPool/Wallace/RealMain.lean new file mode 100644 index 000000000..3a49cc842 --- /dev/null +++ b/LeanPool/Wallace/RealMain.lean @@ -0,0 +1,59 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.GeneralMain +import Mathlib.LinearAlgebra.Complex.FiniteDimensional + +/-! +# The rational proposition on the additive group of real numbers + +The paper writes `ℚ^(𝔠) ≅ ℝ`. This module formalizes that algebraic identification using the +rational Hamel dimension of `ℝ`, then transports the fully constructed character package rather +than merely asserting that a suitable topology can be transferred. +-/ + +open Cardinal Module + +namespace Wallace + +noncomputable section + +open RationalTriangularPreprocess + +theorem rank_continuumRationalGroup : + Module.rank ℚ ContinuumRationalGroup = 𝔠 := by + rw [rank_finsupp_self', TriangularPreprocess.mk_continuumIndex] + +/-- A rational-linear equivalence `ℚ^(𝔠) ≃ₗ[ℚ] ℝ`. -/ +def continuumRationalGroupLinearEquivReal : ContinuumRationalGroup ≃ₗ[ℚ] ℝ := + Classical.choice <| nonempty_linearEquiv_of_rank_eq <| by + rw [rank_continuumRationalGroup, Real.rank_rat_real] + +/-- The algebraic isomorphism explicitly invoked in the paper's rational proposition. -/ +def continuumRationalGroupAddEquivReal : ContinuumRationalGroup ≃+ ℝ := + continuumRationalGroupLinearEquivReal.toAddEquiv + +/-- The concrete rational character package transported to the additive group of real numbers. -/ +def realFullCharacterPackage : FullCharacterPackage ℝ := + RationalAssembly.fullCharacterPackage.comapAddEquiv + continuumRationalGroupAddEquivReal.symm + +/-- **Rational proposition of the paper, in its literal real-group form.** The additive group +of real numbers admits a Hausdorff countably compact group topology in which every convergent +sequence is eventually constant. -/ +theorem realAdditiveGroup_mainTheorem : HasMainGroupTopology ℝ := + realFullCharacterPackage.hasMainGroupTopology + +/-- A single declaration recording both presentations used in the paper, +`ℚ^(𝔠)` and the additively isomorphic group `ℝ`. -/ +theorem continuumRationalGroup_and_real_mainTheorem : + HasMainGroupTopology ContinuumRationalGroup ∧ HasMainGroupTopology ℝ := + ⟨RationalAssembly.continuumRationalGroup_mainTheorem, + realAdditiveGroup_mainTheorem⟩ + +end + +end Wallace diff --git a/LeanPool/Wallace/Result.lean b/LeanPool/Wallace/Result.lean new file mode 100644 index 000000000..e41866c2f --- /dev/null +++ b/LeanPool/Wallace/Result.lean @@ -0,0 +1,249 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import Mathlib.Algebra.Group.Finsupp +import Mathlib.Algebra.Group.Units.Defs +import Mathlib.Data.Real.Basic +import Mathlib.Order.Filter.Ultrafilter.Basic +import Mathlib.Topology.Algebra.Group.Basic +import Mathlib.Topology.Compactness.CountablyCompact + +/-! +# The Wallace semigroup deduction + +This file formalizes Section 9, the final deduction of the Wallace-semigroup corollary in the +current paper under `paper/`. + +The paper constructs a Hausdorff group topology on the free Abelian group and proves a +free-ultrafilter subsequence limit property. Here that output is named +`HasWallaceLimitProperty`. We prove from it that the nonnegative cone is Hausdorff, countably +compact, cancellative on both sides, a topological semigroup, and not a group. + +Every declaration in this file is proved from its explicitly stated hypotheses. +-/ + +open Filter Set Topology + +universe u + +namespace Wallace + +/-- The precise additive form of a Hausdorff Wallace semigroup. + +The final conjunct says that the additive monoid has a noninvertible element, hence is not a +group. An additive monoid is used rather than a bare semigroup because the counterexample in the +paper is the nonnegative cone and contains zero. -/ +def IsWallaceSemigroup (S : Type u) [TopologicalSpace S] [AddMonoid S] : Prop := + ContinuousAdd S ∧ IsCancelAdd S ∧ T2Space S ∧ CountablyCompactSpace S ∧ + ∃ x : S, ¬ IsAddUnit x + +/-- The existential statement of the Wallace counterexample, bundled with its topology and +additive monoid structure. -/ +def WallaceCounterexampleExists : Prop := + ∃ (S : Type) (topology : TopologicalSpace S) (monoid : AddMonoid S), + @IsWallaceSemigroup S topology monoid + +/-- A convenient unbundled form of the accumulation-point criterion used for countable +compactness. -/ +def HasInfiniteSetAccumulationProperty + (X : Type u) [TopologicalSpace X] : Prop := + ∀ B : Set X, B.Infinite → ∃ x : X, AccPt x (Filter.principal B) + +/-- In a T1 space, the accumulation-point property implies countable compactness. + +This invokes mathlib's standard equivalence +`isCountablyCompact_iff_infinite_subset_has_accPt`; it is not a custom compactness notion. -/ +theorem countablyCompact_of_infiniteSet_accumulation + {X : Type u} [TopologicalSpace X] [T1Space X] + (hacc : HasInfiniteSetAccumulationProperty X) : + CountablyCompactSpace X := by + rw [← isCountablyCompact_univ_iff] + refine isCountablyCompact_iff_infinite_subset_has_accPt.2 ?_ + intro B _hB hBinf + obtain ⟨x, hx⟩ := hacc B hBinf + exact ⟨x, Set.mem_univ x, hx⟩ + +/-- An injective sequence converging along a free ultrafilter has its limit as an accumulation +point of its range. -/ +theorem accPt_range_of_free_ultrafilter_limit + {X : Type u} [TopologicalSpace X] + {h : ℕ → X} {p : Ultrafilter ℕ} {x : X} + (hinj : Function.Injective h) + (hfree : (p : Filter ℕ) ≤ cofinite) + (htendsto : Tendsto h p (𝓝 x)) : + AccPt x (Filter.principal (Set.range h)) := by + have hcluster : MapClusterPt x cofinite h := htendsto.mapClusterPt.mono hfree + refine accPt_iff_clusterPt.2 <| ClusterPt.mono hcluster <| le_inf ?_ ?_ + · exact tendsto_principal.mpr + ((Set.finite_singleton x).preimage hinj.injOn).compl_mem_cofinite + · exact tendsto_principal.mpr <| Eventually.of_forall fun n => ⟨n, rfl⟩ + +/-- The exact part of the paper's construction used by the Wallace corollary. + +Every injective sequence contained in `P` has a genuine subsequence (`StrictMono φ`) converging +to a point of `P` along a free ultrafilter. -/ +def HasWallaceLimitProperty + {F : Type u} [TopologicalSpace F] [AddZeroClass F] + (P : AddSubmonoid F) : Prop := + ∀ s : ℕ → F, Function.Injective s → (∀ n, s n ∈ P) → + ∃ (φ : ℕ → ℕ) (x : F) (p : Ultrafilter ℕ), + StrictMono φ ∧ x ∈ P ∧ (p : Filter ℕ) ≤ cofinite ∧ + Tendsto (s ∘ φ) p (𝓝 x) + +/-- A limit in the ambient space is also a limit in a subspace when the sequence and its limit +lie in that subspace. -/ +theorem tendsto_subtype_of_tendsto + {X : Type u} [TopologicalSpace X] {P : Set X} {p : Filter ℕ} + {u : ℕ → X} {x : X} + (hu : ∀ n, u n ∈ P) (hx : x ∈ P) + (htendsto : Tendsto u p (𝓝 x)) : + Tendsto (fun n => (⟨u n, hu n⟩ : P)) p (𝓝 (⟨x, hx⟩ : P)) := by + rw [Topology.IsInducing.subtypeVal.tendsto_nhds_iff] + exact htendsto + +/-- The paper's free-ultrafilter limit property gives the accumulation-point property on the +subspace `P`. -/ +theorem infiniteSet_accumulation_of_wallaceLimitProperty + {F : Type u} [TopologicalSpace F] [AddZeroClass F] + (P : AddSubmonoid F) + (hlimits : HasWallaceLimitProperty (F := F) P) : + HasInfiniteSetAccumulationProperty P := by + intro B hBinf + let e : ℕ ↪ B := hBinf.natEmbedding + let eP : ℕ → P := fun n => (e n : P) + let s : ℕ → F := fun n => eP n + have ePinj : Function.Injective eP := + Subtype.val_injective.comp e.injective + have sinj : Function.Injective s := + Subtype.val_injective.comp ePinj + have hsmem : ∀ n, s n ∈ P := fun n => (eP n).property + obtain ⟨φ, x, p, hφ, hx, hfree, htendsto⟩ := hlimits s sinj hsmem + let u : ℕ → P := fun n => ⟨s (φ n), hsmem (φ n)⟩ + have uinj : Function.Injective u := + ePinj.comp hφ.injective + have utendsto : Tendsto u p (𝓝 (⟨x, hx⟩ : P)) := by + exact tendsto_subtype_of_tendsto (fun n => hsmem (φ n)) hx htendsto + have hacc : AccPt (⟨x, hx⟩ : P) (Filter.principal (Set.range u)) := + accPt_range_of_free_ultrafilter_limit uinj hfree utendsto + refine ⟨⟨x, hx⟩, hacc.mono <| Filter.principal_mono.2 ?_⟩ + intro y hy + obtain ⟨n, rfl⟩ := hy + change eP (φ n) ∈ B + exact (e (φ n)).property + +/-- The algebraic witness `a ∈ P`, `-a ∉ P` is not an additive unit of the cone. -/ +theorem not_isAddUnit_of_neg_not_mem + {F : Type u} [AddCommGroup F] (P : AddSubmonoid F) + {a : F} (ha : a ∈ P) (hneg : -a ∉ P) : + ¬ IsAddUnit (⟨a, ha⟩ : P) := by + intro hunit + obtain ⟨b, hab⟩ := hunit.exists_neg + have habF : a + (b : F) = 0 := congrArg Subtype.val hab + apply hneg + rw [← eq_neg_of_add_eq_zero_right habF] + exact b.property + +/-- A countably compact additive submonoid `P` of a Hausdorff Abelian group with continuous +addition is a Wallace semigroup whenever `a ∈ P` and `-a ∉ P` for some `a`. -/ +theorem addSubmonoid_isWallace + {F : Type u} [TopologicalSpace F] [AddCommGroup F] + [ContinuousAdd F] [T2Space F] + (P : AddSubmonoid F) + (hcompact : CountablyCompactSpace P) + {a : F} (ha : a ∈ P) (hneg : -a ∉ P) : + IsWallaceSemigroup P := by + letI : CountablyCompactSpace P := hcompact + refine ⟨inferInstance, inferInstance, inferInstance, inferInstance, ?_⟩ + exact ⟨⟨a, ha⟩, not_isAddUnit_of_neg_not_mem P ha hneg⟩ + +/-- The Wallace conclusion from the exact accumulation-point hypothesis. -/ +theorem addSubmonoid_isWallace_of_accumulation + {F : Type u} [TopologicalSpace F] [AddCommGroup F] + [ContinuousAdd F] [T2Space F] + (P : AddSubmonoid F) + (hacc : HasInfiniteSetAccumulationProperty P) + {a : F} (ha : a ∈ P) (hneg : -a ∉ P) : + IsWallaceSemigroup P := + addSubmonoid_isWallace P + (countablyCompact_of_infiniteSet_accumulation hacc) ha hneg + +/-- The Wallace conclusion from the free-ultrafilter limit property proved in the paper. -/ +theorem addSubmonoid_isWallace_of_limitProperty + {F : Type u} [TopologicalSpace F] [AddCommGroup F] + [ContinuousAdd F] [T2Space F] + (P : AddSubmonoid F) + (hlimits : HasWallaceLimitProperty (F := F) P) + {a : F} (ha : a ∈ P) (hneg : -a ∉ P) : + IsWallaceSemigroup P := + addSubmonoid_isWallace_of_accumulation P + (infiniteSet_accumulation_of_wallaceLimitProperty P hlimits) ha hneg + +/-- The coordinatewise nonnegative cone in the free Abelian group `ι →₀ ℤ`. -/ +def positiveCone (ι : Type u) : AddSubmonoid (ι →₀ ℤ) where + carrier := {x | ∀ i, 0 ≤ x i} + zero_mem' i := by simp + add_mem' hx hy i := add_nonneg (hx i) (hy i) + +theorem single_one_mem_positiveCone (ι : Type u) (i : ι) : + Finsupp.single i (1 : ℤ) ∈ positiveCone ι := by + classical + intro j + by_cases hij : i = j + · subst j + simp + · rw [Finsupp.single_eq_of_ne (Ne.symm hij)] + +theorem neg_single_one_not_mem_positiveCone (ι : Type u) (i : ι) : + -Finsupp.single i (1 : ℤ) ∉ positiveCone ι := by + intro h + have hi := h i + simp at hi + +/-- The formalized Wallace deduction for a free Abelian group: if the topology has the exact +free-ultrafilter limit property constructed by the paper, its nonnegative cone is a Wallace +semigroup. -/ +theorem positiveCone_isWallace_of_limitProperty + (ι : Type u) [TopologicalSpace (ι →₀ ℤ)] + [IsTopologicalAddGroup (ι →₀ ℤ)] [T2Space (ι →₀ ℤ)] + (i : ι) + (hlimits : HasWallaceLimitProperty (F := ι →₀ ℤ) (positiveCone ι)) : + IsWallaceSemigroup (positiveCone ι) := + addSubmonoid_isWallace_of_limitProperty (positiveCone ι) hlimits + (single_one_mem_positiveCone ι i) (neg_single_one_not_mem_positiveCone ι i) + +/-- A concrete index type of cardinality continuum for the free Abelian group in the paper. -/ +abbrev ContinuumFreeAbelianGroup := ℝ →₀ ℤ + +/-- The nonnegative cone in the free Abelian group indexed by the continuum. -/ +abbrev continuumPositiveCone : AddSubmonoid ContinuumFreeAbelianGroup := + positiveCone ℝ + +/-- The corollary in its concrete continuum-indexed form. + +The hypothesis is precisely the construction-specific property supplied by the main theorem of +the paper; the entire deduction after that point is proved here. -/ +theorem continuumPositiveCone_isWallace_of_limitProperty + [TopologicalSpace ContinuumFreeAbelianGroup] + [IsTopologicalAddGroup ContinuumFreeAbelianGroup] + [T2Space ContinuumFreeAbelianGroup] + (hlimits : HasWallaceLimitProperty + (F := ContinuumFreeAbelianGroup) continuumPositiveCone) : + IsWallaceSemigroup continuumPositiveCone := + positiveCone_isWallace_of_limitProperty ℝ (0 : ℝ) hlimits + +/-- Existential form of the Wallace conclusion from a Hausdorff topological group structure and +the construction-specific limit property supplied by the paper. -/ +theorem wallaceCounterexampleExists_of_limitProperty + [TopologicalSpace ContinuumFreeAbelianGroup] + [IsTopologicalAddGroup ContinuumFreeAbelianGroup] + [T2Space ContinuumFreeAbelianGroup] + (hlimits : HasWallaceLimitProperty + (F := ContinuumFreeAbelianGroup) continuumPositiveCone) : + WallaceCounterexampleExists := by + refine ⟨continuumPositiveCone, inferInstance, inferInstance, ?_⟩ + exact continuumPositiveCone_isWallace_of_limitProperty hlimits + +end Wallace diff --git a/LeanPool/Wallace/SeparationInterface.lean b/LeanPool/Wallace/SeparationInterface.lean new file mode 100644 index 000000000..cd4ad66c8 --- /dev/null +++ b/LeanPool/Wallace/SeparationInterface.lean @@ -0,0 +1,154 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.Result +import Mathlib.Analysis.Normed.Group.AddCircle + +/-! +# Minimal construction interface for the Wallace counterexample + +The construction supplies characters compatible with all prescribed ultrafilter limits and +separating the points of the free group. For the Wallace corollary it is enough that, for every +nonzero element `x`, one compatible character does not annihilate `x`. This file isolates +precisely that output. + +No topology on the free Abelian group and no compactness conclusion is stored in +`SeparationPackage`; both are derived below from its algebraic and filter-theoretic fields. +-/ + +open Filter Set Topology + +universe u + +namespace Wallace + +noncomputable section + +/-- An injective sequence bundled with the proof of injectivity. -/ +def InjectiveSequence' (G : Type u) := + {s : ℕ → G // Function.Injective s} + +/-- +The minimal post-fusion data needed for Wallace's problem. + +The difficult construction must supply the coding, the prepared subsequences and free +ultrafilters, and a compatible separating character for every nonzero element. The structure +does not assume any topology or compactness property of the free Abelian group. +-/ +structure SeparationPackage (I : Type u) where + Code : Type u + codeEquiv : Code ≃ InjectiveSequence' (I →₀ ℤ) + codeIndex : Code → I + subsequence : Code → ℕ → ℕ + subsequence_strictMono : ∀ c, StrictMono (subsequence c) + ultrafilter : Code → Ultrafilter ℕ + ultrafilter_free : ∀ c, (ultrafilter c : Filter ℕ) ≤ cofinite + character : {x : I →₀ ℤ // x ≠ 0} → (I →₀ ℤ) →+ UnitAddCircle + character_self_ne_zero : ∀ x, character x x ≠ 0 + character_limit : + ∀ (c : Code) (x : {x : I →₀ ℤ // x ≠ 0}), + Tendsto + (fun n ↦ character x ((codeEquiv c).1 (subsequence c n))) + (ultrafilter c) + (nhds (character x (Finsupp.single (codeIndex c) (1 : ℤ)))) + +namespace SeparationPackage + +variable {I : Type u} + +/-- Simultaneous evaluation by all compatible separating characters. -/ +def evaluation (C : SeparationPackage I) : + (I →₀ ℤ) →+ ({x : I →₀ ℤ // x ≠ 0} → UnitAddCircle) where + toFun y x := C.character x y + map_zero' := by + funext x + exact map_zero (C.character x) + map_add' x y := by + funext z + exact map_add (C.character z) x y + +/-- The initial topology induced by the compatible separating characters. -/ +@[reducible] def initialTopology (C : SeparationPackage I) : + TopologicalSpace (I →₀ ℤ) := + TopologicalSpace.induced C.evaluation inferInstance + +theorem evaluation_injective (C : SeparationPackage I) : + Function.Injective C.evaluation := by + intro x y hxy + by_contra hne + have hsub : x - y ≠ 0 := sub_ne_zero.mpr hne + let z : {z : I →₀ ℤ // z ≠ 0} := ⟨x - y, hsub⟩ + have hz := C.character_self_ne_zero z + apply hz + rw [map_sub] + have hcoord : C.character z x = C.character z y := congrFun hxy z + rw [hcoord, sub_self] + +theorem initial_isTopologicalAddGroup (C : SeparationPackage I) : + @IsTopologicalAddGroup (I →₀ ℤ) C.initialTopology _ := by + exact topologicalAddGroup_induced C.evaluation + +theorem initial_t2Space (C : SeparationPackage I) : + @T2Space (I →₀ ℤ) C.initialTopology := by + letI : TopologicalSpace (I →₀ ℤ) := C.initialTopology + exact C.evaluation_injective.isEmbedding_induced.t2Space + +/-- The prepared subsequence converges to its prescribed basis point in the initial topology. -/ +theorem prepared_tendsto_basis (C : SeparationPackage I) (c : C.Code) : + Tendsto + (fun n ↦ (C.codeEquiv c).1 (C.subsequence c n)) + (C.ultrafilter c) + (@nhds (I →₀ ℤ) C.initialTopology + (Finsupp.single (C.codeIndex c) (1 : ℤ))) := by + letI : TopologicalSpace (I →₀ ℤ) := C.initialTopology + have hinducing : IsInducing C.evaluation := ⟨rfl⟩ + refine hinducing.tendsto_nhds_iff.mpr ?_ + refine tendsto_pi_nhds.2 fun x ↦ ?_ + simpa [evaluation, Function.comp_def] using C.character_limit c x + +/-- The package supplies the exact free-ultrafilter limit property used by the cone argument. -/ +theorem positiveCone_hasWallaceLimitProperty (C : SeparationPackage I) : + @HasWallaceLimitProperty (I →₀ ℤ) C.initialTopology _ (positiveCone I) := by + letI : TopologicalSpace (I →₀ ℤ) := C.initialTopology + intro s hs _hscone + let encoded : InjectiveSequence' (I →₀ ℤ) := ⟨s, hs⟩ + let c : C.Code := C.codeEquiv.symm encoded + have hcoded : (C.codeEquiv c).1 = s := by + exact congrArg Subtype.val (C.codeEquiv.apply_symm_apply encoded) + refine ⟨C.subsequence c, Finsupp.single (C.codeIndex c) 1, C.ultrafilter c, + C.subsequence_strictMono c, single_one_mem_positiveCone I (C.codeIndex c), + C.ultrafilter_free c, ?_⟩ + change Tendsto (fun n ↦ s (C.subsequence c n)) (C.ultrafilter c) _ + rw [← hcoded] + exact C.prepared_tendsto_basis c + +/-- A minimal construction package yields a Hausdorff group topology with the Wallace limit +property on the nonnegative cone. -/ +theorem exists_initialTopology_with_wallaceLimitProperty (C : SeparationPackage I) : + ∃ topology : TopologicalSpace (I →₀ ℤ), + @IsTopologicalAddGroup (I →₀ ℤ) topology _ ∧ + @T2Space (I →₀ ℤ) topology ∧ + @HasWallaceLimitProperty (I →₀ ℤ) topology _ (positiveCone I) := by + exact ⟨C.initialTopology, C.initial_isTopologicalAddGroup, C.initial_t2Space, + C.positiveCone_hasWallaceLimitProperty⟩ + +/-- Once the genuinely constructed package is available on a nonempty index type, the Wallace +counterexample follows with no further hypotheses. -/ +theorem wallaceCounterexampleExists {I : Type} (C : SeparationPackage I) [Nonempty I] : + WallaceCounterexampleExists := by + let topology : TopologicalSpace (I →₀ ℤ) := C.initialTopology + letI : TopologicalSpace (I →₀ ℤ) := topology + letI : IsTopologicalAddGroup (I →₀ ℤ) := C.initial_isTopologicalAddGroup + letI : T2Space (I →₀ ℤ) := C.initial_t2Space + let i : I := Classical.choice inferInstance + refine ⟨positiveCone I, inferInstance, inferInstance, ?_⟩ + exact positiveCone_isWallace_of_limitProperty I i C.positiveCone_hasWallaceLimitProperty + +end SeparationPackage + +end + +end Wallace diff --git a/LeanPool/Wallace/TorsionFreeCoordinate.lean b/LeanPool/Wallace/TorsionFreeCoordinate.lean new file mode 100644 index 000000000..a95c50d3d --- /dev/null +++ b/LeanPool/Wallace/TorsionFreeCoordinate.lean @@ -0,0 +1,196 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.RationalTriangularPreprocess +import Mathlib.GroupTheory.DivisibleHull +import Mathlib.GroupTheory.OreLocalization.Cardinality +import Mathlib.LinearAlgebra.Basis.SMul +import Mathlib.LinearAlgebra.Dimension.Free + +/-! +# Coordinatizing continuum-sized torsion-free Abelian groups + +This file formalizes the coordinatization lemma used in Section 2 of the paper. A torsion-free +Abelian group of cardinality continuum embeds in the rational direct sum of continuum rank in a +way whose image contains every standard basis vector. +-/ + +open Cardinal Module + +namespace Wallace + +noncomputable section + +/-- The witness form of the paper's coordinatization lemma. -/ +structure RationalCoordinatization (G : Type) [AddCommGroup G] where + embedding : G →+ RationalTriangularPreprocess.ContinuumRationalGroup + embedding_injective : Function.Injective embedding + basisPreimage : TriangularPreprocess.ContinuumIndex → G + embedding_basisPreimage : ∀ i, + embedding (basisPreimage i) = Finsupp.single i 1 + +namespace RationalCoordinatization + +variable {G : Type} [AddCommGroup G] + +/-- The coordinatewise inclusion `ℤ^(𝔠) → ℚ^(𝔠)` occurring in the paper's +coordinatization lemma. -/ +def integerCoordinateEmbedding : + TriangularPreprocess.ContinuumFreeGroup →+ + RationalTriangularPreprocess.ContinuumRationalGroup := + Finsupp.mapRange.addMonoidHom (Int.castAddHom ℚ) + +theorem integerCoordinateEmbedding_injective : + Function.Injective integerCoordinateEmbedding := by + intro z w h + ext i + have hi := congrArg (fun q : RationalTriangularPreprocess.ContinuumRationalGroup ↦ q i) h + change (z i : ℚ) = (w i : ℚ) at hi + exact_mod_cast hi + +/-- Integer linear combinations of the distinguished preimages in `G`. -/ +def integerCoordinatePreimage (K : RationalCoordinatization G) : + TriangularPreprocess.ContinuumFreeGroup →+ G := + Finsupp.liftAddHom (fun i ↦ zmultiplesHom G (K.basisPreimage i)) + +/-- The embedding of a coordinatized group contains the whole canonical copy of +`ℤ^(𝔠)`, not merely its individual basis vectors. -/ +theorem embedding_integerCoordinatePreimage (K : RationalCoordinatization G) : + K.embedding.comp K.integerCoordinatePreimage = integerCoordinateEmbedding := by + ext i z + simp [integerCoordinatePreimage, integerCoordinateEmbedding, + K.embedding_basisPreimage] + +theorem integerCoordinatePreimage_injective (K : RationalCoordinatization G) : + Function.Injective K.integerCoordinatePreimage := by + intro z w h + apply integerCoordinateEmbedding_injective + rw [← K.embedding_integerCoordinatePreimage] + simpa using congrArg K.embedding h + +variable [IsAddTorsionFree G] + +omit [IsAddTorsionFree G] in +private theorem exists_divisibleHull_mk (x : DivisibleHull G) : + ∃ g : G, ∃ d : ℕ+, DivisibleHull.mk g d = x := by + induction x using DivisibleHull.ind with + | mk g d => exact ⟨g, d, rfl⟩ + +/-- Localizing a continuum-sized torsion-free group by the positive integers does not change its +cardinality. -/ +theorem mk_divisibleHull (hcard : #G = 𝔠) : #(DivisibleHull G) = 𝔠 := by + apply le_antisymm + · refine (OreLocalization.cardinalMk_le_max (nonZeroDivisors ℕ) G).trans ?_ + rw [hcard] + refine max_le ?_ (by simp) + have hsub : #(↥(nonZeroDivisors ℕ)) ≤ 𝔠 := + (Cardinal.mk_subtype_le (nonZeroDivisors ℕ : Set ℕ)).trans + (by simpa using Cardinal.aleph0_le_continuum) + simpa using hsub + · rw [← hcard] + exact Cardinal.mk_le_of_injective DivisibleHull.coe_injective + +/-- The divisible hull has rational dimension continuum. -/ +theorem rank_divisibleHull (hcard : #G = 𝔠) : + Module.rank ℚ (DivisibleHull G) = 𝔠 := by + rw [Module.Free.rank_eq_mk_of_infinite_lt ℚ (DivisibleHull G)] + · exact mk_divisibleHull hcard + · rw [mk_divisibleHull hcard] + simpa using Cardinal.aleph0_lt_continuum + +/-- A rational basis of the divisible hull indexed by the canonical continuum type. -/ +def continuumBasis (hcard : #G = 𝔠) : + Basis TriangularPreprocess.ContinuumIndex ℚ (DivisibleHull G) := by + let b := Module.Free.chooseBasis ℚ (DivisibleHull G) + have hindex : #(Module.Free.ChooseBasisIndex ℚ (DivisibleHull G)) = + #TriangularPreprocess.ContinuumIndex := by + rw [b.mk_eq_rank'', rank_divisibleHull hcard, + TriangularPreprocess.mk_continuumIndex] + exact b.reindex (Classical.choice (Cardinal.eq.mp hindex)) + +/-- A numerator in `G` representing a vector of the chosen basis of the divisible hull. -/ +def basisNumerator (hcard : #G = 𝔠) (i : TriangularPreprocess.ContinuumIndex) : G := + Classical.choose (exists_divisibleHull_mk (G := G) (continuumBasis hcard i)) + +/-- The positive denominator attached to `basisNumerator`. -/ +def basisDenominator (hcard : #G = 𝔠) (i : TriangularPreprocess.ContinuumIndex) : ℕ+ := + Classical.choose (Classical.choose_spec + (exists_divisibleHull_mk (G := G) (continuumBasis hcard i))) + +theorem basisFraction (hcard : #G = 𝔠) (i : TriangularPreprocess.ContinuumIndex) : + DivisibleHull.mk (basisNumerator hcard i) (basisDenominator hcard i) = + continuumBasis hcard i := + Classical.choose_spec (Classical.choose_spec + (exists_divisibleHull_mk (G := G) (continuumBasis hcard i))) + +theorem denominator_smul_basis (hcard : #G = 𝔠) + (i : TriangularPreprocess.ContinuumIndex) : + ((basisDenominator (G := G) hcard i : ℕ) : ℚ) • continuumBasis hcard i = + (basisNumerator (G := G) hcard i : DivisibleHull G) := by + rw [← basisFraction hcard i, Nat.cast_smul_eq_nsmul, + DivisibleHull.nsmul_mk, DivisibleHull.mk_eq_mk_iff_smul_eq_smul] + simp + +/-- Rescale the chosen rational basis so that every basis vector is literally the image of an +element of the original group. -/ +def integralBasis (hcard : #G = 𝔠) : + Basis TriangularPreprocess.ContinuumIndex ℚ (DivisibleHull G) := + (continuumBasis hcard).isUnitSMul + (fun i ↦ (isUnit_iff_ne_zero.mpr (by + positivity : ((basisDenominator (G := G) hcard i : ℕ) : ℚ) ≠ 0))) + +theorem integralBasis_apply (hcard : #G = 𝔠) + (i : TriangularPreprocess.ContinuumIndex) : + integralBasis hcard i = (basisNumerator (G := G) hcard i : DivisibleHull G) := by + simp only [integralBasis, Basis.isUnitSMul_apply] + exact denominator_smul_basis hcard i + +/-- The additive embedding furnished by the rescaled basis. -/ +def canonicalEmbedding (hcard : #G = 𝔠) : + G →+ RationalTriangularPreprocess.ContinuumRationalGroup := + (integralBasis hcard).repr.toLinearMap.toAddMonoidHom.comp + (DivisibleHull.coeAddMonoidHom G) + +theorem canonicalEmbedding_injective (hcard : #G = 𝔠) : + Function.Injective (canonicalEmbedding hcard) := + (integralBasis hcard).repr.injective.comp DivisibleHull.coe_injective + +theorem canonicalEmbedding_basisNumerator (hcard : #G = 𝔠) + (i : TriangularPreprocess.ContinuumIndex) : + canonicalEmbedding hcard (basisNumerator (G := G) hcard i) = + Finsupp.single i 1 := by + change (integralBasis hcard).repr + (basisNumerator (G := G) hcard i : DivisibleHull G) = _ + rw [← integralBasis_apply hcard i] + simp + +/-- **Torsion-free coordinatization lemma (paper, Section 2).** Every torsion-free Abelian +group of cardinality continuum embeds in `ℚ^(𝔠)` and its image contains `ℤ^(𝔠)`, expressed by +the preimage of every standard basis vector. -/ +def ofCardinalityContinuum (hcard : #G = 𝔠) : RationalCoordinatization G where + embedding := canonicalEmbedding hcard + embedding_injective := canonicalEmbedding_injective hcard + basisPreimage := basisNumerator (G := G) hcard + embedding_basisPreimage := canonicalEmbedding_basisNumerator hcard + +/-- A proposition-level form of the paper's coordinatization lemma: the map is +injective and its image contains the canonical copy of `ℤ^(𝔠)` in `ℚ^(𝔠)`. -/ +theorem exists_coordinatization (hcard : #G = 𝔠) : + ∃ (embedding : G →+ RationalTriangularPreprocess.ContinuumRationalGroup) + (preimage : TriangularPreprocess.ContinuumFreeGroup →+ G), + Function.Injective embedding ∧ + Function.Injective preimage ∧ + embedding.comp preimage = integerCoordinateEmbedding := by + let K := ofCardinalityContinuum (G := G) hcard + exact ⟨K.embedding, K.integerCoordinatePreimage, K.embedding_injective, + K.integerCoordinatePreimage_injective, + K.embedding_integerCoordinatePreimage⟩ + +end RationalCoordinatization + +end + +end Wallace diff --git a/LeanPool/Wallace/TransfiniteExtension.lean b/LeanPool/Wallace/TransfiniteExtension.lean new file mode 100644 index 000000000..f5d6645a9 --- /dev/null +++ b/LeanPool/Wallace/TransfiniteExtension.lean @@ -0,0 +1,267 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.TriangularPreprocess + +/-! +# Transfinite extension of a local circle-valued character + +This file isolates the transfinite part of the Wallace construction behind a small, reusable +interface. The only input about the prepared sequences is the triangular support condition: +every coordinate occurring in the sequence coded at `codeIndex c` is strictly smaller than +`codeIndex c`. + +At a coordinate in the closed set `D` we use the prescribed local character. At a code +coordinate outside `D` we take the compact ultrafilter limit of the values of its prepared +sequence, evaluated using coordinates already defined by well-founded recursion. All other +coordinates receive zero. The resulting basis assignment extends uniquely to the free Abelian +group, extends the local character, and is admissible for every code. + +There are no axioms or omitted proofs in this file. +-/ + +open Filter Set Topology + +namespace Wallace +namespace TransfiniteExtension + +noncomputable section + +universe u v + +/-! ## Abstract triangular input -/ + +/-- The minimal triangular data needed by the transfinite character extension. -/ +structure Data (I : Type u) [LT I] where + /-- Codes for the prepared sequences. -/ + Code : Type v + /-- The fresh coordinate assigned to a code. -/ + codeIndex : Code ↪ I + /-- The sequence after the finite block preprocessing. -/ + prepared : Code → ℕ → I →₀ ℤ + /-- Every coordinate used by a prepared term precedes its code coordinate. -/ + support_lt : ∀ c n i, i ∈ (prepared c n).support → i < codeIndex c + /-- The ultrafilter with respect to which the coded limit is imposed. -/ + p : Code → Ultrafilter ℕ + +/-- Closure of `D` under the coordinates occurring in codes whose fresh coordinate lies in +`D`. This is precisely what is needed to transfer the already-established local limits. -/ +def ClosedUnderPreparedSupports {I : Type u} [LT I] (E : Data I) (D : Set I) : Prop := + ∀ c, E.codeIndex c ∈ D → ∀ n i, i ∈ (E.prepared c n).support → i ∈ D + +/-- The local admissibility condition, stated after restricting each prepared term to `D`. -/ +def LocallyAdmissible {I : Type u} [LT I] (E : Data I) (D : Set I) + (χD : (D →₀ ℤ) →+ UnitAddCircle) : Prop := + ∀ (c : E.Code) (hc : E.codeIndex c ∈ D), + Tendsto (fun n ↦ χD (Finsupp.subtypeDomain D (E.prepared c n))) (E.p c) + (nhds (χD (Finsupp.single ⟨E.codeIndex c, hc⟩ 1))) + +/-! ## Evaluation below a recursive stage -/ + +/-- Turn the values available below stage `i` into a total basis assignment by putting zero +above the stage. -/ +def stageBasis {I : Type u} [LT I] [DecidableRel ((· < ·) : I → I → Prop)] (i : I) + (previous : ∀ j, j < i → UnitAddCircle) : I → UnitAddCircle := + fun j ↦ if h : j < i then previous j h else 0 + +/-- Evaluation of a prepared term using only values available below the current stage. -/ +def stageEvaluation {I : Type u} [LT I] [DecidableRel ((· < ·) : I → I → Prop)] + (E : Data I) (i : I) + (previous : ∀ j, j < i → UnitAddCircle) (c : E.Code) (n : ℕ) : UnitAddCircle := + finsuppAddHomOfBasis (stageBasis i previous) (E.prepared c n) + +/-- The compact ultrafilter limit chosen at a code coordinate. -/ +def compactStageLimit {I : Type u} [LT I] [DecidableRel ((· < ·) : I → I → Prop)] + (E : Data I) (i : I) + (previous : ∀ j, j < i → UnitAddCircle) (c : E.Code) : UnitAddCircle := + (Ultrafilter.map (stageEvaluation E i previous c) (E.p c)).lim + +/-- Two basis assignments that agree on the support of a vector give the same value. -/ +theorem finsuppAddHomOfBasis_eq_of_eq_on_support {I : Type u} + {z w : I → UnitAddCircle} {x : I →₀ ℤ} + (h : ∀ i ∈ x.support, z i = w i) : + finsuppAddHomOfBasis z x = finsuppAddHomOfBasis w x := by + simp only [finsuppAddHomOfBasis, Finsupp.liftAddHom_apply] + apply Finsupp.sum_congr + intro i hi + rw [h i hi] + +/-! ## Well-founded definition of the global basis values -/ + +/-- One step of the recursion. Injectivity of `codeIndex` makes the code chosen in the second +branch unique. -/ +def basisStep {I : Type u} [LinearOrder I] (E : Data I) (D : Set I) + (χD : (D →₀ ℤ) →+ UnitAddCircle) (i : I) + (previous : ∀ j, j < i → UnitAddCircle) : UnitAddCircle := by + classical + exact if hi : i ∈ D then + χD (Finsupp.single ⟨i, hi⟩ 1) + else if hcode : ∃ c : E.Code, E.codeIndex c = i then + compactStageLimit E i previous (Classical.choose hcode) + else + 0 + +/-- The global values on the standard basis, defined by recursion along the well-order. -/ +def globalBasisValue {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) : + I → UnitAddCircle := + WellFoundedLT.fix fun i previous ↦ basisStep E D χD i previous + +theorem globalBasisValue_eq {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) (i : I) : + globalBasisValue E D χD i = + basisStep E D χD i (fun j _ ↦ globalBasisValue E D χD j) := by + rw [globalBasisValue, WellFoundedLT.fix_eq] + +theorem globalBasisValue_of_mem {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) + {i : I} (hi : i ∈ D) : + globalBasisValue E D χD i = χD (Finsupp.single ⟨i, hi⟩ 1) := by + rw [globalBasisValue_eq] + simp [basisStep, hi] + +theorem globalBasisValue_codeIndex_of_not_mem + {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) + (c : E.Code) (hc : E.codeIndex c ∉ D) : + globalBasisValue E D χD (E.codeIndex c) = + compactStageLimit E (E.codeIndex c) + (fun j _ ↦ globalBasisValue E D χD j) c := by + rw [globalBasisValue_eq] + simp only [basisStep, hc, dite_false] + let hex : ∃ d : E.Code, E.codeIndex d = E.codeIndex c := ⟨c, rfl⟩ + rw [dif_pos hex] + have hchosen : Classical.choose hex = c := by + apply E.codeIndex.injective + exact Classical.choose_spec hex + rw [hchosen] + +/-! ## The global character and its extension property -/ + +/-- The unique additive character determined by the recursively constructed basis values. -/ +def globalCharacter {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) : + (I →₀ ℤ) →+ UnitAddCircle := + finsuppAddHomOfBasis (globalBasisValue E D χD) + +@[simp] +theorem globalCharacter_single_one {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) (i : I) : + globalCharacter E D χD (Finsupp.single i 1) = globalBasisValue E D χD i := by + simp [globalCharacter] + +/-- On finitely supported vectors on `D`, the global character is exactly the prescribed local +character. -/ +theorem globalCharacter_extendDomain {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) + (x : D →₀ ℤ) : + globalCharacter E D χD (Finsupp.embDomain (.subtype D) x) = χD x := by + let inclusion : (D →₀ ℤ) →+ (I →₀ ℤ) := + Finsupp.embDomain.addMonoidHom (.subtype (D : I → Prop)) + have hhom : (globalCharacter E D χD).comp inclusion = χD := by + apply Finsupp.addHom_ext + intro i n + rcases i with ⟨i, hi⟩ + change globalCharacter E D χD + (Finsupp.embDomain (.subtype (D : I → Prop)) (Finsupp.single ⟨i, hi⟩ n)) = + χD (Finsupp.single ⟨i, hi⟩ n) + rw [Finsupp.embDomain_single] + simp only [globalCharacter, finsuppAddHomOfBasis_single] + have hbasis := globalBasisValue_of_mem E D χD (i := i) hi + have hbasis' : + globalBasisValue E D χD i = + χD (Finsupp.single ⟨i, hi⟩ 1) := by + exact hbasis + calc + n • globalBasisValue E D χD i = + n • χD (Finsupp.single ⟨i, hi⟩ 1) := congrArg (fun z ↦ n • z) hbasis' + _ = χD (n • Finsupp.single ⟨i, hi⟩ 1) := (map_zsmul χD _ _).symm + _ = χD (Finsupp.single ⟨i, hi⟩ n) := by simp + exact DFunLike.congr_fun hhom x + +/-- Equivalent extension statement for an ambient vector whose support is contained in `D`. -/ +theorem globalCharacter_eq_local_restriction {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) + (x : I →₀ ℤ) (hx : ∀ i ∈ x.support, i ∈ D) : + globalCharacter E D χD x = χD (Finsupp.subtypeDomain D x) := by + have hxrange : (↑x.support : Set I) ⊆ + Set.range (Function.Embedding.subtype D) := by + intro i hi + exact ⟨⟨i, hx i hi⟩, rfl⟩ + obtain ⟨y, rfl⟩ := + (Finsupp.mem_range_embDomain_iff (Function.Embedding.subtype D) x).2 hxrange + rw [globalCharacter_extendDomain E D χD y] + congr 1 + ext i + exact (Finsupp.embDomain_apply_self (Function.Embedding.subtype D) y i).symm + +/-! ## Admissibility at every code -/ + +theorem stageEvaluation_eq_globalCharacter + {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) + (c : E.Code) (n : ℕ) : + stageEvaluation E (E.codeIndex c) + (fun j _ ↦ globalBasisValue E D χD j) c n = + globalCharacter E D χD (E.prepared c n) := by + apply finsuppAddHomOfBasis_eq_of_eq_on_support + intro i hi + simp [stageBasis, E.support_lt c n i hi] + +/-- Compactness of the circle supplies the limit used at each external code coordinate. -/ +theorem tendsto_stageEvaluation_compactLimit + {I : Type u} [LinearOrder I] (E : Data I) (i : I) + (previous : ∀ j, j < i → UnitAddCircle) (c : E.Code) : + Tendsto (stageEvaluation E i previous c) (E.p c) + (nhds (compactStageLimit E i previous c)) := by + exact (Ultrafilter.map (stageEvaluation E i previous c) (E.p c)).le_nhds_lim + +/-- The transfinite extension is admissible for every prepared code, including codes outside +the local closed set. -/ +theorem globalCharacter_admissible + {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) + (hclosed : ClosedUnderPreparedSupports E D) + (hlocal : LocallyAdmissible E D χD) : + ∀ c : E.Code, + Tendsto (fun n ↦ globalCharacter E D χD (E.prepared c n)) (E.p c) + (nhds (globalCharacter E D χD (Finsupp.single (E.codeIndex c) 1))) := by + intro c + by_cases hc : E.codeIndex c ∈ D + · have heval : + (fun n ↦ globalCharacter E D χD (E.prepared c n)) = + (fun n ↦ χD (Finsupp.subtypeDomain D (E.prepared c n))) := by + funext n + exact globalCharacter_eq_local_restriction E D χD (E.prepared c n) + (hclosed c hc n) + have hbasis : + globalCharacter E D χD (Finsupp.single (E.codeIndex c) 1) = + χD (Finsupp.single ⟨E.codeIndex c, hc⟩ 1) := by + rw [globalCharacter_single_one, globalBasisValue_of_mem E D χD hc] + rw [heval, hbasis] + exact hlocal c hc + · have hlim := tendsto_stageEvaluation_compactLimit E (E.codeIndex c) + (fun j _ ↦ globalBasisValue E D χD j) c + have heval : + (fun n ↦ globalCharacter E D χD (E.prepared c n)) = + stageEvaluation E (E.codeIndex c) + (fun j _ ↦ globalBasisValue E D χD j) c := by + funext n + exact (stageEvaluation_eq_globalCharacter E D χD c n).symm + rw [heval, globalCharacter_single_one, + globalBasisValue_codeIndex_of_not_mem E D χD c hc] + exact hlim + +/-! ## Specialization of the index type to the continuum well-order -/ + +/-- The generic theorem applies directly to the canonical continuum index constructed in +`TriangularPreprocess`. Concrete fusion data only has to fill the fields of `Data`. -/ +abbrev ContinuumData := Data TriangularPreprocess.ContinuumIndex + +end + +end TransfiniteExtension +end Wallace diff --git a/LeanPool/Wallace/TriangularPreprocess.lean b/LeanPool/Wallace/TriangularPreprocess.lean new file mode 100644 index 000000000..ff8ba4942 --- /dev/null +++ b/LeanPool/Wallace/TriangularPreprocess.lean @@ -0,0 +1,633 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.MathlibFoundations +import LeanPool.Wallace.FiniteCombinatorics + +/-! +# Triangular coding and block preprocessing + +This file supplies the unconditional set-theoretic bookkeeping that precedes the character +construction. The index set is the canonical well-order of cardinality continuum. All +injective sequences in the corresponding free Abelian group are coded, and their codes are +assigned distinct indices strictly above every coordinate in the sequence. The second half of +the file constructs a genuine subsequence whose prescribed finite blocks are bounded-independent. +-/ + +open Set +open scoped Cardinal + +namespace Wallace +namespace TriangularPreprocess + +noncomputable section + +/-! ## The continuum initial ordinal and its free group -/ + +/-- The canonical well-ordered index type of cardinality continuum. -/ +abbrev ContinuumIndex := (Cardinal.ord (𝔠 : Cardinal.{0})).ToType + +/-- The free Abelian group on the canonical continuum index. -/ +abbrev ContinuumFreeGroup := ContinuumIndex →₀ ℤ + +/-- The type of all injective sequences in the free group. -/ +abbrev InjectiveSequences := + {s : ℕ → ContinuumFreeGroup // Function.Injective s} + +@[simp] +theorem mk_continuumIndex : #ContinuumIndex = 𝔠 := by + exact Cardinal.mk_ord_toType 𝔠 + +theorem continuumIndex_infinite : Infinite ContinuumIndex := by + exact Cardinal.aleph0_le_mk_iff.mp <| by + simpa only [mk_continuumIndex] using Cardinal.aleph0_le_continuum + +theorem mk_continuumFreeGroup : #ContinuumFreeGroup = 𝔠 := by + letI : Infinite ContinuumIndex := continuumIndex_infinite + change #(ContinuumIndex →₀ ℤ) = 𝔠 + rw [Cardinal.mk_finsupp_of_infinite, mk_continuumIndex, Cardinal.mk_int] + exact max_eq_left Cardinal.aleph0_le_continuum + +theorem mk_continuumFreeGroup_sequences : #(ℕ → ContinuumFreeGroup) = 𝔠 := by + change #(ℕ → (ContinuumIndex →₀ ℤ)) = 𝔠 + rw [Cardinal.mk_arrow, mk_continuumFreeGroup, Cardinal.mk_nat] + simpa only [Cardinal.lift_id] using Cardinal.continuum_power_aleph0 + +/-- An injective ray along one basis vector. -/ +def basisRay (i : ContinuumIndex) (n : ℕ) : ContinuumFreeGroup := + Finsupp.single i (n : ℤ) + +theorem basisRay_injective (i : ContinuumIndex) : Function.Injective (basisRay i) := by + intro m n h + have hi := congrArg (fun z : ContinuumFreeGroup => z i) h + simpa [basisRay] using hi + +theorem basisRay_family_injective : + Function.Injective (fun i : ContinuumIndex => + (⟨basisRay i, basisRay_injective i⟩ : InjectiveSequences)) := by + intro i j hij + have hfun : basisRay i = basisRay j := congrArg Subtype.val hij + have hi := congrArg (fun s : ℕ → ContinuumFreeGroup => s 1 i) hfun + by_contra hne + simp [basisRay, hne] at hi + +theorem mk_injectiveSequences : #InjectiveSequences = 𝔠 := by + apply le_antisymm + · exact (Cardinal.mk_subtype_le _).trans_eq mk_continuumFreeGroup_sequences + · rw [← mk_continuumIndex] + exact Cardinal.mk_le_of_injective basisRay_family_injective + +/-- A fixed equivalence between the canonical continuum index and all injective sequences. -/ +def sequenceCodeEquiv : ContinuumIndex ≃ InjectiveSequences := + Classical.choice <| Cardinal.eq.mp <| mk_continuumIndex.trans mk_injectiveSequences.symm + +/-- The sequence represented by a code. -/ +def codedSequence (a : ContinuumIndex) : ℕ → ContinuumFreeGroup := + (sequenceCodeEquiv a).1 + +theorem codedSequence_injective (a : ContinuumIndex) : + Function.Injective (codedSequence a) := + (sequenceCodeEquiv a).2 + +theorem codedSequence_code_injective : Function.Injective codedSequence := by + intro a b hab + apply sequenceCodeEquiv.injective + exact Subtype.ext hab + +/-! ## Countable supports have strict upper bounds -/ + +/-- All coordinates that occur in a sequence. -/ +def sequenceSupport (s : ℕ → ContinuumFreeGroup) : Set ContinuumIndex := + {i | ∃ n, i ∈ (s n).support} + +theorem sequenceSupport_countable (s : ℕ → ContinuumFreeGroup) : + (sequenceSupport s).Countable := by + rw [show sequenceSupport s = ⋃ n, ((s n).support : Set ContinuumIndex) by + ext i + simp [sequenceSupport]] + exact Set.countable_iUnion fun n => (s n).support.finite_toSet.countable + +/-- Every countable set of continuum indices is strictly bounded. -/ +theorem exists_strict_upperBound_of_countable + {S : Set ContinuumIndex} (hS : S.Countable) : + ∃ i : ContinuumIndex, ∀ j ∈ S, j < i := by + have hcard : #S < Order.cof ContinuumIndex := by + calc + #S ≤ ℵ₀ := Cardinal.le_aleph0_iff_set_countable.mpr hS + _ < (𝔠 : Cardinal).ord.cof := Wallace.aleph0_lt_cof_continuum + _ = Order.cof ContinuumIndex := (Ordinal.cof_toType _).symm + have hncof : ¬ IsCofinal S := by + intro hcof + exact hcard.2 (Order.cof_le hcof) + exact not_isCofinal_iff.mp hncof + +/-- A chosen strict upper bound for the support of each coded sequence. -/ +def supportBound (a : ContinuumIndex) : ContinuumIndex := + Classical.choose <| exists_strict_upperBound_of_countable + (sequenceSupport_countable (codedSequence a)) + +theorem support_lt_supportBound (a : ContinuumIndex) {n : ℕ} {i : ContinuumIndex} + (hi : i ∈ (codedSequence a n).support) : i < supportBound a := by + exact (Classical.choose_spec <| exists_strict_upperBound_of_countable + (sequenceSupport_countable (codedSequence a))) i ⟨n, hi⟩ + +/-! ## Fresh indices above all supports -/ + +theorem exists_fresh_above + (bound : ContinuumIndex → ContinuumIndex) (a : ContinuumIndex) + (previous : ∀ b, b < a → ContinuumIndex) : + ∃ i, bound a < i ∧ ∀ b (h : b < a), previous b h ≠ i := by + let prior : Set ContinuumIndex := + Set.range fun b : Set.Iio a => previous b b.property + let excluded : Set ContinuumIndex := Set.Iic (bound a) ∪ prior + have hIic : #(Set.Iic (bound a)) < #ContinuumIndex := by + apply Cardinal.mk_Iic_lt + · simp + · simpa only [mk_continuumIndex] using Cardinal.aleph0_le_continuum + have hprior : #prior < #ContinuumIndex := by + change #(Set.range fun b : Set.Iio a => previous b b.property) < #ContinuumIndex + exact Cardinal.mk_range_le.trans_lt (Cardinal.mk_Iio_lt a (by simp)) + have hexcluded : #excluded < #ContinuumIndex := by + apply (Cardinal.mk_union_le _ _).trans_lt + exact Cardinal.add_lt_of_lt + (by simpa only [mk_continuumIndex] using Cardinal.aleph0_le_continuum) + hIic hprior + have hne : excluded ≠ Set.univ := by + intro heq + have : #excluded = #ContinuumIndex := by rw [heq, Cardinal.mk_univ] + exact hexcluded.ne this + obtain ⟨i, hi⟩ := (Set.ne_univ_iff_exists_notMem excluded).mp hne + refine ⟨i, ?_, ?_⟩ + · exact lt_of_not_ge fun h => hi (Set.mem_union_left prior h) + · intro b hb hbi + apply hi + apply Set.mem_union_right (Set.Iic (bound a)) + exact ⟨⟨b, hb⟩, hbi⟩ + +/-- Transfinite fresh-index assignment. At stage `a`, it avoids all values assigned below `a` +and lies strictly above `bound a`. -/ +def freshIndex (bound : ContinuumIndex → ContinuumIndex) : + ContinuumIndex → ContinuumIndex := + WellFoundedLT.fix fun a previous => + Classical.choose (exists_fresh_above bound a previous) + +theorem freshIndex_spec (bound : ContinuumIndex → ContinuumIndex) (a : ContinuumIndex) : + bound a < freshIndex bound a ∧ + ∀ b (_h : b < a), freshIndex bound b ≠ freshIndex bound a := by + rw [freshIndex, WellFoundedLT.fix_eq] + exact Classical.choose_spec (exists_fresh_above bound a fun b _ => freshIndex bound b) + +theorem freshIndex_injective (bound : ContinuumIndex → ContinuumIndex) : + Function.Injective (freshIndex bound) := by + apply Function.Injective.of_lt_imp_ne + intro a b hab + exact (freshIndex_spec bound b).2 a hab + +/-- The injective index assigned to every sequence code. -/ +def codeIndex : ContinuumIndex ↪ ContinuumIndex := + ⟨freshIndex supportBound, freshIndex_injective supportBound⟩ + +theorem codedSequence_supportedBelow (a : ContinuumIndex) : + FiniteCombinatorics.SupportedBelow (codedSequence a) (codeIndex a) := by + intro n i hi + exact (support_lt_supportBound a hi).trans (freshIndex_spec supportBound a).1 + +/-- The paper's set `Λ` of fresh indices. -/ +abbrev TriangularIndices : Set ContinuumIndex := Set.range codeIndex + +/-- The code type and `Λ` are equivalent by the fresh-index embedding. -/ +def codeIndexEquiv : ContinuumIndex ≃ TriangularIndices := + Equiv.ofInjective codeIndex codeIndex.injective + +/-- The paper-style enumeration, now indexed literally by `Λ`. -/ +def triangularSequenceEquiv : TriangularIndices ≃ InjectiveSequences := + codeIndexEquiv.symm.trans sequenceCodeEquiv + +def triangularSequence (α : TriangularIndices) : ℕ → ContinuumFreeGroup := + (triangularSequenceEquiv α).1 + +@[simp] +theorem mk_triangularIndices : #TriangularIndices = 𝔠 := by + exact (Cardinal.mk_range_eq codeIndex codeIndex.injective).trans mk_continuumIndex + +theorem triangularSequence_injective (α : TriangularIndices) : + Function.Injective (triangularSequence α) := + (triangularSequenceEquiv α).2 + +/-- Exact triangular support condition with the fresh index itself as upper bound. -/ +theorem triangularSequence_supportedBelow (α : TriangularIndices) : + FiniteCombinatorics.SupportedBelow (triangularSequence α) α := by + let a := codeIndexEquiv.symm α + have hα : (codeIndex a : ContinuumIndex) = α := by + exact Subtype.ext_iff.mp (codeIndexEquiv.apply_symm_apply α) + change FiniteCombinatorics.SupportedBelow + (codedSequence (codeIndexEquiv.symm α)) α + simpa only [a, hα] using codedSequence_supportedBelow a + +/-! ## Blockwise bounded-independence selection -/ + +open FiniteCombinatorics + +/-- Bounded independence is inherited by finite subsets. -/ +theorem boundedIndependent_mono + {G : Type*} [AddCommGroup G] {M : ℕ} {X Y : Finset G} + (hY : BoundedIndependent M Y) (hXY : X ⊆ Y) : + BoundedIndependent M X := by + classical + intro c hc hsum + let c' : G → ℤ := fun z => if z ∈ X then c z else 0 + have hc' : ∀ y ∈ Y, Int.natAbs (c' y) ≤ M := by + intro y hy + by_cases hyX : y ∈ X + · simpa [c', hyX] using hc y hyX + · simp [c', hyX] + have hsum' : (∑ y ∈ Y, c' y • y) = 0 := by + rw [← hsum] + calc + ∑ y ∈ Y, c' y • y = ∑ x ∈ X, c' x • x := by + symm + apply Finset.sum_subset hXY + intro y hyY hyX + simp [c', hyX] + _ = ∑ x ∈ X, c x • x := by + apply Finset.sum_congr rfl + intro x hx + simp [c', hx] + have hz := hY c' hc' hsum' + intro x hx + simpa [c', hx] using hz x (hXY hx) + +/-- An injective sequence has arbitrarily late terms outside any fixed finite set. -/ +theorem exists_index_gt_avoiding_finset + {G : Type*} {u : ℕ → G} (hu : Function.Injective u) + (B : Finset G) (k : ℕ) : + ∃ m, k < m ∧ u m ∉ B := by + let bad : Set ℕ := u ⁻¹' (B : Set G) + have hbad : bad.Finite := B.finite_toSet.preimage hu.injOn + obtain ⟨m, hmk, hm⟩ := (Set.Ioi_infinite k).exists_notMem_finite hbad + exact ⟨m, hmk, hm⟩ + +/-- State of the recursive block selector. `values l` contains the values already selected in +block `l`; `last` is the last source index used. -/ +structure BlockSelectionState (G : Type*) where + last : ℕ + values : ℕ → Finset G + +def initialBlockSelectionState (G : Type*) : BlockSelectionState G where + last := 0 + values := fun _ => ∅ + +noncomputable def excludedAt + {G : Type*} [AddCommGroup G] (M block : ℕ → ℕ) (n : ℕ) + (st : BlockSelectionState G) : Finset G := by + classical + exact st.values (block n) ∪ + forbiddenFinset (M (block n)) (st.values (block n)) + +/-- The next source index: strictly later than the previous one and outside both the values +already used in this block and every bounded forbidden equation over them. -/ +def nextBlockIndex + {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) + (M block : ℕ → ℕ) (n : ℕ) (st : BlockSelectionState G) : ℕ := + Classical.choose <| + exists_index_gt_avoiding_finset hu (excludedAt M block n st) st.last + +theorem nextBlockIndex_spec + {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) + (M block : ℕ → ℕ) (n : ℕ) (st : BlockSelectionState G) : + st.last < nextBlockIndex u hu M block n st ∧ + u (nextBlockIndex u hu M block n st) ∉ excludedAt M block n st := + Classical.choose_spec <| + exists_index_gt_avoiding_finset hu (excludedAt M block n st) st.last + +theorem nextBlockIndex_not_mem_values + {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) + (M block : ℕ → ℕ) (n : ℕ) (st : BlockSelectionState G) : + u (nextBlockIndex u hu M block n st) ∉ st.values (block n) := by + classical + exact fun h => (nextBlockIndex_spec u hu M block n st).2 + (Finset.mem_union_left _ h) + +theorem nextBlockIndex_not_forbidden + {G : Type*} [AddCommGroup G] [IsAddTorsionFree G] + (u : ℕ → G) (hu : Function.Injective u) + (M block : ℕ → ℕ) (n : ℕ) (st : BlockSelectionState G) : + ¬ Forbidden (M (block n)) (st.values (block n)) + (u (nextBlockIndex u hu M block n st)) := by + classical + intro h + exact (nextBlockIndex_spec u hu M block n st).2 + (Finset.mem_union_right _ <| forbidden_mem_forbiddenFinset h) + +noncomputable def blockSelectionStep + {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) + (M block : ℕ → ℕ) (n : ℕ) (st : BlockSelectionState G) : + BlockSelectionState G := by + classical + let k := nextBlockIndex u hu M block n st + exact + { last := k + values := Function.update st.values (block n) + (insert (u k) (st.values (block n))) } + +/-- States after the first `n` positions of the new sequence have been selected. -/ +def blockSelectionStates + {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) + (M block : ℕ → ℕ) : ℕ → BlockSelectionState G + | 0 => initialBlockSelectionState G + | n + 1 => blockSelectionStep u hu M block n (blockSelectionStates u hu M block n) + +/-- The actual source-index subsequence selected by the state recursion. -/ +def blockSubsequenceIndex + {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) + (M block : ℕ → ℕ) (n : ℕ) : ℕ := + (blockSelectionStates u hu M block (n + 1)).last + +theorem blockSelectionStates_last_lt_succ + {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) + (M block : ℕ → ℕ) (n : ℕ) : + (blockSelectionStates u hu M block n).last < + (blockSelectionStates u hu M block (n + 1)).last := by + rw [blockSelectionStates] + exact nextBlockIndex_spec u hu M block n (blockSelectionStates u hu M block n) |>.1 + +theorem blockSubsequenceIndex_strictMono + {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) + (M block : ℕ → ℕ) : + StrictMono (blockSubsequenceIndex u hu M block) := by + apply strictMono_nat_of_lt_succ + intro n + exact blockSelectionStates_last_lt_succ u hu M block (n + 1) + +theorem blockSelectionStates_boundedIndependent + {G : Type*} [AddCommGroup G] [IsAddTorsionFree G] + (u : ℕ → G) (hu : Function.Injective u) (M block : ℕ → ℕ) + (n l : ℕ) : + BoundedIndependent (M l) ((blockSelectionStates u hu M block n).values l) := by + classical + induction n with + | zero => + intro c hc hsum x hx + simp [blockSelectionStates, initialBlockSelectionState] at hx + | succ n ih => + rw [blockSelectionStates] + by_cases hl : l = block n + · subst l + simp only [blockSelectionStep] + simp + exact boundedIndependent_insert_of_not_forbidden ih + (nextBlockIndex_not_mem_values u hu M block n + (blockSelectionStates u hu M block n)) + (nextBlockIndex_not_forbidden u hu M block n + (blockSelectionStates u hu M block n)) + · simp [blockSelectionStep, hl] + exact ih + +theorem blockSelectionStates_values_mono_succ + {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) + (M block : ℕ → ℕ) (n l : ℕ) : + (blockSelectionStates u hu M block n).values l ⊆ + (blockSelectionStates u hu M block (n + 1)).values l := by + classical + rw [blockSelectionStates] + by_cases hl : l = block n + · subst l + simp [blockSelectionStep] + · simp [blockSelectionStep, hl] + +theorem blockSelectionStates_values_monotone + {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) + (M block : ℕ → ℕ) (l : ℕ) : + Monotone fun n => (blockSelectionStates u hu M block n).values l := + monotone_nat_of_le_succ fun n => + blockSelectionStates_values_mono_succ u hu M block n l + +theorem selected_value_mem_state + {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) + (M block : ℕ → ℕ) (n : ℕ) : + u (blockSubsequenceIndex u hu M block n) ∈ + (blockSelectionStates u hu M block (n + 1)).values (block n) := by + classical + simp [blockSubsequenceIndex, blockSelectionStates, blockSelectionStep] + +/-- A cutoff beyond every position in a finite set. -/ +def finsetCutoff (B : Finset ℕ) : ℕ := + B.sup fun n => n + 1 + +theorem add_one_le_finsetCutoff {B : Finset ℕ} {n : ℕ} (hn : n ∈ B) : + n + 1 ≤ finsetCutoff B := by + exact Finset.le_sup (s := B) (f := fun k => k + 1) hn + +/-- Generic block preprocessing. `block n` specifies which finite block contains output +position `n`. Each block may have any prescribed positive finite size; only finiteness is +needed by the selection argument. -/ +theorem exists_blockwise_boundedIndependent_subsequence + {G : Type*} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] + (u : ℕ → G) (hu : Function.Injective u) + (block M : ℕ → ℕ) + (hfinite : ∀ l, {n | block n = l}.Finite) : + ∃ φ : ℕ → ℕ, StrictMono φ ∧ + ∀ l, BoundedIndependent (M l) + ((hfinite l).toFinset.image fun n => u (φ n)) := by + classical + let φ := blockSubsequenceIndex u hu M block + refine ⟨φ, blockSubsequenceIndex_strictMono u hu M block, ?_⟩ + intro l + let B : Finset ℕ := (hfinite l).toFinset + let K : ℕ := finsetCutoff B + apply boundedIndependent_mono + (blockSelectionStates_boundedIndependent u hu M block K l) + intro x hx + rcases Finset.mem_image.mp hx with ⟨n, hnB, rfl⟩ + have hnblock : block n = l := by + exact (Set.Finite.mem_toFinset (hfinite l)).mp hnB + have hmem := selected_value_mem_state u hu M block n + rw [hnblock] at hmem + exact blockSelectionStates_values_monotone u hu M block l + (add_one_le_finsetCutoff hnB) hmem + +/-! ## The consecutive block partition used in the paper -/ + +/-- The first position of block `l`, namely `∑ j < l, N j`. This is the paper's `S_l`. -/ +def blockStart (N : ℕ → ℕ) (l : ℕ) : ℕ := + ∑ j ∈ Finset.range l, N j + +@[simp] +theorem blockStart_zero (N : ℕ → ℕ) : blockStart N 0 = 0 := by + simp [blockStart] + +theorem blockStart_succ (N : ℕ → ℕ) (l : ℕ) : + blockStart N (l + 1) = blockStart N l + N l := by + simp [blockStart, Finset.sum_range_succ] + +theorem blockStart_strictMono (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) : + StrictMono (blockStart N) := by + apply strictMono_nat_of_lt_succ + intro l + rw [blockStart_succ] + exact Nat.lt_add_of_pos_right (hN l) + +theorem index_le_blockStart (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) : + ∀ l, l ≤ blockStart N l := by + intro l + induction l with + | zero => simp + | succ l ih => + rw [blockStart_succ] + have hpos := hN l + omega + +private theorem exists_lt_next_blockStart + (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (n : ℕ) : + ∃ l, n < blockStart N (l + 1) := by + refine ⟨n, ?_⟩ + have h := index_le_blockStart N hN (n + 1) + omega + +/-- The unique block label whose consecutive half-open interval contains `n`. -/ +def blockOf (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (n : ℕ) : ℕ := + Nat.find (exists_lt_next_blockStart N hN n) + +theorem blockOf_spec (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (n : ℕ) : + blockStart N (blockOf N hN n) ≤ n ∧ + n < blockStart N (blockOf N hN n + 1) := by + let hex := exists_lt_next_blockStart N hN n + have hupper : n < blockStart N (blockOf N hN n + 1) := by + exact Nat.find_spec hex + refine ⟨?_, hupper⟩ + cases hb : blockOf N hN n with + | zero => simp + | succ l => + have hminimal : ¬ n < blockStart N (l + 1) := by + have hfind : Nat.find hex = l + 1 := by + simpa only [blockOf] using hb + have hlt : l < Nat.find hex := by + rw [hfind] + exact Nat.lt_succ_self l + exact Nat.find_min hex hlt + simpa only [hb] using Nat.le_of_not_gt hminimal + +/-- The finite interval `I_l = [S_l, S_l + N_l)` used in the paper. -/ +def blockPositions (N : ℕ → ℕ) (_hN : ∀ l, 0 < N l) (l : ℕ) : Finset ℕ := + Finset.Ico (blockStart N l) (blockStart N (l + 1)) + +theorem mem_blockPositions_iff + (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) {l n : ℕ} : + n ∈ blockPositions N hN l ↔ blockOf N hN n = l := by + constructor + · intro hn + have hnIco : blockStart N l ≤ n ∧ n < blockStart N (l + 1) := by + simpa only [blockPositions, Finset.mem_Ico] using hn + obtain ⟨hblo, hbhi⟩ := blockOf_spec N hN n + by_contra hne + rcases lt_or_gt_of_ne hne with hbl | hlb + · have hstarts : blockStart N (blockOf N hN n + 1) ≤ blockStart N l := + (blockStart_strictMono N hN).monotone (Nat.add_one_le_iff.mpr hbl) + omega + · have hstarts : blockStart N (l + 1) ≤ blockStart N (blockOf N hN n) := + (blockStart_strictMono N hN).monotone (Nat.add_one_le_iff.mpr hlb) + omega + · rintro rfl + simpa only [blockPositions, Finset.mem_Ico] using blockOf_spec N hN n + +theorem blockPositions_card + (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (l : ℕ) : + (blockPositions N hN l).card = N l := by + simp [blockPositions, blockStart_succ] + +theorem blockPositions_disjoint + (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) {l k : ℕ} (hlk : l ≠ k) : + Disjoint (blockPositions N hN l) (blockPositions N hN k) := by + rw [Finset.disjoint_left] + intro n hnl hnk + have hl := (mem_blockPositions_iff N hN).mp hnl + have hk := (mem_blockPositions_iff N hN).mp hnk + exact hlk (hl.symm.trans hk) + +theorem mem_blockPositions_blockOf + (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (n : ℕ) : + n ∈ blockPositions N hN (blockOf N hN n) := + (mem_blockPositions_iff N hN).mpr rfl + +/-- The finite blocks are pairwise disjoint and cover all natural-number positions. -/ +theorem iUnion_blockPositions + (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) : + ⋃ l, (blockPositions N hN l : Set ℕ) = Set.univ := by + apply Set.eq_univ_of_forall + intro n + exact Set.mem_iUnion.mpr + ⟨blockOf N hN n, mem_blockPositions_blockOf N hN n⟩ + +theorem blockFiber_finite + (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (l : ℕ) : + {n | blockOf N hN n = l}.Finite := by + have heq : {n | blockOf N hN n = l} = (blockPositions N hN l : Set ℕ) := by + ext n + exact (mem_blockPositions_iff N hN).symm + rw [heq] + exact (blockPositions N hN l).finite_toSet + +/-- Block preprocessing for any prescribed sequence of positive finite sizes. -/ +theorem exists_boundedIndependent_subsequence_for_sizes + {G : Type*} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] + (u : ℕ → G) (hu : Function.Injective u) + (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) : + ∃ φ : ℕ → ℕ, StrictMono φ ∧ + ∀ l, (blockPositions N hN l).card = N l ∧ + BoundedIndependent (M l) + ((blockPositions N hN l).image fun n => u (φ n)) := by + classical + let hfinite : ∀ l, {n | blockOf N hN n = l}.Finite := + blockFiber_finite N hN + obtain ⟨φ, hφ, hind⟩ := + exists_blockwise_boundedIndependent_subsequence u hu (blockOf N hN) M hfinite + refine ⟨φ, hφ, fun l => ⟨blockPositions_card N hN l, ?_⟩⟩ + have hfinset : (hfinite l).toFinset = blockPositions N hN l := by + ext n + simp only [Set.Finite.mem_toFinset, Set.mem_setOf_eq, mem_blockPositions_iff] + simpa only [hfinset] using hind l + +/-! ## The paper's shifted coded sequences -/ + +/-- The basis vector attached to a code's fresh index. -/ +def codeBasisVector (a : ContinuumIndex) : ContinuumFreeGroup := + Finsupp.single (codeIndex a) 1 + +/-- The sequence to which finite bounded-independence extraction is applied. -/ +def codedDifference (a : ContinuumIndex) (n : ℕ) : ContinuumFreeGroup := + codedSequence a n - codeBasisVector a + +theorem codedDifference_injective (a : ContinuumIndex) : + Function.Injective (codedDifference a) := by + intro m n hmn + apply codedSequence_injective a + have h := congrArg (fun z => z + codeBasisVector a) hmn + simpa [codedDifference] using h + +/-- **Full block preprocessing.** For every triangular code and every prescribed positive block +size sequence `N` and coefficient-bound sequence `M`, a genuine subsequence is chosen so that +the shifted values in each block have exactly size `N l` and are `M l`-independent. The original +strict support bound is preserved by passage to the subsequence. -/ +theorem triangular_block_preprocess + (a : ContinuumIndex) + (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) : + ∃ φ : ℕ → ℕ, StrictMono φ ∧ + (∀ l, (blockPositions N hN l).card = N l ∧ + BoundedIndependent (M l) + ((blockPositions N hN l).image fun n => + codedSequence a (φ n) - codeBasisVector a)) ∧ + FiniteCombinatorics.SupportedBelow (codedSequence a ∘ φ) (codeIndex a) := by + obtain ⟨φ, hφ, hblocks⟩ := + exists_boundedIndependent_subsequence_for_sizes + (codedDifference a) (codedDifference_injective a) N hN M + refine ⟨φ, hφ, ?_, ?_⟩ + · simpa only [codedDifference] using hblocks + · intro n i hi + exact codedSequence_supportedBelow a (φ n) i hi + +end +end TriangularPreprocess +end Wallace diff --git a/LeanPool/Wallace/TychonoffWallace.lean b/LeanPool/Wallace/TychonoffWallace.lean new file mode 100644 index 000000000..958f70032 --- /dev/null +++ b/LeanPool/Wallace/TychonoffWallace.lean @@ -0,0 +1,87 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.Main +import Mathlib.Topology.Separation.CompletelyRegular + +/-! +# The commutative Tychonoff Wallace semigroup + +The original Wallace interface records Hausdorffness, countable compactness, cancellation and a +noninvertible element. The paper's printed corollary also says that the witness is commutative +and Tychonoff. This module makes both properties part of the public proposition. +-/ + +namespace Wallace + +noncomputable section + +open TriangularPreprocess + +namespace FullCharacterPackage + +variable {G : Type*} [AddCommGroup G] + +/-- The initial topology is Tychonoff (`T₃.₅` in mathlib), since evaluation embeds the group into +a product of circles. -/ +theorem initial_t35Space (C : FullCharacterPackage G) : + @T35Space G C.initialTopology := by + letI : TopologicalSpace G := C.initialTopology + exact C.evaluation_injective.isEmbedding_induced.t35Space + +end FullCharacterPackage + +namespace SeparationPackage + +variable {I : Type*} + +theorem initial_t35Space (C : SeparationPackage I) : + @T35Space (I →₀ ℤ) C.initialTopology := + C.toFullCharacterPackage.initial_t35Space + +end SeparationPackage + +/-- The exact existential content of the paper's Wallace corollary. The algebraic structure is +explicitly commutative and the separation property is explicitly Tychonoff. -/ +def CommutativeTychonoffWallaceCounterexampleExists : Prop := + ∃ (S : Type) (topology : TopologicalSpace S) (monoid : AddCommMonoid S), + @T35Space S topology ∧ + @IsWallaceSemigroup S topology monoid.toAddMonoid + +/-- The concrete nonnegative cone, with all properties in the printed corollary visible. -/ +theorem continuumPositiveCone_isCommutativeTychonoffWallace : + ∃ topology : TopologicalSpace (positiveCone ContinuumIndex), + @T35Space (positiveCone ContinuumIndex) topology ∧ + @IsWallaceSemigroup (positiveCone ContinuumIndex) topology _ := by + let C : SeparationPackage ContinuumIndex := continuumFullSeparationPackage + let ambientTopology : TopologicalSpace ContinuumFreeGroup := C.initialTopology + letI : TopologicalSpace ContinuumFreeGroup := ambientTopology + letI : IsTopologicalAddGroup ContinuumFreeGroup := C.initial_isTopologicalAddGroup + letI : T2Space ContinuumFreeGroup := C.initial_t2Space + letI : T35Space ContinuumFreeGroup := C.initial_t35Space + letI : Infinite ContinuumIndex := continuumIndex_infinite + let coneTopology : TopologicalSpace (positiveCone ContinuumIndex) := + TopologicalSpace.induced + (fun z : positiveCone ContinuumIndex ↦ (z : ContinuumFreeGroup)) ambientTopology + letI : TopologicalSpace (positiveCone ContinuumIndex) := coneTopology + let i : ContinuumIndex := Classical.choice inferInstance + have hwallace : IsWallaceSemigroup (positiveCone ContinuumIndex) := + positiveCone_isWallace_of_limitProperty ContinuumIndex i + C.positiveCone_hasWallaceLimitProperty + exact ⟨coneTopology, inferInstance, hwallace⟩ + +/-- **Formal counterpart of the paper's Wallace corollary.** There exists a commutative +Tychonoff countably compact topological semigroup with two-sided cancellation which is not a +group. `Wallace.Audit` records the standard classical Lean foundations used by the proof. -/ +theorem commutativeTychonoffWallaceCounterexampleExists : + CommutativeTychonoffWallaceCounterexampleExists := by + obtain ⟨topology, hT35, hwallace⟩ := + continuumPositiveCone_isCommutativeTychonoffWallace + exact ⟨positiveCone ContinuumIndex, topology, inferInstance, hT35, hwallace⟩ + +end + +end Wallace diff --git a/LeanPool/Wallace/UniformKronecker.lean b/LeanPool/Wallace/UniformKronecker.lean new file mode 100644 index 000000000..c095baf83 --- /dev/null +++ b/LeanPool/Wallace/UniformKronecker.lean @@ -0,0 +1,795 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import Mathlib.Algebra.Category.Grp.Injective +import Mathlib.Algebra.Group.Subgroup.Ker +import Mathlib.Algebra.Module.CharacterModule +import Mathlib.Analysis.Fourier.AddCircleMulti +import Mathlib.Analysis.Normed.Group.AddCircle +import Mathlib.Data.Fin.Tuple.Basic +import Mathlib.MeasureTheory.Integral.BoundedContinuousFunction +import Mathlib.MeasureTheory.Measure.Haar.Basic +import Mathlib.Topology.Algebra.Group.ClosedSubgroup +import Mathlib.Topology.ContinuousMap.Bounded.ArzelaAscoli +import Mathlib.Topology.MetricSpace.Closeds +import Mathlib.Topology.MetricSpace.UniformConvergence +import Mathlib.Topology.Sets.VietorisTopology + +/-! +# Algebraic foundations for the uniform Kronecker lemma + +This file isolates the exact (non-quantitative) character-extension argument used in the paper. +The remaining quantitative statement is developed on top of these declarations. +-/ + +open scoped BigOperators + +noncomputable section + +universe u + +namespace Wallace + +open Filter Set TopologicalSpace Topology + +/-- The homomorphism which evaluates an integer relation on a finite tuple. -/ +def relationMap {G : Type u} [AddCommGroup G] {m : ℕ} (z : Fin m → G) : + (Fin m → ℤ) →+ G where + toFun a := ∑ i, a i • z i + map_zero' := by simp + map_add' a b := by + simp only [Pi.add_apply, add_zsmul] + exact Finset.sum_add_distrib + +@[simp] +theorem relationMap_single {G : Type u} [AddCommGroup G] {m : ℕ} + (z : Fin m → G) (i : Fin m) : + relationMap z (Pi.single i 1) = z i := by + classical + simp [relationMap] + +/-- Evaluation of an integer vector on a tuple in the unit additive torus. -/ +def torusRelationMap {m : ℕ} (t : Fin m → UnitAddCircle) : + (Fin m → ℤ) →+ UnitAddCircle := + relationMap t + +@[simp] +theorem torusRelationMap_single {m : ℕ} (t : Fin m → UnitAddCircle) (i : Fin m) : + torusRelationMap t (Pi.single i 1) = t i := + relationMap_single t i + +/-- The subgroup of integer relations on a tuple. -/ +abbrev relationGroup {G : Type u} [AddCommGroup G] {m : ℕ} (z : Fin m → G) : + AddSubgroup (Fin m → ℤ) := + (relationMap z).ker + +theorem mem_relationGroup_iff {G : Type u} [AddCommGroup G] {m : ℕ} + (z : Fin m → G) (a : Fin m → ℤ) : + a ∈ relationGroup z ↔ ∑ i, a i • z i = 0 := by + rfl + +/-- A target tuple respects every relation of `z`. -/ +def RespectsRelations {G : Type u} [AddCommGroup G] {m : ℕ} + (z : Fin m → G) (t : Fin m → UnitAddCircle) : Prop := + (relationMap z).ker ≤ (torusRelationMap t).ker + +theorem respectsRelations_iff {G : Type u} [AddCommGroup G] {m : ℕ} + (z : Fin m → G) (t : Fin m → UnitAddCircle) : + RespectsRelations z t ↔ + ∀ a : Fin m → ℤ, (∑ i, a i • z i = 0) → (∑ i, a i • t i = 0) := by + rfl + +/-- Supremum norm (height) of an integer vector with finite index type. -/ +def intVectorHeight {m : ℕ} (a : Fin m → ℤ) : ℕ := + Finset.univ.sup fun i => (a i).natAbs + +theorem natAbs_le_intVectorHeight {m : ℕ} (a : Fin m → ℤ) (i : Fin m) : + (a i).natAbs ≤ intVectorHeight a := by + exact Finset.le_sup (f := fun j => (a j).natAbs) (Finset.mem_univ i) + +/-- A target tuple respects all relations of height at most `q`. -/ +def RespectsRelationsUpTo {G : Type u} [AddCommGroup G] {m : ℕ} + (q : ℕ) (z : Fin m → G) (t : Fin m → UnitAddCircle) : Prop := + ∀ a : Fin m → ℤ, intVectorHeight a ≤ q → + relationMap z a = 0 → torusRelationMap t a = 0 + +theorem RespectsRelations.respectsRelationsUpTo + {G : Type u} [AddCommGroup G] {m : ℕ} + {z : Fin m → G} {t : Fin m → UnitAddCircle} + (h : RespectsRelations z t) (q : ℕ) : + RespectsRelationsUpTo q z t := by + intro a _ha haz + exact h haz + +/-- `q` is a uniform Kronecker bound for tuples of length `m` and error `ε`. -/ +def IsUniformKroneckerBound (m : ℕ) (ε : ℝ) (q : ℕ) : Prop := + ∀ {G : Type u} [AddCommGroup G] (z : Fin m → G) (t : Fin m → UnitAddCircle), + RespectsRelationsUpTo q z t → + ∃ χ : G →+ UnitAddCircle, ∀ i, ‖χ (z i) - t i‖ < ε + +/-- A target which respects all relations defines a homomorphism on the range generated by the +tuple. -/ +def homOnTupleRange {G : Type u} [AddCommGroup G] {m : ℕ} + (z : Fin m → G) (t : Fin m → UnitAddCircle) + (h : RespectsRelations z t) : (relationMap z).range →+ UnitAddCircle := by + let inv : (relationMap z).range → (Fin m → ℤ) := + Function.surjInv (relationMap z).rangeRestrict_surjective + exact (relationMap z).rangeRestrict.liftOfRightInverse inv + (Function.rightInverse_surjInv (relationMap z).rangeRestrict_surjective) + ⟨torusRelationMap t, by + simpa only [AddMonoidHom.ker_rangeRestrict, RespectsRelations] using h⟩ + +theorem homOnTupleRange_comp {G : Type u} [AddCommGroup G] {m : ℕ} + (z : Fin m → G) (t : Fin m → UnitAddCircle) + (h : RespectsRelations z t) : + (homOnTupleRange z t h).comp (relationMap z).rangeRestrict = torusRelationMap t := by + let inv : (relationMap z).range → (Fin m → ℤ) := + Function.surjInv (relationMap z).rangeRestrict_surjective + exact (relationMap z).rangeRestrict.liftOfRightInverse_comp inv + (Function.rightInverse_surjInv (relationMap z).rangeRestrict_surjective) + ⟨torusRelationMap t, by + simpa only [AddMonoidHom.ker_rangeRestrict, RespectsRelations] using h⟩ + +/-- Exact finite Kronecker extension: a target tuple which respects all integer relations is the +restriction of a character of the ambient Abelian group. -/ +theorem exists_character_of_respectsRelations + {G : Type u} [AddCommGroup G] {m : ℕ} + (z : Fin m → G) (t : Fin m → UnitAddCircle) + (h : RespectsRelations z t) : + ∃ χ : G →+ UnitAddCircle, ∀ i, χ (z i) = t i := by + obtain ⟨χ, hχ⟩ := (Module.Baer.of_divisible UnitAddCircle).extension_property_addMonoidHom + (relationMap z).range.subtype (relationMap z).range.subtype_injective + (homOnTupleRange z t h) + refine ⟨χ, fun i => ?_⟩ + have hcomp : χ.comp (relationMap z).range.subtype = homOnTupleRange z t h := hχ + have hrange := DFunLike.congr_fun hcomp ((relationMap z).rangeRestrict (Pi.single i 1)) + have htuple := DFunLike.congr_fun (homOnTupleRange_comp z t h) (Pi.single i 1) + simpa only [AddMonoidHom.comp_apply, AddSubgroup.coe_subtype, + AddMonoidHom.coe_rangeRestrict, relationMap_single, torusRelationMap_single] using + hrange.trans htuple + +/-- Characters into the unit additive circle separate points of every torsion-free Abelian +group. -/ +theorem exists_character_ne_zero {G : Type u} [AddCommGroup G] [IsAddTorsionFree G] + {x : G} (hx : x ≠ 0) : + ∃ χ : G →+ UnitAddCircle, χ x ≠ 0 := by + let z : Fin 1 → G := fun _ => x + let t : Fin 1 → UnitAddCircle := fun _ => (1 / 2 : ℝ) + have hrel : RespectsRelations z t := by + rw [respectsRelations_iff] + intro a ha + have ha0 : a 0 = 0 := by + have : a 0 • x = 0 := by simpa [z] using ha + exact (IsAddTorsionFree.zsmul_eq_zero_iff_left hx).mp this + simp [t, ha0] + obtain ⟨χ, hχ⟩ := exists_character_of_respectsRelations z t hrel + refine ⟨χ, ?_⟩ + have hχx : χ x = ((1 / 2 : ℝ) : UnitAddCircle) := by simpa [z, t] using hχ 0 + rw [hχx] + intro hzero + rw [AddCircle.coe_eq_zero_iff] at hzero + obtain ⟨n, hn⟩ := hzero + have hnR : (n : ℝ) = 1 / 2 := by simpa using hn + have hn' : (2 : ℝ) * (n : ℝ) = 1 := by linarith + have hnInt : (2 : ℤ) * n = 1 := by exact_mod_cast hn' + omega + +/-! ## Algebraic separation into the real unit circle -/ + +/-- The embedding of the rational additive circle into the real additive circle. -/ +noncomputable def rationalCircleToUnit : AddCircle (1 : ℚ) →+ UnitAddCircle := + QuotientAddGroup.map (AddSubgroup.zmultiples (1 : ℚ)) + (AddSubgroup.zmultiples (1 : ℝ)) (Rat.castHom ℝ).toAddMonoidHom (by + rintro x hx + rw [AddSubgroup.mem_comap] + rw [AddSubgroup.mem_zmultiples_iff] at hx ⊢ + obtain ⟨n, rfl⟩ := hx + exact ⟨n, by simp⟩) + +private theorem rationalCircleToUnit_eq_zero + (x : AddCircle (1 : ℚ)) (hx : rationalCircleToUnit x = 0) : x = 0 := by + induction x using QuotientAddGroup.induction_on + rename_i q + change (((q : ℝ) : UnitAddCircle) = 0) at hx + rw [AddCircle.coe_eq_zero_iff] at hx ⊢ + obtain ⟨n, hn⟩ := hx + refine ⟨n, ?_⟩ + norm_num at hn ⊢ + exact_mod_cast hn + +theorem rationalCircleToUnit_injective : Function.Injective rationalCircleToUnit := by + intro x y hxy + rw [← sub_eq_zero] + apply rationalCircleToUnit_eq_zero + simpa using sub_eq_zero.mpr hxy + +/-- Characters into the real unit circle separate points of every Abelian group. The +`CharacterModule` theorem supplies a rational-circle character and the preceding embedding changes +the codomain without losing its nonzero value. -/ +theorem exists_unit_character_apply_ne_zero + {A : Type u} [AddCommGroup A] {a : A} (ha : a ≠ 0) : + ∃ c : A →+ UnitAddCircle, c a ≠ 0 := by + obtain ⟨c, hc⟩ := CharacterModule.exists_character_apply_ne_zero_of_ne_zero ha + refine ⟨rationalCircleToUnit.comp c, ?_⟩ + intro hz + apply hc + apply rationalCircleToUnit_injective + change rationalCircleToUnit (c a) = 0 at hz + simpa only [map_zero] using hz + +/-! ## Relation annihilators and their distance functions -/ + +/-- The annihilator in the finite torus of a subgroup of integer relations. -/ +def integerAnnihilator {m : ℕ} (R : AddSubgroup (Fin m → ℤ)) : + AddSubgroup (UnitAddTorus (Fin m)) where + carrier := {x | ∀ a ∈ R, torusRelationMap x a = 0} + zero_mem' := by + intro a _ha + simp [torusRelationMap, relationMap] + add_mem' {x y} hx hy a ha := by + change (∀ a ∈ R, ∑ i, a i • x i = 0) at hx + change (∀ a ∈ R, ∑ i, a i • y i = 0) at hy + change ∑ i, a i • (x i + y i) = 0 + simp_rw [smul_add, Finset.sum_add_distrib, hx a ha, hy a ha, add_zero] + neg_mem' {x} hx a ha := by + change (∀ a ∈ R, ∑ i, a i • x i = 0) at hx + change ∑ i, a i • (-x i) = 0 + simp_rw [smul_neg, Finset.sum_neg_distrib, hx a ha, neg_zero] + +@[simp] +theorem mem_integerAnnihilator_iff {m : ℕ} {R : AddSubgroup (Fin m → ℤ)} + {x : UnitAddTorus (Fin m)} : + x ∈ integerAnnihilator R ↔ ∀ a ∈ R, torusRelationMap x a = 0 := + Iff.rfl + +theorem isClosed_integerAnnihilator {m : ℕ} (R : AddSubgroup (Fin m → ℤ)) : + IsClosed (integerAnnihilator R : Set (UnitAddTorus (Fin m))) := by + rw [show (integerAnnihilator R : Set (UnitAddTorus (Fin m))) = + ⋂ a : Fin m → ℤ, ⋂ (_ha : a ∈ R), {x | torusRelationMap x a = 0} by + ext x + simp [integerAnnihilator]] + refine isClosed_biInter fun a _ha ↦ ?_ + change IsClosed {x : UnitAddTorus (Fin m) | (∑ i, a i • x i) = 0} + exact isClosed_singleton.preimage (by fun_prop) + +/-- The annihilator, bundled as a nonempty compact subset of the finite torus. -/ +def integerAnnihilatorCompact {m : ℕ} (R : AddSubgroup (Fin m → ℤ)) : + NonemptyCompacts (UnitAddTorus (Fin m)) := + ⟨⟨integerAnnihilator R, + (isClosed_integerAnnihilator R).isCompact⟩, + ⟨0, (integerAnnihilator R).zero_mem⟩⟩ + +@[simp] +theorem coe_integerAnnihilatorCompact {m : ℕ} (R : AddSubgroup (Fin m → ℤ)) : + (integerAnnihilatorCompact R : Set (UnitAddTorus (Fin m))) = integerAnnihilator R := + rfl + +/-- Distance to the relation annihilator, as a bounded continuous real-valued function. -/ +def annihilatorDistance {m : ℕ} (R : AddSubgroup (Fin m → ℤ)) : + BoundedContinuousFunction (UnitAddTorus (Fin m)) ℝ := + BoundedContinuousFunction.mkOfCompact + (⟨fun x ↦ Metric.infDist x (integerAnnihilator R), + Metric.continuous_infDist_pt _⟩ : C(UnitAddTorus (Fin m), ℝ)) + +@[simp] +theorem annihilatorDistance_apply {m : ℕ} (R : AddSubgroup (Fin m → ℤ)) + (x : UnitAddTorus (Fin m)) : + annihilatorDistance R x = Metric.infDist x (integerAnnihilator R) := + rfl + +theorem annihilatorDistance_lipschitz {m : ℕ} (R : AddSubgroup (Fin m → ℤ)) : + LipschitzWith 1 (annihilatorDistance R) := + Metric.lipschitz_infDist_pt _ + +private theorem intTuple_eq_sum_single {m : ℕ} (a : Fin m → ℤ) : + (∑ i, a i • Pi.single i 1) = a := by + classical + exact (pi_eq_sum_univ' a).symm + +/-- The algebraic double-annihilator direction needed below: if an integer vector is not in +`R`, some point of `R⁺` detects it. -/ +theorem exists_mem_integerAnnihilator_not_annihilate {m : ℕ} + (R : AddSubgroup (Fin m → ℤ)) {a : Fin m → ℤ} (ha : a ∉ R) : + ∃ x ∈ integerAnnihilator R, torusRelationMap x a ≠ 0 := by + have hqa : QuotientAddGroup.mk' R a ≠ 0 := by + intro hzero + exact ha ((QuotientAddGroup.eq_zero_iff a).mp hzero) + obtain ⟨c, hc⟩ := exists_unit_character_apply_ne_zero hqa + let z : Fin m → (Fin m → ℤ) ⧸ R := + fun i ↦ QuotientAddGroup.mk' R (Pi.single i 1) + have hz (b : Fin m → ℤ) : relationMap z b = QuotientAddGroup.mk' R b := by + change (∑ i, b i • QuotientAddGroup.mk' R (Pi.single i 1)) = + QuotientAddGroup.mk' R b + calc + _ = QuotientAddGroup.mk' R (∑ i, b i • Pi.single i 1) := by + rw [map_sum] + simp + _ = QuotientAddGroup.mk' R b := congrArg _ (intTuple_eq_sum_single b) + let x : UnitAddTorus (Fin m) := fun i ↦ c (z i) + have heval (b : Fin m → ℤ) : torusRelationMap x b = c (QuotientAddGroup.mk' R b) := by + change (∑ i, b i • c (z i)) = c (QuotientAddGroup.mk' R b) + calc + _ = c (∑ i, b i • z i) := by + rw [map_sum] + simp + _ = c (relationMap z b) := rfl + _ = c (QuotientAddGroup.mk' R b) := congrArg c (hz b) + refine ⟨x, ?_, ?_⟩ + · intro b hb + rw [heval] + have hb0 : QuotientAddGroup.mk' R b = 0 := + (QuotientAddGroup.eq_zero_iff b).mpr hb + rw [hb0, map_zero] + · simpa only [heval] using hc + +theorem mem_iff_annihilates_integerAnnihilator {m : ℕ} + (R : AddSubgroup (Fin m → ℤ)) (a : Fin m → ℤ) : + a ∈ R ↔ ∀ x ∈ integerAnnihilator R, torusRelationMap x a = 0 := by + constructor + · intro ha x hx + exact hx a ha + · contrapose! + exact exists_mem_integerAnnihilator_not_annihilate R + +theorem mFourier_eq_toCircle_relation {m : ℕ} (a : Fin m → ℤ) + (x : UnitAddTorus (Fin m)) : + UnitAddTorus.mFourier a x = (AddCircle.toCircle (torusRelationMap x a) : ℂ) := by + simp only [UnitAddTorus.mFourier, ContinuousMap.coe_mk, fourier_apply, + torusRelationMap, relationMap] + have hprod (s : Finset (Fin m)) : + (∏ i ∈ s, (AddCircle.toCircle (a i • x i) : ℂ)) = + (AddCircle.toCircle (∑ i ∈ s, a i • x i) : ℂ) := by + induction s using Finset.induction_on with + | empty => simp + | @insert i s hi ih => + rw [Finset.prod_insert hi, Finset.sum_insert hi, AddCircle.toCircle_add, ih] + simp only [Circle.coe_mul] + change (∏ i, (AddCircle.toCircle (a i • x i) : ℂ)) = + (AddCircle.toCircle (∑ i, a i • x i) : ℂ) + simpa only [Finset.prod_const_one, Finset.sum_const_zero] using hprod Finset.univ + +/-- The family of all distance-to-annihilator functions for a fixed tuple length. -/ +def annihilatorDistanceFamily (m : ℕ) : + Set (BoundedContinuousFunction (UnitAddTorus (Fin m)) ℝ) := + Set.range annihilatorDistance + +/-- Arzelà--Ascoli makes the closure of the family of annihilator-distance functions compact. +All functions are `1`-Lipschitz and their ranges lie in one compact interval. -/ +theorem isCompact_closure_annihilatorDistanceFamily (m : ℕ) : + IsCompact (closure (annihilatorDistanceFamily m)) := by + let D : ℝ := Metric.diam (Set.univ : Set (UnitAddTorus (Fin m))) + apply BoundedContinuousFunction.arzela_ascoli (Set.Icc 0 D) isCompact_Icc + · rintro f x ⟨R, rfl⟩ + refine ⟨Metric.infDist_nonneg, ?_⟩ + calc + Metric.infDist x (integerAnnihilator R) ≤ dist x 0 := + Metric.infDist_le_dist_of_mem (integerAnnihilator R).zero_mem + _ ≤ D := Metric.dist_le_diam_of_mem isCompact_univ.isBounded + (mem_univ x) (mem_univ 0) + · apply UniformEquicontinuous.equicontinuous + apply LipschitzWith.uniformEquicontinuous _ 1 + rintro ⟨f, R, rfl⟩ + exact annihilatorDistance_lipschitz R + +/-- Regard a bounded real-valued continuous function on the compact torus as a complex-valued +continuous function. -/ +def complexifyDistanceFunction {m : ℕ} + (f : BoundedContinuousFunction (UnitAddTorus (Fin m)) ℝ) : + C(UnitAddTorus (Fin m), ℂ) := + ⟨fun x ↦ (f x : ℂ), Complex.continuous_ofReal.comp f.continuous⟩ + +/-- The family occurring in the paper's uniform-frequency-set lemma: real-valued functions on +the finite torus which are `1`-Lipschitz and take their values in `[0, 1 / 2]`. -/ +def oneLipschitzHalfRangeFamily (m : ℕ) : + Set (BoundedContinuousFunction (UnitAddTorus (Fin m)) ℝ) := + {f | LipschitzWith 1 f ∧ ∀ x, f x ∈ Set.Icc (0 : ℝ) (1 / 2)} + +/-- Arzelà--Ascoli compactness for the family in the uniform-frequency-set lemma. We retain +the closure in the statement because that is exactly the form supplied by Mathlib's version of +Arzelà--Ascoli; membership of the original family is enough for every application below. -/ +theorem isCompact_closure_oneLipschitzHalfRangeFamily (m : ℕ) : + IsCompact (closure (oneLipschitzHalfRangeFamily m)) := by + apply BoundedContinuousFunction.arzela_ascoli (Set.Icc (0 : ℝ) (1 / 2)) isCompact_Icc + · intro f x hf + exact hf.2 x + · apply UniformEquicontinuous.equicontinuous + apply LipschitzWith.uniformEquicontinuous _ 1 + rintro ⟨f, hf⟩ + exact hf.1 + +/-- A compact family of real-valued continuous functions on a finite torus admits one finite +Fourier support which works, with error `2 * δ`, for every member of the family. -/ +private theorem exists_finite_frequency_approximation_of_compact + (m : ℕ) (A : Set (BoundedContinuousFunction (UnitAddTorus (Fin m)) ℝ)) + (hA : IsCompact A) {δ : ℝ} (hδ : 0 < δ) : + ∃ S : Finset (Fin m → ℤ), ∀ f ∈ A, + ∃ c : (Fin m → ℤ) →₀ ℂ, c.support ⊆ S ∧ + ∀ x : UnitAddTorus (Fin m), + ‖(c.sum fun a z ↦ z • UnitAddTorus.mFourier a) x - (f x : ℂ)‖ < 2 * δ := by + classical + obtain ⟨T, hTA, hTfin, hcover⟩ := hA.finite_cover_balls hδ + have hpoly (g : A) : ∃ c : (Fin m → ℤ) →₀ ℂ, + ∀ x : UnitAddTorus (Fin m), + ‖(c.sum fun a z ↦ z • UnitAddTorus.mFourier a) x - + (complexifyDistanceFunction g.1) x‖ < δ := by + let V : Submodule ℂ C(UnitAddTorus (Fin m), ℂ) := + Submodule.span ℂ (Set.range UnitAddTorus.mFourier) + have hg_top : complexifyDistanceFunction g.1 ∈ V.topologicalClosure := by + rw [show V.topologicalClosure = ⊤ from UnitAddTorus.span_mFourier_closure_eq_top] + exact Submodule.mem_top + have hg_closure : complexifyDistanceFunction g.1 ∈ closure (V : Set _) := + (Submodule.mem_closure_iff).mpr hg_top + obtain ⟨P, hPV, hgP⟩ := (Metric.mem_closure_iff.mp hg_closure) δ hδ + obtain ⟨c, rfl⟩ := Finsupp.mem_span_range_iff_exists_finsupp.mp hPV + refine ⟨c, fun x ↦ ?_⟩ + calc + ‖(c.sum fun a z ↦ z • UnitAddTorus.mFourier a) x - + (complexifyDistanceFunction g.1) x‖ = + ‖((c.sum fun a z ↦ z • UnitAddTorus.mFourier a) - + complexifyDistanceFunction g.1) x‖ := rfl + _ ≤ ‖(c.sum fun a z ↦ z • UnitAddTorus.mFourier a) - + complexifyDistanceFunction g.1‖ := + ContinuousMap.norm_coe_le_norm _ x + _ = dist (c.sum fun a z ↦ z • UnitAddTorus.mFourier a) + (complexifyDistanceFunction g.1) := by rw [dist_eq_norm] + _ < δ := by simpa only [dist_comm] using hgP + letI : Fintype T := hTfin.fintype + choose coeff hcoeff using fun g : T ↦ hpoly ⟨g.1, hTA g.2⟩ + let S : Finset (Fin m → ℤ) := Finset.univ.biUnion fun g : T ↦ (coeff g).support + refine ⟨S, fun f hfA ↦ ?_⟩ + obtain ⟨g, hgT, hfg⟩ := Set.mem_iUnion₂.mp (hcover hfA) + let gT : T := ⟨g, hgT⟩ + refine ⟨coeff gT, ?_, fun x ↦ ?_⟩ + · intro a ha + exact Finset.mem_biUnion.mpr ⟨gT, Finset.mem_univ _, ha⟩ + · calc + ‖((coeff gT).sum (fun a z ↦ z • UnitAddTorus.mFourier a)) x - (f x : ℂ)‖ ≤ + ‖((coeff gT).sum (fun a z ↦ z • UnitAddTorus.mFourier a)) x - + (g x : ℂ)‖ + ‖(g x : ℂ) - (f x : ℂ)‖ := by + rw [show + ((coeff gT).sum (fun a z ↦ z • UnitAddTorus.mFourier a)) x - (f x : ℂ) = + (((coeff gT).sum (fun a z ↦ z • UnitAddTorus.mFourier a)) x - + (g x : ℂ)) + ((g x : ℂ) - (f x : ℂ)) by ring] + exact norm_add_le _ _ + _ < δ + δ := add_lt_add (hcoeff gT x) (by + calc + ‖(g x : ℂ) - (f x : ℂ)‖ = |g x - f x| := by + rw [← Complex.ofReal_sub, Complex.norm_real, Real.norm_eq_abs] + _ < δ := by + simpa only [abs_sub_comm, Real.dist_eq] using lt_of_le_of_lt + (BoundedContinuousFunction.dist_coe_le_dist x) hfg) + _ = 2 * δ := by ring + +/-- **Uniform finite frequency set (paper, Lemma `uniform-frequency-set`).** + +For every dimension and every positive error there is a finite set of integer frequencies such +that every real-valued `1`-Lipschitz function with values in `[0, 1 / 2]` is uniformly approximated +by a trigonometric polynomial supported on that same set. The paper assumes `1 ≤ m`; the +formal statement is slightly stronger, since it also holds for `m = 0`. -/ +theorem exists_uniform_frequency_set (m : ℕ) {η : ℝ} (hη : 0 < η) : + ∃ S : Finset (Fin m → ℤ), + ∀ f : BoundedContinuousFunction (UnitAddTorus (Fin m)) ℝ, + LipschitzWith 1 f → + (∀ x, f x ∈ Set.Icc (0 : ℝ) (1 / 2)) → + ∃ c : (Fin m → ℤ) →₀ ℂ, c.support ⊆ S ∧ + ∀ x : UnitAddTorus (Fin m), + ‖(c.sum fun a z ↦ z • UnitAddTorus.mFourier a) x - (f x : ℂ)‖ < η := by + let δ : ℝ := η / 2 + have hδ : 0 < δ := by + dsimp [δ] + positivity + let A := closure (oneLipschitzHalfRangeFamily m) + have hA : IsCompact A := isCompact_closure_oneLipschitzHalfRangeFamily m + obtain ⟨S, hS⟩ := exists_finite_frequency_approximation_of_compact m A hA hδ + refine ⟨S, fun f hfLip hfRange ↦ ?_⟩ + have hfA : f ∈ A := subset_closure ⟨hfLip, hfRange⟩ + obtain ⟨c, hcS, hc⟩ := hS f hfA + refine ⟨c, hcS, fun x ↦ ?_⟩ + have htwo : 2 * δ = η := by + dsimp [δ] + ring + simpa only [htwo] using hc x + +/-- Uniform finite Fourier approximation for all annihilator-distance functions of a fixed +dimension. Compactness is used only here: it turns the frequency support, initially depending on +the subgroup, into one finite set. -/ +theorem exists_finite_frequency_approximation (m : ℕ) {δ : ℝ} (hδ : 0 < δ) : + ∃ S : Finset (Fin m → ℤ), ∀ R : AddSubgroup (Fin m → ℤ), + ∃ c : (Fin m → ℤ) →₀ ℂ, c.support ⊆ S ∧ + ∀ x : UnitAddTorus (Fin m), + ‖(c.sum fun a z ↦ z • UnitAddTorus.mFourier a) x - + (annihilatorDistance R x : ℂ)‖ < 2 * δ := by + have htwoδ : 0 < 2 * δ := by positivity + obtain ⟨S, hS⟩ := exists_uniform_frequency_set m htwoδ + refine ⟨S, fun R ↦ hS (annihilatorDistance R) (annihilatorDistance_lipschitz R) ?_⟩ + intro x + refine ⟨Metric.infDist_nonneg, ?_⟩ + calc + Metric.infDist x (integerAnnihilator R) ≤ dist x 0 := + Metric.infDist_le_dist_of_mem (integerAnnihilator R).zero_mem + _ ≤ 1 / 2 := by + refine (dist_pi_le_iff (by positivity)).2 fun i ↦ ?_ + simpa only [Pi.zero_apply, dist_zero_right, abs_one] using + (AddCircle.norm_le_half_period (p := (1 : ℝ)) (x := x i) one_ne_zero) + +/-! ## Averaging over a relation annihilator -/ + +private noncomputable def annihilatorHaarMeasure {m : ℕ} + (R : AddSubgroup (Fin m → ℤ)) : MeasureTheory.Measure (integerAnnihilator R) := + letI : CompactSpace (integerAnnihilator R) := + isCompact_iff_compactSpace.mp (isClosed_integerAnnihilator R).isCompact + MeasureTheory.Measure.addHaarMeasure ⊤ + +private instance annihilatorHaar_isProbability {m : ℕ} + (R : AddSubgroup (Fin m → ℤ)) : + MeasureTheory.IsProbabilityMeasure (annihilatorHaarMeasure R) := by + letI : CompactSpace (integerAnnihilator R) := + isCompact_iff_compactSpace.mp (isClosed_integerAnnihilator R).isCompact + constructor + change MeasureTheory.Measure.addHaarMeasure (⊤ : PositiveCompacts (integerAnnihilator R)) + Set.univ = 1 + rw [← PositiveCompacts.coe_top] + exact MeasureTheory.Measure.addHaarMeasure_self + +private theorem integral_mFourier_translate {m : ℕ} + (R : AddSubgroup (Fin m → ℤ)) (a : Fin m → ℤ) + (x : UnitAddTorus (Fin m)) : + (∫ h : integerAnnihilator R, UnitAddTorus.mFourier a (x + h.1) + ∂(annihilatorHaarMeasure R)) = + UnitAddTorus.mFourier a x * + ∫ h : integerAnnihilator R, UnitAddTorus.mFourier a h.1 + ∂(annihilatorHaarMeasure R) := by + letI : CompactSpace (integerAnnihilator R) := + isCompact_iff_compactSpace.mp (isClosed_integerAnnihilator R).isCompact + rw [← MeasureTheory.integral_const_mul] + apply MeasureTheory.integral_congr_ae + filter_upwards [] with h + change (∏ i, fourier (a i) (x i + h.1 i)) = + (∏ i, fourier (a i) (x i)) * ∏ i, fourier (a i) (h.1 i) + simp only [fourier_apply, zsmul_add, AddCircle.toCircle_add, + Circle.coe_mul, Finset.prod_mul_distrib] + +private theorem integral_mFourier_eq_zero_of_not_mem {m : ℕ} + (R : AddSubgroup (Fin m → ℤ)) {a : Fin m → ℤ} (ha : a ∉ R) : + (∫ h : integerAnnihilator R, UnitAddTorus.mFourier a h.1 + ∂(annihilatorHaarMeasure R)) = 0 := by + letI : CompactSpace (integerAnnihilator R) := + isCompact_iff_compactSpace.mp (isClosed_integerAnnihilator R).isCompact + obtain ⟨x, hxR, hxa⟩ := exists_mem_integerAnnihilator_not_annihilate R ha + let xR : integerAnnihilator R := ⟨x, hxR⟩ + let I : ℂ := ∫ h : integerAnnihilator R, UnitAddTorus.mFourier a h.1 + ∂(annihilatorHaarMeasure R) + let K : PositiveCompacts (integerAnnihilator R) := ⊤ + have hmeasure : annihilatorHaarMeasure R = + MeasureTheory.Measure.addHaarMeasure K := rfl + letI : (annihilatorHaarMeasure R).IsAddLeftInvariant := by + rw [hmeasure] + infer_instance + have hinv : (∫ h : integerAnnihilator R, + UnitAddTorus.mFourier a (xR.1 + h.1) ∂(annihilatorHaarMeasure R)) = I := by + have htranslate := MeasureTheory.integral_add_left_eq_self + (fun h : integerAnnihilator R ↦ UnitAddTorus.mFourier a h.1) xR + (μ := annihilatorHaarMeasure R) + simpa only [I, AddSubgroup.coe_add] using htranslate + have hscalar : UnitAddTorus.mFourier a x * I = I := by + rw [← integral_mFourier_translate R a x] + exact hinv + have hfactor : UnitAddTorus.mFourier a x ≠ 1 := by + intro hone + have hcirc : AddCircle.toCircle (torusRelationMap x a) = 1 := by + apply Subtype.ext + simpa [mFourier_eq_toCircle_relation] using hone + exact hxa <| AddCircle.injective_toCircle one_ne_zero <| by + simpa using hcirc + by_contra hI + apply hfactor + exact mul_right_cancel₀ hI (by simpa only [one_mul] using hscalar) + +private theorem integral_mFourier_eq_one_of_mem {m : ℕ} + (R : AddSubgroup (Fin m → ℤ)) {a : Fin m → ℤ} (ha : a ∈ R) : + (∫ h : integerAnnihilator R, UnitAddTorus.mFourier a h.1 + ∂(annihilatorHaarMeasure R)) = 1 := by + letI : CompactSpace (integerAnnihilator R) := + isCompact_iff_compactSpace.mp (isClosed_integerAnnihilator R).isCompact + have hone : ∀ h : integerAnnihilator R, UnitAddTorus.mFourier a h.1 = 1 := by + intro h + rw [mFourier_eq_toCircle_relation, h.2 a ha, AddCircle.toCircle_zero] + rfl + simp_rw [hone] + simp + +/-- Averaging a finite Fourier polynomial over a translated annihilator deletes exactly the +frequencies which are not relations. -/ +private noncomputable def filteredFourierTerm {m : ℕ} + (R : AddSubgroup (Fin m → ℤ)) (a : Fin m → ℤ) (z : ℂ) + (x : UnitAddTorus (Fin m)) : ℂ := by + classical + exact if a ∈ R then z * UnitAddTorus.mFourier a x else 0 + +private theorem integral_fourierPolynomial_translate {m : ℕ} + (R : AddSubgroup (Fin m → ℤ)) (c : (Fin m → ℤ) →₀ ℂ) + (x : UnitAddTorus (Fin m)) : + (∫ h : integerAnnihilator R, + (c.sum fun a z ↦ z • UnitAddTorus.mFourier a) (x + h.1) + ∂(annihilatorHaarMeasure R)) = + c.sum fun a z ↦ filteredFourierTerm R a z x := by + classical + letI : CompactSpace (integerAnnihilator R) := + isCompact_iff_compactSpace.mp (isClosed_integerAnnihilator R).isCompact + rw [Finsupp.sum_of_support_subset c (s := c.support) Subset.rfl _ (by + intro a _ha + exact zero_smul ℂ (UnitAddTorus.mFourier a))] + simp_rw [ContinuousMap.sum_apply] + rw [Finsupp.sum_of_support_subset c (s := c.support) Subset.rfl _ (by + intro a _ha + simp [filteredFourierTerm])] + rw [MeasureTheory.integral_finsetSum c.support] + · apply Finset.sum_congr rfl + intro a ha + simp_rw [ContinuousMap.smul_apply, smul_eq_mul] + rw [MeasureTheory.integral_const_mul, integral_mFourier_translate R a x] + by_cases haR : a ∈ R + · rw [filteredFourierTerm, if_pos haR, + integral_mFourier_eq_one_of_mem R haR, mul_one] + · rw [filteredFourierTerm, if_neg haR, + integral_mFourier_eq_zero_of_not_mem R haR, mul_zero, mul_zero] + · intro a _ha + apply MeasureTheory.Integrable.const_mul + exact (UnitAddTorus.mFourier a).continuous.comp + (continuous_const.add continuous_subtype_val) + |>.continuousOn.integrableOn_compact isCompact_univ |> + MeasureTheory.integrableOn_univ.mp + +/-- A target satisfying all frequencies in `c.support` is close to the corresponding annihilator. +This is the quantitative conclusion extracted from the averaged finite Fourier approximation. -/ +theorem infDist_integerAnnihilator_lt_of_finite_relations {m : ℕ} {δ : ℝ} (_hδ : 0 < δ) + {S : Finset (Fin m → ℤ)} + (hS : ∀ R : AddSubgroup (Fin m → ℤ), + ∃ c : (Fin m → ℤ) →₀ ℂ, c.support ⊆ S ∧ + ∀ x : UnitAddTorus (Fin m), + ‖(c.sum fun a z ↦ z • UnitAddTorus.mFourier a) x - + (annihilatorDistance R x : ℂ)‖ < 2 * δ) + (R : AddSubgroup (Fin m → ℤ)) (t : UnitAddTorus (Fin m)) + (ht : ∀ a ∈ S, a ∈ R → torusRelationMap t a = 0) : + Metric.infDist t (integerAnnihilator R) ≤ 4 * δ := by + classical + letI : CompactSpace (integerAnnihilator R) := + isCompact_iff_compactSpace.mp (isClosed_integerAnnihilator R).isCompact + obtain ⟨c, hcS, hc⟩ := hS R + let P : C(UnitAddTorus (Fin m), ℂ) := c.sum fun a z ↦ z • UnitAddTorus.mFourier a + have haverage : + (∫ h : integerAnnihilator R, P (t + h.1) ∂(annihilatorHaarMeasure R)) = + ∫ h : integerAnnihilator R, P h.1 ∂(annihilatorHaarMeasure R) := by + rw [integral_fourierPolynomial_translate] + have hzero := integral_fourierPolynomial_translate R c 0 + simp only [zero_add] at hzero + rw [hzero] + apply Finsupp.sum_congr + intro a ha + have haS : a ∈ S := hcS ha + by_cases haR : a ∈ R + · simp only [filteredFourierTerm, if_pos haR] + have hat : torusRelationMap t a = 0 := ht a haS haR + rw [mFourier_eq_toCircle_relation, hat, AddCircle.toCircle_zero] + simp [UnitAddTorus.mFourier] + · simp only [filteredFourierTerm, if_neg haR] + have hdistInvariant : ∀ h : integerAnnihilator R, + annihilatorDistance R (t + h.1) = annihilatorDistance R t := by + intro h + simp only [annihilatorDistance_apply] + rw [← QuotientAddGroup.norm_mk (S := integerAnnihilator R), + ← QuotientAddGroup.norm_mk (S := integerAnnihilator R)] + congr 1 + exact (QuotientAddGroup.eq_iff_sub_mem).mpr (by simp [h.2]) + have hdistZero : ∀ h : integerAnnihilator R, + annihilatorDistance R h.1 = 0 := by + intro h + rw [annihilatorDistance_apply] + exact Metric.infDist_zero_of_mem h.2 + let It : ℂ := ∫ h : integerAnnihilator R, P (t + h.1) + ∂(annihilatorHaarMeasure R) + let I0 : ℂ := ∫ h : integerAnnihilator R, P h.1 + ∂(annihilatorHaarMeasure R) + have hIt : ‖It - (annihilatorDistance R t : ℂ)‖ ≤ 2 * δ := by + have hPint : MeasureTheory.Integrable + (fun h : integerAnnihilator R ↦ P (t + h.1)) + (annihilatorHaarMeasure R) := + (P.continuous.comp (continuous_const.add continuous_subtype_val)).continuousOn + |>.integrableOn_compact isCompact_univ |> + (MeasureTheory.integrableOn_univ.mp) + have hconstint : MeasureTheory.Integrable + (fun _ : integerAnnihilator R ↦ (annihilatorDistance R t : ℂ)) + (annihilatorHaarMeasure R) := MeasureTheory.integrable_const _ + have hconst : + (∫ _ : integerAnnihilator R, (annihilatorDistance R t : ℂ) + ∂(annihilatorHaarMeasure R)) = (annihilatorDistance R t : ℂ) := by + simp + have hsub : + (∫ h : integerAnnihilator R, + (P (t + h.1) - (annihilatorDistance R t : ℂ)) + ∂(annihilatorHaarMeasure R)) = + It - (annihilatorDistance R t : ℂ) := by + rw [MeasureTheory.integral_sub hPint hconstint, hconst] + rw [← hsub] + simpa using MeasureTheory.norm_integral_le_of_norm_le_const + (μ := annihilatorHaarMeasure R) (Eventually.of_forall fun h ↦ + (by simpa [hdistInvariant h] using (hc (t + h.1)).le)) + have hI0 : ‖I0‖ ≤ 2 * δ := by + rw [show I0 = ∫ h : integerAnnihilator R, P h.1 - 0 + ∂(annihilatorHaarMeasure R) by simp [I0]] + simpa using MeasureTheory.norm_integral_le_of_norm_le_const + (μ := annihilatorHaarMeasure R) (Eventually.of_forall fun h ↦ by + simpa [hdistZero h] using (hc h.1).le) + have hII : It = I0 := haverage + have hnorm : ‖(annihilatorDistance R t : ℂ)‖ ≤ 4 * δ := by + calc + ‖(annihilatorDistance R t : ℂ)‖ ≤ + ‖It - (annihilatorDistance R t : ℂ)‖ + ‖It‖ := by + calc + ‖(annihilatorDistance R t : ℂ)‖ = + ‖((annihilatorDistance R t : ℂ) - It) + It‖ := by ring_nf + _ ≤ ‖(annihilatorDistance R t : ℂ) - It‖ + ‖It‖ := norm_add_le _ _ + _ = ‖It - (annihilatorDistance R t : ℂ)‖ + ‖It‖ := by + rw [norm_sub_rev] + _ ≤ 2 * δ + 2 * δ := by + exact add_le_add hIt (by simpa [hII] using hI0) + _ = 4 * δ := by ring + simpa [annihilatorDistance_apply, Complex.norm_real, Real.norm_eq_abs, + abs_of_nonneg Metric.infDist_nonneg] using hnorm + +/-- A uniform Kronecker bound remains valid when the permitted relation height is increased. -/ +theorem IsUniformKroneckerBound.mono {m q q' : ℕ} {ε : ℝ} + (h : IsUniformKroneckerBound.{u} m ε q) (hqq' : q ≤ q') : + IsUniformKroneckerBound.{u} m ε q' := by + intro G _ z t ht + apply h (G := G) z t + intro a ha haz + exact ht a (ha.trans hqq') haz + +/-- Unconditional uniform finite-dimensional Kronecker theorem. + +For every tuple length and every positive error, a single finite height bound detects enough +integer relations to guarantee approximation by a character of every Abelian group. -/ +theorem exists_uniform_kronecker_bound (m : ℕ) {ε : ℝ} (hε : 0 < ε) : + ∃ q : ℕ, IsUniformKroneckerBound.{u} m ε q := by + classical + let δ : ℝ := ε / 8 + have hδ : 0 < δ := by + dsimp [δ] + positivity + obtain ⟨S, hS⟩ := exists_finite_frequency_approximation m hδ + let q : ℕ := max 1 (S.sup intVectorHeight) + refine ⟨q, ?_⟩ + intro G _ z t ht + let R : AddSubgroup (Fin m → ℤ) := relationGroup z + have hfinite : ∀ a ∈ S, a ∈ R → torusRelationMap t a = 0 := by + intro a haS haR + apply ht a + · exact (Finset.le_sup haS).trans (Nat.le_max_right 1 _) + · exact haR + have hdist : Metric.infDist t (integerAnnihilator R) ≤ 4 * δ := + infDist_integerAnnihilator_lt_of_finite_relations hδ hS R t hfinite + have hdistlt : Metric.infDist t (integerAnnihilator R) < ε := by + apply hdist.trans_lt + dsimp [δ] + linarith + have hnonempty : (integerAnnihilator R : Set (UnitAddTorus (Fin m))).Nonempty := + ⟨0, (integerAnnihilator R).zero_mem⟩ + obtain ⟨x, hx, htx⟩ := (Metric.infDist_lt_iff hnonempty).mp hdistlt + have hrelations : RespectsRelations z x := by + intro a ha + exact hx a ha + obtain ⟨χ, hχ⟩ := exists_character_of_respectsRelations z x hrelations + refine ⟨χ, fun i ↦ ?_⟩ + have hi : dist (t i) (x i) < ε := (dist_pi_lt_iff hε).mp htx i + simpa only [hχ i, ← dist_eq_norm, dist_comm] using hi + +/-- Camel-case compatibility spelling for downstream modules. -/ +theorem exists_uniformKroneckerBound (m : ℕ) {ε : ℝ} (hε : 0 < ε) : + ∃ q : ℕ, IsUniformKroneckerBound.{u} m ε q := + exists_uniform_kronecker_bound m hε + +end Wallace From 6455c802467ebc94644f42360c184424aeb2051e Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 4 Sep 2026 13:29:58 +0000 Subject: [PATCH 2/7] Prune unused Wallace declarations --- LeanPool/Wallace/BlockFilters.lean | 62 ---- LeanPool/Wallace/ConcreteClosure.lean | 6 - LeanPool/Wallace/ConcreteData.lean | 21 -- LeanPool/Wallace/ConcreteLocalSetup.lean | 62 ---- LeanPool/Wallace/CountableClosure.lean | 12 - LeanPool/Wallace/FiniteCombinatorics.lean | 58 ---- LeanPool/Wallace/FullTopology.lean | 9 - LeanPool/Wallace/FullTopologyMain.lean | 24 -- LeanPool/Wallace/FusionLimit.lean | 30 -- LeanPool/Wallace/FusionSchedule.lean | 32 -- LeanPool/Wallace/FusionStage.lean | 37 --- LeanPool/Wallace/GeneralMain.lean | 9 - LeanPool/Wallace/GlobalAssembly.lean | 8 - LeanPool/Wallace/InitialCharacter.lean | 10 - LeanPool/Wallace/LocalEnumeration.lean | 6 - LeanPool/Wallace/LocalFusion.lean | 52 ---- LeanPool/Wallace/Main.lean | 37 --- LeanPool/Wallace/MathlibFoundations.lean | 276 ------------------ LeanPool/Wallace/NontrivialSequences.lean | 26 -- LeanPool/Wallace/RationalClosure.lean | 18 -- LeanPool/Wallace/RationalData.lean | 21 -- LeanPool/Wallace/RationalFusionRun.lean | 9 - LeanPool/Wallace/RationalLocalSetup.lean | 61 ---- .../Wallace/RationalTriangularPreprocess.lean | 5 - LeanPool/Wallace/Result.lean | 38 --- LeanPool/Wallace/SeparationInterface.lean | 22 -- LeanPool/Wallace/TorsionFreeCoordinate.lean | 48 --- LeanPool/Wallace/TriangularPreprocess.lean | 60 ---- LeanPool/Wallace/UniformKronecker.lean | 89 ------ 29 files changed, 1148 deletions(-) diff --git a/LeanPool/Wallace/BlockFilters.lean b/LeanPool/Wallace/BlockFilters.lean index 9e8cdc5e7..5bf5886c7 100644 --- a/LeanPool/Wallace/BlockFilters.lean +++ b/LeanPool/Wallace/BlockFilters.lean @@ -258,54 +258,6 @@ theorem disjointize_loss_finite [LinearOrder ι] (family : ι → Set α) rcases Set.mem_iUnion.mp hxi with ⟨hi, hxFamily⟩ exact Set.mem_iUnion_of_mem i <| Set.mem_iUnion_of_mem hi ⟨hxj, hxFamily⟩ -/-- Equivalent modulo a finite set, phrased as eventual equality on the cofinite filter. -/ -theorem disjointize_eventuallyEq [LinearOrder ι] (family : ι → Set α) - (had : Pairwise fun i j ↦ (family i ∩ family j).Finite) (j : ι) - (hpred : (Set.Iio j).Finite) : - (fun x ↦ x ∈ disjointize family j) =ᶠ[cofinite] (fun x ↦ x ∈ family j) := by - have hloss := disjointize_loss_finite family had j hpred - filter_upwards [hloss.compl_mem_cofinite] with x hx - apply propext - constructor - · exact fun hxdis ↦ disjointize_subset family j hxdis - · intro hxj - by_contra hxdis - exact hx ⟨hxj, hxdis⟩ - -/-- Countable-family specialization: at stage `j : ℕ`, there are finitely many predecessors. -/ -theorem disjointize_eventuallyEq_nat (family : ℕ → Set α) - (had : Pairwise fun i j ↦ (family i ∩ family j).Finite) (j : ℕ) : - (fun x ↦ x ∈ disjointize family j) =ᶠ[cofinite] (fun x ↦ x ∈ family j) := - disjointize_eventuallyEq family had j (Set.finite_Iio j) - -/-- Finite-family specialization. A finite family can be put in any linear order. -/ -theorem disjointize_eventuallyEq_finite [LinearOrder ι] [Finite ι] - (family : ι → Set α) (had : Pairwise fun i j ↦ (family i ∩ family j).Finite) (j : ι) : - (fun x ↦ x ∈ disjointize family j) =ᶠ[cofinite] (fun x ↦ x ∈ family j) := - disjointize_eventuallyEq family had j (Set.toFinite _) - -/-- Bundled countable version of the paper's disjointization assertion. -/ -theorem exists_disjoint_refinement_nat (family : ℕ → Set α) - (had : Pairwise fun i j ↦ (family i ∩ family j).Finite) : - ∃ refined : ℕ → Set α, - (Pairwise fun i j ↦ Disjoint (refined i) (refined j)) ∧ - ∀ j, refined j ⊆ family j ∧ - (fun x ↦ x ∈ refined j) =ᶠ[cofinite] (fun x ↦ x ∈ family j) := by - refine ⟨disjointize family, pairwise_disjoint_disjointize family, ?_⟩ - intro j - exact ⟨disjointize_subset family j, disjointize_eventuallyEq_nat family had j⟩ - -/-- Bundled finite version of the paper's disjointization assertion. -/ -theorem exists_disjoint_refinement_finite [LinearOrder ι] [Finite ι] - (family : ι → Set α) (had : Pairwise fun i j ↦ (family i ∩ family j).Finite) : - ∃ refined : ι → Set α, - (Pairwise fun i j ↦ Disjoint (refined i) (refined j)) ∧ - ∀ j, refined j ⊆ family j ∧ - (fun x ↦ x ∈ refined j) =ᶠ[cofinite] (fun x ↦ x ∈ family j) := by - refine ⟨disjointize family, pairwise_disjoint_disjointize family, ?_⟩ - intro j - exact ⟨disjointize_subset family j, disjointize_eventuallyEq_finite family had j⟩ - end AlmostDisjoint namespace BlockSystem @@ -385,20 +337,6 @@ theorem retainedBlocks_mem_densityFilter_ofBlockPositions apply (ofBlockPositions N hN).retainedBlocks_mem_densityFilter E R hab hE hcard simpa only [ofBlockPositions_card] using hratio -/-- A free ultrafilter extension can be chosen to contain every retained set supplied by -the preceding lemma. -/ -theorem exists_free_ultrafilter_with_retainedBlocks (B : BlockSystem) {a b : Set ℕ} - (ha : a.Infinite) (E : ℕ → Finset ℕ) (R : ℕ → ℕ) - (hab : (a \ b).Finite) (hE : ∀ l, E l ⊆ B.block l) - (hcard : ∀ l ∈ b, (E l).card ≤ R l) - (hratio : Tendsto (fun l ↦ (R l : ℝ) / ((B.block l).card : ℝ)) atTop (nhds 0)) : - ∃ p : Ultrafilter ℕ, - (p : Filter ℕ) ≤ B.densityFilter a ∧ (p : Filter ℕ) ≤ cofinite ∧ - B.retainedBlocks b E ∈ p := by - rcases B.exists_free_ultrafilter_le_densityFilter ha with ⟨p, hpD, hpFree⟩ - refine ⟨p, hpD, hpFree, hpD ?_⟩ - exact B.retainedBlocks_mem_densityFilter E R hab hE hcard hratio - end BlockSystem end diff --git a/LeanPool/Wallace/ConcreteClosure.lean b/LeanPool/Wallace/ConcreteClosure.lean index a00d3d4e0..56db43176 100644 --- a/LeanPool/Wallace/ConcreteClosure.lean +++ b/LeanPool/Wallace/ConcreteClosure.lean @@ -80,12 +80,6 @@ def enumeration {x : ContinuumFreeGroup} (hx : x ≠ 0) : letI : Nonempty (closure N hN M x) := (closure_nonempty N hN M hx).to_subtype exact Classical.choose (exists_surjective_nat (closure N hN M x)) -theorem enumeration_surjective {x : ContinuumFreeGroup} (hx : x ≠ 0) : - Function.Surjective (enumeration N hN M hx) := by - letI : Countable (closure N hN M x) := (closure_countable N hN M x).to_subtype - letI : Nonempty (closure N hN M x) := (closure_nonempty N hN M hx).to_subtype - exact Classical.choose_spec (exists_surjective_nat (closure N hN M x)) - end end ConcreteClosure diff --git a/LeanPool/Wallace/ConcreteData.lean b/LeanPool/Wallace/ConcreteData.lean index 21482070a..d3cdf0d7b 100644 --- a/LeanPool/Wallace/ConcreteData.lean +++ b/LeanPool/Wallace/ConcreteData.lean @@ -51,11 +51,6 @@ theorem label_inter_finite {a b : ContinuumIndex} (hab : a ≠ b) : apply binaryBranchOnNat_inter_finite exact continuumIndexEquivBinaryStream.injective.ne hab -theorem label_pairwise : - Pairwise fun a b : ContinuumIndex ↦ (label a ∩ label b).Finite := by - intro a b hab - exact label_inter_finite hab - /-! ## The globally prepared sequences -/ variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) @@ -95,22 +90,6 @@ theorem preparedDifference_injective (a : ContinuumIndex) : apply prepared_injective N hN M a exact sub_left_injective hmn -/-- Each shifted block has exactly the scheduled cardinality `N l`, as in -Lemma 5.3 of the paper. -/ -theorem differenceBlock_card (a : ContinuumIndex) (l : ℕ) : - (differenceBlock N hN M a l).card = N l := by - rw [differenceBlock, - Finset.card_image_iff.mpr (preparedDifference_injective N hN M a).injOn, - blockPositions_card] - -theorem differenceBlock_subset_range (a : ContinuumIndex) (l : ℕ) : - ↑(differenceBlock N hN M a l) ⊆ - Set.range (fun n ↦ prepared N hN M a n - codeBasisVector a) := by - intro x hx - simp only [differenceBlock, Finset.mem_coe, Finset.mem_image] at hx - obtain ⟨n, _hn, rfl⟩ := hx - exact Set.mem_range_self n - /-! ## The fixed free ultrafilters -/ /-- The block system determined by the prescribed sizes. -/ diff --git a/LeanPool/Wallace/ConcreteLocalSetup.lean b/LeanPool/Wallace/ConcreteLocalSetup.lean index 73b8db718..a41ad12cd 100644 --- a/LeanPool/Wallace/ConcreteLocalSetup.lean +++ b/LeanPool/Wallace/ConcreteLocalSetup.lean @@ -68,14 +68,6 @@ theorem refinedLabel_pairwise (x : ContinuumFreeGroup) : (fun a : RelevantCode N hN M x ↦ label a.1) (relevantLabels_pairwise N hN M x))).1 -theorem refinedLabel_subset (x : ContinuumFreeGroup) (a : RelevantCode N hN M x) : - refinedLabel N hN M x a ⊆ label a.1 := by - letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x - exact (Classical.choose_spec - (exists_disjoint_refinement_countable - (fun a : RelevantCode N hN M x ↦ label a.1) - (relevantLabels_pairwise N hN M x))).2 a |>.1 - theorem label_diff_refinedLabel_finite (x : ContinuumFreeGroup) (a : RelevantCode N hN M x) : (label a.1 \ refinedLabel N hN M x a).Finite := by @@ -111,54 +103,6 @@ theorem activeCode_eq_some_of_mem (x : ContinuumFreeGroup) (l : ℕ) · rename_i h exact (h ⟨a, ha⟩).elim -theorem mem_refinedLabel_of_activeCode_eq_some - (x : ContinuumFreeGroup) (l : ℕ) (a : RelevantCode N hN M x) - (h : activeCode N hN M x l = some a) : - l ∈ refinedLabel N hN M x a := by - classical - unfold activeCode at h - split at h - · rename_i hex - have hchosen : Classical.choose hex = a := Option.some.inj h - simpa only [hchosen] using Classical.choose_spec hex - · simp at h - -theorem activeCode_eq_some_iff - (x : ContinuumFreeGroup) (l : ℕ) (a : RelevantCode N hN M x) : - activeCode N hN M x l = some a ↔ l ∈ refinedLabel N hN M x a := - ⟨mem_refinedLabel_of_activeCode_eq_some N hN M x l a, - activeCode_eq_some_of_mem N hN M x l a⟩ - -/-- The fresh shifted set presented to bounded deletion at stage `l`. -/ -def activeBlock (x : ContinuumFreeGroup) (l : ℕ) : Finset ContinuumFreeGroup := - match activeCode N hN M x l with - | none => ∅ - | some a => differenceBlock N hN M a.1 l - -theorem activeBlock_eq_of_mem (x : ContinuumFreeGroup) (l : ℕ) - (a : RelevantCode N hN M x) (ha : l ∈ refinedLabel N hN M x a) : - activeBlock N hN M x l = differenceBlock N hN M a.1 l := by - simp [activeBlock, activeCode_eq_some_of_mem N hN M x l a ha] - -theorem activeBlock_boundedIndependent (x : ContinuumFreeGroup) (l : ℕ) : - BoundedIndependent (M l) (activeBlock N hN M x l) := by - unfold activeBlock - split - · simp [BoundedIndependent] - · rename_i a hactive - exact differenceBlock_boundedIndependent N hN M a.1 l - -theorem activeBlock_card_le (x : ContinuumFreeGroup) (l : ℕ) : - (activeBlock N hN M x l).card ≤ N l := by - unfold activeBlock - split - · simp - · rename_i a hactive - calc - (differenceBlock N hN M a.1 l).card ≤ (blockPositions N hN l).card := by - exact Finset.card_image_le - _ = N l := blockPositions_card N hN l - /-! ## Restriction to the countable local free group -/ /-- Inclusion of the free group on the closure coordinates into the ambient free group. -/ @@ -306,12 +250,6 @@ theorem localActiveBlock_card_le (x : ContinuumFreeGroup) (l : ℕ) : · rename_i a hactive rw [localDifferenceBlock_card] -theorem localActiveBlock_card_eq_of_mem (x : ContinuumFreeGroup) (l : ℕ) - (a : RelevantCode N hN M x) (ha : l ∈ refinedLabel N hN M x a) : - (localActiveBlock N hN M x l).card = N l := by - rw [localActiveBlock_eq_of_mem N hN M x l a ha, - localDifferenceBlock_card] - end end ConcreteLocalSetup diff --git a/LeanPool/Wallace/CountableClosure.lean b/LeanPool/Wallace/CountableClosure.lean index 1d0331d27..b9df70159 100644 --- a/LeanPool/Wallace/CountableClosure.lean +++ b/LeanPool/Wallace/CountableClosure.lean @@ -40,18 +40,6 @@ def dependencyClosure (index : Code ↪ I) (dependency : Code → Set I) (D₀ : Set I) : Set I := ⋃ n, dependencyClosureStages index dependency D₀ n -theorem subset_dependencyClosureStep (index : Code ↪ I) (dependency : Code → Set I) - (D : Set I) : D ⊆ dependencyClosureStep index dependency D := - subset_union_left - -theorem dependencyClosureStages_mono (index : Code ↪ I) (dependency : Code → Set I) - (D₀ : Set I) : Monotone (dependencyClosureStages index dependency D₀) := by - intro m n hmn - induction n, hmn using Nat.le_induction with - | base => exact Subset.rfl - | succ n _ ih => - exact ih.trans (subset_dependencyClosureStep index dependency _) - theorem subset_dependencyClosure (index : Code ↪ I) (dependency : Code → Set I) (D₀ : Set I) : D₀ ⊆ dependencyClosure index dependency D₀ := by intro x hx diff --git a/LeanPool/Wallace/FiniteCombinatorics.lean b/LeanPool/Wallace/FiniteCombinatorics.lean index 60693c395..7433d1ed1 100644 --- a/LeanPool/Wallace/FiniteCombinatorics.lean +++ b/LeanPool/Wallace/FiniteCombinatorics.lean @@ -40,35 +40,6 @@ the sequence lies strictly below its assigned index. -/ def SupportedBelow (s : ℕ → I →₀ ℤ) (i : I) : Prop := ∀ n j, j ∈ (s n).support → j < i -/-- Reindex a family by the range of an injective assignment of fresh upper bounds. - -This is the final reindexing step of the triangular-coding lemma in the paper. The genuinely -set-theoretic input of that lemma—that continuum many countable supports admit distinct upper -bounds below the initial ordinal of the continuum—is deliberately visible as `hbound`; it is not -silently postulated here. -/ -theorem triangular_reindex - (t : T → ℕ → I →₀ ℤ) (index : T ↪ I) - (ht : Function.Injective t) - (hbound : ∀ a, SupportedBelow (t a) (index a)) : - ∃ (Λ : Set I) (s : Λ → ℕ → I →₀ ℤ), - Function.Injective s ∧ Set.range s = Set.range t ∧ - ∀ α : Λ, SupportedBelow (s α) α := by - let Λ : Set I := Set.range index - let e : T ≃ Λ := Equiv.ofInjective index index.injective - let s : Λ → ℕ → I →₀ ℤ := t ∘ e.symm - refine ⟨Λ, s, ?_, ?_, ?_⟩ - · exact ht.comp e.symm.injective - · ext z - constructor - · rintro ⟨a, rfl⟩ - exact ⟨e.symm a, rfl⟩ - · rintro ⟨a, rfl⟩ - exact ⟨e a, by simp [s]⟩ - · intro α - have hα : (index (e.symm α) : I) = α := by - exact Subtype.ext_iff.mp (e.apply_symm_apply α) - simpa [s, SupportedBelow, hα] using hbound (e.symm α) - end Triangular section Relations @@ -185,35 +156,6 @@ theorem boundedIndependent_insert_of_not_forbidden [IsAddTorsionFree G] [Decidab · exact hcx · exact hcY z hzY -/-- **Bounded-independence extraction** (Lemma `lem:finite-extraction` in the paper). - -Every infinite subset of a torsion-free Abelian group contains an `M`-independent finite subset -of any prescribed cardinality `N`. -/ -theorem exists_boundedIndependent_finset [IsAddTorsionFree G] - {S : Set G} (hS : S.Infinite) (M N : ℕ) : - ∃ X : Finset G, (X : Set G) ⊆ S ∧ X.card = N ∧ BoundedIndependent M X := by - classical - induction N with - | zero => - refine ⟨∅, by simp, by simp, ?_⟩ - intro c _ _ x hx - simp at hx - | succ N ih => - obtain ⟨Y, hYS, hYcard, hYind⟩ := ih - obtain ⟨x, hxS, hxout⟩ := - hS.exists_notMem_finset (Y ∪ forbiddenFinset M Y) - have hxY : x ∉ Y := fun hx ↦ hxout (Finset.mem_union_left _ hx) - have hxforbidden : ¬ Forbidden M Y x := by - intro hx - exact hxout (Finset.mem_union_right _ (forbidden_mem_forbiddenFinset hx)) - refine ⟨insert x Y, ?_, ?_, - boundedIndependent_insert_of_not_forbidden hYind hxY hxforbidden⟩ - · intro z hz - rcases Finset.mem_insert.mp hz with rfl | hz - · exact hxS - · exact hYS hz - · simp [Finset.card_insert_of_notMem hxY, hYcard] - section IntegerDependence /-- `s+1` integer vectors in `ℤ^s` have a nontrivial integer dependence. diff --git a/LeanPool/Wallace/FullTopology.lean b/LeanPool/Wallace/FullTopology.lean index 6abcadf91..43f572acb 100644 --- a/LeanPool/Wallace/FullTopology.lean +++ b/LeanPool/Wallace/FullTopology.lean @@ -282,19 +282,10 @@ theorem FullCharacterPackage.hasMainGroupTopology C.initial_totallyBounded, C.initial_onlyEventuallyConstantConvergentSequences⟩ -/-- Exact statement of the free-Abelian group theorem for an arbitrary index type. -/ -abbrev FreeAbelianGroupConclusion (I : Type u) : Prop := - HasMainGroupTopology (I →₀ ℤ) - /-- Exact statement of the rational-vector-group proposition for an arbitrary index type. -/ abbrev RationalVectorGroupConclusion (I : Type u) : Prop := HasMainGroupTopology (I →₀ ℚ) -theorem SeparationPackage.freeAbelianGroupConclusion - {I : Type u} (C : SeparationPackage I) : - FreeAbelianGroupConclusion I := - C.toFullCharacterPackage.hasMainGroupTopology - /-- Once the construction is instantiated on the rational direct sum, the rational proposition follows through exactly the same topology argument. -/ theorem FullCharacterPackage.rationalVectorGroupConclusion diff --git a/LeanPool/Wallace/FullTopologyMain.lean b/LeanPool/Wallace/FullTopologyMain.lean index 8ecd4fac1..01e6cdfda 100644 --- a/LeanPool/Wallace/FullTopologyMain.lean +++ b/LeanPool/Wallace/FullTopologyMain.lean @@ -29,30 +29,6 @@ def continuumFullSeparationPackage : SeparationPackage ContinuumIndex := ConcreteFusionRun.independenceBound ConcreteFusionRun.hasLocalSeparatingCharacters -/-- **Free-Abelian specialization of the main theorem.** The free Abelian group of rank -continuum admits a Hausdorff -precompact countably compact group topology in which every convergent sequence is eventually -constant. Precompactness is certified by a compatible totally bounded uniform group -structure. -/ -theorem continuumFreeAbelianGroup_mainTheorem : - FreeAbelianGroupConclusion ContinuumIndex := - continuumFullSeparationPackage.freeAbelianGroupConclusion - -/-- The witness-level form of the free-Abelian specialization, kept as a convenient public API. -/ -theorem continuumFreeAbelianGroup_mainTheorem_explicit : - ∃ (topology : TopologicalSpace ContinuumFreeGroup) - (uniformity : UniformSpace ContinuumFreeGroup), - uniformity.toTopologicalSpace = topology ∧ - @IsUniformAddGroup ContinuumFreeGroup uniformity _ ∧ - @IsTopologicalAddGroup ContinuumFreeGroup topology _ ∧ - @T2Space ContinuumFreeGroup topology ∧ - @CountablyCompactSpace ContinuumFreeGroup topology ∧ - @TotallyBounded ContinuumFreeGroup uniformity Set.univ ∧ - (∀ (s : ℕ → ContinuumFreeGroup) (x : ContinuumFreeGroup), - Tendsto s Filter.atTop (@nhds ContinuumFreeGroup topology x) → - ∀ᶠ n in Filter.atTop, s n = x) := - continuumFreeAbelianGroup_mainTheorem - end end Wallace diff --git a/LeanPool/Wallace/FusionLimit.lean b/LeanPool/Wallace/FusionLimit.lean index 951d4ddb5..0006389e6 100644 --- a/LeanPool/Wallace/FusionLimit.lean +++ b/LeanPool/Wallace/FusionLimit.lean @@ -27,36 +27,6 @@ noncomputable section variable {G : Type u} [AddGroup G] -/-- A geometric estimate after deleting a finite initial segment implies that the original -sequence is Cauchy. -/ -theorem cauchySeq_of_tail_edist_le_geometric_two - {X : Type*} [PseudoEMetricSpace X] {u : ℕ → X} - (N : ℕ) (C : ℝ≥0∞) (hC : C ≠ ∞) - (hstep : ∀ n, edist (u (N + n)) (u (N + n + 1)) ≤ C / 2 ^ n) : - CauchySeq u := by - rw [← cauchySeq_shift N] - apply cauchySeq_of_edist_le_geometric_two C hC - intro n - simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hstep n - -/-- Explicit distance from the beginning of a geometrically controlled tail to its limit. -/ -theorem edist_le_of_tail_geometric_two_of_tendsto - {X : Type*} [PseudoEMetricSpace X] {u : ℕ → X} {a : X} - (N : ℕ) (C : ℝ≥0∞) - (hstep : ∀ n, edist (u (N + n)) (u (N + n + 1)) ≤ C / 2 ^ n) - (hu : Tendsto u atTop (nhds a)) : - edist (u N) a ≤ 2 * C := by - let v : ℕ → X := fun n ↦ u (N + n) - have hvstep : ∀ n, edist (v n) (v (n + 1)) ≤ C / 2 ^ n := by - intro n - simpa [v, Nat.add_assoc] using hstep n - have hvlim : Tendsto v atTop (nhds a) := by - have hshift := hu.comp (tendsto_add_atTop_nat N) - change Tendsto (fun n ↦ u (n + N)) atTop (nhds a) at hshift - simpa only [v, Nat.add_comm] using hshift - simpa [v] using - edist_le_of_edist_le_geometric_two_of_tendsto₀ C hvstep hvlim - /-- The pointwise limit of a pointwise-Cauchy sequence of additive characters. -/ def pointwiseLimitCharacter (f : ℕ → G →+ UnitAddCircle) diff --git a/LeanPool/Wallace/FusionSchedule.lean b/LeanPool/Wallace/FusionSchedule.lean index 240d77809..b97fb8aee 100644 --- a/LeanPool/Wallace/FusionSchedule.lean +++ b/LeanPool/Wallace/FusionSchedule.lean @@ -45,22 +45,11 @@ def protectedBound (l : ℕ) : ℕ := def blockSize (l : ℕ) : ℕ := (l + 2) * protectedBound l -@[simp] -theorem accumulatedSize_zero : accumulatedSize 0 = 0 := rfl - @[simp] theorem accumulatedSize_succ (l : ℕ) : accumulatedSize (l + 1) = accumulatedSize l + blockSize l := by rfl -/-- `accumulatedSize` is exactly the sum of all preceding block sizes. -/ -theorem sum_blockSize (l : ℕ) : - ∑ i ∈ Finset.range l, blockSize i = accumulatedSize l := by - induction l with - | zero => simp - | succ l ih => - rw [Finset.sum_range_succ, ih, accumulatedSize_succ] - theorem protectedBound_pos (l : ℕ) : 0 < protectedBound l := by simp only [protectedBound] omega @@ -77,9 +66,6 @@ theorem blockSize_pos (l : ℕ) : 0 < blockSize l := by simp only [blockSize] exact Nat.mul_pos (by omega) (protectedBound_pos l) -theorem blockSize_ne_zero (l : ℕ) : blockSize l ≠ 0 := - Nat.ne_of_gt (blockSize_pos l) - /-- The exact discarded-proportion identity behind the density-one argument. -/ theorem protectedBound_div_blockSize (l : ℕ) : (protectedBound l : ℝ) / (blockSize l : ℝ) = @@ -108,9 +94,6 @@ theorem stageError_pos (l : ℕ) : 0 < stageError l := by simp only [stageError] positivity -theorem stageError_ne_zero (l : ℕ) : stageError l ≠ 0 := - ne_of_gt (stageError_pos l) - /-- Exact geometric-tail identity, convenient for the completeness estimate. -/ theorem stageError_add (L n : ℕ) : stageError (L + n) = stageError L / 2 ^ n := by @@ -145,21 +128,6 @@ theorem tsum_stageError : ∑' l : ℕ, stageError l = (1 / 32 : ℝ) := by change (∑' n : ℕ, (1 / 32 : ℝ) / 2 / 2 ^ n) = 1 / 32 exact tsum_geometric_two' (1 / 32 : ℝ) -theorem tsum_stageError_pos : 0 < ∑' l : ℕ, stageError l := by - rw [tsum_stageError] - norm_num - -/-- Even twice the full error budget is far below the initial value `1/2`. -/ -theorem two_mul_tsum_stageError_lt_half : - 2 * (∑' l : ℕ, stageError l) < (1 / 2 : ℝ) := by - rw [tsum_stageError] - norm_num - -/-- The pointwise-limit estimate from the zeroth stage also preserves a nonzero half-turn. -/ -theorem two_mul_stageError_zero_lt_half : - 2 * stageError 0 < (1 / 2 : ℝ) := by - norm_num [stageError] - /-- Independence threshold used before the bounded-deletion step. -/ def independenceBound (l Q : ℕ) : ℕ := deletionIndependenceBound (protectedBound l) Q diff --git a/LeanPool/Wallace/FusionStage.lean b/LeanPool/Wallace/FusionStage.lean index bef9eac3a..d983d559a 100644 --- a/LeanPool/Wallace/FusionStage.lean +++ b/LeanPool/Wallace/FusionStage.lean @@ -215,43 +215,6 @@ theorem exists_character_fusion_stage (disjoint_of_mixedRelationFree hQ hfree) hyA hyY simpa [stageTarget, hzi, hyA, norm_eq_zero] using hnext i -/-- **One fusion step** (the complete form used in Section 4 of the paper). - -`Q` is a uniform Kronecker bound for every positive tuple length that can occur. Bounded -deletion first produces `Y`, including the no-mixed-relation certificate, and one application -of the uniform Kronecker lemma then produces the next homomorphism. The empty union is handled -directly, exactly as in the paper, so no artificial bound for zero-length tuples is required. -/ -theorem exists_one_fusion_step - [IsAddTorsionFree G] - (r Q : ℕ) (hQ : 1 ≤ Q) (A X : Finset G) (hAr : A.card ≤ r) - (hX : BoundedIndependent (deletionIndependenceBound r Q) X) - (old : G →+ UnitAddCircle) {eps : ℝ} - (hbound : ∀ m, 0 < m → m ≤ r + X.card → - IsUniformKroneckerBound.{u} m eps Q) : - ∃ (Y : Finset G) (next : G →+ UnitAddCircle), - Y ⊆ X ∧ - (X \ Y).card ≤ A.card ∧ - MixedRelationFree Q A Y ∧ - (∀ a ∈ A, ‖next a - old a‖ < eps) ∧ - (∀ y ∈ Y, ‖next y‖ < eps) := by - classical - obtain ⟨Y, hYX, hdeleted, hfree⟩ := bounded_deletion r Q A X hAr hX - by_cases hempty : A ∪ Y = ∅ - · have hA : A = ∅ := (Finset.union_eq_empty.mp hempty).1 - have hY : Y = ∅ := (Finset.union_eq_empty.mp hempty).2 - subst A - subst Y - exact ⟨∅, old, by simp, hdeleted, hfree, by simp, by simp⟩ - · have hcardPos : 0 < (A ∪ Y).card := - Finset.card_pos.mpr (Finset.nonempty_iff_ne_empty.mpr hempty) - have hcardLe : (A ∪ Y).card ≤ r + X.card := by - calc - (A ∪ Y).card ≤ A.card + Y.card := Finset.card_union_le A Y - _ ≤ r + X.card := Nat.add_le_add hAr (Finset.card_le_card hYX) - obtain ⟨next, hold, hnew⟩ := exists_character_fusion_stage - hQ hfree old (hbound (A ∪ Y).card hcardPos hcardLe) - exact ⟨Y, next, hYX, hdeleted, hfree, hold, hnew⟩ - end end Wallace diff --git a/LeanPool/Wallace/GeneralMain.lean b/LeanPool/Wallace/GeneralMain.lean index 2c3425d2f..2885b6bd3 100644 --- a/LeanPool/Wallace/GeneralMain.lean +++ b/LeanPool/Wallace/GeneralMain.lean @@ -78,15 +78,6 @@ theorem torsionFreeAbelianGroup_mainTheorem_exact torsionFreeAbelianGroup_mainTheorem G hcard exact ⟨topology, htopologicalGroup, hT2, hcompact, hsequences⟩ -/-- The Baer--Specker group has cardinality continuum. -/ -theorem mk_baerSpeckerGroup : #(ℕ → ℤ) = 𝔠 := by - rw [Cardinal.mk_arrow, Cardinal.mk_int, Cardinal.mk_nat] - simp - -/-- The Baer--Specker specialization highlighted in the abstract and introduction. -/ -theorem baerSpeckerGroup_mainTheorem : HasMainGroupTopology (ℕ → ℤ) := - torsionFreeAbelianGroup_mainTheorem (ℕ → ℤ) mk_baerSpeckerGroup - end end Wallace diff --git a/LeanPool/Wallace/GlobalAssembly.lean b/LeanPool/Wallace/GlobalAssembly.lean index 77e7d6610..13f49f7ae 100644 --- a/LeanPool/Wallace/GlobalAssembly.lean +++ b/LeanPool/Wallace/GlobalAssembly.lean @@ -96,14 +96,6 @@ def separationPackage : SeparationPackage ContinuumIndex where intro a x exact globalCharacter_admissible N hN M H x a -/-- Once the local fusion has been proved for the concrete schedule, the existential Wallace -counterexample follows without any additional topological or set-theoretic assumption. -/ -theorem wallaceCounterexampleExists_of_local - (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) - (H : HasLocalSeparatingCharacters N hN M) : WallaceCounterexampleExists := by - letI : Infinite ContinuumIndex := continuumIndex_infinite - exact (separationPackage N hN M H).wallaceCounterexampleExists - end end GlobalAssembly diff --git a/LeanPool/Wallace/InitialCharacter.lean b/LeanPool/Wallace/InitialCharacter.lean index 02d9c7dcb..2a283e0e1 100644 --- a/LeanPool/Wallace/InitialCharacter.lean +++ b/LeanPool/Wallace/InitialCharacter.lean @@ -38,16 +38,6 @@ theorem exists_character_apply_eq_half obtain ⟨χ, hχ⟩ := exists_character_of_respectsRelations z t hrel exact ⟨χ, by simpa [z, t] using hχ 0⟩ -/-- The half-turn is nonzero. -/ -theorem half_ne_zero : (((1 / 2 : ℝ) : UnitAddCircle)) ≠ 0 := by - intro hzero - rw [AddCircle.coe_eq_zero_iff] at hzero - obtain ⟨n, hn⟩ := hzero - have hnR : (n : ℝ) = 1 / 2 := by simpa using hn - have hn' : (2 : ℝ) * (n : ℝ) = 1 := by linarith - have hnInt : (2 : ℤ) * n = 1 := by exact_mod_cast hn' - omega - end end Wallace diff --git a/LeanPool/Wallace/LocalEnumeration.lean b/LeanPool/Wallace/LocalEnumeration.lean index 6fac0e508..78d66b87e 100644 --- a/LeanPool/Wallace/LocalEnumeration.lean +++ b/LeanPool/Wallace/LocalEnumeration.lean @@ -19,12 +19,6 @@ open TriangularPreprocess variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) -/-- The free Abelian group on a countable coordinate closure is countable. -/ -theorem localFreeGroup_countable (x : ContinuumFreeGroup) : - Countable (closure N hN M x →₀ ℤ) := by - letI : Countable (closure N hN M x) := (closure_countable N hN M x).to_subtype - infer_instance - /-- A fixed surjective enumeration of every local free group. -/ def groupEnumeration (x : ContinuumFreeGroup) : ℕ → (closure N hN M x →₀ ℤ) := by diff --git a/LeanPool/Wallace/LocalFusion.lean b/LeanPool/Wallace/LocalFusion.lean index 2a544f14f..7a63a4eee 100644 --- a/LeanPool/Wallace/LocalFusion.lean +++ b/LeanPool/Wallace/LocalFusion.lean @@ -43,24 +43,6 @@ open FiniteCombinatorics /-! ## The bounded-deletion input to one stage -/ -/-- A retained finite subset of `X` supplied by the bounded-deletion theorem. -/ -structure DeletionStage {G : Type u} [AddCommGroup G] [DecidableEq G] - (A X : Finset G) (Q : ℕ) where - retained : Finset G - retained_subset : retained ⊆ X - deleted_card_le : (X \ retained).card ≤ A.card - mixedRelationFree : MixedRelationFree Q A retained - -/-- The existing bounded-deletion theorem produces a complete stage certificate. -/ -theorem exists_deletionStage {G : Type u} [AddCommGroup G] [IsAddTorsionFree G] - [DecidableEq G] - (r Q : ℕ) (A X : Finset G) (hAr : A.card ≤ r) - (hX : BoundedIndependent (deletionIndependenceBound r Q) X) : - Nonempty (DeletionStage A X Q) := by - classical - obtain ⟨Y, hYX, hcard, hfree⟩ := bounded_deletion r Q A X hAr hX - exact ⟨⟨Y, hYX, hcard, hfree⟩⟩ - /-- A scheduled bounded-deletion and finite-fusion stage. -/ theorem exists_character_after_deletion {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] @@ -234,29 +216,6 @@ theorem norm_limit_difference_le_on_retained (R : FusionRun G) (B : CodeBlocks R exact R.norm_limitCharacter_le_of_mem_retained l (B.retained_in_stage l n hlab hnblock) -/-- If retained indices determine block labels tending to infinity, the limiting character of -the difference sequence tends to zero along the fixed ultrafilter. -/ -theorem tendsto_limit_difference_zero (R : FusionRun G) (B : CodeBlocks R) - (blockOf : ℕ → ℕ) - (hblockOf : ∀ l n, n ∈ B.block l → blockOf n = l) - (hblockTendsto : Tendsto blockOf B.p atTop) : - Tendsto (fun n ↦ R.limitCharacter (B.difference n)) B.p (nhds 0) := by - rw [Metric.tendsto_nhds] - intro ε hε - have herr : Tendsto (fun l ↦ 2 * FusionSchedule.stageError l) atTop (nhds 0) := by - simpa using FusionSchedule.tendsto_stageError.const_mul 2 - have hevent : ∀ᶠ l in atTop, 2 * FusionSchedule.stageError l < ε := - (Metric.tendsto_nhds.mp herr ε hε).mono fun l hl ↦ by - simpa [abs_of_pos (FusionSchedule.stageError_pos l)] using hl - have heventP : ∀ᶠ n in B.p, 2 * FusionSchedule.stageError (blockOf n) < ε := - hblockTendsto hevent - filter_upwards [B.retained_mem, heventP] with n hnret hnerr - obtain ⟨l, _hlab, hnblock, hnorm⟩ := - R.norm_limit_difference_le_on_retained B hnret - have hlabel : blockOf n = l := hblockOf l n (Finset.mem_sdiff.mp hnblock).1 - rw [dist_zero_right] - exact hnorm.trans_lt (by simpa [hlabel] using hnerr) - /-- Concrete block-position version of `tendsto_limit_difference_zero`. Here freeness of the ultrafilter and the partition theorem for `blockPositions` supply the required divergence of block labels automatically. -/ @@ -423,17 +382,6 @@ def fusionStates (fusionStates fresh enumeration x hfresh_card hfresh_independent initial 0).character = initial := rfl -@[simp] theorem fusionStates_succ - {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] - (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) - (hfresh_card : ∀ l, (fresh l).card ≤ FusionSchedule.blockSize l) - (hfresh_independent : ∀ l, - BoundedIndependent (FusionSchedule.stageIndependenceBound l) (fresh l)) - (initial : G →+ UnitAddCircle) (l : ℕ) : - fusionStates fresh enumeration x hfresh_card hfresh_independent initial (l + 1) = - nextFusionState fresh enumeration x hfresh_card hfresh_independent l - (fusionStates fresh enumeration x hfresh_card hfresh_independent initial l) := rfl - /- The rest of the construction uses shorter local names. -/ section ScheduledConstruction diff --git a/LeanPool/Wallace/Main.lean b/LeanPool/Wallace/Main.lean index ad6db8fda..3fe5ca5f8 100644 --- a/LeanPool/Wallace/Main.lean +++ b/LeanPool/Wallace/Main.lean @@ -19,41 +19,4 @@ namespace Wallace open TriangularPreprocess -/-- A closed, witness-level form of the main construction. - -There is a Hausdorff group topology on the canonical free Abelian group of rank continuum for -which the nonnegative cone, with its induced topology, is countably compact and is a Wallace -semigroup. The explicit `CountablyCompactSpace` conjunct records the principal topological -conclusion separately, although it is also contained in `IsWallaceSemigroup`. -/ -theorem continuumFreeGroup_positiveCone_isWallace : - ∃ topology : TopologicalSpace ContinuumFreeGroup, - @IsTopologicalAddGroup ContinuumFreeGroup topology _ ∧ - @T2Space ContinuumFreeGroup topology ∧ - @CountablyCompactSpace (positiveCone ContinuumIndex) - (TopologicalSpace.induced - (fun z : positiveCone ContinuumIndex ↦ (z : ContinuumFreeGroup)) topology) ∧ - @IsWallaceSemigroup (positiveCone ContinuumIndex) - (TopologicalSpace.induced - (fun z : positiveCone ContinuumIndex ↦ (z : ContinuumFreeGroup)) topology) _ := by - let C : SeparationPackage ContinuumIndex := continuumFullSeparationPackage - let topology : TopologicalSpace ContinuumFreeGroup := C.initialTopology - letI : TopologicalSpace ContinuumFreeGroup := topology - letI : IsTopologicalAddGroup ContinuumFreeGroup := C.initial_isTopologicalAddGroup - letI : T2Space ContinuumFreeGroup := C.initial_t2Space - letI : Infinite ContinuumIndex := continuumIndex_infinite - let i : ContinuumIndex := Classical.choice inferInstance - have hwallace : IsWallaceSemigroup (positiveCone ContinuumIndex) := - positiveCone_isWallace_of_limitProperty ContinuumIndex i - C.positiveCone_hasWallaceLimitProperty - refine ⟨topology, C.initial_isTopologicalAddGroup, C.initial_t2Space, ?_, hwallace⟩ - exact hwallace.2.2.2.1 - -/-- There exists a Hausdorff countably compact cancellative topological additive monoid which is -not a group. The stronger public theorem in `TychonoffWallace.lean` also exposes commutativity -and Tychonoffness in its proposition. -/ -theorem wallaceCounterexampleExists : WallaceCounterexampleExists := - by - letI : Infinite ContinuumIndex := continuumIndex_infinite - exact continuumFullSeparationPackage.wallaceCounterexampleExists - end Wallace diff --git a/LeanPool/Wallace/MathlibFoundations.lean b/LeanPool/Wallace/MathlibFoundations.lean index 45f69f6a7..1f3467c01 100644 --- a/LeanPool/Wallace/MathlibFoundations.lean +++ b/LeanPool/Wallace/MathlibFoundations.lean @@ -27,31 +27,6 @@ noncomputable section /-! ## Families with the finite-intersection property -/ -/-- A family of sets has the finite-intersection property when every finite subfamily has -nonempty intersection. The empty finite subfamily is included, so this also records that the -underlying type is nonempty whenever the property holds. -/ -def HasFiniteIntersectionProperty {α : Type u} (𝒜 : Set (Set α)) : Prop := - ∀ T : Finset (Set α), (↑T : Set (Set α)) ⊆ 𝒜 → - (⋂₀ (↑T : Set (Set α))).Nonempty - -/-- The ultrafilter lemma in the exact finite-intersection form needed in the construction. -/ -theorem exists_ultrafilter_extending_fip {α : Type u} {𝒜 : Set (Set α)} - (h𝒜 : HasFiniteIntersectionProperty 𝒜) : - ∃ p : Ultrafilter α, 𝒜 ⊆ (p : Filter α).sets := - Ultrafilter.exists_ultrafilter_of_finite_inter_nonempty 𝒜 h𝒜 - -/-- If a finite-intersection family contains every cofinite set, its ultrafilter extension is -free (expressed by lying below the cofinite filter in the filter order). -/ -theorem exists_free_ultrafilter_extending_fip {α : Type u} {𝒜 : Set (Set α)} - (h𝒜 : HasFiniteIntersectionProperty 𝒜) - (hcofinite : (cofinite : Filter α).sets ⊆ 𝒜) : - ∃ p : Ultrafilter α, - 𝒜 ⊆ (p : Filter α).sets ∧ (p : Filter α) ≤ cofinite := by - obtain ⟨p, hp⟩ := exists_ultrafilter_extending_fip h𝒜 - refine ⟨p, hp, ?_⟩ - intro s hs - exact hp (hcofinite hs) - /-- Any proper filter extending the cofinite filter admits a free ultrafilter refinement. -/ theorem exists_free_ultrafilter_le_filter {α : Type u} (l : Filter α) [l.NeBot] (hl : l ≤ cofinite) : @@ -60,12 +35,6 @@ theorem exists_free_ultrafilter_le_filter {α : Type u} (l : Filter α) [l.NeBot refine ⟨Ultrafilter.of l, Ultrafilter.of_le l, ?_⟩ exact (Ultrafilter.of_le l).trans hl -/-- A filter below the cofinite filter contains no finite set. -/ -theorem finite_not_mem_of_le_cofinite {α : Type u} {l : Filter α} - [l.NeBot] (hl : l ≤ cofinite) {s : Set α} (hs : s.Finite) : s ∉ l := by - intro hsl - exact compl_notMem hsl (hl hs.compl_mem_cofinite) - /-! ## Characters of a free Abelian group -/ /-- The homomorphism out of a free Abelian group determined by its values on the standard @@ -80,200 +49,16 @@ theorem finsuppAddHomOfBasis_single {ι : Type u} {A : Type v} [AddCommGroup A] finsuppAddHomOfBasis z (Finsupp.single i n) = n • z i := by simp [finsuppAddHomOfBasis] -@[simp] -theorem finsuppAddHomOfBasis_single_one {ι : Type u} {A : Type v} [AddCommGroup A] - (z : ι → A) (i : ι) : - finsuppAddHomOfBasis z (Finsupp.single i 1) = z i := by - simp - /-! ## The initial topology generated by circle-valued characters -/ -/-- The diagonal homomorphism associated to a family of characters. -/ -def characterDiagonal {G : Type u} {I : Type v} [AddGroup G] - (χ : I → G →+ UnitAddCircle) : G →+ (I → UnitAddCircle) where - toFun x i := χ i x - map_zero' := by ext i; simp - map_add' x y := by ext i; simp - -@[simp] -theorem characterDiagonal_apply {G : Type u} {I : Type v} [AddGroup G] - (χ : I → G →+ UnitAddCircle) (x : G) (i : I) : - characterDiagonal χ x i = χ i x := - rfl - -/-- Point-separation stated at zero, the natural form for additive characters. -/ -def CharactersSeparatePoints {G : Type u} {I : Type v} [AddGroup G] - (χ : I → G →+ UnitAddCircle) : Prop := - ∀ x : G, (∀ i, χ i x = 0) → x = 0 - -theorem characterDiagonal_injective {G : Type u} {I : Type v} [AddGroup G] - {χ : I → G →+ UnitAddCircle} (hχ : CharactersSeparatePoints χ) : - Function.Injective (characterDiagonal χ) := by - intro x y hxy - apply sub_eq_zero.mp - apply hχ (x - y) - intro i - have hi : χ i x = χ i y := by - simpa only [characterDiagonal_apply] using congrFun hxy i - rw [map_sub, hi, sub_self] - -/-- The initial topology generated by all members of `χ`. Equivalently, this is the topology -induced by the diagonal map into the corresponding power of the circle. -/ -@[reducible] -def characterTopology {G : Type u} {I : Type v} [AddGroup G] - (χ : I → G →+ UnitAddCircle) : TopologicalSpace G := - TopologicalSpace.induced (characterDiagonal χ) inferInstance - -/-- The uniformity induced by the same diagonal map. -/ -@[reducible] -def characterUniformSpace {G : Type u} {I : Type v} [AddGroup G] - (χ : I → G →+ UnitAddCircle) : UniformSpace G := - UniformSpace.comap (characterDiagonal χ) inferInstance - -theorem characterUniformSpace_toTopology {G : Type u} {I : Type v} [AddGroup G] - (χ : I → G →+ UnitAddCircle) : - (characterUniformSpace χ).toTopologicalSpace = characterTopology χ := - rfl - -/-- The diagonal description really is the infimum of the topologies induced by the individual -characters. -/ -theorem characterTopology_eq_iInf {G : Type u} {I : Type v} [AddGroup G] - (χ : I → G →+ UnitAddCircle) : - characterTopology χ = - ⨅ i, TopologicalSpace.induced (χ i : G → UnitAddCircle) inferInstance := by - change TopologicalSpace.induced (fun x i => χ i x) Pi.topologicalSpace = _ - exact induced_to_pi fun x i => χ i x - -/-- Universal property of the initial character topology. -/ -theorem le_characterTopology_iff {G : Type u} {I : Type v} [AddGroup G] - (χ : I → G →+ UnitAddCircle) (t : TopologicalSpace G) : - t ≤ characterTopology χ ↔ - ∀ i, @Continuous G UnitAddCircle t inferInstance (χ i) := by - change t ≤ TopologicalSpace.induced (characterDiagonal χ) inferInstance ↔ _ - rw [← continuous_iff_le_induced] - exact continuous_pi_iff - -/-- Every generating character is continuous for the initial topology. -/ -theorem continuous_character {G : Type u} {I : Type v} [AddGroup G] - (χ : I → G →+ UnitAddCircle) (i : I) : - @Continuous G UnitAddCircle (characterTopology χ) inferInstance (χ i) := by - exact (le_characterTopology_iff χ (characterTopology χ)).1 le_rfl i - -/-- The initial character topology is a topological group topology. -/ -theorem characterTopology_isTopologicalAddGroup - {G : Type u} {I : Type v} [AddGroup G] - (χ : I → G →+ UnitAddCircle) : - @IsTopologicalAddGroup G (characterTopology χ) _ := by - exact topologicalAddGroup_induced (characterDiagonal χ) - -/-- A point-separating family of characters makes its initial topology Hausdorff. -/ -theorem characterTopology_t2Space - {G : Type u} {I : Type v} [AddGroup G] - {χ : I → G →+ UnitAddCircle} (hχ : CharactersSeparatePoints χ) : - @T2Space G (characterTopology χ) := by - letI : TopologicalSpace G := characterTopology χ - exact (characterDiagonal_injective hχ).isEmbedding_induced.t2Space - -/-- The diagonal map is uniformly inducing for the pulled-back uniformity. -/ -theorem characterDiagonal_isUniformInducing - {G : Type u} {I : Type v} [AddGroup G] - (χ : I → G →+ UnitAddCircle) : - @IsUniformInducing G (I → UnitAddCircle) - (characterUniformSpace χ) inferInstance (characterDiagonal χ) := - by - letI : UniformSpace G := characterUniformSpace χ - exact ⟨rfl⟩ - -/-- The pulled-back character uniformity is totally bounded: it is induced from a compact -power of the circle. This is the precise uniform-space content of precompactness here. -/ -theorem characterUniformSpace_totallyBounded - {G : Type u} {I : Type v} [AddGroup G] - (χ : I → G →+ UnitAddCircle) : - @TotallyBounded G (characterUniformSpace χ) Set.univ := by - letI : UniformSpace G := characterUniformSpace χ - have htarget : TotallyBounded (Set.univ : Set (I → UnitAddCircle)) := - isCompact_univ.totallyBounded - simpa using totallyBounded_preimage (characterDiagonal_isUniformInducing χ) htarget - /-! ## Cardinal bookkeeping for the continuum-indexed free group -/ -/-- The free Abelian group on `ℝ` has cardinality continuum. -/ -theorem mk_continuumFreeAbelianGroup : #(ℝ →₀ ℤ) = 𝔠 := by - rw [Cardinal.mk_finsupp_of_infinite, Cardinal.mk_real, Cardinal.mk_int] - exact max_eq_left Cardinal.aleph0_le_continuum - -/-- The collection of all sequences in the continuum-indexed free group still has cardinality -continuum. -/ -theorem mk_continuumFreeAbelianGroup_sequences : #(ℕ → (ℝ →₀ ℤ)) = 𝔠 := by - rw [Cardinal.mk_arrow, mk_continuumFreeAbelianGroup, Cardinal.mk_nat] - simpa only [Cardinal.lift_id] using Cardinal.continuum_power_aleph0 - /-- König's theorem gives the strict uncountable cofinality of the continuum. This is the precise fact used to bound a countable union of supports below the initial ordinal of `𝔠`. -/ theorem aleph0_lt_cof_continuum : ℵ₀ < (𝔠 : Cardinal).ord.cof := by rw [← Cardinal.two_power_aleph0] exact Cardinal.lt_cof_ord_power le_rfl (by simp) -/-- A countable supremum of cardinals strictly below the continuum remains below the -continuum. -/ -theorem iSup_nat_lt_continuum {f : ℕ → Cardinal.{0}} - (hf : ∀ n, f n < 𝔠) : ⨆ n, f n < 𝔠 := by - apply Cardinal.iSup_lt_of_lt_cof_ord - · simpa only [Cardinal.mk_nat] using aleph0_lt_cof_continuum - · exact hf - -/-- Ordinal form of the same boundedness fact: countably many ordinals below the initial -ordinal of the continuum have supremum below it. -/ -theorem iSup_nat_ordinal_lt_continuum {f : ℕ → Ordinal.{0}} - (hf : ∀ n, f n < (𝔠 : Cardinal).ord) : - ⨆ n, f n < (𝔠 : Cardinal).ord := by - apply Ordinal.iSup_lt_of_lt_cof - · simpa only [Cardinal.mk_nat] using aleph0_lt_cof_continuum - · exact hf - -/-- An explicit injective sequence in the free group, supported on one basis vector. -/ -def basisRaySequence (r : ℝ) (n : ℕ) : ℝ →₀ ℤ := - Finsupp.single r (n : ℤ) - -theorem basisRaySequence_injective (r : ℝ) : - Function.Injective (basisRaySequence r) := by - intro m n hmn - have := congrArg (fun z : ℝ →₀ ℤ => z r) hmn - simpa [basisRaySequence] using this - -/-- Distinct basis vectors give distinct injective sequences. -/ -theorem basisRaySequence_family_injective : - Function.Injective (fun r : ℝ => - (⟨basisRaySequence r, basisRaySequence_injective r⟩ : - {s : ℕ → (ℝ →₀ ℤ) // Function.Injective s})) := by - intro r s hrs - have hfun : basisRaySequence r = basisRaySequence s := - congrArg Subtype.val hrs - have hzero := congrArg (fun q : ℕ → (ℝ →₀ ℤ) => q 1 r) hfun - by_contra hrs' - simp [basisRaySequence, hrs'] at hzero - -/-- Hence every subtype of sequences, in particular the injective sequences used by the paper, -has cardinality at most continuum. -/ -theorem mk_injective_continuumFreeAbelianGroup_sequences_le : - #({s : ℕ → (ℝ →₀ ℤ) // Function.Injective s}) ≤ 𝔠 := by - exact (Cardinal.mk_subtype_le _).trans_eq mk_continuumFreeAbelianGroup_sequences - -/-- The injective sequences in the continuum-indexed free group have cardinality exactly -continuum. -/ -theorem mk_injective_continuumFreeAbelianGroup_sequences : - #({s : ℕ → (ℝ →₀ ℤ) // Function.Injective s}) = 𝔠 := by - apply le_antisymm mk_injective_continuumFreeAbelianGroup_sequences_le - rw [← Cardinal.mk_real] - exact Cardinal.mk_le_of_injective basisRaySequence_family_injective - -/-- A genuine enumeration (equivalence), not merely a cardinal upper bound, of the injective -sequences by a continuum-sized index type. -/ -def injectiveSequenceEnumeration : - ℝ ≃ {s : ℕ → (ℝ →₀ ℤ) // Function.Injective s} := - Classical.choice <| Cardinal.eq.mp <| - Cardinal.mk_real.trans mk_injective_continuumFreeAbelianGroup_sequences.symm - /-! ## A continuum-sized almost-disjoint family -/ /-- A concrete node on the binary tree: a level and the values below that level. -/ @@ -324,38 +109,6 @@ theorem binaryBranch_inter_finite {x y : ℕ → Bool} (hxy : x ≠ y) : have hkm : k < m := Nat.lt_of_not_ge hmk exact hk ((eq_on_Iio_of_binaryPrefix_eq hmn).2 k hkm).symm -/-- The branch assignment is injective. -/ -theorem binaryBranch_injective : Function.Injective binaryBranch := by - intro x y hxy - by_contra hne - have hfinite := binaryBranch_inter_finite hne - rw [hxy, inter_self] at hfinite - exact (binaryBranch_infinite y) hfinite - -/-- The concrete almost-disjoint family of binary-tree branches has cardinality continuum. -/ -theorem mk_binaryBranch_family : #(Set.range binaryBranch) = 𝔠 := by - rw [Cardinal.mk_range_eq binaryBranch binaryBranch_injective, Cardinal.mk_arrow, - Cardinal.mk_bool, Cardinal.mk_nat] - simp only [Cardinal.lift_id, Cardinal.two_power_aleph0] - -/-- A packaged continuum-sized almost-disjoint family: every member is infinite, distinct -members have finite intersection, and the family itself has cardinality continuum. -/ -theorem binaryBranch_family_spec : - (∀ A ∈ Set.range binaryBranch, A.Infinite) ∧ - ((Set.range binaryBranch).Pairwise fun A B => (A ∩ B).Finite) ∧ - #(Set.range binaryBranch) = 𝔠 := by - refine ⟨?_, ?_, mk_binaryBranch_family⟩ - · rintro A ⟨x, rfl⟩ - exact binaryBranch_infinite x - · rintro A ⟨x, rfl⟩ B ⟨y, rfl⟩ hAB - apply binaryBranch_inter_finite - intro hxy - exact hAB (congrArg binaryBranch hxy) - -/-- The binary-tree node type used above is countable. -/ -theorem binaryTreeNode_countable : Countable BinaryTreeNode := - inferInstance - /-- The binary-tree node type is infinite. -/ theorem binaryTreeNode_infinite : Infinite BinaryTreeNode := Infinite.of_injective (binaryPrefix fun _ => false) @@ -383,37 +136,8 @@ theorem binaryBranchOnNat_inter_finite {x y : ℕ → Bool} (hxy : x ≠ y) : rw [← Set.image_inter binaryTreeNodeEquivNat.injective] exact (binaryBranch_inter_finite hxy).image binaryTreeNodeEquivNat -theorem binaryBranchOnNat_injective : Function.Injective binaryBranchOnNat := - binaryTreeNodeEquivNat.injective.image_injective.comp binaryBranch_injective - -/-- Standard ZFC form: there is an explicit almost-disjoint family on `ℕ` of cardinality -continuum. -/ -theorem binaryBranchOnNat_family_spec : - (∀ A ∈ Set.range binaryBranchOnNat, A.Infinite) ∧ - ((Set.range binaryBranchOnNat).Pairwise fun A B => (A ∩ B).Finite) ∧ - #(Set.range binaryBranchOnNat) = 𝔠 := by - refine ⟨?_, ?_, ?_⟩ - · rintro A ⟨x, rfl⟩ - exact binaryBranchOnNat_infinite x - · rintro A ⟨x, rfl⟩ B ⟨y, rfl⟩ hAB - apply binaryBranchOnNat_inter_finite - intro hxy - exact hAB (congrArg binaryBranchOnNat hxy) - · rw [Cardinal.mk_range_eq binaryBranchOnNat binaryBranchOnNat_injective, - Cardinal.mk_arrow, Cardinal.mk_bool, Cardinal.mk_nat] - simp only [Cardinal.lift_id, Cardinal.two_power_aleph0] - /-! ## A reusable transfinite-iteration fact -/ -/-- Inflationary transfinite iteration is monotone in the ordinal-like index. This records the -mathlib recursion principle used for monotone bookkeeping constructions. -/ -theorem transfiniteIterate_mono - {L : Type u} [CompleteLattice L] - {J : Type v} [LinearOrder J] [OrderBot J] [SuccOrder J] [WellFoundedLT J] - (φ : L → L) (x : L) (hφ : ∀ y, y ≤ φ y) : - Monotone (fun j : J => transfiniteIterate φ j x) := - monotone_transfiniteIterate φ x hφ - end end Wallace diff --git a/LeanPool/Wallace/NontrivialSequences.lean b/LeanPool/Wallace/NontrivialSequences.lean index 94963db9b..47dfad0c1 100644 --- a/LeanPool/Wallace/NontrivialSequences.lean +++ b/LeanPool/Wallace/NontrivialSequences.lean @@ -80,19 +80,6 @@ theorem no_injective_sequence_converges_of_nonzeroLimitProperty have hp0 : Tendsto (t ∘ φ) p (nhds 0) := hsub0.mono_left hfree' exact hy (tendsto_nhds_unique hpy hp0) -/-- The nonzero limits supplied by a separation package rule out convergence of every injective -sequence in its initial topology. -/ -theorem SeparationPackage.no_injective_sequence_converges - {I : Type u} (C : SeparationPackage I) : - ∀ s : ℕ → (I →₀ ℤ), Function.Injective s → - ¬ ∃ x : I →₀ ℤ, - Tendsto s atTop (@nhds (I →₀ ℤ) C.initialTopology x) := by - letI : TopologicalSpace (I →₀ ℤ) := C.initialTopology - letI : IsTopologicalAddGroup (I →₀ ℤ) := C.initial_isTopologicalAddGroup - letI : T2Space (I →₀ ℤ) := C.initial_t2Space - exact no_injective_sequence_converges_of_nonzeroLimitProperty - C.hasNonzeroLimitProperty - /-- Any sequence with infinite range has a strictly reindexed injective subsequence. -/ theorem exists_injective_subsequence_of_infinite_range {X : Type u} {s : ℕ → X} (hinf : (Set.range s).Infinite) : @@ -144,19 +131,6 @@ theorem eventually_eq_limit_of_no_injective_sequence_converges obtain ⟨φ, hφ, hinj⟩ := exists_injective_subsequence_of_infinite_range hinf exact ((hno (s ∘ φ) hinj) ⟨x, hs.comp hφ.tendsto_atTop⟩).elim -/-- Consequently every convergent sequence in the initial topology of a separation package is -eventually constant at its limit. -/ -theorem SeparationPackage.every_convergent_sequence_eventually_constant - {I : Type u} (C : SeparationPackage I) - {s : ℕ → (I →₀ ℤ)} {x : I →₀ ℤ} - (hs : Tendsto s atTop (@nhds (I →₀ ℤ) C.initialTopology x)) : - ∀ᶠ n in atTop, s n = x := by - letI : TopologicalSpace (I →₀ ℤ) := C.initialTopology - letI : IsTopologicalAddGroup (I →₀ ℤ) := C.initial_isTopologicalAddGroup - letI : T2Space (I →₀ ℤ) := C.initial_t2Space - exact eventually_eq_limit_of_no_injective_sequence_converges - C.no_injective_sequence_converges hs - end end Wallace diff --git a/LeanPool/Wallace/RationalClosure.lean b/LeanPool/Wallace/RationalClosure.lean index 964e8caac..abb811848 100644 --- a/LeanPool/Wallace/RationalClosure.lean +++ b/LeanPool/Wallace/RationalClosure.lean @@ -64,24 +64,6 @@ theorem closure_closedUnderPreparedSupports (x : ContinuumRationalGroup) : intro a ha n i hi exact prepared_support_mem_closure N hN M x a ha n i hi -theorem closure_nonempty {x : ContinuumRationalGroup} (hx : x ≠ 0) : - (closure N hN M x).Nonempty := by - obtain ⟨i, hi⟩ := Finsupp.support_nonempty_iff.mpr hx - exact ⟨i, support_subset_closure N hN M x hi⟩ - -/-- A fixed enumeration of the nonempty countable closure. -/ -def enumeration {x : ContinuumRationalGroup} (hx : x ≠ 0) : - ℕ → closure N hN M x := by - letI : Countable (closure N hN M x) := (closure_countable N hN M x).to_subtype - letI : Nonempty (closure N hN M x) := (closure_nonempty N hN M hx).to_subtype - exact Classical.choose (exists_surjective_nat (closure N hN M x)) - -theorem enumeration_surjective {x : ContinuumRationalGroup} (hx : x ≠ 0) : - Function.Surjective (enumeration N hN M hx) := by - letI : Countable (closure N hN M x) := (closure_countable N hN M x).to_subtype - letI : Nonempty (closure N hN M x) := (closure_nonempty N hN M hx).to_subtype - exact Classical.choose_spec (exists_surjective_nat (closure N hN M x)) - end end RationalClosure end Wallace diff --git a/LeanPool/Wallace/RationalData.lean b/LeanPool/Wallace/RationalData.lean index bbd10fe53..467c9af29 100644 --- a/LeanPool/Wallace/RationalData.lean +++ b/LeanPool/Wallace/RationalData.lean @@ -43,11 +43,6 @@ theorem label_inter_finite {a b : ContinuumIndex} (hab : a ≠ b) : apply binaryBranchOnNat_inter_finite exact continuumIndexEquivBinaryStream.injective.ne hab -theorem label_pairwise : - Pairwise fun a b : ContinuumIndex ↦ (label a ∩ label b).Finite := by - intro a b hab - exact label_inter_finite hab - variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) /-- Strictly increasing selector supplied by rational block preprocessing. -/ @@ -84,22 +79,6 @@ theorem preparedDifference_injective (a : ContinuumIndex) : apply prepared_injective N hN M a exact sub_left_injective hmn -/-- Each shifted rational block has exactly the scheduled cardinality `N l`, as in -Lemma 5.3 of the paper. -/ -theorem differenceBlock_card (a : ContinuumIndex) (l : ℕ) : - (differenceBlock N hN M a l).card = N l := by - rw [differenceBlock, - Finset.card_image_iff.mpr (preparedDifference_injective N hN M a).injOn, - TriangularPreprocess.blockPositions_card] - -theorem differenceBlock_subset_range (a : ContinuumIndex) (l : ℕ) : - ↑(differenceBlock N hN M a l) ⊆ - Set.range (fun n ↦ prepared N hN M a n - codeBasisVector a) := by - intro x hx - simp only [differenceBlock, Finset.mem_coe, Finset.mem_image] at hx - obtain ⟨n, _hn, rfl⟩ := hx - exact Set.mem_range_self n - abbrev blocks : BlockSystem := BlockSystem.ofBlockPositions N hN /-- A free ultrafilter refining the block-density filter for code `a`. -/ diff --git a/LeanPool/Wallace/RationalFusionRun.lean b/LeanPool/Wallace/RationalFusionRun.lean index 07a5fbcd2..5e7d55cfc 100644 --- a/LeanPool/Wallace/RationalFusionRun.lean +++ b/LeanPool/Wallace/RationalFusionRun.lean @@ -41,11 +41,6 @@ abbrev LocalGroup (x : ContinuumRationalGroup) := localCarrier x →₀ ℚ abbrev fresh (x : ContinuumRationalGroup) : ℕ → Finset (LocalGroup x) := localActiveBlock blockSize blockSize_pos independenceBound x -theorem localGroup_countable (x : ContinuumRationalGroup) : Countable (LocalGroup x) := by - letI : Countable (localCarrier x) := - (closure_countable blockSize blockSize_pos independenceBound x).to_subtype - infer_instance - /-- A fixed surjection used to make every local point eventually protected. -/ def localEnumeration (x : ContinuumRationalGroup) : ℕ → LocalGroup x := by letI : Countable (localCarrier x) := @@ -258,10 +253,6 @@ def localRunCertificate (x : {x : ContinuumRationalGroup // x ≠ 0}) : · exact (scheduledCertificate x).distinguished_protected codeBlocks := codeBlocks x -theorem exists_localRunCertificate - (x : {x : ContinuumRationalGroup // x ≠ 0}) : - Nonempty (LocalRunCertificate x) := ⟨localRunCertificate x⟩ - end end RationalFusionRun end Wallace diff --git a/LeanPool/Wallace/RationalLocalSetup.lean b/LeanPool/Wallace/RationalLocalSetup.lean index 0b8dc3bd3..d6b418ffd 100644 --- a/LeanPool/Wallace/RationalLocalSetup.lean +++ b/LeanPool/Wallace/RationalLocalSetup.lean @@ -65,15 +65,6 @@ theorem refinedLabel_pairwise (x : ContinuumRationalGroup) : (fun a : RelevantCode N hN M x ↦ label a.1) (relevantLabels_pairwise N hN M x))).1 -theorem refinedLabel_subset (x : ContinuumRationalGroup) - (a : RelevantCode N hN M x) : - refinedLabel N hN M x a ⊆ label a.1 := by - letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x - exact (Classical.choose_spec - (exists_disjoint_refinement_countable - (fun a : RelevantCode N hN M x ↦ label a.1) - (relevantLabels_pairwise N hN M x))).2 a |>.1 - theorem label_diff_refinedLabel_finite (x : ContinuumRationalGroup) (a : RelevantCode N hN M x) : (label a.1 \ refinedLabel N hN M x a).Finite := by @@ -108,53 +99,6 @@ theorem activeCode_eq_some_of_mem (x : ContinuumRationalGroup) (l : ℕ) · rename_i h exact (h ⟨a, ha⟩).elim -theorem mem_refinedLabel_of_activeCode_eq_some (x : ContinuumRationalGroup) (l : ℕ) - (a : RelevantCode N hN M x) (h : activeCode N hN M x l = some a) : - l ∈ refinedLabel N hN M x a := by - classical - unfold activeCode at h - split at h - · rename_i hex - have hchosen : Classical.choose hex = a := Option.some.inj h - simpa only [hchosen] using Classical.choose_spec hex - · simp at h - -theorem activeCode_eq_some_iff (x : ContinuumRationalGroup) (l : ℕ) - (a : RelevantCode N hN M x) : - activeCode N hN M x l = some a ↔ l ∈ refinedLabel N hN M x a := - ⟨mem_refinedLabel_of_activeCode_eq_some N hN M x l a, - activeCode_eq_some_of_mem N hN M x l a⟩ - -def activeBlock (x : ContinuumRationalGroup) (l : ℕ) : - Finset ContinuumRationalGroup := - match activeCode N hN M x l with - | none => ∅ - | some a => differenceBlock N hN M a.1 l - -theorem activeBlock_eq_of_mem (x : ContinuumRationalGroup) (l : ℕ) - (a : RelevantCode N hN M x) (ha : l ∈ refinedLabel N hN M x a) : - activeBlock N hN M x l = differenceBlock N hN M a.1 l := by - simp [activeBlock, activeCode_eq_some_of_mem N hN M x l a ha] - -theorem activeBlock_boundedIndependent (x : ContinuumRationalGroup) (l : ℕ) : - BoundedIndependent (M l) (activeBlock N hN M x l) := by - unfold activeBlock - split - · simp [BoundedIndependent] - · rename_i a hactive - exact differenceBlock_boundedIndependent N hN M a.1 l - -theorem activeBlock_card_le (x : ContinuumRationalGroup) (l : ℕ) : - (activeBlock N hN M x l).card ≤ N l := by - unfold activeBlock - split - · simp - · rename_i a hactive - calc - (differenceBlock N hN M a.1 l).card ≤ - (TriangularPreprocess.blockPositions N hN l).card := Finset.card_image_le - _ = N l := TriangularPreprocess.blockPositions_card N hN l - /-! ## The countable local rational group -/ def closureInclusion (x : ContinuumRationalGroup) : @@ -295,11 +239,6 @@ theorem localActiveBlock_card_le (x : ContinuumRationalGroup) (l : ℕ) : · rename_i a hactive rw [localDifferenceBlock_card] -theorem localActiveBlock_card_eq_of_mem (x : ContinuumRationalGroup) (l : ℕ) - (a : RelevantCode N hN M x) (ha : l ∈ refinedLabel N hN M x a) : - (localActiveBlock N hN M x l).card = N l := by - rw [localActiveBlock_eq_of_mem N hN M x l a ha, localDifferenceBlock_card] - end end RationalLocalSetup end Wallace diff --git a/LeanPool/Wallace/RationalTriangularPreprocess.lean b/LeanPool/Wallace/RationalTriangularPreprocess.lean index 49c8ea96f..141aad293 100644 --- a/LeanPool/Wallace/RationalTriangularPreprocess.lean +++ b/LeanPool/Wallace/RationalTriangularPreprocess.lean @@ -96,11 +96,6 @@ theorem codedSequence_injective (a : ContinuumIndex) : Function.Injective (codedSequence a) := (rationalSequenceCodeEquiv a).2 -theorem codedSequence_code_injective : Function.Injective codedSequence := by - intro a b hab - apply rationalSequenceCodeEquiv.injective - exact Subtype.ext hab - /-- The union of the finite supports of a rational sequence. -/ def sequenceSupport (s : ℕ → ContinuumRationalGroup) : Set ContinuumIndex := {i | ∃ n, i ∈ (s n).support} diff --git a/LeanPool/Wallace/Result.lean b/LeanPool/Wallace/Result.lean index e41866c2f..4a487fa86 100644 --- a/LeanPool/Wallace/Result.lean +++ b/LeanPool/Wallace/Result.lean @@ -40,12 +40,6 @@ def IsWallaceSemigroup (S : Type u) [TopologicalSpace S] [AddMonoid S] : Prop := ContinuousAdd S ∧ IsCancelAdd S ∧ T2Space S ∧ CountablyCompactSpace S ∧ ∃ x : S, ¬ IsAddUnit x -/-- The existential statement of the Wallace counterexample, bundled with its topology and -additive monoid structure. -/ -def WallaceCounterexampleExists : Prop := - ∃ (S : Type) (topology : TopologicalSpace S) (monoid : AddMonoid S), - @IsWallaceSemigroup S topology monoid - /-- A convenient unbundled form of the accumulation-point criterion used for countable compactness. -/ def HasInfiniteSetAccumulationProperty @@ -214,36 +208,4 @@ theorem positiveCone_isWallace_of_limitProperty addSubmonoid_isWallace_of_limitProperty (positiveCone ι) hlimits (single_one_mem_positiveCone ι i) (neg_single_one_not_mem_positiveCone ι i) -/-- A concrete index type of cardinality continuum for the free Abelian group in the paper. -/ -abbrev ContinuumFreeAbelianGroup := ℝ →₀ ℤ - -/-- The nonnegative cone in the free Abelian group indexed by the continuum. -/ -abbrev continuumPositiveCone : AddSubmonoid ContinuumFreeAbelianGroup := - positiveCone ℝ - -/-- The corollary in its concrete continuum-indexed form. - -The hypothesis is precisely the construction-specific property supplied by the main theorem of -the paper; the entire deduction after that point is proved here. -/ -theorem continuumPositiveCone_isWallace_of_limitProperty - [TopologicalSpace ContinuumFreeAbelianGroup] - [IsTopologicalAddGroup ContinuumFreeAbelianGroup] - [T2Space ContinuumFreeAbelianGroup] - (hlimits : HasWallaceLimitProperty - (F := ContinuumFreeAbelianGroup) continuumPositiveCone) : - IsWallaceSemigroup continuumPositiveCone := - positiveCone_isWallace_of_limitProperty ℝ (0 : ℝ) hlimits - -/-- Existential form of the Wallace conclusion from a Hausdorff topological group structure and -the construction-specific limit property supplied by the paper. -/ -theorem wallaceCounterexampleExists_of_limitProperty - [TopologicalSpace ContinuumFreeAbelianGroup] - [IsTopologicalAddGroup ContinuumFreeAbelianGroup] - [T2Space ContinuumFreeAbelianGroup] - (hlimits : HasWallaceLimitProperty - (F := ContinuumFreeAbelianGroup) continuumPositiveCone) : - WallaceCounterexampleExists := by - refine ⟨continuumPositiveCone, inferInstance, inferInstance, ?_⟩ - exact continuumPositiveCone_isWallace_of_limitProperty hlimits - end Wallace diff --git a/LeanPool/Wallace/SeparationInterface.lean b/LeanPool/Wallace/SeparationInterface.lean index cd4ad66c8..b7b61e7f4 100644 --- a/LeanPool/Wallace/SeparationInterface.lean +++ b/LeanPool/Wallace/SeparationInterface.lean @@ -125,28 +125,6 @@ theorem positiveCone_hasWallaceLimitProperty (C : SeparationPackage I) : rw [← hcoded] exact C.prepared_tendsto_basis c -/-- A minimal construction package yields a Hausdorff group topology with the Wallace limit -property on the nonnegative cone. -/ -theorem exists_initialTopology_with_wallaceLimitProperty (C : SeparationPackage I) : - ∃ topology : TopologicalSpace (I →₀ ℤ), - @IsTopologicalAddGroup (I →₀ ℤ) topology _ ∧ - @T2Space (I →₀ ℤ) topology ∧ - @HasWallaceLimitProperty (I →₀ ℤ) topology _ (positiveCone I) := by - exact ⟨C.initialTopology, C.initial_isTopologicalAddGroup, C.initial_t2Space, - C.positiveCone_hasWallaceLimitProperty⟩ - -/-- Once the genuinely constructed package is available on a nonempty index type, the Wallace -counterexample follows with no further hypotheses. -/ -theorem wallaceCounterexampleExists {I : Type} (C : SeparationPackage I) [Nonempty I] : - WallaceCounterexampleExists := by - let topology : TopologicalSpace (I →₀ ℤ) := C.initialTopology - letI : TopologicalSpace (I →₀ ℤ) := topology - letI : IsTopologicalAddGroup (I →₀ ℤ) := C.initial_isTopologicalAddGroup - letI : T2Space (I →₀ ℤ) := C.initial_t2Space - let i : I := Classical.choice inferInstance - refine ⟨positiveCone I, inferInstance, inferInstance, ?_⟩ - exact positiveCone_isWallace_of_limitProperty I i C.positiveCone_hasWallaceLimitProperty - end SeparationPackage end diff --git a/LeanPool/Wallace/TorsionFreeCoordinate.lean b/LeanPool/Wallace/TorsionFreeCoordinate.lean index a95c50d3d..776eb2974 100644 --- a/LeanPool/Wallace/TorsionFreeCoordinate.lean +++ b/LeanPool/Wallace/TorsionFreeCoordinate.lean @@ -36,41 +36,6 @@ namespace RationalCoordinatization variable {G : Type} [AddCommGroup G] -/-- The coordinatewise inclusion `ℤ^(𝔠) → ℚ^(𝔠)` occurring in the paper's -coordinatization lemma. -/ -def integerCoordinateEmbedding : - TriangularPreprocess.ContinuumFreeGroup →+ - RationalTriangularPreprocess.ContinuumRationalGroup := - Finsupp.mapRange.addMonoidHom (Int.castAddHom ℚ) - -theorem integerCoordinateEmbedding_injective : - Function.Injective integerCoordinateEmbedding := by - intro z w h - ext i - have hi := congrArg (fun q : RationalTriangularPreprocess.ContinuumRationalGroup ↦ q i) h - change (z i : ℚ) = (w i : ℚ) at hi - exact_mod_cast hi - -/-- Integer linear combinations of the distinguished preimages in `G`. -/ -def integerCoordinatePreimage (K : RationalCoordinatization G) : - TriangularPreprocess.ContinuumFreeGroup →+ G := - Finsupp.liftAddHom (fun i ↦ zmultiplesHom G (K.basisPreimage i)) - -/-- The embedding of a coordinatized group contains the whole canonical copy of -`ℤ^(𝔠)`, not merely its individual basis vectors. -/ -theorem embedding_integerCoordinatePreimage (K : RationalCoordinatization G) : - K.embedding.comp K.integerCoordinatePreimage = integerCoordinateEmbedding := by - ext i z - simp [integerCoordinatePreimage, integerCoordinateEmbedding, - K.embedding_basisPreimage] - -theorem integerCoordinatePreimage_injective (K : RationalCoordinatization G) : - Function.Injective K.integerCoordinatePreimage := by - intro z w h - apply integerCoordinateEmbedding_injective - rw [← K.embedding_integerCoordinatePreimage] - simpa using congrArg K.embedding h - variable [IsAddTorsionFree G] omit [IsAddTorsionFree G] in @@ -176,19 +141,6 @@ def ofCardinalityContinuum (hcard : #G = 𝔠) : RationalCoordinatization G wher basisPreimage := basisNumerator (G := G) hcard embedding_basisPreimage := canonicalEmbedding_basisNumerator hcard -/-- A proposition-level form of the paper's coordinatization lemma: the map is -injective and its image contains the canonical copy of `ℤ^(𝔠)` in `ℚ^(𝔠)`. -/ -theorem exists_coordinatization (hcard : #G = 𝔠) : - ∃ (embedding : G →+ RationalTriangularPreprocess.ContinuumRationalGroup) - (preimage : TriangularPreprocess.ContinuumFreeGroup →+ G), - Function.Injective embedding ∧ - Function.Injective preimage ∧ - embedding.comp preimage = integerCoordinateEmbedding := by - let K := ofCardinalityContinuum (G := G) hcard - exact ⟨K.embedding, K.integerCoordinatePreimage, K.embedding_injective, - K.integerCoordinatePreimage_injective, - K.embedding_integerCoordinatePreimage⟩ - end RationalCoordinatization end diff --git a/LeanPool/Wallace/TriangularPreprocess.lean b/LeanPool/Wallace/TriangularPreprocess.lean index ff8ba4942..d7f648515 100644 --- a/LeanPool/Wallace/TriangularPreprocess.lean +++ b/LeanPool/Wallace/TriangularPreprocess.lean @@ -92,11 +92,6 @@ theorem codedSequence_injective (a : ContinuumIndex) : Function.Injective (codedSequence a) := (sequenceCodeEquiv a).2 -theorem codedSequence_code_injective : Function.Injective codedSequence := by - intro a b hab - apply sequenceCodeEquiv.injective - exact Subtype.ext hab - /-! ## Countable supports have strict upper bounds -/ /-- All coordinates that occur in a sequence. -/ @@ -195,38 +190,6 @@ theorem codedSequence_supportedBelow (a : ContinuumIndex) : intro n i hi exact (support_lt_supportBound a hi).trans (freshIndex_spec supportBound a).1 -/-- The paper's set `Λ` of fresh indices. -/ -abbrev TriangularIndices : Set ContinuumIndex := Set.range codeIndex - -/-- The code type and `Λ` are equivalent by the fresh-index embedding. -/ -def codeIndexEquiv : ContinuumIndex ≃ TriangularIndices := - Equiv.ofInjective codeIndex codeIndex.injective - -/-- The paper-style enumeration, now indexed literally by `Λ`. -/ -def triangularSequenceEquiv : TriangularIndices ≃ InjectiveSequences := - codeIndexEquiv.symm.trans sequenceCodeEquiv - -def triangularSequence (α : TriangularIndices) : ℕ → ContinuumFreeGroup := - (triangularSequenceEquiv α).1 - -@[simp] -theorem mk_triangularIndices : #TriangularIndices = 𝔠 := by - exact (Cardinal.mk_range_eq codeIndex codeIndex.injective).trans mk_continuumIndex - -theorem triangularSequence_injective (α : TriangularIndices) : - Function.Injective (triangularSequence α) := - (triangularSequenceEquiv α).2 - -/-- Exact triangular support condition with the fresh index itself as upper bound. -/ -theorem triangularSequence_supportedBelow (α : TriangularIndices) : - FiniteCombinatorics.SupportedBelow (triangularSequence α) α := by - let a := codeIndexEquiv.symm α - have hα : (codeIndex a : ContinuumIndex) = α := by - exact Subtype.ext_iff.mp (codeIndexEquiv.apply_symm_apply α) - change FiniteCombinatorics.SupportedBelow - (codedSequence (codeIndexEquiv.symm α)) α - simpa only [a, hα] using codedSequence_supportedBelow a - /-! ## Blockwise bounded-independence selection -/ open FiniteCombinatorics @@ -538,29 +501,6 @@ theorem blockPositions_card (blockPositions N hN l).card = N l := by simp [blockPositions, blockStart_succ] -theorem blockPositions_disjoint - (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) {l k : ℕ} (hlk : l ≠ k) : - Disjoint (blockPositions N hN l) (blockPositions N hN k) := by - rw [Finset.disjoint_left] - intro n hnl hnk - have hl := (mem_blockPositions_iff N hN).mp hnl - have hk := (mem_blockPositions_iff N hN).mp hnk - exact hlk (hl.symm.trans hk) - -theorem mem_blockPositions_blockOf - (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (n : ℕ) : - n ∈ blockPositions N hN (blockOf N hN n) := - (mem_blockPositions_iff N hN).mpr rfl - -/-- The finite blocks are pairwise disjoint and cover all natural-number positions. -/ -theorem iUnion_blockPositions - (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) : - ⋃ l, (blockPositions N hN l : Set ℕ) = Set.univ := by - apply Set.eq_univ_of_forall - intro n - exact Set.mem_iUnion.mpr - ⟨blockOf N hN n, mem_blockPositions_blockOf N hN n⟩ - theorem blockFiber_finite (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (l : ℕ) : {n | blockOf N hN n = l}.Finite := by diff --git a/LeanPool/Wallace/UniformKronecker.lean b/LeanPool/Wallace/UniformKronecker.lean index c095baf83..d28467b98 100644 --- a/LeanPool/Wallace/UniformKronecker.lean +++ b/LeanPool/Wallace/UniformKronecker.lean @@ -66,11 +66,6 @@ abbrev relationGroup {G : Type u} [AddCommGroup G] {m : ℕ} (z : Fin m → G) : AddSubgroup (Fin m → ℤ) := (relationMap z).ker -theorem mem_relationGroup_iff {G : Type u} [AddCommGroup G] {m : ℕ} - (z : Fin m → G) (a : Fin m → ℤ) : - a ∈ relationGroup z ↔ ∑ i, a i • z i = 0 := by - rfl - /-- A target tuple respects every relation of `z`. -/ def RespectsRelations {G : Type u} [AddCommGroup G] {m : ℕ} (z : Fin m → G) (t : Fin m → UnitAddCircle) : Prop := @@ -96,14 +91,6 @@ def RespectsRelationsUpTo {G : Type u} [AddCommGroup G] {m : ℕ} ∀ a : Fin m → ℤ, intVectorHeight a ≤ q → relationMap z a = 0 → torusRelationMap t a = 0 -theorem RespectsRelations.respectsRelationsUpTo - {G : Type u} [AddCommGroup G] {m : ℕ} - {z : Fin m → G} {t : Fin m → UnitAddCircle} - (h : RespectsRelations z t) (q : ℕ) : - RespectsRelationsUpTo q z t := by - intro a _ha haz - exact h haz - /-- `q` is a uniform Kronecker bound for tuples of length `m` and error `ε`. -/ def IsUniformKroneckerBound (m : ℕ) (ε : ℝ) (q : ℕ) : Prop := ∀ {G : Type u} [AddCommGroup G] (z : Fin m → G) (t : Fin m → UnitAddCircle), @@ -151,32 +138,6 @@ theorem exists_character_of_respectsRelations AddMonoidHom.coe_rangeRestrict, relationMap_single, torusRelationMap_single] using hrange.trans htuple -/-- Characters into the unit additive circle separate points of every torsion-free Abelian -group. -/ -theorem exists_character_ne_zero {G : Type u} [AddCommGroup G] [IsAddTorsionFree G] - {x : G} (hx : x ≠ 0) : - ∃ χ : G →+ UnitAddCircle, χ x ≠ 0 := by - let z : Fin 1 → G := fun _ => x - let t : Fin 1 → UnitAddCircle := fun _ => (1 / 2 : ℝ) - have hrel : RespectsRelations z t := by - rw [respectsRelations_iff] - intro a ha - have ha0 : a 0 = 0 := by - have : a 0 • x = 0 := by simpa [z] using ha - exact (IsAddTorsionFree.zsmul_eq_zero_iff_left hx).mp this - simp [t, ha0] - obtain ⟨χ, hχ⟩ := exists_character_of_respectsRelations z t hrel - refine ⟨χ, ?_⟩ - have hχx : χ x = ((1 / 2 : ℝ) : UnitAddCircle) := by simpa [z, t] using hχ 0 - rw [hχx] - intro hzero - rw [AddCircle.coe_eq_zero_iff] at hzero - obtain ⟨n, hn⟩ := hzero - have hnR : (n : ℝ) = 1 / 2 := by simpa using hn - have hn' : (2 : ℝ) * (n : ℝ) = 1 := by linarith - have hnInt : (2 : ℤ) * n = 1 := by exact_mod_cast hn' - omega - /-! ## Algebraic separation into the real unit circle -/ /-- The embedding of the rational additive circle into the real additive circle. -/ @@ -239,12 +200,6 @@ def integerAnnihilator {m : ℕ} (R : AddSubgroup (Fin m → ℤ)) : change ∑ i, a i • (-x i) = 0 simp_rw [smul_neg, Finset.sum_neg_distrib, hx a ha, neg_zero] -@[simp] -theorem mem_integerAnnihilator_iff {m : ℕ} {R : AddSubgroup (Fin m → ℤ)} - {x : UnitAddTorus (Fin m)} : - x ∈ integerAnnihilator R ↔ ∀ a ∈ R, torusRelationMap x a = 0 := - Iff.rfl - theorem isClosed_integerAnnihilator {m : ℕ} (R : AddSubgroup (Fin m → ℤ)) : IsClosed (integerAnnihilator R : Set (UnitAddTorus (Fin m))) := by rw [show (integerAnnihilator R : Set (UnitAddTorus (Fin m))) = @@ -255,18 +210,6 @@ theorem isClosed_integerAnnihilator {m : ℕ} (R : AddSubgroup (Fin m → ℤ)) change IsClosed {x : UnitAddTorus (Fin m) | (∑ i, a i • x i) = 0} exact isClosed_singleton.preimage (by fun_prop) -/-- The annihilator, bundled as a nonempty compact subset of the finite torus. -/ -def integerAnnihilatorCompact {m : ℕ} (R : AddSubgroup (Fin m → ℤ)) : - NonemptyCompacts (UnitAddTorus (Fin m)) := - ⟨⟨integerAnnihilator R, - (isClosed_integerAnnihilator R).isCompact⟩, - ⟨0, (integerAnnihilator R).zero_mem⟩⟩ - -@[simp] -theorem coe_integerAnnihilatorCompact {m : ℕ} (R : AddSubgroup (Fin m → ℤ)) : - (integerAnnihilatorCompact R : Set (UnitAddTorus (Fin m))) = integerAnnihilator R := - rfl - /-- Distance to the relation annihilator, as a bounded continuous real-valued function. -/ def annihilatorDistance {m : ℕ} (R : AddSubgroup (Fin m → ℤ)) : BoundedContinuousFunction (UnitAddTorus (Fin m)) ℝ := @@ -325,15 +268,6 @@ theorem exists_mem_integerAnnihilator_not_annihilate {m : ℕ} rw [hb0, map_zero] · simpa only [heval] using hc -theorem mem_iff_annihilates_integerAnnihilator {m : ℕ} - (R : AddSubgroup (Fin m → ℤ)) (a : Fin m → ℤ) : - a ∈ R ↔ ∀ x ∈ integerAnnihilator R, torusRelationMap x a = 0 := by - constructor - · intro ha x hx - exact hx a ha - · contrapose! - exact exists_mem_integerAnnihilator_not_annihilate R - theorem mFourier_eq_toCircle_relation {m : ℕ} (a : Fin m → ℤ) (x : UnitAddTorus (Fin m)) : UnitAddTorus.mFourier a x = (AddCircle.toCircle (torusRelationMap x a) : ℂ) := by @@ -351,29 +285,6 @@ theorem mFourier_eq_toCircle_relation {m : ℕ} (a : Fin m → ℤ) (AddCircle.toCircle (∑ i, a i • x i) : ℂ) simpa only [Finset.prod_const_one, Finset.sum_const_zero] using hprod Finset.univ -/-- The family of all distance-to-annihilator functions for a fixed tuple length. -/ -def annihilatorDistanceFamily (m : ℕ) : - Set (BoundedContinuousFunction (UnitAddTorus (Fin m)) ℝ) := - Set.range annihilatorDistance - -/-- Arzelà--Ascoli makes the closure of the family of annihilator-distance functions compact. -All functions are `1`-Lipschitz and their ranges lie in one compact interval. -/ -theorem isCompact_closure_annihilatorDistanceFamily (m : ℕ) : - IsCompact (closure (annihilatorDistanceFamily m)) := by - let D : ℝ := Metric.diam (Set.univ : Set (UnitAddTorus (Fin m))) - apply BoundedContinuousFunction.arzela_ascoli (Set.Icc 0 D) isCompact_Icc - · rintro f x ⟨R, rfl⟩ - refine ⟨Metric.infDist_nonneg, ?_⟩ - calc - Metric.infDist x (integerAnnihilator R) ≤ dist x 0 := - Metric.infDist_le_dist_of_mem (integerAnnihilator R).zero_mem - _ ≤ D := Metric.dist_le_diam_of_mem isCompact_univ.isBounded - (mem_univ x) (mem_univ 0) - · apply UniformEquicontinuous.equicontinuous - apply LipschitzWith.uniformEquicontinuous _ 1 - rintro ⟨f, R, rfl⟩ - exact annihilatorDistance_lipschitz R - /-- Regard a bounded real-valued continuous function on the compact torus as a complex-valued continuous function. -/ def complexifyDistanceFunction {m : ℕ} From 11884462d5041d6a0d6146041cd90d23c3ef1013 Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 4 Sep 2026 13:46:46 +0000 Subject: [PATCH 3/7] Narrow Wallace dependencies and clear warnings --- LeanPool/Wallace/BlockFilters.lean | 11 ++++----- LeanPool/Wallace/BlockLimit.lean | 4 ++-- LeanPool/Wallace/BoundedIndependentMap.lean | 3 +-- LeanPool/Wallace/ConcreteLocalSetup.lean | 6 ++--- .../Wallace/CountableDisjointization.lean | 2 +- LeanPool/Wallace/FiniteCombinatorics.lean | 18 +++++++------- LeanPool/Wallace/FullTopology.lean | 20 ++++++++-------- LeanPool/Wallace/FusionStage.lean | 7 +++--- LeanPool/Wallace/LocalEnumeration.lean | 3 ++- LeanPool/Wallace/LocalFusion.lean | 17 ++++++++----- LeanPool/Wallace/MathlibFoundations.lean | 11 +++++++-- LeanPool/Wallace/NontrivialSequences.lean | 2 +- LeanPool/Wallace/RationalFusionRun.lean | 3 ++- LeanPool/Wallace/RationalLocalSetup.lean | 6 ++--- .../Wallace/RationalTransfiniteExtension.lean | 3 ++- .../Wallace/RationalTriangularPreprocess.lean | 5 ++-- LeanPool/Wallace/Result.lean | 2 +- LeanPool/Wallace/SeparationInterface.lean | 6 ++--- LeanPool/Wallace/TransfiniteExtension.lean | 3 ++- LeanPool/Wallace/TriangularPreprocess.lean | 9 ++++--- LeanPool/Wallace/TychonoffWallace.lean | 14 +++++------ LeanPool/Wallace/UniformKronecker.lean | 24 +++++++++---------- 22 files changed, 97 insertions(+), 82 deletions(-) diff --git a/LeanPool/Wallace/BlockFilters.lean b/LeanPool/Wallace/BlockFilters.lean index 5bf5886c7..d1f12b786 100644 --- a/LeanPool/Wallace/BlockFilters.lean +++ b/LeanPool/Wallace/BlockFilters.lean @@ -57,7 +57,6 @@ theorem ofBlockPositions_block (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (l : ℕ) (ofBlockPositions N hN).block l = TriangularPreprocess.blockPositions N hN l := rfl -@[simp] theorem ofBlockPositions_card (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (l : ℕ) : ((ofBlockPositions N hN).block l).card = N l := TriangularPreprocess.blockPositions_card N hN l @@ -100,7 +99,7 @@ theorem missingRatio_mono (B : BlockSystem) {A C : Set ℕ} (hAC : A ⊆ C) (l : theorem missingRatio_inter_le (B : BlockSystem) (A C : Set ℕ) (l : ℕ) : B.missingRatio (A ∩ C) l ≤ B.missingRatio A l + B.missingRatio C l := by classical - letI (n : ℕ) : Decidable (n ∈ A ∩ C) := Classical.propDecidable _ + let (n : ℕ) : Decidable (n ∈ A ∩ C) := Classical.propDecidable _ have hsubset : (B.block l).filter (fun n ↦ n ∉ A ∩ C) ⊆ (B.block l).filter (fun n ↦ n ∉ A) ∪ @@ -154,7 +153,7 @@ theorem densityFilter_le_cofinite (B : BlockSystem) (a : Set ℕ) : classical rw [le_cofinite_iff_compl_singleton_mem] intro n - letI (k : ℕ) : Decidable (k ∈ ({n} : Set ℕ)ᶜ) := Classical.propDecidable _ + let (k : ℕ) : Decidable (k ∈ ({n} : Set ℕ)ᶜ) := Classical.propDecidable _ rw [mem_densityFilter_iff] unfold IsLarge apply tendsto_congr' ?_ |>.mpr tendsto_const_nhds @@ -187,7 +186,7 @@ theorem densityFilter_neBot (B : BlockSystem) {a : Set ℕ} (ha : a.Infinite) : exact Filter.mem_bot rw [mem_densityFilter_iff] at hempty unfold IsLarge at hempty - haveI : NeBot (atTop ⊓ Filter.principal a) := by + have : NeBot (atTop ⊓ Filter.principal a) := by rw [← Nat.cofinite_eq_atTop] exact ha.cofinite_inf_principal_neBot have hone_tendsto : @@ -204,7 +203,7 @@ theorem exists_free_ultrafilter_le_densityFilter (B : BlockSystem) {a : Set ℕ} (ha : a.Infinite) : ∃ p : Ultrafilter ℕ, (p : Filter ℕ) ≤ B.densityFilter a ∧ (p : Filter ℕ) ≤ cofinite := by - letI : (B.densityFilter a).NeBot := B.densityFilter_neBot ha + let : (B.densityFilter a).NeBot := B.densityFilter_neBot ha exact exists_free_ultrafilter_le_filter (B.densityFilter a) (B.densityFilter_le_cofinite a) @@ -225,7 +224,7 @@ def disjointize [Preorder ι] (family : ι → Set α) (j : ι) : Set α := theorem disjointize_subset [Preorder ι] (family : ι → Set α) (j : ι) : disjointize family j ⊆ family j := - Set.diff_subset + Set.sdiff_subset /-- Disjointization makes any linearly enumerated family pairwise disjoint; no almost-disjointness assumption is needed for this part. -/ diff --git a/LeanPool/Wallace/BlockLimit.lean b/LeanPool/Wallace/BlockLimit.lean index 983348235..f992ba168 100644 --- a/LeanPool/Wallace/BlockLimit.lean +++ b/LeanPool/Wallace/BlockLimit.lean @@ -35,7 +35,7 @@ theorem tendsto_blockOf_atTop have heq : {n : ℕ | blockOf N hN n < L} = ⋃ l ∈ Set.Iio L, {n : ℕ | blockOf N hN n = l} := by ext n - simp only [Set.mem_setOf_eq, Set.mem_iUnion, exists_prop] + simp only [Set.mem_ofPred_eq, Set.mem_iUnion, exists_prop] constructor · intro hn exact ⟨blockOf N hN n, hn, rfl⟩ @@ -44,7 +44,7 @@ theorem tendsto_blockOf_atTop rw [heq] exact (Set.finite_Iio L).biUnion fun l _hl ↦ blockFiber_finite N hN l have hcompl : {n : ℕ | ¬ blockOf N hN n < L} ∈ (cofinite : Filter ℕ) := by - simpa only [Set.compl_setOf] using hfinite.compl_mem_cofinite + simpa only [Set.compl_ofPred] using hfinite.compl_mem_cofinite have hlarge : {n : ℕ | L ≤ blockOf N hN n} ∈ (cofinite : Filter ℕ) := by simpa only [not_lt] using hcompl exact hp hlarge diff --git a/LeanPool/Wallace/BoundedIndependentMap.lean b/LeanPool/Wallace/BoundedIndependentMap.lean index 63e54b84f..7f2d357c5 100644 --- a/LeanPool/Wallace/BoundedIndependentMap.lean +++ b/LeanPool/Wallace/BoundedIndependentMap.lean @@ -21,8 +21,7 @@ universe u v /-- Bounded independence is reflected by an injective additive homomorphism. -/ theorem boundedIndependent_of_image - {G : Type u} {H : Type v} [AddCommGroup G] [AddCommGroup H] - [DecidableEq G] [DecidableEq H] + {G : Type u} {H : Type v} [AddCommGroup G] [AddCommGroup H] [DecidableEq H] (f : G →+ H) (hf : Function.Injective f) {M : ℕ} {X : Finset G} (himage : BoundedIndependent M (X.image f)) : diff --git a/LeanPool/Wallace/ConcreteLocalSetup.lean b/LeanPool/Wallace/ConcreteLocalSetup.lean index a41ad12cd..3018593dc 100644 --- a/LeanPool/Wallace/ConcreteLocalSetup.lean +++ b/LeanPool/Wallace/ConcreteLocalSetup.lean @@ -62,7 +62,7 @@ def refinedLabel (x : ContinuumFreeGroup) : RelevantCode N hN M x → Set ℕ := theorem refinedLabel_pairwise (x : ContinuumFreeGroup) : Pairwise fun a b : RelevantCode N hN M x ↦ Disjoint (refinedLabel N hN M x a) (refinedLabel N hN M x b) := by - letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x + let : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x exact (Classical.choose_spec (exists_disjoint_refinement_countable (fun a : RelevantCode N hN M x ↦ label a.1) @@ -71,7 +71,7 @@ theorem refinedLabel_pairwise (x : ContinuumFreeGroup) : theorem label_diff_refinedLabel_finite (x : ContinuumFreeGroup) (a : RelevantCode N hN M x) : (label a.1 \ refinedLabel N hN M x a).Finite := by - letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x + let : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x exact (Classical.choose_spec (exists_disjoint_refinement_countable (fun a : RelevantCode N hN M x ↦ label a.1) @@ -166,7 +166,7 @@ theorem closureInclusion_localDifference closureInclusion N hN M x (localDifference N hN M x a n) = prepared N hN M a.1 n - codeBasisVector a.1 := by classical - letI : DecidablePred (closure N hN M x : ContinuumIndex → Prop) := + let : DecidablePred (closure N hN M x : ContinuumIndex → Prop) := fun _ ↦ Classical.propDecidable _ rw [closureInclusion_apply] change Finsupp.embDomain diff --git a/LeanPool/Wallace/CountableDisjointization.lean b/LeanPool/Wallace/CountableDisjointization.lean index 76da3c4dd..fd29a9b1a 100644 --- a/LeanPool/Wallace/CountableDisjointization.lean +++ b/LeanPool/Wallace/CountableDisjointization.lean @@ -36,7 +36,7 @@ theorem exists_disjoint_refinement_countable ∀ i, refined i ⊆ family i ∧ (family i \ refined i).Finite := by let rank : ι → ℕ := Classical.choose (exists_injective_nat ι) have hrank : Function.Injective rank := Classical.choose_spec (exists_injective_nat ι) - letI : LinearOrder ι := LinearOrder.lift' rank hrank + let : LinearOrder ι := LinearOrder.lift' rank hrank have hpred (i : ι) : (Set.Iio i).Finite := by have heq : Set.Iio i = rank ⁻¹' Set.Iio (rank i) := by ext j diff --git a/LeanPool/Wallace/FiniteCombinatorics.lean b/LeanPool/Wallace/FiniteCombinatorics.lean index 7433d1ed1..35c124e17 100644 --- a/LeanPool/Wallace/FiniteCombinatorics.lean +++ b/LeanPool/Wallace/FiniteCombinatorics.lean @@ -4,7 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues -/ -import Mathlib +import Mathlib.Analysis.Normed.Field.Lemmas +import Mathlib.NumberTheory.NumberField.Basic +import Mathlib.Tactic.DeriveFintype /-! # Finite combinatorics used in the Wallace construction @@ -101,7 +103,7 @@ theorem equationSolution_spec {B : Finset G} {q : ℤ} {c : B → ℤ} (h : ∃ x : G, q • x + ∑ b, c b • (b : G) = 0) : q • equationSolution B q c + ∑ b, c b • (b : G) = 0 := by classical - simp only [equationSolution, dif_pos h] + simp only [equationSolution, dite_eq_left h] exact Classical.choose_spec h /-- A concrete finite set containing every forbidden point. -/ @@ -130,7 +132,7 @@ theorem forbidden_mem_forbiddenFinset [IsAddTorsionFree G] rw [hxeq] exact Finset.mem_image.mpr ⟨(q, c), Finset.mem_product.mpr ⟨hqmem, hcmem⟩, rfl⟩ -theorem boundedIndependent_insert_of_not_forbidden [IsAddTorsionFree G] [DecidableEq G] +theorem boundedIndependent_insert_of_not_forbidden [DecidableEq G] {M : ℕ} {Y : Finset G} {x : G} (hY : BoundedIndependent M Y) (hxY : x ∉ Y) (hx : ¬ Forbidden M Y x) : BoundedIndependent M (insert x Y) := by @@ -337,7 +339,7 @@ noncomputable def deletionIndependenceBound (r Q : ℕ) : ℕ := From an adequately bounded-independent finite set `X`, delete at most `|A|` points so that no bounded relation uses both `A` and the retained set. The threshold and the conclusion—including the sharp deletion count `|X \ Y| ≤ |A|`—are the ones in the paper. -/ -theorem bounded_deletion [IsAddTorsionFree G] [DecidableEq G] +theorem bounded_deletion [DecidableEq G] (r Q : ℕ) (A X : Finset G) (hAr : A.card ≤ r) (hX : BoundedIndependent (deletionIndependenceBound r Q) X) : ∃ Y : Finset G, Y ⊆ X ∧ (X \ Y).card ≤ A.card ∧ MixedRelationFree Q A Y := by @@ -370,9 +372,9 @@ theorem bounded_deletion [IsAddTorsionFree G] [DecidableEq G] if z ∈ insert (point i) Y then c i z else 0 have hcNBound (i : Fin (s + 1)) (z : G) : Int.natAbs (cN i z) ≤ Q := by by_cases hz : z ∈ insert (point i) Y - · rw [show cN i z = c i z by simp only [cN, if_pos hz]] + · rw [show cN i z = c i z by simp only [cN, ite_eq_left hz]] exact hcQ i z hz - · rw [show cN i z = 0 by simp only [cN, if_neg hz]] + · rw [show cN i z = 0 by simp only [cN, ite_eq_right hz]] simp have hcNPoint (i : Fin (s + 1)) : cN i (point i) ≠ 0 := by simpa [cN] using hcx i @@ -383,7 +385,7 @@ theorem bounded_deletion [IsAddTorsionFree G] [DecidableEq G] congr 1 apply Finset.sum_congr rfl intro z hz - rw [show cN i z = c i z by simp only [cN, if_pos hz]] + rw [show cN i z = c i z by simp only [cN, ite_eq_left hz]] let k : G → ℤ := fun z ↦ ∑ i, coeff i * cN i z have hkBound : ∀ z ∈ X, Int.natAbs (k z) ≤ deletionIndependenceBound r Q := by @@ -462,7 +464,7 @@ theorem bounded_deletion [IsAddTorsionFree G] [DecidableEq G] symm apply Finset.sum_subset (hinsertX i) intro z hzX hznot - have hcz : cN i z = 0 := by simp only [cN, if_neg hznot] + have hcz : cN i z = 0 := by simp only [cN, ite_eq_right hznot] simp [hcz] _ = ∑ i, coeff i • (∑ z ∈ insert (point i) Y, cN i z • z) := by diff --git a/LeanPool/Wallace/FullTopology.lean b/LeanPool/Wallace/FullTopology.lean index 43f572acb..eb1e63ad5 100644 --- a/LeanPool/Wallace/FullTopology.lean +++ b/LeanPool/Wallace/FullTopology.lean @@ -123,7 +123,7 @@ theorem initial_isTopologicalAddGroup (C : FullCharacterPackage G) : theorem initial_t2Space (C : FullCharacterPackage G) : @T2Space G C.initialTopology := by - letI : TopologicalSpace G := C.initialTopology + let : TopologicalSpace G := C.initialTopology exact C.evaluation_injective.isEmbedding_induced.t2Space /-- The selected subsequence converges to its prescribed point in the initial topology. -/ @@ -132,7 +132,7 @@ theorem prepared_tendsto_limitPoint (C : FullCharacterPackage G) (c : C.Code) : (fun n ↦ (C.codeEquiv c).1 (C.subsequence c n)) (C.ultrafilter c) (@nhds G C.initialTopology (C.limitPoint c)) := by - letI : TopologicalSpace G := C.initialTopology + let : TopologicalSpace G := C.initialTopology have hinducing : IsInducing C.evaluation := ⟨rfl⟩ refine hinducing.tendsto_nhds_iff.mpr ?_ refine tendsto_pi_nhds.2 fun j ↦ ?_ @@ -154,17 +154,17 @@ theorem hasNonzeroLimitProperty (C : FullCharacterPackage G) : theorem initial_countablyCompactSpace (C : FullCharacterPackage G) : @CountablyCompactSpace G C.initialTopology := by - letI : TopologicalSpace G := C.initialTopology - letI : T2Space G := C.initial_t2Space + let : TopologicalSpace G := C.initialTopology + let : T2Space G := C.initial_t2Space exact countablyCompact_of_nonzero_ultrafilter_limits C.hasNonzeroLimitProperty theorem initial_noInjectiveConvergentSequences (C : FullCharacterPackage G) : ∀ s : ℕ → G, Function.Injective s → ¬ ∃ x : G, Tendsto s atTop (@nhds G C.initialTopology x) := by - letI : TopologicalSpace G := C.initialTopology - letI : IsTopologicalAddGroup G := C.initial_isTopologicalAddGroup - letI : T2Space G := C.initial_t2Space + let : TopologicalSpace G := C.initialTopology + let : IsTopologicalAddGroup G := C.initial_isTopologicalAddGroup + let : T2Space G := C.initial_t2Space exact no_injective_sequence_converges_of_nonzeroLimitProperty C.hasNonzeroLimitProperty @@ -173,8 +173,8 @@ theorem initial_onlyEventuallyConstantConvergentSequences ∀ (s : ℕ → G) (x : G), Tendsto s atTop (@nhds G C.initialTopology x) → ∀ᶠ n in atTop, s n = x := by - letI : TopologicalSpace G := C.initialTopology - letI : T2Space G := C.initial_t2Space + let : TopologicalSpace G := C.initialTopology + let : T2Space G := C.initial_t2Space intro s x hs exact eventually_eq_limit_of_no_injective_sequence_converges C.initial_noInjectiveConvergentSequences hs @@ -183,7 +183,7 @@ theorem initial_onlyEventuallyConstantConvergentSequences circle. -/ theorem initial_totallyBounded (C : FullCharacterPackage G) : @TotallyBounded G C.initialUniformSpace Set.univ := by - letI : UniformSpace G := C.initialUniformSpace + let : UniformSpace G := C.initialUniformSpace have hinducing : IsUniformInducing C.evaluation := ⟨rfl⟩ have htarget : TotallyBounded (Set.univ : Set (C.CharacterIndex → UnitAddCircle)) := diff --git a/LeanPool/Wallace/FusionStage.lean b/LeanPool/Wallace/FusionStage.lean index d983d559a..00f94e0aa 100644 --- a/LeanPool/Wallace/FusionStage.lean +++ b/LeanPool/Wallace/FusionStage.lean @@ -27,6 +27,7 @@ open FiniteCombinatorics variable {G : Type u} [AddCommGroup G] [DecidableEq G] +omit [DecidableEq G] in /-- A short-relation-free old/new pair is disjoint as soon as the height bound contains `1`. -/ theorem disjoint_of_mixedRelationFree {A Y : Finset G} {Q : ℕ} (hQ : 1 ≤ Q) (hfree : MixedRelationFree Q A Y) : Disjoint A Y := by @@ -62,7 +63,7 @@ private theorem unionCoefficient_of_mem (a : Fin (A ∪ Y).card → ℤ) {x : G} (hx : x ∈ A ∪ Y) : unionCoefficient A Y a x = a ((unionEquiv A Y).symm ⟨x, hx⟩) := by classical - simp only [unionCoefficient, dif_pos hx] + simp only [unionCoefficient, dite_eq_left hx] omit [AddCommGroup G] in private theorem unionCoefficient_tuple @@ -134,13 +135,13 @@ private theorem sum_stageTarget_eq_sum_old ∑ x ∈ A, unionCoefficient A Y a x • old x := by apply Finset.sum_congr rfl intro x hx - rw [if_pos hx] + rw [ite_eq_left hx] have hsumY : (∑ x ∈ Y, unionCoefficient A Y a x • (if x ∈ A then old x else 0)) = 0 := by apply Finset.sum_eq_zero intro y hy - rw [if_neg (hYA y hy), smul_zero] + rw [ite_eq_right (hYA y hy), smul_zero] rw [hsumA, hsumY, add_zero] /-- Bounded deletion makes the finite fusion target compatible with every relation up to `Q`. -/ diff --git a/LeanPool/Wallace/LocalEnumeration.lean b/LeanPool/Wallace/LocalEnumeration.lean index 78d66b87e..9522badb9 100644 --- a/LeanPool/Wallace/LocalEnumeration.lean +++ b/LeanPool/Wallace/LocalEnumeration.lean @@ -5,6 +5,7 @@ Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues -/ import LeanPool.Wallace.ConcreteClosure +import Mathlib.Data.Finsupp.Encodable /-! # Enumeration of a countable local free group @@ -27,7 +28,7 @@ def groupEnumeration (x : ContinuumFreeGroup) : theorem groupEnumeration_surjective (x : ContinuumFreeGroup) : Function.Surjective (groupEnumeration N hN M x) := by - letI : Countable (closure N hN M x) := (closure_countable N hN M x).to_subtype + let : Countable (closure N hN M x) := (closure_countable N hN M x).to_subtype exact Classical.choose_spec (exists_surjective_nat (closure N hN M x →₀ ℤ)) end diff --git a/LeanPool/Wallace/LocalFusion.lean b/LeanPool/Wallace/LocalFusion.lean index 7a63a4eee..e24848188 100644 --- a/LeanPool/Wallace/LocalFusion.lean +++ b/LeanPool/Wallace/LocalFusion.lean @@ -350,12 +350,14 @@ def nextFusionState (S.pastRetained ∪ (chosenFusionStep fresh enumeration x hfresh_card hfresh_independent l S).retained).card ≤ S.pastRetained.card + - (chosenFusionStep fresh enumeration x hfresh_card hfresh_independent l S).retained.card := + (chosenFusionStep fresh enumeration x hfresh_card hfresh_independent + l S).retained.card := Finset.card_union_le _ _ _ ≤ FusionSchedule.accumulatedSize l + FusionSchedule.blockSize l := by apply Nat.add_le_add S.pastRetained_card_le exact (Finset.card_le_card - (chosenFusionStep fresh enumeration x hfresh_card hfresh_independent l S).retained_subset).trans + (chosenFusionStep fresh enumeration x hfresh_card + hfresh_independent l S).retained_subset).trans (hfresh_card l) _ = FusionSchedule.accumulatedSize (l + 1) := (FusionSchedule.accumulatedSize_succ l).symm @@ -416,7 +418,8 @@ theorem fusionStates_pastRetained_mono : Monotone fun l ↦ /-- The fully scheduled run associated with a chosen initial character. -/ def scheduledRun (henumeration : Function.Surjective enumeration) : FusionRun G where - character := fun l ↦ (states fresh enumeration x hfresh_card hfresh_independent initial l).character + character := fun l ↦ + (states fresh enumeration x hfresh_card hfresh_independent initial l).character guardSet := fun l ↦ stageGuard enumeration x l (states fresh enumeration x hfresh_card hfresh_independent initial l) retained := fun l ↦ (step fresh enumeration x hfresh_card hfresh_independent initial l).retained @@ -433,15 +436,17 @@ def scheduledRun (henumeration : Function.Surjective enumeration) : FusionRun G change dist ((states fresh enumeration x hfresh_card hfresh_independent initial l).character g) ((step fresh enumeration x hfresh_card hfresh_independent initial l).next g) ≤ _ - exact (step fresh enumeration x hfresh_card hfresh_independent initial l).protected_closeness g hg + exact + (step fresh enumeration x hfresh_card hfresh_independent initial l).protected_closeness g hg retained_at_stage := by intro l g hg change ‖(step fresh enumeration x hfresh_card hfresh_independent initial l).next g‖ ≤ _ exact (step fresh enumeration x hfresh_card hfresh_independent initial l).retained_small g hg retained_protected := by intro l g hg k hlk - have hgNext : g ∈ - (states fresh enumeration x hfresh_card hfresh_independent initial (l + 1)).pastRetained := by + have hgNext : + g ∈ (states fresh enumeration x hfresh_card hfresh_independent + initial (l + 1)).pastRetained := by change g ∈ (states fresh enumeration x hfresh_card hfresh_independent initial l).pastRetained ∪ (step fresh enumeration x hfresh_card hfresh_independent initial l).retained diff --git a/LeanPool/Wallace/MathlibFoundations.lean b/LeanPool/Wallace/MathlibFoundations.lean index 1f3467c01..eb20c1e17 100644 --- a/LeanPool/Wallace/MathlibFoundations.lean +++ b/LeanPool/Wallace/MathlibFoundations.lean @@ -4,7 +4,14 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues -/ -import Mathlib +import Mathlib.Algebra.BigOperators.Finsupp.Basic +import Mathlib.Algebra.Module.NatInt +import Mathlib.Logic.Encodable.Pi +import Mathlib.Order.Filter.Cofinite +import Mathlib.Order.Filter.Ultrafilter.Defs +import Mathlib.Order.Interval.Finset.Nat +import Mathlib.SetTheory.Cardinal.Cofinality.Ordinal +import Mathlib.SetTheory.Cardinal.Continuum /-! # ZFC foundations used by the Wallace construction @@ -16,7 +23,7 @@ the basic facts about the initial topology generated by a family of circle-value No declaration in this file is an axiom and no proof is omitted. -/ -open Filter Set Topology +open Filter Set open scoped Cardinal universe u v w diff --git a/LeanPool/Wallace/NontrivialSequences.lean b/LeanPool/Wallace/NontrivialSequences.lean index 47dfad0c1..6be63c1fa 100644 --- a/LeanPool/Wallace/NontrivialSequences.lean +++ b/LeanPool/Wallace/NontrivialSequences.lean @@ -119,7 +119,7 @@ theorem eventually_eq_limit_of_no_injective_sequence_converges ∀ᶠ n in atTop, s n = x := by by_cases hfinite : (Set.range s).Finite · let A : Set X := Set.range s \ {x} - have hA : A.Finite := hfinite.diff + have hA : A.Finite := hfinite.sdiff have hAc : IsClosed A := hA.isClosed have hxA : x ∈ Aᶜ := by simp [A] have hnhds : Aᶜ ∈ nhds x := hAc.isOpen_compl.mem_nhds hxA diff --git a/LeanPool/Wallace/RationalFusionRun.lean b/LeanPool/Wallace/RationalFusionRun.lean index 5e7d55cfc..d9cc05c68 100644 --- a/LeanPool/Wallace/RationalFusionRun.lean +++ b/LeanPool/Wallace/RationalFusionRun.lean @@ -6,6 +6,7 @@ Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues import LeanPool.Wallace.RationalLocalSetup import LeanPool.Wallace.LocalFusion +import Mathlib.Data.Finsupp.Encodable /-! # The unconditional local fusion for the rational direct sum @@ -49,7 +50,7 @@ def localEnumeration (x : ContinuumRationalGroup) : ℕ → LocalGroup x := by theorem localEnumeration_surjective (x : ContinuumRationalGroup) : Function.Surjective (localEnumeration x) := by - letI : Countable (localCarrier x) := + let : Countable (localCarrier x) := (closure_countable blockSize blockSize_pos independenceBound x).to_subtype exact Classical.choose_spec (exists_surjective_nat (LocalGroup x)) diff --git a/LeanPool/Wallace/RationalLocalSetup.lean b/LeanPool/Wallace/RationalLocalSetup.lean index d6b418ffd..ae965c2be 100644 --- a/LeanPool/Wallace/RationalLocalSetup.lean +++ b/LeanPool/Wallace/RationalLocalSetup.lean @@ -59,7 +59,7 @@ def refinedLabel (x : ContinuumRationalGroup) : theorem refinedLabel_pairwise (x : ContinuumRationalGroup) : Pairwise fun a b : RelevantCode N hN M x ↦ Disjoint (refinedLabel N hN M x a) (refinedLabel N hN M x b) := by - letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x + let : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x exact (Classical.choose_spec (exists_disjoint_refinement_countable (fun a : RelevantCode N hN M x ↦ label a.1) @@ -68,7 +68,7 @@ theorem refinedLabel_pairwise (x : ContinuumRationalGroup) : theorem label_diff_refinedLabel_finite (x : ContinuumRationalGroup) (a : RelevantCode N hN M x) : (label a.1 \ refinedLabel N hN M x a).Finite := by - letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x + let : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x exact (Classical.choose_spec (exists_disjoint_refinement_countable (fun a : RelevantCode N hN M x ↦ label a.1) @@ -157,7 +157,7 @@ theorem closureInclusion_localDifference closureInclusion N hN M x (localDifference N hN M x a n) = prepared N hN M a.1 n - codeBasisVector a.1 := by classical - letI : DecidablePred (closure N hN M x : ContinuumIndex → Prop) := + let : DecidablePred (closure N hN M x : ContinuumIndex → Prop) := fun _ ↦ Classical.propDecidable _ rw [closureInclusion_apply] change Finsupp.embDomain diff --git a/LeanPool/Wallace/RationalTransfiniteExtension.lean b/LeanPool/Wallace/RationalTransfiniteExtension.lean index 7420e9f20..72ab0415e 100644 --- a/LeanPool/Wallace/RationalTransfiniteExtension.lean +++ b/LeanPool/Wallace/RationalTransfiniteExtension.lean @@ -6,6 +6,7 @@ Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues import LeanPool.Wallace.RationalTriangularPreprocess import Mathlib.Algebra.Category.Grp.Injective +import Mathlib.Topology.Instances.AddCircle.Real /-! # Transfinite extension for the rational direct sum @@ -164,7 +165,7 @@ theorem globalCoordinate_codeIndex_of_not_mem rw [globalCoordinate_eq] simp only [coordinateStep, hc, dite_false] let hex : ∃ d : E.Code, E.codeIndex d = E.codeIndex c := ⟨c, rfl⟩ - rw [dif_pos hex] + rw [dite_eq_left hex] have hchosen : Classical.choose hex = c := by apply E.codeIndex.injective exact Classical.choose_spec hex diff --git a/LeanPool/Wallace/RationalTriangularPreprocess.lean b/LeanPool/Wallace/RationalTriangularPreprocess.lean index 141aad293..b0f9c8dcb 100644 --- a/LeanPool/Wallace/RationalTriangularPreprocess.lean +++ b/LeanPool/Wallace/RationalTriangularPreprocess.lean @@ -5,7 +5,7 @@ Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues -/ import LeanPool.Wallace.TriangularPreprocess -import Mathlib.Data.Rat.Cardinal +import Mathlib.SetTheory.Cardinal.Rat /-! # Triangular preprocessing for the rational direct sum @@ -41,7 +41,6 @@ abbrev RationalInjectiveSequences := def RationalSupportedBelow (s : ℕ → ContinuumRationalGroup) (i : ContinuumIndex) : Prop := ∀ n j, j ∈ (s n).support → j < i -@[simp] theorem mk_continuumIndex : #ContinuumIndex = 𝔠 := TriangularPreprocess.mk_continuumIndex @@ -49,7 +48,7 @@ theorem continuumIndex_infinite : Infinite ContinuumIndex := TriangularPreprocess.continuumIndex_infinite theorem mk_continuumRationalGroup : #ContinuumRationalGroup = 𝔠 := by - letI : Infinite ContinuumIndex := continuumIndex_infinite + let : Infinite ContinuumIndex := continuumIndex_infinite change #(ContinuumIndex →₀ ℚ) = 𝔠 rw [Cardinal.mk_finsupp_of_infinite, mk_continuumIndex, Cardinal.mkRat] exact max_eq_left Cardinal.aleph0_le_continuum diff --git a/LeanPool/Wallace/Result.lean b/LeanPool/Wallace/Result.lean index 4a487fa86..3837a719e 100644 --- a/LeanPool/Wallace/Result.lean +++ b/LeanPool/Wallace/Result.lean @@ -149,7 +149,7 @@ theorem addSubmonoid_isWallace (hcompact : CountablyCompactSpace P) {a : F} (ha : a ∈ P) (hneg : -a ∉ P) : IsWallaceSemigroup P := by - letI : CountablyCompactSpace P := hcompact + let : CountablyCompactSpace P := hcompact refine ⟨inferInstance, inferInstance, inferInstance, inferInstance, ?_⟩ exact ⟨⟨a, ha⟩, not_isAddUnit_of_neg_not_mem P ha hneg⟩ diff --git a/LeanPool/Wallace/SeparationInterface.lean b/LeanPool/Wallace/SeparationInterface.lean index b7b61e7f4..9afa93d46 100644 --- a/LeanPool/Wallace/SeparationInterface.lean +++ b/LeanPool/Wallace/SeparationInterface.lean @@ -93,7 +93,7 @@ theorem initial_isTopologicalAddGroup (C : SeparationPackage I) : theorem initial_t2Space (C : SeparationPackage I) : @T2Space (I →₀ ℤ) C.initialTopology := by - letI : TopologicalSpace (I →₀ ℤ) := C.initialTopology + let : TopologicalSpace (I →₀ ℤ) := C.initialTopology exact C.evaluation_injective.isEmbedding_induced.t2Space /-- The prepared subsequence converges to its prescribed basis point in the initial topology. -/ @@ -103,7 +103,7 @@ theorem prepared_tendsto_basis (C : SeparationPackage I) (c : C.Code) : (C.ultrafilter c) (@nhds (I →₀ ℤ) C.initialTopology (Finsupp.single (C.codeIndex c) (1 : ℤ))) := by - letI : TopologicalSpace (I →₀ ℤ) := C.initialTopology + let : TopologicalSpace (I →₀ ℤ) := C.initialTopology have hinducing : IsInducing C.evaluation := ⟨rfl⟩ refine hinducing.tendsto_nhds_iff.mpr ?_ refine tendsto_pi_nhds.2 fun x ↦ ?_ @@ -112,7 +112,7 @@ theorem prepared_tendsto_basis (C : SeparationPackage I) (c : C.Code) : /-- The package supplies the exact free-ultrafilter limit property used by the cone argument. -/ theorem positiveCone_hasWallaceLimitProperty (C : SeparationPackage I) : @HasWallaceLimitProperty (I →₀ ℤ) C.initialTopology _ (positiveCone I) := by - letI : TopologicalSpace (I →₀ ℤ) := C.initialTopology + let : TopologicalSpace (I →₀ ℤ) := C.initialTopology intro s hs _hscone let encoded : InjectiveSequence' (I →₀ ℤ) := ⟨s, hs⟩ let c : C.Code := C.codeEquiv.symm encoded diff --git a/LeanPool/Wallace/TransfiniteExtension.lean b/LeanPool/Wallace/TransfiniteExtension.lean index f5d6645a9..f480520d7 100644 --- a/LeanPool/Wallace/TransfiniteExtension.lean +++ b/LeanPool/Wallace/TransfiniteExtension.lean @@ -5,6 +5,7 @@ Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues -/ import LeanPool.Wallace.TriangularPreprocess +import Mathlib.Topology.Instances.AddCircle.Real /-! # Transfinite extension of a local circle-valued character @@ -133,7 +134,7 @@ theorem globalBasisValue_codeIndex_of_not_mem rw [globalBasisValue_eq] simp only [basisStep, hc, dite_false] let hex : ∃ d : E.Code, E.codeIndex d = E.codeIndex c := ⟨c, rfl⟩ - rw [dif_pos hex] + rw [dite_eq_left hex] have hchosen : Classical.choose hex = c := by apply E.codeIndex.injective exact Classical.choose_spec hex diff --git a/LeanPool/Wallace/TriangularPreprocess.lean b/LeanPool/Wallace/TriangularPreprocess.lean index d7f648515..70e9bef6e 100644 --- a/LeanPool/Wallace/TriangularPreprocess.lean +++ b/LeanPool/Wallace/TriangularPreprocess.lean @@ -37,7 +37,6 @@ abbrev ContinuumFreeGroup := ContinuumIndex →₀ ℤ abbrev InjectiveSequences := {s : ℕ → ContinuumFreeGroup // Function.Injective s} -@[simp] theorem mk_continuumIndex : #ContinuumIndex = 𝔠 := by exact Cardinal.mk_ord_toType 𝔠 @@ -46,7 +45,7 @@ theorem continuumIndex_infinite : Infinite ContinuumIndex := by simpa only [mk_continuumIndex] using Cardinal.aleph0_le_continuum theorem mk_continuumFreeGroup : #ContinuumFreeGroup = 𝔠 := by - letI : Infinite ContinuumIndex := continuumIndex_infinite + let : Infinite ContinuumIndex := continuumIndex_infinite change #(ContinuumIndex →₀ ℤ) = 𝔠 rw [Cardinal.mk_finsupp_of_infinite, mk_continuumIndex, Cardinal.mk_int] exact max_eq_left Cardinal.aleph0_le_continuum @@ -340,13 +339,13 @@ theorem blockSelectionStates_boundedIndependent by_cases hl : l = block n · subst l simp only [blockSelectionStep] - simp + simp only [Function.update_self] exact boundedIndependent_insert_of_not_forbidden ih (nextBlockIndex_not_mem_values u hu M block n (blockSelectionStates u hu M block n)) (nextBlockIndex_not_forbidden u hu M block n (blockSelectionStates u hu M block n)) - · simp [blockSelectionStep, hl] + · simp only [blockSelectionStep, ne_eq, hl, not_false_eq_true, Function.update_of_ne] exact ih theorem blockSelectionStates_values_mono_succ @@ -527,7 +526,7 @@ theorem exists_boundedIndependent_subsequence_for_sizes refine ⟨φ, hφ, fun l => ⟨blockPositions_card N hN l, ?_⟩⟩ have hfinset : (hfinite l).toFinset = blockPositions N hN l := by ext n - simp only [Set.Finite.mem_toFinset, Set.mem_setOf_eq, mem_blockPositions_iff] + simp only [Set.Finite.mem_toFinset, Set.mem_ofPred_eq, mem_blockPositions_iff] simpa only [hfinset] using hind l /-! ## The paper's shifted coded sequences -/ diff --git a/LeanPool/Wallace/TychonoffWallace.lean b/LeanPool/Wallace/TychonoffWallace.lean index 958f70032..71f90996e 100644 --- a/LeanPool/Wallace/TychonoffWallace.lean +++ b/LeanPool/Wallace/TychonoffWallace.lean @@ -29,7 +29,7 @@ variable {G : Type*} [AddCommGroup G] a product of circles. -/ theorem initial_t35Space (C : FullCharacterPackage G) : @T35Space G C.initialTopology := by - letI : TopologicalSpace G := C.initialTopology + let : TopologicalSpace G := C.initialTopology exact C.evaluation_injective.isEmbedding_induced.t35Space end FullCharacterPackage @@ -58,15 +58,15 @@ theorem continuumPositiveCone_isCommutativeTychonoffWallace : @IsWallaceSemigroup (positiveCone ContinuumIndex) topology _ := by let C : SeparationPackage ContinuumIndex := continuumFullSeparationPackage let ambientTopology : TopologicalSpace ContinuumFreeGroup := C.initialTopology - letI : TopologicalSpace ContinuumFreeGroup := ambientTopology - letI : IsTopologicalAddGroup ContinuumFreeGroup := C.initial_isTopologicalAddGroup - letI : T2Space ContinuumFreeGroup := C.initial_t2Space - letI : T35Space ContinuumFreeGroup := C.initial_t35Space - letI : Infinite ContinuumIndex := continuumIndex_infinite + let : TopologicalSpace ContinuumFreeGroup := ambientTopology + let : IsTopologicalAddGroup ContinuumFreeGroup := C.initial_isTopologicalAddGroup + let : T2Space ContinuumFreeGroup := C.initial_t2Space + let : T35Space ContinuumFreeGroup := C.initial_t35Space + let : Infinite ContinuumIndex := continuumIndex_infinite let coneTopology : TopologicalSpace (positiveCone ContinuumIndex) := TopologicalSpace.induced (fun z : positiveCone ContinuumIndex ↦ (z : ContinuumFreeGroup)) ambientTopology - letI : TopologicalSpace (positiveCone ContinuumIndex) := coneTopology + let : TopologicalSpace (positiveCone ContinuumIndex) := coneTopology let i : ContinuumIndex := Classical.choice inferInstance have hwallace : IsWallaceSemigroup (positiveCone ContinuumIndex) := positiveCone_isWallace_of_limitProperty ContinuumIndex i diff --git a/LeanPool/Wallace/UniformKronecker.lean b/LeanPool/Wallace/UniformKronecker.lean index d28467b98..024e6f160 100644 --- a/LeanPool/Wallace/UniformKronecker.lean +++ b/LeanPool/Wallace/UniformKronecker.lean @@ -347,7 +347,7 @@ private theorem exists_finite_frequency_approximation_of_compact _ = dist (c.sum fun a z ↦ z • UnitAddTorus.mFourier a) (complexifyDistanceFunction g.1) := by rw [dist_eq_norm] _ < δ := by simpa only [dist_comm] using hgP - letI : Fintype T := hTfin.fintype + let : Fintype T := hTfin.fintype choose coeff hcoeff using fun g : T ↦ hpoly ⟨g.1, hTA g.2⟩ let S : Finset (Fin m → ℤ) := Finset.univ.biUnion fun g : T ↦ (coeff g).support refine ⟨S, fun f hfA ↦ ?_⟩ @@ -437,7 +437,7 @@ private noncomputable def annihilatorHaarMeasure {m : ℕ} private instance annihilatorHaar_isProbability {m : ℕ} (R : AddSubgroup (Fin m → ℤ)) : MeasureTheory.IsProbabilityMeasure (annihilatorHaarMeasure R) := by - letI : CompactSpace (integerAnnihilator R) := + let : CompactSpace (integerAnnihilator R) := isCompact_iff_compactSpace.mp (isClosed_integerAnnihilator R).isCompact constructor change MeasureTheory.Measure.addHaarMeasure (⊤ : PositiveCompacts (integerAnnihilator R)) @@ -453,7 +453,7 @@ private theorem integral_mFourier_translate {m : ℕ} UnitAddTorus.mFourier a x * ∫ h : integerAnnihilator R, UnitAddTorus.mFourier a h.1 ∂(annihilatorHaarMeasure R) := by - letI : CompactSpace (integerAnnihilator R) := + let : CompactSpace (integerAnnihilator R) := isCompact_iff_compactSpace.mp (isClosed_integerAnnihilator R).isCompact rw [← MeasureTheory.integral_const_mul] apply MeasureTheory.integral_congr_ae @@ -467,7 +467,7 @@ private theorem integral_mFourier_eq_zero_of_not_mem {m : ℕ} (R : AddSubgroup (Fin m → ℤ)) {a : Fin m → ℤ} (ha : a ∉ R) : (∫ h : integerAnnihilator R, UnitAddTorus.mFourier a h.1 ∂(annihilatorHaarMeasure R)) = 0 := by - letI : CompactSpace (integerAnnihilator R) := + let : CompactSpace (integerAnnihilator R) := isCompact_iff_compactSpace.mp (isClosed_integerAnnihilator R).isCompact obtain ⟨x, hxR, hxa⟩ := exists_mem_integerAnnihilator_not_annihilate R ha let xR : integerAnnihilator R := ⟨x, hxR⟩ @@ -476,7 +476,7 @@ private theorem integral_mFourier_eq_zero_of_not_mem {m : ℕ} let K : PositiveCompacts (integerAnnihilator R) := ⊤ have hmeasure : annihilatorHaarMeasure R = MeasureTheory.Measure.addHaarMeasure K := rfl - letI : (annihilatorHaarMeasure R).IsAddLeftInvariant := by + let : (annihilatorHaarMeasure R).IsAddLeftInvariant := by rw [hmeasure] infer_instance have hinv : (∫ h : integerAnnihilator R, @@ -503,7 +503,7 @@ private theorem integral_mFourier_eq_one_of_mem {m : ℕ} (R : AddSubgroup (Fin m → ℤ)) {a : Fin m → ℤ} (ha : a ∈ R) : (∫ h : integerAnnihilator R, UnitAddTorus.mFourier a h.1 ∂(annihilatorHaarMeasure R)) = 1 := by - letI : CompactSpace (integerAnnihilator R) := + let : CompactSpace (integerAnnihilator R) := isCompact_iff_compactSpace.mp (isClosed_integerAnnihilator R).isCompact have hone : ∀ h : integerAnnihilator R, UnitAddTorus.mFourier a h.1 = 1 := by intro h @@ -528,7 +528,7 @@ private theorem integral_fourierPolynomial_translate {m : ℕ} ∂(annihilatorHaarMeasure R)) = c.sum fun a z ↦ filteredFourierTerm R a z x := by classical - letI : CompactSpace (integerAnnihilator R) := + let : CompactSpace (integerAnnihilator R) := isCompact_iff_compactSpace.mp (isClosed_integerAnnihilator R).isCompact rw [Finsupp.sum_of_support_subset c (s := c.support) Subset.rfl _ (by intro a _ha @@ -543,9 +543,9 @@ private theorem integral_fourierPolynomial_translate {m : ℕ} simp_rw [ContinuousMap.smul_apply, smul_eq_mul] rw [MeasureTheory.integral_const_mul, integral_mFourier_translate R a x] by_cases haR : a ∈ R - · rw [filteredFourierTerm, if_pos haR, + · rw [filteredFourierTerm, ite_eq_left haR, integral_mFourier_eq_one_of_mem R haR, mul_one] - · rw [filteredFourierTerm, if_neg haR, + · rw [filteredFourierTerm, ite_eq_right haR, integral_mFourier_eq_zero_of_not_mem R haR, mul_zero, mul_zero] · intro a _ha apply MeasureTheory.Integrable.const_mul @@ -567,7 +567,7 @@ theorem infDist_integerAnnihilator_lt_of_finite_relations {m : ℕ} {δ : ℝ} ( (ht : ∀ a ∈ S, a ∈ R → torusRelationMap t a = 0) : Metric.infDist t (integerAnnihilator R) ≤ 4 * δ := by classical - letI : CompactSpace (integerAnnihilator R) := + let : CompactSpace (integerAnnihilator R) := isCompact_iff_compactSpace.mp (isClosed_integerAnnihilator R).isCompact obtain ⟨c, hcS, hc⟩ := hS R let P : C(UnitAddTorus (Fin m), ℂ) := c.sum fun a z ↦ z • UnitAddTorus.mFourier a @@ -582,11 +582,11 @@ theorem infDist_integerAnnihilator_lt_of_finite_relations {m : ℕ} {δ : ℝ} ( intro a ha have haS : a ∈ S := hcS ha by_cases haR : a ∈ R - · simp only [filteredFourierTerm, if_pos haR] + · simp only [filteredFourierTerm, ite_eq_left haR] have hat : torusRelationMap t a = 0 := ht a haS haR rw [mFourier_eq_toCircle_relation, hat, AddCircle.toCircle_zero] simp [UnitAddTorus.mFourier] - · simp only [filteredFourierTerm, if_neg haR] + · simp only [filteredFourierTerm, ite_eq_right haR] have hdistInvariant : ∀ h : integerAnnihilator R, annihilatorDistance R (t + h.1) = annihilatorDistance R t := by intro h From 4ea108329e53a71bfe9a5a272522cd254f1799e6 Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 4 Sep 2026 14:23:53 +0000 Subject: [PATCH 4/7] Polish and register Wallace formalization --- LeanPool.lean | 40 +++++++++++++++ LeanPool/Wallace.lean | 11 ++++ LeanPool/Wallace/BlockFilters.lean | 1 + LeanPool/Wallace/ConcreteFusionRun.lean | 9 ++++ LeanPool/Wallace/FiniteCombinatorics.lean | 13 ++--- LeanPool/Wallace/FullTopology.lean | 8 +++ LeanPool/Wallace/FusionSchedule.lean | 3 +- LeanPool/Wallace/LocalFusion.lean | 27 +++++++--- LeanPool/Wallace/RationalAssembly.lean | 2 + LeanPool/Wallace/RationalData.lean | 1 + LeanPool/Wallace/RationalFusionRun.lean | 14 +++++ LeanPool/Wallace/RationalLocalSetup.lean | 7 +++ .../Wallace/RationalTransfiniteExtension.lean | 6 +++ .../Wallace/RationalTriangularPreprocess.lean | 2 + LeanPool/Wallace/SeparationInterface.lean | 6 +++ LeanPool/Wallace/TorsionFreeCoordinate.lean | 2 + LeanPool/Wallace/TriangularPreprocess.lean | 28 +++++----- LeanPool/projects.yml | 51 +++++++++++++++++++ 18 files changed, 202 insertions(+), 29 deletions(-) diff --git a/LeanPool.lean b/LeanPool.lean index 604e4f27f..3779df561 100644 --- a/LeanPool.lean +++ b/LeanPool.lean @@ -4065,6 +4065,46 @@ import LeanPool.Vlasov.OT.Coupling import LeanPool.Vlasov.OT.Wasserstein import LeanPool.Vlasov.OT.WeakToLagrangian import LeanPool.Vlasov.OT.WellPosedness +import LeanPool.Wallace +import LeanPool.Wallace.BlockFilters +import LeanPool.Wallace.BlockLimit +import LeanPool.Wallace.BoundedIndependentMap +import LeanPool.Wallace.ConcreteClosure +import LeanPool.Wallace.ConcreteData +import LeanPool.Wallace.ConcreteFusionRun +import LeanPool.Wallace.ConcreteLocalSetup +import LeanPool.Wallace.CountableClosure +import LeanPool.Wallace.CountableDisjointization +import LeanPool.Wallace.FiniteCombinatorics +import LeanPool.Wallace.FullTopology +import LeanPool.Wallace.FullTopologyMain +import LeanPool.Wallace.FusionLimit +import LeanPool.Wallace.FusionSchedule +import LeanPool.Wallace.FusionStage +import LeanPool.Wallace.GeneralMain +import LeanPool.Wallace.GlobalAssembly +import LeanPool.Wallace.InitialCharacter +import LeanPool.Wallace.LocalEnumeration +import LeanPool.Wallace.LocalFusion +import LeanPool.Wallace.Main +import LeanPool.Wallace.MathlibFoundations +import LeanPool.Wallace.NontrivialSequences +import LeanPool.Wallace.PackageTransport +import LeanPool.Wallace.RationalAssembly +import LeanPool.Wallace.RationalClosure +import LeanPool.Wallace.RationalData +import LeanPool.Wallace.RationalFusionRun +import LeanPool.Wallace.RationalLocalSetup +import LeanPool.Wallace.RationalTransfiniteExtension +import LeanPool.Wallace.RationalTriangularPreprocess +import LeanPool.Wallace.RealMain +import LeanPool.Wallace.Result +import LeanPool.Wallace.SeparationInterface +import LeanPool.Wallace.TorsionFreeCoordinate +import LeanPool.Wallace.TransfiniteExtension +import LeanPool.Wallace.TriangularPreprocess +import LeanPool.Wallace.TychonoffWallace +import LeanPool.Wallace.UniformKronecker import LeanPool.WhiteheadTheorem import LeanPool.WhiteheadTheorem.Auxiliary import LeanPool.WhiteheadTheorem.Basic diff --git a/LeanPool/Wallace.lean b/LeanPool/Wallace.lean index 912db42f9..0a99be1da 100644 --- a/LeanPool/Wallace.lean +++ b/LeanPool/Wallace.lean @@ -8,6 +8,17 @@ import LeanPool.Wallace.GeneralMain import LeanPool.Wallace.RealMain import LeanPool.Wallace.TychonoffWallace +/-! +# The Wallace problem in ZFC + +Source: arxiv:2608.17317, doi:10.48550/arXiv.2608.17317, url:https://github.com/vo-rodrigues/wallace-problem-zfc-paper +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +Status: verified +Main declarations: `Wallace.commutativeTychonoffWallaceCounterexampleExists` +Tags: wallace-problem, topological-groups, set-theoretic-topology +MSC: 22A05, 54D30, 20K20 +-/ + /-! # Countably compact groups and the Wallace counterexample diff --git a/LeanPool/Wallace/BlockFilters.lean b/LeanPool/Wallace/BlockFilters.lean index d1f12b786..4b7d70927 100644 --- a/LeanPool/Wallace/BlockFilters.lean +++ b/LeanPool/Wallace/BlockFilters.lean @@ -24,6 +24,7 @@ noncomputable section /-- Finite blocks which move to infinity. -/ structure BlockSystem where + /-- The finite block carrying a given natural-number label. -/ block : ℕ → Finset ℕ block_nonempty : ∀ l, (block l).Nonempty eventually_disjoint_finite : diff --git a/LeanPool/Wallace/ConcreteFusionRun.lean b/LeanPool/Wallace/ConcreteFusionRun.lean index e13aa01c4..ed90ce717 100644 --- a/LeanPool/Wallace/ConcreteFusionRun.lean +++ b/LeanPool/Wallace/ConcreteFusionRun.lean @@ -31,24 +31,31 @@ open LocalFusion /-! ## Specialization of the numerical schedule -/ +/-- The finite-block size schedule used by the concrete integer construction. -/ abbrev blockSize : ℕ → ℕ := FusionSchedule.blockSize theorem blockSize_pos (l : ℕ) : 0 < blockSize l := FusionSchedule.blockSize_pos l +/-- The bounded-independence threshold at each fusion stage. -/ abbrev independenceBound : ℕ → ℕ := FusionSchedule.stageIndependenceBound +/-- The countable coordinate closure generated by `x`. -/ abbrev localCarrier (x : ContinuumFreeGroup) : Set ContinuumIndex := closure blockSize blockSize_pos independenceBound x +/-- The free Abelian group supported on the local coordinate closure of `x`. -/ abbrev LocalGroup (x : ContinuumFreeGroup) := localCarrier x →₀ ℤ +/-- The bounded-independent block presented to each local fusion stage. -/ abbrev fresh (x : ContinuumFreeGroup) : ℕ → Finset (LocalGroup x) := localActiveBlock blockSize blockSize_pos independenceBound x +/-- A fixed enumeration of the countable local group. -/ abbrev enumeration (x : ContinuumFreeGroup) : ℕ → LocalGroup x := groupEnumeration blockSize blockSize_pos independenceBound x +/-- The restriction of `x` to its local coordinate closure. -/ def distinguished (x : ContinuumFreeGroup) : LocalGroup x := by classical exact Finsupp.subtypeDomain (localCarrier x) x @@ -73,6 +80,7 @@ def scheduledCertificate (x : {x : ContinuumFreeGroup // x ≠ 0}) : (localActiveBlock_boundedIndependent blockSize blockSize_pos independenceBound x.1) (groupEnumeration_surjective blockSize blockSize_pos independenceBound x.1) +/-- The certified fusion run attached to a nonzero vector. -/ abbrev run (x : {x : ContinuumFreeGroup // x ≠ 0}) : FusionRun (LocalGroup x.1) := (scheduledCertificate x).run @@ -161,6 +169,7 @@ theorem retainedPositions_mem_ultrafilter /-! ## Concrete block certificates and the local output -/ +/-- The retained-block certificate associated with one relevant sequence code. -/ def codeBlocks (x : {x : ContinuumFreeGroup // x ≠ 0}) (a : RelevantCode blockSize blockSize_pos independenceBound x.1) : ConcreteCodeBlocks blockSize blockSize_pos independenceBound x.1 (run x) a where diff --git a/LeanPool/Wallace/FiniteCombinatorics.lean b/LeanPool/Wallace/FiniteCombinatorics.lean index 35c124e17..b7a995144 100644 --- a/LeanPool/Wallace/FiniteCombinatorics.lean +++ b/LeanPool/Wallace/FiniteCombinatorics.lean @@ -94,12 +94,12 @@ omit [AddCommGroup G] in rw [coefficientPatterns, Fintype.mem_piFinset] simp only [mem_boundedIntFinset_iff] -noncomputable def equationSolution (B : Finset G) (q : ℤ) (c : B → ℤ) : G := +private noncomputable def equationSolution (B : Finset G) (q : ℤ) (c : B → ℤ) : G := by classical exact if h : ∃ x : G, q • x + ∑ b, c b • (b : G) = 0 then Classical.choose h else 0 -theorem equationSolution_spec {B : Finset G} {q : ℤ} {c : B → ℤ} +private theorem equationSolution_spec {B : Finset G} {q : ℤ} {c : B → ℤ} (h : ∃ x : G, q • x + ∑ b, c b • (b : G) = 0) : q • equationSolution B q c + ∑ b, c b • (b : G) = 0 := by classical @@ -209,21 +209,21 @@ theorem exists_integer_dependence (s : ℕ) (b : Fin (s + 1) → Fin s → ℤ) abbrev BoundedInt (Q : ℕ) := ↑(boundedIntFinset Q) /-- All bounded vector families of every dimension at most `r`. -/ -structure BoundedVectorFamily (r Q : ℕ) where +private structure BoundedVectorFamily (r Q : ℕ) where size : Fin (r + 1) vec : Fin (size + 1) → Fin size → BoundedInt Q deriving Fintype -noncomputable def chosenIntegerDependence {r Q : ℕ} (B : BoundedVectorFamily r Q) : +private noncomputable def chosenIntegerDependence {r Q : ℕ} (B : BoundedVectorFamily r Q) : Fin (B.size + 1) → ℤ := Classical.choose <| exists_integer_dependence B.size fun i j ↦ B.vec i j -theorem chosenIntegerDependence_spec {r Q : ℕ} (B : BoundedVectorFamily r Q) : +private theorem chosenIntegerDependence_spec {r Q : ℕ} (B : BoundedVectorFamily r Q) : (∃ i, chosenIntegerDependence B i ≠ 0) ∧ ∀ j, ∑ i, chosenIntegerDependence B i * (B.vec i j : ℤ) = 0 := Classical.choose_spec <| exists_integer_dependence B.size fun i j ↦ B.vec i j -noncomputable def familyDependenceBound {r Q : ℕ} (B : BoundedVectorFamily r Q) : ℕ := +private noncomputable def familyDependenceBound {r Q : ℕ} (B : BoundedVectorFamily r Q) : ℕ := Finset.univ.sup fun i ↦ Int.natAbs (chosenIntegerDependence B i) /-- A uniform bound for an integer dependence among any `s+1` vectors in `ℤ^s`, for `s ≤ r`, @@ -267,6 +267,7 @@ def HasMixedRelation (Q : ℕ) (A Y : Finset G) : Prop := (∃ y ∈ Y, c y ≠ 0) ∧ (∑ a ∈ A, b a • a) + ∑ y ∈ Y, c y • y = 0 +/-- No nontrivial relation of coefficient height at most `Q` uses both `A` and `Y`. -/ def MixedRelationFree (Q : ℕ) (A Y : Finset G) : Prop := ¬ HasMixedRelation Q A Y diff --git a/LeanPool/Wallace/FullTopology.lean b/LeanPool/Wallace/FullTopology.lean index eb1e63ad5..6942a897f 100644 --- a/LeanPool/Wallace/FullTopology.lean +++ b/LeanPool/Wallace/FullTopology.lean @@ -60,15 +60,22 @@ theorem countablyCompact_of_nonzero_ultrafilter_limits /-- The exact character data from which all conclusions of the group theorem follow. This interface applies without change to free Abelian groups and rational vector groups. -/ structure FullCharacterPackage (G : Type u) [AddCommGroup G] where + /-- Codes for injective sequences in `G`. -/ Code : Type v + /-- The identification of codes with injective sequences. -/ codeEquiv : Code ≃ InjectiveSequence' G + /-- The selected subsequence of the sequence represented by each code. -/ subsequence : Code → ℕ → ℕ subsequence_strictMono : ∀ c, StrictMono (subsequence c) + /-- The free ultrafilter along which the selected subsequence converges. -/ ultrafilter : Code → Ultrafilter ℕ ultrafilter_free : ∀ c, (ultrafilter c : Filter ℕ) ≤ cofinite + /-- The prescribed nonzero limit of the selected subsequence. -/ limitPoint : Code → G limitPoint_ne_zero : ∀ c, limitPoint c ≠ 0 + /-- Indices for the separating family of circle-valued characters. -/ CharacterIndex : Type v + /-- The separating family of circle-valued additive characters. -/ character : CharacterIndex → G →+ UnitAddCircle character_detects : ∀ x : G, x ≠ 0 → ∃ j, character j x ≠ 0 character_limit : @@ -237,6 +244,7 @@ theorem initial_onlyEventuallyConstantConvergentSequences rw [← C.full_initialTopology_eq] exact C.toFullCharacterPackage.initial_onlyEventuallyConstantConvergentSequences +/-- The uniform structure induced by all characters in the separation package. -/ @[reducible] def initialUniformSpace (C : SeparationPackage I) : UniformSpace (I →₀ ℤ) := C.toFullCharacterPackage.initialUniformSpace diff --git a/LeanPool/Wallace/FusionSchedule.lean b/LeanPool/Wallace/FusionSchedule.lean index b97fb8aee..564a2ba1a 100644 --- a/LeanPool/Wallace/FusionSchedule.lean +++ b/LeanPool/Wallace/FusionSchedule.lean @@ -195,8 +195,7 @@ theorem card_union_le_tupleLengthBound {G : Type*} [DecidableEq G] _ = tupleLengthBound l := rfl /-- The bounded-deletion lemma specialized to the numerical schedule. -/ -theorem exists_stage_deletion {G : Type*} [AddCommGroup G] [IsAddTorsionFree G] - [DecidableEq G] +theorem exists_stage_deletion {G : Type*} [AddCommGroup G] [DecidableEq G] {l : ℕ} (A X : Finset G) (hA : A.card ≤ protectedBound l) (hX : BoundedIndependent (stageIndependenceBound l) X) : ∃ Y : Finset G, Y ⊆ X ∧ (X \ Y).card ≤ A.card ∧ diff --git a/LeanPool/Wallace/LocalFusion.lean b/LeanPool/Wallace/LocalFusion.lean index e24848188..a302827e6 100644 --- a/LeanPool/Wallace/LocalFusion.lean +++ b/LeanPool/Wallace/LocalFusion.lean @@ -45,7 +45,7 @@ open FiniteCombinatorics /-- A scheduled bounded-deletion and finite-fusion stage. -/ theorem exists_character_after_deletion - {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] + {G : Type} [AddCommGroup G] [DecidableEq G] (l : ℕ) (A X : Finset G) (hA : A.card ≤ FusionSchedule.protectedBound l) (hXcard : X.card ≤ FusionSchedule.blockSize l) @@ -193,10 +193,15 @@ theorem limitCharacter_ne_zero_of_initial_half (R : FusionRun G) {x : G} /-- Abstract block data associated with one relevant code in the local closure. -/ structure CodeBlocks (R : FusionRun G) where + /-- The ultrafilter used for this code. -/ p : Ultrafilter ℕ + /-- The finite block at each stage label. -/ block : ℕ → Finset ℕ + /-- The stages assigned to this code. -/ labels : Set ℕ + /-- The positions deleted from each block. -/ deletions : ℕ → Finset ℕ + /-- The local group difference represented by each position. -/ difference : ℕ → G retained_mem : (⋃ l ∈ labels, ↑(block l \ deletions l)) ∈ p retained_in_stage : ∀ l n, l ∈ labels → n ∈ block l \ deletions l → @@ -262,7 +267,9 @@ end FusionRun /-- The finite state before stage `l`: its character and the union of every set retained at earlier stages. The cardinality invariant is the exact invariant used by `protectedBound`. -/ structure FusionState (G : Type) [AddCommGroup G] (l : ℕ) where + /-- The character constructed before stage `l`. -/ character : G →+ UnitAddCircle + /-- The union of all finite sets retained before stage `l`. -/ pastRetained : Finset G pastRetained_card_le : pastRetained.card ≤ FusionSchedule.accumulatedSize l @@ -295,7 +302,9 @@ theorem stageGuard_card_le {G : Type} [AddCommGroup G] [DecidableEq G] structure FusionStep {G : Type} [AddCommGroup G] [DecidableEq G] (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) (l : ℕ) (S : FusionState G l) where + /-- The subset of the fresh block retained at this stage. -/ retained : Finset G + /-- The character produced by this stage. -/ next : G →+ UnitAddCircle retained_subset : retained ⊆ fresh l deleted_card_le : (fresh l \ retained).card ≤ (stageGuard enumeration x l S).card @@ -305,7 +314,7 @@ structure FusionStep {G : Type} [AddCommGroup G] [DecidableEq G] /-- The finite deletion/fusion theorem supplies the next state at every stage. -/ theorem fusionStep_nonempty - {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] + {G : Type} [AddCommGroup G] [DecidableEq G] (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) (hfresh_card : ∀ l, (fresh l).card ≤ FusionSchedule.blockSize l) (hfresh_independent : ∀ l, @@ -324,7 +333,7 @@ theorem fusionStep_nonempty /-- A stage choice, fixed once and reused by both the state recursion and its certificate. -/ def chosenFusionStep - {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] + {G : Type} [AddCommGroup G] [DecidableEq G] (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) (hfresh_card : ∀ l, (fresh l).card ≤ FusionSchedule.blockSize l) (hfresh_independent : ∀ l, @@ -335,7 +344,7 @@ def chosenFusionStep /-- Update the state using the single chosen stage certificate. -/ def nextFusionState - {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] + {G : Type} [AddCommGroup G] [DecidableEq G] (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) (hfresh_card : ∀ l, (fresh l).card ≤ FusionSchedule.blockSize l) (hfresh_independent : ∀ l, @@ -364,7 +373,7 @@ def nextFusionState /-- The dependent natural-number recursion starting from `initial`. -/ def fusionStates - {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] + {G : Type} [AddCommGroup G] [DecidableEq G] (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) (hfresh_card : ∀ l, (fresh l).card ≤ FusionSchedule.blockSize l) (hfresh_independent : ∀ l, @@ -375,7 +384,7 @@ def fusionStates (fusionStates fresh enumeration x hfresh_card hfresh_independent initial l) @[simp] theorem fusionStates_zero - {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] + {G : Type} [AddCommGroup G] [DecidableEq G] (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) (hfresh_card : ∀ l, (fresh l).card ≤ FusionSchedule.blockSize l) (hfresh_independent : ∀ l, @@ -387,7 +396,7 @@ def fusionStates /- The rest of the construction uses shorter local names. -/ section ScheduledConstruction -variable {G : Type} [AddCommGroup G] [IsAddTorsionFree G] [DecidableEq G] +variable {G : Type} [AddCommGroup G] [DecidableEq G] variable (fresh : ℕ → Finset G) (enumeration : ℕ → G) (x : G) variable (hfresh_card : ∀ l, (fresh l).card ≤ FusionSchedule.blockSize l) variable (hfresh_independent : ∀ l, @@ -459,6 +468,7 @@ def scheduledRun (henumeration : Function.Surjective enumeration) : FusionRun G /-- Public certificate exported by the scheduling recursion. -/ structure ScheduledRunCertificate where + /-- The certified infinite fusion run. -/ run : FusionRun G initial_half : run.character 0 x = ((1 / 2 : ℝ) : UnitAddCircle) distinguished_protected : ∀ l, x ∈ run.guardSet l @@ -527,6 +537,7 @@ structure ConcreteCodeBlocks (x : ContinuumFreeGroup) (R : FusionRun (closure N hN M x →₀ ℤ)) (a : RelevantCode N hN M x) where + /-- The underlying abstract retained-block data. -/ blocks : R.CodeBlocks p_eq : blocks.p = ultrafilter N hN a.1 block_eq : ∀ l, blocks.block l = blockPositions N hN l @@ -584,10 +595,12 @@ relevant code; all limiting arguments are discharged above. -/ structure LocalRunCertificate (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) (x : {x : ContinuumFreeGroup // x ≠ 0}) where + /-- The fusion run on the countable local group generated by `x`. -/ run : FusionRun (closure N hN M x.1 →₀ ℤ) self_ne_zero : run.limitCharacter (Finsupp.subtypeDomain (closure N hN M x.1) x.1) ≠ 0 + /-- A retained-block certificate for every locally relevant code. -/ codeBlocks : ∀ a : RelevantCode N hN M x.1, ConcreteCodeBlocks N hN M x.1 run a diff --git a/LeanPool/Wallace/RationalAssembly.lean b/LeanPool/Wallace/RationalAssembly.lean index 5ccd23463..3f87b6ea3 100644 --- a/LeanPool/Wallace/RationalAssembly.lean +++ b/LeanPool/Wallace/RationalAssembly.lean @@ -28,8 +28,10 @@ open RationalClosure open RationalFusionRun open RationalTransfiniteExtension +/-- The block-size schedule used by the assembled rational construction. -/ abbrev N : ℕ → ℕ := RationalFusionRun.blockSize theorem hN (l : ℕ) : 0 < N l := RationalFusionRun.blockSize_pos l +/-- The bounded-independence schedule used by the assembled rational construction. -/ abbrev M : ℕ → ℕ := RationalFusionRun.independenceBound /-- The local limiting character supplied by the concrete fusion. -/ diff --git a/LeanPool/Wallace/RationalData.lean b/LeanPool/Wallace/RationalData.lean index 467c9af29..67b94c1f7 100644 --- a/LeanPool/Wallace/RationalData.lean +++ b/LeanPool/Wallace/RationalData.lean @@ -79,6 +79,7 @@ theorem preparedDifference_injective (a : ContinuumIndex) : apply prepared_injective N hN M a exact sub_left_injective hmn +/-- The concrete block system used by the rational construction. -/ abbrev blocks : BlockSystem := BlockSystem.ofBlockPositions N hN /-- A free ultrafilter refining the block-density filter for code `a`. -/ diff --git a/LeanPool/Wallace/RationalFusionRun.lean b/LeanPool/Wallace/RationalFusionRun.lean index d9cc05c68..e29526291 100644 --- a/LeanPool/Wallace/RationalFusionRun.lean +++ b/LeanPool/Wallace/RationalFusionRun.lean @@ -30,15 +30,20 @@ open RationalLocalSetup open FiniteCombinatorics open LocalFusion +/-- The finite-block size schedule used by the rational construction. -/ abbrev blockSize : ℕ → ℕ := FusionSchedule.blockSize theorem blockSize_pos (l : ℕ) : 0 < blockSize l := FusionSchedule.blockSize_pos l +/-- The bounded-independence threshold at each fusion stage. -/ abbrev independenceBound : ℕ → ℕ := FusionSchedule.stageIndependenceBound +/-- The countable coordinate closure generated by `x`. -/ abbrev localCarrier (x : ContinuumRationalGroup) : Set ContinuumIndex := closure blockSize blockSize_pos independenceBound x +/-- The rational direct sum supported on the local coordinate closure of `x`. -/ abbrev LocalGroup (x : ContinuumRationalGroup) := localCarrier x →₀ ℚ +/-- The bounded-independent block presented to each local fusion stage. -/ abbrev fresh (x : ContinuumRationalGroup) : ℕ → Finset (LocalGroup x) := localActiveBlock blockSize blockSize_pos independenceBound x @@ -54,6 +59,7 @@ theorem localEnumeration_surjective (x : ContinuumRationalGroup) : (closure_countable blockSize blockSize_pos independenceBound x).to_subtype exact Classical.choose_spec (exists_surjective_nat (LocalGroup x)) +/-- The restriction of `x` to its local coordinate closure. -/ def distinguished (x : ContinuumRationalGroup) : LocalGroup x := by classical exact Finsupp.subtypeDomain (localCarrier x) x @@ -76,9 +82,11 @@ def scheduledCertificate (x : {x : ContinuumRationalGroup // x ≠ 0}) : (localActiveBlock_boundedIndependent blockSize blockSize_pos independenceBound x.1) (localEnumeration_surjective x.1) +/-- The certified fusion run attached to a nonzero rational vector. -/ abbrev run (x : {x : ContinuumRationalGroup // x ≠ 0}) : FusionRun (LocalGroup x.1) := (scheduledCertificate x).run +/-- Positions discarded from the block assigned to a relevant code. -/ def deletedPositions (x : {x : ContinuumRationalGroup // x ≠ 0}) (a : RelevantCode blockSize blockSize_pos independenceBound x.1) (l : ℕ) : Finset ℕ := @@ -153,9 +161,11 @@ theorem retainedPositions_mem_ultrafilter /-! ## Rational block and run certificates -/ +/-- Concrete retained-block data for one rational sequence code. -/ structure RationalCodeBlocks (x : ContinuumRationalGroup) (R : FusionRun (LocalGroup x)) (a : RelevantCode blockSize blockSize_pos independenceBound x) where + /-- The underlying abstract retained-block data. -/ blocks : R.CodeBlocks p_eq : blocks.p = ultrafilter blockSize blockSize_pos a.1 block_eq : ∀ l, blocks.block l = @@ -208,9 +218,12 @@ theorem tendsto_prepared end RationalCodeBlocks +/-- Complete local fusion output for one nonzero rational vector. -/ structure LocalRunCertificate (x : {x : ContinuumRationalGroup // x ≠ 0}) where + /-- The fusion run on the countable local group generated by `x`. -/ run : FusionRun (LocalGroup x.1) self_ne_zero : run.limitCharacter (Finsupp.subtypeDomain (localCarrier x.1) x.1) ≠ 0 + /-- A retained-block certificate for every locally relevant code. -/ codeBlocks : ∀ a : RelevantCode blockSize blockSize_pos independenceBound x.1, RationalCodeBlocks x.1 run a @@ -222,6 +235,7 @@ theorem LocalRunCertificate.locallyAdmissible intro a ha exact (C.codeBlocks ⟨a, ha⟩).tendsto_prepared +/-- The retained-block certificate associated with one relevant sequence code. -/ def codeBlocks (x : {x : ContinuumRationalGroup // x ≠ 0}) (a : RelevantCode blockSize blockSize_pos independenceBound x.1) : RationalCodeBlocks x.1 (run x) a where diff --git a/LeanPool/Wallace/RationalLocalSetup.lean b/LeanPool/Wallace/RationalLocalSetup.lean index ae965c2be..9cdcebb04 100644 --- a/LeanPool/Wallace/RationalLocalSetup.lean +++ b/LeanPool/Wallace/RationalLocalSetup.lean @@ -31,6 +31,7 @@ open FiniteCombinatorics variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) +/-- Codes whose distinguished coordinate lies in the local closure of `x`. -/ abbrev RelevantCode (x : ContinuumRationalGroup) := {a : ContinuumIndex // codeIndex a ∈ closure N hN M x} @@ -48,6 +49,7 @@ private theorem relevantLabels_pairwise (x : ContinuumRationalGroup) : apply hab exact Subtype.ext heq +/-- Pairwise-disjoint refinements of the block labels of all relevant codes. -/ def refinedLabel (x : ContinuumRationalGroup) : RelevantCode N hN M x → Set ℕ := by letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x @@ -81,6 +83,7 @@ theorem refinedLabel_unique (x : ContinuumRationalGroup) {l : ℕ} by_contra hab exact Set.disjoint_left.mp (refinedLabel_pairwise N hN M x hab) ha hb +/-- The unique relevant code assigned to stage `l`, when one exists. -/ def activeCode (x : ContinuumRationalGroup) (l : ℕ) : Option (RelevantCode N hN M x) := by classical @@ -101,6 +104,7 @@ theorem activeCode_eq_some_of_mem (x : ContinuumRationalGroup) (l : ℕ) /-! ## The countable local rational group -/ +/-- The additive inclusion of the local rational direct sum into the ambient one. -/ def closureInclusion (x : ContinuumRationalGroup) : (closure N hN M x →₀ ℚ) →+ ContinuumRationalGroup := by classical @@ -127,6 +131,7 @@ theorem closureInclusion_injective (x : ContinuumRationalGroup) : (.subtype (closure N hN M x : ContinuumIndex → Prop)) z at h exact h +/-- The prepared difference restricted to the local coordinate closure. -/ def localDifference (x : ContinuumRationalGroup) (a : RelevantCode N hN M x) (n : ℕ) : closure N hN M x →₀ ℚ := by classical @@ -183,6 +188,7 @@ theorem localDifference_injective (x : ContinuumRationalGroup) rw [← closureInclusion_localDifference N hN M x a m, ← closureInclusion_localDifference N hN M x a n, hmn] +/-- The finite block of local prepared differences for a relevant code. -/ def localDifferenceBlock (x : ContinuumRationalGroup) (a : RelevantCode N hN M x) (l : ℕ) : Finset (closure N hN M x →₀ ℚ) := @@ -212,6 +218,7 @@ theorem localDifferenceBlock_boundedIndependent (x : ContinuumRationalGroup) rw [localDifferenceBlock_image_inclusion] exact differenceBlock_boundedIndependent N hN M a.1 l +/-- The local difference block active at stage `l`, or the empty block. -/ def localActiveBlock (x : ContinuumRationalGroup) (l : ℕ) : Finset (closure N hN M x →₀ ℚ) := match activeCode N hN M x l with diff --git a/LeanPool/Wallace/RationalTransfiniteExtension.lean b/LeanPool/Wallace/RationalTransfiniteExtension.lean index 72ab0415e..625b911c6 100644 --- a/LeanPool/Wallace/RationalTransfiniteExtension.lean +++ b/LeanPool/Wallace/RationalTransfiniteExtension.lean @@ -28,10 +28,14 @@ universe u v /-- The minimal triangular input for rational-valued prepared sequences. -/ structure Data (I : Type u) [LT I] where + /-- Codes for the prepared injective sequences. -/ Code : Type v + /-- The injective assignment of a distinguished coordinate to every code. -/ codeIndex : Code ↪ I + /-- The prepared rational sequence represented by each code. -/ prepared : Code → ℕ → I →₀ ℚ support_lt : ∀ c n i, i ∈ (prepared c n).support → i < codeIndex c + /-- The ultrafilter along which the prepared sequence is required to converge. -/ p : Code → Ultrafilter ℕ /-- Closure under all supports needed by a code whose distinguished coordinate is local. -/ @@ -173,6 +177,7 @@ theorem globalCoordinate_codeIndex_of_not_mem /-! ## Global character, extension, and admissibility -/ +/-- The global character assembled from the recursively extended rational coordinates. -/ def globalCharacter {I : Type u} [LinearOrder I] [WellFoundedLT I] (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) : (I →₀ ℚ) →+ UnitAddCircle := @@ -274,6 +279,7 @@ theorem globalCharacter_admissible extendRationalCoordinate_one] exact hlim +/-- Rational transfinite-extension data over the canonical continuum index. -/ abbrev ContinuumData := Data RationalTriangularPreprocess.ContinuumIndex end diff --git a/LeanPool/Wallace/RationalTriangularPreprocess.lean b/LeanPool/Wallace/RationalTriangularPreprocess.lean index b0f9c8dcb..d90430279 100644 --- a/LeanPool/Wallace/RationalTriangularPreprocess.lean +++ b/LeanPool/Wallace/RationalTriangularPreprocess.lean @@ -28,6 +28,7 @@ noncomputable section open FiniteCombinatorics +/-- The canonical well-ordered index type of cardinality continuum. -/ abbrev ContinuumIndex := TriangularPreprocess.ContinuumIndex /-- The direct sum of continuum many copies of the additive group of rationals. -/ @@ -88,6 +89,7 @@ def rationalSequenceCodeEquiv : ContinuumIndex ≃ RationalInjectiveSequences := Classical.choice <| Cardinal.eq.mp <| mk_continuumIndex.trans mk_rationalInjectiveSequences.symm +/-- The injective rational sequence represented by the code `a`. -/ def codedSequence (a : ContinuumIndex) : ℕ → ContinuumRationalGroup := (rationalSequenceCodeEquiv a).1 diff --git a/LeanPool/Wallace/SeparationInterface.lean b/LeanPool/Wallace/SeparationInterface.lean index 9afa93d46..43ebeaab5 100644 --- a/LeanPool/Wallace/SeparationInterface.lean +++ b/LeanPool/Wallace/SeparationInterface.lean @@ -39,13 +39,19 @@ ultrafilters, and a compatible separating character for every nonzero element. does not assume any topology or compactness property of the free Abelian group. -/ structure SeparationPackage (I : Type u) where + /-- Codes for injective sequences in the free Abelian group. -/ Code : Type u + /-- The identification of codes with injective sequences. -/ codeEquiv : Code ≃ InjectiveSequence' (I →₀ ℤ) + /-- The distinguished coordinate assigned to each code. -/ codeIndex : Code → I + /-- The selected subsequence of the sequence represented by each code. -/ subsequence : Code → ℕ → ℕ subsequence_strictMono : ∀ c, StrictMono (subsequence c) + /-- The free ultrafilter along which the selected subsequence converges. -/ ultrafilter : Code → Ultrafilter ℕ ultrafilter_free : ∀ c, (ultrafilter c : Filter ℕ) ≤ cofinite + /-- A circle-valued character separating each nonzero group element. -/ character : {x : I →₀ ℤ // x ≠ 0} → (I →₀ ℤ) →+ UnitAddCircle character_self_ne_zero : ∀ x, character x x ≠ 0 character_limit : diff --git a/LeanPool/Wallace/TorsionFreeCoordinate.lean b/LeanPool/Wallace/TorsionFreeCoordinate.lean index 776eb2974..beafa91b2 100644 --- a/LeanPool/Wallace/TorsionFreeCoordinate.lean +++ b/LeanPool/Wallace/TorsionFreeCoordinate.lean @@ -26,8 +26,10 @@ noncomputable section /-- The witness form of the paper's coordinatization lemma. -/ structure RationalCoordinatization (G : Type) [AddCommGroup G] where + /-- An additive embedding of `G` into the continuum-indexed rational direct sum. -/ embedding : G →+ RationalTriangularPreprocess.ContinuumRationalGroup embedding_injective : Function.Injective embedding + /-- A chosen preimage in `G` of every standard basis vector. -/ basisPreimage : TriangularPreprocess.ContinuumIndex → G embedding_basisPreimage : ∀ i, embedding (basisPreimage i) = Finsupp.single i 1 diff --git a/LeanPool/Wallace/TriangularPreprocess.lean b/LeanPool/Wallace/TriangularPreprocess.lean index 70e9bef6e..2aaa13fb3 100644 --- a/LeanPool/Wallace/TriangularPreprocess.lean +++ b/LeanPool/Wallace/TriangularPreprocess.lean @@ -234,15 +234,15 @@ theorem exists_index_gt_avoiding_finset /-- State of the recursive block selector. `values l` contains the values already selected in block `l`; `last` is the last source index used. -/ -structure BlockSelectionState (G : Type*) where +private structure BlockSelectionState (G : Type*) where last : ℕ values : ℕ → Finset G -def initialBlockSelectionState (G : Type*) : BlockSelectionState G where +private def initialBlockSelectionState (G : Type*) : BlockSelectionState G where last := 0 values := fun _ => ∅ -noncomputable def excludedAt +private noncomputable def excludedAt {G : Type*} [AddCommGroup G] (M block : ℕ → ℕ) (n : ℕ) (st : BlockSelectionState G) : Finset G := by classical @@ -251,13 +251,13 @@ noncomputable def excludedAt /-- The next source index: strictly later than the previous one and outside both the values already used in this block and every bounded forbidden equation over them. -/ -def nextBlockIndex +private def nextBlockIndex {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) (M block : ℕ → ℕ) (n : ℕ) (st : BlockSelectionState G) : ℕ := Classical.choose <| exists_index_gt_avoiding_finset hu (excludedAt M block n st) st.last -theorem nextBlockIndex_spec +private theorem nextBlockIndex_spec {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) (M block : ℕ → ℕ) (n : ℕ) (st : BlockSelectionState G) : st.last < nextBlockIndex u hu M block n st ∧ @@ -265,7 +265,7 @@ theorem nextBlockIndex_spec Classical.choose_spec <| exists_index_gt_avoiding_finset hu (excludedAt M block n st) st.last -theorem nextBlockIndex_not_mem_values +private theorem nextBlockIndex_not_mem_values {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) (M block : ℕ → ℕ) (n : ℕ) (st : BlockSelectionState G) : u (nextBlockIndex u hu M block n st) ∉ st.values (block n) := by @@ -273,7 +273,7 @@ theorem nextBlockIndex_not_mem_values exact fun h => (nextBlockIndex_spec u hu M block n st).2 (Finset.mem_union_left _ h) -theorem nextBlockIndex_not_forbidden +private theorem nextBlockIndex_not_forbidden {G : Type*} [AddCommGroup G] [IsAddTorsionFree G] (u : ℕ → G) (hu : Function.Injective u) (M block : ℕ → ℕ) (n : ℕ) (st : BlockSelectionState G) : @@ -284,7 +284,7 @@ theorem nextBlockIndex_not_forbidden exact (nextBlockIndex_spec u hu M block n st).2 (Finset.mem_union_right _ <| forbidden_mem_forbiddenFinset h) -noncomputable def blockSelectionStep +private noncomputable def blockSelectionStep {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) (M block : ℕ → ℕ) (n : ℕ) (st : BlockSelectionState G) : BlockSelectionState G := by @@ -296,7 +296,7 @@ noncomputable def blockSelectionStep (insert (u k) (st.values (block n))) } /-- States after the first `n` positions of the new sequence have been selected. -/ -def blockSelectionStates +private def blockSelectionStates {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) (M block : ℕ → ℕ) : ℕ → BlockSelectionState G | 0 => initialBlockSelectionState G @@ -308,7 +308,7 @@ def blockSubsequenceIndex (M block : ℕ → ℕ) (n : ℕ) : ℕ := (blockSelectionStates u hu M block (n + 1)).last -theorem blockSelectionStates_last_lt_succ +private theorem blockSelectionStates_last_lt_succ {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) (M block : ℕ → ℕ) (n : ℕ) : (blockSelectionStates u hu M block n).last < @@ -324,7 +324,7 @@ theorem blockSubsequenceIndex_strictMono intro n exact blockSelectionStates_last_lt_succ u hu M block (n + 1) -theorem blockSelectionStates_boundedIndependent +private theorem blockSelectionStates_boundedIndependent {G : Type*} [AddCommGroup G] [IsAddTorsionFree G] (u : ℕ → G) (hu : Function.Injective u) (M block : ℕ → ℕ) (n l : ℕ) : @@ -348,7 +348,7 @@ theorem blockSelectionStates_boundedIndependent · simp only [blockSelectionStep, ne_eq, hl, not_false_eq_true, Function.update_of_ne] exact ih -theorem blockSelectionStates_values_mono_succ +private theorem blockSelectionStates_values_mono_succ {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) (M block : ℕ → ℕ) (n l : ℕ) : (blockSelectionStates u hu M block n).values l ⊆ @@ -360,14 +360,14 @@ theorem blockSelectionStates_values_mono_succ simp [blockSelectionStep] · simp [blockSelectionStep, hl] -theorem blockSelectionStates_values_monotone +private theorem blockSelectionStates_values_monotone {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) (M block : ℕ → ℕ) (l : ℕ) : Monotone fun n => (blockSelectionStates u hu M block n).values l := monotone_nat_of_le_succ fun n => blockSelectionStates_values_mono_succ u hu M block n l -theorem selected_value_mem_state +private theorem selected_value_mem_state {G : Type*} [AddCommGroup G] (u : ℕ → G) (hu : Function.Injective u) (M block : ℕ → ℕ) (n : ℕ) : u (blockSubsequenceIndex u hu M block n) ∈ diff --git a/LeanPool/projects.yml b/LeanPool/projects.yml index 95cc1ffd4..b1dbf4564 100644 --- a/LeanPool/projects.yml +++ b/LeanPool/projects.yml @@ -50,6 +50,57 @@ projects: - erdos-rankin msc: - "11N05" + - slug: wallace-problem + title: The Wallace problem in ZFC + summary: >- + Formalizes in ZFC a Hausdorff countably compact group topology without + nontrivial convergent sequences on every torsion-free Abelian group of + cardinality continuum. It specializes the construction to the rational + direct sum and the additive real group, and derives a commutative + Tychonoff countably compact cancellative semigroup that is not a group. + branch: set-theoretic topology and topological algebra + entry_module: LeanPool.Wallace + authors: + - Juliane Trianon Fraga + - Vinicius de Oliveira Rodrigues + source: + title: The Wallace problem and countably compact torsion-free Abelian groups in ZFC + authors: + - Juliane Trianon Fraga + - Vinicius de Oliveira Rodrigues + arxiv: "2608.17317" + doi: 10.48550/arXiv.2608.17317 + url: https://github.com/vo-rodrigues/wallace-problem-zfc-paper + github_repo: vo-rodrigues/wallace-problem-zfc-paper + commit: 23756864de1f14e272dafb070b97fcdc7cbc75c5 + license: Apache-2.0 + status: verified + provenance: AI + main_declarations: + - Wallace.commutativeTychonoffWallaceCounterexampleExists + main_results: + - declaration: Wallace.torsionFreeAbelianGroup_mainTheorem_exact + informal: >- + Every torsion-free Abelian group of cardinality continuum admits a + Hausdorff countably compact group topology with no nontrivial + convergent sequences. + - declaration: Wallace.continuumRationalGroup_and_real_mainTheorem + informal: >- + Both the continuum-indexed rational direct sum and the additive + group of real numbers admit such Hausdorff countably compact group + topologies without nontrivial convergent sequences. + - declaration: Wallace.commutativeTychonoffWallaceCounterexampleExists + informal: >- + There exists a commutative Tychonoff countably compact topological + semigroup with two-sided cancellation which is not a group. + tags: + - wallace-problem + - topological-groups + - set-theoretic-topology + msc: + - "22A05" + - "54D30" + - "20K20" - slug: zeta-zeros title: Simple zeros of the Riemann zeta function summary: >- From 375bf03c4a3f8e1dde37df83ee4da072327161ef Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 4 Sep 2026 17:11:13 +0000 Subject: [PATCH 5/7] Remove empty Wallace forwarding module --- LeanPool.lean | 1 - LeanPool/Wallace/Main.lean | 22 ---------------------- LeanPool/Wallace/TychonoffWallace.lean | 2 +- 3 files changed, 1 insertion(+), 24 deletions(-) delete mode 100644 LeanPool/Wallace/Main.lean diff --git a/LeanPool.lean b/LeanPool.lean index 3779df561..d16177f34 100644 --- a/LeanPool.lean +++ b/LeanPool.lean @@ -4086,7 +4086,6 @@ import LeanPool.Wallace.GlobalAssembly import LeanPool.Wallace.InitialCharacter import LeanPool.Wallace.LocalEnumeration import LeanPool.Wallace.LocalFusion -import LeanPool.Wallace.Main import LeanPool.Wallace.MathlibFoundations import LeanPool.Wallace.NontrivialSequences import LeanPool.Wallace.PackageTransport diff --git a/LeanPool/Wallace/Main.lean b/LeanPool/Wallace/Main.lean deleted file mode 100644 index 3fe5ca5f8..000000000 --- a/LeanPool/Wallace/Main.lean +++ /dev/null @@ -1,22 +0,0 @@ -/- -Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues --/ - -import LeanPool.Wallace.FullTopologyMain - -/-! -# The concrete Wallace counterexample - -This file closes the construction. All numerical parameters, subsequences, filters, -ultrafilters, finite character approximations, countable fusions, transfinite extensions, and -the final topology have been constructed in the imported modules. The theorem below has no -mathematical hypothesis. --/ - -namespace Wallace - -open TriangularPreprocess - -end Wallace diff --git a/LeanPool/Wallace/TychonoffWallace.lean b/LeanPool/Wallace/TychonoffWallace.lean index 71f90996e..25dbd3144 100644 --- a/LeanPool/Wallace/TychonoffWallace.lean +++ b/LeanPool/Wallace/TychonoffWallace.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues -/ -import LeanPool.Wallace.Main +import LeanPool.Wallace.FullTopologyMain import Mathlib.Topology.Separation.CompletelyRegular /-! From 8a42fec9f6cb246cdc49a55ecdf22f94d96c5697 Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 4 Sep 2026 17:52:11 +0000 Subject: [PATCH 6/7] Factor Wallace transfinite extension by coefficient --- LeanPool.lean | 1 + .../CoefficientTransfiniteExtension.lean | 268 ++++++++++++++++++ LeanPool/Wallace/MathlibFoundations.lean | 18 -- .../Wallace/RationalTransfiniteExtension.lean | 266 +++-------------- LeanPool/Wallace/TransfiniteExtension.lean | 268 +++--------------- 5 files changed, 348 insertions(+), 473 deletions(-) create mode 100644 LeanPool/Wallace/CoefficientTransfiniteExtension.lean diff --git a/LeanPool.lean b/LeanPool.lean index d16177f34..6fbba5e20 100644 --- a/LeanPool.lean +++ b/LeanPool.lean @@ -4069,6 +4069,7 @@ import LeanPool.Wallace import LeanPool.Wallace.BlockFilters import LeanPool.Wallace.BlockLimit import LeanPool.Wallace.BoundedIndependentMap +import LeanPool.Wallace.CoefficientTransfiniteExtension import LeanPool.Wallace.ConcreteClosure import LeanPool.Wallace.ConcreteData import LeanPool.Wallace.ConcreteFusionRun diff --git a/LeanPool/Wallace/CoefficientTransfiniteExtension.lean b/LeanPool/Wallace/CoefficientTransfiniteExtension.lean new file mode 100644 index 000000000..99f2b9f4c --- /dev/null +++ b/LeanPool/Wallace/CoefficientTransfiniteExtension.lean @@ -0,0 +1,268 @@ +/- +Copyright (c) 2026 Juliane Trianon Fraga and Vinicius de Oliveira Rodrigues. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues +-/ + +import LeanPool.Wallace.MathlibFoundations +import Mathlib.Topology.Instances.AddCircle.Real + +/-! +# Coefficient-parametric transfinite character extension + +This module contains the recursion shared by the integer and rational Wallace constructions. +The coefficient-specific input is an additive character on one coordinate whose value at one is +a prescribed circle element. The integer specialization uses scalar multiplication; the rational +specialization obtains the character from Baer's extension theorem. +-/ + +open Filter Set Topology + +namespace Wallace +namespace CoefficientTransfiniteExtension + +noncomputable section + +universe u v w + +/-- A way to extend a prescribed circle value to a character on one coefficient coordinate. -/ +structure CoordinateExtension (R : Type w) [AddCommMonoid R] [One R] where + /-- Build a coordinate character with the prescribed value at one. -/ + ofValue : UnitAddCircle → (R →+ UnitAddCircle) + ofValue_one : ∀ t, ofValue t 1 = t + +/-- The triangular data needed by the coefficient-parametric recursion. -/ +structure Data (R : Type w) (I : Type u) [Zero R] [LT I] where + /-- Codes for the prepared sequences. -/ + Code : Type v + /-- The fresh coordinate assigned to a code. -/ + codeIndex : Code ↪ I + /-- The sequence after finite block preprocessing. -/ + prepared : Code → ℕ → I →₀ R + support_lt : ∀ c n i, i ∈ (prepared c n).support → i < codeIndex c + /-- The ultrafilter along which the coded limit is imposed. -/ + p : Code → Ultrafilter ℕ + +/-- Closure under the prepared supports attached to code coordinates in `D`. -/ +def ClosedUnderPreparedSupports {R : Type w} {I : Type u} [Zero R] [LT I] + (E : Data R I) (D : Set I) : Prop := + ∀ c, E.codeIndex c ∈ D → ∀ n i, i ∈ (E.prepared c n).support → i ∈ D + +/-- The local character already realizes each limit whose code coordinate lies in `D`. -/ +def LocallyAdmissible {R : Type w} {I : Type u} [AddCommMonoid R] [One R] [LT I] + (E : Data R I) (D : Set I) (character : (D →₀ R) →+ UnitAddCircle) : Prop := + ∀ (c : E.Code) (hc : E.codeIndex c ∈ D), + Tendsto (fun n ↦ character (Finsupp.subtypeDomain D (E.prepared c n))) (E.p c) + (nhds (character (Finsupp.single ⟨E.codeIndex c, hc⟩ 1))) + +/-- The character on a direct sum induced by its coordinate characters. -/ +private def finsuppAddHom {R : Type w} {I : Type u} [AddCommMonoid R] + (coordinates : I → (R →+ UnitAddCircle)) : (I →₀ R) →+ UnitAddCircle := + Finsupp.liftAddHom coordinates + +@[simp] +private theorem finsuppAddHom_single {R : Type w} {I : Type u} [AddCommMonoid R] + (coordinates : I → (R →+ UnitAddCircle)) (i : I) (r : R) : + finsuppAddHom coordinates (Finsupp.single i r) = coordinates i r := by + simp [finsuppAddHom] + +/-- Totalize the coordinate characters available below a recursive stage. -/ +private def stageCoordinates {R : Type w} {I : Type u} [AddCommMonoid R] [LT I] + [DecidableRel ((· < ·) : I → I → Prop)] (i : I) + (previous : ∀ j, j < i → (R →+ UnitAddCircle)) : I → (R →+ UnitAddCircle) := + fun j ↦ if h : j < i then previous j h else 0 + +/-- Evaluate a prepared term using only coordinates below the current stage. -/ +private def stageEvaluation {R : Type w} {I : Type u} [AddCommMonoid R] [LT I] + [DecidableRel ((· < ·) : I → I → Prop)] (E : Data R I) (i : I) + (previous : ∀ j, j < i → (R →+ UnitAddCircle)) + (c : E.Code) (n : ℕ) : UnitAddCircle := + finsuppAddHom (stageCoordinates i previous) (E.prepared c n) + +/-- The compact ultrafilter limit selected at a code coordinate. -/ +private def compactStageLimit {R : Type w} {I : Type u} [AddCommMonoid R] [LT I] + [DecidableRel ((· < ·) : I → I → Prop)] (E : Data R I) (i : I) + (previous : ∀ j, j < i → (R →+ UnitAddCircle)) + (c : E.Code) : UnitAddCircle := + (Ultrafilter.map (stageEvaluation E i previous c) (E.p c)).lim + +private theorem finsuppAddHom_eq_of_eq_on_support + {R : Type w} {I : Type u} [AddCommMonoid R] + {left right : I → (R →+ UnitAddCircle)} {x : I →₀ R} + (h : ∀ i ∈ x.support, left i = right i) : + finsuppAddHom left x = finsuppAddHom right x := by + simp only [finsuppAddHom, Finsupp.liftAddHom_apply] + apply Finsupp.sum_congr + intro i hi + rw [h i hi] + +/-- One step of the well-founded coordinate recursion. -/ +private def coordinateStep + {R : Type w} {I : Type u} [AddCommMonoid R] [One R] [LinearOrder I] + (extension : CoordinateExtension R) (E : Data R I) (D : Set I) + (character : (D →₀ R) →+ UnitAddCircle) (i : I) + (previous : ∀ j, j < i → (R →+ UnitAddCircle)) : R →+ UnitAddCircle := by + classical + exact if hi : i ∈ D then + character.comp (Finsupp.singleAddHom ⟨i, hi⟩) + else if hcode : ∃ c : E.Code, E.codeIndex c = i then + extension.ofValue (compactStageLimit E i previous (Classical.choose hcode)) + else + 0 + +/-- The coordinate characters constructed by well-founded recursion. -/ +private def globalCoordinate {R : Type w} {I : Type u} [AddCommMonoid R] [One R] + [LinearOrder I] [WellFoundedLT I] (extension : CoordinateExtension R) + (E : Data R I) (D : Set I) (character : (D →₀ R) →+ UnitAddCircle) : + I → (R →+ UnitAddCircle) := + WellFoundedLT.fix fun i previous ↦ coordinateStep extension E D character i previous + +private theorem globalCoordinate_eq {R : Type w} {I : Type u} [AddCommMonoid R] [One R] + [LinearOrder I] [WellFoundedLT I] (extension : CoordinateExtension R) + (E : Data R I) (D : Set I) (character : (D →₀ R) →+ UnitAddCircle) (i : I) : + globalCoordinate extension E D character i = + coordinateStep extension E D character i + (fun j _ ↦ globalCoordinate extension E D character j) := by + rw [globalCoordinate, WellFoundedLT.fix_eq] + +private theorem globalCoordinate_of_mem + {R : Type w} {I : Type u} [AddCommMonoid R] [One R] + [LinearOrder I] [WellFoundedLT I] (extension : CoordinateExtension R) + (E : Data R I) (D : Set I) (character : (D →₀ R) →+ UnitAddCircle) + {i : I} (hi : i ∈ D) : + globalCoordinate extension E D character i = + character.comp (Finsupp.singleAddHom ⟨i, hi⟩) := by + rw [globalCoordinate_eq] + simp [coordinateStep, hi] + +private theorem globalCoordinate_codeIndex_of_not_mem + {R : Type w} {I : Type u} [AddCommMonoid R] [One R] [LinearOrder I] [WellFoundedLT I] + (extension : CoordinateExtension R) (E : Data R I) (D : Set I) + (character : (D →₀ R) →+ UnitAddCircle) + (c : E.Code) (hc : E.codeIndex c ∉ D) : + globalCoordinate extension E D character (E.codeIndex c) = + extension.ofValue + (compactStageLimit E (E.codeIndex c) + (fun j _ ↦ globalCoordinate extension E D character j) c) := by + rw [globalCoordinate_eq] + simp only [coordinateStep, hc, dite_false] + let hex : ∃ d : E.Code, E.codeIndex d = E.codeIndex c := ⟨c, rfl⟩ + rw [dite_eq_left hex] + have hchosen : Classical.choose hex = c := by + apply E.codeIndex.injective + exact Classical.choose_spec hex + rw [hchosen] + +/-- The global character assembled from the recursively constructed coordinates. -/ +def globalCharacter {R : Type w} {I : Type u} [AddCommMonoid R] [One R] + [LinearOrder I] [WellFoundedLT I] (extension : CoordinateExtension R) + (E : Data R I) (D : Set I) (character : (D →₀ R) →+ UnitAddCircle) : + (I →₀ R) →+ UnitAddCircle := + finsuppAddHom (globalCoordinate extension E D character) + +@[simp] +private theorem globalCharacter_single {R : Type w} {I : Type u} [AddCommMonoid R] [One R] + [LinearOrder I] [WellFoundedLT I] (extension : CoordinateExtension R) + (E : Data R I) (D : Set I) (character : (D →₀ R) →+ UnitAddCircle) + (i : I) (r : R) : + globalCharacter extension E D character (Finsupp.single i r) = + globalCoordinate extension E D character i r := by + simp [globalCharacter] + +private theorem globalCharacter_extendDomain {R : Type w} {I : Type u} + [AddCommMonoid R] [One R] [LinearOrder I] [WellFoundedLT I] + (extension : CoordinateExtension R) (E : Data R I) (D : Set I) + (character : (D →₀ R) →+ UnitAddCircle) (x : D →₀ R) : + globalCharacter extension E D character (Finsupp.embDomain (.subtype D) x) = character x := by + let inclusion : (D →₀ R) →+ (I →₀ R) := + Finsupp.embDomain.addMonoidHom (.subtype (D : I → Prop)) + have hhom : (globalCharacter extension E D character).comp inclusion = character := by + apply Finsupp.addHom_ext + intro i r + rcases i with ⟨i, hi⟩ + change globalCharacter extension E D character + (Finsupp.embDomain (.subtype (D : I → Prop)) (Finsupp.single ⟨i, hi⟩ r)) = + character (Finsupp.single ⟨i, hi⟩ r) + rw [Finsupp.embDomain_single, globalCharacter_single] + have hcoordinate := globalCoordinate_of_mem extension E D character (i := i) hi + have happly := DFunLike.congr_fun hcoordinate r + change globalCoordinate extension E D character i r = character (Finsupp.single ⟨i, hi⟩ r) + simpa only [AddMonoidHom.comp_apply, Finsupp.singleAddHom_apply] using happly + exact DFunLike.congr_fun hhom x + +theorem globalCharacter_eq_local_restriction {R : Type w} {I : Type u} + [AddCommMonoid R] [One R] [LinearOrder I] [WellFoundedLT I] + (extension : CoordinateExtension R) (E : Data R I) (D : Set I) + (character : (D →₀ R) →+ UnitAddCircle) + (x : I →₀ R) (hx : ∀ i ∈ x.support, i ∈ D) : + globalCharacter extension E D character x = character (Finsupp.subtypeDomain D x) := by + have hxrange : (↑x.support : Set I) ⊆ Set.range (Function.Embedding.subtype D) := by + intro i hi + exact ⟨⟨i, hx i hi⟩, rfl⟩ + obtain ⟨y, rfl⟩ := + (Finsupp.mem_range_embDomain_iff (Function.Embedding.subtype D) x).2 hxrange + rw [globalCharacter_extendDomain extension E D character y] + congr 1 + ext i + exact (Finsupp.embDomain_apply_self (Function.Embedding.subtype D) y i).symm + +private theorem stageEvaluation_eq_globalCharacter + {R : Type w} {I : Type u} [AddCommMonoid R] [One R] [LinearOrder I] [WellFoundedLT I] + (extension : CoordinateExtension R) (E : Data R I) (D : Set I) + (character : (D →₀ R) →+ UnitAddCircle) (c : E.Code) (n : ℕ) : + stageEvaluation E (E.codeIndex c) + (fun j _ ↦ globalCoordinate extension E D character j) c n = + globalCharacter extension E D character (E.prepared c n) := by + apply finsuppAddHom_eq_of_eq_on_support + intro i hi + simp [stageCoordinates, E.support_lt c n i hi] + +private theorem tendsto_stageEvaluation_compactLimit + {R : Type w} {I : Type u} [AddCommMonoid R] [LinearOrder I] + (E : Data R I) (i : I) (previous : ∀ j, j < i → (R →+ UnitAddCircle)) + (c : E.Code) : + Tendsto (stageEvaluation E i previous c) (E.p c) + (nhds (compactStageLimit E i previous c)) := by + exact (Ultrafilter.map (stageEvaluation E i previous c) (E.p c)).le_nhds_lim + +/-- The transfinite extension realizes every prescribed ultrafilter limit. -/ +theorem globalCharacter_admissible + {R : Type w} {I : Type u} [AddCommMonoid R] [One R] [LinearOrder I] [WellFoundedLT I] + (extension : CoordinateExtension R) (E : Data R I) (D : Set I) + (character : (D →₀ R) →+ UnitAddCircle) + (hclosed : ClosedUnderPreparedSupports E D) + (hlocal : LocallyAdmissible E D character) : + ∀ c : E.Code, + Tendsto (fun n ↦ globalCharacter extension E D character (E.prepared c n)) (E.p c) + (nhds (globalCharacter extension E D character (Finsupp.single (E.codeIndex c) 1))) := by + intro c + by_cases hc : E.codeIndex c ∈ D + · have heval : + (fun n ↦ globalCharacter extension E D character (E.prepared c n)) = + (fun n ↦ character (Finsupp.subtypeDomain D (E.prepared c n))) := by + funext n + exact globalCharacter_eq_local_restriction extension E D character (E.prepared c n) + (hclosed c hc n) + have hbasis : + globalCharacter extension E D character (Finsupp.single (E.codeIndex c) 1) = + character (Finsupp.single ⟨E.codeIndex c, hc⟩ 1) := by + rw [globalCharacter_single, globalCoordinate_of_mem extension E D character hc] + rfl + rw [heval, hbasis] + exact hlocal c hc + · have hlim := tendsto_stageEvaluation_compactLimit E (E.codeIndex c) + (fun j _ ↦ globalCoordinate extension E D character j) c + have heval : + (fun n ↦ globalCharacter extension E D character (E.prepared c n)) = + stageEvaluation E (E.codeIndex c) + (fun j _ ↦ globalCoordinate extension E D character j) c := by + funext n + exact (stageEvaluation_eq_globalCharacter extension E D character c n).symm + rw [heval, globalCharacter_single, + globalCoordinate_codeIndex_of_not_mem extension E D character c hc, + extension.ofValue_one] + exact hlim + +end +end CoefficientTransfiniteExtension +end Wallace diff --git a/LeanPool/Wallace/MathlibFoundations.lean b/LeanPool/Wallace/MathlibFoundations.lean index eb20c1e17..9cf85a752 100644 --- a/LeanPool/Wallace/MathlibFoundations.lean +++ b/LeanPool/Wallace/MathlibFoundations.lean @@ -4,8 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues -/ -import Mathlib.Algebra.BigOperators.Finsupp.Basic -import Mathlib.Algebra.Module.NatInt import Mathlib.Logic.Encodable.Pi import Mathlib.Order.Filter.Cofinite import Mathlib.Order.Filter.Ultrafilter.Defs @@ -42,22 +40,6 @@ theorem exists_free_ultrafilter_le_filter {α : Type u} (l : Filter α) [l.NeBot refine ⟨Ultrafilter.of l, Ultrafilter.of_le l, ?_⟩ exact (Ultrafilter.of_le l).trans hl -/-! ## Characters of a free Abelian group -/ - -/-- The homomorphism out of a free Abelian group determined by its values on the standard -basis. -/ -def finsuppAddHomOfBasis {ι : Type u} {A : Type v} [AddCommGroup A] - (z : ι → A) : (ι →₀ ℤ) →+ A := - Finsupp.liftAddHom fun i => (zmultiplesHom A) (z i) - -@[simp] -theorem finsuppAddHomOfBasis_single {ι : Type u} {A : Type v} [AddCommGroup A] - (z : ι → A) (i : ι) (n : ℤ) : - finsuppAddHomOfBasis z (Finsupp.single i n) = n • z i := by - simp [finsuppAddHomOfBasis] - -/-! ## The initial topology generated by circle-valued characters -/ - /-! ## Cardinal bookkeeping for the continuum-indexed free group -/ /-- König's theorem gives the strict uncountable cofinality of the continuum. This is the diff --git a/LeanPool/Wallace/RationalTransfiniteExtension.lean b/LeanPool/Wallace/RationalTransfiniteExtension.lean index 625b911c6..337236e5e 100644 --- a/LeanPool/Wallace/RationalTransfiniteExtension.lean +++ b/LeanPool/Wallace/RationalTransfiniteExtension.lean @@ -4,17 +4,16 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues -/ +import LeanPool.Wallace.CoefficientTransfiniteExtension import LeanPool.Wallace.RationalTriangularPreprocess import Mathlib.Algebra.Category.Grp.Injective -import Mathlib.Topology.Instances.AddCircle.Real /-! # Transfinite extension for the rational direct sum -The recursive datum at a coordinate is an additive homomorphism `ℚ →+ 𝕋`, rather than a -single point of the circle. At a new code coordinate, Baer's extension theorem extends the -homomorphism `n ↦ n • t` from `ℤ` to `ℚ`, where `t` is the compact ultrafilter limit chosen at -that stage. This is the coefficient-sensitive step in the rational construction. +This file supplies the coefficient-specific input to the shared transfinite recursion. Baer's +extension theorem extends the integer character with prescribed value at one to a character on +each rational coordinate. -/ open Filter Set Topology @@ -24,260 +23,77 @@ namespace RationalTransfiniteExtension noncomputable section -universe u v +universe u -/-- The minimal triangular input for rational-valued prepared sequences. -/ -structure Data (I : Type u) [LT I] where - /-- Codes for the prepared injective sequences. -/ - Code : Type v - /-- The injective assignment of a distinguished coordinate to every code. -/ - codeIndex : Code ↪ I - /-- The prepared rational sequence represented by each code. -/ - prepared : Code → ℕ → I →₀ ℚ - support_lt : ∀ c n i, i ∈ (prepared c n).support → i < codeIndex c - /-- The ultrafilter along which the prepared sequence is required to converge. -/ - p : Code → Ultrafilter ℕ - -/-- Closure under all supports needed by a code whose distinguished coordinate is local. -/ -def ClosedUnderPreparedSupports {I : Type u} [LT I] (E : Data I) (D : Set I) : Prop := - ∀ c, E.codeIndex c ∈ D → ∀ n i, i ∈ (E.prepared c n).support → i ∈ D - -/-- The local character already realizes every limit whose code coordinate belongs to `D`. -/ -def LocallyAdmissible {I : Type u} [LT I] (E : Data I) (D : Set I) - (χD : (D →₀ ℚ) →+ UnitAddCircle) : Prop := - ∀ (c : E.Code) (hc : E.codeIndex c ∈ D), - Tendsto (fun n ↦ χD (Finsupp.subtypeDomain D (E.prepared c n))) (E.p c) - (nhds (χD (Finsupp.single ⟨E.codeIndex c, hc⟩ 1))) - -/-! ## Extending one rational coordinate -/ +open CoefficientTransfiniteExtension /-- The integer character with prescribed value at one. -/ -def integerCircleHom (t : UnitAddCircle) : ℤ →+ UnitAddCircle := +private def integerCircleHom (t : UnitAddCircle) : ℤ →+ UnitAddCircle := (zmultiplesHom UnitAddCircle) t -theorem intCastAddHom_rational_injective : +private theorem intCastAddHom_rational_injective : Function.Injective (Int.castAddHom ℚ) := by intro m n h exact Rat.intCast_injective h -/-- An additive homomorphism on `ℚ` extending `n ↦ n • t` on `ℤ`. - -Only its value at `1` is constrained at the current stage; the chosen full homomorphism is then -used coherently when later prepared sequences are evaluated. -/ -def extendRationalCoordinate (t : UnitAddCircle) : ℚ →+ UnitAddCircle := +/-- An additive homomorphism on `ℚ` extending the integer character with value `t` at one. -/ +private def extendRationalCoordinate (t : UnitAddCircle) : ℚ →+ UnitAddCircle := Classical.choose <| (Module.Baer.of_divisible UnitAddCircle).extension_property_addMonoidHom (Int.castAddHom ℚ) intCastAddHom_rational_injective (integerCircleHom t) -theorem extendRationalCoordinate_comp_intCast (t : UnitAddCircle) : +private theorem extendRationalCoordinate_comp_intCast (t : UnitAddCircle) : (extendRationalCoordinate t).comp (Int.castAddHom ℚ) = integerCircleHom t := Classical.choose_spec <| (Module.Baer.of_divisible UnitAddCircle).extension_property_addMonoidHom (Int.castAddHom ℚ) intCastAddHom_rational_injective (integerCircleHom t) @[simp] -theorem extendRationalCoordinate_one (t : UnitAddCircle) : +private theorem extendRationalCoordinate_one (t : UnitAddCircle) : extendRationalCoordinate t 1 = t := by have h := DFunLike.congr_fun (extendRationalCoordinate_comp_intCast t) 1 simpa [integerCircleHom] using h -/-! ## Evaluation below a recursive stage -/ - -/-- The homomorphism out of a rational direct sum determined coordinatewise. -/ -def rationalFinsuppAddHom {I : Type u} - (θ : I → (ℚ →+ UnitAddCircle)) : (I →₀ ℚ) →+ UnitAddCircle := - Finsupp.liftAddHom θ - -@[simp] -theorem rationalFinsuppAddHom_single {I : Type u} - (θ : I → (ℚ →+ UnitAddCircle)) (i : I) (q : ℚ) : - rationalFinsuppAddHom θ (Finsupp.single i q) = θ i q := by - simp [rationalFinsuppAddHom] - -/-- Totalize the coordinate homomorphisms already available below `i`. -/ -def stageCoordinates {I : Type u} [LT I] [DecidableRel ((· < ·) : I → I → Prop)] - (i : I) (previous : ∀ j, j < i → (ℚ →+ UnitAddCircle)) : - I → (ℚ →+ UnitAddCircle) := - fun j ↦ if h : j < i then previous j h else 0 - -/-- Evaluate a prepared term using only coordinates below the current stage. -/ -def stageEvaluation {I : Type u} [LT I] [DecidableRel ((· < ·) : I → I → Prop)] - (E : Data I) (i : I) - (previous : ∀ j, j < i → (ℚ →+ UnitAddCircle)) - (c : E.Code) (n : ℕ) : UnitAddCircle := - rationalFinsuppAddHom (stageCoordinates i previous) (E.prepared c n) - -/-- Compact ultrafilter limit selected at a code coordinate. -/ -def compactStageLimit {I : Type u} [LT I] [DecidableRel ((· < ·) : I → I → Prop)] - (E : Data I) (i : I) - (previous : ∀ j, j < i → (ℚ →+ UnitAddCircle)) - (c : E.Code) : UnitAddCircle := - (Ultrafilter.map (stageEvaluation E i previous c) (E.p c)).lim +/-- Baer's extension supplies the coordinate extension used by the generic recursion. -/ +private def rationalCoordinateExtension : CoordinateExtension ℚ where + ofValue := extendRationalCoordinate + ofValue_one := extendRationalCoordinate_one -theorem rationalFinsuppAddHom_eq_of_eq_on_support {I : Type u} - {z w : I → (ℚ →+ UnitAddCircle)} {x : I →₀ ℚ} - (h : ∀ i ∈ x.support, z i = w i) : - rationalFinsuppAddHom z x = rationalFinsuppAddHom w x := by - simp only [rationalFinsuppAddHom, Finsupp.liftAddHom_apply] - apply Finsupp.sum_congr - intro i hi - rw [h i hi] +/-- Triangular data for rational-valued prepared sequences. -/ +abbrev Data (I : Type u) [LT I] := CoefficientTransfiniteExtension.Data ℚ I -/-! ## Well-founded construction -/ +/-- Closure under the rational prepared supports associated to local code coordinates. -/ +abbrev ClosedUnderPreparedSupports {I : Type u} [LT I] + (E : Data I) (D : Set I) : Prop := + CoefficientTransfiniteExtension.ClosedUnderPreparedSupports E D -/-- One step of the coordinate recursion. -/ -def coordinateStep {I : Type u} [LinearOrder I] (E : Data I) (D : Set I) - (χD : (D →₀ ℚ) →+ UnitAddCircle) (i : I) - (previous : ∀ j, j < i → (ℚ →+ UnitAddCircle)) : - ℚ →+ UnitAddCircle := by - classical - exact if hi : i ∈ D then - χD.comp (Finsupp.singleAddHom ⟨i, hi⟩) - else if hcode : ∃ c : E.Code, E.codeIndex c = i then - extendRationalCoordinate - (compactStageLimit E i previous (Classical.choose hcode)) - else - 0 +/-- The local rational character realizes every limit whose code coordinate is local. -/ +abbrev LocallyAdmissible {I : Type u} [LT I] (E : Data I) (D : Set I) + (character : (D →₀ ℚ) →+ UnitAddCircle) : Prop := + CoefficientTransfiniteExtension.LocallyAdmissible E D character -/-- The recursively constructed additive homomorphism on each rational coordinate. -/ -def globalCoordinate {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) : - I → (ℚ →+ UnitAddCircle) := - WellFoundedLT.fix fun i previous ↦ coordinateStep E D χD i previous - -theorem globalCoordinate_eq {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) (i : I) : - globalCoordinate E D χD i = - coordinateStep E D χD i (fun j _ ↦ globalCoordinate E D χD j) := by - rw [globalCoordinate, WellFoundedLT.fix_eq] - -theorem globalCoordinate_of_mem {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) - {i : I} (hi : i ∈ D) : - globalCoordinate E D χD i = χD.comp (Finsupp.singleAddHom ⟨i, hi⟩) := by - rw [globalCoordinate_eq] - simp [coordinateStep, hi] - -theorem globalCoordinate_codeIndex_of_not_mem - {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) - (c : E.Code) (hc : E.codeIndex c ∉ D) : - globalCoordinate E D χD (E.codeIndex c) = - extendRationalCoordinate - (compactStageLimit E (E.codeIndex c) - (fun j _ ↦ globalCoordinate E D χD j) c) := by - rw [globalCoordinate_eq] - simp only [coordinateStep, hc, dite_false] - let hex : ∃ d : E.Code, E.codeIndex d = E.codeIndex c := ⟨c, rfl⟩ - rw [dite_eq_left hex] - have hchosen : Classical.choose hex = c := by - apply E.codeIndex.injective - exact Classical.choose_spec hex - rw [hchosen] - -/-! ## Global character, extension, and admissibility -/ - -/-- The global character assembled from the recursively extended rational coordinates. -/ -def globalCharacter {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) : +/-- The global rational character produced by the shared transfinite recursion. -/ +abbrev globalCharacter {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (character : (D →₀ ℚ) →+ UnitAddCircle) : (I →₀ ℚ) →+ UnitAddCircle := - rationalFinsuppAddHom (globalCoordinate E D χD) - -@[simp] -theorem globalCharacter_single {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) - (i : I) (q : ℚ) : - globalCharacter E D χD (Finsupp.single i q) = globalCoordinate E D χD i q := by - simp [globalCharacter] - -theorem globalCharacter_extendDomain {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) - (x : D →₀ ℚ) : - globalCharacter E D χD (Finsupp.embDomain (.subtype D) x) = χD x := by - let inclusion : (D →₀ ℚ) →+ (I →₀ ℚ) := - Finsupp.embDomain.addMonoidHom (.subtype (D : I → Prop)) - have hhom : (globalCharacter E D χD).comp inclusion = χD := by - apply Finsupp.addHom_ext - intro i q - rcases i with ⟨i, hi⟩ - change globalCharacter E D χD - (Finsupp.embDomain (.subtype (D : I → Prop)) (Finsupp.single ⟨i, hi⟩ q)) = - χD (Finsupp.single ⟨i, hi⟩ q) - rw [Finsupp.embDomain_single, globalCharacter_single] - have hcoord := globalCoordinate_of_mem E D χD (i := i) hi - have happly := DFunLike.congr_fun hcoord q - change globalCoordinate E D χD i q = χD (Finsupp.single ⟨i, hi⟩ q) - simpa only [AddMonoidHom.comp_apply, Finsupp.singleAddHom_apply] using happly - exact DFunLike.congr_fun hhom x + CoefficientTransfiniteExtension.globalCharacter rationalCoordinateExtension E D character theorem globalCharacter_eq_local_restriction {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) + (E : Data I) (D : Set I) (character : (D →₀ ℚ) →+ UnitAddCircle) (x : I →₀ ℚ) (hx : ∀ i ∈ x.support, i ∈ D) : - globalCharacter E D χD x = χD (Finsupp.subtypeDomain D x) := by - have hxrange : (↑x.support : Set I) ⊆ Set.range (Function.Embedding.subtype D) := by - intro i hi - exact ⟨⟨i, hx i hi⟩, rfl⟩ - obtain ⟨y, rfl⟩ := - (Finsupp.mem_range_embDomain_iff (Function.Embedding.subtype D) x).2 hxrange - rw [globalCharacter_extendDomain E D χD y] - congr 1 - ext i - exact (Finsupp.embDomain_apply_self (Function.Embedding.subtype D) y i).symm - -theorem stageEvaluation_eq_globalCharacter - {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) - (c : E.Code) (n : ℕ) : - stageEvaluation E (E.codeIndex c) - (fun j _ ↦ globalCoordinate E D χD j) c n = - globalCharacter E D χD (E.prepared c n) := by - apply rationalFinsuppAddHom_eq_of_eq_on_support - intro i hi - simp [stageCoordinates, E.support_lt c n i hi] - -theorem tendsto_stageEvaluation_compactLimit - {I : Type u} [LinearOrder I] (E : Data I) (i : I) - (previous : ∀ j, j < i → (ℚ →+ UnitAddCircle)) (c : E.Code) : - Tendsto (stageEvaluation E i previous c) (E.p c) - (nhds (compactStageLimit E i previous c)) := by - exact (Ultrafilter.map (stageEvaluation E i previous c) (E.p c)).le_nhds_lim + globalCharacter E D character x = character (Finsupp.subtypeDomain D x) := + CoefficientTransfiniteExtension.globalCharacter_eq_local_restriction + rationalCoordinateExtension E D character x hx -/-- The rational transfinite extension realizes every prescribed ultrafilter limit. -/ -theorem globalCharacter_admissible - {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℚ) →+ UnitAddCircle) +theorem globalCharacter_admissible {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (character : (D →₀ ℚ) →+ UnitAddCircle) (hclosed : ClosedUnderPreparedSupports E D) - (hlocal : LocallyAdmissible E D χD) : + (hlocal : LocallyAdmissible E D character) : ∀ c : E.Code, - Tendsto (fun n ↦ globalCharacter E D χD (E.prepared c n)) (E.p c) - (nhds (globalCharacter E D χD (Finsupp.single (E.codeIndex c) 1))) := by - intro c - by_cases hc : E.codeIndex c ∈ D - · have heval : - (fun n ↦ globalCharacter E D χD (E.prepared c n)) = - (fun n ↦ χD (Finsupp.subtypeDomain D (E.prepared c n))) := by - funext n - exact globalCharacter_eq_local_restriction E D χD (E.prepared c n) - (hclosed c hc n) - have hbasis : - globalCharacter E D χD (Finsupp.single (E.codeIndex c) 1) = - χD (Finsupp.single ⟨E.codeIndex c, hc⟩ 1) := by - rw [globalCharacter_single, globalCoordinate_of_mem E D χD hc] - rfl - rw [heval, hbasis] - exact hlocal c hc - · have hlim := tendsto_stageEvaluation_compactLimit E (E.codeIndex c) - (fun j _ ↦ globalCoordinate E D χD j) c - have heval : - (fun n ↦ globalCharacter E D χD (E.prepared c n)) = - stageEvaluation E (E.codeIndex c) - (fun j _ ↦ globalCoordinate E D χD j) c := by - funext n - exact (stageEvaluation_eq_globalCharacter E D χD c n).symm - rw [heval, globalCharacter_single, - globalCoordinate_codeIndex_of_not_mem E D χD c hc, - extendRationalCoordinate_one] - exact hlim + Tendsto (fun n ↦ globalCharacter E D character (E.prepared c n)) (E.p c) + (nhds (globalCharacter E D character (Finsupp.single (E.codeIndex c) 1))) := + CoefficientTransfiniteExtension.globalCharacter_admissible + rationalCoordinateExtension E D character hclosed hlocal /-- Rational transfinite-extension data over the canonical continuum index. -/ abbrev ContinuumData := Data RationalTriangularPreprocess.ContinuumIndex diff --git a/LeanPool/Wallace/TransfiniteExtension.lean b/LeanPool/Wallace/TransfiniteExtension.lean index f480520d7..6d6bbef29 100644 --- a/LeanPool/Wallace/TransfiniteExtension.lean +++ b/LeanPool/Wallace/TransfiniteExtension.lean @@ -4,24 +4,14 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues -/ +import LeanPool.Wallace.CoefficientTransfiniteExtension import LeanPool.Wallace.TriangularPreprocess -import Mathlib.Topology.Instances.AddCircle.Real /-! -# Transfinite extension of a local circle-valued character +# Transfinite extension of an integer-valued local character -This file isolates the transfinite part of the Wallace construction behind a small, reusable -interface. The only input about the prepared sequences is the triangular support condition: -every coordinate occurring in the sequence coded at `codeIndex c` is strictly smaller than -`codeIndex c`. - -At a coordinate in the closed set `D` we use the prescribed local character. At a code -coordinate outside `D` we take the compact ultrafilter limit of the values of its prepared -sequence, evaluated using coordinates already defined by well-founded recursion. All other -coordinates receive zero. The resulting basis assignment extends uniquely to the free Abelian -group, extends the local character, and is admissible for every code. - -There are no axioms or omitted proofs in this file. +This file specializes the coefficient-parametric Wallace recursion to the free Abelian group. +An integer coordinate character is uniquely determined by its value at one. -/ open Filter Set Topology @@ -31,238 +21,56 @@ namespace TransfiniteExtension noncomputable section -universe u v - -/-! ## Abstract triangular input -/ - -/-- The minimal triangular data needed by the transfinite character extension. -/ -structure Data (I : Type u) [LT I] where - /-- Codes for the prepared sequences. -/ - Code : Type v - /-- The fresh coordinate assigned to a code. -/ - codeIndex : Code ↪ I - /-- The sequence after the finite block preprocessing. -/ - prepared : Code → ℕ → I →₀ ℤ - /-- Every coordinate used by a prepared term precedes its code coordinate. -/ - support_lt : ∀ c n i, i ∈ (prepared c n).support → i < codeIndex c - /-- The ultrafilter with respect to which the coded limit is imposed. -/ - p : Code → Ultrafilter ℕ - -/-- Closure of `D` under the coordinates occurring in codes whose fresh coordinate lies in -`D`. This is precisely what is needed to transfer the already-established local limits. -/ -def ClosedUnderPreparedSupports {I : Type u} [LT I] (E : Data I) (D : Set I) : Prop := - ∀ c, E.codeIndex c ∈ D → ∀ n i, i ∈ (E.prepared c n).support → i ∈ D - -/-- The local admissibility condition, stated after restricting each prepared term to `D`. -/ -def LocallyAdmissible {I : Type u} [LT I] (E : Data I) (D : Set I) - (χD : (D →₀ ℤ) →+ UnitAddCircle) : Prop := - ∀ (c : E.Code) (hc : E.codeIndex c ∈ D), - Tendsto (fun n ↦ χD (Finsupp.subtypeDomain D (E.prepared c n))) (E.p c) - (nhds (χD (Finsupp.single ⟨E.codeIndex c, hc⟩ 1))) - -/-! ## Evaluation below a recursive stage -/ - -/-- Turn the values available below stage `i` into a total basis assignment by putting zero -above the stage. -/ -def stageBasis {I : Type u} [LT I] [DecidableRel ((· < ·) : I → I → Prop)] (i : I) - (previous : ∀ j, j < i → UnitAddCircle) : I → UnitAddCircle := - fun j ↦ if h : j < i then previous j h else 0 - -/-- Evaluation of a prepared term using only values available below the current stage. -/ -def stageEvaluation {I : Type u} [LT I] [DecidableRel ((· < ·) : I → I → Prop)] - (E : Data I) (i : I) - (previous : ∀ j, j < i → UnitAddCircle) (c : E.Code) (n : ℕ) : UnitAddCircle := - finsuppAddHomOfBasis (stageBasis i previous) (E.prepared c n) - -/-- The compact ultrafilter limit chosen at a code coordinate. -/ -def compactStageLimit {I : Type u} [LT I] [DecidableRel ((· < ·) : I → I → Prop)] - (E : Data I) (i : I) - (previous : ∀ j, j < i → UnitAddCircle) (c : E.Code) : UnitAddCircle := - (Ultrafilter.map (stageEvaluation E i previous c) (E.p c)).lim +universe u -/-- Two basis assignments that agree on the support of a vector give the same value. -/ -theorem finsuppAddHomOfBasis_eq_of_eq_on_support {I : Type u} - {z w : I → UnitAddCircle} {x : I →₀ ℤ} - (h : ∀ i ∈ x.support, z i = w i) : - finsuppAddHomOfBasis z x = finsuppAddHomOfBasis w x := by - simp only [finsuppAddHomOfBasis, Finsupp.liftAddHom_apply] - apply Finsupp.sum_congr - intro i hi - rw [h i hi] +open CoefficientTransfiniteExtension -/-! ## Well-founded definition of the global basis values -/ +/-- Extend a prescribed circle value to the corresponding integer character. -/ +private def integerCoordinateExtension : CoordinateExtension ℤ where + ofValue := fun t ↦ (zmultiplesHom UnitAddCircle) t + ofValue_one := by + intro t + simp -/-- One step of the recursion. Injectivity of `codeIndex` makes the code chosen in the second -branch unique. -/ -def basisStep {I : Type u} [LinearOrder I] (E : Data I) (D : Set I) - (χD : (D →₀ ℤ) →+ UnitAddCircle) (i : I) - (previous : ∀ j, j < i → UnitAddCircle) : UnitAddCircle := by - classical - exact if hi : i ∈ D then - χD (Finsupp.single ⟨i, hi⟩ 1) - else if hcode : ∃ c : E.Code, E.codeIndex c = i then - compactStageLimit E i previous (Classical.choose hcode) - else - 0 +/-- Triangular data for integer-valued prepared sequences. -/ +abbrev Data (I : Type u) [LT I] := CoefficientTransfiniteExtension.Data ℤ I -/-- The global values on the standard basis, defined by recursion along the well-order. -/ -def globalBasisValue {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) : - I → UnitAddCircle := - WellFoundedLT.fix fun i previous ↦ basisStep E D χD i previous +/-- Closure under the integer prepared supports associated to local code coordinates. -/ +abbrev ClosedUnderPreparedSupports {I : Type u} [LT I] + (E : Data I) (D : Set I) : Prop := + CoefficientTransfiniteExtension.ClosedUnderPreparedSupports E D -theorem globalBasisValue_eq {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) (i : I) : - globalBasisValue E D χD i = - basisStep E D χD i (fun j _ ↦ globalBasisValue E D χD j) := by - rw [globalBasisValue, WellFoundedLT.fix_eq] +/-- The local integer character realizes every limit whose code coordinate is local. -/ +abbrev LocallyAdmissible {I : Type u} [LT I] (E : Data I) (D : Set I) + (character : (D →₀ ℤ) →+ UnitAddCircle) : Prop := + CoefficientTransfiniteExtension.LocallyAdmissible E D character -theorem globalBasisValue_of_mem {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) - {i : I} (hi : i ∈ D) : - globalBasisValue E D χD i = χD (Finsupp.single ⟨i, hi⟩ 1) := by - rw [globalBasisValue_eq] - simp [basisStep, hi] - -theorem globalBasisValue_codeIndex_of_not_mem - {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) - (c : E.Code) (hc : E.codeIndex c ∉ D) : - globalBasisValue E D χD (E.codeIndex c) = - compactStageLimit E (E.codeIndex c) - (fun j _ ↦ globalBasisValue E D χD j) c := by - rw [globalBasisValue_eq] - simp only [basisStep, hc, dite_false] - let hex : ∃ d : E.Code, E.codeIndex d = E.codeIndex c := ⟨c, rfl⟩ - rw [dite_eq_left hex] - have hchosen : Classical.choose hex = c := by - apply E.codeIndex.injective - exact Classical.choose_spec hex - rw [hchosen] - -/-! ## The global character and its extension property -/ - -/-- The unique additive character determined by the recursively constructed basis values. -/ -def globalCharacter {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) : +/-- The global integer character produced by the shared transfinite recursion. -/ +abbrev globalCharacter {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (character : (D →₀ ℤ) →+ UnitAddCircle) : (I →₀ ℤ) →+ UnitAddCircle := - finsuppAddHomOfBasis (globalBasisValue E D χD) - -@[simp] -theorem globalCharacter_single_one {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) (i : I) : - globalCharacter E D χD (Finsupp.single i 1) = globalBasisValue E D χD i := by - simp [globalCharacter] - -/-- On finitely supported vectors on `D`, the global character is exactly the prescribed local -character. -/ -theorem globalCharacter_extendDomain {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) - (x : D →₀ ℤ) : - globalCharacter E D χD (Finsupp.embDomain (.subtype D) x) = χD x := by - let inclusion : (D →₀ ℤ) →+ (I →₀ ℤ) := - Finsupp.embDomain.addMonoidHom (.subtype (D : I → Prop)) - have hhom : (globalCharacter E D χD).comp inclusion = χD := by - apply Finsupp.addHom_ext - intro i n - rcases i with ⟨i, hi⟩ - change globalCharacter E D χD - (Finsupp.embDomain (.subtype (D : I → Prop)) (Finsupp.single ⟨i, hi⟩ n)) = - χD (Finsupp.single ⟨i, hi⟩ n) - rw [Finsupp.embDomain_single] - simp only [globalCharacter, finsuppAddHomOfBasis_single] - have hbasis := globalBasisValue_of_mem E D χD (i := i) hi - have hbasis' : - globalBasisValue E D χD i = - χD (Finsupp.single ⟨i, hi⟩ 1) := by - exact hbasis - calc - n • globalBasisValue E D χD i = - n • χD (Finsupp.single ⟨i, hi⟩ 1) := congrArg (fun z ↦ n • z) hbasis' - _ = χD (n • Finsupp.single ⟨i, hi⟩ 1) := (map_zsmul χD _ _).symm - _ = χD (Finsupp.single ⟨i, hi⟩ n) := by simp - exact DFunLike.congr_fun hhom x + CoefficientTransfiniteExtension.globalCharacter integerCoordinateExtension E D character -/-- Equivalent extension statement for an ambient vector whose support is contained in `D`. -/ theorem globalCharacter_eq_local_restriction {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) + (E : Data I) (D : Set I) (character : (D →₀ ℤ) →+ UnitAddCircle) (x : I →₀ ℤ) (hx : ∀ i ∈ x.support, i ∈ D) : - globalCharacter E D χD x = χD (Finsupp.subtypeDomain D x) := by - have hxrange : (↑x.support : Set I) ⊆ - Set.range (Function.Embedding.subtype D) := by - intro i hi - exact ⟨⟨i, hx i hi⟩, rfl⟩ - obtain ⟨y, rfl⟩ := - (Finsupp.mem_range_embDomain_iff (Function.Embedding.subtype D) x).2 hxrange - rw [globalCharacter_extendDomain E D χD y] - congr 1 - ext i - exact (Finsupp.embDomain_apply_self (Function.Embedding.subtype D) y i).symm + globalCharacter E D character x = character (Finsupp.subtypeDomain D x) := + CoefficientTransfiniteExtension.globalCharacter_eq_local_restriction + integerCoordinateExtension E D character x hx -/-! ## Admissibility at every code -/ - -theorem stageEvaluation_eq_globalCharacter - {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) - (c : E.Code) (n : ℕ) : - stageEvaluation E (E.codeIndex c) - (fun j _ ↦ globalBasisValue E D χD j) c n = - globalCharacter E D χD (E.prepared c n) := by - apply finsuppAddHomOfBasis_eq_of_eq_on_support - intro i hi - simp [stageBasis, E.support_lt c n i hi] - -/-- Compactness of the circle supplies the limit used at each external code coordinate. -/ -theorem tendsto_stageEvaluation_compactLimit - {I : Type u} [LinearOrder I] (E : Data I) (i : I) - (previous : ∀ j, j < i → UnitAddCircle) (c : E.Code) : - Tendsto (stageEvaluation E i previous c) (E.p c) - (nhds (compactStageLimit E i previous c)) := by - exact (Ultrafilter.map (stageEvaluation E i previous c) (E.p c)).le_nhds_lim - -/-- The transfinite extension is admissible for every prepared code, including codes outside -the local closed set. -/ -theorem globalCharacter_admissible - {I : Type u} [LinearOrder I] [WellFoundedLT I] - (E : Data I) (D : Set I) (χD : (D →₀ ℤ) →+ UnitAddCircle) +theorem globalCharacter_admissible {I : Type u} [LinearOrder I] [WellFoundedLT I] + (E : Data I) (D : Set I) (character : (D →₀ ℤ) →+ UnitAddCircle) (hclosed : ClosedUnderPreparedSupports E D) - (hlocal : LocallyAdmissible E D χD) : + (hlocal : LocallyAdmissible E D character) : ∀ c : E.Code, - Tendsto (fun n ↦ globalCharacter E D χD (E.prepared c n)) (E.p c) - (nhds (globalCharacter E D χD (Finsupp.single (E.codeIndex c) 1))) := by - intro c - by_cases hc : E.codeIndex c ∈ D - · have heval : - (fun n ↦ globalCharacter E D χD (E.prepared c n)) = - (fun n ↦ χD (Finsupp.subtypeDomain D (E.prepared c n))) := by - funext n - exact globalCharacter_eq_local_restriction E D χD (E.prepared c n) - (hclosed c hc n) - have hbasis : - globalCharacter E D χD (Finsupp.single (E.codeIndex c) 1) = - χD (Finsupp.single ⟨E.codeIndex c, hc⟩ 1) := by - rw [globalCharacter_single_one, globalBasisValue_of_mem E D χD hc] - rw [heval, hbasis] - exact hlocal c hc - · have hlim := tendsto_stageEvaluation_compactLimit E (E.codeIndex c) - (fun j _ ↦ globalBasisValue E D χD j) c - have heval : - (fun n ↦ globalCharacter E D χD (E.prepared c n)) = - stageEvaluation E (E.codeIndex c) - (fun j _ ↦ globalBasisValue E D χD j) c := by - funext n - exact (stageEvaluation_eq_globalCharacter E D χD c n).symm - rw [heval, globalCharacter_single_one, - globalBasisValue_codeIndex_of_not_mem E D χD c hc] - exact hlim + Tendsto (fun n ↦ globalCharacter E D character (E.prepared c n)) (E.p c) + (nhds (globalCharacter E D character (Finsupp.single (E.codeIndex c) 1))) := + CoefficientTransfiniteExtension.globalCharacter_admissible + integerCoordinateExtension E D character hclosed hlocal -/-! ## Specialization of the index type to the continuum well-order -/ - -/-- The generic theorem applies directly to the canonical continuum index constructed in -`TriangularPreprocess`. Concrete fusion data only has to fill the fields of `Data`. -/ +/-- Integer transfinite-extension data over the canonical continuum index. -/ abbrev ContinuumData := Data TriangularPreprocess.ContinuumIndex end - end TransfiniteExtension end Wallace From 963d662cfdf290bf0fce73ff99ebbe976acb2f54 Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 4 Sep 2026 19:52:43 +0000 Subject: [PATCH 7/7] Deduplicate Wallace local fusion layers --- LeanPool/Wallace/BlockFilters.lean | 52 ++++++++++++- LeanPool/Wallace/ConcreteClosure.lean | 39 ++-------- LeanPool/Wallace/ConcreteData.lean | 41 +--------- LeanPool/Wallace/ConcreteFusionRun.lean | 14 ++-- LeanPool/Wallace/ConcreteLocalSetup.lean | 68 ++++------------- LeanPool/Wallace/CountableClosure.lean | 42 +++++++++- .../Wallace/CountableDisjointization.lean | 76 +++++++++++++++++++ LeanPool/Wallace/GlobalAssembly.lean | 1 + LeanPool/Wallace/LocalEnumeration.lean | 29 ++++--- LeanPool/Wallace/LocalFusion.lean | 64 +++++++++------- LeanPool/Wallace/RationalAssembly.lean | 1 + LeanPool/Wallace/RationalClosure.lean | 26 ++----- LeanPool/Wallace/RationalData.lean | 37 +-------- LeanPool/Wallace/RationalFusionRun.lean | 63 +++++---------- LeanPool/Wallace/RationalLocalSetup.lean | 68 ++++------------- LeanPool/Wallace/UniformKronecker.lean | 4 +- 16 files changed, 283 insertions(+), 342 deletions(-) diff --git a/LeanPool/Wallace/BlockFilters.lean b/LeanPool/Wallace/BlockFilters.lean index 4b7d70927..328bb3308 100644 --- a/LeanPool/Wallace/BlockFilters.lean +++ b/LeanPool/Wallace/BlockFilters.lean @@ -210,6 +210,52 @@ theorem exists_free_ultrafilter_le_densityFilter end BlockSystem +/-! ## Coefficient-independent block labels and ultrafilters -/ + +namespace BlockData + +open TriangularPreprocess + +/-- A fixed identification of the canonical continuum index with binary streams. -/ +def continuumIndexEquivBinaryStream : ContinuumIndex ≃ (ℕ → Bool) := by + apply Classical.choice + apply Cardinal.eq.mp + rw [mk_continuumIndex, Cardinal.mk_arrow, Cardinal.mk_bool, Cardinal.mk_nat] + simp only [Cardinal.lift_id, Cardinal.two_power_aleph0] + +/-- The almost-disjoint block label assigned to a sequence code. -/ +def label (a : ContinuumIndex) : Set ℕ := + binaryBranchOnNat (continuumIndexEquivBinaryStream a) + +theorem label_infinite (a : ContinuumIndex) : (label a).Infinite := + binaryBranchOnNat_infinite _ + +theorem label_inter_finite {a b : ContinuumIndex} (hab : a ≠ b) : + (label a ∩ label b).Finite := by + apply binaryBranchOnNat_inter_finite + exact continuumIndexEquivBinaryStream.injective.ne hab + +variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) + +/-- The block system with the prescribed sizes. -/ +abbrev blocks : BlockSystem := BlockSystem.ofBlockPositions N hN + +/-- A free ultrafilter refining the density filter of a code's label. -/ +def ultrafilter (a : ContinuumIndex) : Ultrafilter ℕ := + Classical.choose ((blocks N hN).exists_free_ultrafilter_le_densityFilter (label_infinite a)) + +theorem ultrafilter_le_density (a : ContinuumIndex) : + (ultrafilter N hN a : Filter ℕ) ≤ (blocks N hN).densityFilter (label a) := + (Classical.choose_spec + ((blocks N hN).exists_free_ultrafilter_le_densityFilter (label_infinite a))).1 + +theorem ultrafilter_free (a : ContinuumIndex) : + (ultrafilter N hN a : Filter ℕ) ≤ cofinite := + (Classical.choose_spec + ((blocks N hN).exists_free_ultrafilter_le_densityFilter (label_infinite a))).2 + +end BlockData + namespace AlmostDisjoint variable {ι α : Type*} @@ -302,7 +348,7 @@ filter. The hypothesis `a \ b` finite records `b =* a` together with `b ⊆ a`, the precise direction needed for the limit along `a`. -/ theorem retainedBlocks_mem_densityFilter (B : BlockSystem) {a b : Set ℕ} (E : ℕ → Finset ℕ) (R : ℕ → ℕ) - (hab : (a \ b).Finite) (_hE : ∀ l, E l ⊆ B.block l) + (hab : (a \ b).Finite) (hcard : ∀ l ∈ b, (E l).card ≤ R l) (hratio : Tendsto (fun l ↦ (R l : ℝ) / ((B.block l).card : ℝ)) atTop (nhds 0)) : B.retainedBlocks b E ∈ B.densityFilter a := by @@ -329,12 +375,12 @@ prescribed paper size `N l`, by `blockPositions_card`. -/ theorem retainedBlocks_mem_densityFilter_ofBlockPositions (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) {a b : Set ℕ} (E : ℕ → Finset ℕ) (R : ℕ → ℕ) - (hab : (a \ b).Finite) (hE : ∀ l, E l ⊆ (ofBlockPositions N hN).block l) + (hab : (a \ b).Finite) (hcard : ∀ l ∈ b, (E l).card ≤ R l) (hratio : Tendsto (fun l ↦ (R l : ℝ) / (N l : ℝ)) atTop (nhds 0)) : (ofBlockPositions N hN).retainedBlocks b E ∈ (ofBlockPositions N hN).densityFilter a := by - apply (ofBlockPositions N hN).retainedBlocks_mem_densityFilter E R hab hE hcard + apply (ofBlockPositions N hN).retainedBlocks_mem_densityFilter E R hab hcard simpa only [ofBlockPositions_card] using hratio end BlockSystem diff --git a/LeanPool/Wallace/ConcreteClosure.lean b/LeanPool/Wallace/ConcreteClosure.lean index 56db43176..ed854ba2f 100644 --- a/LeanPool/Wallace/ConcreteClosure.lean +++ b/LeanPool/Wallace/ConcreteClosure.lean @@ -28,38 +28,24 @@ open ConcreteData variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) -/-- All coordinates occurring in the prepared sequence attached to `a`. -/ -def dependency (a : ContinuumIndex) : Set ContinuumIndex := - ⋃ n, ↑(prepared N hN M a n).support - -theorem dependency_countable (a : ContinuumIndex) : - (dependency N hN M a).Countable := by - apply Set.countable_iUnion - intro n - exact (prepared N hN M a n).support.finite_toSet.countable - /-- The least closure obtained in finitely many dependency steps from the support of `x`. -/ def closure (x : ContinuumFreeGroup) : Set ContinuumIndex := - dependencyClosure codeIndex (dependency N hN M) ↑x.support + preparedClosure codeIndex (prepared N hN M) x theorem support_subset_closure (x : ContinuumFreeGroup) : ↑x.support ⊆ closure N hN M x := - subset_dependencyClosure codeIndex (dependency N hN M) ↑x.support + support_subset_preparedClosure codeIndex (prepared N hN M) x theorem closure_countable (x : ContinuumFreeGroup) : - (closure N hN M x).Countable := by - apply countable_dependencyClosure codeIndex (dependency N hN M) - · exact dependency_countable N hN M - · exact x.support.finite_toSet.countable + (closure N hN M x).Countable := + preparedClosure_countable codeIndex (prepared N hN M) x /-- The closure contains every coordinate of each relevant prepared sequence. -/ theorem prepared_support_mem_closure (x : ContinuumFreeGroup) (a : ContinuumIndex) (ha : codeIndex a ∈ closure N hN M x) (n : ℕ) (i : ContinuumIndex) (hi : i ∈ (prepared N hN M a n).support) : - i ∈ closure N hN M x := by - apply dependency_subset_closure_of_index_mem - codeIndex (dependency N hN M) ↑x.support ha - exact Set.mem_iUnion_of_mem n hi + i ∈ closure N hN M x := + preparedSupport_subset_preparedClosure codeIndex (prepared N hN M) x a ha n hi theorem closure_closedUnderPreparedSupports (x : ContinuumFreeGroup) : TransfiniteExtension.ClosedUnderPreparedSupports @@ -67,19 +53,6 @@ theorem closure_closedUnderPreparedSupports (x : ContinuumFreeGroup) : intro a ha n i hi exact prepared_support_mem_closure N hN M x a ha n i hi -/-- A nonzero vector gives a nonempty coordinate closure. -/ -theorem closure_nonempty {x : ContinuumFreeGroup} (hx : x ≠ 0) : - (closure N hN M x).Nonempty := by - obtain ⟨i, hi⟩ := Finsupp.support_nonempty_iff.mpr hx - exact ⟨i, support_subset_closure N hN M x hi⟩ - -/-- A fixed surjective enumeration of a nonempty concrete closure. -/ -def enumeration {x : ContinuumFreeGroup} (hx : x ≠ 0) : - ℕ → closure N hN M x := by - letI : Countable (closure N hN M x) := (closure_countable N hN M x).to_subtype - letI : Nonempty (closure N hN M x) := (closure_nonempty N hN M hx).to_subtype - exact Classical.choose (exists_surjective_nat (closure N hN M x)) - end end ConcreteClosure diff --git a/LeanPool/Wallace/ConcreteData.lean b/LeanPool/Wallace/ConcreteData.lean index d3cdf0d7b..4bb787a36 100644 --- a/LeanPool/Wallace/ConcreteData.lean +++ b/LeanPool/Wallace/ConcreteData.lean @@ -28,29 +28,9 @@ namespace ConcreteData noncomputable section open TriangularPreprocess +open BlockData open FiniteCombinatorics -/-! ## Almost-disjoint labels indexed by the triangular codes -/ - -/-- The canonical continuum index is in bijection with the binary streams. -/ -def continuumIndexEquivBinaryStream : ContinuumIndex ≃ (ℕ → Bool) := by - apply Classical.choice - apply Cardinal.eq.mp - rw [mk_continuumIndex, Cardinal.mk_arrow, Cardinal.mk_bool, Cardinal.mk_nat] - simp only [Cardinal.lift_id, Cardinal.two_power_aleph0] - -/-- The almost-disjoint set of block labels assigned to a code. -/ -def label (a : ContinuumIndex) : Set ℕ := - binaryBranchOnNat (continuumIndexEquivBinaryStream a) - -theorem label_infinite (a : ContinuumIndex) : (label a).Infinite := - binaryBranchOnNat_infinite _ - -theorem label_inter_finite {a b : ContinuumIndex} (hab : a ≠ b) : - (label a ∩ label b).Finite := by - apply binaryBranchOnNat_inter_finite - exact continuumIndexEquivBinaryStream.injective.ne hab - /-! ## The globally prepared sequences -/ variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) @@ -90,25 +70,6 @@ theorem preparedDifference_injective (a : ContinuumIndex) : apply prepared_injective N hN M a exact sub_left_injective hmn -/-! ## The fixed free ultrafilters -/ - -/-- The block system determined by the prescribed sizes. -/ -abbrev blocks : BlockSystem := BlockSystem.ofBlockPositions N hN - -/-- A free ultrafilter extending the density filter assigned to code `a`. -/ -def ultrafilter (a : ContinuumIndex) : Ultrafilter ℕ := - Classical.choose ((blocks N hN).exists_free_ultrafilter_le_densityFilter (label_infinite a)) - -theorem ultrafilter_le_density (a : ContinuumIndex) : - (ultrafilter N hN a : Filter ℕ) ≤ (blocks N hN).densityFilter (label a) := - (Classical.choose_spec - ((blocks N hN).exists_free_ultrafilter_le_densityFilter (label_infinite a))).1 - -theorem ultrafilter_free (a : ContinuumIndex) : - (ultrafilter N hN a : Filter ℕ) ≤ cofinite := - (Classical.choose_spec - ((blocks N hN).exists_free_ultrafilter_le_densityFilter (label_infinite a))).2 - /-! ## Packaging for the transfinite extension -/ /-- The concrete triangular data used by the transfinite recursion. -/ diff --git a/LeanPool/Wallace/ConcreteFusionRun.lean b/LeanPool/Wallace/ConcreteFusionRun.lean index ed90ce717..32756ffec 100644 --- a/LeanPool/Wallace/ConcreteFusionRun.lean +++ b/LeanPool/Wallace/ConcreteFusionRun.lean @@ -23,6 +23,7 @@ namespace ConcreteFusionRun noncomputable section open TriangularPreprocess +open BlockData open ConcreteData open ConcreteClosure open ConcreteLocalSetup @@ -53,7 +54,8 @@ abbrev fresh (x : ContinuumFreeGroup) : ℕ → Finset (LocalGroup x) := /-- A fixed enumeration of the countable local group. -/ abbrev enumeration (x : ContinuumFreeGroup) : ℕ → LocalGroup x := - groupEnumeration blockSize blockSize_pos independenceBound x + countableFinsuppEnumeration (localCarrier x) + (closure_countable blockSize blockSize_pos independenceBound x) /-- The restriction of `x` to its local coordinate closure. -/ def distinguished (x : ContinuumFreeGroup) : LocalGroup x := by @@ -78,7 +80,8 @@ def scheduledCertificate (x : {x : ContinuumFreeGroup // x ≠ 0}) : (distinguished_ne_zero x.2) (localActiveBlock_card_le blockSize blockSize_pos independenceBound x.1) (localActiveBlock_boundedIndependent blockSize blockSize_pos independenceBound x.1) - (groupEnumeration_surjective blockSize blockSize_pos independenceBound x.1) + (countableFinsuppEnumeration_surjective (localCarrier x.1) + (closure_countable blockSize blockSize_pos independenceBound x.1)) /-- The certified fusion run attached to a nonzero vector. -/ abbrev run (x : {x : ContinuumFreeGroup // x ≠ 0}) : @@ -96,12 +99,6 @@ def deletedPositions (x : {x : ContinuumFreeGroup // x ≠ 0}) localDifference blockSize blockSize_pos independenceBound x.1 a n ∉ (run x).retained l -theorem deletedPositions_subset_block (x : {x : ContinuumFreeGroup // x ≠ 0}) - (a : RelevantCode blockSize blockSize_pos independenceBound x.1) (l : ℕ) : - deletedPositions x a l ⊆ blockPositions blockSize blockSize_pos l := by - intro n hn - exact (Finset.mem_filter.mp hn).1 - private theorem image_deletedPositions (x : {x : ContinuumFreeGroup // x ≠ 0}) (a : RelevantCode blockSize blockSize_pos independenceBound x.1) (l : ℕ) : (deletedPositions x a l).image @@ -163,7 +160,6 @@ theorem retainedPositions_mem_ultrafilter FusionSchedule.protectedBound · exact label_diff_refinedLabel_finite blockSize blockSize_pos independenceBound x.1 a - · exact deletedPositions_subset_block x a · exact deletedPositions_card_le x a · exact FusionSchedule.tendsto_protectedBound_div_blockSize diff --git a/LeanPool/Wallace/ConcreteLocalSetup.lean b/LeanPool/Wallace/ConcreteLocalSetup.lean index 3018593dc..ad9dbe991 100644 --- a/LeanPool/Wallace/ConcreteLocalSetup.lean +++ b/LeanPool/Wallace/ConcreteLocalSetup.lean @@ -26,6 +26,7 @@ namespace ConcreteLocalSetup noncomputable section open TriangularPreprocess +open BlockData open ConcreteData open ConcreteClosure open FiniteCombinatorics @@ -34,74 +35,31 @@ variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) /-- Codes whose prescribed basis coordinate belongs to the local dependency closure of `x`. -/ abbrev RelevantCode (x : ContinuumFreeGroup) := - {a : ContinuumIndex // codeIndex a ∈ closure N hN M x} - -theorem relevantCode_countable (x : ContinuumFreeGroup) : - Countable (RelevantCode N hN M x) := by - apply Countable.to_subtype - exact countable_preimage_of_injective codeIndex (closure_countable N hN M x) - -private theorem relevantLabels_pairwise (x : ContinuumFreeGroup) : - Pairwise fun a b : RelevantCode N hN M x ↦ - (label a.1 ∩ label b.1).Finite := by - intro a b hab - apply label_inter_finite - intro heq - apply hab - exact Subtype.ext heq + LocalCodeSchedule.RelevantCode codeIndex (closure N hN M x) /-- Pairwise disjoint labels obtained by deleting finitely many points from each relevant almost-disjoint label. -/ def refinedLabel (x : ContinuumFreeGroup) : RelevantCode N hN M x → Set ℕ := by - letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x - exact Classical.choose - (exists_disjoint_refinement_countable - (fun a : RelevantCode N hN M x ↦ label a.1) - (relevantLabels_pairwise N hN M x)) - -theorem refinedLabel_pairwise (x : ContinuumFreeGroup) : - Pairwise fun a b : RelevantCode N hN M x ↦ - Disjoint (refinedLabel N hN M x a) (refinedLabel N hN M x b) := by - let : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x - exact (Classical.choose_spec - (exists_disjoint_refinement_countable - (fun a : RelevantCode N hN M x ↦ label a.1) - (relevantLabels_pairwise N hN M x))).1 + exact LocalCodeSchedule.refinedLabel + codeIndex (closure N hN M x) (closure_countable N hN M x) theorem label_diff_refinedLabel_finite (x : ContinuumFreeGroup) (a : RelevantCode N hN M x) : - (label a.1 \ refinedLabel N hN M x a).Finite := by - let : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x - exact (Classical.choose_spec - (exists_disjoint_refinement_countable - (fun a : RelevantCode N hN M x ↦ label a.1) - (relevantLabels_pairwise N hN M x))).2 a |>.2 - -theorem refinedLabel_unique (x : ContinuumFreeGroup) {l : ℕ} - {a b : RelevantCode N hN M x} - (ha : l ∈ refinedLabel N hN M x a) - (hb : l ∈ refinedLabel N hN M x b) : a = b := by - by_contra hab - exact Set.disjoint_left.mp (refinedLabel_pairwise N hN M x hab) ha hb + (label a.1 \ refinedLabel N hN M x a).Finite := + LocalCodeSchedule.label_diff_refinedLabel_finite + codeIndex (closure N hN M x) (closure_countable N hN M x) a /-- The unique relevant code scheduled at label `l`, if there is one. -/ def activeCode (x : ContinuumFreeGroup) (l : ℕ) : - Option (RelevantCode N hN M x) := by - classical - exact if h : ∃ a, l ∈ refinedLabel N hN M x a then - some (Classical.choose h) else none + Option (RelevantCode N hN M x) := + LocalCodeSchedule.activeCode codeIndex + (closure N hN M x) (closure_countable N hN M x) l theorem activeCode_eq_some_of_mem (x : ContinuumFreeGroup) (l : ℕ) (a : RelevantCode N hN M x) (ha : l ∈ refinedLabel N hN M x a) : - activeCode N hN M x l = some a := by - classical - unfold activeCode - split - · rename_i h - congr 1 - exact refinedLabel_unique N hN M x (Classical.choose_spec h) ha - · rename_i h - exact (h ⟨a, ha⟩).elim + activeCode N hN M x l = some a := + LocalCodeSchedule.activeCode_eq_some_of_mem + codeIndex (closure N hN M x) (closure_countable N hN M x) l a ha /-! ## Restriction to the countable local free group -/ diff --git a/LeanPool/Wallace/CountableClosure.lean b/LeanPool/Wallace/CountableClosure.lean index b9df70159..7e9b6b55f 100644 --- a/LeanPool/Wallace/CountableClosure.lean +++ b/LeanPool/Wallace/CountableClosure.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues -/ +import Mathlib.Data.Finsupp.Defs import Mathlib.Data.Set.Countable /-! @@ -16,7 +17,7 @@ whose indices it contains still takes only countably many new coordinates at eac open Set -universe u v +universe u v w namespace Wallace @@ -83,6 +84,45 @@ theorem countable_dependencyClosure | zero => exact hD₀ | succ n ih => exact countable_dependencyClosureStep index dependency hdep ih +/-! ## Prepared-support specialization -/ + +variable {R : Type w} [Zero R] + +/-- All coordinates occurring in the prepared sequence attached to a code. -/ +def preparedDependency (prepared : Code → ℕ → I →₀ R) (c : Code) : Set I := + ⋃ n, ↑(prepared c n).support + +theorem preparedDependency_countable (prepared : Code → ℕ → I →₀ R) (c : Code) : + (preparedDependency prepared c).Countable := by + apply Set.countable_iUnion + intro n + exact (prepared c n).support.finite_toSet.countable + +/-- The dependency closure generated by the support of a finitely supported vector. -/ +def preparedClosure (index : Code ↪ I) (prepared : Code → ℕ → I →₀ R) + (x : I →₀ R) : Set I := + dependencyClosure index (preparedDependency prepared) ↑x.support + +theorem support_subset_preparedClosure (index : Code ↪ I) + (prepared : Code → ℕ → I →₀ R) (x : I →₀ R) : + ↑x.support ⊆ preparedClosure index prepared x := + subset_dependencyClosure index (preparedDependency prepared) ↑x.support + +theorem preparedClosure_countable (index : Code ↪ I) + (prepared : Code → ℕ → I →₀ R) (x : I →₀ R) : + (preparedClosure index prepared x).Countable := + countable_dependencyClosure index (preparedDependency prepared) + (preparedDependency_countable prepared) x.support.finite_toSet.countable + +/-- The closure contains every coordinate in a prepared sequence whose code index it contains. -/ +theorem preparedSupport_subset_preparedClosure (index : Code ↪ I) + (prepared : Code → ℕ → I →₀ R) (x : I →₀ R) (c : Code) + (hc : index c ∈ preparedClosure index prepared x) (n : ℕ) : + ↑(prepared c n).support ⊆ preparedClosure index prepared x := by + intro i hi + exact dependency_subset_closure_of_index_mem + index (preparedDependency prepared) ↑x.support hc (Set.mem_iUnion_of_mem n hi) + end end Wallace diff --git a/LeanPool/Wallace/CountableDisjointization.lean b/LeanPool/Wallace/CountableDisjointization.lean index fd29a9b1a..324d025c9 100644 --- a/LeanPool/Wallace/CountableDisjointization.lean +++ b/LeanPool/Wallace/CountableDisjointization.lean @@ -47,6 +47,82 @@ theorem exists_disjoint_refinement_countable intro i exact ⟨disjointize_subset family i, disjointize_loss_finite family had i (hpred i)⟩ +/-! ## Scheduling the relevant Wallace codes -/ + +namespace LocalCodeSchedule + +open BlockData TriangularPreprocess + +/-- Codes whose distinguished coordinate belongs to a given coordinate set. -/ +abbrev RelevantCode (index : ContinuumIndex ↪ ContinuumIndex) (D : Set ContinuumIndex) := + {a : ContinuumIndex // index a ∈ D} + +private theorem relevantCode_countable (index : ContinuumIndex ↪ ContinuumIndex) + (D : Set ContinuumIndex) (hD : D.Countable) : Countable (RelevantCode index D) := by + apply Countable.to_subtype + exact hD.preimage index.injective + +private theorem relevantLabels_pairwise (index : ContinuumIndex ↪ ContinuumIndex) + (D : Set ContinuumIndex) : + Pairwise fun a b : RelevantCode index D ↦ (label a.1 ∩ label b.1).Finite := by + intro a b hab + apply label_inter_finite + exact fun heq ↦ hab (Subtype.ext heq) + +/-- Pairwise-disjoint refinements of the labels of all codes relevant to `D`. -/ +def refinedLabel (index : ContinuumIndex ↪ ContinuumIndex) + (D : Set ContinuumIndex) (hD : D.Countable) : RelevantCode index D → Set ℕ := by + let : Countable (RelevantCode index D) := relevantCode_countable index D hD + exact Classical.choose + (exists_disjoint_refinement_countable + (fun a : RelevantCode index D ↦ label a.1) (relevantLabels_pairwise index D)) + +theorem refinedLabel_pairwise (index : ContinuumIndex ↪ ContinuumIndex) + (D : Set ContinuumIndex) (hD : D.Countable) : + Pairwise fun a b : RelevantCode index D ↦ + Disjoint (refinedLabel index D hD a) (refinedLabel index D hD b) := by + let : Countable (RelevantCode index D) := relevantCode_countable index D hD + exact (Classical.choose_spec + (exists_disjoint_refinement_countable + (fun a : RelevantCode index D ↦ label a.1) (relevantLabels_pairwise index D))).1 + +theorem label_diff_refinedLabel_finite (index : ContinuumIndex ↪ ContinuumIndex) + (D : Set ContinuumIndex) (hD : D.Countable) (a : RelevantCode index D) : + (label a.1 \ refinedLabel index D hD a).Finite := by + let : Countable (RelevantCode index D) := relevantCode_countable index D hD + exact (Classical.choose_spec + (exists_disjoint_refinement_countable + (fun a : RelevantCode index D ↦ label a.1) (relevantLabels_pairwise index D))).2 a |>.2 + +private theorem refinedLabel_unique (index : ContinuumIndex ↪ ContinuumIndex) + (D : Set ContinuumIndex) (hD : D.Countable) {l : ℕ} + {a b : RelevantCode index D} (ha : l ∈ refinedLabel index D hD a) + (hb : l ∈ refinedLabel index D hD b) : a = b := by + by_contra hab + exact Set.disjoint_left.mp (refinedLabel_pairwise index D hD hab) ha hb + +/-- The unique relevant code scheduled at a label, when one exists. -/ +def activeCode (index : ContinuumIndex ↪ ContinuumIndex) + (D : Set ContinuumIndex) (hD : D.Countable) (l : ℕ) : + Option (RelevantCode index D) := by + classical + exact if h : ∃ a, l ∈ refinedLabel index D hD a then some (Classical.choose h) else none + +theorem activeCode_eq_some_of_mem (index : ContinuumIndex ↪ ContinuumIndex) + (D : Set ContinuumIndex) (hD : D.Countable) (l : ℕ) + (a : RelevantCode index D) (ha : l ∈ refinedLabel index D hD a) : + activeCode index D hD l = some a := by + classical + unfold activeCode + split + · rename_i h + congr 1 + exact refinedLabel_unique index D hD (Classical.choose_spec h) ha + · rename_i h + exact (h ⟨a, ha⟩).elim + +end LocalCodeSchedule + end end Wallace diff --git a/LeanPool/Wallace/GlobalAssembly.lean b/LeanPool/Wallace/GlobalAssembly.lean index 13f49f7ae..efc87abb7 100644 --- a/LeanPool/Wallace/GlobalAssembly.lean +++ b/LeanPool/Wallace/GlobalAssembly.lean @@ -27,6 +27,7 @@ noncomputable section open TriangularPreprocess open ConcreteData +open BlockData open ConcreteClosure open TransfiniteExtension diff --git a/LeanPool/Wallace/LocalEnumeration.lean b/LeanPool/Wallace/LocalEnumeration.lean index 9522badb9..a34fa0c7d 100644 --- a/LeanPool/Wallace/LocalEnumeration.lean +++ b/LeanPool/Wallace/LocalEnumeration.lean @@ -4,34 +4,31 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues -/ -import LeanPool.Wallace.ConcreteClosure import Mathlib.Data.Finsupp.Encodable +import Mathlib.Data.Set.Countable /-! -# Enumeration of a countable local free group +# Enumeration of a countable local direct sum -/ namespace Wallace -namespace ConcreteClosure noncomputable section -open TriangularPreprocess +universe u v -variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) +/-- A fixed surjective enumeration of the direct sum over a countable coordinate set. -/ +def countableFinsuppEnumeration {I : Type u} {R : Type v} [Zero R] [Countable R] + (D : Set I) (hD : D.Countable) : ℕ → (D →₀ R) := by + letI : Countable D := hD.to_subtype + exact Classical.choose (exists_surjective_nat (D →₀ R)) -/-- A fixed surjective enumeration of every local free group. -/ -def groupEnumeration (x : ContinuumFreeGroup) : - ℕ → (closure N hN M x →₀ ℤ) := by - letI : Countable (closure N hN M x) := (closure_countable N hN M x).to_subtype - exact Classical.choose (exists_surjective_nat (closure N hN M x →₀ ℤ)) - -theorem groupEnumeration_surjective (x : ContinuumFreeGroup) : - Function.Surjective (groupEnumeration N hN M x) := by - let : Countable (closure N hN M x) := (closure_countable N hN M x).to_subtype - exact Classical.choose_spec (exists_surjective_nat (closure N hN M x →₀ ℤ)) +theorem countableFinsuppEnumeration_surjective {I : Type u} {R : Type v} + [Zero R] [Countable R] (D : Set I) (hD : D.Countable) : + Function.Surjective (countableFinsuppEnumeration D hD : ℕ → (D →₀ R)) := by + let : Countable D := hD.to_subtype + exact Classical.choose_spec (exists_surjective_nat (D →₀ R)) end -end ConcreteClosure end Wallace diff --git a/LeanPool/Wallace/LocalFusion.lean b/LeanPool/Wallace/LocalFusion.lean index a302827e6..58b34c696 100644 --- a/LeanPool/Wallace/LocalFusion.lean +++ b/LeanPool/Wallace/LocalFusion.lean @@ -260,6 +260,34 @@ theorem tendsto_limit_prepared (R : FusionRun G) (B : CodeBlocks R) simpa using hzero.add_const (R.limitCharacter basis) exact hadd.congr' (Eventually.of_forall fun n ↦ (heq n).symm) +/-- A block certificate whose abstract fields are identified with a particular prepared +sequence, ultrafilter, and block partition. -/ +structure PreparedCodeBlocks (R : FusionRun G) (p : Ultrafilter ℕ) + (block : ℕ → Finset ℕ) (difference : ℕ → G) where + /-- The underlying retained-block data. -/ + blocks : R.CodeBlocks + p_eq : blocks.p = p + block_eq : ∀ l, blocks.block l = block l + difference_eq : ∀ n, blocks.difference n = difference n + +/-- A prepared block certificate supplies the corresponding ultrafilter limit. -/ +theorem PreparedCodeBlocks.tendsto_prepared + {R : FusionRun G} {p : Ultrafilter ℕ} {block : ℕ → Finset ℕ} + {difference prepared : ℕ → G} {basis : G} + (C : PreparedCodeBlocks R p block difference) + (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) + (hp : (p : Filter ℕ) ≤ cofinite) + (hblock : ∀ l, block l = TriangularPreprocess.blockPositions N hN l) + (hdifference : ∀ n, difference n = prepared n - basis) : + Tendsto (fun n ↦ R.limitCharacter (prepared n)) p + (nhds (R.limitCharacter basis)) := by + have hp' : (C.blocks.p : Filter ℕ) ≤ cofinite := by simpa only [C.p_eq] using hp + have hzero := R.tendsto_limit_difference_zero_of_blockPositions + C.blocks N hN hp' fun l ↦ (C.block_eq l).trans (hblock l) + have hprepared := R.tendsto_limit_prepared C.blocks prepared basis + (fun n ↦ (C.difference_eq n).trans (hdifference n)) hzero + simpa only [C.p_eq] using hprepared + end FusionRun /-! ## A generic concrete scheduling recursion -/ @@ -527,22 +555,16 @@ theorem exists_scheduledRunCertificate /-! ## Interface from concrete runs to the global assembly -/ -open TriangularPreprocess ConcreteData ConcreteClosure ConcreteLocalSetup +open TriangularPreprocess BlockData ConcreteData ConcreteClosure ConcreteLocalSetup -/-- The block certificate for one code in the countable closure. In addition to the analytic -`CodeBlocks` data it identifies the abstract fields with the concrete prepared sequence, -ultrafilter, and block partition. -/ -structure ConcreteCodeBlocks +/-- Integer specialization of the shared prepared-block certificate. -/ +abbrev ConcreteCodeBlocks (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) (x : ContinuumFreeGroup) (R : FusionRun (closure N hN M x →₀ ℤ)) - (a : RelevantCode N hN M x) where - /-- The underlying abstract retained-block data. -/ - blocks : R.CodeBlocks - p_eq : blocks.p = ultrafilter N hN a.1 - block_eq : ∀ l, blocks.block l = blockPositions N hN l - difference_eq : ∀ n, - blocks.difference n = localDifference N hN M x a n + (a : RelevantCode N hN M x) := + R.PreparedCodeBlocks (ultrafilter N hN a.1) (blockPositions N hN) + (localDifference N hN M x a) namespace ConcreteCodeBlocks @@ -559,16 +581,10 @@ theorem tendsto_prepared (Finsupp.subtypeDomain (closure N hN M x) (prepared N hN M a.1 n))) (ultrafilter N hN a.1) (nhds (R.limitCharacter (Finsupp.single ⟨codeIndex a.1, a.2⟩ 1))) := by - have hp : (C.blocks.p : Filter ℕ) ≤ cofinite := by - rw [C.p_eq] - exact ultrafilter_free N hN a.1 - have hzero := R.tendsto_limit_difference_zero_of_blockPositions - C.blocks N hN hp C.block_eq - have hdifference : ∀ n, C.blocks.difference n = - Finsupp.subtypeDomain (closure N hN M x) (prepared N hN M a.1 n) - - Finsupp.single ⟨codeIndex a.1, a.2⟩ 1 := by - intro n - rw [C.difference_eq] + apply FusionRun.PreparedCodeBlocks.tendsto_prepared C N hN + · exact ultrafilter_free N hN a.1 + · exact fun _ ↦ rfl + · intro n simp only [localDifference] ext i change prepared N hN M a.1 n i.val - codeBasisVector a.1 i.val = @@ -582,10 +598,6 @@ theorem tendsto_prepared intro heq exact hi (congrArg Subtype.val heq) simp [codeBasisVector, hi, hisub] - have hprepared := R.tendsto_limit_prepared C.blocks - (fun n ↦ Finsupp.subtypeDomain (closure N hN M x) (prepared N hN M a.1 n)) - (Finsupp.single ⟨codeIndex a.1, a.2⟩ 1) hdifference hzero - simpa only [C.p_eq] using hprepared end ConcreteCodeBlocks diff --git a/LeanPool/Wallace/RationalAssembly.lean b/LeanPool/Wallace/RationalAssembly.lean index 3f87b6ea3..f94efe949 100644 --- a/LeanPool/Wallace/RationalAssembly.lean +++ b/LeanPool/Wallace/RationalAssembly.lean @@ -24,6 +24,7 @@ noncomputable section open RationalTriangularPreprocess open RationalData +open BlockData open RationalClosure open RationalFusionRun open RationalTransfiniteExtension diff --git a/LeanPool/Wallace/RationalClosure.lean b/LeanPool/Wallace/RationalClosure.lean index abb811848..05749d657 100644 --- a/LeanPool/Wallace/RationalClosure.lean +++ b/LeanPool/Wallace/RationalClosure.lean @@ -26,37 +26,23 @@ open RationalData variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) -/-- Coordinates occurring in the prepared sequence represented by `a`. -/ -def dependency (a : ContinuumIndex) : Set ContinuumIndex := - ⋃ n, ↑(prepared N hN M a n).support - -theorem dependency_countable (a : ContinuumIndex) : - (dependency N hN M a).Countable := by - apply Set.countable_iUnion - intro n - exact (prepared N hN M a n).support.finite_toSet.countable - /-- Least finite-stage dependency closure of the support of `x`. -/ def closure (x : ContinuumRationalGroup) : Set ContinuumIndex := - dependencyClosure codeIndex (dependency N hN M) ↑x.support + preparedClosure codeIndex (prepared N hN M) x theorem support_subset_closure (x : ContinuumRationalGroup) : ↑x.support ⊆ closure N hN M x := - subset_dependencyClosure codeIndex (dependency N hN M) ↑x.support + support_subset_preparedClosure codeIndex (prepared N hN M) x theorem closure_countable (x : ContinuumRationalGroup) : - (closure N hN M x).Countable := by - apply countable_dependencyClosure codeIndex (dependency N hN M) - · exact dependency_countable N hN M - · exact x.support.finite_toSet.countable + (closure N hN M x).Countable := + preparedClosure_countable codeIndex (prepared N hN M) x theorem prepared_support_mem_closure (x : ContinuumRationalGroup) (a : ContinuumIndex) (ha : codeIndex a ∈ closure N hN M x) (n : ℕ) (i : ContinuumIndex) (hi : i ∈ (prepared N hN M a n).support) : - i ∈ closure N hN M x := by - apply dependency_subset_closure_of_index_mem - codeIndex (dependency N hN M) ↑x.support ha - exact Set.mem_iUnion_of_mem n hi + i ∈ closure N hN M x := + preparedSupport_subset_preparedClosure codeIndex (prepared N hN M) x a ha n hi theorem closure_closedUnderPreparedSupports (x : ContinuumRationalGroup) : RationalTransfiniteExtension.ClosedUnderPreparedSupports diff --git a/LeanPool/Wallace/RationalData.lean b/LeanPool/Wallace/RationalData.lean index 67b94c1f7..17c116d69 100644 --- a/LeanPool/Wallace/RationalData.lean +++ b/LeanPool/Wallace/RationalData.lean @@ -22,27 +22,9 @@ namespace RationalData noncomputable section open RationalTriangularPreprocess +open BlockData open FiniteCombinatorics -/-- The canonical continuum index is in bijection with binary streams. -/ -def continuumIndexEquivBinaryStream : ContinuumIndex ≃ (ℕ → Bool) := by - apply Classical.choice - apply Cardinal.eq.mp - rw [mk_continuumIndex, Cardinal.mk_arrow, Cardinal.mk_bool, Cardinal.mk_nat] - simp only [Cardinal.lift_id, Cardinal.two_power_aleph0] - -/-- Almost-disjoint block label assigned to a rational sequence code. -/ -def label (a : ContinuumIndex) : Set ℕ := - binaryBranchOnNat (continuumIndexEquivBinaryStream a) - -theorem label_infinite (a : ContinuumIndex) : (label a).Infinite := - binaryBranchOnNat_infinite _ - -theorem label_inter_finite {a b : ContinuumIndex} (hab : a ≠ b) : - (label a ∩ label b).Finite := by - apply binaryBranchOnNat_inter_finite - exact continuumIndexEquivBinaryStream.injective.ne hab - variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) /-- Strictly increasing selector supplied by rational block preprocessing. -/ @@ -79,23 +61,6 @@ theorem preparedDifference_injective (a : ContinuumIndex) : apply prepared_injective N hN M a exact sub_left_injective hmn -/-- The concrete block system used by the rational construction. -/ -abbrev blocks : BlockSystem := BlockSystem.ofBlockPositions N hN - -/-- A free ultrafilter refining the block-density filter for code `a`. -/ -def ultrafilter (a : ContinuumIndex) : Ultrafilter ℕ := - Classical.choose ((blocks N hN).exists_free_ultrafilter_le_densityFilter (label_infinite a)) - -theorem ultrafilter_le_density (a : ContinuumIndex) : - (ultrafilter N hN a : Filter ℕ) ≤ (blocks N hN).densityFilter (label a) := - (Classical.choose_spec - ((blocks N hN).exists_free_ultrafilter_le_densityFilter (label_infinite a))).1 - -theorem ultrafilter_free (a : ContinuumIndex) : - (ultrafilter N hN a : Filter ℕ) ≤ cofinite := - (Classical.choose_spec - ((blocks N hN).exists_free_ultrafilter_le_densityFilter (label_infinite a))).2 - /-- Concrete input for the rational transfinite recursion. -/ def transfiniteData : RationalTransfiniteExtension.ContinuumData where Code := ContinuumIndex diff --git a/LeanPool/Wallace/RationalFusionRun.lean b/LeanPool/Wallace/RationalFusionRun.lean index e29526291..2852a5abd 100644 --- a/LeanPool/Wallace/RationalFusionRun.lean +++ b/LeanPool/Wallace/RationalFusionRun.lean @@ -6,7 +6,7 @@ Authors: Juliane Trianon Fraga, Vinicius de Oliveira Rodrigues import LeanPool.Wallace.RationalLocalSetup import LeanPool.Wallace.LocalFusion -import Mathlib.Data.Finsupp.Encodable +import LeanPool.Wallace.LocalEnumeration /-! # The unconditional local fusion for the rational direct sum @@ -24,6 +24,7 @@ namespace RationalFusionRun noncomputable section open RationalTriangularPreprocess +open BlockData open RationalData open RationalClosure open RationalLocalSetup @@ -48,16 +49,9 @@ abbrev fresh (x : ContinuumRationalGroup) : ℕ → Finset (LocalGroup x) := localActiveBlock blockSize blockSize_pos independenceBound x /-- A fixed surjection used to make every local point eventually protected. -/ -def localEnumeration (x : ContinuumRationalGroup) : ℕ → LocalGroup x := by - letI : Countable (localCarrier x) := - (closure_countable blockSize blockSize_pos independenceBound x).to_subtype - exact Classical.choose (exists_surjective_nat (LocalGroup x)) - -theorem localEnumeration_surjective (x : ContinuumRationalGroup) : - Function.Surjective (localEnumeration x) := by - let : Countable (localCarrier x) := - (closure_countable blockSize blockSize_pos independenceBound x).to_subtype - exact Classical.choose_spec (exists_surjective_nat (LocalGroup x)) +abbrev localEnumeration (x : ContinuumRationalGroup) : ℕ → LocalGroup x := + countableFinsuppEnumeration (localCarrier x) + (closure_countable blockSize blockSize_pos independenceBound x) /-- The restriction of `x` to its local coordinate closure. -/ def distinguished (x : ContinuumRationalGroup) : LocalGroup x := by @@ -80,7 +74,8 @@ def scheduledCertificate (x : {x : ContinuumRationalGroup // x ≠ 0}) : (distinguished_ne_zero x.2) (localActiveBlock_card_le blockSize blockSize_pos independenceBound x.1) (localActiveBlock_boundedIndependent blockSize blockSize_pos independenceBound x.1) - (localEnumeration_surjective x.1) + (countableFinsuppEnumeration_surjective (localCarrier x.1) + (closure_countable blockSize blockSize_pos independenceBound x.1)) /-- The certified fusion run attached to a nonzero rational vector. -/ abbrev run (x : {x : ContinuumRationalGroup // x ≠ 0}) : @@ -93,13 +88,6 @@ def deletedPositions (x : {x : ContinuumRationalGroup // x ≠ 0}) (TriangularPreprocess.blockPositions blockSize blockSize_pos l).filter fun n ↦ localDifference blockSize blockSize_pos independenceBound x.1 a n ∉ (run x).retained l -theorem deletedPositions_subset_block - (x : {x : ContinuumRationalGroup // x ≠ 0}) - (a : RelevantCode blockSize blockSize_pos independenceBound x.1) (l : ℕ) : - deletedPositions x a l ⊆ TriangularPreprocess.blockPositions blockSize blockSize_pos l := by - intro n hn - exact (Finset.mem_filter.mp hn).1 - private theorem image_deletedPositions (x : {x : ContinuumRationalGroup // x ≠ 0}) (a : RelevantCode blockSize blockSize_pos independenceBound x.1) (l : ℕ) : @@ -155,23 +143,18 @@ theorem retainedPositions_mem_ultrafilter blockSize blockSize_pos (deletedPositions x a) FusionSchedule.protectedBound · exact label_diff_refinedLabel_finite blockSize blockSize_pos independenceBound x.1 a - · exact deletedPositions_subset_block x a · exact deletedPositions_card_le x a · exact FusionSchedule.tendsto_protectedBound_div_blockSize /-! ## Rational block and run certificates -/ -/-- Concrete retained-block data for one rational sequence code. -/ -structure RationalCodeBlocks +/-- Rational specialization of the shared prepared-block certificate. -/ +abbrev RationalCodeBlocks (x : ContinuumRationalGroup) (R : FusionRun (LocalGroup x)) - (a : RelevantCode blockSize blockSize_pos independenceBound x) where - /-- The underlying abstract retained-block data. -/ - blocks : R.CodeBlocks - p_eq : blocks.p = ultrafilter blockSize blockSize_pos a.1 - block_eq : ∀ l, blocks.block l = - TriangularPreprocess.blockPositions blockSize blockSize_pos l - difference_eq : ∀ n, - blocks.difference n = localDifference blockSize blockSize_pos independenceBound x a n + (a : RelevantCode blockSize blockSize_pos independenceBound x) := + R.PreparedCodeBlocks (ultrafilter blockSize blockSize_pos a.1) + (TriangularPreprocess.blockPositions blockSize blockSize_pos) + (localDifference blockSize blockSize_pos independenceBound x a) namespace RationalCodeBlocks @@ -185,17 +168,10 @@ theorem tendsto_prepared (prepared blockSize blockSize_pos independenceBound a.1 n))) (ultrafilter blockSize blockSize_pos a.1) (nhds (R.limitCharacter (Finsupp.single ⟨codeIndex a.1, a.2⟩ 1))) := by - have hp : (C.blocks.p : Filter ℕ) ≤ cofinite := by - rw [C.p_eq] - exact ultrafilter_free blockSize blockSize_pos a.1 - have hzero := R.tendsto_limit_difference_zero_of_blockPositions - C.blocks blockSize blockSize_pos hp C.block_eq - have hdifference : ∀ n, C.blocks.difference n = - Finsupp.subtypeDomain (localCarrier x) - (prepared blockSize blockSize_pos independenceBound a.1 n) - - Finsupp.single ⟨codeIndex a.1, a.2⟩ 1 := by - intro n - rw [C.difference_eq] + apply FusionRun.PreparedCodeBlocks.tendsto_prepared C blockSize blockSize_pos + · exact ultrafilter_free blockSize blockSize_pos a.1 + · exact fun _ ↦ rfl + · intro n simp only [localDifference] ext i change prepared blockSize blockSize_pos independenceBound a.1 n i.val - @@ -210,11 +186,6 @@ theorem tendsto_prepared intro heq exact hi (congrArg Subtype.val heq) simp [codeBasisVector, hi, hisub] - have hprepared := R.tendsto_limit_prepared C.blocks - (fun n ↦ Finsupp.subtypeDomain (localCarrier x) - (prepared blockSize blockSize_pos independenceBound a.1 n)) - (Finsupp.single ⟨codeIndex a.1, a.2⟩ 1) hdifference hzero - simpa only [C.p_eq] using hprepared end RationalCodeBlocks diff --git a/LeanPool/Wallace/RationalLocalSetup.lean b/LeanPool/Wallace/RationalLocalSetup.lean index 9cdcebb04..fe0505c41 100644 --- a/LeanPool/Wallace/RationalLocalSetup.lean +++ b/LeanPool/Wallace/RationalLocalSetup.lean @@ -25,6 +25,7 @@ namespace RationalLocalSetup noncomputable section open RationalTriangularPreprocess +open BlockData open RationalData open RationalClosure open FiniteCombinatorics @@ -33,74 +34,31 @@ variable (N : ℕ → ℕ) (hN : ∀ l, 0 < N l) (M : ℕ → ℕ) /-- Codes whose distinguished coordinate lies in the local closure of `x`. -/ abbrev RelevantCode (x : ContinuumRationalGroup) := - {a : ContinuumIndex // codeIndex a ∈ closure N hN M x} - -theorem relevantCode_countable (x : ContinuumRationalGroup) : - Countable (RelevantCode N hN M x) := by - apply Countable.to_subtype - exact countable_preimage_of_injective codeIndex (closure_countable N hN M x) - -private theorem relevantLabels_pairwise (x : ContinuumRationalGroup) : - Pairwise fun a b : RelevantCode N hN M x ↦ - (label a.1 ∩ label b.1).Finite := by - intro a b hab - apply label_inter_finite - intro heq - apply hab - exact Subtype.ext heq + LocalCodeSchedule.RelevantCode codeIndex (closure N hN M x) /-- Pairwise-disjoint refinements of the block labels of all relevant codes. -/ def refinedLabel (x : ContinuumRationalGroup) : RelevantCode N hN M x → Set ℕ := by - letI : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x - exact Classical.choose - (exists_disjoint_refinement_countable - (fun a : RelevantCode N hN M x ↦ label a.1) - (relevantLabels_pairwise N hN M x)) - -theorem refinedLabel_pairwise (x : ContinuumRationalGroup) : - Pairwise fun a b : RelevantCode N hN M x ↦ - Disjoint (refinedLabel N hN M x a) (refinedLabel N hN M x b) := by - let : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x - exact (Classical.choose_spec - (exists_disjoint_refinement_countable - (fun a : RelevantCode N hN M x ↦ label a.1) - (relevantLabels_pairwise N hN M x))).1 + exact LocalCodeSchedule.refinedLabel + codeIndex (closure N hN M x) (closure_countable N hN M x) theorem label_diff_refinedLabel_finite (x : ContinuumRationalGroup) (a : RelevantCode N hN M x) : - (label a.1 \ refinedLabel N hN M x a).Finite := by - let : Countable (RelevantCode N hN M x) := relevantCode_countable N hN M x - exact (Classical.choose_spec - (exists_disjoint_refinement_countable - (fun a : RelevantCode N hN M x ↦ label a.1) - (relevantLabels_pairwise N hN M x))).2 a |>.2 - -theorem refinedLabel_unique (x : ContinuumRationalGroup) {l : ℕ} - {a b : RelevantCode N hN M x} - (ha : l ∈ refinedLabel N hN M x a) - (hb : l ∈ refinedLabel N hN M x b) : a = b := by - by_contra hab - exact Set.disjoint_left.mp (refinedLabel_pairwise N hN M x hab) ha hb + (label a.1 \ refinedLabel N hN M x a).Finite := + LocalCodeSchedule.label_diff_refinedLabel_finite + codeIndex (closure N hN M x) (closure_countable N hN M x) a /-- The unique relevant code assigned to stage `l`, when one exists. -/ def activeCode (x : ContinuumRationalGroup) (l : ℕ) : - Option (RelevantCode N hN M x) := by - classical - exact if h : ∃ a, l ∈ refinedLabel N hN M x a then - some (Classical.choose h) else none + Option (RelevantCode N hN M x) := + LocalCodeSchedule.activeCode codeIndex + (closure N hN M x) (closure_countable N hN M x) l theorem activeCode_eq_some_of_mem (x : ContinuumRationalGroup) (l : ℕ) (a : RelevantCode N hN M x) (ha : l ∈ refinedLabel N hN M x a) : - activeCode N hN M x l = some a := by - classical - unfold activeCode - split - · rename_i h - congr 1 - exact refinedLabel_unique N hN M x (Classical.choose_spec h) ha - · rename_i h - exact (h ⟨a, ha⟩).elim + activeCode N hN M x l = some a := + LocalCodeSchedule.activeCode_eq_some_of_mem + codeIndex (closure N hN M x) (closure_countable N hN M x) l a ha /-! ## The countable local rational group -/ diff --git a/LeanPool/Wallace/UniformKronecker.lean b/LeanPool/Wallace/UniformKronecker.lean index 024e6f160..c0054c66b 100644 --- a/LeanPool/Wallace/UniformKronecker.lean +++ b/LeanPool/Wallace/UniformKronecker.lean @@ -556,7 +556,7 @@ private theorem integral_fourierPolynomial_translate {m : ℕ} /-- A target satisfying all frequencies in `c.support` is close to the corresponding annihilator. This is the quantitative conclusion extracted from the averaged finite Fourier approximation. -/ -theorem infDist_integerAnnihilator_lt_of_finite_relations {m : ℕ} {δ : ℝ} (_hδ : 0 < δ) +theorem infDist_integerAnnihilator_lt_of_finite_relations {m : ℕ} {δ : ℝ} {S : Finset (Fin m → ℤ)} (hS : ∀ R : AddSubgroup (Fin m → ℤ), ∃ c : (Fin m → ℤ) →₀ ℂ, c.support ⊆ S ∧ @@ -682,7 +682,7 @@ theorem exists_uniform_kronecker_bound (m : ℕ) {ε : ℝ} (hε : 0 < ε) : · exact (Finset.le_sup haS).trans (Nat.le_max_right 1 _) · exact haR have hdist : Metric.infDist t (integerAnnihilator R) ≤ 4 * δ := - infDist_integerAnnihilator_lt_of_finite_relations hδ hS R t hfinite + infDist_integerAnnihilator_lt_of_finite_relations hS R t hfinite have hdistlt : Metric.infDist t (integerAnnihilator R) < ε := by apply hdist.trans_lt dsimp [δ]