l3lab/ntp-mathlib huggingface dataset:
@[reassoc (attr := simp)]
theorem whiskerRight_toPlus_comp_plusCompIso_hom :
    whiskerRight (J.toPlus _) _ ≫ (J.plusCompIso F P).hom = J.toPlus _ := by
  ext
  dsimp [toPlus]
  simp only [ι_plusCompIso_hom, Functor.map_comp, Category.assoc]
  simp only [← Category.assoc]
  congr 1
  -- porting note: this used to work with `ext`
  -- See https://github.com/leanprover-community/mathlib4/issues/5229
  apply Multiequalizer.hom_ext
  delta Cover.toMultiequalizer
  

Proof state:
case w.h.e_a.h
C : Type u
inst✝⁸ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w₁
inst✝⁷ : Category.{max v u, w₁} D
E : Type w₂
inst✝⁶ : Category.{max v u, w₂} E
F : D ⥤ E
inst✝⁵ : ∀ (α β : Type (max v u)) (fst snd : β → α), HasLimitsOfShape (WalkingMulticospan fst snd) D
inst✝⁴ : ∀ (α β : Type (max v u)) (fst snd : β → α), HasLimitsOfShape (WalkingMulticospan fst snd) E
inst✝³ : (X : C) → (W : Cover J X) → (P : Cᵒᵖ ⥤ D) → PreservesLimit (MulticospanIndex.multicospan (Cover.index W P)) F
P : Cᵒᵖ ⥤ D
inst✝² : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ D
inst✝¹ : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ E
inst✝ : (X : C) → PreservesColimitsOfShape (Cover J X)ᵒᵖ F
x✝ : Cᵒᵖ
⊢ ∀ (a : (Cover.index (op ⊤).unop (P ⋙ F)).L),
    (F.map
            (Multiequalizer.lift (Cover.index ⊤ P) (P.obj (op x✝.unop)) (fun I => P.map I.f.op)
              (_ :
                ∀ (I : (Cover.index ⊤ P).R),
                  (fun I => P.map I.f.op) (MulticospanIndex.fstTo (Cover.index ⊤ P) I) ≫
                      MulticospanIndex.fst (Cover.index ⊤ P) I =
                    (fun I => P.map I.f.op) (MulticospanIndex.sndTo (Cover.index ⊤ P) I) ≫
                      MulticospanIndex.snd (Cover.index ⊤ P) I)) ≫
          (diagramCompIso J F P x✝.unop).hom.app (op ⊤)) ≫
        Multiequalizer.ι (Cover.index (op ⊤).unop (P ⋙ F)) a =
      Multiequalizer.lift (Cover.index ⊤ (P ⋙ F)) ((P ⋙ F).obj (op x✝.unop)) (fun I => (P ⋙ F).map I.f.op)
          (_ :
            ∀ (I : (Cover.index ⊤ (P ⋙ F)).R),
              (fun I => (P ⋙ F).map I.f.op) (MulticospanIndex.fstTo (Cover.index ⊤ (P ⋙ F)) I) ≫
                  MulticospanIndex.fst (Cover.index ⊤ (P ⋙ F)) I =
                (fun I => (P ⋙ F).map I.f.op) (MulticospanIndex.sndTo (Cover.index ⊤ (P ⋙ F)) I) ≫
                  MulticospanIndex.snd (Cover.index ⊤ (P ⋙ F)) I) ≫
        Multiequalizer.ι (Cover.index (op ⊤).unop (P ⋙ F)) a

Next tactic:
simp only [diagramCompIso_hom_ι, Category.assoc, ← F.map_comp]
@[reassoc (attr := simp)]
theorem whiskerRight_toPlus_comp_plusCompIso_hom :
    whiskerRight (J.toPlus _) _ ≫ (J.plusCompIso F P).hom = J.toPlus _ := by
  ext
  dsimp [toPlus]
  simp only [ι_plusCompIso_hom, Functor.map_comp, Category.assoc]
  simp only [← Category.assoc]
  congr 1
  -- porting note: this used to work with `ext`
  -- See https://github.com/leanprover-community/mathlib4/issues/5229
  apply Multiequalizer.hom_ext
  delta Cover.toMultiequalizer
  simp only [diagramCompIso_hom_ι, Category.assoc, ← F.map_comp]
  

Proof state:
case w.h.e_a.h
C : Type u
inst✝⁸ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w₁
inst✝⁷ : Category.{max v u, w₁} D
E : Type w₂
inst✝⁶ : Category.{max v u, w₂} E
F : D ⥤ E
inst✝⁵ : ∀ (α β : Type (max v u)) (fst snd : β → α), HasLimitsOfShape (WalkingMulticospan fst snd) D
inst✝⁴ : ∀ (α β : Type (max v u)) (fst snd : β → α), HasLimitsOfShape (WalkingMulticospan fst snd) E
inst✝³ : (X : C) → (W : Cover J X) → (P : Cᵒᵖ ⥤ D) → PreservesLimit (MulticospanIndex.multicospan (Cover.index W P)) F
P : Cᵒᵖ ⥤ D
inst✝² : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ D
inst✝¹ : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ E
inst✝ : (X : C) → PreservesColimitsOfShape (Cover J X)ᵒᵖ F
x✝ : Cᵒᵖ
⊢ ∀ (a : (Cover.index (op ⊤).unop (P ⋙ F)).L),
    F.map
        (Multiequalizer.lift (Cover.index ⊤ P) (P.obj (op x✝.unop)) (fun I => P.map I.f.op)
            (_ :
              ∀ (I : (Cover.index ⊤ P).R),
                (fun I => P.map I.f.op) (MulticospanIndex.fstTo (Cover.index ⊤ P) I) ≫
                    MulticospanIndex.fst (Cover.index ⊤ P) I =
                  (fun I => P.map I.f.op) (MulticospanIndex.sndTo (Cover.index ⊤ P) I) ≫
                    MulticospanIndex.snd (Cover.index ⊤ P) I) ≫
          Multiequalizer.ι (Cover.index (op ⊤).unop P) a) =
      Multiequalizer.lift (Cover.index ⊤ (P ⋙ F)) ((P ⋙ F).obj (op x✝.unop)) (fun I => (P ⋙ F).map I.f.op)
          (_ :
            ∀ (I : (Cover.index ⊤ (P ⋙ F)).R),
              (fun I => (P ⋙ F).map I.f.op) (MulticospanIndex.fstTo (Cover.index ⊤ (P ⋙ F)) I) ≫
                  MulticospanIndex.fst (Cover.index ⊤ (P ⋙ F)) I =
                (fun I => (P ⋙ F).map I.f.op) (MulticospanIndex.sndTo (Cover.index ⊤ (P ⋙ F)) I) ≫
                  MulticospanIndex.snd (Cover.index ⊤ (P ⋙ F)) I) ≫
        Multiequalizer.ι (Cover.index (op ⊤).unop (P ⋙ F)) a

Next tactic:
simp only [unop_op, limit.lift_π, Multifork.ofι_π_app, Functor.comp_obj, Functor.comp_map,
    implies_true]
@[simp]
theorem toPlus_comp_plusCompIso_inv :
    J.toPlus _ ≫ (J.plusCompIso F P).inv = whiskerRight (J.toPlus _) _ := by 

Proof state:
C : Type u
inst✝⁸ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w₁
inst✝⁷ : Category.{max v u, w₁} D
E : Type w₂
inst✝⁶ : Category.{max v u, w₂} E
F : D ⥤ E
inst✝⁵ : ∀ (α β : Type (max v u)) (fst snd : β → α), HasLimitsOfShape (WalkingMulticospan fst snd) D
inst✝⁴ : ∀ (α β : Type (max v u)) (fst snd : β → α), HasLimitsOfShape (WalkingMulticospan fst snd) E
inst✝³ : (X : C) → (W : Cover J X) → (P : Cᵒᵖ ⥤ D) → PreservesLimit (MulticospanIndex.multicospan (Cover.index W P)) F
P : Cᵒᵖ ⥤ D
inst✝² : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ D
inst✝¹ : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ E
inst✝ : (X : C) → PreservesColimitsOfShape (Cover J X)ᵒᵖ F
⊢ toPlus J (P ⋙ F) ≫ (plusCompIso J F P).inv = whiskerRight (toPlus J P) F

Next tactic:
simp [Iso.comp_inv_eq]
theorem plusCompIso_inv_eq_plusLift (hP : Presheaf.IsSheaf J (J.plusObj P ⋙ F)) :
    (J.plusCompIso F P).inv = J.plusLift (whiskerRight (J.toPlus _) _) hP := by
  

Proof state:
C : Type u
inst✝⁸ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w₁
inst✝⁷ : Category.{max v u, w₁} D
E : Type w₂
inst✝⁶ : Category.{max v u, w₂} E
F : D ⥤ E
inst✝⁵ : ∀ (α β : Type (max v u)) (fst snd : β → α), HasLimitsOfShape (WalkingMulticospan fst snd) D
inst✝⁴ : ∀ (α β : Type (max v u)) (fst snd : β → α), HasLimitsOfShape (WalkingMulticospan fst snd) E
inst✝³ : (X : C) → (W : Cover J X) → (P : Cᵒᵖ ⥤ D) → PreservesLimit (MulticospanIndex.multicospan (Cover.index W P)) F
P : Cᵒᵖ ⥤ D
inst✝² : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ D
inst✝¹ : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ E
inst✝ : (X : C) → PreservesColimitsOfShape (Cover J X)ᵒᵖ F
hP : Presheaf.IsSheaf J (plusObj J P ⋙ F)
⊢ (plusCompIso J F P).inv = plusLift J (whiskerRight (toPlus J P) F) hP

Next tactic:
apply J.plusLift_unique
theorem plusCompIso_inv_eq_plusLift (hP : Presheaf.IsSheaf J (J.plusObj P ⋙ F)) :
    (J.plusCompIso F P).inv = J.plusLift (whiskerRight (J.toPlus _) _) hP := by
  apply J.plusLift_unique
  

Proof state:
case hγ
C : Type u
inst✝⁸ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w₁
inst✝⁷ : Category.{max v u, w₁} D
E : Type w₂
inst✝⁶ : Category.{max v u, w₂} E
F : D ⥤ E
inst✝⁵ : ∀ (α β : Type (max v u)) (fst snd : β → α), HasLimitsOfShape (WalkingMulticospan fst snd) D
inst✝⁴ : ∀ (α β : Type (max v u)) (fst snd : β → α), HasLimitsOfShape (WalkingMulticospan fst snd) E
inst✝³ : (X : C) → (W : Cover J X) → (P : Cᵒᵖ ⥤ D) → PreservesLimit (MulticospanIndex.multicospan (Cover.index W P)) F
P : Cᵒᵖ ⥤ D
inst✝² : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ D
inst✝¹ : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ E
inst✝ : (X : C) → PreservesColimitsOfShape (Cover J X)ᵒᵖ F
hP : Presheaf.IsSheaf J (plusObj J P ⋙ F)
⊢ toPlus J (P ⋙ F) ≫ (plusCompIso J F P).inv = whiskerRight (toPlus J P) F

Next tactic:
simp [Iso.comp_inv_eq]
/-- Every pseudo-metrizable space is first countable. -/
instance (priority := 100) PseudoMetrizableSpace.firstCountableTopology
    [h : PseudoMetrizableSpace X] : FirstCountableTopology X := by
  

Proof state:
ι : Type u_1
X : Type u_2
Y : Type u_3
π : ι → Type u_4
inst✝³ : TopologicalSpace X
inst✝² : TopologicalSpace Y
inst✝¹ : Finite ι
inst✝ : (i : ι) → TopologicalSpace (π i)
h : PseudoMetrizableSpace X
⊢ FirstCountableTopology X

Next tactic:
rcases h with ⟨_, hm⟩
/-- Every pseudo-metrizable space is first countable. -/
instance (priority := 100) PseudoMetrizableSpace.firstCountableTopology
    [h : PseudoMetrizableSpace X] : FirstCountableTopology X := by
  rcases h with ⟨_, hm⟩
  

Proof state:
case mk.intro
ι : Type u_1
X : Type u_2
Y : Type u_3
π : ι → Type u_4
inst✝³ : TopologicalSpace X
inst✝² : TopologicalSpace Y
inst✝¹ : Finite ι
inst✝ : (i : ι) → TopologicalSpace (π i)
w✝ : PseudoMetricSpace X
hm : UniformSpace.toTopologicalSpace = inst✝³
⊢ FirstCountableTopology X

Next tactic:
rw [← hm]
/-- Every pseudo-metrizable space is first countable. -/
instance (priority := 100) PseudoMetrizableSpace.firstCountableTopology
    [h : PseudoMetrizableSpace X] : FirstCountableTopology X := by
  rcases h with ⟨_, hm⟩
  rw [← hm]
  

Proof state:
case mk.intro
ι : Type u_1
X : Type u_2
Y : Type u_3
π : ι → Type u_4
inst✝³ : TopologicalSpace X
inst✝² : TopologicalSpace Y
inst✝¹ : Finite ι
inst✝ : (i : ι) → TopologicalSpace (π i)
w✝ : PseudoMetricSpace X
hm : UniformSpace.toTopologicalSpace = inst✝³
⊢ FirstCountableTopology X

Next tactic:
exact @UniformSpace.firstCountableTopology X PseudoMetricSpace.toUniformSpace
    EMetric.instIsCountablyGeneratedUniformity
instance pseudoMetrizableSpace_pi [∀ i, PseudoMetrizableSpace (π i)] :
    PseudoMetrizableSpace (∀ i, π i) := by
  

Proof state:
ι : Type u_1
X : Type u_2
Y : Type u_3
π : ι → Type u_4
inst✝⁴ : TopologicalSpace X
inst✝³ : TopologicalSpace Y
inst✝² : Finite ι
inst✝¹ : (i : ι) → TopologicalSpace (π i)
inst✝ : ∀ (i : ι), PseudoMetrizableSpace (π i)
⊢ PseudoMetrizableSpace ((i : ι) → π i)

Next tactic:
cases nonempty_fintype ι
instance pseudoMetrizableSpace_pi [∀ i, PseudoMetrizableSpace (π i)] :
    PseudoMetrizableSpace (∀ i, π i) := by
  cases nonempty_fintype ι
  

Proof state:
case intro
ι : Type u_1
X : Type u_2
Y : Type u_3
π : ι → Type u_4
inst✝⁴ : TopologicalSpace X
inst✝³ : TopologicalSpace Y
inst✝² : Finite ι
inst✝¹ : (i : ι) → TopologicalSpace (π i)
inst✝ : ∀ (i : ι), PseudoMetrizableSpace (π i)
val✝ : Fintype ι
⊢ PseudoMetrizableSpace ((i : ι) → π i)

Next tactic:
letI := fun i => pseudoMetrizableSpacePseudoMetric (π i)
instance pseudoMetrizableSpace_pi [∀ i, PseudoMetrizableSpace (π i)] :
    PseudoMetrizableSpace (∀ i, π i) := by
  cases nonempty_fintype ι
  letI := fun i => pseudoMetrizableSpacePseudoMetric (π i)
  

Proof state:
case intro
ι : Type u_1
X : Type u_2
Y : Type u_3
π : ι → Type u_4
inst✝⁴ : TopologicalSpace X
inst✝³ : TopologicalSpace Y
inst✝² : Finite ι
inst✝¹ : (i : ι) → TopologicalSpace (π i)
inst✝ : ∀ (i : ι), PseudoMetrizableSpace (π i)
val✝ : Fintype ι
this : (i : ι) → PseudoMetricSpace (π i) := fun i => pseudoMetrizableSpacePseudoMetric (π i)
⊢ PseudoMetrizableSpace ((i : ι) → π i)

Next tactic:
infer_instance
instance metrizableSpace_pi [∀ i, MetrizableSpace (π i)] : MetrizableSpace (∀ i, π i) := by
  

Proof state:
ι : Type u_1
X : Type u_2
Y : Type u_3
π : ι → Type u_4
inst✝⁴ : TopologicalSpace X
inst✝³ : TopologicalSpace Y
inst✝² : Finite ι
inst✝¹ : (i : ι) → TopologicalSpace (π i)
inst✝ : ∀ (i : ι), MetrizableSpace (π i)
⊢ MetrizableSpace ((i : ι) → π i)

Next tactic:
cases nonempty_fintype ι
instance metrizableSpace_pi [∀ i, MetrizableSpace (π i)] : MetrizableSpace (∀ i, π i) := by
  cases nonempty_fintype ι
  

Proof state:
case intro
ι : Type u_1
X : Type u_2
Y : Type u_3
π : ι → Type u_4
inst✝⁴ : TopologicalSpace X
inst✝³ : TopologicalSpace Y
inst✝² : Finite ι
inst✝¹ : (i : ι) → TopologicalSpace (π i)
inst✝ : ∀ (i : ι), MetrizableSpace (π i)
val✝ : Fintype ι
⊢ MetrizableSpace ((i : ι) → π i)

Next tactic:
letI := fun i => metrizableSpaceMetric (π i)
instance metrizableSpace_pi [∀ i, MetrizableSpace (π i)] : MetrizableSpace (∀ i, π i) := by
  cases nonempty_fintype ι
  letI := fun i => metrizableSpaceMetric (π i)
  

Proof state:
case intro
ι : Type u_1
X : Type u_2
Y : Type u_3
π : ι → Type u_4
inst✝⁴ : TopologicalSpace X
inst✝³ : TopologicalSpace Y
inst✝² : Finite ι
inst✝¹ : (i : ι) → TopologicalSpace (π i)
inst✝ : ∀ (i : ι), MetrizableSpace (π i)
val✝ : Fintype ι
this : (i : ι) → MetricSpace (π i) := fun i => metrizableSpaceMetric (π i)
⊢ MetrizableSpace ((i : ι) → π i)

Next tactic:
infer_instance
theorem IsSeparable.secondCountableTopology [PseudoMetrizableSpace X] {s : Set X}
    (hs : IsSeparable s) : SecondCountableTopology s := by
  

Proof state:
ι : Type u_1
X : Type u_2
Y : Type u_3
π : ι → Type u_4
inst✝⁴ : TopologicalSpace X
inst✝³ : TopologicalSpace Y
inst✝² : Finite ι
inst✝¹ : (i : ι) → TopologicalSpace (π i)
inst✝ : PseudoMetrizableSpace X
s : Set X
hs : IsSeparable s
⊢ SecondCountableTopology ↑s

Next tactic:
letI := pseudoMetrizableSpacePseudoMetric X
theorem IsSeparable.secondCountableTopology [PseudoMetrizableSpace X] {s : Set X}
    (hs : IsSeparable s) : SecondCountableTopology s := by
  letI := pseudoMetrizableSpacePseudoMetric X
  

Proof state:
ι : Type u_1
X : Type u_2
Y : Type u_3
π : ι → Type u_4
inst✝⁴ : TopologicalSpace X
inst✝³ : TopologicalSpace Y
inst✝² : Finite ι
inst✝¹ : (i : ι) → TopologicalSpace (π i)
inst✝ : PseudoMetrizableSpace X
s : Set X
hs : IsSeparable s
this : PseudoMetricSpace X := pseudoMetrizableSpacePseudoMetric X
⊢ SecondCountableTopology ↑s

Next tactic:
have := hs.separableSpace
theorem IsSeparable.secondCountableTopology [PseudoMetrizableSpace X] {s : Set X}
    (hs : IsSeparable s) : SecondCountableTopology s := by
  letI := pseudoMetrizableSpacePseudoMetric X
  have := hs.separableSpace
  

Proof state:
ι : Type u_1
X : Type u_2
Y : Type u_3
π : ι → Type u_4
inst✝⁴ : TopologicalSpace X
inst✝³ : TopologicalSpace Y
inst✝² : Finite ι
inst✝¹ : (i : ι) → TopologicalSpace (π i)
inst✝ : PseudoMetrizableSpace X
s : Set X
hs : IsSeparable s
this✝ : PseudoMetricSpace X := pseudoMetrizableSpacePseudoMetric X
this : SeparableSpace ↑s
⊢ SecondCountableTopology ↑s

Next tactic:
exact UniformSpace.secondCountable_of_separable s
/-- Left `Mul` by a `k : α` over `[Ring α]` is injective, if `k` is not a zero divisor.
The typeclass that restricts all terms of `α` to have this property is `NoZeroDivisors`. -/
theorem isLeftRegular_of_non_zero_divisor [NonUnitalNonAssocRing α] (k : α)
    (h : ∀ x : α, k * x = 0 → x = 0) : IsLeftRegular k := by
  

Proof state:
α : Type u_1
inst✝ : NonUnitalNonAssocRing α
k : α
h : ∀ (x : α), k * x = 0 → x = 0
⊢ IsLeftRegular k

Next tactic:
refine' fun x y (h' : k * x = k * y) => sub_eq_zero.mp (h _ _)
/-- Left `Mul` by a `k : α` over `[Ring α]` is injective, if `k` is not a zero divisor.
The typeclass that restricts all terms of `α` to have this property is `NoZeroDivisors`. -/
theorem isLeftRegular_of_non_zero_divisor [NonUnitalNonAssocRing α] (k : α)
    (h : ∀ x : α, k * x = 0 → x = 0) : IsLeftRegular k := by
  refine' fun x y (h' : k * x = k * y) => sub_eq_zero.mp (h _ _)
  

Proof state:
α : Type u_1
inst✝ : NonUnitalNonAssocRing α
k : α
h : ∀ (x : α), k * x = 0 → x = 0
x y : α
h' : k * x = k * y
⊢ k * (x - y) = 0

Next tactic:
rw [mul_sub, sub_eq_zero, h']
/-- Right `Mul` by a `k : α` over `[Ring α]` is injective, if `k` is not a zero divisor.
The typeclass that restricts all terms of `α` to have this property is `NoZeroDivisors`. -/
theorem isRightRegular_of_non_zero_divisor [NonUnitalNonAssocRing α] (k : α)
    (h : ∀ x : α, x * k = 0 → x = 0) : IsRightRegular k := by
  

Proof state:
α : Type u_1
inst✝ : NonUnitalNonAssocRing α
k : α
h : ∀ (x : α), x * k = 0 → x = 0
⊢ IsRightRegular k

Next tactic:
refine' fun x y (h' : x * k = y * k) => sub_eq_zero.mp (h _ _)
/-- Right `Mul` by a `k : α` over `[Ring α]` is injective, if `k` is not a zero divisor.
The typeclass that restricts all terms of `α` to have this property is `NoZeroDivisors`. -/
theorem isRightRegular_of_non_zero_divisor [NonUnitalNonAssocRing α] (k : α)
    (h : ∀ x : α, x * k = 0 → x = 0) : IsRightRegular k := by
  refine' fun x y (h' : x * k = y * k) => sub_eq_zero.mp (h _ _)
  

Proof state:
α : Type u_1
inst✝ : NonUnitalNonAssocRing α
k : α
h : ∀ (x : α), x * k = 0 → x = 0
x y : α
h' : x * k = y * k
⊢ (x - y) * k = 0

Next tactic:
rw [sub_mul, sub_eq_zero, h']
theorem isRegular_iff_ne_zero' [Nontrivial α] [NonUnitalNonAssocRing α] [NoZeroDivisors α]
    {k : α} : IsRegular k ↔ k ≠ 0 :=
  ⟨fun h => by
    

Proof state:
α : Type u_1
inst✝² : Nontrivial α
inst✝¹ : NonUnitalNonAssocRing α
inst✝ : NoZeroDivisors α
k : α
h : IsRegular k
⊢ k ≠ 0

Next tactic:
rintro rfl
theorem isRegular_iff_ne_zero' [Nontrivial α] [NonUnitalNonAssocRing α] [NoZeroDivisors α]
    {k : α} : IsRegular k ↔ k ≠ 0 :=
  ⟨fun h => by
    rintro rfl
    

Proof state:
α : Type u_1
inst✝² : Nontrivial α
inst✝¹ : NonUnitalNonAssocRing α
inst✝ : NoZeroDivisors α
h : IsRegular 0
⊢ False

Next tactic:
exact not_not.mpr h.left not_isLeftRegular_zero
/-- A ring with no zero divisors is a `CancelMonoidWithZero`.

Note this is not an instance as it forms a typeclass loop. -/
@[reducible]
def NoZeroDivisors.toCancelMonoidWithZero [Ring α] [NoZeroDivisors α] : CancelMonoidWithZero α :=
  { (by 

Proof state:
α : Type u_1
inst✝¹ : Ring α
inst✝ : NoZeroDivisors α
⊢ MonoidWithZero α

Next tactic:
infer_instance
theorem isRoot_of_unity_of_root_cyclotomic {ζ : R} {i : ℕ} (hi : i ∈ n.divisors)
    (h : (cyclotomic i R).IsRoot ζ) : ζ ^ n = 1 := by
  

Proof state:
R : Type u_1
inst✝ : CommRing R
n : ℕ
ζ : R
i : ℕ
hi : i ∈ Nat.divisors n
h : IsRoot (cyclotomic i R) ζ
⊢ ζ ^ n = 1

Next tactic:
rcases n.eq_zero_or_pos with (rfl | hn)
theorem isRoot_of_unity_of_root_cyclotomic {ζ : R} {i : ℕ} (hi : i ∈ n.divisors)
    (h : (cyclotomic i R).IsRoot ζ) : ζ ^ n = 1 := by
  rcases n.eq_zero_or_pos with (rfl | hn)
  · 

Proof state:
case inl
R : Type u_1
inst✝ : CommRing R
ζ : R
i : ℕ
h : IsRoot (cyclotomic i R) ζ
hi : i ∈ Nat.divisors 0
⊢ ζ ^ 0 = 1

Next tactic:
exact pow_zero _
theorem isRoot_of_unity_of_root_cyclotomic {ζ : R} {i : ℕ} (hi : i ∈ n.divisors)
    (h : (cyclotomic i R).IsRoot ζ) : ζ ^ n = 1 := by
  rcases n.eq_zero_or_pos with (rfl | hn)
  · exact pow_zero _
  

Proof state:
case inr
R : Type u_1
inst✝ : CommRing R
n : ℕ
ζ : R
i : ℕ
hi : i ∈ Nat.divisors n
h : IsRoot (cyclotomic i R) ζ
hn : n > 0
⊢ ζ ^ n = 1

Next tactic:
have := congr_arg (eval ζ) (prod_cyclotomic_eq_X_pow_sub_one hn R).symm
theorem isRoot_of_unity_of_root_cyclotomic {ζ : R} {i : ℕ} (hi : i ∈ n.divisors)
    (h : (cyclotomic i R).IsRoot ζ) : ζ ^ n = 1 := by
  rcases n.eq_zero_or_pos with (rfl | hn)
  · exact pow_zero _
  have := congr_arg (eval ζ) (prod_cyclotomic_eq_X_pow_sub_one hn R).symm
  

Proof state:
case inr
R : Type u_1
inst✝ : CommRing R
n : ℕ
ζ : R
i : ℕ
hi : i ∈ Nat.divisors n
h : IsRoot (cyclotomic i R) ζ
hn : n > 0
this : eval ζ (X ^ n - 1) = eval ζ (∏ i in Nat.divisors n, cyclotomic i R)
⊢ ζ ^ n = 1

Next tactic:
rw [eval_sub, eval_pow, eval_X, eval_one] at this
theorem isRoot_of_unity_of_root_cyclotomic {ζ : R} {i : ℕ} (hi : i ∈ n.divisors)
    (h : (cyclotomic i R).IsRoot ζ) : ζ ^ n = 1 := by
  rcases n.eq_zero_or_pos with (rfl | hn)
  · exact pow_zero _
  have := congr_arg (eval ζ) (prod_cyclotomic_eq_X_pow_sub_one hn R).symm
  rw [eval_sub, eval_pow, eval_X, eval_one] at this
  

Proof state:
case inr
R : Type u_1
inst✝ : CommRing R
n : ℕ
ζ : R
i : ℕ
hi : i ∈ Nat.divisors n
h : IsRoot (cyclotomic i R) ζ
hn : n > 0
this : ζ ^ n - 1 = eval ζ (∏ i in Nat.divisors n, cyclotomic i R)
⊢ ζ ^ n = 1

Next tactic:
convert eq_add_of_sub_eq' this
theorem isRoot_of_unity_of_root_cyclotomic {ζ : R} {i : ℕ} (hi : i ∈ n.divisors)
    (h : (cyclotomic i R).IsRoot ζ) : ζ ^ n = 1 := by
  rcases n.eq_zero_or_pos with (rfl | hn)
  · exact pow_zero _
  have := congr_arg (eval ζ) (prod_cyclotomic_eq_X_pow_sub_one hn R).symm
  rw [eval_sub, eval_pow, eval_X, eval_one] at this
  convert eq_add_of_sub_eq' this
  

Proof state:
case h.e'_3
R : Type u_1
inst✝ : CommRing R
n : ℕ
ζ : R
i : ℕ
hi : i ∈ Nat.divisors n
h : IsRoot (cyclotomic i R) ζ
hn : n > 0
this : ζ ^ n - 1 = eval ζ (∏ i in Nat.divisors n, cyclotomic i R)
⊢ 1 = 1 + eval ζ (∏ i in Nat.divisors n, cyclotomic i R)

Next tactic:
convert (add_zero (M := R) _).symm
theorem isRoot_of_unity_of_root_cyclotomic {ζ : R} {i : ℕ} (hi : i ∈ n.divisors)
    (h : (cyclotomic i R).IsRoot ζ) : ζ ^ n = 1 := by
  rcases n.eq_zero_or_pos with (rfl | hn)
  · exact pow_zero _
  have := congr_arg (eval ζ) (prod_cyclotomic_eq_X_pow_sub_one hn R).symm
  rw [eval_sub, eval_pow, eval_X, eval_one] at this
  convert eq_add_of_sub_eq' this
  convert (add_zero (M := R) _).symm
  

Proof state:
case h.e'_3.h.e'_6
R : Type u_1
inst✝ : CommRing R
n : ℕ
ζ : R
i : ℕ
hi : i ∈ Nat.divisors n
h : IsRoot (cyclotomic i R) ζ
hn : n > 0
this : ζ ^ n - 1 = eval ζ (∏ i in Nat.divisors n, cyclotomic i R)
⊢ eval ζ (∏ i in Nat.divisors n, cyclotomic i R) = 0

Next tactic:
apply eval_eq_zero_of_dvd_of_eval_eq_zero _ h
theorem isRoot_of_unity_of_root_cyclotomic {ζ : R} {i : ℕ} (hi : i ∈ n.divisors)
    (h : (cyclotomic i R).IsRoot ζ) : ζ ^ n = 1 := by
  rcases n.eq_zero_or_pos with (rfl | hn)
  · exact pow_zero _
  have := congr_arg (eval ζ) (prod_cyclotomic_eq_X_pow_sub_one hn R).symm
  rw [eval_sub, eval_pow, eval_X, eval_one] at this
  convert eq_add_of_sub_eq' this
  convert (add_zero (M := R) _).symm
  apply eval_eq_zero_of_dvd_of_eval_eq_zero _ h
  

Proof state:
R : Type u_1
inst✝ : CommRing R
n : ℕ
ζ : R
i : ℕ
hi : i ∈ Nat.divisors n
h : IsRoot (cyclotomic i R) ζ
hn : n > 0
this : ζ ^ n - 1 = eval ζ (∏ i in Nat.divisors n, cyclotomic i R)
⊢ cyclotomic i R ∣ ∏ i in Nat.divisors n, cyclotomic i R

Next tactic:
exact Finset.dvd_prod_of_mem _ hi
theorem _root_.isRoot_of_unity_iff (h : 0 < n) (R : Type*) [CommRing R] [IsDomain R] {ζ : R} :
    ζ ^ n = 1 ↔ ∃ i ∈ n.divisors, (cyclotomic i R).IsRoot ζ := by
  

Proof state:
R✝ : Type u_1
inst✝³ : CommRing R✝
n : ℕ
inst✝² : IsDomain R✝
h : 0 < n
R : Type u_2
inst✝¹ : CommRing R
inst✝ : IsDomain R
ζ : R
⊢ ζ ^ n = 1 ↔ ∃ i ∈ Nat.divisors n, IsRoot (cyclotomic i R) ζ

Next tactic:
rw [← mem_nthRoots h, nthRoots, mem_roots <| X_pow_sub_C_ne_zero h _, C_1, ←
      prod_cyclotomic_eq_X_pow_sub_one h, isRoot_prod]
/-- Any `n`-th primitive root of unity is a root of `cyclotomic n R`.-/
theorem _root_.IsPrimitiveRoot.isRoot_cyclotomic (hpos : 0 < n) {μ : R} (h : IsPrimitiveRoot μ n) :
    IsRoot (cyclotomic n R) μ := by
  

Proof state:
R : Type u_1
inst✝¹ : CommRing R
n : ℕ
inst✝ : IsDomain R
hpos : 0 < n
μ : R
h : IsPrimitiveRoot μ n
⊢ IsRoot (cyclotomic n R) μ

Next tactic:
rw [← mem_roots (cyclotomic_ne_zero n R), cyclotomic_eq_prod_X_sub_primitiveRoots h,
    roots_prod_X_sub_C, ← Finset.mem_def]
/-- Any `n`-th primitive root of unity is a root of `cyclotomic n R`.-/
theorem _root_.IsPrimitiveRoot.isRoot_cyclotomic (hpos : 0 < n) {μ : R} (h : IsPrimitiveRoot μ n) :
    IsRoot (cyclotomic n R) μ := by
  rw [← mem_roots (cyclotomic_ne_zero n R), cyclotomic_eq_prod_X_sub_primitiveRoots h,
    roots_prod_X_sub_C, ← Finset.mem_def]
  

Proof state:
R : Type u_1
inst✝¹ : CommRing R
n : ℕ
inst✝ : IsDomain R
hpos : 0 < n
μ : R
h : IsPrimitiveRoot μ n
⊢ μ ∈ primitiveRoots n R

Next tactic:
rwa [← mem_primitiveRoots hpos] at h
private theorem isRoot_cyclotomic_iff' {n : ℕ} {K : Type*} [Field K] {μ : K} [NeZero (n : K)] :
    IsRoot (cyclotomic n K) μ ↔ IsPrimitiveRoot μ n := by
  -- in this proof, `o` stands for `orderOf μ`
  

Proof state:
R : Type u_1
inst✝³ : CommRing R
n✝ : ℕ
inst✝² : IsDomain R
n : ℕ
K : Type u_2
inst✝¹ : Field K
μ : K
inst✝ : NeZero ↑n
⊢ IsRoot (cyclotomic n K) μ ↔ IsPrimitiveRoot μ n

Next tactic:
have hnpos : 0 < n := (NeZero.of_neZero_natCast K).out.bot_lt
private theorem isRoot_cyclotomic_iff' {n : ℕ} {K : Type*} [Field K] {μ : K} [NeZero (n : K)] :
    IsRoot (cyclotomic n K) μ ↔ IsPrimitiveRoot μ n := by
  -- in this proof, `o` stands for `orderOf μ`
  have hnpos : 0 < n := (NeZero.of_neZero_natCast K).out.bot_lt
  

Proof state:
R : Type u_1
inst✝³ : CommRing R
n✝ : ℕ
inst✝² : IsDomain R
n : ℕ
K : Type u_2
inst✝¹ : Field K
μ : K
inst✝ : NeZero ↑n
hnpos : 0 < n
⊢ IsRoot (cyclotomic n K) μ ↔ IsPrimitiveRoot μ n

Next tactic:
refine' ⟨fun hμ => _, IsPrimitiveRoot.isRoot_cyclotomic hnpos⟩