l3lab/ntp-mathlib huggingface dataset:
theorem exists_lt_succ {P : ℕ → Prop} {n : ℕ} : (∃ m < n + 1, P m) ↔ (∃ m < n, P m) ∨ P n := by
  

Proof state:
m n✝ k : ℕ
P : ℕ → Prop
n : ℕ
⊢ (∃ m, m < n + 1 ∧ P m) ↔ (∃ m, m < n ∧ P m) ∨ P n

Next tactic:
rw [← not_iff_not]
theorem exists_lt_succ {P : ℕ → Prop} {n : ℕ} : (∃ m < n + 1, P m) ↔ (∃ m < n, P m) ∨ P n := by
  rw [← not_iff_not]
  

Proof state:
m n✝ k : ℕ
P : ℕ → Prop
n : ℕ
⊢ (¬∃ m, m < n + 1 ∧ P m) ↔ ¬((∃ m, m < n ∧ P m) ∨ P n)

Next tactic:
push_neg
theorem exists_lt_succ {P : ℕ → Prop} {n : ℕ} : (∃ m < n + 1, P m) ↔ (∃ m < n, P m) ∨ P n := by
  rw [← not_iff_not]
  push_neg
  

Proof state:
m n✝ k : ℕ
P : ℕ → Prop
n : ℕ
⊢ (∀ (m : ℕ), m < n + 1 → ¬P m) ↔ (∀ (m : ℕ), m < n → ¬P m) ∧ ¬P n

Next tactic:
exact forall_lt_succ
theorem exists_eq_add_of_lt (h : m < n) : ∃ k : ℕ, n = m + k + 1 :=
  ⟨n - (m + 1), by 

Proof state:
m n k : ℕ
h : m < n
⊢ n = m + (n - (m + 1)) + 1

Next tactic:
rw [Nat.add_right_comm, add_sub_of_le h]
@[simp]
theorem add_succ_sub_one (n m : ℕ) : n + succ m - 1 = n + m := by 

Proof state:
m✝ n✝ k n m : ℕ
⊢ n + succ m - 1 = n + m

Next tactic:
rw [add_succ, Nat.add_one_sub_one]
@[simp]
theorem succ_add_sub_one (n m : ℕ) : succ n + m - 1 = n + m := by 

Proof state:
m✝ n✝ k n m : ℕ
⊢ succ n + m - 1 = n + m

Next tactic:
rw [succ_add, Nat.add_one_sub_one]
theorem pred_eq_of_eq_succ {m n : ℕ} (H : m = n.succ) : m.pred = n := by 

Proof state:
m✝ n✝ k m n : ℕ
H : m = succ n
⊢ pred m = n

Next tactic:
simp [H]
@[simp]
theorem pred_eq_succ_iff {n m : ℕ} : pred n = succ m ↔ n = m + 2 := by
  

Proof state:
m✝ n✝ k n m : ℕ
⊢ pred n = succ m ↔ n = m + 2

Next tactic:
cases n
@[simp]
theorem pred_eq_succ_iff {n m : ℕ} : pred n = succ m ↔ n = m + 2 := by
  cases n <;> 

Proof state:
case zero
m✝ n k m : ℕ
⊢ pred zero = succ m ↔ zero = m + 2

Next tactic:
constructor
@[simp]
theorem pred_eq_succ_iff {n m : ℕ} : pred n = succ m ↔ n = m + 2 := by
  cases n <;> 

Proof state:
case succ
m✝ n k m n✝ : ℕ
⊢ pred (succ n✝) = succ m ↔ succ n✝ = m + 2

Next tactic:
constructor
@[simp]
theorem pred_eq_succ_iff {n m : ℕ} : pred n = succ m ↔ n = m + 2 := by
  cases n <;> constructor <;> 

Proof state:
case zero.mp
m✝ n k m : ℕ
⊢ pred zero = succ m → zero = m + 2

Next tactic:
rintro ⟨⟩
@[simp]
theorem pred_eq_succ_iff {n m : ℕ} : pred n = succ m ↔ n = m + 2 := by
  cases n <;> constructor <;> 

Proof state:
case zero.mpr
m✝ n k m : ℕ
⊢ zero = m + 2 → pred zero = succ m

Next tactic:
rintro ⟨⟩
@[simp]
theorem pred_eq_succ_iff {n m : ℕ} : pred n = succ m ↔ n = m + 2 := by
  cases n <;> constructor <;> 

Proof state:
case succ.mp
m✝ n k m n✝ : ℕ
⊢ pred (succ n✝) = succ m → succ n✝ = m + 2

Next tactic:
rintro ⟨⟩
@[simp]
theorem pred_eq_succ_iff {n m : ℕ} : pred n = succ m ↔ n = m + 2 := by
  cases n <;> constructor <;> 

Proof state:
case succ.mpr
m✝ n k m n✝ : ℕ
⊢ succ n✝ = m + 2 → pred (succ n✝) = succ m

Next tactic:
rintro ⟨⟩
@[simp]
theorem pred_eq_succ_iff {n m : ℕ} : pred n = succ m ↔ n = m + 2 := by
  cases n <;> constructor <;> rintro ⟨⟩ <;> 

Proof state:
case succ.mp.refl
m✝ n k m : ℕ
⊢ succ (succ m) = m + 2

Next tactic:
rfl
@[simp]
theorem pred_eq_succ_iff {n m : ℕ} : pred n = succ m ↔ n = m + 2 := by
  cases n <;> constructor <;> rintro ⟨⟩ <;> 

Proof state:
case succ.mpr.refl
m✝ n k m : ℕ
⊢ pred (succ (Nat.add m 1)) = succ m

Next tactic:
rfl
theorem pred_sub (n m : ℕ) : pred n - m = pred (n - m) := by
  

Proof state:
m✝ n✝ k n m : ℕ
⊢ pred n - m = pred (n - m)

Next tactic:
rw [← Nat.sub_one, Nat.sub_sub, one_add, sub_succ]
theorem self_add_sub_one (n : ℕ) : n + (n - 1) = 2 * n - 1 := by
  

Proof state:
m n✝ k n : ℕ
⊢ n + (n - 1) = 2 * n - 1

Next tactic:
cases n
theorem self_add_sub_one (n : ℕ) : n + (n - 1) = 2 * n - 1 := by
  cases n
  · 

Proof state:
case zero
m n k : ℕ
⊢ zero + (zero - 1) = 2 * zero - 1

Next tactic:
rfl
theorem self_add_sub_one (n : ℕ) : n + (n - 1) = 2 * n - 1 := by
  cases n
  · rfl
  · 

Proof state:
case succ
m n k n✝ : ℕ
⊢ succ n✝ + (succ n✝ - 1) = 2 * succ n✝ - 1

Next tactic:
rw [two_mul]
theorem self_add_sub_one (n : ℕ) : n + (n - 1) = 2 * n - 1 := by
  cases n
  · rfl
  · rw [two_mul]
    

Proof state:
case succ
m n k n✝ : ℕ
⊢ succ n✝ + (succ n✝ - 1) = succ n✝ + succ n✝ - 1

Next tactic:
convert (add_succ_sub_one (Nat.succ _) _).symm
/-- This ensures that `simp` succeeds on `pred (n + 1) = n`. -/
@[simp]
theorem pred_one_add (n : ℕ) : pred (1 + n) = n := by 

Proof state:
m n✝ k n : ℕ
⊢ pred (1 + n) = n

Next tactic:
rw [add_comm, add_one, Nat.pred_succ]
theorem two_mul_ne_two_mul_add_one {n m} : 2 * n ≠ 2 * m + 1 :=
  mt (congr_arg (· % 2))
    (by 

Proof state:
m✝ n✝ k n m : ℕ
⊢ ¬2 * n % 2 = (2 * m + 1) % 2

Next tactic:
rw [add_comm, add_mul_mod_self_left, mul_mod_right, mod_eq_of_lt]
theorem two_mul_ne_two_mul_add_one {n m} : 2 * n ≠ 2 * m + 1 :=
  mt (congr_arg (· % 2))
    (by rw [add_comm, add_mul_mod_self_left, mul_mod_right, mod_eq_of_lt] <;> 

Proof state:
m✝ n✝ k n m : ℕ
⊢ ¬0 = 1

Next tactic:
simp
theorem two_mul_ne_two_mul_add_one {n m} : 2 * n ≠ 2 * m + 1 :=
  mt (congr_arg (· % 2))
    (by rw [add_comm, add_mul_mod_self_left, mul_mod_right, mod_eq_of_lt] <;> 

Proof state:
m✝ n✝ k n m : ℕ
⊢ 1 < 2

Next tactic:
simp
theorem mul_right_eq_self_iff {a b : ℕ} (ha : 0 < a) : a * b = a ↔ b = 1 :=
  suffices a * b = a * 1 ↔ b = 1 by 

Proof state:
m n k a b : ℕ
ha : 0 < a
this : a * b = a * 1 ↔ b = 1
⊢ a * b = a ↔ b = 1

Next tactic:
rwa [mul_one] at this
theorem mul_left_eq_self_iff {a b : ℕ} (hb : 0 < b) : a * b = b ↔ a = 1 := by
  

Proof state:
m n k a b : ℕ
hb : 0 < b
⊢ a * b = b ↔ a = 1

Next tactic:
rw [mul_comm, Nat.mul_right_eq_self_iff hb]
set_option push_neg.use_distrib true in
/-- The product of two natural numbers is greater than 1 if and only if
  at least one of them is greater than 1 and both are positive. -/
lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
  

Proof state:
m n k : ℕ
⊢ 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n)

Next tactic:
constructor
set_option push_neg.use_distrib true in
/-- The product of two natural numbers is greater than 1 if and only if
  at least one of them is greater than 1 and both are positive. -/
lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
  constructor <;> 

Proof state:
case mp
m n k : ℕ
⊢ 1 < m * n → 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n)

Next tactic:
intro h
set_option push_neg.use_distrib true in
/-- The product of two natural numbers is greater than 1 if and only if
  at least one of them is greater than 1 and both are positive. -/
lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
  constructor <;> 

Proof state:
case mpr
m n k : ℕ
⊢ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) → 1 < m * n

Next tactic:
intro h
set_option push_neg.use_distrib true in
/-- The product of two natural numbers is greater than 1 if and only if
  at least one of them is greater than 1 and both are positive. -/
lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
  constructor <;> intro h
  · 

Proof state:
case mp
m n k : ℕ
h : 1 < m * n
⊢ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n)

Next tactic:
by_contra h'
set_option push_neg.use_distrib true in
/-- The product of two natural numbers is greater than 1 if and only if
  at least one of them is greater than 1 and both are positive. -/
lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
  constructor <;> intro h
  · by_contra h'; 

Proof state:
case mp
m n k : ℕ
h : 1 < m * n
h' : ¬(0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n))
⊢ False

Next tactic:
push_neg at h'
set_option push_neg.use_distrib true in
/-- The product of two natural numbers is greater than 1 if and only if
  at least one of them is greater than 1 and both are positive. -/
lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
  constructor <;> intro h
  · by_contra h'; push_neg at h'; 

Proof state:
case mp
m n k : ℕ
h : 1 < m * n
h' : m ≤ 0 ∨ n ≤ 0 ∨ m ≤ 1 ∧ n ≤ 1
⊢ False

Next tactic:
simp_rw [Nat.le_zero] at h'
set_option push_neg.use_distrib true in
/-- The product of two natural numbers is greater than 1 if and only if
  at least one of them is greater than 1 and both are positive. -/
lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
  constructor <;> intro h
  · by_contra h'; push_neg at h'; simp_rw [Nat.le_zero] at h'
    

Proof state:
case mp
m n k : ℕ
h : 1 < m * n
h' : m = 0 ∨ n = 0 ∨ m ≤ 1 ∧ n ≤ 1
⊢ False

Next tactic:
obtain rfl | rfl | h' := h'
set_option push_neg.use_distrib true in
/-- The product of two natural numbers is greater than 1 if and only if
  at least one of them is greater than 1 and both are positive. -/
lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
  constructor <;> intro h
  · by_contra h'; push_neg at h'; simp_rw [Nat.le_zero] at h'
    obtain rfl | rfl | h' := h'
    · 

Proof state:
case mp.inl
n k : ℕ
h : 1 < 0 * n
⊢ False

Next tactic:
simp at h
set_option push_neg.use_distrib true in
/-- The product of two natural numbers is greater than 1 if and only if
  at least one of them is greater than 1 and both are positive. -/
lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
  constructor <;> intro h
  · by_contra h'; push_neg at h'; simp_rw [Nat.le_zero] at h'
    obtain rfl | rfl | h' := h'
    · simp at h
    · 

Proof state:
case mp.inr.inl
m k : ℕ
h : 1 < m * 0
⊢ False

Next tactic:
simp at h
set_option push_neg.use_distrib true in
/-- The product of two natural numbers is greater than 1 if and only if
  at least one of them is greater than 1 and both are positive. -/
lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
  constructor <;> intro h
  · by_contra h'; push_neg at h'; simp_rw [Nat.le_zero] at h'
    obtain rfl | rfl | h' := h'
    · simp at h
    · simp at h
    · 

Proof state:
case mp.inr.inr
m n k : ℕ
h : 1 < m * n
h' : m ≤ 1 ∧ n ≤ 1
⊢ False

Next tactic:
exact (Nat.mul_le_mul h'.1 h'.2).not_lt h
set_option push_neg.use_distrib true in
/-- The product of two natural numbers is greater than 1 if and only if
  at least one of them is greater than 1 and both are positive. -/
lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
  constructor <;> intro h
  · by_contra h'; push_neg at h'; simp_rw [Nat.le_zero] at h'
    obtain rfl | rfl | h' := h'
    · simp at h
    · simp at h
    · exact (Nat.mul_le_mul h'.1 h'.2).not_lt h
  · 

Proof state:
case mpr
m n k : ℕ
h : 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n)
⊢ 1 < m * n

Next tactic:
obtain hm | hn := h.2.2
set_option push_neg.use_distrib true in
/-- The product of two natural numbers is greater than 1 if and only if
  at least one of them is greater than 1 and both are positive. -/
lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
  constructor <;> intro h
  · by_contra h'; push_neg at h'; simp_rw [Nat.le_zero] at h'
    obtain rfl | rfl | h' := h'
    · simp at h
    · simp at h
    · exact (Nat.mul_le_mul h'.1 h'.2).not_lt h
  · obtain hm | hn := h.2.2
    · 

Proof state:
case mpr.inl
m n k : ℕ
h : 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n)
hm : 1 < m
⊢ 1 < m * n

Next tactic:
exact Nat.mul_lt_mul hm h.2.1 Nat.zero_lt_one
set_option push_neg.use_distrib true in
/-- The product of two natural numbers is greater than 1 if and only if
  at least one of them is greater than 1 and both are positive. -/
lemma one_lt_mul_iff : 1 < m * n ↔ 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n) := by
  constructor <;> intro h
  · by_contra h'; push_neg at h'; simp_rw [Nat.le_zero] at h'
    obtain rfl | rfl | h' := h'
    · simp at h
    · simp at h
    · exact (Nat.mul_le_mul h'.1 h'.2).not_lt h
  · obtain hm | hn := h.2.2
    · exact Nat.mul_lt_mul hm h.2.1 Nat.zero_lt_one
    · 

Proof state:
case mpr.inr
m n k : ℕ
h : 0 < m ∧ 0 < n ∧ (1 < m ∨ 1 < n)
hn : 1 < n
⊢ 1 < m * n

Next tactic:
exact Nat.mul_lt_mul' h.1 hn h.1
theorem leRecOn_self {C : ℕ → Sort u} {n} {h : n ≤ n} {next : ∀ {k}, C k → C (k + 1)} (x : C n) :
    (leRecOn h next x : C n) = x := by
  

Proof state:
m n✝ k : ℕ
C : ℕ → Sort u
n : ℕ
h : n ≤ n
next : {k : ℕ} → C k → C (k + 1)
x : C n
⊢ leRecOn h (fun {k} => next) x = x

Next tactic:
cases n
theorem leRecOn_self {C : ℕ → Sort u} {n} {h : n ≤ n} {next : ∀ {k}, C k → C (k + 1)} (x : C n) :
    (leRecOn h next x : C n) = x := by
  cases n <;> 

Proof state:
case zero
m n k : ℕ
C : ℕ → Sort u
next : {k : ℕ} → C k → C (k + 1)
h : zero ≤ zero
x : C zero
⊢ leRecOn h (fun {k} => next) x = x

Next tactic:
unfold leRecOn Eq.recOn
theorem leRecOn_self {C : ℕ → Sort u} {n} {h : n ≤ n} {next : ∀ {k}, C k → C (k + 1)} (x : C n) :
    (leRecOn h next x : C n) = x := by
  cases n <;> 

Proof state:
case succ
m n k : ℕ
C : ℕ → Sort u
next : {k : ℕ} → C k → C (k + 1)
n✝ : ℕ
h : succ n✝ ≤ succ n✝
x : C (succ n✝)
⊢ leRecOn h (fun {k} => next) x = x

Next tactic:
unfold leRecOn Eq.recOn
theorem leRecOn_self {C : ℕ → Sort u} {n} {h : n ≤ n} {next : ∀ {k}, C k → C (k + 1)} (x : C n) :
    (leRecOn h next x : C n) = x := by
  cases n <;> unfold leRecOn Eq.recOn
  · 

Proof state:
case zero
m n k : ℕ
C : ℕ → Sort u
next : {k : ℕ} → C k → C (k + 1)
h : zero ≤ zero
x : C zero
⊢ (_ : zero = 0) ▸ x = x

Next tactic:
simp
theorem leRecOn_self {C : ℕ → Sort u} {n} {h : n ≤ n} {next : ∀ {k}, C k → C (k + 1)} (x : C n) :
    (leRecOn h next x : C n) = x := by
  cases n <;> unfold leRecOn Eq.recOn
  · simp
  · 

Proof state:
case succ
m n k : ℕ
C : ℕ → Sort u
next : {k : ℕ} → C k → C (k + 1)
n✝ : ℕ
h : succ n✝ ≤ succ n✝
x : C (succ n✝)
⊢ (Or.by_cases (_ : succ n✝ ≤ n✝ ∨ succ n✝ = succ n✝) (fun h => (fun {k} => next) (leRecOn h (fun {k} => next) x))
      fun h => h ▸ x) =
    x

Next tactic:
unfold Or.by_cases
theorem leRecOn_self {C : ℕ → Sort u} {n} {h : n ≤ n} {next : ∀ {k}, C k → C (k + 1)} (x : C n) :
    (leRecOn h next x : C n) = x := by
  cases n <;> unfold leRecOn Eq.recOn
  · simp
  · unfold Or.by_cases
    

Proof state:
case succ
m n k : ℕ
C : ℕ → Sort u
next : {k : ℕ} → C k → C (k + 1)
n✝ : ℕ
h : succ n✝ ≤ succ n✝
x : C (succ n✝)
⊢ (if hp : succ n✝ ≤ n✝ then (fun h => (fun {k} => next) (leRecOn h (fun {k} => next) x)) hp
    else (fun h => h ▸ x) (_ : succ n✝ = succ n✝)) =
    x

Next tactic:
rw [dif_neg (Nat.not_succ_le_self _)]
theorem leRecOn_succ {C : ℕ → Sort u} {n m} (h1 : n ≤ m) {h2 : n ≤ m + 1} {next} (x : C n) :
    (leRecOn h2 (@next) x : C (m + 1)) = next (leRecOn h1 (@next) x : C m) := by
  

Proof state:
m✝ n✝ k : ℕ
C : ℕ → Sort u
n m : ℕ
h1 : n ≤ m
h2 : n ≤ m + 1
next : {k : ℕ} → C k → C (k + 1)
x : C n
⊢ leRecOn h2 next x = next (leRecOn h1 next x)

Next tactic:
conv =>
    lhs
    rw [leRecOn, Or.by_cases, dif_pos h1]
theorem leRecOn_succ {C : ℕ → Sort u} {n m} (h1 : n ≤ m) {h2 : n ≤ m + 1} {next} (x : C n) :
    (leRecOn h2 (@next) x : C (m + 1)) = next (leRecOn h1 (@next) x : C m) := by
  conv =>
    

Proof state:
m✝ n✝ k : ℕ
C : ℕ → Sort u
n m : ℕ
h1 : n ≤ m
h2 : n ≤ m + 1
next : {k : ℕ} → C k → C (k + 1)
x : C n
| leRecOn h2 next x = next (leRecOn h1 next x)

Next tactic:
lhs
    rw [leRecOn, Or.by_cases, dif_pos h1]
theorem leRecOn_succ {C : ℕ → Sort u} {n m} (h1 : n ≤ m) {h2 : n ≤ m + 1} {next} (x : C n) :
    (leRecOn h2 (@next) x : C (m + 1)) = next (leRecOn h1 (@next) x : C m) := by
  conv =>
    

Proof state:
m✝ n✝ k : ℕ
C : ℕ → Sort u
n m : ℕ
h1 : n ≤ m
h2 : n ≤ m + 1
next : {k : ℕ} → C k → C (k + 1)
x : C n
| leRecOn h2 next x = next (leRecOn h1 next x)

Next tactic:
lhs
theorem leRecOn_succ {C : ℕ → Sort u} {n m} (h1 : n ≤ m) {h2 : n ≤ m + 1} {next} (x : C n) :
    (leRecOn h2 (@next) x : C (m + 1)) = next (leRecOn h1 (@next) x : C m) := by
  conv =>
    lhs
    

Proof state:
m✝ n✝ k : ℕ
C : ℕ → Sort u
n m : ℕ
h1 : n ≤ m
h2 : n ≤ m + 1
next : {k : ℕ} → C k → C (k + 1)
x : C n
| leRecOn h2 next x

Next tactic:
rw [leRecOn, Or.by_cases, dif_pos h1]
theorem leRecOn_succ' {C : ℕ → Sort u} {n} {h : n ≤ n + 1} {next : ∀ {k}, C k → C (k + 1)}
    (x : C n) :
    (leRecOn h next x : C (n + 1)) = next x := by 

Proof state:
m n✝ k : ℕ
C : ℕ → Sort u
n : ℕ
h : n ≤ n + 1
next : {k : ℕ} → C k → C (k + 1)
x : C n
⊢ leRecOn h (fun {k} => next) x = next x

Next tactic:
rw [leRecOn_succ (le_refl n), leRecOn_self]
theorem leRecOn_trans {C : ℕ → Sort u} {n m k} (hnm : n ≤ m) (hmk : m ≤ k) {next} (x : C n) :
    (leRecOn (le_trans hnm hmk) (@next) x : C k) = leRecOn hmk (@next) (leRecOn hnm (@next) x) := by
  

Proof state:
m✝ n✝ k✝ : ℕ
C : ℕ → Sort u
n m k : ℕ
hnm : n ≤ m
hmk : m ≤ k
next : {k : ℕ} → C k → C (k + 1)
x : C n
⊢ leRecOn (_ : n ≤ k) next x = leRecOn hmk next (leRecOn hnm next x)

Next tactic:
induction' hmk with k hmk ih
theorem leRecOn_trans {C : ℕ → Sort u} {n m k} (hnm : n ≤ m) (hmk : m ≤ k) {next} (x : C n) :
    (leRecOn (le_trans hnm hmk) (@next) x : C k) = leRecOn hmk (@next) (leRecOn hnm (@next) x) := by
  induction' hmk with k hmk ih
  · 

Proof state:
case refl
m✝ n✝ k✝ : ℕ
C : ℕ → Sort u
n m k : ℕ
hnm : n ≤ m
next : {k : ℕ} → C k → C (k + 1)
x : C n
⊢ leRecOn (_ : n ≤ m) next x = leRecOn (_ : Nat.le m m) next (leRecOn hnm next x)

Next tactic:
rw [leRecOn_self]
theorem leRecOn_trans {C : ℕ → Sort u} {n m k} (hnm : n ≤ m) (hmk : m ≤ k) {next} (x : C n) :
    (leRecOn (le_trans hnm hmk) (@next) x : C k) = leRecOn hmk (@next) (leRecOn hnm (@next) x) := by
  induction' hmk with k hmk ih
  · rw [leRecOn_self]

  

Proof state:
case step
m✝ n✝ k✝¹ : ℕ
C : ℕ → Sort u
n m k✝ : ℕ
hnm : n ≤ m
next : {k : ℕ} → C k → C (k + 1)
x : C n
k : ℕ
hmk : Nat.le m k
ih : leRecOn (_ : n ≤ k) next x = leRecOn hmk next (leRecOn hnm next x)
⊢ leRecOn (_ : n ≤ succ k) next x = leRecOn (_ : Nat.le m (succ k)) next (leRecOn hnm next x)

Next tactic:
rw [leRecOn_succ (le_trans hnm hmk), ih, leRecOn_succ]
theorem leRecOn_succ_left {C : ℕ → Sort u} {n m} (h1 : n ≤ m) (h2 : n + 1 ≤ m)
    {next : ∀ {k}, C k → C (k + 1)} (x : C n) :
    (leRecOn h2 next (next x) : C m) = (leRecOn h1 next x : C m) := by
  

Proof state:
m✝ n✝ k : ℕ
C : ℕ → Sort u
n m : ℕ
h1 : n ≤ m
h2 : n + 1 ≤ m
next : {k : ℕ} → C k → C (k + 1)
x : C n
⊢ leRecOn h2 (fun {k} => next) (next x) = leRecOn h1 (fun {k} => next) x

Next tactic:
rw [Subsingleton.elim h1 (le_trans (le_succ n) h2), leRecOn_trans (le_succ n) h2, leRecOn_succ']
theorem leRecOn_injective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
    (Hnext : ∀ n, Function.Injective (@next n)) :
    Function.Injective (@leRecOn C n m hnm next) := by
  

Proof state:
m✝ n✝ k : ℕ
C : ℕ → Sort u
n m : ℕ
hnm : n ≤ m
next : {k : ℕ} → C k → C (k + 1)
Hnext : ∀ (n : ℕ), Function.Injective next
⊢ Function.Injective (leRecOn hnm fun {k} => next)

Next tactic:
induction' hnm with m hnm ih
theorem leRecOn_injective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
    (Hnext : ∀ n, Function.Injective (@next n)) :
    Function.Injective (@leRecOn C n m hnm next) := by
  induction' hnm with m hnm ih
  · 

Proof state:
case refl
m✝ n✝ k : ℕ
C : ℕ → Sort u
n m : ℕ
next : {k : ℕ} → C k → C (k + 1)
Hnext : ∀ (n : ℕ), Function.Injective next
⊢ Function.Injective (leRecOn (_ : Nat.le n n) fun {k} => next)

Next tactic:
intro x y H
theorem leRecOn_injective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
    (Hnext : ∀ n, Function.Injective (@next n)) :
    Function.Injective (@leRecOn C n m hnm next) := by
  induction' hnm with m hnm ih
  · intro x y H
    

Proof state:
case refl
m✝ n✝ k : ℕ
C : ℕ → Sort u
n m : ℕ
next : {k : ℕ} → C k → C (k + 1)
Hnext : ∀ (n : ℕ), Function.Injective next
x y : C n
H : leRecOn (_ : Nat.le n n) (fun {k} => next) x = leRecOn (_ : Nat.le n n) (fun {k} => next) y
⊢ x = y

Next tactic:
rwa [leRecOn_self, leRecOn_self] at H
theorem leRecOn_injective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
    (Hnext : ∀ n, Function.Injective (@next n)) :
    Function.Injective (@leRecOn C n m hnm next) := by
  induction' hnm with m hnm ih
  · intro x y H
    rwa [leRecOn_self, leRecOn_self] at H

  

Proof state:
case step
m✝¹ n✝ k : ℕ
C : ℕ → Sort u
n m✝ : ℕ
next : {k : ℕ} → C k → C (k + 1)
Hnext : ∀ (n : ℕ), Function.Injective next
m : ℕ
hnm : Nat.le n m
ih : Function.Injective (leRecOn hnm fun {k} => next)
⊢ Function.Injective (leRecOn (_ : Nat.le n (succ m)) fun {k} => next)

Next tactic:
intro x y H
theorem leRecOn_injective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
    (Hnext : ∀ n, Function.Injective (@next n)) :
    Function.Injective (@leRecOn C n m hnm next) := by
  induction' hnm with m hnm ih
  · intro x y H
    rwa [leRecOn_self, leRecOn_self] at H

  intro x y H
  

Proof state:
case step
m✝¹ n✝ k : ℕ
C : ℕ → Sort u
n m✝ : ℕ
next : {k : ℕ} → C k → C (k + 1)
Hnext : ∀ (n : ℕ), Function.Injective next
m : ℕ
hnm : Nat.le n m
ih : Function.Injective (leRecOn hnm fun {k} => next)
x y : C n
H : leRecOn (_ : Nat.le n (succ m)) (fun {k} => next) x = leRecOn (_ : Nat.le n (succ m)) (fun {k} => next) y
⊢ x = y

Next tactic:
rw [leRecOn_succ hnm, leRecOn_succ hnm] at H
theorem leRecOn_injective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
    (Hnext : ∀ n, Function.Injective (@next n)) :
    Function.Injective (@leRecOn C n m hnm next) := by
  induction' hnm with m hnm ih
  · intro x y H
    rwa [leRecOn_self, leRecOn_self] at H

  intro x y H
  rw [leRecOn_succ hnm, leRecOn_succ hnm] at H
  

Proof state:
case step
m✝¹ n✝ k : ℕ
C : ℕ → Sort u
n m✝ : ℕ
next : {k : ℕ} → C k → C (k + 1)
Hnext : ∀ (n : ℕ), Function.Injective next
m : ℕ
hnm : Nat.le n m
ih : Function.Injective (leRecOn hnm fun {k} => next)
x y : C n
H : next (leRecOn hnm (fun {k} => next) x) = next (leRecOn hnm (fun {k} => next) y)
⊢ x = y

Next tactic:
exact ih (Hnext _ H)
theorem leRecOn_surjective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
    (Hnext : ∀ n, Function.Surjective (@next n)) :
    Function.Surjective (@leRecOn C n m hnm next) := by
  

Proof state:
m✝ n✝ k : ℕ
C : ℕ → Sort u
n m : ℕ
hnm : n ≤ m
next : {k : ℕ} → C k → C (k + 1)
Hnext : ∀ (n : ℕ), Function.Surjective next
⊢ Function.Surjective (leRecOn hnm fun {k} => next)

Next tactic:
induction' hnm with m hnm ih
theorem leRecOn_surjective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
    (Hnext : ∀ n, Function.Surjective (@next n)) :
    Function.Surjective (@leRecOn C n m hnm next) := by
  induction' hnm with m hnm ih
  · 

Proof state:
case refl
m✝ n✝ k : ℕ
C : ℕ → Sort u
n m : ℕ
next : {k : ℕ} → C k → C (k + 1)
Hnext : ∀ (n : ℕ), Function.Surjective next
⊢ Function.Surjective (leRecOn (_ : Nat.le n n) fun {k} => next)

Next tactic:
intro x
theorem leRecOn_surjective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
    (Hnext : ∀ n, Function.Surjective (@next n)) :
    Function.Surjective (@leRecOn C n m hnm next) := by
  induction' hnm with m hnm ih
  · intro x
    

Proof state:
case refl
m✝ n✝ k : ℕ
C : ℕ → Sort u
n m : ℕ
next : {k : ℕ} → C k → C (k + 1)
Hnext : ∀ (n : ℕ), Function.Surjective next
x : C n
⊢ ∃ a, leRecOn (_ : Nat.le n n) (fun {k} => next) a = x

Next tactic:
use x
theorem leRecOn_surjective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
    (Hnext : ∀ n, Function.Surjective (@next n)) :
    Function.Surjective (@leRecOn C n m hnm next) := by
  induction' hnm with m hnm ih
  · intro x
    use x
    

Proof state:
case h
m✝ n✝ k : ℕ
C : ℕ → Sort u
n m : ℕ
next : {k : ℕ} → C k → C (k + 1)
Hnext : ∀ (n : ℕ), Function.Surjective next
x : C n
⊢ leRecOn (_ : Nat.le n n) (fun {k} => next) x = x

Next tactic:
rw [leRecOn_self]
theorem leRecOn_surjective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
    (Hnext : ∀ n, Function.Surjective (@next n)) :
    Function.Surjective (@leRecOn C n m hnm next) := by
  induction' hnm with m hnm ih
  · intro x
    use x
    rw [leRecOn_self]

  

Proof state:
case step
m✝¹ n✝ k : ℕ
C : ℕ → Sort u
n m✝ : ℕ
next : {k : ℕ} → C k → C (k + 1)
Hnext : ∀ (n : ℕ), Function.Surjective next
m : ℕ
hnm : Nat.le n m
ih : Function.Surjective (leRecOn hnm fun {k} => next)
⊢ Function.Surjective (leRecOn (_ : Nat.le n (succ m)) fun {k} => next)

Next tactic:
intro x