l3lab/ntp-mathlib huggingface dataset:
theorem normalizedFactors_prod_of_prime [Nontrivial α] [Unique αˣ] {m : Multiset α}
    (h : ∀ p ∈ m, Prime p) : normalizedFactors m.prod = m := by
  

Proof state:
α : Type u_1
inst✝⁵ : CancelCommMonoidWithZero α
inst✝⁴ : DecidableEq α
inst✝³ : NormalizationMonoid α
inst✝² : UniqueFactorizationMonoid α
inst✝¹ : Nontrivial α
inst✝ : Unique αˣ
m : Multiset α
h : ∀ p ∈ m, Prime p
⊢ normalizedFactors (Multiset.prod m) = m

Next tactic:
simpa only [← Multiset.rel_eq, ← associated_eq_eq] using
    prime_factors_unique prime_of_normalized_factor h
      (normalizedFactors_prod (m.prod_ne_zero_of_prime h))
theorem mem_normalizedFactors_eq_of_associated {a b c : α} (ha : a ∈ normalizedFactors c)
    (hb : b ∈ normalizedFactors c) (h : Associated a b) : a = b := by
  

Proof state:
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
a b c : α
ha : a ∈ normalizedFactors c
hb : b ∈ normalizedFactors c
h : a ~ᵤ b
⊢ a = b

Next tactic:
rw [← normalize_normalized_factor a ha, ← normalize_normalized_factor b hb,
    normalize_eq_normalize_iff]
theorem mem_normalizedFactors_eq_of_associated {a b c : α} (ha : a ∈ normalizedFactors c)
    (hb : b ∈ normalizedFactors c) (h : Associated a b) : a = b := by
  rw [← normalize_normalized_factor a ha, ← normalize_normalized_factor b hb,
    normalize_eq_normalize_iff]
  

Proof state:
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
a b c : α
ha : a ∈ normalizedFactors c
hb : b ∈ normalizedFactors c
h : a ~ᵤ b
⊢ a ∣ b ∧ b ∣ a

Next tactic:
exact Associated.dvd_dvd h
@[simp]
theorem normalizedFactors_pos (x : α) (hx : x ≠ 0) : 0 < normalizedFactors x ↔ ¬IsUnit x := by
  

Proof state:
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x : α
hx : x ≠ 0
⊢ 0 < normalizedFactors x ↔ ¬IsUnit x

Next tactic:
constructor
@[simp]
theorem normalizedFactors_pos (x : α) (hx : x ≠ 0) : 0 < normalizedFactors x ↔ ¬IsUnit x := by
  constructor
  · 

Proof state:
case mp
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x : α
hx : x ≠ 0
⊢ 0 < normalizedFactors x → ¬IsUnit x

Next tactic:
intro h hx
@[simp]
theorem normalizedFactors_pos (x : α) (hx : x ≠ 0) : 0 < normalizedFactors x ↔ ¬IsUnit x := by
  constructor
  · intro h hx
    

Proof state:
case mp
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x : α
hx✝ : x ≠ 0
h : 0 < normalizedFactors x
hx : IsUnit x
⊢ False

Next tactic:
obtain ⟨p, hp⟩ := Multiset.exists_mem_of_ne_zero h.ne'
@[simp]
theorem normalizedFactors_pos (x : α) (hx : x ≠ 0) : 0 < normalizedFactors x ↔ ¬IsUnit x := by
  constructor
  · intro h hx
    obtain ⟨p, hp⟩ := Multiset.exists_mem_of_ne_zero h.ne'
    

Proof state:
case mp.intro
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x : α
hx✝ : x ≠ 0
h : 0 < normalizedFactors x
hx : IsUnit x
p : α
hp : p ∈ normalizedFactors x
⊢ False

Next tactic:
exact
      (prime_of_normalized_factor _ hp).not_unit
        (isUnit_of_dvd_unit (dvd_of_mem_normalizedFactors hp) hx)
@[simp]
theorem normalizedFactors_pos (x : α) (hx : x ≠ 0) : 0 < normalizedFactors x ↔ ¬IsUnit x := by
  constructor
  · intro h hx
    obtain ⟨p, hp⟩ := Multiset.exists_mem_of_ne_zero h.ne'
    exact
      (prime_of_normalized_factor _ hp).not_unit
        (isUnit_of_dvd_unit (dvd_of_mem_normalizedFactors hp) hx)
  · 

Proof state:
case mpr
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x : α
hx : x ≠ 0
⊢ ¬IsUnit x → 0 < normalizedFactors x

Next tactic:
intro h
@[simp]
theorem normalizedFactors_pos (x : α) (hx : x ≠ 0) : 0 < normalizedFactors x ↔ ¬IsUnit x := by
  constructor
  · intro h hx
    obtain ⟨p, hp⟩ := Multiset.exists_mem_of_ne_zero h.ne'
    exact
      (prime_of_normalized_factor _ hp).not_unit
        (isUnit_of_dvd_unit (dvd_of_mem_normalizedFactors hp) hx)
  · intro h
    

Proof state:
case mpr
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x : α
hx : x ≠ 0
h : ¬IsUnit x
⊢ 0 < normalizedFactors x

Next tactic:
obtain ⟨p, hp⟩ := exists_mem_normalizedFactors hx h
@[simp]
theorem normalizedFactors_pos (x : α) (hx : x ≠ 0) : 0 < normalizedFactors x ↔ ¬IsUnit x := by
  constructor
  · intro h hx
    obtain ⟨p, hp⟩ := Multiset.exists_mem_of_ne_zero h.ne'
    exact
      (prime_of_normalized_factor _ hp).not_unit
        (isUnit_of_dvd_unit (dvd_of_mem_normalizedFactors hp) hx)
  · intro h
    obtain ⟨p, hp⟩ := exists_mem_normalizedFactors hx h
    

Proof state:
case mpr.intro
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x : α
hx : x ≠ 0
h : ¬IsUnit x
p : α
hp : p ∈ normalizedFactors x
⊢ 0 < normalizedFactors x

Next tactic:
exact
      bot_lt_iff_ne_bot.mpr
        (mt Multiset.eq_zero_iff_forall_not_mem.mp (not_forall.mpr ⟨p, not_not.mpr hp⟩))
theorem dvdNotUnit_iff_normalizedFactors_lt_normalizedFactors {x y : α} (hx : x ≠ 0) (hy : y ≠ 0) :
    DvdNotUnit x y ↔ normalizedFactors x < normalizedFactors y := by
  

Proof state:
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
⊢ DvdNotUnit x y ↔ normalizedFactors x < normalizedFactors y

Next tactic:
constructor
theorem dvdNotUnit_iff_normalizedFactors_lt_normalizedFactors {x y : α} (hx : x ≠ 0) (hy : y ≠ 0) :
    DvdNotUnit x y ↔ normalizedFactors x < normalizedFactors y := by
  constructor
  · 

Proof state:
case mp
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
⊢ DvdNotUnit x y → normalizedFactors x < normalizedFactors y

Next tactic:
rintro ⟨_, c, hc, rfl⟩
theorem dvdNotUnit_iff_normalizedFactors_lt_normalizedFactors {x y : α} (hx : x ≠ 0) (hy : y ≠ 0) :
    DvdNotUnit x y ↔ normalizedFactors x < normalizedFactors y := by
  constructor
  · rintro ⟨_, c, hc, rfl⟩
    

Proof state:
case mp.intro.intro.intro
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x : α
hx left✝ : x ≠ 0
c : α
hc : ¬IsUnit c
hy : x * c ≠ 0
⊢ normalizedFactors x < normalizedFactors (x * c)

Next tactic:
simp only [hx, right_ne_zero_of_mul hy, normalizedFactors_mul, Ne.def, not_false_iff,
      lt_add_iff_pos_right, normalizedFactors_pos, hc]
theorem dvdNotUnit_iff_normalizedFactors_lt_normalizedFactors {x y : α} (hx : x ≠ 0) (hy : y ≠ 0) :
    DvdNotUnit x y ↔ normalizedFactors x < normalizedFactors y := by
  constructor
  · rintro ⟨_, c, hc, rfl⟩
    simp only [hx, right_ne_zero_of_mul hy, normalizedFactors_mul, Ne.def, not_false_iff,
      lt_add_iff_pos_right, normalizedFactors_pos, hc]
  · 

Proof state:
case mpr
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
⊢ normalizedFactors x < normalizedFactors y → DvdNotUnit x y

Next tactic:
intro h
theorem dvdNotUnit_iff_normalizedFactors_lt_normalizedFactors {x y : α} (hx : x ≠ 0) (hy : y ≠ 0) :
    DvdNotUnit x y ↔ normalizedFactors x < normalizedFactors y := by
  constructor
  · rintro ⟨_, c, hc, rfl⟩
    simp only [hx, right_ne_zero_of_mul hy, normalizedFactors_mul, Ne.def, not_false_iff,
      lt_add_iff_pos_right, normalizedFactors_pos, hc]
  · intro h
    

Proof state:
case mpr
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : normalizedFactors x < normalizedFactors y
⊢ DvdNotUnit x y

Next tactic:
exact
      dvdNotUnit_of_dvd_of_not_dvd
        ((dvd_iff_normalizedFactors_le_normalizedFactors hx hy).mpr h.le)
        (mt (dvd_iff_normalizedFactors_le_normalizedFactors hy hx).mp h.not_le)
theorem normalizedFactors_multiset_prod (s : Multiset α) (hs : 0 ∉ s) :
    normalizedFactors (s.prod) = (s.map normalizedFactors).sum := by
  

Proof state:
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
s : Multiset α
hs : 0 ∉ s
⊢ normalizedFactors (Multiset.prod s) = Multiset.sum (Multiset.map normalizedFactors s)

Next tactic:
cases subsingleton_or_nontrivial α
theorem normalizedFactors_multiset_prod (s : Multiset α) (hs : 0 ∉ s) :
    normalizedFactors (s.prod) = (s.map normalizedFactors).sum := by
  cases subsingleton_or_nontrivial α
  · 

Proof state:
case inl
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
s : Multiset α
hs : 0 ∉ s
h✝ : Subsingleton α
⊢ normalizedFactors (Multiset.prod s) = Multiset.sum (Multiset.map normalizedFactors s)

Next tactic:
obtain rfl : s = 0
theorem normalizedFactors_multiset_prod (s : Multiset α) (hs : 0 ∉ s) :
    normalizedFactors (s.prod) = (s.map normalizedFactors).sum := by
  cases subsingleton_or_nontrivial α
  · obtain rfl : s = 0
    · 

Proof state:
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
s : Multiset α
hs : 0 ∉ s
h✝ : Subsingleton α
⊢ s = 0

Next tactic:
apply Multiset.eq_zero_of_forall_not_mem
theorem normalizedFactors_multiset_prod (s : Multiset α) (hs : 0 ∉ s) :
    normalizedFactors (s.prod) = (s.map normalizedFactors).sum := by
  cases subsingleton_or_nontrivial α
  · obtain rfl : s = 0
    · apply Multiset.eq_zero_of_forall_not_mem
      

Proof state:
case a
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
s : Multiset α
hs : 0 ∉ s
h✝ : Subsingleton α
⊢ ∀ (x : α), x ∉ s

Next tactic:
intro _
theorem normalizedFactors_multiset_prod (s : Multiset α) (hs : 0 ∉ s) :
    normalizedFactors (s.prod) = (s.map normalizedFactors).sum := by
  cases subsingleton_or_nontrivial α
  · obtain rfl : s = 0
    · apply Multiset.eq_zero_of_forall_not_mem
      intro _
      

Proof state:
case a
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
s : Multiset α
hs : 0 ∉ s
h✝ : Subsingleton α
x✝ : α
⊢ x✝ ∉ s

Next tactic:
convert hs
theorem normalizedFactors_multiset_prod (s : Multiset α) (hs : 0 ∉ s) :
    normalizedFactors (s.prod) = (s.map normalizedFactors).sum := by
  cases subsingleton_or_nontrivial α
  · obtain rfl : s = 0
    · apply Multiset.eq_zero_of_forall_not_mem
      intro _
      convert hs
    

Proof state:
case inl
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
h✝ : Subsingleton α
hs : 0 ∉ 0
⊢ normalizedFactors (Multiset.prod 0) = Multiset.sum (Multiset.map normalizedFactors 0)

Next tactic:
simp
theorem normalizedFactors_multiset_prod (s : Multiset α) (hs : 0 ∉ s) :
    normalizedFactors (s.prod) = (s.map normalizedFactors).sum := by
  cases subsingleton_or_nontrivial α
  · obtain rfl : s = 0
    · apply Multiset.eq_zero_of_forall_not_mem
      intro _
      convert hs
    simp
  

Proof state:
case inr
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
s : Multiset α
hs : 0 ∉ s
h✝ : Nontrivial α
⊢ normalizedFactors (Multiset.prod s) = Multiset.sum (Multiset.map normalizedFactors s)

Next tactic:
induction s using Multiset.induction with
  | empty => simp
  | cons IH =>
    rw [Multiset.prod_cons, Multiset.map_cons, Multiset.sum_cons, normalizedFactors_mul, IH]
    · exact fun h ↦ hs (Multiset.mem_cons_of_mem h)
    · exact fun h ↦ hs (h ▸ Multiset.mem_cons_self _ _)
    · apply Multiset.prod_ne_zero
      exact fun h ↦ hs (Multiset.mem_cons_of_mem h)
theorem normalizedFactors_multiset_prod (s : Multiset α) (hs : 0 ∉ s) :
    normalizedFactors (s.prod) = (s.map normalizedFactors).sum := by
  cases subsingleton_or_nontrivial α
  · obtain rfl : s = 0
    · apply Multiset.eq_zero_of_forall_not_mem
      intro _
      convert hs
    simp
  induction s using Multiset.induction with
  

Proof state:
case inr.empty
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
h✝ : Nontrivial α
hs : 0 ∉ 0
⊢ normalizedFactors (Multiset.prod 0) = Multiset.sum (Multiset.map normalizedFactors 0)

Next tactic:
| empty => simp
theorem normalizedFactors_multiset_prod (s : Multiset α) (hs : 0 ∉ s) :
    normalizedFactors (s.prod) = (s.map normalizedFactors).sum := by
  cases subsingleton_or_nontrivial α
  · obtain rfl : s = 0
    · apply Multiset.eq_zero_of_forall_not_mem
      intro _
      convert hs
    simp
  induction s using Multiset.induction with
  | empty => 

Proof state:
case inr.empty
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
h✝ : Nontrivial α
hs : 0 ∉ 0
⊢ normalizedFactors (Multiset.prod 0) = Multiset.sum (Multiset.map normalizedFactors 0)

Next tactic:
simp
theorem normalizedFactors_multiset_prod (s : Multiset α) (hs : 0 ∉ s) :
    normalizedFactors (s.prod) = (s.map normalizedFactors).sum := by
  cases subsingleton_or_nontrivial α
  · obtain rfl : s = 0
    · apply Multiset.eq_zero_of_forall_not_mem
      intro _
      convert hs
    simp
  induction s using Multiset.induction with
  | empty => simp
  

Proof state:
case inr.cons
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
h✝ : Nontrivial α
a✝ : α
s✝ : Multiset α
IH : 0 ∉ s✝ → normalizedFactors (Multiset.prod s✝) = Multiset.sum (Multiset.map normalizedFactors s✝)
hs : 0 ∉ a✝ ::ₘ s✝
⊢ normalizedFactors (Multiset.prod (a✝ ::ₘ s✝)) = Multiset.sum (Multiset.map normalizedFactors (a✝ ::ₘ s✝))

Next tactic:
| cons IH =>
    rw [Multiset.prod_cons, Multiset.map_cons, Multiset.sum_cons, normalizedFactors_mul, IH]
    · exact fun h ↦ hs (Multiset.mem_cons_of_mem h)
    · exact fun h ↦ hs (h ▸ Multiset.mem_cons_self _ _)
    · apply Multiset.prod_ne_zero
      exact fun h ↦ hs (Multiset.mem_cons_of_mem h)
theorem normalizedFactors_multiset_prod (s : Multiset α) (hs : 0 ∉ s) :
    normalizedFactors (s.prod) = (s.map normalizedFactors).sum := by
  cases subsingleton_or_nontrivial α
  · obtain rfl : s = 0
    · apply Multiset.eq_zero_of_forall_not_mem
      intro _
      convert hs
    simp
  induction s using Multiset.induction with
  | empty => simp
  | cons IH =>
    

Proof state:
case inr.cons
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
h✝ : Nontrivial α
a✝ : α
s✝ : Multiset α
IH : 0 ∉ s✝ → normalizedFactors (Multiset.prod s✝) = Multiset.sum (Multiset.map normalizedFactors s✝)
hs : 0 ∉ a✝ ::ₘ s✝
⊢ normalizedFactors (Multiset.prod (a✝ ::ₘ s✝)) = Multiset.sum (Multiset.map normalizedFactors (a✝ ::ₘ s✝))

Next tactic:
rw [Multiset.prod_cons, Multiset.map_cons, Multiset.sum_cons, normalizedFactors_mul, IH]
theorem normalizedFactors_multiset_prod (s : Multiset α) (hs : 0 ∉ s) :
    normalizedFactors (s.prod) = (s.map normalizedFactors).sum := by
  cases subsingleton_or_nontrivial α
  · obtain rfl : s = 0
    · apply Multiset.eq_zero_of_forall_not_mem
      intro _
      convert hs
    simp
  induction s using Multiset.induction with
  | empty => simp
  | cons IH =>
    rw [Multiset.prod_cons, Multiset.map_cons, Multiset.sum_cons, normalizedFactors_mul, IH]
    · 

Proof state:
case inr.cons
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
h✝ : Nontrivial α
a✝ : α
s✝ : Multiset α
IH : 0 ∉ s✝ → normalizedFactors (Multiset.prod s✝) = Multiset.sum (Multiset.map normalizedFactors s✝)
hs : 0 ∉ a✝ ::ₘ s✝
⊢ 0 ∉ s✝

Next tactic:
exact fun h ↦ hs (Multiset.mem_cons_of_mem h)
theorem normalizedFactors_multiset_prod (s : Multiset α) (hs : 0 ∉ s) :
    normalizedFactors (s.prod) = (s.map normalizedFactors).sum := by
  cases subsingleton_or_nontrivial α
  · obtain rfl : s = 0
    · apply Multiset.eq_zero_of_forall_not_mem
      intro _
      convert hs
    simp
  induction s using Multiset.induction with
  | empty => simp
  | cons IH =>
    rw [Multiset.prod_cons, Multiset.map_cons, Multiset.sum_cons, normalizedFactors_mul, IH]
    · exact fun h ↦ hs (Multiset.mem_cons_of_mem h)
    · 

Proof state:
case inr.cons.hx
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
h✝ : Nontrivial α
a✝ : α
s✝ : Multiset α
IH : 0 ∉ s✝ → normalizedFactors (Multiset.prod s✝) = Multiset.sum (Multiset.map normalizedFactors s✝)
hs : 0 ∉ a✝ ::ₘ s✝
⊢ a✝ ≠ 0

Next tactic:
exact fun h ↦ hs (h ▸ Multiset.mem_cons_self _ _)
theorem normalizedFactors_multiset_prod (s : Multiset α) (hs : 0 ∉ s) :
    normalizedFactors (s.prod) = (s.map normalizedFactors).sum := by
  cases subsingleton_or_nontrivial α
  · obtain rfl : s = 0
    · apply Multiset.eq_zero_of_forall_not_mem
      intro _
      convert hs
    simp
  induction s using Multiset.induction with
  | empty => simp
  | cons IH =>
    rw [Multiset.prod_cons, Multiset.map_cons, Multiset.sum_cons, normalizedFactors_mul, IH]
    · exact fun h ↦ hs (Multiset.mem_cons_of_mem h)
    · exact fun h ↦ hs (h ▸ Multiset.mem_cons_self _ _)
    · 

Proof state:
case inr.cons.hy
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
h✝ : Nontrivial α
a✝ : α
s✝ : Multiset α
IH : 0 ∉ s✝ → normalizedFactors (Multiset.prod s✝) = Multiset.sum (Multiset.map normalizedFactors s✝)
hs : 0 ∉ a✝ ::ₘ s✝
⊢ Multiset.prod s✝ ≠ 0

Next tactic:
apply Multiset.prod_ne_zero
theorem normalizedFactors_multiset_prod (s : Multiset α) (hs : 0 ∉ s) :
    normalizedFactors (s.prod) = (s.map normalizedFactors).sum := by
  cases subsingleton_or_nontrivial α
  · obtain rfl : s = 0
    · apply Multiset.eq_zero_of_forall_not_mem
      intro _
      convert hs
    simp
  induction s using Multiset.induction with
  | empty => simp
  | cons IH =>
    rw [Multiset.prod_cons, Multiset.map_cons, Multiset.sum_cons, normalizedFactors_mul, IH]
    · exact fun h ↦ hs (Multiset.mem_cons_of_mem h)
    · exact fun h ↦ hs (h ▸ Multiset.mem_cons_self _ _)
    · apply Multiset.prod_ne_zero
      

Proof state:
case inr.cons.hy.h
α : Type u_1
inst✝³ : CancelCommMonoidWithZero α
inst✝² : DecidableEq α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
h✝ : Nontrivial α
a✝ : α
s✝ : Multiset α
IH : 0 ∉ s✝ → normalizedFactors (Multiset.prod s✝) = Multiset.sum (Multiset.map normalizedFactors s✝)
hs : 0 ∉ a✝ ::ₘ s✝
⊢ 0 ∉ s✝

Next tactic:
exact fun h ↦ hs (Multiset.mem_cons_of_mem h)
/-- Noncomputably defines a `normalizationMonoid` structure on a `UniqueFactorizationMonoid`. -/
protected noncomputable def normalizationMonoid : NormalizationMonoid α :=
  normalizationMonoidOfMonoidHomRightInverse
    { toFun := fun a : Associates α =>
        if a = 0 then 0
        else
          ((normalizedFactors a).map
              (Classical.choose mk_surjective.hasRightInverse : Associates α → α)).prod
      map_one' := by 

Proof state:
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : Nontrivial α
inst✝ : UniqueFactorizationMonoid α
⊢ (fun a =>
        if a = 0 then 0
        else prod (map (Classical.choose (_ : Function.HasRightInverse Associates.mk)) (normalizedFactors a)))
      1 =
    1

Next tactic:
simp
/-- Noncomputably defines a `normalizationMonoid` structure on a `UniqueFactorizationMonoid`. -/
protected noncomputable def normalizationMonoid : NormalizationMonoid α :=
  normalizationMonoidOfMonoidHomRightInverse
    { toFun := fun a : Associates α =>
        if a = 0 then 0
        else
          ((normalizedFactors a).map
              (Classical.choose mk_surjective.hasRightInverse : Associates α → α)).prod
      map_one' := by simp
      map_mul' := fun x y => by
        

Proof state:
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : Nontrivial α
inst✝ : UniqueFactorizationMonoid α
x y : Associates α
⊢ OneHom.toFun
      {
        toFun := fun a =>
          if a = 0 then 0
          else prod (map (Classical.choose (_ : Function.HasRightInverse Associates.mk)) (normalizedFactors a)),
        map_one' :=
          (_ :
            (if 1 = 0 then 0
              else prod (map (Classical.choose (_ : Function.HasRightInverse Associates.mk)) (normalizedFactors 1))) =
              1) }
      (x * y) =
    OneHom.toFun
        {
          toFun := fun a =>
            if a = 0 then 0
            else prod (map (Classical.choose (_ : Function.HasRightInverse Associates.mk)) (normalizedFactors a)),
          map_one' :=
            (_ :
              (if 1 = 0 then 0
                else prod (map (Classical.choose (_ : Function.HasRightInverse Associates.mk)) (normalizedFactors 1))) =
                1) }
        x *
      OneHom.toFun
        {
          toFun := fun a =>
            if a = 0 then 0
            else prod (map (Classical.choose (_ : Function.HasRightInverse Associates.mk)) (normalizedFactors a)),
          map_one' :=
            (_ :
              (if 1 = 0 then 0
                else prod (map (Classical.choose (_ : Function.HasRightInverse Associates.mk)) (normalizedFactors 1))) =
                1) }
        y

Next tactic:
by_cases hx : x = 0
/-- Noncomputably defines a `normalizationMonoid` structure on a `UniqueFactorizationMonoid`. -/
protected noncomputable def normalizationMonoid : NormalizationMonoid α :=
  normalizationMonoidOfMonoidHomRightInverse
    { toFun := fun a : Associates α =>
        if a = 0 then 0
        else
          ((normalizedFactors a).map
              (Classical.choose mk_surjective.hasRightInverse : Associates α → α)).prod
      map_one' := by simp
      map_mul' := fun x y => by
        by_cases hx : x = 0
        · 

Proof state:
case pos
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : Nontrivial α
inst✝ : UniqueFactorizationMonoid α
x y : Associates α
hx : x = 0
⊢ OneHom.toFun
      {
        toFun := fun a =>
          if a = 0 then 0
          else prod (map (Classical.choose (_ : Function.HasRightInverse Associates.mk)) (normalizedFactors a)),
        map_one' :=
          (_ :
            (if 1 = 0 then 0
              else prod (map (Classical.choose (_ : Function.HasRightInverse Associates.mk)) (normalizedFactors 1))) =
              1) }
      (x * y) =
    OneHom.toFun
        {
          toFun := fun a =>
            if a = 0 then 0
            else prod (map (Classical.choose (_ : Function.HasRightInverse Associates.mk)) (normalizedFactors a)),
          map_one' :=
            (_ :
              (if 1 = 0 then 0
                else prod (map (Classical.choose (_ : Function.HasRightInverse Associates.mk)) (normalizedFactors 1))) =
                1) }
        x *
      OneHom.toFun
        {
          toFun := fun a =>
            if a = 0 then 0
            else prod (map (Classical.choose (_ : Function.HasRightInverse Associates.mk)) (normalizedFactors a)),
          map_one' :=
            (_ :
              (if 1 = 0 then 0
                else prod (map (Classical.choose (_ : Function.HasRightInverse Associates.mk)) (normalizedFactors 1))) =
                1) }
        y

Next tactic:
simp [hx]