|
| 1 | +/- |
| 2 | +Copyright (c) 2021 Joey Lupo |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE-APACHE. |
| 4 | +Authors: Joey Lupo |
| 5 | +-/ |
| 6 | +import Mathlib.Analysis.SpecialFunctions.Log.Basic |
| 7 | +import Mathlib.Analysis.SpecialFunctions.Pow.NNReal |
| 8 | +import Mathlib.Analysis.SpecialFunctions.Pow.Real |
| 9 | +import Mathlib.Data.Nat.Basic |
| 10 | +import Mathlib.Data.Real.Basic |
| 11 | +import Mathlib.Tactic.Cases |
| 12 | +import Mathlib.Tactic.Monotonicity |
| 13 | + |
| 14 | +/-! |
| 15 | +# Negligible functions. |
| 16 | +
|
| 17 | +This file defines negligible functions and provides several useful lemmas regarding |
| 18 | +negligible functions. |
| 19 | +
|
| 20 | + TO-DO connect with security parameter, (or not, as in Nowak), |
| 21 | + and refactor proofs/improve variable naming |
| 22 | +-/ |
| 23 | + |
| 24 | +/- |
| 25 | + A function f : ℤ≥1 → ℝ is called negligible if |
| 26 | + for all c ∈ ℝ>0 there exists n₀ ∈ ℤ≥1 such that |
| 27 | + n₀ ≤ n → |f(n)| < 1/n^c |
| 28 | +-/ |
| 29 | +def negligible (f : ℕ → ℝ) := |
| 30 | + ∀ c > 0, ∃ n₀, ∀ n, |
| 31 | + n₀ ≤ n → abs (f n) < 1 / (n : ℝ)^c |
| 32 | + |
| 33 | +def negligible' (f : ℕ → ℝ) := |
| 34 | + ∀ (c : ℝ), ∃ (n₀ : ℕ), ∀ (n : ℕ), |
| 35 | + 0 < c → n₀ ≤ n → abs (f n) < 1 / n^c |
| 36 | + |
| 37 | +lemma negl_equiv (f : ℕ → ℝ) : negligible f ↔ negligible' f := by |
| 38 | + constructor |
| 39 | + {-- Forward direction |
| 40 | + intros h c |
| 41 | + have arch := exists_nat_gt c |
| 42 | + cases' arch with k hk |
| 43 | + let k₀ := max k 1 |
| 44 | + have k_leq_k₀ : k ≤ k₀ := le_max_left k 1 |
| 45 | + have kr_leq_k₀r : (k:ℝ) ≤ k₀ := Nat.cast_le.mpr k_leq_k₀ |
| 46 | + have k₀_pos : 0 < k₀ := by {apply le_max_right k 1} |
| 47 | + have a := h k₀ k₀_pos |
| 48 | + |
| 49 | + -- use k₀ |
| 50 | + -- intros n c_pos hn |
| 51 | + -- have hnnn : k ≤ n := by linarith |
| 52 | + |
| 53 | + cases' a with n' hn₀ |
| 54 | + let n₀ := max n' 1 |
| 55 | + have n₀_pos : 0 < n₀ := by apply le_max_right n' 1 |
| 56 | + have n'_leq_n₀ : n' ≤ n₀ := le_max_left n' 1 |
| 57 | + use n₀ |
| 58 | + intros n c_pos hn |
| 59 | + have hnnn : n' ≤ n := by linarith |
| 60 | + |
| 61 | + have b : (n : ℝ)^c ≤ (n : ℝ)^(k₀ : ℝ) := by |
| 62 | + apply Real.rpow_le_rpow_of_exponent_le |
| 63 | + norm_cast |
| 64 | + linarith |
| 65 | + linarith |
| 66 | + have daf : (n : ℝ)^(k₀ : ℝ) = (n : ℝ)^k₀ := (n : ℝ).rpow_natCast k₀ |
| 67 | + rw [daf] at b |
| 68 | + have d : 1 / (n : ℝ)^k₀ ≤ 1 / n^c := by |
| 69 | + apply one_div_le_one_div_of_le |
| 70 | + { -- Proving 0 < (n:ℝ) ^ c |
| 71 | + apply Real.rpow_pos_of_pos |
| 72 | + norm_cast |
| 73 | + linarith |
| 74 | + } |
| 75 | + {exact b} |
| 76 | + have goal : abs (f n) < 1 / n^c := |
| 77 | + calc |
| 78 | + abs (f n) < 1 / (n : ℝ)^k₀ := hn₀ n hnnn |
| 79 | + _ ≤ 1 / n^c := d |
| 80 | + exact goal |
| 81 | + } |
| 82 | + |
| 83 | + {-- Reverse direction |
| 84 | + intros h c hc |
| 85 | + cases' h c with n₀ hn₀ |
| 86 | + use n₀ |
| 87 | + intros n hn |
| 88 | + have goal := hn₀ n (Nat.cast_pos.mpr hc) hn |
| 89 | + rw [(n : ℝ).rpow_natCast c] at goal |
| 90 | + exact goal |
| 91 | + } |
| 92 | + |
| 93 | +lemma zero_negl : negligible (λ_ => 0) := by |
| 94 | + intros c hc |
| 95 | + use 1 |
| 96 | + intros n hn |
| 97 | + norm_num |
| 98 | + apply pow_pos |
| 99 | + have h : 0 < n := by linarith |
| 100 | + exact Nat.cast_pos.mpr h |
| 101 | + |
| 102 | +lemma negl_add_negl_negl {f g : ℕ → ℝ} : negligible f → negligible g → negligible (f + g) := by |
| 103 | + intros hf hg |
| 104 | + intros c hc |
| 105 | + have hc1 : (c+1) > 0 := Nat.lt.step hc |
| 106 | + have hf2 := hf (c+1) hc1 |
| 107 | + have hg2 := hg (c+1) hc1 |
| 108 | + cases' hf2 with nf hnf |
| 109 | + cases' hg2 with ng hng |
| 110 | + let n₀ := max (max nf ng) 2 |
| 111 | + use n₀ |
| 112 | + intros n hn |
| 113 | + let nr := (n:ℝ) |
| 114 | + have n_eq_nr : (n:ℝ) = nr := by rfl |
| 115 | + |
| 116 | + have tn : max nf ng ≤ n₀ := le_max_left (max nf ng) 2 |
| 117 | + have t2n₀ : 2 ≤ n₀ := le_max_right (max nf ng) 2 |
| 118 | + have t2n : 2 ≤ n := by linarith |
| 119 | + have t2nr : 2 ≤ nr := by |
| 120 | + -- have j := Nat.cast_le.mpr t2n |
| 121 | + -- rw [n_eq_nr] at j |
| 122 | + -- norm_num at j |
| 123 | + -- exact j |
| 124 | + -- exact is_R_or_C.char_zero_R_or_C |
| 125 | + simp_all only [Nat.ofNat_le_cast, t2n, nr] |
| 126 | + have tnr_pos : 0 < nr := by linarith |
| 127 | + |
| 128 | + have t2na : (1 / nr) * (1/nr^c) ≤ (1 / (2 : ℝ)) * (1 / nr^c) := by |
| 129 | + have ht2 : 0 < (1 / nr^c) := by {apply one_div_pos.mpr; exact pow_pos tnr_pos c} |
| 130 | + apply (mul_le_mul_right ht2).mpr |
| 131 | + apply one_div_le_one_div_of_le |
| 132 | + exact zero_lt_two |
| 133 | + exact t2nr |
| 134 | + |
| 135 | + have tnr2 : 1 / nr^(c + 1) ≤ (1 / (2 : ℝ)) * (1 / nr^c) := |
| 136 | + calc |
| 137 | + 1 / nr ^ (c + 1) = (1 / nr)^(c + 1) := by rw [one_div_pow] |
| 138 | + _ = (1 / nr)^c * (1 / nr) := pow_succ (1 / nr) c |
| 139 | + _ = (1 / nr) * (1 / nr)^c := by ac_nf |
| 140 | + _ = (1 / nr) * (1 / nr^c) := by rw [one_div_pow] |
| 141 | + _ ≤ (1 / (2 : ℝ)) * (1 / nr^c) := t2na |
| 142 | + |
| 143 | + have tnf : nf ≤ n := |
| 144 | + calc |
| 145 | + nf ≤ n₀ := le_of_max_le_left tn |
| 146 | + _ ≤ n := hn |
| 147 | + have tfn := hnf n tnf |
| 148 | + have tf : abs (f n) < (1 / (2 : ℝ)) * (1 / nr^c) := by linarith |
| 149 | + |
| 150 | + have tng : ng ≤ n := |
| 151 | + calc ng ≤ n₀ := le_of_max_le_right tn |
| 152 | + _ ≤ n := hn |
| 153 | + have tgn := hng n tng |
| 154 | + have tg : abs (g n) < (1/(2:ℝ)) * (1/nr^c) := by linarith |
| 155 | + |
| 156 | + have goal : abs ((f + g) n) < 1 / nr ^ c := |
| 157 | + calc |
| 158 | + abs ((f + g) n) = abs (f n + g n) := by rw [Pi.add_apply f g n] |
| 159 | + _ ≤ abs (f n) + abs (g n) := abs_add (f n) (g n) |
| 160 | + _ < (1/(2:ℝ)) * (1/nr^c) + abs (g n) := by linarith |
| 161 | + _ < (1/(2:ℝ)) * (1/nr^c) + (1/(2:ℝ)) * (1/nr^c) := by linarith |
| 162 | + _ = 1/nr^c := by ring_nf |
| 163 | + exact goal |
| 164 | + |
| 165 | +lemma bounded_negl_negl {f g : ℕ → ℝ} (hg : negligible g): |
| 166 | + (∀ n, abs (f n) ≤ abs (g n)) → negligible f := by |
| 167 | + intro h |
| 168 | + intros c hc |
| 169 | + have hh := hg c hc |
| 170 | + cases' hh with n₀ hn₀ |
| 171 | + use n₀ |
| 172 | + intros n hn |
| 173 | + have goal : abs (f n) < 1 / (n : ℝ) ^ c := |
| 174 | + calc |
| 175 | + abs (f n) ≤ abs (g n) := h n |
| 176 | + _ < 1 / (n : ℝ)^c := hn₀ n hn |
| 177 | + exact goal |
| 178 | + |
| 179 | +lemma nat_mul_negl_negl {f : ℕ → ℝ} (m : ℕ): |
| 180 | + negligible f → negligible (λn => m * (f n)) := by |
| 181 | + intros hf |
| 182 | + induction' m with k hk |
| 183 | + { -- Base case |
| 184 | + norm_num |
| 185 | + exact zero_negl |
| 186 | + } |
| 187 | + { -- Inductive step |
| 188 | + norm_num |
| 189 | + have d : (λn => ((k : ℝ) + 1) * (f n)) = (λn => (k : ℝ) * (f n)) + (λn => f n) := by |
| 190 | + ring_nf |
| 191 | + rfl |
| 192 | + rw [d] |
| 193 | + apply negl_add_negl_negl |
| 194 | + exact hk |
| 195 | + exact hf |
| 196 | + } |
| 197 | + |
| 198 | +lemma const_mul_negl_negl {f : ℕ → ℝ} (m : ℝ) : |
| 199 | + negligible f → negligible (λn => m * (f n)) := by |
| 200 | + intro hf |
| 201 | + -- Use Archimedian property to get arch : ℕ with abs m < arch |
| 202 | + have arch := exists_nat_gt (abs m) |
| 203 | + cases' arch with k hk |
| 204 | + apply bounded_negl_negl |
| 205 | + |
| 206 | + { -- Demonstrate a negligible function kf |
| 207 | + have kf_negl := nat_mul_negl_negl k hf |
| 208 | + exact kf_negl |
| 209 | + } |
| 210 | + |
| 211 | + { -- Show kf bounds mf from above |
| 212 | + intro n |
| 213 | + have h : abs m ≤ abs (k : ℝ) := |
| 214 | + calc |
| 215 | + abs m ≤ (k : ℝ) := le_of_lt hk |
| 216 | + _ = abs (k : ℝ) := (Nat.abs_cast k).symm |
| 217 | + |
| 218 | + have goal : abs (m * f n) ≤ abs ((k : ℝ) * f n) := |
| 219 | + calc |
| 220 | + abs (m * f n) = abs m * abs (f n) := by rw [abs_mul] |
| 221 | + _ ≤ abs (k : ℝ) * abs (f n) := mul_le_mul_of_nonneg_right h (abs_nonneg (f n)) |
| 222 | + _ = abs ((k : ℝ) * f n) := by rw [<- abs_mul] |
| 223 | + |
| 224 | + exact goal |
| 225 | + } |
| 226 | + |
| 227 | +theorem neg_exp_negl : negligible ((λn => (1 : ℝ) / 2^n) : ℕ → ℝ) := by sorry |
| 228 | + |
| 229 | +-- Need to prove lim n^c/2^n = 0 by induction on c using L'Hopital's rule to apply inductive |
| 230 | +-- hypothesis |
| 231 | +/- |
| 232 | + let m := 2 |
| 233 | + have hm : 0 < 2 := zero_lt_two |
| 234 | + have c2_negl := c2_mul_neg_exp_is_negl 2 hm |
| 235 | + have r : (λ (n : ℕ) => 16 * (1 / (2 ^ n * 16)): ℕ → ℝ) = ((λn => (1:ℝ)/2^n): ℕ → ℝ) := by |
| 236 | + funext |
| 237 | + have h : (1:ℝ) / 2^n / 16 = (1:ℝ) / (2^n * 16) := div_div_eq_div_mul 1 (2^n) 16 |
| 238 | + rw [<- h] |
| 239 | + ring_nf |
| 240 | +
|
| 241 | + have goal := const_mul_negl_is_negl 16 c2_negl |
| 242 | + norm_num at goal |
| 243 | + rw [<-r] |
| 244 | + exact goal |
| 245 | +-/ |
0 commit comments