l3lab/ntp-mathlib huggingface dataset:
theorem pumping_lemma [Fintype σ] {x : List α} (hx : x ∈ M.accepts)
    (hlen : Fintype.card σ ≤ List.length x) :
    ∃ a b c,
      x = a ++ b ++ c ∧
        a.length + b.length ≤ Fintype.card σ ∧ b ≠ [] ∧ {a} * {b}∗ * {c} ≤ M.accepts := by
  obtain ⟨_, a, b, c, hx, hlen, hnil, rfl, hb, hc⟩ := M.evalFrom_split hlen rfl
  use a, b, c, hx, hlen, hnil
  intro y hy
  

Proof state:
case right
α : Type u
σ : Type v
M : DFA α σ
inst✝ : Fintype σ
x : List α
hx✝ : x ∈ accepts M
hlen✝ : Fintype.card σ ≤ List.length x
a b c : List α
hx : x = a ++ b ++ c
hlen : List.length a + List.length b ≤ Fintype.card σ
hnil : b ≠ []
hb : evalFrom M (evalFrom M ?m.8429 a) b = evalFrom M ?m.8429 a
hc : evalFrom M (evalFrom M ?m.8429 a) c = evalFrom M ?m.8429 x
y : List α
hy : y ∈ {a} * {b}∗ * {c}
⊢ y ∈ accepts M

Next tactic:
rw [Language.mem_mul] at hy
theorem pumping_lemma [Fintype σ] {x : List α} (hx : x ∈ M.accepts)
    (hlen : Fintype.card σ ≤ List.length x) :
    ∃ a b c,
      x = a ++ b ++ c ∧
        a.length + b.length ≤ Fintype.card σ ∧ b ≠ [] ∧ {a} * {b}∗ * {c} ≤ M.accepts := by
  obtain ⟨_, a, b, c, hx, hlen, hnil, rfl, hb, hc⟩ := M.evalFrom_split hlen rfl
  use a, b, c, hx, hlen, hnil
  intro y hy
  rw [Language.mem_mul] at hy
  

Proof state:
case right
α : Type u
σ : Type v
M : DFA α σ
inst✝ : Fintype σ
x : List α
hx✝ : x ∈ accepts M
hlen✝ : Fintype.card σ ≤ List.length x
a b c : List α
hx : x = a ++ b ++ c
hlen : List.length a + List.length b ≤ Fintype.card σ
hnil : b ≠ []
hb : evalFrom M (evalFrom M ?m.8429 a) b = evalFrom M ?m.8429 a
hc : evalFrom M (evalFrom M ?m.8429 a) c = evalFrom M ?m.8429 x
y : List α
hy : ∃ a_1 b_1, a_1 ∈ {a} * {b}∗ ∧ b_1 ∈ {c} ∧ a_1 ++ b_1 = y
⊢ y ∈ accepts M

Next tactic:
rcases hy with ⟨ab, c', hab, hc', rfl⟩
theorem pumping_lemma [Fintype σ] {x : List α} (hx : x ∈ M.accepts)
    (hlen : Fintype.card σ ≤ List.length x) :
    ∃ a b c,
      x = a ++ b ++ c ∧
        a.length + b.length ≤ Fintype.card σ ∧ b ≠ [] ∧ {a} * {b}∗ * {c} ≤ M.accepts := by
  obtain ⟨_, a, b, c, hx, hlen, hnil, rfl, hb, hc⟩ := M.evalFrom_split hlen rfl
  use a, b, c, hx, hlen, hnil
  intro y hy
  rw [Language.mem_mul] at hy
  rcases hy with ⟨ab, c', hab, hc', rfl⟩
  

Proof state:
case right.intro.intro.intro.intro
α : Type u
σ : Type v
M : DFA α σ
inst✝ : Fintype σ
x : List α
hx✝ : x ∈ accepts M
hlen✝ : Fintype.card σ ≤ List.length x
a b c : List α
hx : x = a ++ b ++ c
hlen : List.length a + List.length b ≤ Fintype.card σ
hnil : b ≠ []
hb : evalFrom M (evalFrom M ?m.8429 a) b = evalFrom M ?m.8429 a
hc : evalFrom M (evalFrom M ?m.8429 a) c = evalFrom M ?m.8429 x
ab c' : List α
hab : ab ∈ {a} * {b}∗
hc' : c' ∈ {c}
⊢ ab ++ c' ∈ accepts M

Next tactic:
rw [Language.mem_mul] at hab
theorem pumping_lemma [Fintype σ] {x : List α} (hx : x ∈ M.accepts)
    (hlen : Fintype.card σ ≤ List.length x) :
    ∃ a b c,
      x = a ++ b ++ c ∧
        a.length + b.length ≤ Fintype.card σ ∧ b ≠ [] ∧ {a} * {b}∗ * {c} ≤ M.accepts := by
  obtain ⟨_, a, b, c, hx, hlen, hnil, rfl, hb, hc⟩ := M.evalFrom_split hlen rfl
  use a, b, c, hx, hlen, hnil
  intro y hy
  rw [Language.mem_mul] at hy
  rcases hy with ⟨ab, c', hab, hc', rfl⟩
  rw [Language.mem_mul] at hab
  

Proof state:
case right.intro.intro.intro.intro
α : Type u
σ : Type v
M : DFA α σ
inst✝ : Fintype σ
x : List α
hx✝ : x ∈ accepts M
hlen✝ : Fintype.card σ ≤ List.length x
a b c : List α
hx : x = a ++ b ++ c
hlen : List.length a + List.length b ≤ Fintype.card σ
hnil : b ≠ []
hb : evalFrom M (evalFrom M ?m.8429 a) b = evalFrom M ?m.8429 a
hc : evalFrom M (evalFrom M ?m.8429 a) c = evalFrom M ?m.8429 x
ab c' : List α
hab : ∃ a_1 b_1, a_1 ∈ {a} ∧ b_1 ∈ {b}∗ ∧ a_1 ++ b_1 = ab
hc' : c' ∈ {c}
⊢ ab ++ c' ∈ accepts M

Next tactic:
rcases hab with ⟨a', b', ha', hb', rfl⟩
theorem pumping_lemma [Fintype σ] {x : List α} (hx : x ∈ M.accepts)
    (hlen : Fintype.card σ ≤ List.length x) :
    ∃ a b c,
      x = a ++ b ++ c ∧
        a.length + b.length ≤ Fintype.card σ ∧ b ≠ [] ∧ {a} * {b}∗ * {c} ≤ M.accepts := by
  obtain ⟨_, a, b, c, hx, hlen, hnil, rfl, hb, hc⟩ := M.evalFrom_split hlen rfl
  use a, b, c, hx, hlen, hnil
  intro y hy
  rw [Language.mem_mul] at hy
  rcases hy with ⟨ab, c', hab, hc', rfl⟩
  rw [Language.mem_mul] at hab
  rcases hab with ⟨a', b', ha', hb', rfl⟩
  

Proof state:
case right.intro.intro.intro.intro.intro.intro.intro.intro
α : Type u
σ : Type v
M : DFA α σ
inst✝ : Fintype σ
x : List α
hx✝ : x ∈ accepts M
hlen✝ : Fintype.card σ ≤ List.length x
a b c : List α
hx : x = a ++ b ++ c
hlen : List.length a + List.length b ≤ Fintype.card σ
hnil : b ≠ []
hb : evalFrom M (evalFrom M ?m.8429 a) b = evalFrom M ?m.8429 a
hc : evalFrom M (evalFrom M ?m.8429 a) c = evalFrom M ?m.8429 x
c' : List α
hc' : c' ∈ {c}
a' b' : List α
ha' : a' ∈ {a}
hb' : b' ∈ {b}∗
⊢ a' ++ b' ++ c' ∈ accepts M

Next tactic:
rw [Set.mem_singleton_iff] at ha' hc'
theorem pumping_lemma [Fintype σ] {x : List α} (hx : x ∈ M.accepts)
    (hlen : Fintype.card σ ≤ List.length x) :
    ∃ a b c,
      x = a ++ b ++ c ∧
        a.length + b.length ≤ Fintype.card σ ∧ b ≠ [] ∧ {a} * {b}∗ * {c} ≤ M.accepts := by
  obtain ⟨_, a, b, c, hx, hlen, hnil, rfl, hb, hc⟩ := M.evalFrom_split hlen rfl
  use a, b, c, hx, hlen, hnil
  intro y hy
  rw [Language.mem_mul] at hy
  rcases hy with ⟨ab, c', hab, hc', rfl⟩
  rw [Language.mem_mul] at hab
  rcases hab with ⟨a', b', ha', hb', rfl⟩
  rw [Set.mem_singleton_iff] at ha' hc'
  

Proof state:
case right.intro.intro.intro.intro.intro.intro.intro.intro
α : Type u
σ : Type v
M : DFA α σ
inst✝ : Fintype σ
x : List α
hx✝ : x ∈ accepts M
hlen✝ : Fintype.card σ ≤ List.length x
a b c : List α
hx : x = a ++ b ++ c
hlen : List.length a + List.length b ≤ Fintype.card σ
hnil : b ≠ []
hb : evalFrom M (evalFrom M ?m.8429 a) b = evalFrom M ?m.8429 a
hc : evalFrom M (evalFrom M ?m.8429 a) c = evalFrom M ?m.8429 x
c' : List α
hc' : c' = c
a' b' : List α
ha' : a' = a
hb' : b' ∈ {b}∗
⊢ a' ++ b' ++ c' ∈ accepts M

Next tactic:
substs ha' hc'
theorem pumping_lemma [Fintype σ] {x : List α} (hx : x ∈ M.accepts)
    (hlen : Fintype.card σ ≤ List.length x) :
    ∃ a b c,
      x = a ++ b ++ c ∧
        a.length + b.length ≤ Fintype.card σ ∧ b ≠ [] ∧ {a} * {b}∗ * {c} ≤ M.accepts := by
  obtain ⟨_, a, b, c, hx, hlen, hnil, rfl, hb, hc⟩ := M.evalFrom_split hlen rfl
  use a, b, c, hx, hlen, hnil
  intro y hy
  rw [Language.mem_mul] at hy
  rcases hy with ⟨ab, c', hab, hc', rfl⟩
  rw [Language.mem_mul] at hab
  rcases hab with ⟨a', b', ha', hb', rfl⟩
  rw [Set.mem_singleton_iff] at ha' hc'
  substs ha' hc'
  

Proof state:
case right.intro.intro.intro.intro.intro.intro.intro.intro
α : Type u
σ : Type v
M : DFA α σ
inst✝ : Fintype σ
x : List α
hx✝ : x ∈ accepts M
hlen✝ : Fintype.card σ ≤ List.length x
b : List α
hnil : b ≠ []
c' a' b' : List α
hb' : b' ∈ {b}∗
hlen : List.length a' + List.length b ≤ Fintype.card σ
hb : evalFrom M (evalFrom M ?m.8429 a') b = evalFrom M ?m.8429 a'
hx : x = a' ++ b ++ c'
hc : evalFrom M (evalFrom M ?m.8429 a') c' = evalFrom M ?m.8429 x
⊢ a' ++ b' ++ c' ∈ accepts M

Next tactic:
have h := M.evalFrom_of_pow hb hb'
theorem pumping_lemma [Fintype σ] {x : List α} (hx : x ∈ M.accepts)
    (hlen : Fintype.card σ ≤ List.length x) :
    ∃ a b c,
      x = a ++ b ++ c ∧
        a.length + b.length ≤ Fintype.card σ ∧ b ≠ [] ∧ {a} * {b}∗ * {c} ≤ M.accepts := by
  obtain ⟨_, a, b, c, hx, hlen, hnil, rfl, hb, hc⟩ := M.evalFrom_split hlen rfl
  use a, b, c, hx, hlen, hnil
  intro y hy
  rw [Language.mem_mul] at hy
  rcases hy with ⟨ab, c', hab, hc', rfl⟩
  rw [Language.mem_mul] at hab
  rcases hab with ⟨a', b', ha', hb', rfl⟩
  rw [Set.mem_singleton_iff] at ha' hc'
  substs ha' hc'
  have h := M.evalFrom_of_pow hb hb'
  

Proof state:
case right.intro.intro.intro.intro.intro.intro.intro.intro
α : Type u
σ : Type v
M : DFA α σ
inst✝ : Fintype σ
x : List α
hx✝ : x ∈ accepts M
hlen✝ : Fintype.card σ ≤ List.length x
b : List α
hnil : b ≠ []
c' a' b' : List α
hb' : b' ∈ {b}∗
hlen : List.length a' + List.length b ≤ Fintype.card σ
hb : evalFrom M (evalFrom M ?m.8429 a') b = evalFrom M ?m.8429 a'
hx : x = a' ++ b ++ c'
hc : evalFrom M (evalFrom M ?m.8429 a') c' = evalFrom M ?m.8429 x
h : evalFrom M (evalFrom M ?m.8429 a') b' = evalFrom M ?m.8429 a'
⊢ a' ++ b' ++ c' ∈ accepts M

Next tactic:
rwa [mem_accepts, evalFrom_of_append, evalFrom_of_append, h, hc]
@[to_additive (attr := ext)]
theorem MulOneClass.ext {M : Type u} : ∀ ⦃m₁ m₂ : MulOneClass M⦄, m₁.mul = m₂.mul → m₁ = m₂ := by
  

Proof state:
G : Type u_1
M : Type u
⊢ ∀ ⦃m₁ m₂ : MulOneClass M⦄, Mul.mul = Mul.mul → m₁ = m₂

Next tactic:
rintro @⟨⟨one₁⟩, ⟨mul₁⟩, one_mul₁, mul_one₁⟩ @⟨⟨one₂⟩, ⟨mul₂⟩, one_mul₂, mul_one₂⟩ ⟨rfl⟩
@[to_additive (attr := ext)]
theorem MulOneClass.ext {M : Type u} : ∀ ⦃m₁ m₂ : MulOneClass M⦄, m₁.mul = m₂.mul → m₁ = m₂ := by
  rintro @⟨⟨one₁⟩, ⟨mul₁⟩, one_mul₁, mul_one₁⟩ @⟨⟨one₂⟩, ⟨mul₂⟩, one_mul₂, mul_one₂⟩ ⟨rfl⟩
  -- FIXME (See https://github.com/leanprover/lean4/issues/1711)
  -- congr
  

Proof state:
case mk.mk.mk.mk.mk.mk.refl
G : Type u_1
M : Type u
one₁ : M
mul₁ : M → M → M
one_mul₁ : ∀ (a : M), 1 * a = a
mul_one₁ : ∀ (a : M), a * 1 = a
one₂ : M
one_mul₂ : ∀ (a : M), 1 * a = a
mul_one₂ : ∀ (a : M), a * 1 = a
⊢ mk one_mul₁ mul_one₁ = mk one_mul₂ mul_one₂

Next tactic:
suffices one₁ = one₂ by cases this; rfl
@[to_additive (attr := ext)]
theorem MulOneClass.ext {M : Type u} : ∀ ⦃m₁ m₂ : MulOneClass M⦄, m₁.mul = m₂.mul → m₁ = m₂ := by
  rintro @⟨⟨one₁⟩, ⟨mul₁⟩, one_mul₁, mul_one₁⟩ @⟨⟨one₂⟩, ⟨mul₂⟩, one_mul₂, mul_one₂⟩ ⟨rfl⟩
  -- FIXME (See https://github.com/leanprover/lean4/issues/1711)
  -- congr
  suffices one₁ = one₂ by 

Proof state:
G : Type u_1
M : Type u
one₁ : M
mul₁ : M → M → M
one_mul₁ : ∀ (a : M), 1 * a = a
mul_one₁ : ∀ (a : M), a * 1 = a
one₂ : M
one_mul₂ : ∀ (a : M), 1 * a = a
mul_one₂ : ∀ (a : M), a * 1 = a
this : one₁ = one₂
⊢ mk one_mul₁ mul_one₁ = mk one_mul₂ mul_one₂

Next tactic:
cases this
@[to_additive (attr := ext)]
theorem MulOneClass.ext {M : Type u} : ∀ ⦃m₁ m₂ : MulOneClass M⦄, m₁.mul = m₂.mul → m₁ = m₂ := by
  rintro @⟨⟨one₁⟩, ⟨mul₁⟩, one_mul₁, mul_one₁⟩ @⟨⟨one₂⟩, ⟨mul₂⟩, one_mul₂, mul_one₂⟩ ⟨rfl⟩
  -- FIXME (See https://github.com/leanprover/lean4/issues/1711)
  -- congr
  suffices one₁ = one₂ by cases this; 

Proof state:
case refl
G : Type u_1
M : Type u
one₁ : M
mul₁ : M → M → M
one_mul₁ : ∀ (a : M), 1 * a = a
mul_one₁ : ∀ (a : M), a * 1 = a
one_mul₂ : ∀ (a : M), 1 * a = a
mul_one₂ : ∀ (a : M), a * 1 = a
⊢ mk one_mul₁ mul_one₁ = mk one_mul₂ mul_one₂

Next tactic:
rfl
@[to_additive (attr := ext)]
theorem MulOneClass.ext {M : Type u} : ∀ ⦃m₁ m₂ : MulOneClass M⦄, m₁.mul = m₂.mul → m₁ = m₂ := by
  rintro @⟨⟨one₁⟩, ⟨mul₁⟩, one_mul₁, mul_one₁⟩ @⟨⟨one₂⟩, ⟨mul₂⟩, one_mul₂, mul_one₂⟩ ⟨rfl⟩
  -- FIXME (See https://github.com/leanprover/lean4/issues/1711)
  -- congr
  suffices one₁ = one₂ by cases this; rfl
  

Proof state:
case mk.mk.mk.mk.mk.mk.refl
G : Type u_1
M : Type u
one₁ : M
mul₁ : M → M → M
one_mul₁ : ∀ (a : M), 1 * a = a
mul_one₁ : ∀ (a : M), a * 1 = a
one₂ : M
one_mul₂ : ∀ (a : M), 1 * a = a
mul_one₂ : ∀ (a : M), a * 1 = a
⊢ one₁ = one₂

Next tactic:
exact (one_mul₂ one₁).symm.trans (mul_one₁ one₂)
@[to_additive]
theorem left_inv_eq_right_inv {a b c : M} (hba : b * a = 1) (hac : a * c = 1) : b = c := by
  

Proof state:
G : Type u_1
M : Type u
inst✝ : Monoid M
a b c : M
hba : b * a = 1
hac : a * c = 1
⊢ b = c

Next tactic:
rw [← one_mul c, ← hba, mul_assoc, hac, mul_one b]
theorem zpow_negSucc (a : G) (n : ℕ) : a ^ (Int.negSucc n) = (a ^ (n + 1))⁻¹ := by
  

Proof state:
G : Type u_1
inst✝ : DivInvMonoid G
a✝ b a : G
n : ℕ
⊢ a ^ Int.negSucc n = (a ^ (n + 1))⁻¹

Next tactic:
rw [← zpow_ofNat]
theorem zpow_negSucc (a : G) (n : ℕ) : a ^ (Int.negSucc n) = (a ^ (n + 1))⁻¹ := by
  rw [← zpow_ofNat]
  

Proof state:
G : Type u_1
inst✝ : DivInvMonoid G
a✝ b a : G
n : ℕ
⊢ a ^ Int.negSucc n = (a ^ ↑(n + 1))⁻¹

Next tactic:
exact DivInvMonoid.zpow_neg' n a
theorem negSucc_zsmul {G} [SubNegMonoid G] (a : G) (n : ℕ) :
    Int.negSucc n • a = -((n + 1) • a) := by
  

Proof state:
G✝ : Type u_1
inst✝¹ : DivInvMonoid G✝
a✝ b : G✝
G : Type u_2
inst✝ : SubNegMonoid G
a : G
n : ℕ
⊢ Int.negSucc n • a = -((n + 1) • a)

Next tactic:
rw [← ofNat_zsmul]
theorem negSucc_zsmul {G} [SubNegMonoid G] (a : G) (n : ℕ) :
    Int.negSucc n • a = -((n + 1) • a) := by
  rw [← ofNat_zsmul]
  

Proof state:
G✝ : Type u_1
inst✝¹ : DivInvMonoid G✝
a✝ b : G✝
G : Type u_2
inst✝ : SubNegMonoid G
a : G
n : ℕ
⊢ Int.negSucc n • a = -(↑(n + 1) • a)

Next tactic:
exact SubNegMonoid.zsmul_neg' n a
@[to_additive]
theorem inv_eq_of_mul_eq_one_left (h : a * b = 1) : b⁻¹ = a :=
  by 

Proof state:
G : Type u_1
inst✝ : DivisionMonoid G
a b : G
h : a * b = 1
⊢ b⁻¹ = a

Next tactic:
rw [← inv_eq_of_mul_eq_one_right h, inv_inv]
@[to_additive (attr := simp)]
theorem mul_right_inv (a : G) : a * a⁻¹ = 1 :=
  by 

Proof state:
G : Type u_1
inst✝ : Group G
a✝ b c a : G
⊢ a * a⁻¹ = 1

Next tactic:
rw [← mul_left_inv a⁻¹, inv_eq_of_mul (mul_left_inv a)]
@[to_additive (attr := simp)]
theorem inv_mul_cancel_left (a b : G) : a⁻¹ * (a * b) = b :=
  by 

Proof state:
G : Type u_1
inst✝ : Group G
a✝ b✝ c a b : G
⊢ a⁻¹ * (a * b) = b

Next tactic:
rw [← mul_assoc, mul_left_inv, one_mul]
@[to_additive (attr := simp)]
theorem mul_inv_cancel_left (a b : G) : a * (a⁻¹ * b) = b :=
  by 

Proof state:
G : Type u_1
inst✝ : Group G
a✝ b✝ c a b : G
⊢ a * (a⁻¹ * b) = b

Next tactic:
rw [← mul_assoc, mul_right_inv, one_mul]
@[to_additive (attr := simp)]
theorem mul_inv_cancel_right (a b : G) : a * b * b⁻¹ = a :=
  by 

Proof state:
G : Type u_1
inst✝ : Group G
a✝ b✝ c a b : G
⊢ a * b * b⁻¹ = a

Next tactic:
rw [mul_assoc, mul_right_inv, mul_one]
@[to_additive (attr := simp)]
theorem inv_mul_cancel_right (a b : G) : a * b⁻¹ * b = a :=
  by 

Proof state:
G : Type u_1
inst✝ : Group G
a✝ b✝ c a b : G
⊢ a * b⁻¹ * b = a

Next tactic:
rw [mul_assoc, mul_left_inv, mul_one]
@[to_additive AddGroup.toSubtractionMonoid]
instance (priority := 100) Group.toDivisionMonoid : DivisionMonoid G :=
  { inv_inv := fun a ↦ inv_eq_of_mul (mul_left_inv a)
    mul_inv_rev :=
      fun a b ↦ inv_eq_of_mul <| by 

Proof state:
G : Type u_1
inst✝ : Group G
a✝ b✝ c a b : G
⊢ a * b * (b⁻¹ * a⁻¹) = 1

Next tactic:
rw [mul_assoc, mul_inv_cancel_left, mul_right_inv]
@[to_additive]
instance (priority := 100) Group.toCancelMonoid : CancelMonoid G :=
  { ‹Group G› with
    mul_right_cancel := fun a b c h ↦ by rw [← mul_inv_cancel_right a b, h, mul_inv_cancel_right]
    mul_left_cancel := fun a b c h ↦ by 

Proof state:
G : Type u_1
inst✝ : Group G
a✝ b✝ c✝ : G
src✝ : Group G := inst✝
a b c : G
h : a * b = a * c
⊢ b = c

Next tactic:
rw [← inv_mul_cancel_left a b, h, inv_mul_cancel_left]
@[to_additive]
instance (priority := 100) Group.toCancelMonoid : CancelMonoid G :=
  { ‹Group G› with
    mul_right_cancel := fun a b c h ↦ by 

Proof state:
G : Type u_1
inst✝ : Group G
a✝ b✝ c✝ : G
src✝ : Group G := inst✝
a b c : G
h : a * b = c * b
⊢ a = c

Next tactic:
rw [← mul_inv_cancel_right a b, h, mul_inv_cancel_right]
@[to_additive]
theorem Group.toDivInvMonoid_injective {G : Type*} :
    Function.Injective (@Group.toDivInvMonoid G) := by 

Proof state:
G✝ : Type u_1
G : Type u_2
⊢ Injective (@toDivInvMonoid G)

Next tactic:
rintro ⟨⟩ ⟨⟩ ⟨⟩
@[to_additive]
theorem Group.toDivInvMonoid_injective {G : Type*} :
    Function.Injective (@Group.toDivInvMonoid G) := by rintro ⟨⟩ ⟨⟩ ⟨⟩; 

Proof state:
case mk.mk.refl
G✝ : Type u_1
G : Type u_2
toDivInvMonoid✝ : DivInvMonoid G
mul_left_inv✝¹ mul_left_inv✝ : ∀ (a : G), a⁻¹ * a = 1
⊢ mk mul_left_inv✝¹ = mk mul_left_inv✝

Next tactic:
rfl
@[to_additive]
theorem CommGroup.toGroup_injective {G : Type u} : Function.Injective (@CommGroup.toGroup G) := by
  

Proof state:
G✝ : Type u_1
G : Type u
⊢ Injective (@toGroup G)

Next tactic:
rintro ⟨⟩ ⟨⟩ ⟨⟩
@[to_additive]
theorem CommGroup.toGroup_injective {G : Type u} : Function.Injective (@CommGroup.toGroup G) := by
  rintro ⟨⟩ ⟨⟩ ⟨⟩; 

Proof state:
case mk.mk.refl
G✝ : Type u_1
G : Type u
toGroup✝ : Group G
mul_comm✝¹ mul_comm✝ : ∀ (a b : G), a * b = b * a
⊢ mk mul_comm✝¹ = mk mul_comm✝

Next tactic:
rfl
theorem disjoint_span_sum : Disjoint (span R (range (u ∘ Sum.inl)))
    (span R (range (u ∘ Sum.inr))) := by
  

Proof state:
ι : Type u_1
ι' : Type u_2
R : Type u_3
inst✝ : Ring R
S : ShortComplex (ModuleCat R)
hS : ShortComplex.Exact S
hS' : ShortComplex.ShortExact S
v : ι → ↑S.X₁
hv : LinearIndependent R v
u : ι ⊕ ι' → ↑S.X₂
hw : LinearIndependent R (⇑S.g ∘ u ∘ Sum.inr)
hm : Mono S.f
huv : u ∘ Sum.inl = ⇑S.f ∘ v
⊢ Disjoint (span R (range (u ∘ Sum.inl))) (span R (range (u ∘ Sum.inr)))

Next tactic:
rw [huv, disjoint_comm]
theorem disjoint_span_sum : Disjoint (span R (range (u ∘ Sum.inl)))
    (span R (range (u ∘ Sum.inr))) := by
  rw [huv, disjoint_comm]
  

Proof state:
ι : Type u_1
ι' : Type u_2
R : Type u_3
inst✝ : Ring R
S : ShortComplex (ModuleCat R)
hS : ShortComplex.Exact S
hS' : ShortComplex.ShortExact S
v : ι → ↑S.X₁
hv : LinearIndependent R v
u : ι ⊕ ι' → ↑S.X₂
hw : LinearIndependent R (⇑S.g ∘ u ∘ Sum.inr)
hm : Mono S.f
huv : u ∘ Sum.inl = ⇑S.f ∘ v
⊢ Disjoint (span R (range (u ∘ Sum.inr))) (span R (range (⇑S.f ∘ v)))

Next tactic:
refine' Disjoint.mono_right (span_mono (range_comp_subset_range _ _)) _
theorem disjoint_span_sum : Disjoint (span R (range (u ∘ Sum.inl)))
    (span R (range (u ∘ Sum.inr))) := by
  rw [huv, disjoint_comm]
  refine' Disjoint.mono_right (span_mono (range_comp_subset_range _ _)) _
  

Proof state:
ι : Type u_1
ι' : Type u_2
R : Type u_3
inst✝ : Ring R
S : ShortComplex (ModuleCat R)
hS : ShortComplex.Exact S
hS' : ShortComplex.ShortExact S
v : ι → ↑S.X₁
hv : LinearIndependent R v
u : ι ⊕ ι' → ↑S.X₂
hw : LinearIndependent R (⇑S.g ∘ u ∘ Sum.inr)
hm : Mono S.f
huv : u ∘ Sum.inl = ⇑S.f ∘ v
⊢ Disjoint (span R (range (u ∘ Sum.inr))) (span R (range ⇑S.f))

Next tactic:
rw [← LinearMap.range_coe, (span_eq (LinearMap.range S.f)), hS.moduleCat_range_eq_ker]
theorem disjoint_span_sum : Disjoint (span R (range (u ∘ Sum.inl)))
    (span R (range (u ∘ Sum.inr))) := by
  rw [huv, disjoint_comm]
  refine' Disjoint.mono_right (span_mono (range_comp_subset_range _ _)) _
  rw [← LinearMap.range_coe, (span_eq (LinearMap.range S.f)), hS.moduleCat_range_eq_ker]
  

Proof state:
ι : Type u_1
ι' : Type u_2
R : Type u_3
inst✝ : Ring R
S : ShortComplex (ModuleCat R)
hS : ShortComplex.Exact S
hS' : ShortComplex.ShortExact S
v : ι → ↑S.X₁
hv : LinearIndependent R v
u : ι ⊕ ι' → ↑S.X₂
hw : LinearIndependent R (⇑S.g ∘ u ∘ Sum.inr)
hm : Mono S.f
huv : u ∘ Sum.inl = ⇑S.f ∘ v
⊢ Disjoint (span R (range (u ∘ Sum.inr))) (LinearMap.ker S.g)

Next tactic:
exact range_ker_disjoint hw
/-- In the commutative diagram
```
             f     g
    0 --→ X₁ --→ X₂ --→ X₃
          ↑      ↑      ↑
         v|     u|     w|
          ι  → ι ⊕ ι' ← ι'
```
where the top row is an exact sequence of modules and the maps on the bottom are `Sum.inl` and
`Sum.inr`. If `u` is injective and `v` and `w` are linearly independent, then `u` is linearly
independent. -/
theorem linearIndependent_leftExact : LinearIndependent R u := by
  

Proof state:
ι : Type u_1
ι' : Type u_2
R : Type u_3
inst✝ : Ring R
S : ShortComplex (ModuleCat R)
hS : ShortComplex.Exact S
hS' : ShortComplex.ShortExact S
v : ι → ↑S.X₁
hv : LinearIndependent R v
u : ι ⊕ ι' → ↑S.X₂
hw : LinearIndependent R (⇑S.g ∘ u ∘ Sum.inr)
hm : Mono S.f
huv : u ∘ Sum.inl = ⇑S.f ∘ v
⊢ LinearIndependent R u

Next tactic:
rw [linearIndependent_sum]
/-- In the commutative diagram
```
             f     g
    0 --→ X₁ --→ X₂ --→ X₃
          ↑      ↑      ↑
         v|     u|     w|
          ι  → ι ⊕ ι' ← ι'
```
where the top row is an exact sequence of modules and the maps on the bottom are `Sum.inl` and
`Sum.inr`. If `u` is injective and `v` and `w` are linearly independent, then `u` is linearly
independent. -/
theorem linearIndependent_leftExact : LinearIndependent R u := by
  rw [linearIndependent_sum]
  

Proof state:
ι : Type u_1
ι' : Type u_2
R : Type u_3
inst✝ : Ring R
S : ShortComplex (ModuleCat R)
hS : ShortComplex.Exact S
hS' : ShortComplex.ShortExact S
v : ι → ↑S.X₁
hv : LinearIndependent R v
u : ι ⊕ ι' → ↑S.X₂
hw : LinearIndependent R (⇑S.g ∘ u ∘ Sum.inr)
hm : Mono S.f
huv : u ∘ Sum.inl = ⇑S.f ∘ v
⊢ LinearIndependent R (u ∘ Sum.inl) ∧
    LinearIndependent R (u ∘ Sum.inr) ∧ Disjoint (span R (range (u ∘ Sum.inl))) (span R (range (u ∘ Sum.inr)))

Next tactic:
refine' ⟨_, LinearIndependent.of_comp S.g hw, disjoint_span_sum hS hw huv⟩
/-- In the commutative diagram
```
             f     g
    0 --→ X₁ --→ X₂ --→ X₃
          ↑      ↑      ↑
         v|     u|     w|
          ι  → ι ⊕ ι' ← ι'
```
where the top row is an exact sequence of modules and the maps on the bottom are `Sum.inl` and
`Sum.inr`. If `u` is injective and `v` and `w` are linearly independent, then `u` is linearly
independent. -/
theorem linearIndependent_leftExact : LinearIndependent R u := by
  rw [linearIndependent_sum]
  refine' ⟨_, LinearIndependent.of_comp S.g hw, disjoint_span_sum hS hw huv⟩
  

Proof state:
ι : Type u_1
ι' : Type u_2
R : Type u_3
inst✝ : Ring R
S : ShortComplex (ModuleCat R)
hS : ShortComplex.Exact S
hS' : ShortComplex.ShortExact S
v : ι → ↑S.X₁
hv : LinearIndependent R v
u : ι ⊕ ι' → ↑S.X₂
hw : LinearIndependent R (⇑S.g ∘ u ∘ Sum.inr)
hm : Mono S.f
huv : u ∘ Sum.inl = ⇑S.f ∘ v
⊢ LinearIndependent R (u ∘ Sum.inl)

Next tactic:
rw [huv, LinearMap.linearIndependent_iff S.f]
/-- In the commutative diagram
```
             f     g
    0 --→ X₁ --→ X₂ --→ X₃
          ↑      ↑      ↑
         v|     u|     w|
          ι  → ι ⊕ ι' ← ι'
```
where the top row is an exact sequence of modules and the maps on the bottom are `Sum.inl` and
`Sum.inr`. If `u` is injective and `v` and `w` are linearly independent, then `u` is linearly
independent. -/
theorem linearIndependent_leftExact : LinearIndependent R u := by
  rw [linearIndependent_sum]
  refine' ⟨_, LinearIndependent.of_comp S.g hw, disjoint_span_sum hS hw huv⟩
  rw [huv, LinearMap.linearIndependent_iff S.f]; 

Proof state:
ι : Type u_1
ι' : Type u_2
R : Type u_3
inst✝ : Ring R
S : ShortComplex (ModuleCat R)
hS : ShortComplex.Exact S
hS' : ShortComplex.ShortExact S
v : ι → ↑S.X₁
hv : LinearIndependent R v
u : ι ⊕ ι' → ↑S.X₂
hw : LinearIndependent R (⇑S.g ∘ u ∘ Sum.inr)
hm : Mono S.f
huv : u ∘ Sum.inl = ⇑S.f ∘ v
⊢ LinearIndependent R v
ι : Type u_1
ι' : Type u_2
R : Type u_3
inst✝ : Ring R
S : ShortComplex (ModuleCat R)
hS : ShortComplex.Exact S
hS' : ShortComplex.ShortExact S
v : ι → ↑S.X₁
hv : LinearIndependent R v
u : ι ⊕ ι' → ↑S.X₂
hw : LinearIndependent R (⇑S.g ∘ u ∘ Sum.inr)
hm : Mono S.f
huv : u ∘ Sum.inl = ⇑S.f ∘ v
⊢ LinearMap.ker S.f = ⊥

Next tactic:
swap
/-- In the commutative diagram
```
             f     g
    0 --→ X₁ --→ X₂ --→ X₃
          ↑      ↑      ↑
         v|     u|     w|
          ι  → ι ⊕ ι' ← ι'
```
where the top row is an exact sequence of modules and the maps on the bottom are `Sum.inl` and
`Sum.inr`. If `u` is injective and `v` and `w` are linearly independent, then `u` is linearly
independent. -/
theorem linearIndependent_leftExact : LinearIndependent R u := by
  rw [linearIndependent_sum]
  refine' ⟨_, LinearIndependent.of_comp S.g hw, disjoint_span_sum hS hw huv⟩
  rw [huv, LinearMap.linearIndependent_iff S.f]; swap
  · 

Proof state:
ι : Type u_1
ι' : Type u_2
R : Type u_3
inst✝ : Ring R
S : ShortComplex (ModuleCat R)
hS : ShortComplex.Exact S
hS' : ShortComplex.ShortExact S
v : ι → ↑S.X₁
hv : LinearIndependent R v
u : ι ⊕ ι' → ↑S.X₂
hw : LinearIndependent R (⇑S.g ∘ u ∘ Sum.inr)
hm : Mono S.f
huv : u ∘ Sum.inl = ⇑S.f ∘ v
⊢ LinearMap.ker S.f = ⊥

Next tactic:
rw [LinearMap.ker_eq_bot, ← mono_iff_injective]