l3lab/ntp-mathlib huggingface dataset:
theorem Associated.eq_zero_iff [MonoidWithZero α] {a b : α} (h : a ~ᵤ b) : a = 0 ↔ b = 0 :=
  ⟨fun ha => by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : MonoidWithZero α
a b : α
h : a ~ᵤ b
ha : a = 0
⊢ b = 0

Next tactic:
let ⟨u, hu⟩ := h
theorem Associated.eq_zero_iff [MonoidWithZero α] {a b : α} (h : a ~ᵤ b) : a = 0 ↔ b = 0 :=
  ⟨fun ha => by
    let ⟨u, hu⟩ := h
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : MonoidWithZero α
a b : α
h : a ~ᵤ b
ha : a = 0
u : αˣ
hu : a * ↑u = b
⊢ b = 0

Next tactic:
simp [hu.symm, ha]
theorem Associated.eq_zero_iff [MonoidWithZero α] {a b : α} (h : a ~ᵤ b) : a = 0 ↔ b = 0 :=
  ⟨fun ha => by
    let ⟨u, hu⟩ := h
    simp [hu.symm, ha], fun hb => by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : MonoidWithZero α
a b : α
h : a ~ᵤ b
hb : b = 0
⊢ a = 0

Next tactic:
let ⟨u, hu⟩ := h.symm
theorem Associated.eq_zero_iff [MonoidWithZero α] {a b : α} (h : a ~ᵤ b) : a = 0 ↔ b = 0 :=
  ⟨fun ha => by
    let ⟨u, hu⟩ := h
    simp [hu.symm, ha], fun hb => by
    let ⟨u, hu⟩ := h.symm
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : MonoidWithZero α
a b : α
h : a ~ᵤ b
hb : b = 0
u : αˣ
hu : b * ↑u = a
⊢ a = 0

Next tactic:
simp [hu.symm, hb]
protected theorem Associated.prime [CommMonoidWithZero α] {p q : α} (h : p ~ᵤ q) (hp : Prime p) :
    Prime q :=
  ⟨h.ne_zero_iff.1 hp.ne_zero,
    let ⟨u, hu⟩ := h
    ⟨fun ⟨v, hv⟩ => hp.not_unit ⟨v * u⁻¹, by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p q : α
h : p ~ᵤ q
hp : Prime p
u : αˣ
hu : p * ↑u = q
x✝ : IsUnit q
v : αˣ
hv : ↑v = q
⊢ ↑(v * u⁻¹) = p

Next tactic:
simp [hv, hu.symm]
protected theorem Associated.prime [CommMonoidWithZero α] {p q : α} (h : p ~ᵤ q) (hp : Prime p) :
    Prime q :=
  ⟨h.ne_zero_iff.1 hp.ne_zero,
    let ⟨u, hu⟩ := h
    ⟨fun ⟨v, hv⟩ => hp.not_unit ⟨v * u⁻¹, by simp [hv, hu.symm]⟩,
      hu ▸ by
        

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p q : α
h : p ~ᵤ q
hp : Prime p
u : αˣ
hu : p * ↑u = q
⊢ ∀ (a b : α), p * ↑u ∣ a * b → p * ↑u ∣ a ∨ p * ↑u ∣ b

Next tactic:
simp only [IsUnit.mul_iff, Units.isUnit, and_true, IsUnit.mul_right_dvd]
protected theorem Associated.prime [CommMonoidWithZero α] {p q : α} (h : p ~ᵤ q) (hp : Prime p) :
    Prime q :=
  ⟨h.ne_zero_iff.1 hp.ne_zero,
    let ⟨u, hu⟩ := h
    ⟨fun ⟨v, hv⟩ => hp.not_unit ⟨v * u⁻¹, by simp [hv, hu.symm]⟩,
      hu ▸ by
        simp only [IsUnit.mul_iff, Units.isUnit, and_true, IsUnit.mul_right_dvd]
        

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p q : α
h : p ~ᵤ q
hp : Prime p
u : αˣ
hu : p * ↑u = q
⊢ ∀ (a b : α), p ∣ a * b → p ∣ a ∨ p ∣ b

Next tactic:
intro a b
protected theorem Associated.prime [CommMonoidWithZero α] {p q : α} (h : p ~ᵤ q) (hp : Prime p) :
    Prime q :=
  ⟨h.ne_zero_iff.1 hp.ne_zero,
    let ⟨u, hu⟩ := h
    ⟨fun ⟨v, hv⟩ => hp.not_unit ⟨v * u⁻¹, by simp [hv, hu.symm]⟩,
      hu ▸ by
        simp only [IsUnit.mul_iff, Units.isUnit, and_true, IsUnit.mul_right_dvd]
        intro a b
        

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p q : α
h : p ~ᵤ q
hp : Prime p
u : αˣ
hu : p * ↑u = q
a b : α
⊢ p ∣ a * b → p ∣ a ∨ p ∣ b

Next tactic:
exact hp.dvd_or_dvd
theorem Irreducible.dvd_iff [Monoid α] {x y : α} (hx : Irreducible x) :
    y ∣ x ↔ IsUnit y ∨ Associated x y := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : Monoid α
x y : α
hx : Irreducible x
⊢ y ∣ x ↔ IsUnit y ∨ x ~ᵤ y

Next tactic:
constructor
theorem Irreducible.dvd_iff [Monoid α] {x y : α} (hx : Irreducible x) :
    y ∣ x ↔ IsUnit y ∨ Associated x y := by
  constructor
  · 

Proof state:
case mp
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : Monoid α
x y : α
hx : Irreducible x
⊢ y ∣ x → IsUnit y ∨ x ~ᵤ y

Next tactic:
rintro ⟨z, hz⟩
theorem Irreducible.dvd_iff [Monoid α] {x y : α} (hx : Irreducible x) :
    y ∣ x ↔ IsUnit y ∨ Associated x y := by
  constructor
  · rintro ⟨z, hz⟩
    

Proof state:
case mp.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : Monoid α
x y : α
hx : Irreducible x
z : α
hz : x = y * z
⊢ IsUnit y ∨ x ~ᵤ y

Next tactic:
obtain (h|h) := hx.isUnit_or_isUnit hz
theorem Irreducible.dvd_iff [Monoid α] {x y : α} (hx : Irreducible x) :
    y ∣ x ↔ IsUnit y ∨ Associated x y := by
  constructor
  · rintro ⟨z, hz⟩
    obtain (h|h) := hx.isUnit_or_isUnit hz
    · 

Proof state:
case mp.intro.inl
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : Monoid α
x y : α
hx : Irreducible x
z : α
hz : x = y * z
h : IsUnit y
⊢ IsUnit y ∨ x ~ᵤ y

Next tactic:
exact Or.inl h
theorem Irreducible.dvd_iff [Monoid α] {x y : α} (hx : Irreducible x) :
    y ∣ x ↔ IsUnit y ∨ Associated x y := by
  constructor
  · rintro ⟨z, hz⟩
    obtain (h|h) := hx.isUnit_or_isUnit hz
    · exact Or.inl h
    · 

Proof state:
case mp.intro.inr
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : Monoid α
x y : α
hx : Irreducible x
z : α
hz : x = y * z
h : IsUnit z
⊢ IsUnit y ∨ x ~ᵤ y

Next tactic:
rw [hz]
theorem Irreducible.dvd_iff [Monoid α] {x y : α} (hx : Irreducible x) :
    y ∣ x ↔ IsUnit y ∨ Associated x y := by
  constructor
  · rintro ⟨z, hz⟩
    obtain (h|h) := hx.isUnit_or_isUnit hz
    · exact Or.inl h
    · rw [hz]
      

Proof state:
case mp.intro.inr
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : Monoid α
x y : α
hx : Irreducible x
z : α
hz : x = y * z
h : IsUnit z
⊢ IsUnit y ∨ y * z ~ᵤ y

Next tactic:
exact Or.inr (associated_mul_unit_left _ _ h)
theorem Irreducible.dvd_iff [Monoid α] {x y : α} (hx : Irreducible x) :
    y ∣ x ↔ IsUnit y ∨ Associated x y := by
  constructor
  · rintro ⟨z, hz⟩
    obtain (h|h) := hx.isUnit_or_isUnit hz
    · exact Or.inl h
    · rw [hz]
      exact Or.inr (associated_mul_unit_left _ _ h)
  · 

Proof state:
case mpr
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : Monoid α
x y : α
hx : Irreducible x
⊢ IsUnit y ∨ x ~ᵤ y → y ∣ x

Next tactic:
rintro (hy|h)
theorem Irreducible.dvd_iff [Monoid α] {x y : α} (hx : Irreducible x) :
    y ∣ x ↔ IsUnit y ∨ Associated x y := by
  constructor
  · rintro ⟨z, hz⟩
    obtain (h|h) := hx.isUnit_or_isUnit hz
    · exact Or.inl h
    · rw [hz]
      exact Or.inr (associated_mul_unit_left _ _ h)
  · rintro (hy|h)
    · 

Proof state:
case mpr.inl
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : Monoid α
x y : α
hx : Irreducible x
hy : IsUnit y
⊢ y ∣ x

Next tactic:
exact hy.dvd
theorem Irreducible.dvd_iff [Monoid α] {x y : α} (hx : Irreducible x) :
    y ∣ x ↔ IsUnit y ∨ Associated x y := by
  constructor
  · rintro ⟨z, hz⟩
    obtain (h|h) := hx.isUnit_or_isUnit hz
    · exact Or.inl h
    · rw [hz]
      exact Or.inr (associated_mul_unit_left _ _ h)
  · rintro (hy|h)
    · exact hy.dvd
    · 

Proof state:
case mpr.inr
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : Monoid α
x y : α
hx : Irreducible x
h : x ~ᵤ y
⊢ y ∣ x

Next tactic:
exact h.symm.dvd
protected theorem Associated.isUnit [Monoid α] {a b : α} (h : a ~ᵤ b) : IsUnit a → IsUnit b :=
  let ⟨u, hu⟩ := h
  fun ⟨v, hv⟩ => ⟨v * u, by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : Monoid α
a b : α
h : a ~ᵤ b
u : αˣ
hu : a * ↑u = b
x✝ : IsUnit a
v : αˣ
hv : ↑v = a
⊢ ↑(v * u) = b

Next tactic:
simp [hv, hu.symm]
protected theorem Associated.irreducible [Monoid α] {p q : α} (h : p ~ᵤ q) (hp : Irreducible p) :
    Irreducible q :=
  ⟨mt h.symm.isUnit hp.1,
    let ⟨u, hu⟩ := h
    fun a b hab =>
    have hpab : p = a * (b * (u⁻¹ : αˣ)) :=
      calc
        p = p * u * (u⁻¹ : αˣ) := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : Monoid α
p q : α
h : p ~ᵤ q
hp : Irreducible p
u : αˣ
hu : p * ↑u = q
a b : α
hab : q = a * b
⊢ p = p * ↑u * ↑u⁻¹

Next tactic:
simp
protected theorem Associated.irreducible [Monoid α] {p q : α} (h : p ~ᵤ q) (hp : Irreducible p) :
    Irreducible q :=
  ⟨mt h.symm.isUnit hp.1,
    let ⟨u, hu⟩ := h
    fun a b hab =>
    have hpab : p = a * (b * (u⁻¹ : αˣ)) :=
      calc
        p = p * u * (u⁻¹ : αˣ) := by simp
        _ = _ := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : Monoid α
p q : α
h : p ~ᵤ q
hp : Irreducible p
u : αˣ
hu : p * ↑u = q
a b : α
hab : q = a * b
⊢ p * ↑u * ↑u⁻¹ = a * (b * ↑u⁻¹)

Next tactic:
rw [hu]
protected theorem Associated.irreducible [Monoid α] {p q : α} (h : p ~ᵤ q) (hp : Irreducible p) :
    Irreducible q :=
  ⟨mt h.symm.isUnit hp.1,
    let ⟨u, hu⟩ := h
    fun a b hab =>
    have hpab : p = a * (b * (u⁻¹ : αˣ)) :=
      calc
        p = p * u * (u⁻¹ : αˣ) := by simp
        _ = _ := by rw [hu]; 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : Monoid α
p q : α
h : p ~ᵤ q
hp : Irreducible p
u : αˣ
hu : p * ↑u = q
a b : α
hab : q = a * b
⊢ q * ↑u⁻¹ = a * (b * ↑u⁻¹)

Next tactic:
simp [hab, mul_assoc]
protected theorem Associated.irreducible [Monoid α] {p q : α} (h : p ~ᵤ q) (hp : Irreducible p) :
    Irreducible q :=
  ⟨mt h.symm.isUnit hp.1,
    let ⟨u, hu⟩ := h
    fun a b hab =>
    have hpab : p = a * (b * (u⁻¹ : αˣ)) :=
      calc
        p = p * u * (u⁻¹ : αˣ) := by simp
        _ = _ := by rw [hu]; simp [hab, mul_assoc]

    (hp.isUnit_or_isUnit hpab).elim Or.inl fun ⟨v, hv⟩ => Or.inr ⟨v * u, by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : Monoid α
p q : α
h : p ~ᵤ q
hp : Irreducible p
u : αˣ
hu : p * ↑u = q
a b : α
hab : q = a * b
hpab : p = a * (b * ↑u⁻¹)
x✝ : IsUnit (b * ↑u⁻¹)
v : αˣ
hv : ↑v = b * ↑u⁻¹
⊢ ↑(v * u) = b

Next tactic:
simp [hv]
theorem Associated.of_mul_left [CancelCommMonoidWithZero α] {a b c d : α} (h : a * b ~ᵤ c * d)
    (h₁ : a ~ᵤ c) (ha : a ≠ 0) : b ~ᵤ d :=
  let ⟨u, hu⟩ := h
  let ⟨v, hv⟩ := Associated.symm h₁
  ⟨u * (v : αˣ),
    mul_left_cancel₀ ha
      (by
        

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
a b c d : α
h : a * b ~ᵤ c * d
h₁ : a ~ᵤ c
ha : a ≠ 0
u : αˣ
hu : a * b * ↑u = c * d
v : αˣ
hv : c * ↑v = a
⊢ a * (b * ↑(u * v)) = a * d

Next tactic:
rw [← hv, mul_assoc c (v : α) d, mul_left_comm c, ← hu]
theorem Associated.of_mul_left [CancelCommMonoidWithZero α] {a b c d : α} (h : a * b ~ᵤ c * d)
    (h₁ : a ~ᵤ c) (ha : a ≠ 0) : b ~ᵤ d :=
  let ⟨u, hu⟩ := h
  let ⟨v, hv⟩ := Associated.symm h₁
  ⟨u * (v : αˣ),
    mul_left_cancel₀ ha
      (by
        rw [← hv, mul_assoc c (v : α) d, mul_left_comm c, ← hu]
        

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
a b c d : α
h : a * b ~ᵤ c * d
h₁ : a ~ᵤ c
ha : a ≠ 0
u : αˣ
hu : a * b * ↑u = c * d
v : αˣ
hv : c * ↑v = a
⊢ c * ↑v * (b * ↑(u * v)) = ↑v * (a * b * ↑u)

Next tactic:
simp [hv.symm, mul_assoc, mul_comm, mul_left_comm]
theorem Associated.of_mul_right [CancelCommMonoidWithZero α] {a b c d : α} :
    a * b ~ᵤ c * d → b ~ᵤ d → b ≠ 0 → a ~ᵤ c := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
a b c d : α
⊢ a * b ~ᵤ c * d → b ~ᵤ d → b ≠ 0 → a ~ᵤ c

Next tactic:
rw [mul_comm a, mul_comm c]
theorem Associated.of_mul_right [CancelCommMonoidWithZero α] {a b c d : α} :
    a * b ~ᵤ c * d → b ~ᵤ d → b ≠ 0 → a ~ᵤ c := by
  rw [mul_comm a, mul_comm c]; 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
a b c d : α
⊢ b * a ~ᵤ d * c → b ~ᵤ d → b ≠ 0 → a ~ᵤ c

Next tactic:
exact Associated.of_mul_left
theorem Associated.of_pow_associated_of_prime [CancelCommMonoidWithZero α] {p₁ p₂ : α} {k₁ k₂ : ℕ}
    (hp₁ : Prime p₁) (hp₂ : Prime p₂) (hk₁ : 0 < k₁) (h : p₁ ^ k₁ ~ᵤ p₂ ^ k₂) : p₁ ~ᵤ p₂ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p₁ p₂ : α
k₁ k₂ : ℕ
hp₁ : Prime p₁
hp₂ : Prime p₂
hk₁ : 0 < k₁
h : p₁ ^ k₁ ~ᵤ p₂ ^ k₂
⊢ p₁ ~ᵤ p₂

Next tactic:
have : p₁ ∣ p₂ ^ k₂ := by
    rw [← h.dvd_iff_dvd_right]
    apply dvd_pow_self _ hk₁.ne'
theorem Associated.of_pow_associated_of_prime [CancelCommMonoidWithZero α] {p₁ p₂ : α} {k₁ k₂ : ℕ}
    (hp₁ : Prime p₁) (hp₂ : Prime p₂) (hk₁ : 0 < k₁) (h : p₁ ^ k₁ ~ᵤ p₂ ^ k₂) : p₁ ~ᵤ p₂ := by
  have : p₁ ∣ p₂ ^ k₂ := by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p₁ p₂ : α
k₁ k₂ : ℕ
hp₁ : Prime p₁
hp₂ : Prime p₂
hk₁ : 0 < k₁
h : p₁ ^ k₁ ~ᵤ p₂ ^ k₂
⊢ p₁ ∣ p₂ ^ k₂

Next tactic:
rw [← h.dvd_iff_dvd_right]
theorem Associated.of_pow_associated_of_prime [CancelCommMonoidWithZero α] {p₁ p₂ : α} {k₁ k₂ : ℕ}
    (hp₁ : Prime p₁) (hp₂ : Prime p₂) (hk₁ : 0 < k₁) (h : p₁ ^ k₁ ~ᵤ p₂ ^ k₂) : p₁ ~ᵤ p₂ := by
  have : p₁ ∣ p₂ ^ k₂ := by
    rw [← h.dvd_iff_dvd_right]
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p₁ p₂ : α
k₁ k₂ : ℕ
hp₁ : Prime p₁
hp₂ : Prime p₂
hk₁ : 0 < k₁
h : p₁ ^ k₁ ~ᵤ p₂ ^ k₂
⊢ p₁ ∣ p₁ ^ k₁

Next tactic:
apply dvd_pow_self _ hk₁.ne'
theorem Associated.of_pow_associated_of_prime [CancelCommMonoidWithZero α] {p₁ p₂ : α} {k₁ k₂ : ℕ}
    (hp₁ : Prime p₁) (hp₂ : Prime p₂) (hk₁ : 0 < k₁) (h : p₁ ^ k₁ ~ᵤ p₂ ^ k₂) : p₁ ~ᵤ p₂ := by
  have : p₁ ∣ p₂ ^ k₂ := by
    rw [← h.dvd_iff_dvd_right]
    apply dvd_pow_self _ hk₁.ne'
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p₁ p₂ : α
k₁ k₂ : ℕ
hp₁ : Prime p₁
hp₂ : Prime p₂
hk₁ : 0 < k₁
h : p₁ ^ k₁ ~ᵤ p₂ ^ k₂
this : p₁ ∣ p₂ ^ k₂
⊢ p₁ ~ᵤ p₂

Next tactic:
rw [← hp₁.dvd_prime_iff_associated hp₂]
theorem Associated.of_pow_associated_of_prime [CancelCommMonoidWithZero α] {p₁ p₂ : α} {k₁ k₂ : ℕ}
    (hp₁ : Prime p₁) (hp₂ : Prime p₂) (hk₁ : 0 < k₁) (h : p₁ ^ k₁ ~ᵤ p₂ ^ k₂) : p₁ ~ᵤ p₂ := by
  have : p₁ ∣ p₂ ^ k₂ := by
    rw [← h.dvd_iff_dvd_right]
    apply dvd_pow_self _ hk₁.ne'
  rw [← hp₁.dvd_prime_iff_associated hp₂]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p₁ p₂ : α
k₁ k₂ : ℕ
hp₁ : Prime p₁
hp₂ : Prime p₂
hk₁ : 0 < k₁
h : p₁ ^ k₁ ~ᵤ p₂ ^ k₂
this : p₁ ∣ p₂ ^ k₂
⊢ p₁ ∣ p₂

Next tactic:
exact hp₁.dvd_of_dvd_pow this
theorem associated_iff_eq {x y : α} : x ~ᵤ y ↔ x = y := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Monoid α
inst✝ : Unique αˣ
x y : α
⊢ x ~ᵤ y ↔ x = y

Next tactic:
constructor
theorem associated_iff_eq {x y : α} : x ~ᵤ y ↔ x = y := by
  constructor
  · 

Proof state:
case mp
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Monoid α
inst✝ : Unique αˣ
x y : α
⊢ x ~ᵤ y → x = y

Next tactic:
rintro ⟨c, rfl⟩
theorem associated_iff_eq {x y : α} : x ~ᵤ y ↔ x = y := by
  constructor
  · rintro ⟨c, rfl⟩
    

Proof state:
case mp.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Monoid α
inst✝ : Unique αˣ
x : α
c : αˣ
⊢ x = x * ↑c

Next tactic:
rw [units_eq_one c, Units.val_one, mul_one]
theorem associated_iff_eq {x y : α} : x ~ᵤ y ↔ x = y := by
  constructor
  · rintro ⟨c, rfl⟩
    rw [units_eq_one c, Units.val_one, mul_one]
  · 

Proof state:
case mpr
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Monoid α
inst✝ : Unique αˣ
x y : α
⊢ x = y → x ~ᵤ y

Next tactic:
rintro rfl
theorem associated_iff_eq {x y : α} : x ~ᵤ y ↔ x = y := by
  constructor
  · rintro ⟨c, rfl⟩
    rw [units_eq_one c, Units.val_one, mul_one]
  · rintro rfl
    

Proof state:
case mpr
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Monoid α
inst✝ : Unique αˣ
x : α
⊢ x ~ᵤ x

Next tactic:
rfl
theorem associated_eq_eq : (Associated : α → α → Prop) = Eq := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Monoid α
inst✝ : Unique αˣ
⊢ Associated = Eq

Next tactic:
ext
theorem associated_eq_eq : (Associated : α → α → Prop) = Eq := by
  ext
  

Proof state:
case h.h.a
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Monoid α
inst✝ : Unique αˣ
x✝¹ x✝ : α
⊢ x✝¹ ~ᵤ x✝ ↔ x✝¹ = x✝

Next tactic:
rw [associated_iff_eq]
theorem prime_dvd_prime_iff_eq {M : Type*} [CancelCommMonoidWithZero M] [Unique Mˣ] {p q : M}
    (pp : Prime p) (qp : Prime q) : p ∣ q ↔ p = q := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : Monoid α
inst✝² : Unique αˣ
M : Type u_5
inst✝¹ : CancelCommMonoidWithZero M
inst✝ : Unique Mˣ
p q : M
pp : Prime p
qp : Prime q
⊢ p ∣ q ↔ p = q

Next tactic:
rw [pp.dvd_prime_iff_associated qp, ← associated_eq_eq]
theorem eq_of_prime_pow_eq (hp₁ : Prime p₁) (hp₂ : Prime p₂) (hk₁ : 0 < k₁)
    (h : p₁ ^ k₁ = p₂ ^ k₂) : p₁ = p₂ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
R : Type u_5
inst✝¹ : CancelCommMonoidWithZero R
inst✝ : Unique Rˣ
p₁ p₂ : R
k₁ k₂ : ℕ
hp₁ : Prime p₁
hp₂ : Prime p₂
hk₁ : 0 < k₁
h : p₁ ^ k₁ = p₂ ^ k₂
⊢ p₁ = p₂

Next tactic:
rw [← associated_iff_eq] at h ⊢
theorem eq_of_prime_pow_eq (hp₁ : Prime p₁) (hp₂ : Prime p₂) (hk₁ : 0 < k₁)
    (h : p₁ ^ k₁ = p₂ ^ k₂) : p₁ = p₂ := by
  rw [← associated_iff_eq] at h ⊢
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
R : Type u_5
inst✝¹ : CancelCommMonoidWithZero R
inst✝ : Unique Rˣ
p₁ p₂ : R
k₁ k₂ : ℕ
hp₁ : Prime p₁
hp₂ : Prime p₂
hk₁ : 0 < k₁
h : p₁ ^ k₁ ~ᵤ p₂ ^ k₂
⊢ p₁ ~ᵤ p₂

Next tactic:
apply h.of_pow_associated_of_prime hp₁ hp₂ hk₁
theorem eq_of_prime_pow_eq' (hp₁ : Prime p₁) (hp₂ : Prime p₂) (hk₁ : 0 < k₂)
    (h : p₁ ^ k₁ = p₂ ^ k₂) : p₁ = p₂ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
R : Type u_5
inst✝¹ : CancelCommMonoidWithZero R
inst✝ : Unique Rˣ
p₁ p₂ : R
k₁ k₂ : ℕ
hp₁ : Prime p₁
hp₂ : Prime p₂
hk₁ : 0 < k₂
h : p₁ ^ k₁ = p₂ ^ k₂
⊢ p₁ = p₂

Next tactic:
rw [← associated_iff_eq] at h ⊢
theorem eq_of_prime_pow_eq' (hp₁ : Prime p₁) (hp₂ : Prime p₂) (hk₁ : 0 < k₂)
    (h : p₁ ^ k₁ = p₂ ^ k₂) : p₁ = p₂ := by
  rw [← associated_iff_eq] at h ⊢
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
R : Type u_5
inst✝¹ : CancelCommMonoidWithZero R
inst✝ : Unique Rˣ
p₁ p₂ : R
k₁ k₂ : ℕ
hp₁ : Prime p₁
hp₂ : Prime p₂
hk₁ : 0 < k₂
h : p₁ ^ k₁ ~ᵤ p₂ ^ k₂
⊢ p₁ ~ᵤ p₂

Next tactic:
apply h.of_pow_associated_of_prime' hp₁ hp₂ hk₁
@[simp]
theorem quot_out [Monoid α] (a : Associates α) : Associates.mk (Quot.out a) = a := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : Monoid α
a : Associates α
⊢ Associates.mk (Quot.out a) = a

Next tactic:
rw [← quot_mk_eq_mk, Quot.out_eq]
instance [Monoid α] [Subsingleton α] :
    Unique (Associates α) where
  default := 1
  uniq a := by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Monoid α
inst✝ : Subsingleton α
a : Associates α
⊢ a = default

Next tactic:
apply Quotient.recOnSubsingleton₂
instance [Monoid α] [Subsingleton α] :
    Unique (Associates α) where
  default := 1
  uniq a := by
    apply Quotient.recOnSubsingleton₂
    

Proof state:
case g
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Monoid α
inst✝ : Subsingleton α
a : Associates α
⊢ ∀ (a b : α), ⟦a⟧ = ⟦b⟧

Next tactic:
intro a b
instance [Monoid α] [Subsingleton α] :
    Unique (Associates α) where
  default := 1
  uniq a := by
    apply Quotient.recOnSubsingleton₂
    intro a b
    

Proof state:
case g
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Monoid α
inst✝ : Subsingleton α
a✝ : Associates α
a b : α
⊢ ⟦a⟧ = ⟦b⟧

Next tactic:
congr
instance [Monoid α] [Subsingleton α] :
    Unique (Associates α) where
  default := 1
  uniq a := by
    apply Quotient.recOnSubsingleton₂
    intro a b
    congr
    

Proof state:
case g.e_a
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : Monoid α
inst✝ : Subsingleton α
a✝ : Associates α
a b : α
⊢ a = b

Next tactic:
simp [eq_iff_true_of_subsingleton]
instance instMul : Mul (Associates α) :=
  ⟨fun a' b' =>
    (Quotient.liftOn₂ a' b' fun a b => ⟦a * b⟧) fun a₁ a₂ b₁ b₂ ⟨c₁, h₁⟩ ⟨c₂, h₂⟩ =>
      Quotient.sound <| ⟨c₁ * c₂, by
        

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a' b' : Associates α
a₁ a₂ b₁ b₂ : α
x✝¹ : a₁ ≈ b₁
x✝ : a₂ ≈ b₂
c₁ : αˣ
h₁ : a₁ * ↑c₁ = b₁
c₂ : αˣ
h₂ : a₂ * ↑c₂ = b₂
⊢ a₁ * a₂ * ↑(c₁ * c₂) = b₁ * b₂

Next tactic:
rw [← h₁, ← h₂]
instance instMul : Mul (Associates α) :=
  ⟨fun a' b' =>
    (Quotient.liftOn₂ a' b' fun a b => ⟦a * b⟧) fun a₁ a₂ b₁ b₂ ⟨c₁, h₁⟩ ⟨c₂, h₂⟩ =>
      Quotient.sound <| ⟨c₁ * c₂, by
        rw [← h₁, ← h₂]
        

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a' b' : Associates α
a₁ a₂ b₁ b₂ : α
x✝¹ : a₁ ≈ b₁
x✝ : a₂ ≈ b₂
c₁ : αˣ
h₁ : a₁ * ↑c₁ = b₁
c₂ : αˣ
h₂ : a₂ * ↑c₂ = b₂
⊢ a₁ * a₂ * ↑(c₁ * c₂) = a₁ * ↑c₁ * (a₂ * ↑c₂)

Next tactic:
simp only [Units.val_mul, mul_left_comm, mul_comm]
instance instCommMonoid : CommMonoid (Associates α) where
  one := 1
  mul := (· * ·)
  mul_one a' := Quotient.inductionOn a' <| fun a => show ⟦a * 1⟧ = ⟦a⟧ by simp
  one_mul a' := Quotient.inductionOn a' <| fun a => show ⟦1 * a⟧ = ⟦a⟧ by simp
  mul_assoc a' b' c' :=
    Quotient.inductionOn₃ a' b' c' <| fun a b c =>
      show ⟦a * b * c⟧ = ⟦a * (b * c)⟧ by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a' b' c' : Associates α
a b c : α
⊢ ⟦a * b * c⟧ = ⟦a * (b * c)⟧

Next tactic:
rw [mul_assoc]
instance instCommMonoid : CommMonoid (Associates α) where
  one := 1
  mul := (· * ·)
  mul_one a' := Quotient.inductionOn a' <| fun a => show ⟦a * 1⟧ = ⟦a⟧ by simp
  one_mul a' := Quotient.inductionOn a' <| fun a => show ⟦1 * a⟧ = ⟦a⟧ by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a' : Associates α
a : α
⊢ ⟦1 * a⟧ = ⟦a⟧

Next tactic:
simp
instance instCommMonoid : CommMonoid (Associates α) where
  one := 1
  mul := (· * ·)
  mul_one a' := Quotient.inductionOn a' <| fun a => show ⟦a * 1⟧ = ⟦a⟧ by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a' : Associates α
a : α
⊢ ⟦a * 1⟧ = ⟦a⟧

Next tactic:
simp
instance instCommMonoid : CommMonoid (Associates α) where
  one := 1
  mul := (· * ·)
  mul_one a' := Quotient.inductionOn a' <| fun a => show ⟦a * 1⟧ = ⟦a⟧ by simp
  one_mul a' := Quotient.inductionOn a' <| fun a => show ⟦1 * a⟧ = ⟦a⟧ by simp
  mul_assoc a' b' c' :=
    Quotient.inductionOn₃ a' b' c' <| fun a b c =>
      show ⟦a * b * c⟧ = ⟦a * (b * c)⟧ by rw [mul_assoc]
  mul_comm a' b' :=
    Quotient.inductionOn₂ a' b' <| fun a b => show ⟦a * b⟧ = ⟦b * a⟧ by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a' b' : Associates α
a b : α
⊢ ⟦a * b⟧ = ⟦b * a⟧

Next tactic:
rw [mul_comm]
theorem mk_pow (a : α) (n : ℕ) : Associates.mk (a ^ n) = Associates.mk a ^ n := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a : α
n : ℕ
⊢ Associates.mk (a ^ n) = Associates.mk a ^ n

Next tactic:
induction n
theorem mk_pow (a : α) (n : ℕ) : Associates.mk (a ^ n) = Associates.mk a ^ n := by
  induction n <;> 

Proof state:
case zero
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a : α
⊢ Associates.mk (a ^ Nat.zero) = Associates.mk a ^ Nat.zero

Next tactic:
simp [*, pow_succ, Associates.mk_mul_mk.symm]
theorem mk_pow (a : α) (n : ℕ) : Associates.mk (a ^ n) = Associates.mk a ^ n := by
  induction n <;> 

Proof state:
case succ
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a : α
n✝ : ℕ
n_ih✝ : Associates.mk (a ^ n✝) = Associates.mk a ^ n✝
⊢ Associates.mk (a ^ Nat.succ n✝) = Associates.mk a ^ Nat.succ n✝

Next tactic:
simp [*, pow_succ, Associates.mk_mul_mk.symm]
theorem mul_eq_one_iff {x y : Associates α} : x * y = 1 ↔ x = 1 ∧ y = 1 :=
  Iff.intro
    (Quotient.inductionOn₂ x y <| fun a b h =>
      have : a * b ~ᵤ 1 := Quotient.exact h
      ⟨Quotient.sound <| associated_one_of_associated_mul_one this,
        Quotient.sound <| associated_one_of_associated_mul_one <| by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
x y : Associates α
a b : α
h : ⟦a⟧ * ⟦b⟧ = 1
this : a * b ~ᵤ 1
⊢ b * ?m.198754 a b h this ~ᵤ 1

Next tactic:
rwa [mul_comm] at this