l3lab/ntp-mathlib huggingface dataset:
theorem sup_ker_aeval_eq_ker_aeval_mul_of_coprime (f : M →ₗ[R] M) {p q : R[X]}
    (hpq : IsCoprime p q) :
    LinearMap.ker (aeval f p) ⊔ LinearMap.ker (aeval f q) = LinearMap.ker (aeval f (p * q)) := by
  apply le_antisymm sup_ker_aeval_le_ker_aeval_mul
  intro v hv
  rw [Submodule.mem_sup]
  rcases hpq with ⟨p', q', hpq'⟩
  have h_eval₂_qpp' :=
    calc
      aeval f (q * (p * p')) v = aeval f (p' * (p * q)) v := by
        rw [mul_comm, mul_assoc, mul_comm, mul_assoc, mul_comm q p]
      _ = 0 := by rw [aeval_mul, LinearMap.mul_apply, LinearMap.mem_ker.1 hv, LinearMap.map_zero]

  have h_eval₂_pqq' :=
    calc
      aeval f (p * (q * q')) v = aeval f (q' * (p * q)) v := by rw [← mul_assoc, mul_comm]
      _ = 0 := by rw [aeval_mul, LinearMap.mul_apply, LinearMap.mem_ker.1 hv, LinearMap.map_zero]

  rw [aeval_mul] at h_eval₂_qpp' h_eval₂_pqq'
  refine'
    ⟨aeval f (q * q') v, LinearMap.mem_ker.1 h_eval₂_pqq', aeval f (p * p') v,
      LinearMap.mem_ker.1 h_eval₂_qpp', _⟩
  rw [add_comm, mul_comm p p', mul_comm q q']
  

Proof state:
case intro.intro
R : Type u
S : Type u_1
σ : Type v
M : Type w
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : AddCommGroup M
inst✝ : Module R M
f : M →ₗ[R] M
p q : R[X]
v : M
hv : v ∈ LinearMap.ker ((aeval f) (p * q))
p' q' : R[X]
hpq' : p' * p + q' * q = 1
h_eval₂_qpp' : ((aeval f) q * (aeval f) (p * p')) v = 0
h_eval₂_pqq' : ((aeval f) p * (aeval f) (q * q')) v = 0
⊢ ((aeval f) (p' * p)) v + ((aeval f) (q' * q)) v = v

Next tactic:
simpa only [map_add, map_mul, aeval_one] using congr_arg (fun p : R[X] => aeval f p v) hpq'
theorem isNoetherianRing_fin_0 [IsNoetherianRing R] :
    IsNoetherianRing (MvPolynomial (Fin 0) R) := by
  

Proof state:
R : Type u
S : Type u_1
σ : Type v
M : Type w
inst✝⁴ : CommRing R
inst✝³ : CommRing S
inst✝² : AddCommGroup M
inst✝¹ : Module R M
inst✝ : IsNoetherianRing R
⊢ IsNoetherianRing (MvPolynomial (Fin 0) R)

Next tactic:
apply isNoetherianRing_of_ringEquiv R
theorem isNoetherianRing_fin_0 [IsNoetherianRing R] :
    IsNoetherianRing (MvPolynomial (Fin 0) R) := by
  apply isNoetherianRing_of_ringEquiv R
  

Proof state:
case f
R : Type u
S : Type u_1
σ : Type v
M : Type w
inst✝⁴ : CommRing R
inst✝³ : CommRing S
inst✝² : AddCommGroup M
inst✝¹ : Module R M
inst✝ : IsNoetherianRing R
⊢ R ≃+* MvPolynomial (Fin 0) R

Next tactic:
symm
theorem isNoetherianRing_fin_0 [IsNoetherianRing R] :
    IsNoetherianRing (MvPolynomial (Fin 0) R) := by
  apply isNoetherianRing_of_ringEquiv R
  symm; 

Proof state:
case f
R : Type u
S : Type u_1
σ : Type v
M : Type w
inst✝⁴ : CommRing R
inst✝³ : CommRing S
inst✝² : AddCommGroup M
inst✝¹ : Module R M
inst✝ : IsNoetherianRing R
⊢ MvPolynomial (Fin 0) R ≃+* R

Next tactic:
apply MvPolynomial.isEmptyRingEquiv R (Fin 0)
/-- The multivariate polynomial ring in finitely many variables over a noetherian ring
is itself a noetherian ring. -/
instance isNoetherianRing [Finite σ] [IsNoetherianRing R] :
    IsNoetherianRing (MvPolynomial σ R) := by
  

Proof state:
R : Type u
S : Type u_1
σ : Type v
M : Type w
inst✝⁵ : CommRing R
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : Finite σ
inst✝ : IsNoetherianRing R
⊢ IsNoetherianRing (MvPolynomial σ R)

Next tactic:
cases nonempty_fintype σ
/-- The multivariate polynomial ring in finitely many variables over a noetherian ring
is itself a noetherian ring. -/
instance isNoetherianRing [Finite σ] [IsNoetherianRing R] :
    IsNoetherianRing (MvPolynomial σ R) := by
  cases nonempty_fintype σ
  

Proof state:
case intro
R : Type u
S : Type u_1
σ : Type v
M : Type w
inst✝⁵ : CommRing R
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : Finite σ
inst✝ : IsNoetherianRing R
val✝ : Fintype σ
⊢ IsNoetherianRing (MvPolynomial σ R)

Next tactic:
exact
    @isNoetherianRing_of_ringEquiv (MvPolynomial (Fin (Fintype.card σ)) R) _ _ _
      (renameEquiv R (Fintype.equivFin σ).symm).toRingEquiv isNoetherianRing_fin
/-- Auxiliary definition:
Multivariate polynomials in finitely many variables over an integral domain form an integral domain.
This fact is proven by transport of structure from the `MvPolynomial.noZeroDivisors_fin`,
and then used to prove the general case without finiteness hypotheses.
See `MvPolynomial.noZeroDivisors` for the general case. -/
theorem noZeroDivisors_of_finite (R : Type u) (σ : Type v) [CommSemiring R] [Finite σ]
    [NoZeroDivisors R] : NoZeroDivisors (MvPolynomial σ R) := by
  

Proof state:
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁶ : CommRing R✝
inst✝⁵ : CommRing S
inst✝⁴ : AddCommGroup M
inst✝³ : Module R✝ M
R : Type u
σ : Type v
inst✝² : CommSemiring R
inst✝¹ : Finite σ
inst✝ : NoZeroDivisors R
⊢ NoZeroDivisors (MvPolynomial σ R)

Next tactic:
cases nonempty_fintype σ
/-- Auxiliary definition:
Multivariate polynomials in finitely many variables over an integral domain form an integral domain.
This fact is proven by transport of structure from the `MvPolynomial.noZeroDivisors_fin`,
and then used to prove the general case without finiteness hypotheses.
See `MvPolynomial.noZeroDivisors` for the general case. -/
theorem noZeroDivisors_of_finite (R : Type u) (σ : Type v) [CommSemiring R] [Finite σ]
    [NoZeroDivisors R] : NoZeroDivisors (MvPolynomial σ R) := by
  cases nonempty_fintype σ
  

Proof state:
case intro
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁶ : CommRing R✝
inst✝⁵ : CommRing S
inst✝⁴ : AddCommGroup M
inst✝³ : Module R✝ M
R : Type u
σ : Type v
inst✝² : CommSemiring R
inst✝¹ : Finite σ
inst✝ : NoZeroDivisors R
val✝ : Fintype σ
⊢ NoZeroDivisors (MvPolynomial σ R)

Next tactic:
haveI := noZeroDivisors_fin R (Fintype.card σ)
/-- Auxiliary definition:
Multivariate polynomials in finitely many variables over an integral domain form an integral domain.
This fact is proven by transport of structure from the `MvPolynomial.noZeroDivisors_fin`,
and then used to prove the general case without finiteness hypotheses.
See `MvPolynomial.noZeroDivisors` for the general case. -/
theorem noZeroDivisors_of_finite (R : Type u) (σ : Type v) [CommSemiring R] [Finite σ]
    [NoZeroDivisors R] : NoZeroDivisors (MvPolynomial σ R) := by
  cases nonempty_fintype σ
  haveI := noZeroDivisors_fin R (Fintype.card σ)
  

Proof state:
case intro
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁶ : CommRing R✝
inst✝⁵ : CommRing S
inst✝⁴ : AddCommGroup M
inst✝³ : Module R✝ M
R : Type u
σ : Type v
inst✝² : CommSemiring R
inst✝¹ : Finite σ
inst✝ : NoZeroDivisors R
val✝ : Fintype σ
this : NoZeroDivisors (MvPolynomial (Fin (Fintype.card σ)) R)
⊢ NoZeroDivisors (MvPolynomial σ R)

Next tactic:
exact (renameEquiv R (Fintype.equivFin σ)).injective.noZeroDivisors _ (map_zero _) (map_mul _)
instance {R : Type u} [CommSemiring R] [NoZeroDivisors R] {σ : Type v} :
    NoZeroDivisors (MvPolynomial σ R) :=
  ⟨fun {p} {q} h => by
    

Proof state:
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁵ : CommRing R✝
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R✝ M
R : Type u
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
σ : Type v
p q : MvPolynomial σ R
h : p * q = 0
⊢ p = 0 ∨ q = 0

Next tactic:
classical
    obtain ⟨s, p, rfl⟩ := exists_finset_rename p
    obtain ⟨t, q, rfl⟩ := exists_finset_rename q
    have :
        rename (Subtype.map id (Finset.subset_union_left s t) :
          { x // x ∈ s } → { x // x ∈ s ∪ t }) p *
        rename (Subtype.map id (Finset.subset_union_right s t) :
          { x // x ∈ t } → { x // x ∈ s ∪ t }) q =
        0 := by
      apply rename_injective _ Subtype.val_injective
      simpa using h
    letI that := MvPolynomial.noZeroDivisors_of_finite R { x // x ∈ s ∪ t }
    rw [mul_eq_zero] at this
    apply this.imp <;> intro that <;> simpa using congr_arg (rename Subtype.val) that
instance {R : Type u} [CommSemiring R] [NoZeroDivisors R] {σ : Type v} :
    NoZeroDivisors (MvPolynomial σ R) :=
  ⟨fun {p} {q} h => by
    classical
    

Proof state:
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁵ : CommRing R✝
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R✝ M
R : Type u
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
σ : Type v
p q : MvPolynomial σ R
h : p * q = 0
⊢ p = 0 ∨ q = 0

Next tactic:
obtain ⟨s, p, rfl⟩ := exists_finset_rename p
instance {R : Type u} [CommSemiring R] [NoZeroDivisors R] {σ : Type v} :
    NoZeroDivisors (MvPolynomial σ R) :=
  ⟨fun {p} {q} h => by
    classical
    obtain ⟨s, p, rfl⟩ := exists_finset_rename p
    

Proof state:
case intro.intro
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁵ : CommRing R✝
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R✝ M
R : Type u
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
σ : Type v
q : MvPolynomial σ R
s : Finset σ
p : MvPolynomial { x // x ∈ s } R
h : (rename Subtype.val) p * q = 0
⊢ (rename Subtype.val) p = 0 ∨ q = 0

Next tactic:
obtain ⟨t, q, rfl⟩ := exists_finset_rename q
instance {R : Type u} [CommSemiring R] [NoZeroDivisors R] {σ : Type v} :
    NoZeroDivisors (MvPolynomial σ R) :=
  ⟨fun {p} {q} h => by
    classical
    obtain ⟨s, p, rfl⟩ := exists_finset_rename p
    obtain ⟨t, q, rfl⟩ := exists_finset_rename q
    

Proof state:
case intro.intro.intro.intro
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁵ : CommRing R✝
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R✝ M
R : Type u
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
σ : Type v
s : Finset σ
p : MvPolynomial { x // x ∈ s } R
t : Finset σ
q : MvPolynomial { x // x ∈ t } R
h : (rename Subtype.val) p * (rename Subtype.val) q = 0
⊢ (rename Subtype.val) p = 0 ∨ (rename Subtype.val) q = 0

Next tactic:
have :
        rename (Subtype.map id (Finset.subset_union_left s t) :
          { x // x ∈ s } → { x // x ∈ s ∪ t }) p *
        rename (Subtype.map id (Finset.subset_union_right s t) :
          { x // x ∈ t } → { x // x ∈ s ∪ t }) q =
        0 := by
      apply rename_injective _ Subtype.val_injective
      simpa using h
instance {R : Type u} [CommSemiring R] [NoZeroDivisors R] {σ : Type v} :
    NoZeroDivisors (MvPolynomial σ R) :=
  ⟨fun {p} {q} h => by
    classical
    obtain ⟨s, p, rfl⟩ := exists_finset_rename p
    obtain ⟨t, q, rfl⟩ := exists_finset_rename q
    have :
        rename (Subtype.map id (Finset.subset_union_left s t) :
          { x // x ∈ s } → { x // x ∈ s ∪ t }) p *
        rename (Subtype.map id (Finset.subset_union_right s t) :
          { x // x ∈ t } → { x // x ∈ s ∪ t }) q =
        0 := by
      

Proof state:
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁵ : CommRing R✝
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R✝ M
R : Type u
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
σ : Type v
s : Finset σ
p : MvPolynomial { x // x ∈ s } R
t : Finset σ
q : MvPolynomial { x // x ∈ t } R
h : (rename Subtype.val) p * (rename Subtype.val) q = 0
⊢ (rename (Subtype.map id (_ : s ⊆ s ∪ t))) p * (rename (Subtype.map id (_ : t ⊆ s ∪ t))) q = 0

Next tactic:
apply rename_injective _ Subtype.val_injective
instance {R : Type u} [CommSemiring R] [NoZeroDivisors R] {σ : Type v} :
    NoZeroDivisors (MvPolynomial σ R) :=
  ⟨fun {p} {q} h => by
    classical
    obtain ⟨s, p, rfl⟩ := exists_finset_rename p
    obtain ⟨t, q, rfl⟩ := exists_finset_rename q
    have :
        rename (Subtype.map id (Finset.subset_union_left s t) :
          { x // x ∈ s } → { x // x ∈ s ∪ t }) p *
        rename (Subtype.map id (Finset.subset_union_right s t) :
          { x // x ∈ t } → { x // x ∈ s ∪ t }) q =
        0 := by
      apply rename_injective _ Subtype.val_injective
      

Proof state:
case a
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁵ : CommRing R✝
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R✝ M
R : Type u
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
σ : Type v
s : Finset σ
p : MvPolynomial { x // x ∈ s } R
t : Finset σ
q : MvPolynomial { x // x ∈ t } R
h : (rename Subtype.val) p * (rename Subtype.val) q = 0
⊢ (rename Subtype.val) ((rename (Subtype.map id (_ : s ⊆ s ∪ t))) p * (rename (Subtype.map id (_ : t ⊆ s ∪ t))) q) =
    (rename Subtype.val) 0

Next tactic:
simpa using h
instance {R : Type u} [CommSemiring R] [NoZeroDivisors R] {σ : Type v} :
    NoZeroDivisors (MvPolynomial σ R) :=
  ⟨fun {p} {q} h => by
    classical
    obtain ⟨s, p, rfl⟩ := exists_finset_rename p
    obtain ⟨t, q, rfl⟩ := exists_finset_rename q
    have :
        rename (Subtype.map id (Finset.subset_union_left s t) :
          { x // x ∈ s } → { x // x ∈ s ∪ t }) p *
        rename (Subtype.map id (Finset.subset_union_right s t) :
          { x // x ∈ t } → { x // x ∈ s ∪ t }) q =
        0 := by
      apply rename_injective _ Subtype.val_injective
      simpa using h
    

Proof state:
case intro.intro.intro.intro
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁵ : CommRing R✝
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R✝ M
R : Type u
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
σ : Type v
s : Finset σ
p : MvPolynomial { x // x ∈ s } R
t : Finset σ
q : MvPolynomial { x // x ∈ t } R
h : (rename Subtype.val) p * (rename Subtype.val) q = 0
this : (rename (Subtype.map id (_ : s ⊆ s ∪ t))) p * (rename (Subtype.map id (_ : t ⊆ s ∪ t))) q = 0
⊢ (rename Subtype.val) p = 0 ∨ (rename Subtype.val) q = 0

Next tactic:
letI that := MvPolynomial.noZeroDivisors_of_finite R { x // x ∈ s ∪ t }
instance {R : Type u} [CommSemiring R] [NoZeroDivisors R] {σ : Type v} :
    NoZeroDivisors (MvPolynomial σ R) :=
  ⟨fun {p} {q} h => by
    classical
    obtain ⟨s, p, rfl⟩ := exists_finset_rename p
    obtain ⟨t, q, rfl⟩ := exists_finset_rename q
    have :
        rename (Subtype.map id (Finset.subset_union_left s t) :
          { x // x ∈ s } → { x // x ∈ s ∪ t }) p *
        rename (Subtype.map id (Finset.subset_union_right s t) :
          { x // x ∈ t } → { x // x ∈ s ∪ t }) q =
        0 := by
      apply rename_injective _ Subtype.val_injective
      simpa using h
    letI that := MvPolynomial.noZeroDivisors_of_finite R { x // x ∈ s ∪ t }
    

Proof state:
case intro.intro.intro.intro
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁵ : CommRing R✝
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R✝ M
R : Type u
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
σ : Type v
s : Finset σ
p : MvPolynomial { x // x ∈ s } R
t : Finset σ
q : MvPolynomial { x // x ∈ t } R
h : (rename Subtype.val) p * (rename Subtype.val) q = 0
this : (rename (Subtype.map id (_ : s ⊆ s ∪ t))) p * (rename (Subtype.map id (_ : t ⊆ s ∪ t))) q = 0
that : NoZeroDivisors (MvPolynomial { x // x ∈ s ∪ t } R) := noZeroDivisors_of_finite R { x // x ∈ s ∪ t }
⊢ (rename Subtype.val) p = 0 ∨ (rename Subtype.val) q = 0

Next tactic:
rw [mul_eq_zero] at this
instance {R : Type u} [CommSemiring R] [NoZeroDivisors R] {σ : Type v} :
    NoZeroDivisors (MvPolynomial σ R) :=
  ⟨fun {p} {q} h => by
    classical
    obtain ⟨s, p, rfl⟩ := exists_finset_rename p
    obtain ⟨t, q, rfl⟩ := exists_finset_rename q
    have :
        rename (Subtype.map id (Finset.subset_union_left s t) :
          { x // x ∈ s } → { x // x ∈ s ∪ t }) p *
        rename (Subtype.map id (Finset.subset_union_right s t) :
          { x // x ∈ t } → { x // x ∈ s ∪ t }) q =
        0 := by
      apply rename_injective _ Subtype.val_injective
      simpa using h
    letI that := MvPolynomial.noZeroDivisors_of_finite R { x // x ∈ s ∪ t }
    rw [mul_eq_zero] at this
    

Proof state:
case intro.intro.intro.intro
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁵ : CommRing R✝
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R✝ M
R : Type u
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
σ : Type v
s : Finset σ
p : MvPolynomial { x // x ∈ s } R
t : Finset σ
q : MvPolynomial { x // x ∈ t } R
h : (rename Subtype.val) p * (rename Subtype.val) q = 0
this : (rename (Subtype.map id (_ : s ⊆ s ∪ t))) p = 0 ∨ (rename (Subtype.map id (_ : t ⊆ s ∪ t))) q = 0
that : NoZeroDivisors (MvPolynomial { x // x ∈ s ∪ t } R) := noZeroDivisors_of_finite R { x // x ∈ s ∪ t }
⊢ (rename Subtype.val) p = 0 ∨ (rename Subtype.val) q = 0

Next tactic:
apply this.imp
instance {R : Type u} [CommSemiring R] [NoZeroDivisors R] {σ : Type v} :
    NoZeroDivisors (MvPolynomial σ R) :=
  ⟨fun {p} {q} h => by
    classical
    obtain ⟨s, p, rfl⟩ := exists_finset_rename p
    obtain ⟨t, q, rfl⟩ := exists_finset_rename q
    have :
        rename (Subtype.map id (Finset.subset_union_left s t) :
          { x // x ∈ s } → { x // x ∈ s ∪ t }) p *
        rename (Subtype.map id (Finset.subset_union_right s t) :
          { x // x ∈ t } → { x // x ∈ s ∪ t }) q =
        0 := by
      apply rename_injective _ Subtype.val_injective
      simpa using h
    letI that := MvPolynomial.noZeroDivisors_of_finite R { x // x ∈ s ∪ t }
    rw [mul_eq_zero] at this
    apply this.imp <;> 

Proof state:
case intro.intro.intro.intro.f
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁵ : CommRing R✝
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R✝ M
R : Type u
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
σ : Type v
s : Finset σ
p : MvPolynomial { x // x ∈ s } R
t : Finset σ
q : MvPolynomial { x // x ∈ t } R
h : (rename Subtype.val) p * (rename Subtype.val) q = 0
this : (rename (Subtype.map id (_ : s ⊆ s ∪ t))) p = 0 ∨ (rename (Subtype.map id (_ : t ⊆ s ∪ t))) q = 0
that : NoZeroDivisors (MvPolynomial { x // x ∈ s ∪ t } R) := noZeroDivisors_of_finite R { x // x ∈ s ∪ t }
⊢ (rename (Subtype.map id (_ : s ⊆ s ∪ t))) p = 0 → (rename Subtype.val) p = 0

Next tactic:
intro that
instance {R : Type u} [CommSemiring R] [NoZeroDivisors R] {σ : Type v} :
    NoZeroDivisors (MvPolynomial σ R) :=
  ⟨fun {p} {q} h => by
    classical
    obtain ⟨s, p, rfl⟩ := exists_finset_rename p
    obtain ⟨t, q, rfl⟩ := exists_finset_rename q
    have :
        rename (Subtype.map id (Finset.subset_union_left s t) :
          { x // x ∈ s } → { x // x ∈ s ∪ t }) p *
        rename (Subtype.map id (Finset.subset_union_right s t) :
          { x // x ∈ t } → { x // x ∈ s ∪ t }) q =
        0 := by
      apply rename_injective _ Subtype.val_injective
      simpa using h
    letI that := MvPolynomial.noZeroDivisors_of_finite R { x // x ∈ s ∪ t }
    rw [mul_eq_zero] at this
    apply this.imp <;> 

Proof state:
case intro.intro.intro.intro.g
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁵ : CommRing R✝
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R✝ M
R : Type u
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
σ : Type v
s : Finset σ
p : MvPolynomial { x // x ∈ s } R
t : Finset σ
q : MvPolynomial { x // x ∈ t } R
h : (rename Subtype.val) p * (rename Subtype.val) q = 0
this : (rename (Subtype.map id (_ : s ⊆ s ∪ t))) p = 0 ∨ (rename (Subtype.map id (_ : t ⊆ s ∪ t))) q = 0
that : NoZeroDivisors (MvPolynomial { x // x ∈ s ∪ t } R) := noZeroDivisors_of_finite R { x // x ∈ s ∪ t }
⊢ (rename (Subtype.map id (_ : t ⊆ s ∪ t))) q = 0 → (rename Subtype.val) q = 0

Next tactic:
intro that
instance {R : Type u} [CommSemiring R] [NoZeroDivisors R] {σ : Type v} :
    NoZeroDivisors (MvPolynomial σ R) :=
  ⟨fun {p} {q} h => by
    classical
    obtain ⟨s, p, rfl⟩ := exists_finset_rename p
    obtain ⟨t, q, rfl⟩ := exists_finset_rename q
    have :
        rename (Subtype.map id (Finset.subset_union_left s t) :
          { x // x ∈ s } → { x // x ∈ s ∪ t }) p *
        rename (Subtype.map id (Finset.subset_union_right s t) :
          { x // x ∈ t } → { x // x ∈ s ∪ t }) q =
        0 := by
      apply rename_injective _ Subtype.val_injective
      simpa using h
    letI that := MvPolynomial.noZeroDivisors_of_finite R { x // x ∈ s ∪ t }
    rw [mul_eq_zero] at this
    apply this.imp <;> intro that <;> 

Proof state:
case intro.intro.intro.intro.f
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁵ : CommRing R✝
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R✝ M
R : Type u
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
σ : Type v
s : Finset σ
p : MvPolynomial { x // x ∈ s } R
t : Finset σ
q : MvPolynomial { x // x ∈ t } R
h : (rename Subtype.val) p * (rename Subtype.val) q = 0
this : (rename (Subtype.map id (_ : s ⊆ s ∪ t))) p = 0 ∨ (rename (Subtype.map id (_ : t ⊆ s ∪ t))) q = 0
that✝ : NoZeroDivisors (MvPolynomial { x // x ∈ s ∪ t } R) := noZeroDivisors_of_finite R { x // x ∈ s ∪ t }
that : (rename (Subtype.map id (_ : s ⊆ s ∪ t))) p = 0
⊢ (rename Subtype.val) p = 0

Next tactic:
simpa using congr_arg (rename Subtype.val) that
instance {R : Type u} [CommSemiring R] [NoZeroDivisors R] {σ : Type v} :
    NoZeroDivisors (MvPolynomial σ R) :=
  ⟨fun {p} {q} h => by
    classical
    obtain ⟨s, p, rfl⟩ := exists_finset_rename p
    obtain ⟨t, q, rfl⟩ := exists_finset_rename q
    have :
        rename (Subtype.map id (Finset.subset_union_left s t) :
          { x // x ∈ s } → { x // x ∈ s ∪ t }) p *
        rename (Subtype.map id (Finset.subset_union_right s t) :
          { x // x ∈ t } → { x // x ∈ s ∪ t }) q =
        0 := by
      apply rename_injective _ Subtype.val_injective
      simpa using h
    letI that := MvPolynomial.noZeroDivisors_of_finite R { x // x ∈ s ∪ t }
    rw [mul_eq_zero] at this
    apply this.imp <;> intro that <;> 

Proof state:
case intro.intro.intro.intro.g
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁵ : CommRing R✝
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R✝ M
R : Type u
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
σ : Type v
s : Finset σ
p : MvPolynomial { x // x ∈ s } R
t : Finset σ
q : MvPolynomial { x // x ∈ t } R
h : (rename Subtype.val) p * (rename Subtype.val) q = 0
this : (rename (Subtype.map id (_ : s ⊆ s ∪ t))) p = 0 ∨ (rename (Subtype.map id (_ : t ⊆ s ∪ t))) q = 0
that✝ : NoZeroDivisors (MvPolynomial { x // x ∈ s ∪ t } R) := noZeroDivisors_of_finite R { x // x ∈ s ∪ t }
that : (rename (Subtype.map id (_ : t ⊆ s ∪ t))) q = 0
⊢ (rename Subtype.val) q = 0

Next tactic:
simpa using congr_arg (rename Subtype.val) that
/-- The multivariate polynomial ring over an integral domain is an integral domain. -/
instance isDomain {R : Type u} {σ : Type v} [CommRing R] [IsDomain R] :
    IsDomain (MvPolynomial σ R) := by
  

Proof state:
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁵ : CommRing R✝
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R✝ M
R : Type u
σ : Type v
inst✝¹ : CommRing R
inst✝ : IsDomain R
⊢ IsDomain (MvPolynomial σ R)

Next tactic:
apply @NoZeroDivisors.to_isDomain (MvPolynomial σ R) _ ?_ _
/-- The multivariate polynomial ring over an integral domain is an integral domain. -/
instance isDomain {R : Type u} {σ : Type v} [CommRing R] [IsDomain R] :
    IsDomain (MvPolynomial σ R) := by
  apply @NoZeroDivisors.to_isDomain (MvPolynomial σ R) _ ?_ _
  

Proof state:
R✝ : Type u
S : Type u_1
σ✝ : Type v
M : Type w
inst✝⁵ : CommRing R✝
inst✝⁴ : CommRing S
inst✝³ : AddCommGroup M
inst✝² : Module R✝ M
R : Type u
σ : Type v
inst✝¹ : CommRing R
inst✝ : IsDomain R
⊢ Nontrivial (MvPolynomial σ R)

Next tactic:
apply AddMonoidAlgebra.nontrivial
theorem map_mvPolynomial_eq_eval₂ {S : Type*} [CommRing S] [Finite σ] (ϕ : MvPolynomial σ R →+* S)
    (p : MvPolynomial σ R) :
    ϕ p = MvPolynomial.eval₂ (ϕ.comp MvPolynomial.C) (fun s => ϕ (MvPolynomial.X s)) p := by
  

Proof state:
R : Type u
S✝ : Type u_1
σ : Type v
M : Type w
inst✝⁵ : CommRing R
inst✝⁴ : CommRing S✝
inst✝³ : AddCommGroup M
inst✝² : Module R M
S : Type u_2
inst✝¹ : CommRing S
inst✝ : Finite σ
ϕ : MvPolynomial σ R →+* S
p : MvPolynomial σ R
⊢ ϕ p = eval₂ (RingHom.comp ϕ C) (fun s => ϕ (X s)) p

Next tactic:
cases nonempty_fintype σ
theorem map_mvPolynomial_eq_eval₂ {S : Type*} [CommRing S] [Finite σ] (ϕ : MvPolynomial σ R →+* S)
    (p : MvPolynomial σ R) :
    ϕ p = MvPolynomial.eval₂ (ϕ.comp MvPolynomial.C) (fun s => ϕ (MvPolynomial.X s)) p := by
  cases nonempty_fintype σ
  

Proof state:
case intro
R : Type u
S✝ : Type u_1
σ : Type v
M : Type w
inst✝⁵ : CommRing R
inst✝⁴ : CommRing S✝
inst✝³ : AddCommGroup M
inst✝² : Module R M
S : Type u_2
inst✝¹ : CommRing S
inst✝ : Finite σ
ϕ : MvPolynomial σ R →+* S
p : MvPolynomial σ R
val✝ : Fintype σ
⊢ ϕ p = eval₂ (RingHom.comp ϕ C) (fun s => ϕ (X s)) p

Next tactic:
refine' Trans.trans (congr_arg ϕ (MvPolynomial.as_sum p)) _