l3lab/ntp-mathlib huggingface dataset:
/-- If `f` maps `p ^ i` to `(f p) ^ i` for primes `p`, and `f`
is multiplicative on coprime elements, then `f` is multiplicative everywhere. -/
theorem multiplicative_of_coprime (f : α → β) (a b : α) (h0 : f 0 = 0)
    (h1 : ∀ {x y}, IsUnit y → f (x * y) = f x * f y)
    (hpr : ∀ {p} (i : ℕ), Prime p → f (p ^ i) = f p ^ i)
    (hcp : ∀ {x y}, (∀ p, p ∣ x → p ∣ y → IsUnit p) → f (x * y) = f x * f y) :
    f (a * b) = f a * f b := by
  letI := Classical.decEq α
  by_cases ha0 : a = 0
  · rw [ha0, zero_mul, h0, zero_mul]
  by_cases hb0 : b = 0
  · rw [hb0, mul_zero, h0, mul_zero]
  by_cases hf1 : f 1 = 0
  · calc
      f (a * b) = f (a * b * 1) := by rw [mul_one]
      _ = 0 := by simp only [h1 isUnit_one, hf1, mul_zero]
      _ = f a * f (b * 1) := by simp only [h1 isUnit_one, hf1, mul_zero]
      _ = f a * f b := by rw [mul_one]
  haveI : Nontrivial α := ⟨⟨_, _, ha0⟩⟩
  letI : NormalizationMonoid α := UniqueFactorizationMonoid.normalizationMonoid
  suffices
      f (∏ p in (normalizedFactors a).toFinset ∪ (normalizedFactors b).toFinset,
        p ^ ((normalizedFactors a).count p + (normalizedFactors b).count p)) =
      f (∏ p in (normalizedFactors a).toFinset ∪ (normalizedFactors b).toFinset,
        p ^ (normalizedFactors a).count p) *
      f (∏ p : α in (normalizedFactors a).toFinset ∪ (normalizedFactors b).toFinset,
        p ^ (normalizedFactors b).count p) by
    obtain ⟨ua, a_eq⟩ := normalizedFactors_prod ha0
    obtain ⟨ub, b_eq⟩ := normalizedFactors_prod hb0
    rw [← a_eq, ← b_eq, mul_right_comm (Multiset.prod (normalizedFactors a)) ua
        (Multiset.prod (normalizedFactors b) * ub), h1 ua.isUnit, h1 ub.isUnit, h1 ua.isUnit, ←
      mul_assoc, h1 ub.isUnit, mul_right_comm _ (f ua), ← mul_assoc]
    congr
    rw [← (normalizedFactors a).map_id, ← (normalizedFactors b).map_id,
      Finset.prod_multiset_map_count, Finset.prod_multiset_map_count,
      Finset.prod_subset (Finset.subset_union_left _ (normalizedFactors b).toFinset),
      Finset.prod_subset (Finset.subset_union_right _ (normalizedFactors b).toFinset), ←
      Finset.prod_mul_distrib]
    simp_rw [id.def, ← pow_add, this]
    all_goals simp only [Multiset.mem_toFinset]
    · intro p _ hpb
      simp [hpb]
    · intro p _ hpa
      simp [hpa]
  refine' multiplicative_prime_power _ _ _ _ _ @h1 @hpr @hcp
  all_goals simp only [Multiset.mem_toFinset, Finset.mem_union]
  · rintro p (hpa | hpb) <;> 

Proof state:
case neg.refine'_1.inr
α : Type u_1
R : Type u_2
inst✝⁴ : CancelCommMonoidWithZero R
inst✝³ : UniqueFactorizationMonoid R
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : UniqueFactorizationMonoid α
β : Type u_3
inst✝ : CancelCommMonoidWithZero β
f : α → β
a b : α
h0 : f 0 = 0
h1 : ∀ {x y : α}, IsUnit y → f (x * y) = f x * f y
hpr : ∀ {p : α} (i : ℕ), Prime p → f (p ^ i) = f p ^ i
hcp : ∀ {x y : α}, (∀ (p : α), p ∣ x → p ∣ y → IsUnit p) → f (x * y) = f x * f y
this✝¹ : DecidableEq α := Classical.decEq α
ha0 : ¬a = 0
hb0 : ¬b = 0
hf1 : ¬f 1 = 0
this✝ : Nontrivial α
this : NormalizationMonoid α := UniqueFactorizationMonoid.normalizationMonoid
p : α
hpb : p ∈ normalizedFactors b
⊢ Prime p

Next tactic:
apply prime_of_normalized_factor
theorem FactorSet.coe_add {a b : Multiset { a : Associates α // Irreducible a }} :
    (↑(a + b) : FactorSet α) = a + b := by 

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
a b : Multiset { a // Irreducible a }
⊢ ↑(a + b) = ↑a + ↑b

Next tactic:
norm_cast
theorem FactorSet.sup_add_inf_eq_add [DecidableEq (Associates α)] :
    ∀ a b : FactorSet α, a ⊔ b + a ⊓ b = a + b
  | none, b => show ⊤ ⊔ b + ⊤ ⊓ b = ⊤ + b by 

Proof state:
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq (Associates α)
b : FactorSet α
⊢ ⊤ ⊔ b + ⊤ ⊓ b = ⊤ + b

Next tactic:
simp
theorem FactorSet.sup_add_inf_eq_add [DecidableEq (Associates α)] :
    ∀ a b : FactorSet α, a ⊔ b + a ⊓ b = a + b
  | none, b => show ⊤ ⊔ b + ⊤ ⊓ b = ⊤ + b by simp
  | a, none => show a ⊔ ⊤ + a ⊓ ⊤ = a + ⊤ by 

Proof state:
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq (Associates α)
a : FactorSet α
⊢ a ⊔ ⊤ + a ⊓ ⊤ = a + ⊤

Next tactic:
simp
theorem FactorSet.sup_add_inf_eq_add [DecidableEq (Associates α)] :
    ∀ a b : FactorSet α, a ⊔ b + a ⊓ b = a + b
  | none, b => show ⊤ ⊔ b + ⊤ ⊓ b = ⊤ + b by simp
  | a, none => show a ⊔ ⊤ + a ⊓ ⊤ = a + ⊤ by simp
  | some a, some b =>
    show (a : FactorSet α) ⊔ b + (a : FactorSet α) ⊓ b = a + b by
      

Proof state:
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq (Associates α)
a b : Multiset { a // Irreducible a }
⊢ ↑a ⊔ ↑b + ↑a ⊓ ↑b = ↑a + ↑b

Next tactic:
rw [← WithTop.coe_sup, ← WithTop.coe_inf, ← WithTop.coe_add, ← WithTop.coe_add,
        WithTop.coe_eq_coe]
theorem FactorSet.sup_add_inf_eq_add [DecidableEq (Associates α)] :
    ∀ a b : FactorSet α, a ⊔ b + a ⊓ b = a + b
  | none, b => show ⊤ ⊔ b + ⊤ ⊓ b = ⊤ + b by simp
  | a, none => show a ⊔ ⊤ + a ⊓ ⊤ = a + ⊤ by simp
  | some a, some b =>
    show (a : FactorSet α) ⊔ b + (a : FactorSet α) ⊓ b = a + b by
      rw [← WithTop.coe_sup, ← WithTop.coe_inf, ← WithTop.coe_add, ← WithTop.coe_add,
        WithTop.coe_eq_coe]
      

Proof state:
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : DecidableEq (Associates α)
a b : Multiset { a // Irreducible a }
⊢ a ⊔ b + a ⊓ b = a + b

Next tactic:
exact Multiset.union_add_inter _ _
@[simp]
theorem prod_add : ∀ a b : FactorSet α, (a + b).prod = a.prod * b.prod
  | none, b => show (⊤ + b).prod = (⊤ : FactorSet α).prod * b.prod by 

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
b : FactorSet α
⊢ FactorSet.prod (⊤ + b) = FactorSet.prod ⊤ * FactorSet.prod b

Next tactic:
simp
@[simp]
theorem prod_add : ∀ a b : FactorSet α, (a + b).prod = a.prod * b.prod
  | none, b => show (⊤ + b).prod = (⊤ : FactorSet α).prod * b.prod by simp
  | a, none => show (a + ⊤).prod = a.prod * (⊤ : FactorSet α).prod by 

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
a : FactorSet α
⊢ FactorSet.prod (a + ⊤) = FactorSet.prod a * FactorSet.prod ⊤

Next tactic:
simp
@[simp]
theorem prod_add : ∀ a b : FactorSet α, (a + b).prod = a.prod * b.prod
  | none, b => show (⊤ + b).prod = (⊤ : FactorSet α).prod * b.prod by simp
  | a, none => show (a + ⊤).prod = a.prod * (⊤ : FactorSet α).prod by simp
  | some a, some b =>
    show (↑a + ↑b : FactorSet α).prod =
        FactorSet.prod (↑a : FactorSet α) * FactorSet.prod (↑b : FactorSet α) by
      

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
a b : Multiset { a // Irreducible a }
⊢ FactorSet.prod (↑a + ↑b) = FactorSet.prod ↑a * FactorSet.prod ↑b

Next tactic:
rw [← FactorSet.coe_add, prod_coe, prod_coe, prod_coe, Multiset.map_add, Multiset.prod_add]
theorem prod_mono : ∀ {a b : FactorSet α}, a ≤ b → a.prod ≤ b.prod
  | none, b, h => by
    

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
b : FactorSet α
h : none ≤ b
⊢ FactorSet.prod none ≤ FactorSet.prod b

Next tactic:
have : b = ⊤ := top_unique h
theorem prod_mono : ∀ {a b : FactorSet α}, a ≤ b → a.prod ≤ b.prod
  | none, b, h => by
    have : b = ⊤ := top_unique h
    

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
b : FactorSet α
h : none ≤ b
this : b = ⊤
⊢ FactorSet.prod none ≤ FactorSet.prod b

Next tactic:
rw [this, prod_top]
theorem prod_mono : ∀ {a b : FactorSet α}, a ≤ b → a.prod ≤ b.prod
  | none, b, h => by
    have : b = ⊤ := top_unique h
    rw [this, prod_top]; 

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
b : FactorSet α
h : none ≤ b
this : b = ⊤
⊢ FactorSet.prod none ≤ 0

Next tactic:
exact le_rfl
theorem prod_mono : ∀ {a b : FactorSet α}, a ≤ b → a.prod ≤ b.prod
  | none, b, h => by
    have : b = ⊤ := top_unique h
    rw [this, prod_top]; exact le_rfl
  | a, none, _ => show a.prod ≤ (⊤ : FactorSet α).prod by 

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
a : FactorSet α
x✝ : a ≤ none
⊢ FactorSet.prod a ≤ FactorSet.prod ⊤

Next tactic:
simp
theorem prod_mono : ∀ {a b : FactorSet α}, a ≤ b → a.prod ≤ b.prod
  | none, b, h => by
    have : b = ⊤ := top_unique h
    rw [this, prod_top]; exact le_rfl
  | a, none, _ => show a.prod ≤ (⊤ : FactorSet α).prod by simp; 

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
a : FactorSet α
x✝ : a ≤ none
⊢ FactorSet.prod a ≤ 0

Next tactic:
exact le_top
theorem FactorSet.prod_eq_zero_iff [Nontrivial α] (p : FactorSet α) : p.prod = 0 ↔ p = ⊤ := by
  

Proof state:
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Nontrivial α
p : FactorSet α
⊢ prod p = 0 ↔ p = ⊤

Next tactic:
induction p using WithTop.recTopCoe
theorem FactorSet.prod_eq_zero_iff [Nontrivial α] (p : FactorSet α) : p.prod = 0 ↔ p = ⊤ := by
  induction p using WithTop.recTopCoe
  · 

Proof state:
case top
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Nontrivial α
⊢ prod ⊤ = 0 ↔ ⊤ = ⊤

Next tactic:
simp only [iff_self_iff, eq_self_iff_true, Associates.prod_top]
theorem FactorSet.prod_eq_zero_iff [Nontrivial α] (p : FactorSet α) : p.prod = 0 ↔ p = ⊤ := by
  induction p using WithTop.recTopCoe
  · simp only [iff_self_iff, eq_self_iff_true, Associates.prod_top]
  · 

Proof state:
case coe
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Nontrivial α
a✝ : Multiset { a // Irreducible a }
⊢ prod ↑a✝ = 0 ↔ ↑a✝ = ⊤

Next tactic:
rw [prod_coe, Multiset.prod_eq_zero_iff, Multiset.mem_map, eq_false WithTop.coe_ne_top,
      iff_false_iff, not_exists]
theorem FactorSet.prod_eq_zero_iff [Nontrivial α] (p : FactorSet α) : p.prod = 0 ↔ p = ⊤ := by
  induction p using WithTop.recTopCoe
  · simp only [iff_self_iff, eq_self_iff_true, Associates.prod_top]
  · rw [prod_coe, Multiset.prod_eq_zero_iff, Multiset.mem_map, eq_false WithTop.coe_ne_top,
      iff_false_iff, not_exists]
    

Proof state:
case coe
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Nontrivial α
a✝ : Multiset { a // Irreducible a }
⊢ ∀ (x : { a // Irreducible a }), ¬(x ∈ a✝ ∧ ↑x = 0)

Next tactic:
exact fun a => not_and_of_not_right _ a.prop.ne_zero
@[simp]
theorem count_some [DecidableEq (Associates α)] {p : Associates α} (hp : Irreducible p)
    (s : Multiset _) : count p (some s) = s.count ⟨p, hp⟩ := by
  

Proof state:
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
inst✝ : DecidableEq (Associates α)
p : Associates α
hp : Irreducible p
s : Multiset { a // Irreducible a }
⊢ count p (some s) = Multiset.count { val := p, property := hp } s

Next tactic:
dsimp only [count]
@[simp]
theorem count_some [DecidableEq (Associates α)] {p : Associates α} (hp : Irreducible p)
    (s : Multiset _) : count p (some s) = s.count ⟨p, hp⟩ := by
  dsimp only [count]
  

Proof state:
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
inst✝ : DecidableEq (Associates α)
p : Associates α
hp : Irreducible p
s : Multiset { a // Irreducible a }
⊢ dite (Irreducible p) (fun hp => bcount { val := p, property := hp }) (fun hp => 0) (some s) =
    Multiset.count { val := p, property := hp } s

Next tactic:
split_ifs
@[simp]
theorem count_some [DecidableEq (Associates α)] {p : Associates α} (hp : Irreducible p)
    (s : Multiset _) : count p (some s) = s.count ⟨p, hp⟩ := by
  dsimp only [count]
  split_ifs
  

Proof state:
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
inst✝ : DecidableEq (Associates α)
p : Associates α
hp : Irreducible p
s : Multiset { a // Irreducible a }
⊢ bcount { val := p, property := hp } (some s) = Multiset.count { val := p, property := hp } s

Next tactic:
rfl
@[simp]
theorem count_zero [DecidableEq (Associates α)] {p : Associates α} (hp : Irreducible p) :
    count p (0 : FactorSet α) = 0 := by
  

Proof state:
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
inst✝ : DecidableEq (Associates α)
p : Associates α
hp : Irreducible p
⊢ count p 0 = 0

Next tactic:
dsimp only [count]
@[simp]
theorem count_zero [DecidableEq (Associates α)] {p : Associates α} (hp : Irreducible p) :
    count p (0 : FactorSet α) = 0 := by
  dsimp only [count]
  

Proof state:
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
inst✝ : DecidableEq (Associates α)
p : Associates α
hp : Irreducible p
⊢ dite (Irreducible p) (fun hp => bcount { val := p, property := hp }) (fun hp => 0) 0 = 0

Next tactic:
split_ifs
@[simp]
theorem count_zero [DecidableEq (Associates α)] {p : Associates α} (hp : Irreducible p) :
    count p (0 : FactorSet α) = 0 := by
  dsimp only [count]
  split_ifs
  

Proof state:
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
inst✝ : DecidableEq (Associates α)
p : Associates α
hp : Irreducible p
⊢ bcount { val := p, property := hp } 0 = 0

Next tactic:
rfl
theorem mem_factorSet_top {p : Associates α} {hp : Irreducible p} : p ∈ (⊤ : FactorSet α) := by
  

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
p : Associates α
hp : Irreducible p
⊢ p ∈ ⊤

Next tactic:
dsimp only [Membership.mem]
theorem mem_factorSet_top {p : Associates α} {hp : Irreducible p} : p ∈ (⊤ : FactorSet α) := by
  dsimp only [Membership.mem]; 

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
p : Associates α
hp : Irreducible p
⊢ FactorSetMem p ⊤

Next tactic:
dsimp only [FactorSetMem]
theorem mem_factorSet_top {p : Associates α} {hp : Irreducible p} : p ∈ (⊤ : FactorSet α) := by
  dsimp only [Membership.mem]; dsimp only [FactorSetMem]; 

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
p : Associates α
hp : Irreducible p
⊢ if hp : Irreducible p then BfactorSetMem { val := p, property := hp } ⊤ else False

Next tactic:
split_ifs
theorem mem_factorSet_top {p : Associates α} {hp : Irreducible p} : p ∈ (⊤ : FactorSet α) := by
  dsimp only [Membership.mem]; dsimp only [FactorSetMem]; split_ifs; 

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
p : Associates α
hp : Irreducible p
⊢ BfactorSetMem { val := p, property := hp } ⊤

Next tactic:
exact trivial
theorem mem_factorSet_some {p : Associates α} {hp : Irreducible p}
    {l : Multiset { a : Associates α // Irreducible a }} :
    p ∈ (l : FactorSet α) ↔ Subtype.mk p hp ∈ l := by
  

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
p : Associates α
hp : Irreducible p
l : Multiset { a // Irreducible a }
⊢ p ∈ ↑l ↔ { val := p, property := hp } ∈ l

Next tactic:
dsimp only [Membership.mem]
theorem mem_factorSet_some {p : Associates α} {hp : Irreducible p}
    {l : Multiset { a : Associates α // Irreducible a }} :
    p ∈ (l : FactorSet α) ↔ Subtype.mk p hp ∈ l := by
  dsimp only [Membership.mem]; 

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
p : Associates α
hp : Irreducible p
l : Multiset { a // Irreducible a }
⊢ FactorSetMem p ↑l ↔ Mem { val := p, property := hp } l

Next tactic:
dsimp only [FactorSetMem]
theorem mem_factorSet_some {p : Associates α} {hp : Irreducible p}
    {l : Multiset { a : Associates α // Irreducible a }} :
    p ∈ (l : FactorSet α) ↔ Subtype.mk p hp ∈ l := by
  dsimp only [Membership.mem]; dsimp only [FactorSetMem]; 

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
p : Associates α
hp : Irreducible p
l : Multiset { a // Irreducible a }
⊢ (if hp : Irreducible p then BfactorSetMem { val := p, property := hp } ↑l else False) ↔
    Mem { val := p, property := hp } l

Next tactic:
split_ifs
theorem mem_factorSet_some {p : Associates α} {hp : Irreducible p}
    {l : Multiset { a : Associates α // Irreducible a }} :
    p ∈ (l : FactorSet α) ↔ Subtype.mk p hp ∈ l := by
  dsimp only [Membership.mem]; dsimp only [FactorSetMem]; split_ifs; 

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
p : Associates α
hp : Irreducible p
l : Multiset { a // Irreducible a }
⊢ BfactorSetMem { val := p, property := hp } ↑l ↔ Mem { val := p, property := hp } l

Next tactic:
rfl
theorem reducible_not_mem_factorSet {p : Associates α} (hp : ¬Irreducible p) (s : FactorSet α) :
    ¬p ∈ s := fun h : if hp : Irreducible p then BfactorSetMem ⟨p, hp⟩ s else False => by
  

Proof state:
α : Type u_1
inst✝ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
p : Associates α
hp : ¬Irreducible p
s : FactorSet α
h : if hp : Irreducible p then BfactorSetMem { val := p, property := hp } s else False
⊢ False

Next tactic:
rwa [dif_neg hp] at h
theorem unique' {p q : Multiset (Associates α)} :
    (∀ a ∈ p, Irreducible a) → (∀ a ∈ q, Irreducible a) → p.prod = q.prod → p = q := by
  

Proof state:
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
inst✝ : UniqueFactorizationMonoid α
p q : Multiset (Associates α)
⊢ (∀ a ∈ p, Irreducible a) → (∀ a ∈ q, Irreducible a) → Multiset.prod p = Multiset.prod q → p = q

Next tactic:
apply Multiset.induction_on_multiset_quot p
theorem unique' {p q : Multiset (Associates α)} :
    (∀ a ∈ p, Irreducible a) → (∀ a ∈ q, Irreducible a) → p.prod = q.prod → p = q := by
  apply Multiset.induction_on_multiset_quot p
  

Proof state:
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
inst✝ : UniqueFactorizationMonoid α
p q : Multiset (Associates α)
⊢ ∀ (s : Multiset α),
    (∀ a ∈ map (Quot.mk Setoid.r) s, Irreducible a) →
      (∀ a ∈ q, Irreducible a) →
        Multiset.prod (map (Quot.mk Setoid.r) s) = Multiset.prod q → map (Quot.mk Setoid.r) s = q

Next tactic:
apply Multiset.induction_on_multiset_quot q
theorem unique' {p q : Multiset (Associates α)} :
    (∀ a ∈ p, Irreducible a) → (∀ a ∈ q, Irreducible a) → p.prod = q.prod → p = q := by
  apply Multiset.induction_on_multiset_quot p
  apply Multiset.induction_on_multiset_quot q
  

Proof state:
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
inst✝ : UniqueFactorizationMonoid α
p q : Multiset (Associates α)
⊢ ∀ (s s_1 : Multiset α),
    (∀ a ∈ map (Quot.mk Setoid.r) s_1, Irreducible a) →
      (∀ a ∈ map (Quot.mk Setoid.r) s, Irreducible a) →
        Multiset.prod (map (Quot.mk Setoid.r) s_1) = Multiset.prod (map (Quot.mk Setoid.r) s) →
          map (Quot.mk Setoid.r) s_1 = map (Quot.mk Setoid.r) s

Next tactic:
intro s t hs ht eq
theorem unique' {p q : Multiset (Associates α)} :
    (∀ a ∈ p, Irreducible a) → (∀ a ∈ q, Irreducible a) → p.prod = q.prod → p = q := by
  apply Multiset.induction_on_multiset_quot p
  apply Multiset.induction_on_multiset_quot q
  intro s t hs ht eq
  

Proof state:
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
inst✝ : UniqueFactorizationMonoid α
p q : Multiset (Associates α)
s t : Multiset α
hs : ∀ a ∈ map (Quot.mk Setoid.r) t, Irreducible a
ht : ∀ a ∈ map (Quot.mk Setoid.r) s, Irreducible a
eq : Multiset.prod (map (Quot.mk Setoid.r) t) = Multiset.prod (map (Quot.mk Setoid.r) s)
⊢ map (Quot.mk Setoid.r) t = map (Quot.mk Setoid.r) s

Next tactic:
refine' Multiset.map_mk_eq_map_mk_of_rel (UniqueFactorizationMonoid.factors_unique _ _ _)
theorem unique' {p q : Multiset (Associates α)} :
    (∀ a ∈ p, Irreducible a) → (∀ a ∈ q, Irreducible a) → p.prod = q.prod → p = q := by
  apply Multiset.induction_on_multiset_quot p
  apply Multiset.induction_on_multiset_quot q
  intro s t hs ht eq
  refine' Multiset.map_mk_eq_map_mk_of_rel (UniqueFactorizationMonoid.factors_unique _ _ _)
  · 

Proof state:
case refine'_1
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
inst✝ : UniqueFactorizationMonoid α
p q : Multiset (Associates α)
s t : Multiset α
hs : ∀ a ∈ map (Quot.mk Setoid.r) t, Irreducible a
ht : ∀ a ∈ map (Quot.mk Setoid.r) s, Irreducible a
eq : Multiset.prod (map (Quot.mk Setoid.r) t) = Multiset.prod (map (Quot.mk Setoid.r) s)
⊢ ∀ x ∈ t, Irreducible x

Next tactic:
exact fun a ha => (irreducible_mk _).1 <| hs _ <| Multiset.mem_map_of_mem _ ha
theorem unique' {p q : Multiset (Associates α)} :
    (∀ a ∈ p, Irreducible a) → (∀ a ∈ q, Irreducible a) → p.prod = q.prod → p = q := by
  apply Multiset.induction_on_multiset_quot p
  apply Multiset.induction_on_multiset_quot q
  intro s t hs ht eq
  refine' Multiset.map_mk_eq_map_mk_of_rel (UniqueFactorizationMonoid.factors_unique _ _ _)
  · exact fun a ha => (irreducible_mk _).1 <| hs _ <| Multiset.mem_map_of_mem _ ha
  · 

Proof state:
case refine'_2
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
inst✝ : UniqueFactorizationMonoid α
p q : Multiset (Associates α)
s t : Multiset α
hs : ∀ a ∈ map (Quot.mk Setoid.r) t, Irreducible a
ht : ∀ a ∈ map (Quot.mk Setoid.r) s, Irreducible a
eq : Multiset.prod (map (Quot.mk Setoid.r) t) = Multiset.prod (map (Quot.mk Setoid.r) s)
⊢ ∀ x ∈ s, Irreducible x

Next tactic:
exact fun a ha => (irreducible_mk _).1 <| ht _ <| Multiset.mem_map_of_mem _ ha
theorem unique' {p q : Multiset (Associates α)} :
    (∀ a ∈ p, Irreducible a) → (∀ a ∈ q, Irreducible a) → p.prod = q.prod → p = q := by
  apply Multiset.induction_on_multiset_quot p
  apply Multiset.induction_on_multiset_quot q
  intro s t hs ht eq
  refine' Multiset.map_mk_eq_map_mk_of_rel (UniqueFactorizationMonoid.factors_unique _ _ _)
  · exact fun a ha => (irreducible_mk _).1 <| hs _ <| Multiset.mem_map_of_mem _ ha
  · exact fun a ha => (irreducible_mk _).1 <| ht _ <| Multiset.mem_map_of_mem _ ha
  

Proof state:
case refine'_3
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
inst✝ : UniqueFactorizationMonoid α
p q : Multiset (Associates α)
s t : Multiset α
hs : ∀ a ∈ map (Quot.mk Setoid.r) t, Irreducible a
ht : ∀ a ∈ map (Quot.mk Setoid.r) s, Irreducible a
eq : Multiset.prod (map (Quot.mk Setoid.r) t) = Multiset.prod (map (Quot.mk Setoid.r) s)
⊢ Multiset.prod t ~ᵤ Multiset.prod s

Next tactic:
have eq' : (Quot.mk Setoid.r : α → Associates α) = Associates.mk := funext quot_mk_eq_mk
theorem unique' {p q : Multiset (Associates α)} :
    (∀ a ∈ p, Irreducible a) → (∀ a ∈ q, Irreducible a) → p.prod = q.prod → p = q := by
  apply Multiset.induction_on_multiset_quot p
  apply Multiset.induction_on_multiset_quot q
  intro s t hs ht eq
  refine' Multiset.map_mk_eq_map_mk_of_rel (UniqueFactorizationMonoid.factors_unique _ _ _)
  · exact fun a ha => (irreducible_mk _).1 <| hs _ <| Multiset.mem_map_of_mem _ ha
  · exact fun a ha => (irreducible_mk _).1 <| ht _ <| Multiset.mem_map_of_mem _ ha
  have eq' : (Quot.mk Setoid.r : α → Associates α) = Associates.mk := funext quot_mk_eq_mk
  

Proof state:
case refine'_3
α : Type u_1
inst✝¹ : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
inst✝ : UniqueFactorizationMonoid α
p q : Multiset (Associates α)
s t : Multiset α
hs : ∀ a ∈ map (Quot.mk Setoid.r) t, Irreducible a
ht : ∀ a ∈ map (Quot.mk Setoid.r) s, Irreducible a
eq : Multiset.prod (map (Quot.mk Setoid.r) t) = Multiset.prod (map (Quot.mk Setoid.r) s)
eq' : Quot.mk Setoid.r = Associates.mk
⊢ Multiset.prod t ~ᵤ Multiset.prod s

Next tactic:
rwa [eq', prod_mk, prod_mk, mk_eq_mk_iff_associated] at eq
theorem FactorSet.unique [Nontrivial α] {p q : FactorSet α} (h : p.prod = q.prod) : p = q := by
  

Proof state:
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
inst✝¹ : UniqueFactorizationMonoid α
inst✝ : Nontrivial α
p q : FactorSet α
h : prod p = prod q
⊢ p = q

Next tactic:
induction p using WithTop.recTopCoe
theorem FactorSet.unique [Nontrivial α] {p q : FactorSet α} (h : p.prod = q.prod) : p = q := by
  induction p using WithTop.recTopCoe <;> 

Proof state:
case top
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
dec_irr : (p : Associates α) → Decidable (Irreducible p)
inst✝¹ : UniqueFactorizationMonoid α
inst✝ : Nontrivial α
q : FactorSet α
h : prod ⊤ = prod q
⊢ ⊤ = q

Next tactic:
induction q using WithTop.recTopCoe