l3lab/ntp-mathlib huggingface dataset:
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 rwa [mul_comm] at this⟩)
    (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
x y : Associates α
⊢ x = 1 ∧ y = 1 → x * y = 1

Next tactic:
simp (config := { contextual := true })
@[simp]
theorem coe_unit_eq_one (u : (Associates α)ˣ) : (u : Associates α) = 1 := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
u : (Associates α)ˣ
⊢ ↑u = 1

Next tactic:
simp [eq_iff_true_of_subsingleton]
theorem isUnit_iff_eq_bot {a : Associates α} : IsUnit a ↔ a = ⊥ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a : Associates α
⊢ IsUnit a ↔ a = ⊥

Next tactic:
rw [Associates.isUnit_iff_eq_one, bot_eq_one]
theorem isUnit_mk {a : α} : IsUnit (Associates.mk a) ↔ IsUnit a :=
  calc
    IsUnit (Associates.mk a) ↔ a ~ᵤ 1 := by
      

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a : α
⊢ IsUnit (Associates.mk a) ↔ a ~ᵤ 1

Next tactic:
rw [isUnit_iff_eq_one, one_eq_mk_one, mk_eq_mk_iff_associated]
theorem mul_mono {a b c d : Associates α} (h₁ : a ≤ b) (h₂ : c ≤ d) : a * c ≤ b * d :=
  let ⟨x, hx⟩ := h₁
  let ⟨y, hy⟩ := h₂
  ⟨x * y, by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a b c d : Associates α
h₁ : a ≤ b
h₂ : c ≤ d
x : Associates α
hx : b = a * x
y : Associates α
hy : d = c * y
⊢ b * d = a * c * (x * y)

Next tactic:
simp [hx, hy, mul_comm, mul_assoc, mul_left_comm]
theorem le_mul_left {a b : Associates α} : a ≤ 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

Next tactic:
rw [mul_comm]
theorem le_mul_left {a b : Associates α} : a ≤ b * a := by rw [mul_comm]; 

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

Next tactic:
exact le_mul_right
theorem dvd_of_mk_le_mk {a b : α} : Associates.mk a ≤ Associates.mk b → a ∣ b
  | ⟨c', hc'⟩ =>
    let step : ∀ (c : α),
      Associates.mk b = Associates.mk a * Quotient.mk (Associated.setoid α) c → a ∣ b := by
      

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a b : α
c' : Associates α
hc' : Associates.mk b = Associates.mk a * c'
⊢ ∀ (c : α), Associates.mk b = Associates.mk a * ⟦c⟧ → a ∣ b

Next tactic:
intro c hc
theorem dvd_of_mk_le_mk {a b : α} : Associates.mk a ≤ Associates.mk b → a ∣ b
  | ⟨c', hc'⟩ =>
    let step : ∀ (c : α),
      Associates.mk b = Associates.mk a * Quotient.mk (Associated.setoid α) c → a ∣ b := by
      intro c hc
      

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

Next tactic:
let ⟨d, hd⟩ := (Quotient.exact hc).symm
theorem dvd_of_mk_le_mk {a b : α} : Associates.mk a ≤ Associates.mk b → a ∣ b
  | ⟨c', hc'⟩ =>
    let step : ∀ (c : α),
      Associates.mk b = Associates.mk a * Quotient.mk (Associated.setoid α) c → a ∣ b := by
      intro c hc
      let ⟨d, hd⟩ := (Quotient.exact hc).symm
      

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a b : α
c' : Associates α
hc' : Associates.mk b = Associates.mk a * c'
c : α
hc : Associates.mk b = Associates.mk a * ⟦c⟧
d : αˣ
hd : a * c * ↑d = b
⊢ a ∣ b

Next tactic:
exact ⟨↑d * c,
          calc
            b = a * c * ↑d := hd.symm
            _ = a * (↑d * c) := by ac_rfl
            ⟩
theorem dvd_of_mk_le_mk {a b : α} : Associates.mk a ≤ Associates.mk b → a ∣ b
  | ⟨c', hc'⟩ =>
    let step : ∀ (c : α),
      Associates.mk b = Associates.mk a * Quotient.mk (Associated.setoid α) c → a ∣ b := by
      intro c hc
      let ⟨d, hd⟩ := (Quotient.exact hc).symm
      exact ⟨↑d * c,
          calc
            b = a * c * ↑d := hd.symm
            _ = a * (↑d * c) := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a b : α
c' : Associates α
hc' : Associates.mk b = Associates.mk a * c'
c : α
hc : Associates.mk b = Associates.mk a * ⟦c⟧
d : αˣ
hd : a * c * ↑d = b
⊢ a * c * ↑d = a * (↑d * c)

Next tactic:
ac_rfl
theorem mk_le_mk_of_dvd {a b : α} : a ∣ b → Associates.mk a ≤ Associates.mk b := fun ⟨c, hc⟩ =>
  ⟨Associates.mk c, by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a b : α
x✝ : a ∣ b
c : α
hc : b = a * c
⊢ Associates.mk b = Associates.mk a * Associates.mk c

Next tactic:
simp [hc]
theorem mk_le_mk_of_dvd {a b : α} : a ∣ b → Associates.mk a ≤ Associates.mk b := fun ⟨c, hc⟩ =>
  ⟨Associates.mk c, by simp [hc]; 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
a b : α
x✝ : a ∣ b
c : α
hc : b = a * c
⊢ Associates.mk (a * c) = Associates.mk a * Associates.mk c

Next tactic:
rfl
instance instCommMonoidWithZero : CommMonoidWithZero (Associates α) where
    zero_mul := by
      

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
⊢ ∀ (a : Associates α), 0 * a = 0

Next tactic:
rintro ⟨a⟩
instance instCommMonoidWithZero : CommMonoidWithZero (Associates α) where
    zero_mul := by
      rintro ⟨a⟩
      

Proof state:
case mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a✝ : Associates α
a : α
⊢ 0 * Quot.mk Setoid.r a = 0

Next tactic:
show Associates.mk (0 * a) = Associates.mk 0
instance instCommMonoidWithZero : CommMonoidWithZero (Associates α) where
    zero_mul := by
      rintro ⟨a⟩
      show Associates.mk (0 * a) = Associates.mk 0
      

Proof state:
case mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a✝ : Associates α
a : α
⊢ Associates.mk (0 * a) = Associates.mk 0

Next tactic:
rw [zero_mul]
instance instCommMonoidWithZero : CommMonoidWithZero (Associates α) where
    zero_mul := by
      rintro ⟨a⟩
      show Associates.mk (0 * a) = Associates.mk 0
      rw [zero_mul]
    mul_zero := by
      

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
⊢ ∀ (a : Associates α), a * 0 = 0

Next tactic:
rintro ⟨a⟩
instance instCommMonoidWithZero : CommMonoidWithZero (Associates α) where
    zero_mul := by
      rintro ⟨a⟩
      show Associates.mk (0 * a) = Associates.mk 0
      rw [zero_mul]
    mul_zero := by
      rintro ⟨a⟩
      

Proof state:
case mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a✝ : Associates α
a : α
⊢ Quot.mk Setoid.r a * 0 = 0

Next tactic:
show Associates.mk (a * 0) = Associates.mk 0
instance instCommMonoidWithZero : CommMonoidWithZero (Associates α) where
    zero_mul := by
      rintro ⟨a⟩
      show Associates.mk (0 * a) = Associates.mk 0
      rw [zero_mul]
    mul_zero := by
      rintro ⟨a⟩
      show Associates.mk (a * 0) = Associates.mk 0
      

Proof state:
case mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a✝ : Associates α
a : α
⊢ Associates.mk (a * 0) = Associates.mk 0

Next tactic:
rw [mul_zero]
theorem prime_mk (p : α) : Prime (Associates.mk p) ↔ Prime p := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
⊢ Prime (Associates.mk p) ↔ Prime p

Next tactic:
rw [Prime, _root_.Prime, forall_associated]
theorem prime_mk (p : α) : Prime (Associates.mk p) ↔ Prime p := by
  rw [Prime, _root_.Prime, forall_associated]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
⊢ (Associates.mk p ≠ 0 ∧
      ¬IsUnit (Associates.mk p) ∧
        ∀ (a : α) (b : Associates α),
          Associates.mk p ∣ Associates.mk a * b → Associates.mk p ∣ Associates.mk a ∨ Associates.mk p ∣ b) ↔
    p ≠ 0 ∧ ¬IsUnit p ∧ ∀ (a b : α), p ∣ a * b → p ∣ a ∨ p ∣ b

Next tactic:
trans
theorem prime_mk (p : α) : Prime (Associates.mk p) ↔ Prime p := by
  rw [Prime, _root_.Prime, forall_associated]
  trans
  · 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
⊢ (Associates.mk p ≠ 0 ∧
      ¬IsUnit (Associates.mk p) ∧
        ∀ (a : α) (b : Associates α),
          Associates.mk p ∣ Associates.mk a * b → Associates.mk p ∣ Associates.mk a ∨ Associates.mk p ∣ b) ↔
    ?m.226282

Next tactic:
apply and_congr
theorem prime_mk (p : α) : Prime (Associates.mk p) ↔ Prime p := by
  rw [Prime, _root_.Prime, forall_associated]
  trans
  · apply and_congr
    

Proof state:
case h₁
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
⊢ Associates.mk p ≠ 0 ↔ ?c
case h₂
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
⊢ (¬IsUnit (Associates.mk p) ∧
      ∀ (a : α) (b : Associates α),
        Associates.mk p ∣ Associates.mk a * b → Associates.mk p ∣ Associates.mk a ∨ Associates.mk p ∣ b) ↔
    ?d
case c
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
⊢ Prop
case d α : Type u_1 β : Type u_2 γ : Type u_3 δ : Type u_4 inst✝ : CommMonoidWithZero α p : α ⊢ Prop

Next tactic:
rfl
theorem prime_mk (p : α) : Prime (Associates.mk p) ↔ Prime p := by
  rw [Prime, _root_.Prime, forall_associated]
  trans
  · apply and_congr
    rfl
    

Proof state:
case h₂
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
⊢ (¬IsUnit (Associates.mk p) ∧
      ∀ (a : α) (b : Associates α),
        Associates.mk p ∣ Associates.mk a * b → Associates.mk p ∣ Associates.mk a ∨ Associates.mk p ∣ b) ↔
    ?d
case d α : Type u_1 β : Type u_2 γ : Type u_3 δ : Type u_4 inst✝ : CommMonoidWithZero α p : α ⊢ Prop

Next tactic:
apply and_congr
theorem prime_mk (p : α) : Prime (Associates.mk p) ↔ Prime p := by
  rw [Prime, _root_.Prime, forall_associated]
  trans
  · apply and_congr
    rfl
    apply and_congr
    

Proof state:
case h₂.h₁
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
⊢ ¬IsUnit (Associates.mk p) ↔ ?h₂.c
case h₂.h₂
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
⊢ (∀ (a : α) (b : Associates α),
      Associates.mk p ∣ Associates.mk a * b → Associates.mk p ∣ Associates.mk a ∨ Associates.mk p ∣ b) ↔
    ?h₂.d
case h₂.c
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
⊢ Prop
case h₂.d α : Type u_1 β : Type u_2 γ : Type u_3 δ : Type u_4 inst✝ : CommMonoidWithZero α p : α ⊢ Prop

Next tactic:
rfl
theorem prime_mk (p : α) : Prime (Associates.mk p) ↔ Prime p := by
  rw [Prime, _root_.Prime, forall_associated]
  trans
  · apply and_congr
    rfl
    apply and_congr
    rfl
    

Proof state:
case h₂.h₂
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
⊢ (∀ (a : α) (b : Associates α),
      Associates.mk p ∣ Associates.mk a * b → Associates.mk p ∣ Associates.mk a ∨ Associates.mk p ∣ b) ↔
    ?h₂.d
case h₂.d α : Type u_1 β : Type u_2 γ : Type u_3 δ : Type u_4 inst✝ : CommMonoidWithZero α p : α ⊢ Prop

Next tactic:
apply forall_congr'
theorem prime_mk (p : α) : Prime (Associates.mk p) ↔ Prime p := by
  rw [Prime, _root_.Prime, forall_associated]
  trans
  · apply and_congr
    rfl
    apply and_congr
    rfl
    apply forall_congr'
    

Proof state:
case h₂.h₂.h
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
⊢ ∀ (a : α),
    (∀ (b : Associates α),
        Associates.mk p ∣ Associates.mk a * b → Associates.mk p ∣ Associates.mk a ∨ Associates.mk p ∣ b) ↔
      ?h₂.h₂.q a
case h₂.h₂.q α : Type u_1 β : Type u_2 γ : Type u_3 δ : Type u_4 inst✝ : CommMonoidWithZero α p : α ⊢ α → Prop

Next tactic:
intro a
theorem prime_mk (p : α) : Prime (Associates.mk p) ↔ Prime p := by
  rw [Prime, _root_.Prime, forall_associated]
  trans
  · apply and_congr
    rfl
    apply and_congr
    rfl
    apply forall_congr'
    intro a
    

Proof state:
case h₂.h₂.h
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p a : α
⊢ (∀ (b : Associates α),
      Associates.mk p ∣ Associates.mk a * b → Associates.mk p ∣ Associates.mk a ∨ Associates.mk p ∣ b) ↔
    ?h₂.h₂.q a
case h₂.h₂.q α : Type u_1 β : Type u_2 γ : Type u_3 δ : Type u_4 inst✝ : CommMonoidWithZero α p : α ⊢ α → Prop

Next tactic:
exact forall_associated
theorem prime_mk (p : α) : Prime (Associates.mk p) ↔ Prime p := by
  rw [Prime, _root_.Prime, forall_associated]
  trans
  · apply and_congr
    rfl
    apply and_congr
    rfl
    apply forall_congr'
    intro a
    exact forall_associated
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
⊢ (Associates.mk p ≠ 0 ∧
      ¬IsUnit (Associates.mk p) ∧
        ∀ (a a_1 : α),
          Associates.mk p ∣ Associates.mk a * Associates.mk a_1 →
            Associates.mk p ∣ Associates.mk a ∨ Associates.mk p ∣ Associates.mk a_1) ↔
    p ≠ 0 ∧ ¬IsUnit p ∧ ∀ (a b : α), p ∣ a * b → p ∣ a ∨ p ∣ b

Next tactic:
apply and_congr mk_ne_zero
theorem prime_mk (p : α) : Prime (Associates.mk p) ↔ Prime p := by
  rw [Prime, _root_.Prime, forall_associated]
  trans
  · apply and_congr
    rfl
    apply and_congr
    rfl
    apply forall_congr'
    intro a
    exact forall_associated
  apply and_congr mk_ne_zero
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
⊢ (¬IsUnit (Associates.mk p) ∧
      ∀ (a a_1 : α),
        Associates.mk p ∣ Associates.mk a * Associates.mk a_1 →
          Associates.mk p ∣ Associates.mk a ∨ Associates.mk p ∣ Associates.mk a_1) ↔
    ¬IsUnit p ∧ ∀ (a b : α), p ∣ a * b → p ∣ a ∨ p ∣ b

Next tactic:
apply and_congr
theorem prime_mk (p : α) : Prime (Associates.mk p) ↔ Prime p := by
  rw [Prime, _root_.Prime, forall_associated]
  trans
  · apply and_congr
    rfl
    apply and_congr
    rfl
    apply forall_congr'
    intro a
    exact forall_associated
  apply and_congr mk_ne_zero
  apply and_congr
  · 

Proof state:
case h₁
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
⊢ ¬IsUnit (Associates.mk p) ↔ ¬IsUnit p

Next tactic:
rw [isUnit_mk]
theorem prime_mk (p : α) : Prime (Associates.mk p) ↔ Prime p := by
  rw [Prime, _root_.Prime, forall_associated]
  trans
  · apply and_congr
    rfl
    apply and_congr
    rfl
    apply forall_congr'
    intro a
    exact forall_associated
  apply and_congr mk_ne_zero
  apply and_congr
  · rw [isUnit_mk]
  

Proof state:
case h₂
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
⊢ (∀ (a a_1 : α),
      Associates.mk p ∣ Associates.mk a * Associates.mk a_1 →
        Associates.mk p ∣ Associates.mk a ∨ Associates.mk p ∣ Associates.mk a_1) ↔
    ∀ (a b : α), p ∣ a * b → p ∣ a ∨ p ∣ b

Next tactic:
refine' forall₂_congr fun a b => _
theorem prime_mk (p : α) : Prime (Associates.mk p) ↔ Prime p := by
  rw [Prime, _root_.Prime, forall_associated]
  trans
  · apply and_congr
    rfl
    apply and_congr
    rfl
    apply forall_congr'
    intro a
    exact forall_associated
  apply and_congr mk_ne_zero
  apply and_congr
  · rw [isUnit_mk]
  refine' forall₂_congr fun a b => _
  

Proof state:
case h₂
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p a b : α
⊢ Associates.mk p ∣ Associates.mk a * Associates.mk b →
      Associates.mk p ∣ Associates.mk a ∨ Associates.mk p ∣ Associates.mk b ↔
    p ∣ a * b → p ∣ a ∨ p ∣ b

Next tactic:
rw [mk_mul_mk, mk_dvd_mk, mk_dvd_mk, mk_dvd_mk]
theorem irreducible_mk (a : α) : Irreducible (Associates.mk a) ↔ Irreducible a := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a : α
⊢ Irreducible (Associates.mk a) ↔ Irreducible a

Next tactic:
simp only [irreducible_iff, isUnit_mk]
theorem irreducible_mk (a : α) : Irreducible (Associates.mk a) ↔ Irreducible a := by
  simp only [irreducible_iff, isUnit_mk]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a : α
⊢ (¬IsUnit a ∧ ∀ (a_1 b : Associates α), Associates.mk a = a_1 * b → IsUnit a_1 ∨ IsUnit b) ↔
    ¬IsUnit a ∧ ∀ (a_1 b : α), a = a_1 * b → IsUnit a_1 ∨ IsUnit b

Next tactic:
apply and_congr Iff.rfl
theorem irreducible_mk (a : α) : Irreducible (Associates.mk a) ↔ Irreducible a := by
  simp only [irreducible_iff, isUnit_mk]
  apply and_congr Iff.rfl
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a : α
⊢ (∀ (a_1 b : Associates α), Associates.mk a = a_1 * b → IsUnit a_1 ∨ IsUnit b) ↔
    ∀ (a_1 b : α), a = a_1 * b → IsUnit a_1 ∨ IsUnit b

Next tactic:
constructor
theorem irreducible_mk (a : α) : Irreducible (Associates.mk a) ↔ Irreducible a := by
  simp only [irreducible_iff, isUnit_mk]
  apply and_congr Iff.rfl
  constructor
  · 

Proof state:
case mp
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a : α
⊢ (∀ (a_1 b : Associates α), Associates.mk a = a_1 * b → IsUnit a_1 ∨ IsUnit b) →
    ∀ (a_2 b : α), a = a_2 * b → IsUnit a_2 ∨ IsUnit b

Next tactic:
rintro h x y rfl
theorem irreducible_mk (a : α) : Irreducible (Associates.mk a) ↔ Irreducible a := by
  simp only [irreducible_iff, isUnit_mk]
  apply and_congr Iff.rfl
  constructor
  · rintro h x y rfl
    

Proof state:
case mp
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
x y : α
h : ∀ (a b : Associates α), Associates.mk (x * y) = a * b → IsUnit a ∨ IsUnit b
⊢ IsUnit x ∨ IsUnit y

Next tactic:
simpa [isUnit_mk] using h (Associates.mk x) (Associates.mk y) rfl
theorem irreducible_mk (a : α) : Irreducible (Associates.mk a) ↔ Irreducible a := by
  simp only [irreducible_iff, isUnit_mk]
  apply and_congr Iff.rfl
  constructor
  · rintro h x y rfl
    simpa [isUnit_mk] using h (Associates.mk x) (Associates.mk y) rfl
  · 

Proof state:
case mpr
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a : α
⊢ (∀ (a_1 b : α), a = a_1 * b → IsUnit a_1 ∨ IsUnit b) →
    ∀ (a_2 b : Associates α), Associates.mk a = a_2 * b → IsUnit a_2 ∨ IsUnit b

Next tactic:
intro h x y
theorem irreducible_mk (a : α) : Irreducible (Associates.mk a) ↔ Irreducible a := by
  simp only [irreducible_iff, isUnit_mk]
  apply and_congr Iff.rfl
  constructor
  · rintro h x y rfl
    simpa [isUnit_mk] using h (Associates.mk x) (Associates.mk y) rfl
  · intro h x y
    

Proof state:
case mpr
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a : α
h : ∀ (a_1 b : α), a = a_1 * b → IsUnit a_1 ∨ IsUnit b
x y : Associates α
⊢ Associates.mk a = x * y → IsUnit x ∨ IsUnit y

Next tactic:
refine' Quotient.inductionOn₂ x y fun x y a_eq => _
theorem irreducible_mk (a : α) : Irreducible (Associates.mk a) ↔ Irreducible a := by
  simp only [irreducible_iff, isUnit_mk]
  apply and_congr Iff.rfl
  constructor
  · rintro h x y rfl
    simpa [isUnit_mk] using h (Associates.mk x) (Associates.mk y) rfl
  · intro h x y
    refine' Quotient.inductionOn₂ x y fun x y a_eq => _
    

Proof state:
case mpr
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a : α
h : ∀ (a_1 b : α), a = a_1 * b → IsUnit a_1 ∨ IsUnit b
x✝ y✝ : Associates α
x y : α
a_eq : Associates.mk a = ⟦x⟧ * ⟦y⟧
⊢ IsUnit ⟦x⟧ ∨ IsUnit ⟦y⟧

Next tactic:
rcases Quotient.exact a_eq.symm with ⟨u, a_eq⟩
theorem irreducible_mk (a : α) : Irreducible (Associates.mk a) ↔ Irreducible a := by
  simp only [irreducible_iff, isUnit_mk]
  apply and_congr Iff.rfl
  constructor
  · rintro h x y rfl
    simpa [isUnit_mk] using h (Associates.mk x) (Associates.mk y) rfl
  · intro h x y
    refine' Quotient.inductionOn₂ x y fun x y a_eq => _
    rcases Quotient.exact a_eq.symm with ⟨u, a_eq⟩
    

Proof state:
case mpr.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a : α
h : ∀ (a_1 b : α), a = a_1 * b → IsUnit a_1 ∨ IsUnit b
x✝ y✝ : Associates α
x y : α
a_eq✝ : Associates.mk a = ⟦x⟧ * ⟦y⟧
u : αˣ
a_eq : x * y * ↑u = a
⊢ IsUnit ⟦x⟧ ∨ IsUnit ⟦y⟧

Next tactic:
rw [mul_assoc] at a_eq
theorem irreducible_mk (a : α) : Irreducible (Associates.mk a) ↔ Irreducible a := by
  simp only [irreducible_iff, isUnit_mk]
  apply and_congr Iff.rfl
  constructor
  · rintro h x y rfl
    simpa [isUnit_mk] using h (Associates.mk x) (Associates.mk y) rfl
  · intro h x y
    refine' Quotient.inductionOn₂ x y fun x y a_eq => _
    rcases Quotient.exact a_eq.symm with ⟨u, a_eq⟩
    rw [mul_assoc] at a_eq
    

Proof state:
case mpr.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a : α
h : ∀ (a_1 b : α), a = a_1 * b → IsUnit a_1 ∨ IsUnit b
x✝ y✝ : Associates α
x y : α
a_eq✝ : Associates.mk a = ⟦x⟧ * ⟦y⟧
u : αˣ
a_eq : x * (y * ↑u) = a
⊢ IsUnit ⟦x⟧ ∨ IsUnit ⟦y⟧

Next tactic:
show IsUnit (Associates.mk x) ∨ IsUnit (Associates.mk y)
theorem irreducible_mk (a : α) : Irreducible (Associates.mk a) ↔ Irreducible a := by
  simp only [irreducible_iff, isUnit_mk]
  apply and_congr Iff.rfl
  constructor
  · rintro h x y rfl
    simpa [isUnit_mk] using h (Associates.mk x) (Associates.mk y) rfl
  · intro h x y
    refine' Quotient.inductionOn₂ x y fun x y a_eq => _
    rcases Quotient.exact a_eq.symm with ⟨u, a_eq⟩
    rw [mul_assoc] at a_eq
    show IsUnit (Associates.mk x) ∨ IsUnit (Associates.mk y)
    

Proof state:
case mpr.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a : α
h : ∀ (a_1 b : α), a = a_1 * b → IsUnit a_1 ∨ IsUnit b
x✝ y✝ : Associates α
x y : α
a_eq✝ : Associates.mk a = ⟦x⟧ * ⟦y⟧
u : αˣ
a_eq : x * (y * ↑u) = a
⊢ IsUnit (Associates.mk x) ∨ IsUnit (Associates.mk y)

Next tactic:
simpa [isUnit_mk] using h _ _ a_eq.symm
theorem mk_dvdNotUnit_mk_iff {a b : α} :
    DvdNotUnit (Associates.mk a) (Associates.mk b) ↔ DvdNotUnit a b := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a b : α
⊢ DvdNotUnit (Associates.mk a) (Associates.mk b) ↔ DvdNotUnit a b

Next tactic:
rw [DvdNotUnit, DvdNotUnit, mk_ne_zero]
theorem mk_dvdNotUnit_mk_iff {a b : α} :
    DvdNotUnit (Associates.mk a) (Associates.mk b) ↔ DvdNotUnit a b := by
  rw [DvdNotUnit, DvdNotUnit, mk_ne_zero]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a b : α
⊢ (a ≠ 0 ∧ ∃ x, ¬IsUnit x ∧ Associates.mk b = Associates.mk a * x) ↔ a ≠ 0 ∧ ∃ x, ¬IsUnit x ∧ b = a * x

Next tactic:
apply and_congr_right
theorem mk_dvdNotUnit_mk_iff {a b : α} :
    DvdNotUnit (Associates.mk a) (Associates.mk b) ↔ DvdNotUnit a b := by
  rw [DvdNotUnit, DvdNotUnit, mk_ne_zero]
  apply and_congr_right; 

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a b : α
⊢ a ≠ 0 → ((∃ x, ¬IsUnit x ∧ Associates.mk b = Associates.mk a * x) ↔ ∃ x, ¬IsUnit x ∧ b = a * x)

Next tactic:
intro
theorem mk_dvdNotUnit_mk_iff {a b : α} :
    DvdNotUnit (Associates.mk a) (Associates.mk b) ↔ DvdNotUnit a b := by
  rw [DvdNotUnit, DvdNotUnit, mk_ne_zero]
  apply and_congr_right; intro
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a b : α
a✝ : a ≠ 0
⊢ (∃ x, ¬IsUnit x ∧ Associates.mk b = Associates.mk a * x) ↔ ∃ x, ¬IsUnit x ∧ b = a * x

Next tactic:
constructor
theorem mk_dvdNotUnit_mk_iff {a b : α} :
    DvdNotUnit (Associates.mk a) (Associates.mk b) ↔ DvdNotUnit a b := by
  rw [DvdNotUnit, DvdNotUnit, mk_ne_zero]
  apply and_congr_right; intro
  constructor
  · 

Proof state:
case h.mp
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
a b : α
a✝ : a ≠ 0
⊢ (∃ x, ¬IsUnit x ∧ Associates.mk b = Associates.mk a * x) → ∃ x, ¬IsUnit x ∧ b = a * x

Next tactic:
contrapose!