l3lab/ntp-mathlib huggingface dataset:
@[ext]
theorem ext_ring {f g : R →+[R] M'} (h : f 1 = g 1) : f = g := by
  ext x
  

Proof state:
case a
M' : Type u_1
X : Type u_2
inst✝²⁵ : SMul M' X
Y : Type u_3
inst✝²⁴ : SMul M' Y
Z : Type u_4
inst✝²³ : SMul M' Z
M : Type u_5
inst✝²² : Monoid M
A : Type u_6
inst✝²¹ : AddMonoid A
inst✝²⁰ : DistribMulAction M A
A' : Type u_7
inst✝¹⁹ : AddGroup A'
inst✝¹⁸ : DistribMulAction M A'
B : Type u_8
inst✝¹⁷ : AddMonoid B
inst✝¹⁶ : DistribMulAction M B
B' : Type u_9
inst✝¹⁵ : AddGroup B'
inst✝¹⁴ : DistribMulAction M B'
C : Type u_10
inst✝¹³ : AddMonoid C
inst✝¹² : DistribMulAction M C
R : Type u_11
inst✝¹¹ : Semiring R
inst✝¹⁰ : MulSemiringAction M R
R' : Type u_12
inst✝⁹ : Ring R'
inst✝⁸ : MulSemiringAction M R'
S : Type u_13
inst✝⁷ : Semiring S
inst✝⁶ : MulSemiringAction M S
S' : Type u_14
inst✝⁵ : Ring S'
inst✝⁴ : MulSemiringAction M S'
T : Type u_15
inst✝³ : Semiring T
inst✝² : MulSemiringAction M T
inst✝¹ : AddMonoid M'
inst✝ : DistribMulAction R M'
f g : R →+[R] M'
h : f 1 = g 1
x : R
⊢ f x = g x

Next tactic:
rw [← mul_one x, ← smul_eq_mul R, f.map_smul, g.map_smul, h]
instance : MulSemiringActionHomClass (R →+*[M] S) M R S where
  coe m := m.toFun
  coe_injective' f g h := by
    

Proof state:
M' : Type u_1
X : Type u_2
inst✝²³ : SMul M' X
Y : Type u_3
inst✝²² : SMul M' Y
Z : Type u_4
inst✝²¹ : SMul M' Z
M : Type u_5
inst✝²⁰ : Monoid M
A : Type u_6
inst✝¹⁹ : AddMonoid A
inst✝¹⁸ : DistribMulAction M A
A' : Type u_7
inst✝¹⁷ : AddGroup A'
inst✝¹⁶ : DistribMulAction M A'
B : Type u_8
inst✝¹⁵ : AddMonoid B
inst✝¹⁴ : DistribMulAction M B
B' : Type u_9
inst✝¹³ : AddGroup B'
inst✝¹² : DistribMulAction M B'
C : Type u_10
inst✝¹¹ : AddMonoid C
inst✝¹⁰ : DistribMulAction M C
R : Type u_11
inst✝⁹ : Semiring R
inst✝⁸ : MulSemiringAction M R
R' : Type u_12
inst✝⁷ : Ring R'
inst✝⁶ : MulSemiringAction M R'
S : Type u_13
inst✝⁵ : Semiring S
inst✝⁴ : MulSemiringAction M S
S' : Type u_14
inst✝³ : Ring S'
inst✝² : MulSemiringAction M S'
T : Type u_15
inst✝¹ : Semiring T
inst✝ : MulSemiringAction M T
f g : R →+*[M] S
h : (fun m => m.toFun) f = (fun m => m.toFun) g
⊢ f = g

Next tactic:
rcases f with ⟨⟨tF, _, _⟩, _, _⟩
instance : MulSemiringActionHomClass (R →+*[M] S) M R S where
  coe m := m.toFun
  coe_injective' f g h := by
    rcases f with ⟨⟨tF, _, _⟩, _, _⟩; 

Proof state:
case mk.mk
M' : Type u_1
X : Type u_2
inst✝²³ : SMul M' X
Y : Type u_3
inst✝²² : SMul M' Y
Z : Type u_4
inst✝²¹ : SMul M' Z
M : Type u_5
inst✝²⁰ : Monoid M
A : Type u_6
inst✝¹⁹ : AddMonoid A
inst✝¹⁸ : DistribMulAction M A
A' : Type u_7
inst✝¹⁷ : AddGroup A'
inst✝¹⁶ : DistribMulAction M A'
B : Type u_8
inst✝¹⁵ : AddMonoid B
inst✝¹⁴ : DistribMulAction M B
B' : Type u_9
inst✝¹³ : AddGroup B'
inst✝¹² : DistribMulAction M B'
C : Type u_10
inst✝¹¹ : AddMonoid C
inst✝¹⁰ : DistribMulAction M C
R : Type u_11
inst✝⁹ : Semiring R
inst✝⁸ : MulSemiringAction M R
R' : Type u_12
inst✝⁷ : Ring R'
inst✝⁶ : MulSemiringAction M R'
S : Type u_13
inst✝⁵ : Semiring S
inst✝⁴ : MulSemiringAction M S
S' : Type u_14
inst✝³ : Ring S'
inst✝² : MulSemiringAction M S'
T : Type u_15
inst✝¹ : Semiring T
inst✝ : MulSemiringAction M T
g : R →+*[M] S
tF : R →[M] S
map_zero'✝ : MulActionHom.toFun tF 0 = 0
map_add'✝ : ∀ (x y : R), MulActionHom.toFun tF (x + y) = MulActionHom.toFun tF x + MulActionHom.toFun tF y
map_one'✝ :
  MulActionHom.toFun { toMulActionHom := tF, map_zero' := map_zero'✝, map_add' := map_add'✝ }.toMulActionHom 1 = 1
map_mul'✝ :
  ∀ (x y : R),
    MulActionHom.toFun { toMulActionHom := tF, map_zero' := map_zero'✝, map_add' := map_add'✝ }.toMulActionHom (x * y) =
      MulActionHom.toFun { toMulActionHom := tF, map_zero' := map_zero'✝, map_add' := map_add'✝ }.toMulActionHom x *
        MulActionHom.toFun { toMulActionHom := tF, map_zero' := map_zero'✝, map_add' := map_add'✝ }.toMulActionHom y
h :
  (fun m => m.toFun)
      { toDistribMulActionHom := { toMulActionHom := tF, map_zero' := map_zero'✝, map_add' := map_add'✝ },
        map_one' := map_one'✝, map_mul' := map_mul'✝ } =
    (fun m => m.toFun) g
⊢ { toDistribMulActionHom := { toMulActionHom := tF, map_zero' := map_zero'✝, map_add' := map_add'✝ },
      map_one' := map_one'✝, map_mul' := map_mul'✝ } =
    g

Next tactic:
rcases g with ⟨⟨tG, _, _⟩, _, _⟩
instance : MulSemiringActionHomClass (R →+*[M] S) M R S where
  coe m := m.toFun
  coe_injective' f g h := by
    rcases f with ⟨⟨tF, _, _⟩, _, _⟩; rcases g with ⟨⟨tG, _, _⟩, _, _⟩
    

Proof state:
case mk.mk.mk.mk
M' : Type u_1
X : Type u_2
inst✝²³ : SMul M' X
Y : Type u_3
inst✝²² : SMul M' Y
Z : Type u_4
inst✝²¹ : SMul M' Z
M : Type u_5
inst✝²⁰ : Monoid M
A : Type u_6
inst✝¹⁹ : AddMonoid A
inst✝¹⁸ : DistribMulAction M A
A' : Type u_7
inst✝¹⁷ : AddGroup A'
inst✝¹⁶ : DistribMulAction M A'
B : Type u_8
inst✝¹⁵ : AddMonoid B
inst✝¹⁴ : DistribMulAction M B
B' : Type u_9
inst✝¹³ : AddGroup B'
inst✝¹² : DistribMulAction M B'
C : Type u_10
inst✝¹¹ : AddMonoid C
inst✝¹⁰ : DistribMulAction M C
R : Type u_11
inst✝⁹ : Semiring R
inst✝⁸ : MulSemiringAction M R
R' : Type u_12
inst✝⁷ : Ring R'
inst✝⁶ : MulSemiringAction M R'
S : Type u_13
inst✝⁵ : Semiring S
inst✝⁴ : MulSemiringAction M S
S' : Type u_14
inst✝³ : Ring S'
inst✝² : MulSemiringAction M S'
T : Type u_15
inst✝¹ : Semiring T
inst✝ : MulSemiringAction M T
tF : R →[M] S
map_zero'✝¹ : MulActionHom.toFun tF 0 = 0
map_add'✝¹ : ∀ (x y : R), MulActionHom.toFun tF (x + y) = MulActionHom.toFun tF x + MulActionHom.toFun tF y
map_one'✝¹ :
  MulActionHom.toFun { toMulActionHom := tF, map_zero' := map_zero'✝¹, map_add' := map_add'✝¹ }.toMulActionHom 1 = 1
map_mul'✝¹ :
  ∀ (x y : R),
    MulActionHom.toFun { toMulActionHom := tF, map_zero' := map_zero'✝¹, map_add' := map_add'✝¹ }.toMulActionHom
        (x * y) =
      MulActionHom.toFun { toMulActionHom := tF, map_zero' := map_zero'✝¹, map_add' := map_add'✝¹ }.toMulActionHom x *
        MulActionHom.toFun { toMulActionHom := tF, map_zero' := map_zero'✝¹, map_add' := map_add'✝¹ }.toMulActionHom y
tG : R →[M] S
map_zero'✝ : MulActionHom.toFun tG 0 = 0
map_add'✝ : ∀ (x y : R), MulActionHom.toFun tG (x + y) = MulActionHom.toFun tG x + MulActionHom.toFun tG y
map_one'✝ :
  MulActionHom.toFun { toMulActionHom := tG, map_zero' := map_zero'✝, map_add' := map_add'✝ }.toMulActionHom 1 = 1
map_mul'✝ :
  ∀ (x y : R),
    MulActionHom.toFun { toMulActionHom := tG, map_zero' := map_zero'✝, map_add' := map_add'✝ }.toMulActionHom (x * y) =
      MulActionHom.toFun { toMulActionHom := tG, map_zero' := map_zero'✝, map_add' := map_add'✝ }.toMulActionHom x *
        MulActionHom.toFun { toMulActionHom := tG, map_zero' := map_zero'✝, map_add' := map_add'✝ }.toMulActionHom y
h :
  (fun m => m.toFun)
      { toDistribMulActionHom := { toMulActionHom := tF, map_zero' := map_zero'✝¹, map_add' := map_add'✝¹ },
        map_one' := map_one'✝¹, map_mul' := map_mul'✝¹ } =
    (fun m => m.toFun)
      { toDistribMulActionHom := { toMulActionHom := tG, map_zero' := map_zero'✝, map_add' := map_add'✝ },
        map_one' := map_one'✝, map_mul' := map_mul'✝ }
⊢ { toDistribMulActionHom := { toMulActionHom := tF, map_zero' := map_zero'✝¹, map_add' := map_add'✝¹ },
      map_one' := map_one'✝¹, map_mul' := map_mul'✝¹ } =
    { toDistribMulActionHom := { toMulActionHom := tG, map_zero' := map_zero'✝, map_add' := map_add'✝ },
      map_one' := map_one'✝, map_mul' := map_mul'✝ }

Next tactic:
cases tF
@[simp]
theorem id_comp (f : R →+*[M] S) : (MulSemiringActionHom.id M).comp f = f :=
  ext fun x => by 

Proof state:
M' : Type u_1
X : Type u_2
inst✝²³ : SMul M' X
Y : Type u_3
inst✝²² : SMul M' Y
Z : Type u_4
inst✝²¹ : SMul M' Z
M : Type u_5
inst✝²⁰ : Monoid M
A : Type u_6
inst✝¹⁹ : AddMonoid A
inst✝¹⁸ : DistribMulAction M A
A' : Type u_7
inst✝¹⁷ : AddGroup A'
inst✝¹⁶ : DistribMulAction M A'
B : Type u_8
inst✝¹⁵ : AddMonoid B
inst✝¹⁴ : DistribMulAction M B
B' : Type u_9
inst✝¹³ : AddGroup B'
inst✝¹² : DistribMulAction M B'
C : Type u_10
inst✝¹¹ : AddMonoid C
inst✝¹⁰ : DistribMulAction M C
R : Type u_11
inst✝⁹ : Semiring R
inst✝⁸ : MulSemiringAction M R
R' : Type u_12
inst✝⁷ : Ring R'
inst✝⁶ : MulSemiringAction M R'
S : Type u_13
inst✝⁵ : Semiring S
inst✝⁴ : MulSemiringAction M S
S' : Type u_14
inst✝³ : Ring S'
inst✝² : MulSemiringAction M S'
T : Type u_15
inst✝¹ : Semiring T
inst✝ : MulSemiringAction M T
f : R →+*[M] S
x : R
⊢ (comp (MulSemiringActionHom.id M) f) x = f x

Next tactic:
rw [comp_apply, id_apply]
@[simp]
theorem comp_id (f : R →+*[M] S) : f.comp (MulSemiringActionHom.id M) = f :=
  ext fun x => by 

Proof state:
M' : Type u_1
X : Type u_2
inst✝²³ : SMul M' X
Y : Type u_3
inst✝²² : SMul M' Y
Z : Type u_4
inst✝²¹ : SMul M' Z
M : Type u_5
inst✝²⁰ : Monoid M
A : Type u_6
inst✝¹⁹ : AddMonoid A
inst✝¹⁸ : DistribMulAction M A
A' : Type u_7
inst✝¹⁷ : AddGroup A'
inst✝¹⁶ : DistribMulAction M A'
B : Type u_8
inst✝¹⁵ : AddMonoid B
inst✝¹⁴ : DistribMulAction M B
B' : Type u_9
inst✝¹³ : AddGroup B'
inst✝¹² : DistribMulAction M B'
C : Type u_10
inst✝¹¹ : AddMonoid C
inst✝¹⁰ : DistribMulAction M C
R : Type u_11
inst✝⁹ : Semiring R
inst✝⁸ : MulSemiringAction M R
R' : Type u_12
inst✝⁷ : Ring R'
inst✝⁶ : MulSemiringAction M R'
S : Type u_13
inst✝⁵ : Semiring S
inst✝⁴ : MulSemiringAction M S
S' : Type u_14
inst✝³ : Ring S'
inst✝² : MulSemiringAction M S'
T : Type u_15
inst✝¹ : Semiring T
inst✝ : MulSemiringAction M T
f : R →+*[M] S
x : R
⊢ (comp f (MulSemiringActionHom.id M)) x = f x

Next tactic:
rw [comp_apply, id_apply]
/-- If an element `b` becomes left-regular after multiplying it on the left by a left-regular
element, then `b` is left-regular. -/
@[to_additive "If an element `b` becomes add-left-regular after adding to it on the left
an add-left-regular element, then `b` is add-left-regular."]
theorem IsLeftRegular.of_mul (ab : IsLeftRegular (a * b)) : IsLeftRegular b :=
  Function.Injective.of_comp (by 

Proof state:
R : Type u_1
inst✝ : Semigroup R
a b : R
ab : IsLeftRegular (a * b)
⊢ Function.Injective (?m.3269 ab ∘ fun x => b * x)

Next tactic:
rwa [comp_mul_left a b]
/-- If an element `b` becomes right-regular after multiplying it on the right by a right-regular
element, then `b` is right-regular. -/
@[to_additive "If an element `b` becomes add-right-regular after adding to it on the right
an add-right-regular element, then `b` is add-right-regular."]
theorem IsRightRegular.of_mul (ab : IsRightRegular (b * a)) : IsRightRegular b := by
  

Proof state:
R : Type u_1
inst✝ : Semigroup R
a b : R
ab : IsRightRegular (b * a)
⊢ IsRightRegular b

Next tactic:
refine' fun x y xy => ab (_ : x * (b * a) = y * (b * a))
/-- If an element `b` becomes right-regular after multiplying it on the right by a right-regular
element, then `b` is right-regular. -/
@[to_additive "If an element `b` becomes add-right-regular after adding to it on the right
an add-right-regular element, then `b` is add-right-regular."]
theorem IsRightRegular.of_mul (ab : IsRightRegular (b * a)) : IsRightRegular b := by
  refine' fun x y xy => ab (_ : x * (b * a) = y * (b * a))
  

Proof state:
R : Type u_1
inst✝ : Semigroup R
a b : R
ab : IsRightRegular (b * a)
x y : R
xy : (fun x => x * b) x = (fun x => x * b) y
⊢ x * (b * a) = y * (b * a)

Next tactic:
rw [← mul_assoc, ← mul_assoc]
/-- If an element `b` becomes right-regular after multiplying it on the right by a right-regular
element, then `b` is right-regular. -/
@[to_additive "If an element `b` becomes add-right-regular after adding to it on the right
an add-right-regular element, then `b` is add-right-regular."]
theorem IsRightRegular.of_mul (ab : IsRightRegular (b * a)) : IsRightRegular b := by
  refine' fun x y xy => ab (_ : x * (b * a) = y * (b * a))
  rw [← mul_assoc, ← mul_assoc]
  

Proof state:
R : Type u_1
inst✝ : Semigroup R
a b : R
ab : IsRightRegular (b * a)
x y : R
xy : (fun x => x * b) x = (fun x => x * b) y
⊢ x * b * a = y * b * a

Next tactic:
exact congr_arg (· * a) xy
/-- Two elements `a` and `b` are regular if and only if both products `a * b` and `b * a`
are regular. -/
@[to_additive "Two elements `a` and `b` are add-regular if and only if both sums `a + b` and
`b + a` are add-regular."]
theorem isRegular_mul_and_mul_iff :
    IsRegular (a * b) ∧ IsRegular (b * a) ↔ IsRegular a ∧ IsRegular b := by
  

Proof state:
R : Type u_1
inst✝ : Semigroup R
a b : R
⊢ IsRegular (a * b) ∧ IsRegular (b * a) ↔ IsRegular a ∧ IsRegular b

Next tactic:
refine' ⟨_, _⟩
/-- Two elements `a` and `b` are regular if and only if both products `a * b` and `b * a`
are regular. -/
@[to_additive "Two elements `a` and `b` are add-regular if and only if both sums `a + b` and
`b + a` are add-regular."]
theorem isRegular_mul_and_mul_iff :
    IsRegular (a * b) ∧ IsRegular (b * a) ↔ IsRegular a ∧ IsRegular b := by
  refine' ⟨_, _⟩
  · 

Proof state:
case refine'_1
R : Type u_1
inst✝ : Semigroup R
a b : R
⊢ IsRegular (a * b) ∧ IsRegular (b * a) → IsRegular a ∧ IsRegular b

Next tactic:
rintro ⟨ab, ba⟩
/-- Two elements `a` and `b` are regular if and only if both products `a * b` and `b * a`
are regular. -/
@[to_additive "Two elements `a` and `b` are add-regular if and only if both sums `a + b` and
`b + a` are add-regular."]
theorem isRegular_mul_and_mul_iff :
    IsRegular (a * b) ∧ IsRegular (b * a) ↔ IsRegular a ∧ IsRegular b := by
  refine' ⟨_, _⟩
  · rintro ⟨ab, ba⟩
    

Proof state:
case refine'_1.intro
R : Type u_1
inst✝ : Semigroup R
a b : R
ab : IsRegular (a * b)
ba : IsRegular (b * a)
⊢ IsRegular a ∧ IsRegular b

Next tactic:
exact
      ⟨⟨IsLeftRegular.of_mul ba.left, IsRightRegular.of_mul ab.right⟩,
        ⟨IsLeftRegular.of_mul ab.left, IsRightRegular.of_mul ba.right⟩⟩
/-- Two elements `a` and `b` are regular if and only if both products `a * b` and `b * a`
are regular. -/
@[to_additive "Two elements `a` and `b` are add-regular if and only if both sums `a + b` and
`b + a` are add-regular."]
theorem isRegular_mul_and_mul_iff :
    IsRegular (a * b) ∧ IsRegular (b * a) ↔ IsRegular a ∧ IsRegular b := by
  refine' ⟨_, _⟩
  · rintro ⟨ab, ba⟩
    exact
      ⟨⟨IsLeftRegular.of_mul ba.left, IsRightRegular.of_mul ab.right⟩,
        ⟨IsLeftRegular.of_mul ab.left, IsRightRegular.of_mul ba.right⟩⟩
  · 

Proof state:
case refine'_2
R : Type u_1
inst✝ : Semigroup R
a b : R
⊢ IsRegular a ∧ IsRegular b → IsRegular (a * b) ∧ IsRegular (b * a)

Next tactic:
rintro ⟨ha, hb⟩
/-- Two elements `a` and `b` are regular if and only if both products `a * b` and `b * a`
are regular. -/
@[to_additive "Two elements `a` and `b` are add-regular if and only if both sums `a + b` and
`b + a` are add-regular."]
theorem isRegular_mul_and_mul_iff :
    IsRegular (a * b) ∧ IsRegular (b * a) ↔ IsRegular a ∧ IsRegular b := by
  refine' ⟨_, _⟩
  · rintro ⟨ab, ba⟩
    exact
      ⟨⟨IsLeftRegular.of_mul ba.left, IsRightRegular.of_mul ab.right⟩,
        ⟨IsLeftRegular.of_mul ab.left, IsRightRegular.of_mul ba.right⟩⟩
  · rintro ⟨ha, hb⟩
    

Proof state:
case refine'_2.intro
R : Type u_1
inst✝ : Semigroup R
a b : R
ha : IsRegular a
hb : IsRegular b
⊢ IsRegular (a * b) ∧ IsRegular (b * a)

Next tactic:
exact
      ⟨⟨(mul_isLeftRegular_iff _ ha.left).mpr hb.left,
          (mul_isRightRegular_iff _ hb.right).mpr ha.right⟩,
        ⟨(mul_isLeftRegular_iff _ hb.left).mpr ha.left,
          (mul_isRightRegular_iff _ ha.right).mpr hb.right⟩⟩
/-- In a non-trivial `MulZeroClass`, the `0` element is not left-regular. -/
theorem not_isLeftRegular_zero_iff : ¬IsLeftRegular (0 : R) ↔ Nontrivial R := by
  

Proof state:
R : Type u_1
inst✝ : MulZeroClass R
a b : R
⊢ ¬IsLeftRegular 0 ↔ Nontrivial R

Next tactic:
rw [nontrivial_iff, not_iff_comm, isLeftRegular_zero_iff_subsingleton, subsingleton_iff]
/-- In a non-trivial `MulZeroClass`, the `0` element is not left-regular. -/
theorem not_isLeftRegular_zero_iff : ¬IsLeftRegular (0 : R) ↔ Nontrivial R := by
  rw [nontrivial_iff, not_iff_comm, isLeftRegular_zero_iff_subsingleton, subsingleton_iff]
  

Proof state:
R : Type u_1
inst✝ : MulZeroClass R
a b : R
⊢ (¬∃ x y, x ≠ y) ↔ ∀ (x y : R), x = y

Next tactic:
push_neg
/-- In a non-trivial `MulZeroClass`, the `0` element is not left-regular. -/
theorem not_isLeftRegular_zero_iff : ¬IsLeftRegular (0 : R) ↔ Nontrivial R := by
  rw [nontrivial_iff, not_iff_comm, isLeftRegular_zero_iff_subsingleton, subsingleton_iff]
  push_neg
  

Proof state:
R : Type u_1
inst✝ : MulZeroClass R
a b : R
⊢ (∀ (x y : R), x = y) ↔ ∀ (x y : R), x = y

Next tactic:
exact Iff.rfl
/-- In a non-trivial `MulZeroClass`, the `0` element is not right-regular. -/
theorem not_isRightRegular_zero_iff : ¬IsRightRegular (0 : R) ↔ Nontrivial R := by
  

Proof state:
R : Type u_1
inst✝ : MulZeroClass R
a b : R
⊢ ¬IsRightRegular 0 ↔ Nontrivial R

Next tactic:
rw [nontrivial_iff, not_iff_comm, isRightRegular_zero_iff_subsingleton, subsingleton_iff]
/-- In a non-trivial `MulZeroClass`, the `0` element is not right-regular. -/
theorem not_isRightRegular_zero_iff : ¬IsRightRegular (0 : R) ↔ Nontrivial R := by
  rw [nontrivial_iff, not_iff_comm, isRightRegular_zero_iff_subsingleton, subsingleton_iff]
  

Proof state:
R : Type u_1
inst✝ : MulZeroClass R
a b : R
⊢ (¬∃ x y, x ≠ y) ↔ ∀ (x y : R), x = y

Next tactic:
push_neg
/-- In a non-trivial `MulZeroClass`, the `0` element is not right-regular. -/
theorem not_isRightRegular_zero_iff : ¬IsRightRegular (0 : R) ↔ Nontrivial R := by
  rw [nontrivial_iff, not_iff_comm, isRightRegular_zero_iff_subsingleton, subsingleton_iff]
  push_neg
  

Proof state:
R : Type u_1
inst✝ : MulZeroClass R
a b : R
⊢ (∀ (x y : R), x = y) ↔ ∀ (x y : R), x = y

Next tactic:
exact Iff.rfl
/-- A left-regular element of a `Nontrivial` `MulZeroClass` is non-zero. -/
theorem IsLeftRegular.ne_zero [Nontrivial R] (la : IsLeftRegular a) : a ≠ 0 := by
  

Proof state:
R : Type u_1
inst✝¹ : MulZeroClass R
a b : R
inst✝ : Nontrivial R
la : IsLeftRegular a
⊢ a ≠ 0

Next tactic:
rintro rfl
/-- A left-regular element of a `Nontrivial` `MulZeroClass` is non-zero. -/
theorem IsLeftRegular.ne_zero [Nontrivial R] (la : IsLeftRegular a) : a ≠ 0 := by
  rintro rfl
  

Proof state:
R : Type u_1
inst✝¹ : MulZeroClass R
b : R
inst✝ : Nontrivial R
la : IsLeftRegular 0
⊢ False

Next tactic:
rcases exists_pair_ne R with ⟨x, y, xy⟩
/-- A left-regular element of a `Nontrivial` `MulZeroClass` is non-zero. -/
theorem IsLeftRegular.ne_zero [Nontrivial R] (la : IsLeftRegular a) : a ≠ 0 := by
  rintro rfl
  rcases exists_pair_ne R with ⟨x, y, xy⟩
  

Proof state:
case intro.intro
R : Type u_1
inst✝¹ : MulZeroClass R
b : R
inst✝ : Nontrivial R
la : IsLeftRegular 0
x y : R
xy : x ≠ y
⊢ False

Next tactic:
refine' xy (la (_ : 0 * x = 0 * y))
/-- A left-regular element of a `Nontrivial` `MulZeroClass` is non-zero. -/
theorem IsLeftRegular.ne_zero [Nontrivial R] (la : IsLeftRegular a) : a ≠ 0 := by
  rintro rfl
  rcases exists_pair_ne R with ⟨x, y, xy⟩
  refine' xy (la (_ : 0 * x = 0 * y)) -- Porting note: lean4 seems to need the type signature
  

Proof state:
case intro.intro
R : Type u_1
inst✝¹ : MulZeroClass R
b : R
inst✝ : Nontrivial R
la : IsLeftRegular 0
x y : R
xy : x ≠ y
⊢ 0 * x = 0 * y

Next tactic:
rw [zero_mul, zero_mul]
/-- A right-regular element of a `Nontrivial` `MulZeroClass` is non-zero. -/
theorem IsRightRegular.ne_zero [Nontrivial R] (ra : IsRightRegular a) : a ≠ 0 := by
  

Proof state:
R : Type u_1
inst✝¹ : MulZeroClass R
a b : R
inst✝ : Nontrivial R
ra : IsRightRegular a
⊢ a ≠ 0

Next tactic:
rintro rfl
/-- A right-regular element of a `Nontrivial` `MulZeroClass` is non-zero. -/
theorem IsRightRegular.ne_zero [Nontrivial R] (ra : IsRightRegular a) : a ≠ 0 := by
  rintro rfl
  

Proof state:
R : Type u_1
inst✝¹ : MulZeroClass R
b : R
inst✝ : Nontrivial R
ra : IsRightRegular 0
⊢ False

Next tactic:
rcases exists_pair_ne R with ⟨x, y, xy⟩
/-- A right-regular element of a `Nontrivial` `MulZeroClass` is non-zero. -/
theorem IsRightRegular.ne_zero [Nontrivial R] (ra : IsRightRegular a) : a ≠ 0 := by
  rintro rfl
  rcases exists_pair_ne R with ⟨x, y, xy⟩
  

Proof state:
case intro.intro
R : Type u_1
inst✝¹ : MulZeroClass R
b : R
inst✝ : Nontrivial R
ra : IsRightRegular 0
x y : R
xy : x ≠ y
⊢ False

Next tactic:
refine' xy (ra (_ : x * 0 = y * 0))
/-- A right-regular element of a `Nontrivial` `MulZeroClass` is non-zero. -/
theorem IsRightRegular.ne_zero [Nontrivial R] (ra : IsRightRegular a) : a ≠ 0 := by
  rintro rfl
  rcases exists_pair_ne R with ⟨x, y, xy⟩
  refine' xy (ra (_ : x * 0 = y * 0))
  

Proof state:
case intro.intro
R : Type u_1
inst✝¹ : MulZeroClass R
b : R
inst✝ : Nontrivial R
ra : IsRightRegular 0
x y : R
xy : x ≠ y
⊢ x * 0 = y * 0

Next tactic:
rw [mul_zero, mul_zero]
@[simp] lemma IsLeftRegular.mul_left_eq_zero_iff (hb : IsLeftRegular b) : b * a = 0 ↔ a = 0 := by
  

Proof state:
R : Type u_1
inst✝ : MulZeroClass R
a b : R
hb : IsLeftRegular b
⊢ b * a = 0 ↔ a = 0

Next tactic:
nth_rw 1 [← mul_zero b]
@[simp] lemma IsLeftRegular.mul_left_eq_zero_iff (hb : IsLeftRegular b) : b * a = 0 ↔ a = 0 := by
  nth_rw 1 [← mul_zero b]
  

Proof state:
R : Type u_1
inst✝ : MulZeroClass R
a b : R
hb : IsLeftRegular b
⊢ b * a = b * 0 ↔ a = 0

Next tactic:
exact ⟨fun h ↦ hb h, fun ha ↦ by rw [ha, mul_zero]⟩
@[simp] lemma IsLeftRegular.mul_left_eq_zero_iff (hb : IsLeftRegular b) : b * a = 0 ↔ a = 0 := by
  nth_rw 1 [← mul_zero b]
  exact ⟨fun h ↦ hb h, fun ha ↦ by 

Proof state:
R : Type u_1
inst✝ : MulZeroClass R
a b : R
hb : IsLeftRegular b
ha : a = 0
⊢ b * a = b * 0

Next tactic:
rw [ha, mul_zero]
@[simp] lemma IsRightRegular.mul_right_eq_zero_iff (hb : IsRightRegular b) : a * b = 0 ↔ a = 0 := by
  

Proof state:
R : Type u_1
inst✝ : MulZeroClass R
a b : R
hb : IsRightRegular b
⊢ a * b = 0 ↔ a = 0

Next tactic:
nth_rw 1 [← zero_mul b]
@[simp] lemma IsRightRegular.mul_right_eq_zero_iff (hb : IsRightRegular b) : a * b = 0 ↔ a = 0 := by
  nth_rw 1 [← zero_mul b]
  

Proof state:
R : Type u_1
inst✝ : MulZeroClass R
a b : R
hb : IsRightRegular b
⊢ a * b = 0 * b ↔ a = 0

Next tactic:
exact ⟨fun h ↦ hb h, fun ha ↦ by rw [ha, zero_mul]⟩
@[simp] lemma IsRightRegular.mul_right_eq_zero_iff (hb : IsRightRegular b) : a * b = 0 ↔ a = 0 := by
  nth_rw 1 [← zero_mul b]
  exact ⟨fun h ↦ hb h, fun ha ↦ by 

Proof state:
R : Type u_1
inst✝ : MulZeroClass R
a b : R
hb : IsRightRegular b
ha : a = 0
⊢ a * b = 0 * b

Next tactic:
rw [ha, zero_mul]
/-- A product is regular if and only if the factors are. -/
@[to_additive "A sum is add-regular if and only if the summands are."]
theorem isRegular_mul_iff : IsRegular (a * b) ↔ IsRegular a ∧ IsRegular b := by
  

Proof state:
R : Type u_1
inst✝ : CommSemigroup R
a b : R
⊢ IsRegular (a * b) ↔ IsRegular a ∧ IsRegular b

Next tactic:
refine' Iff.trans _ isRegular_mul_and_mul_iff
/-- A product is regular if and only if the factors are. -/
@[to_additive "A sum is add-regular if and only if the summands are."]
theorem isRegular_mul_iff : IsRegular (a * b) ↔ IsRegular a ∧ IsRegular b := by
  refine' Iff.trans _ isRegular_mul_and_mul_iff
  

Proof state:
R : Type u_1
inst✝ : CommSemigroup R
a b : R
⊢ IsRegular (a * b) ↔ IsRegular (a * b) ∧ IsRegular (b * a)

Next tactic:
refine' ⟨fun ab => ⟨ab, by rwa [mul_comm]⟩, fun rab => rab.1⟩
/-- A product is regular if and only if the factors are. -/
@[to_additive "A sum is add-regular if and only if the summands are."]
theorem isRegular_mul_iff : IsRegular (a * b) ↔ IsRegular a ∧ IsRegular b := by
  refine' Iff.trans _ isRegular_mul_and_mul_iff
  refine' ⟨fun ab => ⟨ab, by 

Proof state:
R : Type u_1
inst✝ : CommSemigroup R
a b : R
ab : IsRegular (a * b)
⊢ IsRegular (b * a)

Next tactic:
rwa [mul_comm]
/-- An element admitting a left inverse is left-regular. -/
@[to_additive "An element admitting a left additive opposite is add-left-regular."]
theorem isLeftRegular_of_mul_eq_one (h : b * a = 1) : IsLeftRegular a :=
  @IsLeftRegular.of_mul R _ _ _ (by 

Proof state:
R : Type u_1
inst✝ : Monoid R
a b : R
h : b * a = 1
⊢ IsLeftRegular (?m.13171 h * a)

Next tactic:
rw [h]
/-- An element admitting a left inverse is left-regular. -/
@[to_additive "An element admitting a left additive opposite is add-left-regular."]
theorem isLeftRegular_of_mul_eq_one (h : b * a = 1) : IsLeftRegular a :=
  @IsLeftRegular.of_mul R _ _ _ (by rw [h]; 

Proof state:
R : Type u_1
inst✝ : Monoid R
a b : R
h : b * a = 1
⊢ IsLeftRegular 1

Next tactic:
exact isRegular_one.left