l3lab/ntp-mathlib huggingface dataset:
theorem fundamentalSequence_has_prop (o) : FundamentalSequenceProp o (fundamentalSequence o) := by
  induction' o with a m b iha ihb; · exact rfl
  rw [fundamentalSequence]
  rcases e : b.fundamentalSequence with (⟨_ | b'⟩ | f) <;>
    simp only [FundamentalSequenceProp] <;>
    rw [e, FundamentalSequenceProp] at ihb
  · rcases e : a.fundamentalSequence with (⟨_ | a'⟩ | f) <;> cases' e' : m.natPred with m' <;>
      simp only [FundamentalSequenceProp] <;>
      rw [e, FundamentalSequenceProp] at iha <;>
      (try rw [show m = 1 by
            have := PNat.natPred_add_one m; rw [e'] at this; exact PNat.coe_inj.1 this.symm]) <;>
      (try rw [show m = m'.succ.succPNat by
              rw [← e', ← PNat.coe_inj, Nat.succPNat_coe, ← Nat.add_one, PNat.natPred_add_one]]) <;>
      simp only [repr, iha, ihb, opow_lt_opow_iff_right one_lt_omega, add_lt_add_iff_left, add_zero,
        eq_self_iff_true, lt_add_iff_pos_right, lt_def, mul_one, Nat.cast_zero, Nat.cast_succ,
        Nat.succPNat_coe, opow_succ, opow_zero, mul_add_one, PNat.one_coe, succ_zero,
        true_and_iff, _root_.zero_add, zero_def]
    · decide
    · exact ⟨rfl, inferInstance⟩
    · have := opow_pos (repr a') omega_pos
      refine'
        ⟨mul_isLimit this omega_isLimit, fun i =>
          ⟨this, _, fun H => @NF.oadd_zero _ _ (iha.2 H.fst)⟩, exists_lt_mul_omega'⟩
      rw [← mul_succ, ← nat_cast_succ, Ordinal.mul_lt_mul_iff_left this]
      apply nat_lt_omega
    · have := opow_pos (repr a') omega_pos
      refine'
        ⟨add_isLimit _ (mul_isLimit this omega_isLimit), fun i => ⟨this, _, _⟩,
          exists_lt_add exists_lt_mul_omega'⟩
      · rw [← mul_succ, ← nat_cast_succ, Ordinal.mul_lt_mul_iff_left this]
        apply nat_lt_omega
      · refine' fun H => H.fst.oadd _ (NF.below_of_lt' _ (@NF.oadd_zero _ _ (iha.2 H.fst)))
        rw [repr, ← zero_def, repr, add_zero, iha.1, opow_succ, Ordinal.mul_lt_mul_iff_left this]
        apply nat_lt_omega
    · rcases iha with ⟨h1, h2, h3⟩
      refine' ⟨opow_isLimit one_lt_omega h1, fun i => _, exists_lt_omega_opow' one_lt_omega h1 h3⟩
      obtain ⟨h4, h5, h6⟩ := h2 i
      exact ⟨h4, h5, fun H => @NF.oadd_zero _ _ (h6 H.fst)⟩
    · rcases iha with ⟨h1, h2, h3⟩
      refine'
        ⟨add_isLimit _ (opow_isLimit one_lt_omega h1), fun i => _,
          exists_lt_add (exists_lt_omega_opow' one_lt_omega h1 h3)⟩
      obtain ⟨h4, h5, h6⟩ := h2 i
      refine' ⟨h4, h5, fun H => H.fst.oadd _ (NF.below_of_lt' _ (@NF.oadd_zero _ _ (h6 H.fst)))⟩
      rwa [repr, ← zero_def, repr, add_zero, PNat.one_coe, Nat.cast_one, mul_one,
        opow_lt_opow_iff_right one_lt_omega]
  · refine'
      ⟨by 

Proof state:
a : ONote
m : ℕ+
b : ONote
iha : FundamentalSequenceProp a (fundamentalSequence a)
b' : ONote
ihb : repr b = succ (repr b') ∧ (NF b → NF b')
e : fundamentalSequence b = Sum.inl (some b')
⊢ repr (oadd a m b) = succ (repr (oadd a m b'))

Next tactic:
rw [repr, ihb.1, add_succ, repr]
theorem fundamentalSequence_has_prop (o) : FundamentalSequenceProp o (fundamentalSequence o) := by
  induction' o with a m b iha ihb; · exact rfl
  rw [fundamentalSequence]
  rcases e : b.fundamentalSequence with (⟨_ | b'⟩ | f) <;>
    simp only [FundamentalSequenceProp] <;>
    rw [e, FundamentalSequenceProp] at ihb
  · rcases e : a.fundamentalSequence with (⟨_ | a'⟩ | f) <;> cases' e' : m.natPred with m' <;>
      simp only [FundamentalSequenceProp] <;>
      rw [e, FundamentalSequenceProp] at iha <;>
      (try rw [show m = 1 by
            have := PNat.natPred_add_one m; rw [e'] at this; exact PNat.coe_inj.1 this.symm]) <;>
      (try rw [show m = m'.succ.succPNat by
              rw [← e', ← PNat.coe_inj, Nat.succPNat_coe, ← Nat.add_one, PNat.natPred_add_one]]) <;>
      simp only [repr, iha, ihb, opow_lt_opow_iff_right one_lt_omega, add_lt_add_iff_left, add_zero,
        eq_self_iff_true, lt_add_iff_pos_right, lt_def, mul_one, Nat.cast_zero, Nat.cast_succ,
        Nat.succPNat_coe, opow_succ, opow_zero, mul_add_one, PNat.one_coe, succ_zero,
        true_and_iff, _root_.zero_add, zero_def]
    · decide
    · exact ⟨rfl, inferInstance⟩
    · have := opow_pos (repr a') omega_pos
      refine'
        ⟨mul_isLimit this omega_isLimit, fun i =>
          ⟨this, _, fun H => @NF.oadd_zero _ _ (iha.2 H.fst)⟩, exists_lt_mul_omega'⟩
      rw [← mul_succ, ← nat_cast_succ, Ordinal.mul_lt_mul_iff_left this]
      apply nat_lt_omega
    · have := opow_pos (repr a') omega_pos
      refine'
        ⟨add_isLimit _ (mul_isLimit this omega_isLimit), fun i => ⟨this, _, _⟩,
          exists_lt_add exists_lt_mul_omega'⟩
      · rw [← mul_succ, ← nat_cast_succ, Ordinal.mul_lt_mul_iff_left this]
        apply nat_lt_omega
      · refine' fun H => H.fst.oadd _ (NF.below_of_lt' _ (@NF.oadd_zero _ _ (iha.2 H.fst)))
        rw [repr, ← zero_def, repr, add_zero, iha.1, opow_succ, Ordinal.mul_lt_mul_iff_left this]
        apply nat_lt_omega
    · rcases iha with ⟨h1, h2, h3⟩
      refine' ⟨opow_isLimit one_lt_omega h1, fun i => _, exists_lt_omega_opow' one_lt_omega h1 h3⟩
      obtain ⟨h4, h5, h6⟩ := h2 i
      exact ⟨h4, h5, fun H => @NF.oadd_zero _ _ (h6 H.fst)⟩
    · rcases iha with ⟨h1, h2, h3⟩
      refine'
        ⟨add_isLimit _ (opow_isLimit one_lt_omega h1), fun i => _,
          exists_lt_add (exists_lt_omega_opow' one_lt_omega h1 h3)⟩
      obtain ⟨h4, h5, h6⟩ := h2 i
      refine' ⟨h4, h5, fun H => H.fst.oadd _ (NF.below_of_lt' _ (@NF.oadd_zero _ _ (h6 H.fst)))⟩
      rwa [repr, ← zero_def, repr, add_zero, PNat.one_coe, Nat.cast_one, mul_one,
        opow_lt_opow_iff_right one_lt_omega]
  · refine'
      ⟨by rw [repr, ihb.1, add_succ, repr], fun H => H.fst.oadd _ (NF.below_of_lt' _ (ihb.2 H.snd))⟩
    

Proof state:
case oadd.inl.some
a : ONote
m : ℕ+
b : ONote
iha : FundamentalSequenceProp a (fundamentalSequence a)
b' : ONote
ihb : repr b = succ (repr b') ∧ (NF b → NF b')
e : fundamentalSequence b = Sum.inl (some b')
H : NF (oadd a m b)
⊢ repr b' < ω ^ repr a

Next tactic:
have := H.snd'.repr_lt
theorem fundamentalSequence_has_prop (o) : FundamentalSequenceProp o (fundamentalSequence o) := by
  induction' o with a m b iha ihb; · exact rfl
  rw [fundamentalSequence]
  rcases e : b.fundamentalSequence with (⟨_ | b'⟩ | f) <;>
    simp only [FundamentalSequenceProp] <;>
    rw [e, FundamentalSequenceProp] at ihb
  · rcases e : a.fundamentalSequence with (⟨_ | a'⟩ | f) <;> cases' e' : m.natPred with m' <;>
      simp only [FundamentalSequenceProp] <;>
      rw [e, FundamentalSequenceProp] at iha <;>
      (try rw [show m = 1 by
            have := PNat.natPred_add_one m; rw [e'] at this; exact PNat.coe_inj.1 this.symm]) <;>
      (try rw [show m = m'.succ.succPNat by
              rw [← e', ← PNat.coe_inj, Nat.succPNat_coe, ← Nat.add_one, PNat.natPred_add_one]]) <;>
      simp only [repr, iha, ihb, opow_lt_opow_iff_right one_lt_omega, add_lt_add_iff_left, add_zero,
        eq_self_iff_true, lt_add_iff_pos_right, lt_def, mul_one, Nat.cast_zero, Nat.cast_succ,
        Nat.succPNat_coe, opow_succ, opow_zero, mul_add_one, PNat.one_coe, succ_zero,
        true_and_iff, _root_.zero_add, zero_def]
    · decide
    · exact ⟨rfl, inferInstance⟩
    · have := opow_pos (repr a') omega_pos
      refine'
        ⟨mul_isLimit this omega_isLimit, fun i =>
          ⟨this, _, fun H => @NF.oadd_zero _ _ (iha.2 H.fst)⟩, exists_lt_mul_omega'⟩
      rw [← mul_succ, ← nat_cast_succ, Ordinal.mul_lt_mul_iff_left this]
      apply nat_lt_omega
    · have := opow_pos (repr a') omega_pos
      refine'
        ⟨add_isLimit _ (mul_isLimit this omega_isLimit), fun i => ⟨this, _, _⟩,
          exists_lt_add exists_lt_mul_omega'⟩
      · rw [← mul_succ, ← nat_cast_succ, Ordinal.mul_lt_mul_iff_left this]
        apply nat_lt_omega
      · refine' fun H => H.fst.oadd _ (NF.below_of_lt' _ (@NF.oadd_zero _ _ (iha.2 H.fst)))
        rw [repr, ← zero_def, repr, add_zero, iha.1, opow_succ, Ordinal.mul_lt_mul_iff_left this]
        apply nat_lt_omega
    · rcases iha with ⟨h1, h2, h3⟩
      refine' ⟨opow_isLimit one_lt_omega h1, fun i => _, exists_lt_omega_opow' one_lt_omega h1 h3⟩
      obtain ⟨h4, h5, h6⟩ := h2 i
      exact ⟨h4, h5, fun H => @NF.oadd_zero _ _ (h6 H.fst)⟩
    · rcases iha with ⟨h1, h2, h3⟩
      refine'
        ⟨add_isLimit _ (opow_isLimit one_lt_omega h1), fun i => _,
          exists_lt_add (exists_lt_omega_opow' one_lt_omega h1 h3)⟩
      obtain ⟨h4, h5, h6⟩ := h2 i
      refine' ⟨h4, h5, fun H => H.fst.oadd _ (NF.below_of_lt' _ (@NF.oadd_zero _ _ (h6 H.fst)))⟩
      rwa [repr, ← zero_def, repr, add_zero, PNat.one_coe, Nat.cast_one, mul_one,
        opow_lt_opow_iff_right one_lt_omega]
  · refine'
      ⟨by rw [repr, ihb.1, add_succ, repr], fun H => H.fst.oadd _ (NF.below_of_lt' _ (ihb.2 H.snd))⟩
    have := H.snd'.repr_lt
    

Proof state:
case oadd.inl.some
a : ONote
m : ℕ+
b : ONote
iha : FundamentalSequenceProp a (fundamentalSequence a)
b' : ONote
ihb : repr b = succ (repr b') ∧ (NF b → NF b')
e : fundamentalSequence b = Sum.inl (some b')
H : NF (oadd a m b)
this : repr b < ω ^ repr a
⊢ repr b' < ω ^ repr a

Next tactic:
rw [ihb.1] at this
theorem fundamentalSequence_has_prop (o) : FundamentalSequenceProp o (fundamentalSequence o) := by
  induction' o with a m b iha ihb; · exact rfl
  rw [fundamentalSequence]
  rcases e : b.fundamentalSequence with (⟨_ | b'⟩ | f) <;>
    simp only [FundamentalSequenceProp] <;>
    rw [e, FundamentalSequenceProp] at ihb
  · rcases e : a.fundamentalSequence with (⟨_ | a'⟩ | f) <;> cases' e' : m.natPred with m' <;>
      simp only [FundamentalSequenceProp] <;>
      rw [e, FundamentalSequenceProp] at iha <;>
      (try rw [show m = 1 by
            have := PNat.natPred_add_one m; rw [e'] at this; exact PNat.coe_inj.1 this.symm]) <;>
      (try rw [show m = m'.succ.succPNat by
              rw [← e', ← PNat.coe_inj, Nat.succPNat_coe, ← Nat.add_one, PNat.natPred_add_one]]) <;>
      simp only [repr, iha, ihb, opow_lt_opow_iff_right one_lt_omega, add_lt_add_iff_left, add_zero,
        eq_self_iff_true, lt_add_iff_pos_right, lt_def, mul_one, Nat.cast_zero, Nat.cast_succ,
        Nat.succPNat_coe, opow_succ, opow_zero, mul_add_one, PNat.one_coe, succ_zero,
        true_and_iff, _root_.zero_add, zero_def]
    · decide
    · exact ⟨rfl, inferInstance⟩
    · have := opow_pos (repr a') omega_pos
      refine'
        ⟨mul_isLimit this omega_isLimit, fun i =>
          ⟨this, _, fun H => @NF.oadd_zero _ _ (iha.2 H.fst)⟩, exists_lt_mul_omega'⟩
      rw [← mul_succ, ← nat_cast_succ, Ordinal.mul_lt_mul_iff_left this]
      apply nat_lt_omega
    · have := opow_pos (repr a') omega_pos
      refine'
        ⟨add_isLimit _ (mul_isLimit this omega_isLimit), fun i => ⟨this, _, _⟩,
          exists_lt_add exists_lt_mul_omega'⟩
      · rw [← mul_succ, ← nat_cast_succ, Ordinal.mul_lt_mul_iff_left this]
        apply nat_lt_omega
      · refine' fun H => H.fst.oadd _ (NF.below_of_lt' _ (@NF.oadd_zero _ _ (iha.2 H.fst)))
        rw [repr, ← zero_def, repr, add_zero, iha.1, opow_succ, Ordinal.mul_lt_mul_iff_left this]
        apply nat_lt_omega
    · rcases iha with ⟨h1, h2, h3⟩
      refine' ⟨opow_isLimit one_lt_omega h1, fun i => _, exists_lt_omega_opow' one_lt_omega h1 h3⟩
      obtain ⟨h4, h5, h6⟩ := h2 i
      exact ⟨h4, h5, fun H => @NF.oadd_zero _ _ (h6 H.fst)⟩
    · rcases iha with ⟨h1, h2, h3⟩
      refine'
        ⟨add_isLimit _ (opow_isLimit one_lt_omega h1), fun i => _,
          exists_lt_add (exists_lt_omega_opow' one_lt_omega h1 h3)⟩
      obtain ⟨h4, h5, h6⟩ := h2 i
      refine' ⟨h4, h5, fun H => H.fst.oadd _ (NF.below_of_lt' _ (@NF.oadd_zero _ _ (h6 H.fst)))⟩
      rwa [repr, ← zero_def, repr, add_zero, PNat.one_coe, Nat.cast_one, mul_one,
        opow_lt_opow_iff_right one_lt_omega]
  · refine'
      ⟨by rw [repr, ihb.1, add_succ, repr], fun H => H.fst.oadd _ (NF.below_of_lt' _ (ihb.2 H.snd))⟩
    have := H.snd'.repr_lt
    rw [ihb.1] at this
    

Proof state:
case oadd.inl.some
a : ONote
m : ℕ+
b : ONote
iha : FundamentalSequenceProp a (fundamentalSequence a)
b' : ONote
ihb : repr b = succ (repr b') ∧ (NF b → NF b')
e : fundamentalSequence b = Sum.inl (some b')
H : NF (oadd a m b)
this : succ (repr b') < ω ^ repr a
⊢ repr b' < ω ^ repr a

Next tactic:
exact (lt_succ _).trans this
/-- The fast growing hierarchy for ordinal notations `< ε₀`. This is a sequence of
functions `ℕ → ℕ` indexed by ordinals, with the definition:
* `f_0(n) = n + 1`
* `f_(α+1)(n) = f_α^[n](n)`
* `f_α(n) = f_(α[n])(n)` where `α` is a limit ordinal
   and `α[i]` is the fundamental sequence converging to `α` -/
def fastGrowing : ONote → ℕ → ℕ
  | o =>
    match fundamentalSequence o, fundamentalSequence_has_prop o with
    | Sum.inl none, _ => Nat.succ
    | Sum.inl (some a), h =>
      have : a < o := by 

Proof state:
x✝ : ONote
o : ONote := x✝
a : ONote
h : FundamentalSequenceProp o (Sum.inl (some a))
⊢ a < o

Next tactic:
rw [lt_def, h.1]
/-- The fast growing hierarchy for ordinal notations `< ε₀`. This is a sequence of
functions `ℕ → ℕ` indexed by ordinals, with the definition:
* `f_0(n) = n + 1`
* `f_(α+1)(n) = f_α^[n](n)`
* `f_α(n) = f_(α[n])(n)` where `α` is a limit ordinal
   and `α[i]` is the fundamental sequence converging to `α` -/
def fastGrowing : ONote → ℕ → ℕ
  | o =>
    match fundamentalSequence o, fundamentalSequence_has_prop o with
    | Sum.inl none, _ => Nat.succ
    | Sum.inl (some a), h =>
      have : a < o := by rw [lt_def, h.1]; 

Proof state:
x✝ : ONote
o : ONote := x✝
a : ONote
h : FundamentalSequenceProp o (Sum.inl (some a))
⊢ repr a < succ (repr a)

Next tactic:
apply lt_succ
@[nolint unusedHavesSuffices]
theorem fastGrowing_def {o : ONote} {x} (e : fundamentalSequence o = x) :
    fastGrowing o =
      match
        (motive := (x : Option ONote ⊕ (ℕ → ONote)) → FundamentalSequenceProp o x → ℕ → ℕ)
        x, e ▸ fundamentalSequence_has_prop o with
      | Sum.inl none, _ => Nat.succ
      | Sum.inl (some a), _ =>
        fun i => (fastGrowing a)^[i] i
      | Sum.inr f, _ => fun i =>
        fastGrowing (f i) i := by
  

Proof state:
o : ONote
x : Option ONote ⊕ (ℕ → ONote)
e : fundamentalSequence o = x
⊢ fastGrowing o =
    match (motive := (x : Option ONote ⊕ (ℕ → ONote)) → FundamentalSequenceProp o x → ℕ → ℕ) x,
      (_ : FundamentalSequenceProp o x) with
    | Sum.inl none, x => Nat.succ
    | Sum.inl (some a), x => fun i => (fastGrowing a)^[i] i
    | Sum.inr f, x => fun i => fastGrowing (f i) i

Next tactic:
subst x
@[nolint unusedHavesSuffices]
theorem fastGrowing_def {o : ONote} {x} (e : fundamentalSequence o = x) :
    fastGrowing o =
      match
        (motive := (x : Option ONote ⊕ (ℕ → ONote)) → FundamentalSequenceProp o x → ℕ → ℕ)
        x, e ▸ fundamentalSequence_has_prop o with
      | Sum.inl none, _ => Nat.succ
      | Sum.inl (some a), _ =>
        fun i => (fastGrowing a)^[i] i
      | Sum.inr f, _ => fun i =>
        fastGrowing (f i) i := by
  subst x
  

Proof state:
o : ONote
⊢ fastGrowing o =
    match (motive := (x : Option ONote ⊕ (ℕ → ONote)) → FundamentalSequenceProp o x → ℕ → ℕ) fundamentalSequence o,
      (_ : FundamentalSequenceProp o (fundamentalSequence o)) with
    | Sum.inl none, x => Nat.succ
    | Sum.inl (some a), x => fun i => (fastGrowing a)^[i] i
    | Sum.inr f, x => fun i => fastGrowing (f i) i

Next tactic:
rw [fastGrowing]
theorem fastGrowing_zero' (o : ONote) (h : fundamentalSequence o = Sum.inl none) :
    fastGrowing o = Nat.succ := by
  

Proof state:
o : ONote
h : fundamentalSequence o = Sum.inl none
⊢ fastGrowing o = Nat.succ

Next tactic:
rw [fastGrowing_def h]
theorem fastGrowing_succ (o) {a} (h : fundamentalSequence o = Sum.inl (some a)) :
    fastGrowing o = fun i => (fastGrowing a)^[i] i := by
  

Proof state:
o a : ONote
h : fundamentalSequence o = Sum.inl (some a)
⊢ fastGrowing o = fun i => (fastGrowing a)^[i] i

Next tactic:
rw [fastGrowing_def h]
theorem fastGrowing_limit (o) {f} (h : fundamentalSequence o = Sum.inr f) :
    fastGrowing o = fun i => fastGrowing (f i) i := by
  

Proof state:
o : ONote
f : ℕ → ONote
h : fundamentalSequence o = Sum.inr f
⊢ fastGrowing o = fun i => fastGrowing (f i) i

Next tactic:
rw [fastGrowing_def h]
@[simp]
theorem fastGrowing_one : fastGrowing 1 = fun n => 2 * n := by
  

Proof state:
⊢ fastGrowing 1 = fun n => 2 * n

Next tactic:
rw [@fastGrowing_succ 1 0 rfl]
@[simp]
theorem fastGrowing_one : fastGrowing 1 = fun n => 2 * n := by
  rw [@fastGrowing_succ 1 0 rfl]; 

Proof state:
⊢ (fun i => (fastGrowing 0)^[i] i) = fun n => 2 * n

Next tactic:
funext i
@[simp]
theorem fastGrowing_one : fastGrowing 1 = fun n => 2 * n := by
  rw [@fastGrowing_succ 1 0 rfl]; funext i; 

Proof state:
case h
i : ℕ
⊢ (fastGrowing 0)^[i] i = 2 * i

Next tactic:
rw [two_mul, fastGrowing_zero]
@[simp]
theorem fastGrowing_one : fastGrowing 1 = fun n => 2 * n := by
  rw [@fastGrowing_succ 1 0 rfl]; funext i; rw [two_mul, fastGrowing_zero]
  

Proof state:
case h
i : ℕ
⊢ Nat.succ^[i] i = i + i

Next tactic:
suffices : ∀ a b, Nat.succ^[a] b = b + a
@[simp]
theorem fastGrowing_one : fastGrowing 1 = fun n => 2 * n := by
  rw [@fastGrowing_succ 1 0 rfl]; funext i; rw [two_mul, fastGrowing_zero]
  suffices : ∀ a b, Nat.succ^[a] b = b + a; 

Proof state:
case h
i : ℕ
this : ∀ (a b : ℕ), Nat.succ^[a] b = b + a
⊢ Nat.succ^[i] i = i + i
case this i : ℕ ⊢ ∀ (a b : ℕ), Nat.succ^[a] b = b + a

Next tactic:
exact this _ _
@[simp]
theorem fastGrowing_one : fastGrowing 1 = fun n => 2 * n := by
  rw [@fastGrowing_succ 1 0 rfl]; funext i; rw [two_mul, fastGrowing_zero]
  suffices : ∀ a b, Nat.succ^[a] b = b + a; exact this _ _
  

Proof state:
case this
i : ℕ
⊢ ∀ (a b : ℕ), Nat.succ^[a] b = b + a

Next tactic:
intro a b
@[simp]
theorem fastGrowing_one : fastGrowing 1 = fun n => 2 * n := by
  rw [@fastGrowing_succ 1 0 rfl]; funext i; rw [two_mul, fastGrowing_zero]
  suffices : ∀ a b, Nat.succ^[a] b = b + a; exact this _ _
  intro a b; 

Proof state:
case this
i a b : ℕ
⊢ Nat.succ^[a] b = b + a

Next tactic:
induction a
@[simp]
theorem fastGrowing_one : fastGrowing 1 = fun n => 2 * n := by
  rw [@fastGrowing_succ 1 0 rfl]; funext i; rw [two_mul, fastGrowing_zero]
  suffices : ∀ a b, Nat.succ^[a] b = b + a; exact this _ _
  intro a b; induction a <;> 

Proof state:
case this.zero
i b : ℕ
⊢ Nat.succ^[Nat.zero] b = b + Nat.zero

Next tactic:
simp [*, Function.iterate_succ', Nat.add_succ, -Function.iterate_succ]
@[simp]
theorem fastGrowing_one : fastGrowing 1 = fun n => 2 * n := by
  rw [@fastGrowing_succ 1 0 rfl]; funext i; rw [two_mul, fastGrowing_zero]
  suffices : ∀ a b, Nat.succ^[a] b = b + a; exact this _ _
  intro a b; induction a <;> 

Proof state:
case this.succ
i b n✝ : ℕ
n_ih✝ : Nat.succ^[n✝] b = b + n✝
⊢ Nat.succ^[Nat.succ n✝] b = b + Nat.succ n✝

Next tactic:
simp [*, Function.iterate_succ', Nat.add_succ, -Function.iterate_succ]
@[simp]
theorem fastGrowing_two : fastGrowing 2 = fun n => (2 ^ n) * n := by
  

Proof state:
⊢ fastGrowing 2 = fun n => 2 ^ n * n

Next tactic:
rw [@fastGrowing_succ 2 1 rfl]
@[simp]
theorem fastGrowing_two : fastGrowing 2 = fun n => (2 ^ n) * n := by
  rw [@fastGrowing_succ 2 1 rfl]; 

Proof state:
⊢ (fun i => (fastGrowing 1)^[i] i) = fun n => 2 ^ n * n

Next tactic:
funext i
@[simp]
theorem fastGrowing_two : fastGrowing 2 = fun n => (2 ^ n) * n := by
  rw [@fastGrowing_succ 2 1 rfl]; funext i; 

Proof state:
case h
i : ℕ
⊢ (fastGrowing 1)^[i] i = 2 ^ i * i

Next tactic:
rw [fastGrowing_one]
@[simp]
theorem fastGrowing_two : fastGrowing 2 = fun n => (2 ^ n) * n := by
  rw [@fastGrowing_succ 2 1 rfl]; funext i; rw [fastGrowing_one]
  

Proof state:
case h
i : ℕ
⊢ (fun n => 2 * n)^[i] i = 2 ^ i * i

Next tactic:
suffices : ∀ a b, (fun n : ℕ => 2 * n)^[a] b = (2 ^ a) * b
@[simp]
theorem fastGrowing_two : fastGrowing 2 = fun n => (2 ^ n) * n := by
  rw [@fastGrowing_succ 2 1 rfl]; funext i; rw [fastGrowing_one]
  suffices : ∀ a b, (fun n : ℕ => 2 * n)^[a] b = (2 ^ a) * b; 

Proof state:
case h
i : ℕ
this : ∀ (a b : ℕ), (fun n => 2 * n)^[a] b = 2 ^ a * b
⊢ (fun n => 2 * n)^[i] i = 2 ^ i * i
case this i : ℕ ⊢ ∀ (a b : ℕ), (fun n => 2 * n)^[a] b = 2 ^ a * b

Next tactic:
exact this _ _
@[simp]
theorem fastGrowing_two : fastGrowing 2 = fun n => (2 ^ n) * n := by
  rw [@fastGrowing_succ 2 1 rfl]; funext i; rw [fastGrowing_one]
  suffices : ∀ a b, (fun n : ℕ => 2 * n)^[a] b = (2 ^ a) * b; exact this _ _
  

Proof state:
case this
i : ℕ
⊢ ∀ (a b : ℕ), (fun n => 2 * n)^[a] b = 2 ^ a * b

Next tactic:
intro a b
@[simp]
theorem fastGrowing_two : fastGrowing 2 = fun n => (2 ^ n) * n := by
  rw [@fastGrowing_succ 2 1 rfl]; funext i; rw [fastGrowing_one]
  suffices : ∀ a b, (fun n : ℕ => 2 * n)^[a] b = (2 ^ a) * b; exact this _ _
  intro a b; 

Proof state:
case this
i a b : ℕ
⊢ (fun n => 2 * n)^[a] b = 2 ^ a * b

Next tactic:
induction a
@[simp]
theorem fastGrowing_two : fastGrowing 2 = fun n => (2 ^ n) * n := by
  rw [@fastGrowing_succ 2 1 rfl]; funext i; rw [fastGrowing_one]
  suffices : ∀ a b, (fun n : ℕ => 2 * n)^[a] b = (2 ^ a) * b; exact this _ _
  intro a b; induction a <;>
    

Proof state:
case this.zero
i b : ℕ
⊢ (fun n => 2 * n)^[Nat.zero] b = 2 ^ Nat.zero * b

Next tactic:
simp [*, Function.iterate_succ', pow_succ, mul_assoc, -Function.iterate_succ]
@[simp]
theorem fastGrowing_two : fastGrowing 2 = fun n => (2 ^ n) * n := by
  rw [@fastGrowing_succ 2 1 rfl]; funext i; rw [fastGrowing_one]
  suffices : ∀ a b, (fun n : ℕ => 2 * n)^[a] b = (2 ^ a) * b; exact this _ _
  intro a b; induction a <;>
    

Proof state:
case this.succ
i b n✝ : ℕ
n_ih✝ : (fun n => 2 * n)^[n✝] b = 2 ^ n✝ * b
⊢ (fun n => 2 * n)^[Nat.succ n✝] b = 2 ^ Nat.succ n✝ * b

Next tactic:
simp [*, Function.iterate_succ', pow_succ, mul_assoc, -Function.iterate_succ]
theorem fastGrowingε₀_zero : fastGrowingε₀ 0 = 1 := by 

Proof state:
⊢ fastGrowingε₀ 0 = 1

Next tactic:
simp [fastGrowingε₀]
theorem fastGrowingε₀_one : fastGrowingε₀ 1 = 2 := by
  

Proof state:
⊢ fastGrowingε₀ 1 = 2

Next tactic:
simp [fastGrowingε₀, show oadd 0 1 0 = 1 from rfl]
theorem fastGrowingε₀_two : fastGrowingε₀ 2 = 2048 := by
  

Proof state:
⊢ fastGrowingε₀ 2 = 2048

Next tactic:
norm_num [fastGrowingε₀, show oadd 0 1 0 = 1 from rfl, @fastGrowing_limit (oadd 1 1 0) _ rfl,
    show oadd 0 (2 : Nat).succPNat 0 = 3 from rfl, @fastGrowing_succ 3 2 rfl]
instance : DecidableEq NONote := by 

Proof state:
⊢ DecidableEq NONote

Next tactic:
unfold NONote
instance : DecidableEq NONote := by unfold NONote; 

Proof state:
⊢ DecidableEq { o // ONote.NF o }

Next tactic:
infer_instance
theorem cmp_compares : ∀ a b : NONote, (cmp a b).Compares a b
  | ⟨a, ha⟩, ⟨b, hb⟩ => by
    

Proof state:
a : ONote
ha : ONote.NF a
b : ONote
hb : ONote.NF b
⊢ Ordering.Compares (cmp { val := a, property := ha } { val := b, property := hb }) { val := a, property := ha }
    { val := b, property := hb }

Next tactic:
dsimp [cmp]
theorem cmp_compares : ∀ a b : NONote, (cmp a b).Compares a b
  | ⟨a, ha⟩, ⟨b, hb⟩ => by
    dsimp [cmp]
    

Proof state:
a : ONote
ha : ONote.NF a
b : ONote
hb : ONote.NF b
⊢ Ordering.Compares (ONote.cmp a b) { val := a, property := ha } { val := b, property := hb }

Next tactic:
have := ONote.cmp_compares a b
theorem cmp_compares : ∀ a b : NONote, (cmp a b).Compares a b
  | ⟨a, ha⟩, ⟨b, hb⟩ => by
    dsimp [cmp]
    have := ONote.cmp_compares a b
    

Proof state:
a : ONote
ha : ONote.NF a
b : ONote
hb : ONote.NF b
this : Ordering.Compares (ONote.cmp a b) a b
⊢ Ordering.Compares (ONote.cmp a b) { val := a, property := ha } { val := b, property := hb }

Next tactic:
cases h: ONote.cmp a b
theorem cmp_compares : ∀ a b : NONote, (cmp a b).Compares a b
  | ⟨a, ha⟩, ⟨b, hb⟩ => by
    dsimp [cmp]
    have := ONote.cmp_compares a b
    cases h: ONote.cmp a b <;> 

Proof state:
case lt
a : ONote
ha : ONote.NF a
b : ONote
hb : ONote.NF b
this : Ordering.Compares (ONote.cmp a b) a b
h : ONote.cmp a b = Ordering.lt
⊢ Ordering.Compares Ordering.lt { val := a, property := ha } { val := b, property := hb }

Next tactic:
simp only [h] at this
theorem cmp_compares : ∀ a b : NONote, (cmp a b).Compares a b
  | ⟨a, ha⟩, ⟨b, hb⟩ => by
    dsimp [cmp]
    have := ONote.cmp_compares a b
    cases h: ONote.cmp a b <;> 

Proof state:
case eq
a : ONote
ha : ONote.NF a
b : ONote
hb : ONote.NF b
this : Ordering.Compares (ONote.cmp a b) a b
h : ONote.cmp a b = Ordering.eq
⊢ Ordering.Compares Ordering.eq { val := a, property := ha } { val := b, property := hb }

Next tactic:
simp only [h] at this