l3lab/ntp-mathlib huggingface dataset:
/-- The cokernel of `f.op` is the opposite of `kernel f`. -/
@[simps]
def cokernelOpUnop : (cokernel f.op).unop ≅ kernel f where
  hom :=
    kernel.lift f (cokernel.π f.op).unop <| by
      rw [← f.unop_op, ← unop_comp, f.unop_op]
      

Proof state:
C : Type u_1
inst✝¹ : Category.{?u.12173, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ (f.op ≫ cokernel.π f.op).unop = 0

Next tactic:
simp
/-- The cokernel of `f.op` is the opposite of `kernel f`. -/
@[simps]
def cokernelOpUnop : (cokernel f.op).unop ≅ kernel f where
  hom :=
    kernel.lift f (cokernel.π f.op).unop <| by
      rw [← f.unop_op, ← unop_comp, f.unop_op]
      simp
  inv := (cokernel.desc f.op (kernel.ι f).op <| by 

Proof state:
C : Type u_1
inst✝¹ : Category.{?u.12173, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ f.op ≫ (kernel.ι f).op = 0

Next tactic:
simp [← op_comp]
/-- The cokernel of `f.op` is the opposite of `kernel f`. -/
@[simps]
def cokernelOpUnop : (cokernel f.op).unop ≅ kernel f where
  hom :=
    kernel.lift f (cokernel.π f.op).unop <| by
      rw [← f.unop_op, ← unop_comp, f.unop_op]
      simp
  inv := (cokernel.desc f.op (kernel.ι f).op <| by simp [← op_comp]).unop
  hom_inv_id := by
    

Proof state:
C : Type u_1
inst✝¹ : Category.{?u.12173, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ kernel.lift f (cokernel.π f.op).unop (_ : (cokernel.π f.op).unop ≫ f = 0) ≫
      (cokernel.desc f.op (kernel.ι f).op (_ : (kernel.ι f ≫ f).op = 0)).unop =
    𝟙 (cokernel f.op).unop

Next tactic:
rw [← unop_id, ← (kernel.lift f _ _).unop_op, ← unop_comp]
/-- The cokernel of `f.op` is the opposite of `kernel f`. -/
@[simps]
def cokernelOpUnop : (cokernel f.op).unop ≅ kernel f where
  hom :=
    kernel.lift f (cokernel.π f.op).unop <| by
      rw [← f.unop_op, ← unop_comp, f.unop_op]
      simp
  inv := (cokernel.desc f.op (kernel.ι f).op <| by simp [← op_comp]).unop
  hom_inv_id := by
    rw [← unop_id, ← (kernel.lift f _ _).unop_op, ← unop_comp]
    

Proof state:
C : Type u_1
inst✝¹ : Category.{?u.12173, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ (cokernel.desc f.op (kernel.ι f).op (_ : (kernel.ι f ≫ f).op = 0) ≫
        (kernel.lift f (cokernel.π f.op).unop (_ : (cokernel.π f.op).unop ≫ f = 0)).op).unop =
    (𝟙 (cokernel f.op)).unop

Next tactic:
congr 1
/-- The cokernel of `f.op` is the opposite of `kernel f`. -/
@[simps]
def cokernelOpUnop : (cokernel f.op).unop ≅ kernel f where
  hom :=
    kernel.lift f (cokernel.π f.op).unop <| by
      rw [← f.unop_op, ← unop_comp, f.unop_op]
      simp
  inv := (cokernel.desc f.op (kernel.ι f).op <| by simp [← op_comp]).unop
  hom_inv_id := by
    rw [← unop_id, ← (kernel.lift f _ _).unop_op, ← unop_comp]
    congr 1
    

Proof state:
case e_f
C : Type u_1
inst✝¹ : Category.{?u.12173, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ cokernel.desc f.op (kernel.ι f).op (_ : (kernel.ι f ≫ f).op = 0) ≫
      (kernel.lift f (cokernel.π f.op).unop (_ : (cokernel.π f.op).unop ≫ f = 0)).op =
    𝟙 (cokernel f.op)

Next tactic:
ext
/-- The cokernel of `f.op` is the opposite of `kernel f`. -/
@[simps]
def cokernelOpUnop : (cokernel f.op).unop ≅ kernel f where
  hom :=
    kernel.lift f (cokernel.π f.op).unop <| by
      rw [← f.unop_op, ← unop_comp, f.unop_op]
      simp
  inv := (cokernel.desc f.op (kernel.ι f).op <| by simp [← op_comp]).unop
  hom_inv_id := by
    rw [← unop_id, ← (kernel.lift f _ _).unop_op, ← unop_comp]
    congr 1
    ext
    

Proof state:
case e_f.h
C : Type u_1
inst✝¹ : Category.{?u.12173, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ coequalizer.π f.op 0 ≫
      cokernel.desc f.op (kernel.ι f).op (_ : (kernel.ι f ≫ f).op = 0) ≫
        (kernel.lift f (cokernel.π f.op).unop (_ : (cokernel.π f.op).unop ≫ f = 0)).op =
    coequalizer.π f.op 0 ≫ 𝟙 (cokernel f.op)

Next tactic:
simp [← op_comp]
/-- The cokernel of `f.op` is the opposite of `kernel f`. -/
@[simps]
def cokernelOpUnop : (cokernel f.op).unop ≅ kernel f where
  hom :=
    kernel.lift f (cokernel.π f.op).unop <| by
      rw [← f.unop_op, ← unop_comp, f.unop_op]
      simp
  inv := (cokernel.desc f.op (kernel.ι f).op <| by simp [← op_comp]).unop
  hom_inv_id := by
    rw [← unop_id, ← (kernel.lift f _ _).unop_op, ← unop_comp]
    congr 1
    ext
    simp [← op_comp]
  inv_hom_id := by
    

Proof state:
C : Type u_1
inst✝¹ : Category.{?u.12173, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ (cokernel.desc f.op (kernel.ι f).op (_ : (kernel.ι f ≫ f).op = 0)).unop ≫
      kernel.lift f (cokernel.π f.op).unop (_ : (cokernel.π f.op).unop ≫ f = 0) =
    𝟙 (kernel f)

Next tactic:
ext
/-- The cokernel of `f.op` is the opposite of `kernel f`. -/
@[simps]
def cokernelOpUnop : (cokernel f.op).unop ≅ kernel f where
  hom :=
    kernel.lift f (cokernel.π f.op).unop <| by
      rw [← f.unop_op, ← unop_comp, f.unop_op]
      simp
  inv := (cokernel.desc f.op (kernel.ι f).op <| by simp [← op_comp]).unop
  hom_inv_id := by
    rw [← unop_id, ← (kernel.lift f _ _).unop_op, ← unop_comp]
    congr 1
    ext
    simp [← op_comp]
  inv_hom_id := by
    ext
    

Proof state:
case h
C : Type u_1
inst✝¹ : Category.{?u.12173, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ ((cokernel.desc f.op (kernel.ι f).op (_ : (kernel.ι f ≫ f).op = 0)).unop ≫
        kernel.lift f (cokernel.π f.op).unop (_ : (cokernel.π f.op).unop ≫ f = 0)) ≫
      equalizer.ι f 0 =
    𝟙 (kernel f) ≫ equalizer.ι f 0

Next tactic:
simp [← unop_comp]
theorem cokernel.π_op :
    (cokernel.π f.op).unop =
      (cokernelOpUnop f).hom ≫ kernel.ι f ≫ eqToHom (Opposite.unop_op _).symm :=
  by 

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ (cokernel.π f.op).unop = (cokernelOpUnop f).hom ≫ kernel.ι f ≫ eqToHom (_ : X = (Opposite.op X).unop)

Next tactic:
simp [cokernelOpUnop]
theorem kernel.ι_op :
    (kernel.ι f.op).unop = eqToHom (Opposite.unop_op _) ≫ cokernel.π f ≫ (kernelOpUnop f).inv := by
  

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ (kernel.ι f.op).unop = eqToHom (_ : (Opposite.op Y).unop = Y) ≫ cokernel.π f ≫ (kernelOpUnop f).inv

Next tactic:
simp [kernelOpUnop]
theorem kernel.ι_unop :
    (kernel.ι g.unop).op = eqToHom (Opposite.op_unop _) ≫ cokernel.π g ≫ (kernelUnopOp g).inv := by
  

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ (kernel.ι g.unop).op = eqToHom (_ : Opposite.op B.unop = B) ≫ cokernel.π g ≫ (kernelUnopOp g).inv

Next tactic:
simp
theorem cokernel.π_unop :
    (cokernel.π g.unop).op =
      (cokernelUnopOp g).hom ≫ kernel.ι g ≫ eqToHom (Opposite.op_unop _).symm :=
  by 

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ (cokernel.π g.unop).op = (cokernelUnopOp g).hom ≫ kernel.ι g ≫ eqToHom (_ : A = Opposite.op A.unop)

Next tactic:
simp
theorem image_ι_op_comp_imageUnopOp_hom :
    (image.ι g.unop).op ≫ (imageUnopOp g).hom = factorThruImage g := by
  

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ (image.ι g.unop).op ≫ (imageUnopOp g).hom = factorThruImage g

Next tactic:
simp only [imageUnopOp, Iso.trans, Iso.symm, Iso.op, cokernelOpOp_inv, cokernelEpiComp_hom,
    cokernelCompIsIso_hom, Abelian.coimageIsoImage'_hom, ← Category.assoc, ← op_comp]
theorem image_ι_op_comp_imageUnopOp_hom :
    (image.ι g.unop).op ≫ (imageUnopOp g).hom = factorThruImage g := by
  simp only [imageUnopOp, Iso.trans, Iso.symm, Iso.op, cokernelOpOp_inv, cokernelEpiComp_hom,
    cokernelCompIsIso_hom, Abelian.coimageIsoImage'_hom, ← Category.assoc, ← op_comp]
  

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ (((((kernel.lift (cokernel.π g.unop) (cokernel.π (cokernel.π g.unop).op).unop
                    (_ : (cokernel.π (cokernel.π g.unop).op).unop ≫ cokernel.π g.unop = 0) ≫
                  (Abelian.imageIsoImage g.unop).hom) ≫
                image.ι g.unop).op ≫
            (cokernelIsoOfEq
                (_ :
                  (cokernel.π g.unop).op =
                    (cokernelUnopOp g).hom ≫ kernel.ι g ≫ eqToHom (_ : A = Opposite.op A.unop))).hom) ≫
          cokernel.desc ((cokernelUnopOp g).hom ≫ kernel.ι g ≫ eqToHom (_ : A = Opposite.op A.unop))
            (cokernel.π (kernel.ι g ≫ eqToHom (_ : A = Opposite.op A.unop)))
            (_ :
              ((cokernelUnopOp g).hom ≫ kernel.ι g ≫ eqToHom (_ : A = Opposite.op A.unop)) ≫
                  cokernel.π (kernel.ι g ≫ eqToHom (_ : A = Opposite.op A.unop)) =
                0)) ≫
        cokernel.desc (kernel.ι g ≫ eqToHom (_ : A = Opposite.op A.unop))
          (inv (eqToHom (_ : A = Opposite.op A.unop)) ≫ cokernel.π (kernel.ι g))
          (_ :
            (kernel.ι g ≫ eqToHom (_ : A = Opposite.op A.unop)) ≫
                inv (eqToHom (_ : A = Opposite.op A.unop)) ≫ cokernel.π (kernel.ι g) =
              0)) ≫
      cokernel.desc (kernel.ι g) (factorThruImage g) (_ : kernel.ι g ≫ factorThruImage g = 0) =
    factorThruImage g

Next tactic:
simp only [Category.assoc, Abelian.imageIsoImage_hom_comp_image_ι, kernel.lift_ι,
    Quiver.Hom.op_unop, cokernelIsoOfEq_hom_comp_desc_assoc, cokernel.π_desc_assoc,
    cokernel.π_desc]
theorem image_ι_op_comp_imageUnopOp_hom :
    (image.ι g.unop).op ≫ (imageUnopOp g).hom = factorThruImage g := by
  simp only [imageUnopOp, Iso.trans, Iso.symm, Iso.op, cokernelOpOp_inv, cokernelEpiComp_hom,
    cokernelCompIsIso_hom, Abelian.coimageIsoImage'_hom, ← Category.assoc, ← op_comp]
  simp only [Category.assoc, Abelian.imageIsoImage_hom_comp_image_ι, kernel.lift_ι,
    Quiver.Hom.op_unop, cokernelIsoOfEq_hom_comp_desc_assoc, cokernel.π_desc_assoc,
    cokernel.π_desc]
  

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ inv (eqToHom (_ : A = Opposite.op A.unop)) ≫ factorThruImage g = factorThruImage g

Next tactic:
simp only [eqToHom_refl]
theorem image_ι_op_comp_imageUnopOp_hom :
    (image.ι g.unop).op ≫ (imageUnopOp g).hom = factorThruImage g := by
  simp only [imageUnopOp, Iso.trans, Iso.symm, Iso.op, cokernelOpOp_inv, cokernelEpiComp_hom,
    cokernelCompIsIso_hom, Abelian.coimageIsoImage'_hom, ← Category.assoc, ← op_comp]
  simp only [Category.assoc, Abelian.imageIsoImage_hom_comp_image_ι, kernel.lift_ι,
    Quiver.Hom.op_unop, cokernelIsoOfEq_hom_comp_desc_assoc, cokernel.π_desc_assoc,
    cokernel.π_desc]
  simp only [eqToHom_refl]
  

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ inv (𝟙 A) ≫ factorThruImage g = factorThruImage g

Next tactic:
erw [IsIso.inv_id, Category.id_comp]
theorem imageUnopOp_hom_comp_image_ι :
    (imageUnopOp g).hom ≫ image.ι g = (factorThruImage g.unop).op := by
  

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ (imageUnopOp g).hom ≫ image.ι g = (factorThruImage g.unop).op

Next tactic:
simp only [← cancel_epi (image.ι g.unop).op, ← Category.assoc, image_ι_op_comp_imageUnopOp_hom,
    ← op_comp, image.fac, Quiver.Hom.op_unop]
theorem factorThruImage_comp_imageUnopOp_inv :
    factorThruImage g ≫ (imageUnopOp g).inv = (image.ι g.unop).op := by
  

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ factorThruImage g ≫ (imageUnopOp g).inv = (image.ι g.unop).op

Next tactic:
rw [Iso.comp_inv_eq, image_ι_op_comp_imageUnopOp_hom]
theorem imageUnopOp_inv_comp_op_factorThruImage :
    (imageUnopOp g).inv ≫ (factorThruImage g.unop).op = image.ι g := by
  

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : Abelian C
X Y : C
f : X ⟶ Y
A B : Cᵒᵖ
g : A ⟶ B
⊢ (imageUnopOp g).inv ≫ (factorThruImage g.unop).op = image.ι g

Next tactic:
rw [Iso.inv_comp_eq, imageUnopOp_hom_comp_image_ι]
@[norm_cast]
theorem Int.coe_nat_multiplicity (a b : ℕ) : multiplicity (a : ℤ) (b : ℤ) = multiplicity a b := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Monoid α
inst✝ : Monoid β
a b : ℕ
⊢ multiplicity ↑a ↑b = multiplicity a b

Next tactic:
apply Part.ext'
@[norm_cast]
theorem Int.coe_nat_multiplicity (a b : ℕ) : multiplicity (a : ℤ) (b : ℤ) = multiplicity a b := by
  apply Part.ext'
  · 

Proof state:
case x
α : Type u_1
β : Type u_2
inst✝¹ : Monoid α
inst✝ : Monoid β
a b : ℕ
⊢ (multiplicity ↑a ↑b).Dom ↔ (multiplicity a b).Dom

Next tactic:
rw [← @finite_iff_dom ℕ, @finite_def ℕ, ← @finite_iff_dom ℤ, @finite_def ℤ]
@[norm_cast]
theorem Int.coe_nat_multiplicity (a b : ℕ) : multiplicity (a : ℤ) (b : ℤ) = multiplicity a b := by
  apply Part.ext'
  · rw [← @finite_iff_dom ℕ, @finite_def ℕ, ← @finite_iff_dom ℤ, @finite_def ℤ]
    

Proof state:
case x
α : Type u_1
β : Type u_2
inst✝¹ : Monoid α
inst✝ : Monoid β
a b : ℕ
⊢ (∃ n, ¬↑a ^ (n + 1) ∣ ↑b) ↔ ∃ n, ¬a ^ (n + 1) ∣ b

Next tactic:
norm_cast
@[norm_cast]
theorem Int.coe_nat_multiplicity (a b : ℕ) : multiplicity (a : ℤ) (b : ℤ) = multiplicity a b := by
  apply Part.ext'
  · rw [← @finite_iff_dom ℕ, @finite_def ℕ, ← @finite_iff_dom ℤ, @finite_def ℤ]
    norm_cast
  · 

Proof state:
case x
α : Type u_1
β : Type u_2
inst✝¹ : Monoid α
inst✝ : Monoid β
a b : ℕ
⊢ ∀ (h₁ : (multiplicity ↑a ↑b).Dom) (h₂ : (multiplicity a b).Dom),
    Part.get (multiplicity ↑a ↑b) h₁ = Part.get (multiplicity a b) h₂

Next tactic:
intro h1 h2
@[norm_cast]
theorem Int.coe_nat_multiplicity (a b : ℕ) : multiplicity (a : ℤ) (b : ℤ) = multiplicity a b := by
  apply Part.ext'
  · rw [← @finite_iff_dom ℕ, @finite_def ℕ, ← @finite_iff_dom ℤ, @finite_def ℤ]
    norm_cast
  · intro h1 h2
    

Proof state:
case x
α : Type u_1
β : Type u_2
inst✝¹ : Monoid α
inst✝ : Monoid β
a b : ℕ
h1 : (multiplicity ↑a ↑b).Dom
h2 : (multiplicity a b).Dom
⊢ Part.get (multiplicity ↑a ↑b) h1 = Part.get (multiplicity a b) h2

Next tactic:
apply _root_.le_antisymm
@[norm_cast]
theorem Int.coe_nat_multiplicity (a b : ℕ) : multiplicity (a : ℤ) (b : ℤ) = multiplicity a b := by
  apply Part.ext'
  · rw [← @finite_iff_dom ℕ, @finite_def ℕ, ← @finite_iff_dom ℤ, @finite_def ℤ]
    norm_cast
  · intro h1 h2
    apply _root_.le_antisymm <;>
      · 

Proof state:
case x.a
α : Type u_1
β : Type u_2
inst✝¹ : Monoid α
inst✝ : Monoid β
a b : ℕ
h1 : (multiplicity ↑a ↑b).Dom
h2 : (multiplicity a b).Dom
⊢ Part.get (multiplicity ↑a ↑b) h1 ≤ Part.get (multiplicity a b) h2

Next tactic:
apply Nat.find_mono
@[norm_cast]
theorem Int.coe_nat_multiplicity (a b : ℕ) : multiplicity (a : ℤ) (b : ℤ) = multiplicity a b := by
  apply Part.ext'
  · rw [← @finite_iff_dom ℕ, @finite_def ℕ, ← @finite_iff_dom ℤ, @finite_def ℤ]
    norm_cast
  · intro h1 h2
    apply _root_.le_antisymm <;>
      · apply Nat.find_mono
        

Proof state:
case x.a.h
α : Type u_1
β : Type u_2
inst✝¹ : Monoid α
inst✝ : Monoid β
a b : ℕ
h1 : (multiplicity ↑a ↑b).Dom
h2 : (multiplicity a b).Dom
⊢ ∀ (n : ℕ), (fun n => ¬a ^ (n + 1) ∣ b) n → (fun n => ¬↑a ^ (n + 1) ∣ ↑b) n

Next tactic:
norm_cast
@[norm_cast]
theorem Int.coe_nat_multiplicity (a b : ℕ) : multiplicity (a : ℤ) (b : ℤ) = multiplicity a b := by
  apply Part.ext'
  · rw [← @finite_iff_dom ℕ, @finite_def ℕ, ← @finite_iff_dom ℤ, @finite_def ℤ]
    norm_cast
  · intro h1 h2
    apply _root_.le_antisymm <;>
      · apply Nat.find_mono
        norm_cast
        

Proof state:
case x.a.h
α : Type u_1
β : Type u_2
inst✝¹ : Monoid α
inst✝ : Monoid β
a b : ℕ
h1 : (multiplicity ↑a ↑b).Dom
h2 : (multiplicity a b).Dom
⊢ ∀ (n : ℕ), (fun n => ¬a ^ (n + 1) ∣ b) n → (fun n => ¬a ^ (n + 1) ∣ b) n

Next tactic:
simp
@[norm_cast]
theorem Int.coe_nat_multiplicity (a b : ℕ) : multiplicity (a : ℤ) (b : ℤ) = multiplicity a b := by
  apply Part.ext'
  · rw [← @finite_iff_dom ℕ, @finite_def ℕ, ← @finite_iff_dom ℤ, @finite_def ℤ]
    norm_cast
  · intro h1 h2
    apply _root_.le_antisymm <;>
      · 

Proof state:
case x.a
α : Type u_1
β : Type u_2
inst✝¹ : Monoid α
inst✝ : Monoid β
a b : ℕ
h1 : (multiplicity ↑a ↑b).Dom
h2 : (multiplicity a b).Dom
⊢ Part.get (multiplicity a b) h2 ≤ Part.get (multiplicity ↑a ↑b) h1

Next tactic:
apply Nat.find_mono
@[norm_cast]
theorem Int.coe_nat_multiplicity (a b : ℕ) : multiplicity (a : ℤ) (b : ℤ) = multiplicity a b := by
  apply Part.ext'
  · rw [← @finite_iff_dom ℕ, @finite_def ℕ, ← @finite_iff_dom ℤ, @finite_def ℤ]
    norm_cast
  · intro h1 h2
    apply _root_.le_antisymm <;>
      · apply Nat.find_mono
        

Proof state:
case x.a.h
α : Type u_1
β : Type u_2
inst✝¹ : Monoid α
inst✝ : Monoid β
a b : ℕ
h1 : (multiplicity ↑a ↑b).Dom
h2 : (multiplicity a b).Dom
⊢ ∀ (n : ℕ), (fun n => ¬↑a ^ (n + 1) ∣ ↑b) n → (fun n => ¬a ^ (n + 1) ∣ b) n

Next tactic:
norm_cast
theorem not_finite_iff_forall {a b : α} : ¬Finite a b ↔ ∀ n : ℕ, a ^ n ∣ b :=
  ⟨fun h n =>
    Nat.casesOn n
      (by
        

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Monoid α
inst✝ : Monoid β
a b : α
h : ¬Finite a b
n : ℕ
⊢ a ^ zero ∣ b

Next tactic:
rw [_root_.pow_zero]
theorem not_finite_iff_forall {a b : α} : ¬Finite a b ↔ ∀ n : ℕ, a ^ n ∣ b :=
  ⟨fun h n =>
    Nat.casesOn n
      (by
        rw [_root_.pow_zero]
        

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Monoid α
inst✝ : Monoid β
a b : α
h : ¬Finite a b
n : ℕ
⊢ 1 ∣ b

Next tactic:
exact one_dvd _
theorem not_finite_iff_forall {a b : α} : ¬Finite a b ↔ ∀ n : ℕ, a ^ n ∣ b :=
  ⟨fun h n =>
    Nat.casesOn n
      (by
        rw [_root_.pow_zero]
        exact one_dvd _)
      (by 

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Monoid α
inst✝ : Monoid β
a b : α
h : ¬Finite a b
n : ℕ
⊢ ∀ (n : ℕ), a ^ succ n ∣ b

Next tactic:
simpa [Finite, Classical.not_not] using h
theorem not_finite_iff_forall {a b : α} : ¬Finite a b ↔ ∀ n : ℕ, a ^ n ∣ b :=
  ⟨fun h n =>
    Nat.casesOn n
      (by
        rw [_root_.pow_zero]
        exact one_dvd _)
      (by simpa [Finite, Classical.not_not] using h),
    by 

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Monoid α
inst✝ : Monoid β
a b : α
⊢ (∀ (n : ℕ), a ^ n ∣ b) → ¬Finite a b

Next tactic:
simp [Finite, multiplicity, Classical.not_not]
theorem not_finite_iff_forall {a b : α} : ¬Finite a b ↔ ∀ n : ℕ, a ^ n ∣ b :=
  ⟨fun h n =>
    Nat.casesOn n
      (by
        rw [_root_.pow_zero]
        exact one_dvd _)
      (by simpa [Finite, Classical.not_not] using h),
    by simp [Finite, multiplicity, Classical.not_not]; 

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Monoid α
inst✝ : Monoid β
a b : α
⊢ (∀ (n : ℕ), a ^ n ∣ b) → ∀ (x : ℕ), a ^ (x + 1) ∣ b

Next tactic:
tauto
theorem pow_dvd_of_le_multiplicity {a b : α} {k : ℕ} :
    (k : PartENat) ≤ multiplicity a b → a ^ k ∣ b := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝³ : Monoid α
inst✝² : Monoid β
inst✝¹ : DecidableRel fun x x_1 => x ∣ x_1
inst✝ : DecidableRel fun x x_1 => x ∣ x_1
a b : α
k : ℕ
⊢ ↑k ≤ multiplicity a b → a ^ k ∣ b

Next tactic:
rw [← PartENat.some_eq_natCast]
theorem pow_dvd_of_le_multiplicity {a b : α} {k : ℕ} :
    (k : PartENat) ≤ multiplicity a b → a ^ k ∣ b := by
  rw [← PartENat.some_eq_natCast]
  

Proof state:
α : Type u_1
β : Type u_2
inst✝³ : Monoid α
inst✝² : Monoid β
inst✝¹ : DecidableRel fun x x_1 => x ∣ x_1
inst✝ : DecidableRel fun x x_1 => x ∣ x_1
a b : α
k : ℕ
⊢ ↑k ≤ multiplicity a b → a ^ k ∣ b

Next tactic:
exact
    Nat.casesOn k
      (fun _ => by
        rw [_root_.pow_zero]
        exact one_dvd _)
      fun k ⟨_, h₂⟩ => by_contradiction fun hk => Nat.find_min _ (lt_of_succ_le (h₂ ⟨k, hk⟩)) hk
theorem pow_dvd_of_le_multiplicity {a b : α} {k : ℕ} :
    (k : PartENat) ≤ multiplicity a b → a ^ k ∣ b := by
  rw [← PartENat.some_eq_natCast]
  exact
    Nat.casesOn k
      (fun _ => by
        

Proof state:
α : Type u_1
β : Type u_2
inst✝³ : Monoid α
inst✝² : Monoid β
inst✝¹ : DecidableRel fun x x_1 => x ∣ x_1
inst✝ : DecidableRel fun x x_1 => x ∣ x_1
a b : α
k : ℕ
x✝ : ↑zero ≤ multiplicity a b
⊢ a ^ zero ∣ b

Next tactic:
rw [_root_.pow_zero]
theorem pow_dvd_of_le_multiplicity {a b : α} {k : ℕ} :
    (k : PartENat) ≤ multiplicity a b → a ^ k ∣ b := by
  rw [← PartENat.some_eq_natCast]
  exact
    Nat.casesOn k
      (fun _ => by
        rw [_root_.pow_zero]
        

Proof state:
α : Type u_1
β : Type u_2
inst✝³ : Monoid α
inst✝² : Monoid β
inst✝¹ : DecidableRel fun x x_1 => x ∣ x_1
inst✝ : DecidableRel fun x x_1 => x ∣ x_1
a b : α
k : ℕ
x✝ : ↑zero ≤ multiplicity a b
⊢ 1 ∣ b

Next tactic:
exact one_dvd _
theorem pow_multiplicity_dvd {a b : α} (h : Finite a b) : a ^ get (multiplicity a b) h ∣ b :=
  pow_dvd_of_le_multiplicity (by 

Proof state:
α : Type u_1
β : Type u_2
inst✝³ : Monoid α
inst✝² : Monoid β
inst✝¹ : DecidableRel fun x x_1 => x ∣ x_1
inst✝ : DecidableRel fun x x_1 => x ∣ x_1
a b : α
h : Finite a b
⊢ ↑(Part.get (multiplicity a b) h) ≤ multiplicity a b

Next tactic:
rw [PartENat.natCast_get]
theorem is_greatest {a b : α} {m : ℕ} (hm : multiplicity a b < m) : ¬a ^ m ∣ b := fun h => by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝³ : Monoid α
inst✝² : Monoid β
inst✝¹ : DecidableRel fun x x_1 => x ∣ x_1
inst✝ : DecidableRel fun x x_1 => x ∣ x_1
a b : α
m : ℕ
hm : multiplicity a b < ↑m
h : a ^ m ∣ b
⊢ False

Next tactic:
rw [PartENat.lt_coe_iff] at hm
theorem is_greatest {a b : α} {m : ℕ} (hm : multiplicity a b < m) : ¬a ^ m ∣ b := fun h => by
  rw [PartENat.lt_coe_iff] at hm; 

Proof state:
α : Type u_1
β : Type u_2
inst✝³ : Monoid α
inst✝² : Monoid β
inst✝¹ : DecidableRel fun x x_1 => x ∣ x_1
inst✝ : DecidableRel fun x x_1 => x ∣ x_1
a b : α
m : ℕ
hm : ∃ (h : (multiplicity a b).Dom), Part.get (multiplicity a b) h < m
h : a ^ m ∣ b
⊢ False

Next tactic:
exact Nat.find_spec hm.fst ((pow_dvd_pow _ hm.snd).trans h)
theorem is_greatest' {a b : α} {m : ℕ} (h : Finite a b) (hm : get (multiplicity a b) h < m) :
    ¬a ^ m ∣ b :=
  is_greatest (by 

Proof state:
α : Type u_1
β : Type u_2
inst✝³ : Monoid α
inst✝² : Monoid β
inst✝¹ : DecidableRel fun x x_1 => x ∣ x_1
inst✝ : DecidableRel fun x x_1 => x ∣ x_1
a b : α
m : ℕ
h : Finite a b
hm : Part.get (multiplicity a b) h < m
⊢ multiplicity a b < ↑m

Next tactic:
rwa [← PartENat.coe_lt_coe, PartENat.natCast_get] at hm
theorem pos_of_dvd {a b : α} (hfin : Finite a b) (hdiv : a ∣ b) :
    0 < (multiplicity a b).get hfin := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝³ : Monoid α
inst✝² : Monoid β
inst✝¹ : DecidableRel fun x x_1 => x ∣ x_1
inst✝ : DecidableRel fun x x_1 => x ∣ x_1
a b : α
hfin : Finite a b
hdiv : a ∣ b
⊢ 0 < Part.get (multiplicity a b) hfin

Next tactic:
refine' zero_lt_iff.2 fun h => _
theorem pos_of_dvd {a b : α} (hfin : Finite a b) (hdiv : a ∣ b) :
    0 < (multiplicity a b).get hfin := by
  refine' zero_lt_iff.2 fun h => _
  

Proof state:
α : Type u_1
β : Type u_2
inst✝³ : Monoid α
inst✝² : Monoid β
inst✝¹ : DecidableRel fun x x_1 => x ∣ x_1
inst✝ : DecidableRel fun x x_1 => x ∣ x_1
a b : α
hfin : Finite a b
hdiv : a ∣ b
h : Part.get (multiplicity a b) hfin = 0
⊢ False

Next tactic:
simpa [hdiv] using is_greatest' hfin (lt_one_iff.mpr h)
theorem unique {a b : α} {k : ℕ} (hk : a ^ k ∣ b) (hsucc : ¬a ^ (k + 1) ∣ b) :
    (k : PartENat) = multiplicity a b :=
  le_antisymm (le_of_not_gt fun hk' => is_greatest hk' hk) <| by
    

Proof state:
α : Type u_1
β : Type u_2
inst✝³ : Monoid α
inst✝² : Monoid β
inst✝¹ : DecidableRel fun x x_1 => x ∣ x_1
inst✝ : DecidableRel fun x x_1 => x ∣ x_1
a b : α
k : ℕ
hk : a ^ k ∣ b
hsucc : ¬a ^ (k + 1) ∣ b
⊢ multiplicity a b ≤ ↑k

Next tactic:
have : Finite a b := ⟨k, hsucc⟩
theorem unique {a b : α} {k : ℕ} (hk : a ^ k ∣ b) (hsucc : ¬a ^ (k + 1) ∣ b) :
    (k : PartENat) = multiplicity a b :=
  le_antisymm (le_of_not_gt fun hk' => is_greatest hk' hk) <| by
    have : Finite a b := ⟨k, hsucc⟩
    

Proof state:
α : Type u_1
β : Type u_2
inst✝³ : Monoid α
inst✝² : Monoid β
inst✝¹ : DecidableRel fun x x_1 => x ∣ x_1
inst✝ : DecidableRel fun x x_1 => x ∣ x_1
a b : α
k : ℕ
hk : a ^ k ∣ b
hsucc : ¬a ^ (k + 1) ∣ b
this : Finite a b
⊢ multiplicity a b ≤ ↑k

Next tactic:
rw [PartENat.le_coe_iff]