|
1 | 1 | import LogicFormalization.Chapter2.Section4.Term |
2 | 2 | import Mathlib.Data.Fin.VecNotation |
3 | 3 | import Mathlib.Tactic.Linarith.Frontend |
| 4 | +import Mathlib.Tactic.Ring |
4 | 5 |
|
5 | 6 | namespace Homeworks |
6 | 7 |
|
@@ -105,10 +106,161 @@ theorem not_exists_nat_rig_term₁ : ¬∃ (t: Term .Rig) (x: Var) (hx: AreVarsF |
105 | 106 | end a |
106 | 107 |
|
107 | 108 |
|
| 109 | +section b |
| 110 | + |
| 111 | +/-- Represents polynomials with coefficients from `ℕ`.-/ |
| 112 | +inductive Poly |
| 113 | +| const: ℕ → Poly |
| 114 | +| var |
| 115 | +| add: Poly → Poly → Poly |
| 116 | +| mul: Poly → Poly → Poly |
| 117 | + |
| 118 | +namespace Poly |
| 119 | + |
| 120 | +def eval: Poly → ℕ → ℕ |
| 121 | +| .const a, _ => a |
| 122 | +| .var, n => n |
| 123 | +| .add p q, n => p.eval n + q.eval n |
| 124 | +| .mul p q, n => p.eval n * q.eval n |
| 125 | + |
| 126 | +lemma eval_mono: ∀ {p: Poly}, Monotone p.eval |
| 127 | +| .const _ => fun _ _ _ => Nat.le_refl _ |
| 128 | +| .var => fun _ _ => id |
| 129 | +| .add _ _ => Monotone.add eval_mono eval_mono |
| 130 | +| .mul _ |
| 131 | + _ => Monotone.mul' eval_mono eval_mono |
| 132 | + |
| 133 | +/-- Degree of a polynomial -/ |
| 134 | +def deg: Poly → ℕ |
| 135 | +| .const _ => 0 |
| 136 | +| .var => 1 |
| 137 | +| .add p q => max (deg p) (deg q) |
| 138 | +| .mul p q => deg p + deg q |
| 139 | + |
| 140 | +/-- Polynomials are homogenous. -/ |
| 141 | +lemma eval_mul_le {a n} (ha: a ≠ 0) : ∀ {p: Poly}, eval p (a * n) ≤ a^(deg p) * eval p n |
| 142 | +| .const c | .var => by simp [eval, deg] |
| 143 | +| .add q r => calc eval (add q r) (a * n) |
| 144 | + _ = eval q (a * n) + eval r (a * n) := rfl |
| 145 | + _ ≤ a^(deg q) * eval q n + a^(deg r) * eval r n := |
| 146 | + Nat.add_le_add (eval_mul_le ha) (eval_mul_le ha) |
| 147 | + _ ≤ _ := by |
| 148 | + apply (Nat.le_or_ge (deg q) (deg r)).elim |
| 149 | + · intro h |
| 150 | + simp only [deg, h, sup_of_le_right, eval, Nat.mul_add, add_le_add_iff_right] |
| 151 | + apply Nat.mul_le_mul_right |
| 152 | + apply Nat.pow_le_pow_right <;> simp [*, Nat.zero_lt_of_ne_zero] |
| 153 | + · intro h |
| 154 | + simp only [deg, h, sup_of_le_left, eval, Nat.mul_add, add_le_add_iff_left] |
| 155 | + apply Nat.mul_le_mul_right |
| 156 | + apply Nat.pow_le_pow_right <;> simp [*, Nat.zero_lt_of_ne_zero] |
| 157 | +| .mul q r => calc eval (mul q r) (a * n) |
| 158 | + _ = eval q (a * n) * eval r (a * n) := rfl |
| 159 | + _ ≤ (a^(deg q) * eval q n) * (a^(deg r) * eval r n) := |
| 160 | + Nat.mul_le_mul (eval_mul_le ha) (eval_mul_le ha) |
| 161 | + _ = _ := by simp [deg, eval]; ring |
| 162 | + |
| 163 | +/-- Roughly speaking, use `eval_mul_le` to go from `p(n)` |
| 164 | +to `p(2 * n / 2)` to `2^deg(p) p(n)`. This is complicated |
| 165 | +by the fact that we are in `ℕ` and lack clean division. |
| 166 | +We end up using `⌈n/2⌉` instead. -/ |
| 167 | +lemma eval_le_mul_eval_half {p: Poly} {n: ℕ}: |
| 168 | + eval p n ≤ 2^(deg p) * eval p ((n + 1) / 2) := calc _ |
| 169 | + _ ≤ eval p (2 * ((n + 1) / 2)) := eval_mono (by omega) |
| 170 | + _ ≤ _ := eval_mul_le (by decide) |
| 171 | + |
| 172 | +/-- p(n) does not converge to 2^n as n → ∞ -/ |
| 173 | +lemma eval_diverges_from_two_pow: ∀ p m, ∃ N, ∀ n ≥ N, m * eval p n < 2^n |
| 174 | +| .const c, m => ⟨m * c, fun n hn => Nat.lt_of_le_of_lt hn Nat.lt_two_pow_self⟩ |
| 175 | +| .var, m => ⟨m + 1, fun n hn => |
| 176 | + have: m ≤ n - 1 := Nat.le_sub_one_of_lt hn |
| 177 | + Nat.lt_of_le_of_lt |
| 178 | + (Nat.mul_le_mul_right n this) mul_pred_self_lt_two_pow⟩ |
| 179 | +| .add q r, m => |
| 180 | + let ⟨Nq, hq⟩ := eval_diverges_from_two_pow q (2 * m) |
| 181 | + let ⟨Nr, hr⟩ := eval_diverges_from_two_pow r (2 * m) |
| 182 | + ⟨max Nq Nr, fun n hn => by |
| 183 | + replace hu := hq n (le_of_max_le_left hn) |
| 184 | + replace hv := hr n (le_of_max_le_right hn) |
| 185 | + have := Nat.add_lt_add hu hv |
| 186 | + simp_rw [Nat.two_mul, Nat.add_mul, ←Nat.two_mul, ←Nat.mul_add] at this |
| 187 | + exact Nat.lt_of_mul_lt_mul_left this⟩ |
| 188 | +| .mul q r, m => |
| 189 | + -- this one is trickier. we make use of the homogeneity property (`eval_mul_le`) |
| 190 | + let ⟨Nq, hq⟩ := eval_diverges_from_two_pow q (m * 2^(deg q)) |
| 191 | + let ⟨Nr, hr⟩ := eval_diverges_from_two_pow r (2 * 2^(deg r)) |
| 192 | + ⟨(max Nq Nr) * 2, fun n hn => by |
| 193 | + replace hq := hq ((n + 1) / 2) (by omega) |
| 194 | + replace hr := hr ((n + 1) / 2) (by omega) |
| 195 | + replace hr: 2 ^ r.deg * r.eval ((n + 1) / 2) < 2 ^ ((n + 1) / 2 - 1) := by |
| 196 | + simp only [Nat.mul_assoc] at hr |
| 197 | + apply Nat.lt_of_mul_lt_mul_left (a := 2) |
| 198 | + rw [←Nat.pow_succ'] |
| 199 | + apply Nat.lt_of_lt_of_le hr |
| 200 | + apply Nat.pow_le_pow_right (by decide) |
| 201 | + omega |
| 202 | + |
| 203 | + calc m * eval (mul q r) n |
| 204 | + _ = m * (eval q n * eval r n) := rfl |
| 205 | + _ ≤ m * ((2^(deg q) * eval q ((n + 1) / 2)) * (2^(deg r) * eval r ((n + 1) / 2))) := by |
| 206 | + apply Nat.mul_le_mul_left |
| 207 | + apply Nat.mul_le_mul <;> exact eval_le_mul_eval_half |
| 208 | + _ = (m * 2^(deg q) * eval q ((n + 1) / 2)) * (2^(deg r) * eval r ((n + 1) / 2)) := by ring |
| 209 | + _ < (2 ^ ((n + 1) / 2)) * (2 ^ ((n + 1) / 2 - 1)) := Nat.mul_lt_mul'' hq hr |
| 210 | + _ = 2 ^ ((n + 1) / 2 + ((n + 1) / 2 - 1)) := (Nat.pow_add ..).symm |
| 211 | + _ ≤ 2 ^ n := Nat.pow_le_pow_right (by decide) (by omega)⟩ |
| 212 | +where |
| 213 | + mul_pred_self_lt_two_pow : ∀ {n: ℕ}, (n - 1) * n < 2^n |
| 214 | + | 0 => by decide |
| 215 | + | k + 1 => calc (k + 1 - 1) * (k + 1) |
| 216 | + _ = k * (k + 1) := rfl |
| 217 | + _ = (k - 1) * k + 2 * k := by |
| 218 | + simp only [Nat.mul_succ, Nat.sub_mul] |
| 219 | + have := Nat.sub_add_cancel (Nat.le_mul_self k) |
| 220 | + omega |
| 221 | + _ < 2 ^ k + 2 * k := |
| 222 | + Nat.add_lt_add_right mul_pred_self_lt_two_pow _ |
| 223 | + _ ≤ 2 ^ (k + 1) := by |
| 224 | + simp only [Nat.pow_succ, Nat.mul_two, add_le_add_iff_left] |
| 225 | + have: (k - 1) + 1 ≤ 2^(k-1) := Nat.lt_two_pow_self |
| 226 | + match k with |
| 227 | + | 0 => decide |
| 228 | + | l + 1 => |
| 229 | + rw [Nat.add_sub_cancel] at this |
| 230 | + omega |
| 231 | + |
| 232 | +/-- Convert one of the `L`-terms to a `Poly`. -/ |
| 233 | +def ofTerm (t: Term .Rig) {x: Var} (hx: AreVarsFor ![x] t): |
| 234 | + { p // ∀ n, interp t 𝒩 hx ![n] = eval p n } := |
| 235 | + match t with |
| 236 | + | .var _ => ⟨.var, fun n => by simp [interp, eval]⟩ |
| 237 | + | .app .zero _ => ⟨.const 0, fun n => rfl⟩ |
| 238 | + | .app .one _ => ⟨.const 1, fun n => rfl⟩ |
| 239 | + | .app .add ts => |
| 240 | + let ⟨a, ha⟩ := ofTerm (ts 0) (.ofApp hx 0) |
| 241 | + let ⟨b, hb⟩ := ofTerm (ts 1) (.ofApp hx 1) |
| 242 | + ⟨.add a b, fun n => by simp only [eval, ←ha, ←hb]; rfl⟩ |
| 243 | + | .app .mul ts => |
| 244 | + let ⟨a, ha⟩ := ofTerm (ts 0) (.ofApp hx 0) |
| 245 | + let ⟨b, hb⟩ := ofTerm (ts 1) (.ofApp hx 1) |
| 246 | + ⟨.mul a b, fun n => by simp only [eval, ←ha, ←hb]; rfl⟩ |
| 247 | + |
| 248 | +end Poly |
| 249 | + |
| 250 | + |
108 | 251 | /-- 2.4 #5 (b) -/ |
109 | 252 | theorem not_exists_nat_rig_term₂ : ¬∃ (t: Term .Rig) (x: Var) (hx: AreVarsFor ![x] t), |
110 | 253 | ∀ n, interp t 𝒩 hx ![n] = 2^n := |
111 | | - sorry |
| 254 | + fun ⟨t, x, hx, h⟩ => |
| 255 | + let ⟨p, hp⟩ := Poly.ofTerm t hx |
| 256 | + have ⟨N, hN⟩ := Poly.eval_diverges_from_two_pow p 17 |
| 257 | + by { |
| 258 | + have := hN N (Nat.le_refl N) |
| 259 | + rw [←h N, hp N] at this |
| 260 | + omega |
| 261 | + } |
| 262 | + |
| 263 | +end b |
112 | 264 |
|
113 | 265 | open Structure in |
114 | 266 | /-- 2.4 #5 (c). The only substructure of `𝒩` is `𝒩` itself. -/ |
|
0 commit comments