l3lab/ntp-mathlib huggingface dataset:
/-- Given an orthogonal basis with respect to a bilinear form, the bilinear form is left-separating
if the basis has no elements which are self-orthogonal. -/
theorem IsOrthoᵢ.separatingLeft_of_not_isOrtho_basis_self [NoZeroDivisors R] {B : M →ₗ[R] M →ₗ[R] R}
    (v : Basis n R M) (hO : B.IsOrthoᵢ v) (h : ∀ i, ¬B.IsOrtho (v i) (v i)) : B.SeparatingLeft := by
  intro m hB
  obtain ⟨vi, rfl⟩ := v.repr.symm.surjective m
  rw [LinearEquiv.map_eq_zero_iff]
  ext i
  rw [Finsupp.zero_apply]
  specialize hB (v i)
  simp_rw [Basis.repr_symm_apply, Finsupp.total_apply, Finsupp.sum, map_sum₂, map_smulₛₗ₂,
    smul_eq_mul] at hB
  rw [Finset.sum_eq_single i] at hB
  · exact eq_zero_of_ne_zero_of_mul_right_eq_zero (h i) hB
  · intro j _hj hij
    replace hij : B (v j) (v i) = 0 := hO hij
    rw [hij, RingHom.id_apply, mul_zero]
  · intro hi
    

Proof state:
case intro.h.h₁
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
M : Type u_5
M₁ : Type u_6
M₂ : Type u_7
Mₗ₁ : Type u_8
Mₗ₁' : Type u_9
Mₗ₂ : Type u_10
Mₗ₂' : Type u_11
K : Type u_12
K₁ : Type u_13
K₂ : Type u_14
V : Type u_15
V₁ : Type u_16
V₂ : Type u_17
n : Type u_18
inst✝³ : CommRing R
inst✝² : AddCommGroup M
inst✝¹ : Module R M
I I' : R →+* R
inst✝ : NoZeroDivisors R
B : M →ₗ[R] M →ₗ[R] R
v : Basis n R M
hO : IsOrthoᵢ B ⇑v
h : ∀ (i : n), ¬IsOrtho B (v i) (v i)
vi : n →₀ R
i : n
hB : ∑ x in vi.support, (RingHom.id R) (vi x) * (B (v x)) (v i) = 0
hi : i ∉ vi.support
⊢ (RingHom.id R) (vi i) * (B (v i)) (v i) = 0

Next tactic:
replace hi : vi i = 0 := Finsupp.not_mem_support_iff.mp hi
/-- Given an orthogonal basis with respect to a bilinear form, the bilinear form is left-separating
if the basis has no elements which are self-orthogonal. -/
theorem IsOrthoᵢ.separatingLeft_of_not_isOrtho_basis_self [NoZeroDivisors R] {B : M →ₗ[R] M →ₗ[R] R}
    (v : Basis n R M) (hO : B.IsOrthoᵢ v) (h : ∀ i, ¬B.IsOrtho (v i) (v i)) : B.SeparatingLeft := by
  intro m hB
  obtain ⟨vi, rfl⟩ := v.repr.symm.surjective m
  rw [LinearEquiv.map_eq_zero_iff]
  ext i
  rw [Finsupp.zero_apply]
  specialize hB (v i)
  simp_rw [Basis.repr_symm_apply, Finsupp.total_apply, Finsupp.sum, map_sum₂, map_smulₛₗ₂,
    smul_eq_mul] at hB
  rw [Finset.sum_eq_single i] at hB
  · exact eq_zero_of_ne_zero_of_mul_right_eq_zero (h i) hB
  · intro j _hj hij
    replace hij : B (v j) (v i) = 0 := hO hij
    rw [hij, RingHom.id_apply, mul_zero]
  · intro hi
    replace hi : vi i = 0 := Finsupp.not_mem_support_iff.mp hi
    

Proof state:
case intro.h.h₁
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
M : Type u_5
M₁ : Type u_6
M₂ : Type u_7
Mₗ₁ : Type u_8
Mₗ₁' : Type u_9
Mₗ₂ : Type u_10
Mₗ₂' : Type u_11
K : Type u_12
K₁ : Type u_13
K₂ : Type u_14
V : Type u_15
V₁ : Type u_16
V₂ : Type u_17
n : Type u_18
inst✝³ : CommRing R
inst✝² : AddCommGroup M
inst✝¹ : Module R M
I I' : R →+* R
inst✝ : NoZeroDivisors R
B : M →ₗ[R] M →ₗ[R] R
v : Basis n R M
hO : IsOrthoᵢ B ⇑v
h : ∀ (i : n), ¬IsOrtho B (v i) (v i)
vi : n →₀ R
i : n
hB : ∑ x in vi.support, (RingHom.id R) (vi x) * (B (v x)) (v i) = 0
hi : vi i = 0
⊢ (RingHom.id R) (vi i) * (B (v i)) (v i) = 0

Next tactic:
rw [hi, RingHom.id_apply, zero_mul]
/-- Given an orthogonal basis with respect to a bilinear form, the bilinear form is right-separating
if the basis has no elements which are self-orthogonal. -/
theorem IsOrthoᵢ.separatingRight_iff_not_isOrtho_basis_self [NoZeroDivisors R]
    {B : M →ₗ[R] M →ₗ[R] R} (v : Basis n R M) (hO : B.IsOrthoᵢ v)
    (h : ∀ i, ¬B.IsOrtho (v i) (v i)) : B.SeparatingRight := by
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
M : Type u_5
M₁ : Type u_6
M₂ : Type u_7
Mₗ₁ : Type u_8
Mₗ₁' : Type u_9
Mₗ₂ : Type u_10
Mₗ₂' : Type u_11
K : Type u_12
K₁ : Type u_13
K₂ : Type u_14
V : Type u_15
V₁ : Type u_16
V₂ : Type u_17
n : Type u_18
inst✝³ : CommRing R
inst✝² : AddCommGroup M
inst✝¹ : Module R M
I I' : R →+* R
inst✝ : NoZeroDivisors R
B : M →ₗ[R] M →ₗ[R] R
v : Basis n R M
hO : IsOrthoᵢ B ⇑v
h : ∀ (i : n), ¬IsOrtho B (v i) (v i)
⊢ SeparatingRight B

Next tactic:
rw [isOrthoᵢ_flip] at hO
/-- Given an orthogonal basis with respect to a bilinear form, the bilinear form is right-separating
if the basis has no elements which are self-orthogonal. -/
theorem IsOrthoᵢ.separatingRight_iff_not_isOrtho_basis_self [NoZeroDivisors R]
    {B : M →ₗ[R] M →ₗ[R] R} (v : Basis n R M) (hO : B.IsOrthoᵢ v)
    (h : ∀ i, ¬B.IsOrtho (v i) (v i)) : B.SeparatingRight := by
  rw [isOrthoᵢ_flip] at hO
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
M : Type u_5
M₁ : Type u_6
M₂ : Type u_7
Mₗ₁ : Type u_8
Mₗ₁' : Type u_9
Mₗ₂ : Type u_10
Mₗ₂' : Type u_11
K : Type u_12
K₁ : Type u_13
K₂ : Type u_14
V : Type u_15
V₁ : Type u_16
V₂ : Type u_17
n : Type u_18
inst✝³ : CommRing R
inst✝² : AddCommGroup M
inst✝¹ : Module R M
I I' : R →+* R
inst✝ : NoZeroDivisors R
B : M →ₗ[R] M →ₗ[R] R
v : Basis n R M
hO : IsOrthoᵢ (flip B) ⇑v
h : ∀ (i : n), ¬IsOrtho B (v i) (v i)
⊢ SeparatingRight B

Next tactic:
rw [← flip_separatingLeft]
/-- Given an orthogonal basis with respect to a bilinear form, the bilinear form is right-separating
if the basis has no elements which are self-orthogonal. -/
theorem IsOrthoᵢ.separatingRight_iff_not_isOrtho_basis_self [NoZeroDivisors R]
    {B : M →ₗ[R] M →ₗ[R] R} (v : Basis n R M) (hO : B.IsOrthoᵢ v)
    (h : ∀ i, ¬B.IsOrtho (v i) (v i)) : B.SeparatingRight := by
  rw [isOrthoᵢ_flip] at hO
  rw [← flip_separatingLeft]
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
M : Type u_5
M₁ : Type u_6
M₂ : Type u_7
Mₗ₁ : Type u_8
Mₗ₁' : Type u_9
Mₗ₂ : Type u_10
Mₗ₂' : Type u_11
K : Type u_12
K₁ : Type u_13
K₂ : Type u_14
V : Type u_15
V₁ : Type u_16
V₂ : Type u_17
n : Type u_18
inst✝³ : CommRing R
inst✝² : AddCommGroup M
inst✝¹ : Module R M
I I' : R →+* R
inst✝ : NoZeroDivisors R
B : M →ₗ[R] M →ₗ[R] R
v : Basis n R M
hO : IsOrthoᵢ (flip B) ⇑v
h : ∀ (i : n), ¬IsOrtho B (v i) (v i)
⊢ SeparatingLeft (flip B)

Next tactic:
refine' IsOrthoᵢ.separatingLeft_of_not_isOrtho_basis_self v hO fun i ↦ _
/-- Given an orthogonal basis with respect to a bilinear form, the bilinear form is right-separating
if the basis has no elements which are self-orthogonal. -/
theorem IsOrthoᵢ.separatingRight_iff_not_isOrtho_basis_self [NoZeroDivisors R]
    {B : M →ₗ[R] M →ₗ[R] R} (v : Basis n R M) (hO : B.IsOrthoᵢ v)
    (h : ∀ i, ¬B.IsOrtho (v i) (v i)) : B.SeparatingRight := by
  rw [isOrthoᵢ_flip] at hO
  rw [← flip_separatingLeft]
  refine' IsOrthoᵢ.separatingLeft_of_not_isOrtho_basis_self v hO fun i ↦ _
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
M : Type u_5
M₁ : Type u_6
M₂ : Type u_7
Mₗ₁ : Type u_8
Mₗ₁' : Type u_9
Mₗ₂ : Type u_10
Mₗ₂' : Type u_11
K : Type u_12
K₁ : Type u_13
K₂ : Type u_14
V : Type u_15
V₁ : Type u_16
V₂ : Type u_17
n : Type u_18
inst✝³ : CommRing R
inst✝² : AddCommGroup M
inst✝¹ : Module R M
I I' : R →+* R
inst✝ : NoZeroDivisors R
B : M →ₗ[R] M →ₗ[R] R
v : Basis n R M
hO : IsOrthoᵢ (flip B) ⇑v
h : ∀ (i : n), ¬IsOrtho B (v i) (v i)
i : n
⊢ ¬IsOrtho (flip B) (v i) (v i)

Next tactic:
rw [isOrtho_flip]
/-- Given an orthogonal basis with respect to a bilinear form, the bilinear form is right-separating
if the basis has no elements which are self-orthogonal. -/
theorem IsOrthoᵢ.separatingRight_iff_not_isOrtho_basis_self [NoZeroDivisors R]
    {B : M →ₗ[R] M →ₗ[R] R} (v : Basis n R M) (hO : B.IsOrthoᵢ v)
    (h : ∀ i, ¬B.IsOrtho (v i) (v i)) : B.SeparatingRight := by
  rw [isOrthoᵢ_flip] at hO
  rw [← flip_separatingLeft]
  refine' IsOrthoᵢ.separatingLeft_of_not_isOrtho_basis_self v hO fun i ↦ _
  rw [isOrtho_flip]
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
R₃ : Type u_4
M : Type u_5
M₁ : Type u_6
M₂ : Type u_7
Mₗ₁ : Type u_8
Mₗ₁' : Type u_9
Mₗ₂ : Type u_10
Mₗ₂' : Type u_11
K : Type u_12
K₁ : Type u_13
K₂ : Type u_14
V : Type u_15
V₁ : Type u_16
V₂ : Type u_17
n : Type u_18
inst✝³ : CommRing R
inst✝² : AddCommGroup M
inst✝¹ : Module R M
I I' : R →+* R
inst✝ : NoZeroDivisors R
B : M →ₗ[R] M →ₗ[R] R
v : Basis n R M
hO : IsOrthoᵢ (flip B) ⇑v
h : ∀ (i : n), ¬IsOrtho B (v i) (v i)
i : n
⊢ ¬IsOrtho (flip (flip B)) (v i) (v i)

Next tactic:
exact h i
theorem one_lt_iff_ne_zero_and_ne_one : ∀ {n : ℕ}, 1 < n ↔ n ≠ 0 ∧ n ≠ 1
  | 0 => by 

Proof state:
m n k l : ℕ
⊢ 1 < 0 ↔ 0 ≠ 0 ∧ 0 ≠ 1

Next tactic:
decide
theorem one_lt_iff_ne_zero_and_ne_one : ∀ {n : ℕ}, 1 < n ↔ n ≠ 0 ∧ n ≠ 1
  | 0 => by decide
  | 1 => by 

Proof state:
m n k l : ℕ
⊢ 1 < 1 ↔ 1 ≠ 0 ∧ 1 ≠ 1

Next tactic:
decide
theorem one_lt_iff_ne_zero_and_ne_one : ∀ {n : ℕ}, 1 < n ↔ n ≠ 0 ∧ n ≠ 1
  | 0 => by decide
  | 1 => by decide
  | n + 2 => by 

Proof state:
m n✝ k l n : ℕ
⊢ 1 < n + 2 ↔ n + 2 ≠ 0 ∧ n + 2 ≠ 1

Next tactic:
simp
theorem le_one_iff_eq_zero_or_eq_one : ∀ {n : ℕ}, n ≤ 1 ↔ n = 0 ∨ n = 1
  | 0 => by 

Proof state:
m n k l : ℕ
⊢ 0 ≤ 1 ↔ 0 = 0 ∨ 0 = 1

Next tactic:
decide
theorem le_one_iff_eq_zero_or_eq_one : ∀ {n : ℕ}, n ≤ 1 ↔ n = 0 ∨ n = 1
  | 0 => by decide
  | 1 => by 

Proof state:
m n k l : ℕ
⊢ 1 ≤ 1 ↔ 1 = 0 ∨ 1 = 1

Next tactic:
decide
theorem le_one_iff_eq_zero_or_eq_one : ∀ {n : ℕ}, n ≤ 1 ↔ n = 0 ∨ n = 1
  | 0 => by decide
  | 1 => by decide
  | n + 2 => by 

Proof state:
m n✝ k l n : ℕ
⊢ n + 2 ≤ 1 ↔ n + 2 = 0 ∨ n + 2 = 1

Next tactic:
simp
protected theorem zero_eq_mul : 0 = m * n ↔ m = 0 ∨ n = 0 := by 

Proof state:
m n k l : ℕ
⊢ 0 = m * n ↔ m = 0 ∨ n = 0

Next tactic:
rw [eq_comm, Nat.mul_eq_zero]
theorem add_eq_max_iff : m + n = max m n ↔ m = 0 ∨ n = 0 := by
  

Proof state:
m n k l : ℕ
⊢ m + n = max m n ↔ m = 0 ∨ n = 0

Next tactic:
rw [← min_eq_zero_iff]
theorem add_eq_max_iff : m + n = max m n ↔ m = 0 ∨ n = 0 := by
  rw [← min_eq_zero_iff]
  

Proof state:
m n k l : ℕ
⊢ m + n = max m n ↔ min m n = 0

Next tactic:
rcases le_total m n with H | H
theorem add_eq_max_iff : m + n = max m n ↔ m = 0 ∨ n = 0 := by
  rw [← min_eq_zero_iff]
  rcases le_total m n with H | H <;> 

Proof state:
case inl
m n k l : ℕ
H : m ≤ n
⊢ m + n = max m n ↔ min m n = 0

Next tactic:
simp [H]
theorem add_eq_max_iff : m + n = max m n ↔ m = 0 ∨ n = 0 := by
  rw [← min_eq_zero_iff]
  rcases le_total m n with H | H <;> 

Proof state:
case inr
m n k l : ℕ
H : n ≤ m
⊢ m + n = max m n ↔ min m n = 0

Next tactic:
simp [H]
theorem add_eq_min_iff : m + n = min m n ↔ m = 0 ∧ n = 0 := by
  

Proof state:
m n k l : ℕ
⊢ m + n = min m n ↔ m = 0 ∧ n = 0

Next tactic:
rw [← max_eq_zero_iff]
theorem add_eq_min_iff : m + n = min m n ↔ m = 0 ∧ n = 0 := by
  rw [← max_eq_zero_iff]
  

Proof state:
m n k l : ℕ
⊢ m + n = min m n ↔ max m n = 0

Next tactic:
rcases le_total m n with H | H
theorem add_eq_min_iff : m + n = min m n ↔ m = 0 ∧ n = 0 := by
  rw [← max_eq_zero_iff]
  rcases le_total m n with H | H <;> 

Proof state:
case inl
m n k l : ℕ
H : m ≤ n
⊢ m + n = min m n ↔ max m n = 0

Next tactic:
simp [H]
theorem add_eq_min_iff : m + n = min m n ↔ m = 0 ∧ n = 0 := by
  rw [← max_eq_zero_iff]
  rcases le_total m n with H | H <;> 

Proof state:
case inr
m n k l : ℕ
H : n ≤ m
⊢ m + n = min m n ↔ max m n = 0

Next tactic:
simp [H]
theorem eq_one_of_mul_eq_one_left (H : m * n = 1) : n = 1 :=
  eq_one_of_mul_eq_one_right (by 

Proof state:
m n k l : ℕ
H : m * n = 1
⊢ n * ?m.12592 H = 1

Next tactic:
rwa [mul_comm]
theorem two_le_iff : ∀ n, 2 ≤ n ↔ n ≠ 0 ∧ n ≠ 1
  | 0 => by 

Proof state:
m n k l : ℕ
⊢ 2 ≤ 0 ↔ 0 ≠ 0 ∧ 0 ≠ 1

Next tactic:
simp
theorem two_le_iff : ∀ n, 2 ≤ n ↔ n ≠ 0 ∧ n ≠ 1
  | 0 => by simp
  | 1 => by 

Proof state:
m n k l : ℕ
⊢ 2 ≤ 1 ↔ 1 ≠ 0 ∧ 1 ≠ 1

Next tactic:
simp
theorem two_le_iff : ∀ n, 2 ≤ n ↔ n ≠ 0 ∧ n ≠ 1
  | 0 => by simp
  | 1 => by simp
  | n + 2 => by 

Proof state:
m n✝ k l n : ℕ
⊢ 2 ≤ n + 2 ↔ n + 2 ≠ 0 ∧ n + 2 ≠ 1

Next tactic:
simp
theorem add_pos_iff_pos_or_pos (m n : ℕ) : 0 < m + n ↔ 0 < m ∨ 0 < n :=
  Iff.intro
    (by
      

Proof state:
m✝ n✝ k l m n : ℕ
⊢ 0 < m + n → 0 < m ∨ 0 < n

Next tactic:
intro h
theorem add_pos_iff_pos_or_pos (m n : ℕ) : 0 < m + n ↔ 0 < m ∨ 0 < n :=
  Iff.intro
    (by
      intro h
      

Proof state:
m✝ n✝ k l m n : ℕ
h : 0 < m + n
⊢ 0 < m ∨ 0 < n

Next tactic:
cases' m with m
theorem add_pos_iff_pos_or_pos (m n : ℕ) : 0 < m + n ↔ 0 < m ∨ 0 < n :=
  Iff.intro
    (by
      intro h
      cases' m with m
      · 

Proof state:
case zero
m n✝ k l n : ℕ
h : 0 < zero + n
⊢ 0 < zero ∨ 0 < n

Next tactic:
simp [zero_add] at h
theorem add_pos_iff_pos_or_pos (m n : ℕ) : 0 < m + n ↔ 0 < m ∨ 0 < n :=
  Iff.intro
    (by
      intro h
      cases' m with m
      · simp [zero_add] at h
        

Proof state:
case zero
m n✝ k l n : ℕ
h : 0 < n
⊢ 0 < zero ∨ 0 < n

Next tactic:
exact Or.inr h
theorem add_pos_iff_pos_or_pos (m n : ℕ) : 0 < m + n ↔ 0 < m ∨ 0 < n :=
  Iff.intro
    (by
      intro h
      cases' m with m
      · simp [zero_add] at h
        exact Or.inr h
      

Proof state:
case succ
m✝ n✝ k l n m : ℕ
h : 0 < succ m + n
⊢ 0 < succ m ∨ 0 < n

Next tactic:
exact Or.inl (succ_pos _)
theorem add_pos_iff_pos_or_pos (m n : ℕ) : 0 < m + n ↔ 0 < m ∨ 0 < n :=
  Iff.intro
    (by
      intro h
      cases' m with m
      · simp [zero_add] at h
        exact Or.inr h
      exact Or.inl (succ_pos _))
    (by
      

Proof state:
m✝ n✝ k l m n : ℕ
⊢ 0 < m ∨ 0 < n → 0 < m + n

Next tactic:
intro h
theorem add_pos_iff_pos_or_pos (m n : ℕ) : 0 < m + n ↔ 0 < m ∨ 0 < n :=
  Iff.intro
    (by
      intro h
      cases' m with m
      · simp [zero_add] at h
        exact Or.inr h
      exact Or.inl (succ_pos _))
    (by
      intro h; 

Proof state:
m✝ n✝ k l m n : ℕ
h : 0 < m ∨ 0 < n
⊢ 0 < m + n

Next tactic:
cases' h with mpos npos
theorem add_pos_iff_pos_or_pos (m n : ℕ) : 0 < m + n ↔ 0 < m ∨ 0 < n :=
  Iff.intro
    (by
      intro h
      cases' m with m
      · simp [zero_add] at h
        exact Or.inr h
      exact Or.inl (succ_pos _))
    (by
      intro h; cases' h with mpos npos
      · 

Proof state:
case inl
m✝ n✝ k l m n : ℕ
mpos : 0 < m
⊢ 0 < m + n

Next tactic:
apply Nat.add_pos_left mpos
theorem add_pos_iff_pos_or_pos (m n : ℕ) : 0 < m + n ↔ 0 < m ∨ 0 < n :=
  Iff.intro
    (by
      intro h
      cases' m with m
      · simp [zero_add] at h
        exact Or.inr h
      exact Or.inl (succ_pos _))
    (by
      intro h; cases' h with mpos npos
      · apply Nat.add_pos_left mpos
      

Proof state:
case inr
m✝ n✝ k l m n : ℕ
npos : 0 < n
⊢ 0 < m + n

Next tactic:
apply Nat.add_pos_right _ npos
theorem add_eq_one_iff : m + n = 1 ↔ m = 0 ∧ n = 1 ∨ m = 1 ∧ n = 0 := by
  

Proof state:
m n k l : ℕ
⊢ m + n = 1 ↔ m = 0 ∧ n = 1 ∨ m = 1 ∧ n = 0

Next tactic:
cases n
theorem add_eq_one_iff : m + n = 1 ↔ m = 0 ∧ n = 1 ∨ m = 1 ∧ n = 0 := by
  cases n <;> 

Proof state:
case zero
m k l : ℕ
⊢ m + zero = 1 ↔ m = 0 ∧ zero = 1 ∨ m = 1 ∧ zero = 0

Next tactic:
simp [succ_eq_add_one, ← add_assoc, succ_inj']
theorem add_eq_one_iff : m + n = 1 ↔ m = 0 ∧ n = 1 ∨ m = 1 ∧ n = 0 := by
  cases n <;> 

Proof state:
case succ
m k l n✝ : ℕ
⊢ m + succ n✝ = 1 ↔ m = 0 ∧ succ n✝ = 1 ∨ m = 1 ∧ succ n✝ = 0

Next tactic:
simp [succ_eq_add_one, ← add_assoc, succ_inj']
theorem add_eq_two_iff : m + n = 2 ↔ m = 0 ∧ n = 2 ∨ m = 1 ∧ n = 1 ∨ m = 2 ∧ n = 0 := by
  

Proof state:
m n k l : ℕ
⊢ m + n = 2 ↔ m = 0 ∧ n = 2 ∨ m = 1 ∧ n = 1 ∨ m = 2 ∧ n = 0

Next tactic:
cases n
theorem add_eq_two_iff : m + n = 2 ↔ m = 0 ∧ n = 2 ∨ m = 1 ∧ n = 1 ∨ m = 2 ∧ n = 0 := by
  cases n <;>
  

Proof state:
case zero
m k l : ℕ
⊢ m + zero = 2 ↔ m = 0 ∧ zero = 2 ∨ m = 1 ∧ zero = 1 ∨ m = 2 ∧ zero = 0

Next tactic:
simp [(succ_ne_zero 1).symm, (show 2 = Nat.succ 1 from rfl),
    succ_eq_add_one, ← add_assoc, succ_inj', add_eq_one_iff]
theorem add_eq_two_iff : m + n = 2 ↔ m = 0 ∧ n = 2 ∨ m = 1 ∧ n = 1 ∨ m = 2 ∧ n = 0 := by
  cases n <;>
  

Proof state:
case succ
m k l n✝ : ℕ
⊢ m + succ n✝ = 2 ↔ m = 0 ∧ succ n✝ = 2 ∨ m = 1 ∧ succ n✝ = 1 ∨ m = 2 ∧ succ n✝ = 0

Next tactic:
simp [(succ_ne_zero 1).symm, (show 2 = Nat.succ 1 from rfl),
    succ_eq_add_one, ← add_assoc, succ_inj', add_eq_one_iff]
theorem add_eq_three_iff :
    m + n = 3 ↔ m = 0 ∧ n = 3 ∨ m = 1 ∧ n = 2 ∨ m = 2 ∧ n = 1 ∨ m = 3 ∧ n = 0 := by
  

Proof state:
m n k l : ℕ
⊢ m + n = 3 ↔ m = 0 ∧ n = 3 ∨ m = 1 ∧ n = 2 ∨ m = 2 ∧ n = 1 ∨ m = 3 ∧ n = 0

Next tactic:
cases n
theorem add_eq_three_iff :
    m + n = 3 ↔ m = 0 ∧ n = 3 ∨ m = 1 ∧ n = 2 ∨ m = 2 ∧ n = 1 ∨ m = 3 ∧ n = 0 := by
  cases n <;>
  

Proof state:
case zero
m k l : ℕ
⊢ m + zero = 3 ↔ m = 0 ∧ zero = 3 ∨ m = 1 ∧ zero = 2 ∨ m = 2 ∧ zero = 1 ∨ m = 3 ∧ zero = 0

Next tactic:
simp [(succ_ne_zero 1).symm, succ_eq_add_one, (show 3 = Nat.succ 2 from rfl),
    ← add_assoc, succ_inj', add_eq_two_iff]
theorem add_eq_three_iff :
    m + n = 3 ↔ m = 0 ∧ n = 3 ∨ m = 1 ∧ n = 2 ∨ m = 2 ∧ n = 1 ∨ m = 3 ∧ n = 0 := by
  cases n <;>
  

Proof state:
case succ
m k l n✝ : ℕ
⊢ m + succ n✝ = 3 ↔ m = 0 ∧ succ n✝ = 3 ∨ m = 1 ∧ succ n✝ = 2 ∨ m = 2 ∧ succ n✝ = 1 ∨ m = 3 ∧ succ n✝ = 0

Next tactic:
simp [(succ_ne_zero 1).symm, succ_eq_add_one, (show 3 = Nat.succ 2 from rfl),
    ← add_assoc, succ_inj', add_eq_two_iff]
theorem le_and_le_add_one_iff : n ≤ m ∧ m ≤ n + 1 ↔ m = n ∨ m = n + 1 := by
  

Proof state:
m n k l : ℕ
⊢ n ≤ m ∧ m ≤ n + 1 ↔ m = n ∨ m = n + 1

Next tactic:
rw [le_add_one_iff, and_or_left, ← le_antisymm_iff, eq_comm, and_iff_right_of_imp]
theorem le_and_le_add_one_iff : n ≤ m ∧ m ≤ n + 1 ↔ m = n ∨ m = n + 1 := by
  rw [le_add_one_iff, and_or_left, ← le_antisymm_iff, eq_comm, and_iff_right_of_imp]
  

Proof state:
m n k l : ℕ
⊢ m = n + 1 → n ≤ m

Next tactic:
rintro rfl
theorem le_and_le_add_one_iff : n ≤ m ∧ m ≤ n + 1 ↔ m = n ∨ m = n + 1 := by
  rw [le_add_one_iff, and_or_left, ← le_antisymm_iff, eq_comm, and_iff_right_of_imp]
  rintro rfl
  

Proof state:
n k l : ℕ
⊢ n ≤ n + 1

Next tactic:
exact n.le_succ
theorem add_succ_lt_add (hab : m < n) (hcd : k < l) : m + k + 1 < n + l := by
  

Proof state:
m n k l : ℕ
hab : m < n
hcd : k < l
⊢ m + k + 1 < n + l

Next tactic:
rw [add_assoc]
theorem add_succ_lt_add (hab : m < n) (hcd : k < l) : m + k + 1 < n + l := by
  rw [add_assoc]
  

Proof state:
m n k l : ℕ
hab : m < n
hcd : k < l
⊢ m + (k + 1) < n + l

Next tactic:
exact add_lt_add_of_lt_of_le hab (Nat.succ_le_iff.2 hcd)
theorem pred_le_iff : pred m ≤ n ↔ m ≤ succ n :=
  ⟨le_succ_of_pred_le, by
    

Proof state:
m n k l : ℕ
⊢ m ≤ succ n → pred m ≤ n

Next tactic:
cases m
theorem pred_le_iff : pred m ≤ n ↔ m ≤ succ n :=
  ⟨le_succ_of_pred_le, by
    cases m
    · 

Proof state:
case zero
n k l : ℕ
⊢ zero ≤ succ n → pred zero ≤ n

Next tactic:
exact fun _ => zero_le n
theorem pred_le_iff : pred m ≤ n ↔ m ≤ succ n :=
  ⟨le_succ_of_pred_le, by
    cases m
    · exact fun _ => zero_le n
    

Proof state:
case succ
n k l n✝ : ℕ
⊢ succ n✝ ≤ succ n → pred (succ n✝) ≤ n

Next tactic:
exact le_of_succ_le_succ
instance : OrderedSub ℕ := by
  

Proof state:
m n k l : ℕ
⊢ OrderedSub ℕ

Next tactic:
constructor
instance : OrderedSub ℕ := by
  constructor
  

Proof state:
case tsub_le_iff_right
m n k l : ℕ
⊢ ∀ (a b c : ℕ), a - b ≤ c ↔ a ≤ c + b

Next tactic:
intro m n k
instance : OrderedSub ℕ := by
  constructor
  intro m n k
  

Proof state:
case tsub_le_iff_right
m✝ n✝ k✝ l m n k : ℕ
⊢ m - n ≤ k ↔ m ≤ k + n

Next tactic:
induction' n with n ih generalizing k
instance : OrderedSub ℕ := by
  constructor
  intro m n k
  induction' n with n ih generalizing k
  · 

Proof state:
case tsub_le_iff_right.zero
m✝ n k✝ l m k : ℕ
⊢ m - zero ≤ k ↔ m ≤ k + zero

Next tactic:
simp
instance : OrderedSub ℕ := by
  constructor
  intro m n k
  induction' n with n ih generalizing k
  · simp
  · 

Proof state:
case tsub_le_iff_right.succ
m✝ n✝ k✝ l m n : ℕ
ih : ∀ (k : ℕ), m - n ≤ k ↔ m ≤ k + n
k : ℕ
⊢ m - succ n ≤ k ↔ m ≤ k + succ n

Next tactic:
simp only [sub_succ, pred_le_iff, ih, succ_add, add_succ]
theorem le_or_le_of_add_eq_add_pred (h : k + l = m + n - 1) : m ≤ k ∨ n ≤ l := by
  

Proof state:
m n k l : ℕ
h : k + l = m + n - 1
⊢ m ≤ k ∨ n ≤ l

Next tactic:
rcases le_or_lt m k with h' | h' <;> [left; right]
theorem le_or_le_of_add_eq_add_pred (h : k + l = m + n - 1) : m ≤ k ∨ n ≤ l := by
  

Proof state:
m n k l : ℕ
h : k + l = m + n - 1
⊢ m ≤ k ∨ n ≤ l

Next tactic:
rcases le_or_lt m k with h' | h'
theorem le_or_le_of_add_eq_add_pred (h : k + l = m + n - 1) : m ≤ k ∨ n ≤ l := by
  rcases le_or_lt m k with h' | h' <;> [

Proof state:
case inl
m n k l : ℕ
h : k + l = m + n - 1
h' : m ≤ k
⊢ m ≤ k ∨ n ≤ l

Next tactic:
left
theorem le_or_le_of_add_eq_add_pred (h : k + l = m + n - 1) : m ≤ k ∨ n ≤ l := by
  rcases le_or_lt m k with h' | h' <;> [left; 

Proof state:
case inr
m n k l : ℕ
h : k + l = m + n - 1
h' : k < m
⊢ m ≤ k ∨ n ≤ l

Next tactic:
right
theorem le_or_le_of_add_eq_add_pred (h : k + l = m + n - 1) : m ≤ k ∨ n ≤ l := by
  rcases le_or_lt m k with h' | h' <;> [left; right]
  · 

Proof state:
case inl.h
m n k l : ℕ
h : k + l = m + n - 1
h' : m ≤ k
⊢ m ≤ k

Next tactic:
exact h'
theorem le_or_le_of_add_eq_add_pred (h : k + l = m + n - 1) : m ≤ k ∨ n ≤ l := by
  rcases le_or_lt m k with h' | h' <;> [left; right]
  · exact h'
  · 

Proof state:
case inr.h
m n k l : ℕ
h : k + l = m + n - 1
h' : k < m
⊢ n ≤ l

Next tactic:
replace h' := add_lt_add_right h' l
theorem le_or_le_of_add_eq_add_pred (h : k + l = m + n - 1) : m ≤ k ∨ n ≤ l := by
  rcases le_or_lt m k with h' | h' <;> [left; right]
  · exact h'
  · replace h' := add_lt_add_right h' l
    

Proof state:
case inr.h
m n k l : ℕ
h : k + l = m + n - 1
h' : k + l < m + l
⊢ n ≤ l

Next tactic:
rw [h] at h'
theorem le_or_le_of_add_eq_add_pred (h : k + l = m + n - 1) : m ≤ k ∨ n ≤ l := by
  rcases le_or_lt m k with h' | h' <;> [left; right]
  · exact h'
  · replace h' := add_lt_add_right h' l
    rw [h] at h'
    

Proof state:
case inr.h
m n k l : ℕ
h : k + l = m + n - 1
h' : m + n - 1 < m + l
⊢ n ≤ l

Next tactic:
rcases n.eq_zero_or_pos with hn | hn
theorem le_or_le_of_add_eq_add_pred (h : k + l = m + n - 1) : m ≤ k ∨ n ≤ l := by
  rcases le_or_lt m k with h' | h' <;> [left; right]
  · exact h'
  · replace h' := add_lt_add_right h' l
    rw [h] at h'
    rcases n.eq_zero_or_pos with hn | hn
    · 

Proof state:
case inr.h.inl
m n k l : ℕ
h : k + l = m + n - 1
h' : m + n - 1 < m + l
hn : n = 0
⊢ n ≤ l

Next tactic:
rw [hn]
theorem le_or_le_of_add_eq_add_pred (h : k + l = m + n - 1) : m ≤ k ∨ n ≤ l := by
  rcases le_or_lt m k with h' | h' <;> [left; right]
  · exact h'
  · replace h' := add_lt_add_right h' l
    rw [h] at h'
    rcases n.eq_zero_or_pos with hn | hn
    · rw [hn]
      

Proof state:
case inr.h.inl
m n k l : ℕ
h : k + l = m + n - 1
h' : m + n - 1 < m + l
hn : n = 0
⊢ 0 ≤ l

Next tactic:
exact zero_le l
theorem le_or_le_of_add_eq_add_pred (h : k + l = m + n - 1) : m ≤ k ∨ n ≤ l := by
  rcases le_or_lt m k with h' | h' <;> [left; right]
  · exact h'
  · replace h' := add_lt_add_right h' l
    rw [h] at h'
    rcases n.eq_zero_or_pos with hn | hn
    · rw [hn]
      exact zero_le l
    

Proof state:
case inr.h.inr
m n k l : ℕ
h : k + l = m + n - 1
h' : m + n - 1 < m + l
hn : n > 0
⊢ n ≤ l

Next tactic:
rw [n.add_sub_assoc (Nat.succ_le_of_lt hn), add_lt_add_iff_left] at h'
theorem le_or_le_of_add_eq_add_pred (h : k + l = m + n - 1) : m ≤ k ∨ n ≤ l := by
  rcases le_or_lt m k with h' | h' <;> [left; right]
  · exact h'
  · replace h' := add_lt_add_right h' l
    rw [h] at h'
    rcases n.eq_zero_or_pos with hn | hn
    · rw [hn]
      exact zero_le l
    rw [n.add_sub_assoc (Nat.succ_le_of_lt hn), add_lt_add_iff_left] at h'
    

Proof state:
case inr.h.inr
m n k l : ℕ
h : k + l = m + n - 1
h' : n - succ 0 < l
hn : n > 0
⊢ n ≤ l

Next tactic:
exact Nat.le_of_pred_lt h'
theorem le_mul_self : ∀ n : ℕ, n ≤ n * n
  | 0 => le_rfl
  | n + 1 => by 

Proof state:
m n✝ k l n : ℕ
⊢ n + 1 ≤ (n + 1) * (n + 1)

Next tactic:
simp
theorem le_mul_of_pos_left (h : 0 < n) : m ≤ n * m := by
  

Proof state:
m n k l : ℕ
h : 0 < n
⊢ m ≤ n * m

Next tactic:
conv =>
    lhs
    rw [← one_mul m]
theorem le_mul_of_pos_left (h : 0 < n) : m ≤ n * m := by
  conv =>
    

Proof state:
m n k l : ℕ
h : 0 < n
| m ≤ n * m

Next tactic:
lhs
    rw [← one_mul m]
theorem le_mul_of_pos_left (h : 0 < n) : m ≤ n * m := by
  conv =>
    

Proof state:
m n k l : ℕ
h : 0 < n
| m ≤ n * m

Next tactic:
lhs
theorem le_mul_of_pos_left (h : 0 < n) : m ≤ n * m := by
  conv =>
    lhs
    

Proof state:
m n k l : ℕ
h : 0 < n
| m

Next tactic:
rw [← one_mul m]
theorem le_mul_of_pos_left (h : 0 < n) : m ≤ n * m := by
  conv =>
    lhs
    rw [← one_mul m]
  

Proof state:
m n k l : ℕ
h : 0 < n
⊢ 1 * m ≤ n * m

Next tactic:
exact mul_le_mul_of_nonneg_right h.nat_succ_le (zero_le _)