l3lab/ntp-mathlib huggingface dataset:
/-- A ring homomorphism f : Z[X_1, X_2, ...] → R
is determined by the evaluations f(X_1), f(X_2), ... -/
@[simp]
theorem eval₂Hom_X {R : Type u} (c : ℤ →+* S) (f : MvPolynomial R ℤ →+* S) (x : MvPolynomial R ℤ) :
    eval₂ c (f ∘ X) x = f x := by
  apply MvPolynomial.induction_on x
    (fun n => by
      rw [hom_C f, eval₂_C]
      exact eq_intCast c n)
    (fun p q hp hq => by
      rw [eval₂_add, hp, hq]
      exact (f.map_add _ _).symm)
    (fun p n hp => by
      

Proof state:
R✝ : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R✝
e : ℕ
n✝ m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R✝
p✝ q : MvPolynomial σ R✝
inst✝ : CommRing S
f✝ : R✝ →+* S
g : σ → S
R : Type u
c : ℤ →+* S
f : MvPolynomial R ℤ →+* S
x p : MvPolynomial R ℤ
n : R
hp : eval₂ c (⇑f ∘ X) p = f p
⊢ eval₂ c (⇑f ∘ X) (p * X n) = f (p * X n)

Next tactic:
rw [eval₂_mul, eval₂_X, hp]
/-- A ring homomorphism f : Z[X_1, X_2, ...] → R
is determined by the evaluations f(X_1), f(X_2), ... -/
@[simp]
theorem eval₂Hom_X {R : Type u} (c : ℤ →+* S) (f : MvPolynomial R ℤ →+* S) (x : MvPolynomial R ℤ) :
    eval₂ c (f ∘ X) x = f x := by
  apply MvPolynomial.induction_on x
    (fun n => by
      rw [hom_C f, eval₂_C]
      exact eq_intCast c n)
    (fun p q hp hq => by
      rw [eval₂_add, hp, hq]
      exact (f.map_add _ _).symm)
    (fun p n hp => by
      rw [eval₂_mul, eval₂_X, hp]
      

Proof state:
R✝ : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R✝
e : ℕ
n✝ m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R✝
p✝ q : MvPolynomial σ R✝
inst✝ : CommRing S
f✝ : R✝ →+* S
g : σ → S
R : Type u
c : ℤ →+* S
f : MvPolynomial R ℤ →+* S
x p : MvPolynomial R ℤ
n : R
hp : eval₂ c (⇑f ∘ X) p = f p
⊢ f p * (⇑f ∘ X) n = f (p * X n)

Next tactic:
exact (f.map_mul _ _).symm
/-- Ring homomorphisms out of integer polynomials on a type `σ` are the same as
functions out of the type `σ`, -/
def homEquiv : (MvPolynomial σ ℤ →+* S) ≃ (σ → S) where
  toFun f := f ∘ X
  invFun f := eval₂Hom (Int.castRingHom S) f
  left_inv f := RingHom.ext <| eval₂Hom_X _ _
  right_inv f := funext fun x => by 

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R
p q : MvPolynomial σ R
inst✝ : CommRing S
f✝ : R →+* S
g f : σ → S
x : σ
⊢ (fun f => ⇑f ∘ X) ((fun f => eval₂Hom (Int.castRingHom S) f) f) x = f x

Next tactic:
simp only [coe_eval₂Hom, Function.comp_apply, eval₂_X]
theorem degreeOf_sub_lt {x : σ} {f g : MvPolynomial σ R} {k : ℕ} (h : 0 < k)
    (hf : ∀ m : σ →₀ ℕ, m ∈ f.support → k ≤ m x → coeff m f = coeff m g)
    (hg : ∀ m : σ →₀ ℕ, m ∈ g.support → k ≤ m x → coeff m f = coeff m g) :
    degreeOf x (f - g) < k := by
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝ : CommRing R
p q : MvPolynomial σ R
x : σ
f g : MvPolynomial σ R
k : ℕ
h : 0 < k
hf : ∀ m ∈ support f, k ≤ m x → coeff m f = coeff m g
hg : ∀ m ∈ support g, k ≤ m x → coeff m f = coeff m g
⊢ degreeOf x (f - g) < k

Next tactic:
classical
  rw [degreeOf_lt_iff h]
  intro m hm
  by_contra! hc
  have h := support_sub σ f g hm
  simp only [mem_support_iff, Ne.def, coeff_sub, sub_eq_zero] at hm
  cases' Finset.mem_union.1 h with cf cg
  · exact hm (hf m cf hc)
  · exact hm (hg m cg hc)
theorem degreeOf_sub_lt {x : σ} {f g : MvPolynomial σ R} {k : ℕ} (h : 0 < k)
    (hf : ∀ m : σ →₀ ℕ, m ∈ f.support → k ≤ m x → coeff m f = coeff m g)
    (hg : ∀ m : σ →₀ ℕ, m ∈ g.support → k ≤ m x → coeff m f = coeff m g) :
    degreeOf x (f - g) < k := by
  classical
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝ : CommRing R
p q : MvPolynomial σ R
x : σ
f g : MvPolynomial σ R
k : ℕ
h : 0 < k
hf : ∀ m ∈ support f, k ≤ m x → coeff m f = coeff m g
hg : ∀ m ∈ support g, k ≤ m x → coeff m f = coeff m g
⊢ degreeOf x (f - g) < k

Next tactic:
rw [degreeOf_lt_iff h]
theorem degreeOf_sub_lt {x : σ} {f g : MvPolynomial σ R} {k : ℕ} (h : 0 < k)
    (hf : ∀ m : σ →₀ ℕ, m ∈ f.support → k ≤ m x → coeff m f = coeff m g)
    (hg : ∀ m : σ →₀ ℕ, m ∈ g.support → k ≤ m x → coeff m f = coeff m g) :
    degreeOf x (f - g) < k := by
  classical
  rw [degreeOf_lt_iff h]
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝ : CommRing R
p q : MvPolynomial σ R
x : σ
f g : MvPolynomial σ R
k : ℕ
h : 0 < k
hf : ∀ m ∈ support f, k ≤ m x → coeff m f = coeff m g
hg : ∀ m ∈ support g, k ≤ m x → coeff m f = coeff m g
⊢ ∀ m ∈ support (f - g), m x < k

Next tactic:
intro m hm
theorem degreeOf_sub_lt {x : σ} {f g : MvPolynomial σ R} {k : ℕ} (h : 0 < k)
    (hf : ∀ m : σ →₀ ℕ, m ∈ f.support → k ≤ m x → coeff m f = coeff m g)
    (hg : ∀ m : σ →₀ ℕ, m ∈ g.support → k ≤ m x → coeff m f = coeff m g) :
    degreeOf x (f - g) < k := by
  classical
  rw [degreeOf_lt_iff h]
  intro m hm
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m✝ : σ
s : σ →₀ ℕ
inst✝ : CommRing R
p q : MvPolynomial σ R
x : σ
f g : MvPolynomial σ R
k : ℕ
h : 0 < k
hf : ∀ m ∈ support f, k ≤ m x → coeff m f = coeff m g
hg : ∀ m ∈ support g, k ≤ m x → coeff m f = coeff m g
m : σ →₀ ℕ
hm : m ∈ support (f - g)
⊢ m x < k

Next tactic:
by_contra! hc
theorem degreeOf_sub_lt {x : σ} {f g : MvPolynomial σ R} {k : ℕ} (h : 0 < k)
    (hf : ∀ m : σ →₀ ℕ, m ∈ f.support → k ≤ m x → coeff m f = coeff m g)
    (hg : ∀ m : σ →₀ ℕ, m ∈ g.support → k ≤ m x → coeff m f = coeff m g) :
    degreeOf x (f - g) < k := by
  classical
  rw [degreeOf_lt_iff h]
  intro m hm
  by_contra! hc
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m✝ : σ
s : σ →₀ ℕ
inst✝ : CommRing R
p q : MvPolynomial σ R
x : σ
f g : MvPolynomial σ R
k : ℕ
h : 0 < k
hf : ∀ m ∈ support f, k ≤ m x → coeff m f = coeff m g
hg : ∀ m ∈ support g, k ≤ m x → coeff m f = coeff m g
m : σ →₀ ℕ
hm : m ∈ support (f - g)
hc : k ≤ m x
⊢ False

Next tactic:
have h := support_sub σ f g hm
theorem degreeOf_sub_lt {x : σ} {f g : MvPolynomial σ R} {k : ℕ} (h : 0 < k)
    (hf : ∀ m : σ →₀ ℕ, m ∈ f.support → k ≤ m x → coeff m f = coeff m g)
    (hg : ∀ m : σ →₀ ℕ, m ∈ g.support → k ≤ m x → coeff m f = coeff m g) :
    degreeOf x (f - g) < k := by
  classical
  rw [degreeOf_lt_iff h]
  intro m hm
  by_contra! hc
  have h := support_sub σ f g hm
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m✝ : σ
s : σ →₀ ℕ
inst✝ : CommRing R
p q : MvPolynomial σ R
x : σ
f g : MvPolynomial σ R
k : ℕ
h✝ : 0 < k
hf : ∀ m ∈ support f, k ≤ m x → coeff m f = coeff m g
hg : ∀ m ∈ support g, k ≤ m x → coeff m f = coeff m g
m : σ →₀ ℕ
hm : m ∈ support (f - g)
hc : k ≤ m x
h : m ∈ support f ∪ support g
⊢ False

Next tactic:
simp only [mem_support_iff, Ne.def, coeff_sub, sub_eq_zero] at hm
theorem degreeOf_sub_lt {x : σ} {f g : MvPolynomial σ R} {k : ℕ} (h : 0 < k)
    (hf : ∀ m : σ →₀ ℕ, m ∈ f.support → k ≤ m x → coeff m f = coeff m g)
    (hg : ∀ m : σ →₀ ℕ, m ∈ g.support → k ≤ m x → coeff m f = coeff m g) :
    degreeOf x (f - g) < k := by
  classical
  rw [degreeOf_lt_iff h]
  intro m hm
  by_contra! hc
  have h := support_sub σ f g hm
  simp only [mem_support_iff, Ne.def, coeff_sub, sub_eq_zero] at hm
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m✝ : σ
s : σ →₀ ℕ
inst✝ : CommRing R
p q : MvPolynomial σ R
x : σ
f g : MvPolynomial σ R
k : ℕ
h✝ : 0 < k
hf : ∀ m ∈ support f, k ≤ m x → coeff m f = coeff m g
hg : ∀ m ∈ support g, k ≤ m x → coeff m f = coeff m g
m : σ →₀ ℕ
hc : k ≤ m x
h : m ∈ support f ∪ support g
hm : ¬coeff m f = coeff m g
⊢ False

Next tactic:
cases' Finset.mem_union.1 h with cf cg
theorem degreeOf_sub_lt {x : σ} {f g : MvPolynomial σ R} {k : ℕ} (h : 0 < k)
    (hf : ∀ m : σ →₀ ℕ, m ∈ f.support → k ≤ m x → coeff m f = coeff m g)
    (hg : ∀ m : σ →₀ ℕ, m ∈ g.support → k ≤ m x → coeff m f = coeff m g) :
    degreeOf x (f - g) < k := by
  classical
  rw [degreeOf_lt_iff h]
  intro m hm
  by_contra! hc
  have h := support_sub σ f g hm
  simp only [mem_support_iff, Ne.def, coeff_sub, sub_eq_zero] at hm
  cases' Finset.mem_union.1 h with cf cg
  · 

Proof state:
case inl
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m✝ : σ
s : σ →₀ ℕ
inst✝ : CommRing R
p q : MvPolynomial σ R
x : σ
f g : MvPolynomial σ R
k : ℕ
h✝ : 0 < k
hf : ∀ m ∈ support f, k ≤ m x → coeff m f = coeff m g
hg : ∀ m ∈ support g, k ≤ m x → coeff m f = coeff m g
m : σ →₀ ℕ
hc : k ≤ m x
h : m ∈ support f ∪ support g
hm : ¬coeff m f = coeff m g
cf : m ∈ support f
⊢ False

Next tactic:
exact hm (hf m cf hc)
theorem degreeOf_sub_lt {x : σ} {f g : MvPolynomial σ R} {k : ℕ} (h : 0 < k)
    (hf : ∀ m : σ →₀ ℕ, m ∈ f.support → k ≤ m x → coeff m f = coeff m g)
    (hg : ∀ m : σ →₀ ℕ, m ∈ g.support → k ≤ m x → coeff m f = coeff m g) :
    degreeOf x (f - g) < k := by
  classical
  rw [degreeOf_lt_iff h]
  intro m hm
  by_contra! hc
  have h := support_sub σ f g hm
  simp only [mem_support_iff, Ne.def, coeff_sub, sub_eq_zero] at hm
  cases' Finset.mem_union.1 h with cf cg
  · exact hm (hf m cf hc)
  · 

Proof state:
case inr
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m✝ : σ
s : σ →₀ ℕ
inst✝ : CommRing R
p q : MvPolynomial σ R
x : σ
f g : MvPolynomial σ R
k : ℕ
h✝ : 0 < k
hf : ∀ m ∈ support f, k ≤ m x → coeff m f = coeff m g
hg : ∀ m ∈ support g, k ≤ m x → coeff m f = coeff m g
m : σ →₀ ℕ
hc : k ≤ m x
h : m ∈ support f ∪ support g
hm : ¬coeff m f = coeff m g
cg : m ∈ support g
⊢ False

Next tactic:
exact hm (hg m cg hc)
@[simp]
theorem totalDegree_neg (a : MvPolynomial σ R) : (-a).totalDegree = a.totalDegree := by
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
a✝ a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝ : CommRing R
p q a : MvPolynomial σ R
⊢ totalDegree (-a) = totalDegree a

Next tactic:
simp only [totalDegree, support_neg]
theorem totalDegree_sub (a b : MvPolynomial σ R) :
    (a - b).totalDegree ≤ max a.totalDegree b.totalDegree :=
  calc
    (a - b).totalDegree = (a + -b).totalDegree := by 

Proof state:
R : Type u
S : Type v
σ : Type u_1
a✝ a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝ : CommRing R
p q a b : MvPolynomial σ R
⊢ totalDegree (a - b) = totalDegree (a + -b)

Next tactic:
rw [sub_eq_add_neg]
theorem totalDegree_sub (a b : MvPolynomial σ R) :
    (a - b).totalDegree ≤ max a.totalDegree b.totalDegree :=
  calc
    (a - b).totalDegree = (a + -b).totalDegree := by rw [sub_eq_add_neg]
    _ ≤ max a.totalDegree (-b).totalDegree := (totalDegree_add a (-b))
    _ = max a.totalDegree b.totalDegree := by 

Proof state:
R : Type u
S : Type v
σ : Type u_1
a✝ a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝ : CommRing R
p q a b : MvPolynomial σ R
⊢ max (totalDegree a) (totalDegree (-b)) = max (totalDegree a) (totalDegree b)

Next tactic:
rw [totalDegree_neg]
theorem totalDegree_sub_C_le (p : MvPolynomial σ R) (r : R) :
    totalDegree (p - C r) ≤ totalDegree p :=
  (totalDegree_sub _ _).trans_eq <| by 

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝ : CommRing R
p✝ q p : MvPolynomial σ R
r : R
⊢ max (totalDegree p) (totalDegree (C r)) = totalDegree p

Next tactic:
rw [totalDegree_C, Nat.max_zero]
/-- The collection of elements of a `MonoidWithZero` that are not left zero divisors form a
`Submonoid`. -/
def nonZeroDivisorsLeft : Submonoid M₀ where
  carrier := {x | ∀ y, y * x = 0 → y = 0}
  one_mem' := by 

Proof state:
M₀ : Type u_1
inst✝ : MonoidWithZero M₀
⊢ 1 ∈
    { carrier := {x | ∀ (y : M₀), y * x = 0 → y = 0},
        mul_mem' :=
          (_ :
            ∀ {x y : M₀},
              x ∈ {x | ∀ (y : M₀), y * x = 0 → y = 0} →
                y ∈ {x | ∀ (y : M₀), y * x = 0 → y = 0} → ∀ (z : M₀), z * (x * y) = 0 → z = 0) }.carrier

Next tactic:
simp
/-- The collection of elements of a `MonoidWithZero` that are not right zero divisors form a
`Submonoid`. -/
def nonZeroDivisorsRight : Submonoid M₀ where
  carrier := {x | ∀ y, x * y = 0 → y = 0}
  one_mem' := by 

Proof state:
M₀ : Type u_1
inst✝ : MonoidWithZero M₀
⊢ 1 ∈
    { carrier := {x | ∀ (y : M₀), x * y = 0 → y = 0},
        mul_mem' :=
          (_ :
            ∀ {x y : M₀},
              x ∈ {x | ∀ (y : M₀), x * y = 0 → y = 0} →
                y ∈ {x | ∀ (y : M₀), x * y = 0 → y = 0} → ∀ (z : M₀), x * y * z = 0 → z = 0) }.carrier

Next tactic:
simp
lemma nonZeroDivisorsLeft_eq_right (M₀ : Type*) [CommMonoidWithZero M₀] :
    nonZeroDivisorsLeft M₀ = nonZeroDivisorsRight M₀ := by
  

Proof state:
M₀✝ : Type u_1
inst✝¹ : MonoidWithZero M₀✝
M₀ : Type u_2
inst✝ : CommMonoidWithZero M₀
⊢ nonZeroDivisorsLeft M₀ = nonZeroDivisorsRight M₀

Next tactic:
ext x
lemma nonZeroDivisorsLeft_eq_right (M₀ : Type*) [CommMonoidWithZero M₀] :
    nonZeroDivisorsLeft M₀ = nonZeroDivisorsRight M₀ := by
  ext x; 

Proof state:
case h
M₀✝ : Type u_1
inst✝¹ : MonoidWithZero M₀✝
M₀ : Type u_2
inst✝ : CommMonoidWithZero M₀
x : M₀
⊢ x ∈ nonZeroDivisorsLeft M₀ ↔ x ∈ nonZeroDivisorsRight M₀

Next tactic:
simp [mul_comm x]
@[simp] lemma coe_nonZeroDivisorsLeft_eq [NoZeroDivisors M₀] [Nontrivial M₀] :
    nonZeroDivisorsLeft M₀ = {x : M₀ | x ≠ 0} := by
  

Proof state:
M₀ : Type u_1
inst✝² : MonoidWithZero M₀
inst✝¹ : NoZeroDivisors M₀
inst✝ : Nontrivial M₀
⊢ ↑(nonZeroDivisorsLeft M₀) = {x | x ≠ 0}

Next tactic:
ext x
@[simp] lemma coe_nonZeroDivisorsLeft_eq [NoZeroDivisors M₀] [Nontrivial M₀] :
    nonZeroDivisorsLeft M₀ = {x : M₀ | x ≠ 0} := by
  ext x
  

Proof state:
case h
M₀ : Type u_1
inst✝² : MonoidWithZero M₀
inst✝¹ : NoZeroDivisors M₀
inst✝ : Nontrivial M₀
x : M₀
⊢ x ∈ ↑(nonZeroDivisorsLeft M₀) ↔ x ∈ {x | x ≠ 0}

Next tactic:
simp only [SetLike.mem_coe, mem_nonZeroDivisorsLeft_iff, mul_eq_zero, forall_eq_or_imp, true_and,
    Set.mem_setOf_eq]
@[simp] lemma coe_nonZeroDivisorsLeft_eq [NoZeroDivisors M₀] [Nontrivial M₀] :
    nonZeroDivisorsLeft M₀ = {x : M₀ | x ≠ 0} := by
  ext x
  simp only [SetLike.mem_coe, mem_nonZeroDivisorsLeft_iff, mul_eq_zero, forall_eq_or_imp, true_and,
    Set.mem_setOf_eq]
  

Proof state:
case h
M₀ : Type u_1
inst✝² : MonoidWithZero M₀
inst✝¹ : NoZeroDivisors M₀
inst✝ : Nontrivial M₀
x : M₀
⊢ (∀ (a : M₀), x = 0 → a = 0) ↔ x ≠ 0

Next tactic:
refine' ⟨fun h ↦ _, fun hx y hx' ↦ by contradiction⟩
@[simp] lemma coe_nonZeroDivisorsLeft_eq [NoZeroDivisors M₀] [Nontrivial M₀] :
    nonZeroDivisorsLeft M₀ = {x : M₀ | x ≠ 0} := by
  ext x
  simp only [SetLike.mem_coe, mem_nonZeroDivisorsLeft_iff, mul_eq_zero, forall_eq_or_imp, true_and,
    Set.mem_setOf_eq]
  refine' ⟨fun h ↦ _, fun hx y hx' ↦ by 

Proof state:
M₀ : Type u_1
inst✝² : MonoidWithZero M₀
inst✝¹ : NoZeroDivisors M₀
inst✝ : Nontrivial M₀
x : M₀
hx : x ≠ 0
y : M₀
hx' : x = 0
⊢ y = 0

Next tactic:
contradiction
@[simp] lemma coe_nonZeroDivisorsLeft_eq [NoZeroDivisors M₀] [Nontrivial M₀] :
    nonZeroDivisorsLeft M₀ = {x : M₀ | x ≠ 0} := by
  ext x
  simp only [SetLike.mem_coe, mem_nonZeroDivisorsLeft_iff, mul_eq_zero, forall_eq_or_imp, true_and,
    Set.mem_setOf_eq]
  refine' ⟨fun h ↦ _, fun hx y hx' ↦ by contradiction⟩
  

Proof state:
case h
M₀ : Type u_1
inst✝² : MonoidWithZero M₀
inst✝¹ : NoZeroDivisors M₀
inst✝ : Nontrivial M₀
x : M₀
h : ∀ (a : M₀), x = 0 → a = 0
⊢ x ≠ 0

Next tactic:
contrapose! h
@[simp] lemma coe_nonZeroDivisorsLeft_eq [NoZeroDivisors M₀] [Nontrivial M₀] :
    nonZeroDivisorsLeft M₀ = {x : M₀ | x ≠ 0} := by
  ext x
  simp only [SetLike.mem_coe, mem_nonZeroDivisorsLeft_iff, mul_eq_zero, forall_eq_or_imp, true_and,
    Set.mem_setOf_eq]
  refine' ⟨fun h ↦ _, fun hx y hx' ↦ by contradiction⟩
  contrapose! h
  

Proof state:
case h
M₀ : Type u_1
inst✝² : MonoidWithZero M₀
inst✝¹ : NoZeroDivisors M₀
inst✝ : Nontrivial M₀
x : M₀
h : x = 0
⊢ ∃ a, x = 0 ∧ a ≠ 0

Next tactic:
exact ⟨1, h, one_ne_zero⟩
@[simp] lemma coe_nonZeroDivisorsRight_eq [NoZeroDivisors M₀] [Nontrivial M₀] :
    nonZeroDivisorsRight M₀ = {x : M₀ | x ≠ 0} := by
  

Proof state:
M₀ : Type u_1
inst✝² : MonoidWithZero M₀
inst✝¹ : NoZeroDivisors M₀
inst✝ : Nontrivial M₀
⊢ ↑(nonZeroDivisorsRight M₀) = {x | x ≠ 0}

Next tactic:
ext x
@[simp] lemma coe_nonZeroDivisorsRight_eq [NoZeroDivisors M₀] [Nontrivial M₀] :
    nonZeroDivisorsRight M₀ = {x : M₀ | x ≠ 0} := by
  ext x
  

Proof state:
case h
M₀ : Type u_1
inst✝² : MonoidWithZero M₀
inst✝¹ : NoZeroDivisors M₀
inst✝ : Nontrivial M₀
x : M₀
⊢ x ∈ ↑(nonZeroDivisorsRight M₀) ↔ x ∈ {x | x ≠ 0}

Next tactic:
simp only [SetLike.mem_coe, mem_nonZeroDivisorsRight_iff, mul_eq_zero, Set.mem_setOf_eq]
@[simp] lemma coe_nonZeroDivisorsRight_eq [NoZeroDivisors M₀] [Nontrivial M₀] :
    nonZeroDivisorsRight M₀ = {x : M₀ | x ≠ 0} := by
  ext x
  simp only [SetLike.mem_coe, mem_nonZeroDivisorsRight_iff, mul_eq_zero, Set.mem_setOf_eq]
  

Proof state:
case h
M₀ : Type u_1
inst✝² : MonoidWithZero M₀
inst✝¹ : NoZeroDivisors M₀
inst✝ : Nontrivial M₀
x : M₀
⊢ (∀ (y : M₀), x = 0 ∨ y = 0 → y = 0) ↔ x ≠ 0

Next tactic:
refine' ⟨fun h ↦ _, fun hx y hx' ↦ by aesop⟩
@[simp] lemma coe_nonZeroDivisorsRight_eq [NoZeroDivisors M₀] [Nontrivial M₀] :
    nonZeroDivisorsRight M₀ = {x : M₀ | x ≠ 0} := by
  ext x
  simp only [SetLike.mem_coe, mem_nonZeroDivisorsRight_iff, mul_eq_zero, Set.mem_setOf_eq]
  refine' ⟨fun h ↦ _, fun hx y hx' ↦ by 

Proof state:
M₀ : Type u_1
inst✝² : MonoidWithZero M₀
inst✝¹ : NoZeroDivisors M₀
inst✝ : Nontrivial M₀
x : M₀
hx : x ≠ 0
y : M₀
hx' : x = 0 ∨ y = 0
⊢ y = 0

Next tactic:
aesop
@[simp] lemma coe_nonZeroDivisorsRight_eq [NoZeroDivisors M₀] [Nontrivial M₀] :
    nonZeroDivisorsRight M₀ = {x : M₀ | x ≠ 0} := by
  ext x
  simp only [SetLike.mem_coe, mem_nonZeroDivisorsRight_iff, mul_eq_zero, Set.mem_setOf_eq]
  refine' ⟨fun h ↦ _, fun hx y hx' ↦ by aesop⟩
  

Proof state:
case h
M₀ : Type u_1
inst✝² : MonoidWithZero M₀
inst✝¹ : NoZeroDivisors M₀
inst✝ : Nontrivial M₀
x : M₀
h : ∀ (y : M₀), x = 0 ∨ y = 0 → y = 0
⊢ x ≠ 0

Next tactic:
contrapose! h
@[simp] lemma coe_nonZeroDivisorsRight_eq [NoZeroDivisors M₀] [Nontrivial M₀] :
    nonZeroDivisorsRight M₀ = {x : M₀ | x ≠ 0} := by
  ext x
  simp only [SetLike.mem_coe, mem_nonZeroDivisorsRight_iff, mul_eq_zero, Set.mem_setOf_eq]
  refine' ⟨fun h ↦ _, fun hx y hx' ↦ by aesop⟩
  contrapose! h
  

Proof state:
case h
M₀ : Type u_1
inst✝² : MonoidWithZero M₀
inst✝¹ : NoZeroDivisors M₀
inst✝ : Nontrivial M₀
x : M₀
h : x = 0
⊢ ∃ y, (x = 0 ∨ y = 0) ∧ y ≠ 0

Next tactic:
exact ⟨1, Or.inl h, one_ne_zero⟩
/-- The submonoid of non-zero-divisors of a `MonoidWithZero` `R`. -/
def nonZeroDivisors (R : Type*) [MonoidWithZero R] : Submonoid R where
  carrier := { x | ∀ z, z * x = 0 → z = 0 }
  one_mem' _ hz := by rwa [mul_one] at hz
  mul_mem' hx₁ hx₂ _ hz := by
    

Proof state:
M₀ : Type u_1
inst✝¹ : MonoidWithZero M₀
R : Type u_2
inst✝ : MonoidWithZero R
a✝ b✝ : R
hx₁ : a✝ ∈ {x | ∀ (z : R), z * x = 0 → z = 0}
hx₂ : b✝ ∈ {x | ∀ (z : R), z * x = 0 → z = 0}
x✝ : R
hz : x✝ * (a✝ * b✝) = 0
⊢ x✝ = 0

Next tactic:
rw [← mul_assoc] at hz
/-- The submonoid of non-zero-divisors of a `MonoidWithZero` `R`. -/
def nonZeroDivisors (R : Type*) [MonoidWithZero R] : Submonoid R where
  carrier := { x | ∀ z, z * x = 0 → z = 0 }
  one_mem' _ hz := by rwa [mul_one] at hz
  mul_mem' hx₁ hx₂ _ hz := by
    rw [← mul_assoc] at hz
    

Proof state:
M₀ : Type u_1
inst✝¹ : MonoidWithZero M₀
R : Type u_2
inst✝ : MonoidWithZero R
a✝ b✝ : R
hx₁ : a✝ ∈ {x | ∀ (z : R), z * x = 0 → z = 0}
hx₂ : b✝ ∈ {x | ∀ (z : R), z * x = 0 → z = 0}
x✝ : R
hz : x✝ * a✝ * b✝ = 0
⊢ x✝ = 0

Next tactic:
exact hx₁ _ (hx₂ _ hz)
/-- The submonoid of non-zero-divisors of a `MonoidWithZero` `R`. -/
def nonZeroDivisors (R : Type*) [MonoidWithZero R] : Submonoid R where
  carrier := { x | ∀ z, z * x = 0 → z = 0 }
  one_mem' _ hz := by 

Proof state:
M₀ : Type u_1
inst✝¹ : MonoidWithZero M₀
R : Type u_2
inst✝ : MonoidWithZero R
x✝ : R
hz : x✝ * 1 = 0
⊢ x✝ = 0

Next tactic:
rwa [mul_one] at hz
theorem mul_right_mem_nonZeroDivisors_eq_zero_iff {x r : M} (hr : r ∈ M⁰) : x * r = 0 ↔ x = 0 :=
  ⟨hr _, by 

Proof state:
M₀ : Type u_1
inst✝⁵ : MonoidWithZero M₀
M : Type u_2
M' : Type u_3
M₁ : Type u_4
R : Type u_5
R' : Type u_6
F : Type u_7
inst✝⁴ : MonoidWithZero M
inst✝³ : MonoidWithZero M'
inst✝² : CommMonoidWithZero M₁
inst✝¹ : Ring R
inst✝ : CommRing R'
x r : M
hr : r ∈ M⁰
⊢ x = 0 → x * r = 0

Next tactic:
simp (config := { contextual := true })
theorem mul_left_mem_nonZeroDivisors_eq_zero_iff {r x : M₁} (hr : r ∈ M₁⁰) : r * x = 0 ↔ x = 0 := by
  

Proof state:
M₀ : Type u_1
inst✝⁵ : MonoidWithZero M₀
M : Type u_2
M' : Type u_3
M₁ : Type u_4
R : Type u_5
R' : Type u_6
F : Type u_7
inst✝⁴ : MonoidWithZero M
inst✝³ : MonoidWithZero M'
inst✝² : CommMonoidWithZero M₁
inst✝¹ : Ring R
inst✝ : CommRing R'
r x : M₁
hr : r ∈ M₁⁰
⊢ r * x = 0 ↔ x = 0

Next tactic:
rw [mul_comm, mul_right_mem_nonZeroDivisors_eq_zero_iff hr]
theorem mul_cancel_right_mem_nonZeroDivisors {x y r : R} (hr : r ∈ R⁰) : x * r = y * r ↔ x = y := by
  

Proof state:
M₀ : Type u_1
inst✝⁵ : MonoidWithZero M₀
M : Type u_2
M' : Type u_3
M₁ : Type u_4
R : Type u_5
R' : Type u_6
F : Type u_7
inst✝⁴ : MonoidWithZero M
inst✝³ : MonoidWithZero M'
inst✝² : CommMonoidWithZero M₁
inst✝¹ : Ring R
inst✝ : CommRing R'
x y r : R
hr : r ∈ R⁰
⊢ x * r = y * r ↔ x = y

Next tactic:
refine ⟨fun h ↦ ?_, congrArg (· * r)⟩
theorem mul_cancel_right_mem_nonZeroDivisors {x y r : R} (hr : r ∈ R⁰) : x * r = y * r ↔ x = y := by
  refine ⟨fun h ↦ ?_, congrArg (· * r)⟩
  

Proof state:
M₀ : Type u_1
inst✝⁵ : MonoidWithZero M₀
M : Type u_2
M' : Type u_3
M₁ : Type u_4
R : Type u_5
R' : Type u_6
F : Type u_7
inst✝⁴ : MonoidWithZero M
inst✝³ : MonoidWithZero M'
inst✝² : CommMonoidWithZero M₁
inst✝¹ : Ring R
inst✝ : CommRing R'
x y r : R
hr : r ∈ R⁰
h : x * r = y * r
⊢ x = y

Next tactic:
rw [← sub_eq_zero, ← mul_right_mem_nonZeroDivisors_eq_zero_iff hr, sub_mul, h, sub_self]
@[simp]
theorem mul_cancel_left_mem_nonZeroDivisors {x y r : R'} (hr : r ∈ R'⁰) : r * x = r * y ↔ x = y :=
  by 

Proof state:
M₀ : Type u_1
inst✝⁵ : MonoidWithZero M₀
M : Type u_2
M' : Type u_3
M₁ : Type u_4
R : Type u_5
R' : Type u_6
F : Type u_7
inst✝⁴ : MonoidWithZero M
inst✝³ : MonoidWithZero M'
inst✝² : CommMonoidWithZero M₁
inst✝¹ : Ring R
inst✝ : CommRing R'
x y r : R'
hr : r ∈ R'⁰
⊢ r * x = r * y ↔ x = y

Next tactic:
simp_rw [mul_comm r, mul_cancel_right_mem_nonZeroDivisors hr]
theorem dvd_cancel_right_mem_nonZeroDivisors {x y r : R'} (hr : r ∈ R'⁰) : x * r ∣ y * r ↔ x ∣ y :=
  ⟨fun ⟨z, _⟩ ↦ ⟨z, by 

Proof state:
M₀ : Type u_1
inst✝⁵ : MonoidWithZero M₀
M : Type u_2
M' : Type u_3
M₁ : Type u_4
R : Type u_5
R' : Type u_6
F : Type u_7
inst✝⁴ : MonoidWithZero M
inst✝³ : MonoidWithZero M'
inst✝² : CommMonoidWithZero M₁
inst✝¹ : Ring R
inst✝ : CommRing R'
x y r : R'
hr : r ∈ R'⁰
x✝ : x * r ∣ y * r
z : R'
h✝ : y * r = x * r * z
⊢ y = x * z

Next tactic:
rwa [← mul_cancel_right_mem_nonZeroDivisors hr, mul_assoc, mul_comm z r,
    ← mul_assoc]
theorem dvd_cancel_right_mem_nonZeroDivisors {x y r : R'} (hr : r ∈ R'⁰) : x * r ∣ y * r ↔ x ∣ y :=
  ⟨fun ⟨z, _⟩ ↦ ⟨z, by rwa [← mul_cancel_right_mem_nonZeroDivisors hr, mul_assoc, mul_comm z r,
    ← mul_assoc]⟩, fun ⟨z, h⟩ ↦ ⟨z, by 

Proof state:
M₀ : Type u_1
inst✝⁵ : MonoidWithZero M₀
M : Type u_2
M' : Type u_3
M₁ : Type u_4
R : Type u_5
R' : Type u_6
F : Type u_7
inst✝⁴ : MonoidWithZero M
inst✝³ : MonoidWithZero M'
inst✝² : CommMonoidWithZero M₁
inst✝¹ : Ring R
inst✝ : CommRing R'
x y r : R'
hr : r ∈ R'⁰
x✝ : x ∣ y
z : R'
h : y = x * z
⊢ y * r = x * r * z

Next tactic:
rw [h, mul_assoc, mul_comm z r, ← mul_assoc]
theorem dvd_cancel_left_mem_nonZeroDivisors {x y r : R'} (hr : r ∈ R'⁰) : r * x ∣ r * y ↔ x ∣ y :=
  ⟨fun ⟨z, _⟩ ↦ ⟨z, by 

Proof state:
M₀ : Type u_1
inst✝⁵ : MonoidWithZero M₀
M : Type u_2
M' : Type u_3
M₁ : Type u_4
R : Type u_5
R' : Type u_6
F : Type u_7
inst✝⁴ : MonoidWithZero M
inst✝³ : MonoidWithZero M'
inst✝² : CommMonoidWithZero M₁
inst✝¹ : Ring R
inst✝ : CommRing R'
x y r : R'
hr : r ∈ R'⁰
x✝ : r * x ∣ r * y
z : R'
h✝ : r * y = r * x * z
⊢ y = x * z

Next tactic:
rwa [← mul_cancel_left_mem_nonZeroDivisors hr, ← mul_assoc]
theorem dvd_cancel_left_mem_nonZeroDivisors {x y r : R'} (hr : r ∈ R'⁰) : r * x ∣ r * y ↔ x ∣ y :=
  ⟨fun ⟨z, _⟩ ↦ ⟨z, by rwa [← mul_cancel_left_mem_nonZeroDivisors hr, ← mul_assoc]⟩,
    fun ⟨z, h⟩ ↦ ⟨z, by 

Proof state:
M₀ : Type u_1
inst✝⁵ : MonoidWithZero M₀
M : Type u_2
M' : Type u_3
M₁ : Type u_4
R : Type u_5
R' : Type u_6
F : Type u_7
inst✝⁴ : MonoidWithZero M
inst✝³ : MonoidWithZero M'
inst✝² : CommMonoidWithZero M₁
inst✝¹ : Ring R
inst✝ : CommRing R'
x y r : R'
hr : r ∈ R'⁰
x✝ : x ∣ y
z : R'
h : y = x * z
⊢ r * y = r * x * z

Next tactic:
rw [h, ← mul_assoc]