l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem inv_mem_centralizer₀ [GroupWithZero M] (ha : a ∈ centralizer S) : a⁻¹ ∈ centralizer S :=
  (eq_or_ne a 0).elim
    (fun h => by
      rw [h, inv_zero]
      

Proof state:
M : Type u_1
S T : Set M
a b : M
inst✝ : GroupWithZero M
ha : a ∈ centralizer S
h : a = 0
⊢ 0 ∈ centralizer S

Next tactic:
exact zero_mem_centralizer S
@[simp]
theorem inv_mem_centralizer₀ [GroupWithZero M] (ha : a ∈ centralizer S) : a⁻¹ ∈ centralizer S :=
  (eq_or_ne a 0).elim
    (fun h => by
      rw [h, inv_zero]
      exact zero_mem_centralizer S)
    fun ha0 c hc => by
    

Proof state:
M : Type u_1
S T : Set M
a b : M
inst✝ : GroupWithZero M
ha : a ∈ centralizer S
ha0 : a ≠ 0
c : M
hc : c ∈ S
⊢ c * a⁻¹ = a⁻¹ * c

Next tactic:
rw [mul_inv_eq_iff_eq_mul₀ ha0, mul_assoc, eq_inv_mul_iff_mul_eq₀ ha0, ha c hc]
@[to_additive (attr := simp) sub_mem_addCentralizer]
theorem div_mem_centralizer [Group M] (ha : a ∈ centralizer S) (hb : b ∈ centralizer S) :
    a / b ∈ centralizer S := by
  

Proof state:
M : Type u_1
S T : Set M
a b : M
inst✝ : Group M
ha : a ∈ centralizer S
hb : b ∈ centralizer S
⊢ a / b ∈ centralizer S

Next tactic:
rw [div_eq_mul_inv]
@[to_additive (attr := simp) sub_mem_addCentralizer]
theorem div_mem_centralizer [Group M] (ha : a ∈ centralizer S) (hb : b ∈ centralizer S) :
    a / b ∈ centralizer S := by
  rw [div_eq_mul_inv]
  

Proof state:
M : Type u_1
S T : Set M
a b : M
inst✝ : Group M
ha : a ∈ centralizer S
hb : b ∈ centralizer S
⊢ a * b⁻¹ ∈ centralizer S

Next tactic:
exact mul_mem_centralizer ha (inv_mem_centralizer hb)
@[simp]
theorem div_mem_centralizer₀ [GroupWithZero M] (ha : a ∈ centralizer S) (hb : b ∈ centralizer S) :
    a / b ∈ centralizer S := by
  

Proof state:
M : Type u_1
S T : Set M
a b : M
inst✝ : GroupWithZero M
ha : a ∈ centralizer S
hb : b ∈ centralizer S
⊢ a / b ∈ centralizer S

Next tactic:
rw [div_eq_mul_inv]
@[simp]
theorem div_mem_centralizer₀ [GroupWithZero M] (ha : a ∈ centralizer S) (hb : b ∈ centralizer S) :
    a / b ∈ centralizer S := by
  rw [div_eq_mul_inv]
  

Proof state:
M : Type u_1
S T : Set M
a b : M
inst✝ : GroupWithZero M
ha : a ∈ centralizer S
hb : b ∈ centralizer S
⊢ a * b⁻¹ ∈ centralizer S

Next tactic:
exact mul_mem_centralizer ha (inv_mem_centralizer₀ hb)
@[to_additive (attr := simp) addCentralizer_eq_top_iff_subset]
theorem centralizer_eq_top_iff_subset {s : Set M} [Semigroup M] :
    centralizer s = Set.univ ↔ s ⊆ center M :=
  eq_top_iff.trans <| ⟨
    fun h _ hx => Semigroup.mem_center_iff.mpr fun _ => by 

Proof state:
M : Type u_1
S T : Set M
a b : M
s : Set M
inst✝ : Semigroup M
h : ⊤ ≤ centralizer s
x✝¹ : M
hx : x✝¹ ∈ s
x✝ : M
⊢ x✝ * x✝¹ = x✝¹ * x✝

Next tactic:
rw [h trivial _ hx]
theorem coe_fold_l (b : α) (l : List α) : fold op b l = l.foldl op b :=
  (coe_foldr_swap op _ b l).trans <| by 

Proof state:
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
b : α
l : List α
⊢ List.foldl (fun x y => op y x) b l = List.foldl op b l

Next tactic:
simp [hc.comm]
theorem fold_cons_right (b a : α) (s : Multiset α) : (a ::ₘ s).fold op b = s.fold op b * a := by
  

Proof state:
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
b a : α
s : Multiset α
⊢ fold op b (a ::ₘ s) = op (fold op b s) a

Next tactic:
simp [hc.comm]
theorem fold_cons'_right (b a : α) (s : Multiset α) : (a ::ₘ s).fold op b = s.fold op (b * a) := by
  

Proof state:
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
b a : α
s : Multiset α
⊢ fold op b (a ::ₘ s) = fold op (op b a) s

Next tactic:
rw [fold_eq_foldl, foldl_cons, ← fold_eq_foldl]
theorem fold_cons'_left (b a : α) (s : Multiset α) : (a ::ₘ s).fold op b = s.fold op (a * b) := by
  

Proof state:
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
b a : α
s : Multiset α
⊢ fold op b (a ::ₘ s) = fold op (op a b) s

Next tactic:
rw [fold_cons'_right, hc.comm]
theorem fold_add (b₁ b₂ : α) (s₁ s₂ : Multiset α) :
    (s₁ + s₂).fold op (b₁ * b₂) = s₁.fold op b₁ * s₂.fold op b₂ :=
  Multiset.induction_on s₂ (by 

Proof state:
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
b₁ b₂ : α
s₁ s₂ : Multiset α
⊢ fold op (op b₁ b₂) (s₁ + 0) = op (fold op b₁ s₁) (fold op b₂ 0)

Next tactic:
rw [add_zero, fold_zero, ← fold_cons'_right, ← fold_cons_right op]
theorem fold_add (b₁ b₂ : α) (s₁ s₂ : Multiset α) :
    (s₁ + s₂).fold op (b₁ * b₂) = s₁.fold op b₁ * s₂.fold op b₂ :=
  Multiset.induction_on s₂ (by rw [add_zero, fold_zero, ← fold_cons'_right, ← fold_cons_right op])
    (fun a b h => by 

Proof state:
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
b₁ b₂ : α
s₁ s₂ : Multiset α
a : α
b : Multiset α
h : fold op (op b₁ b₂) (s₁ + b) = op (fold op b₁ s₁) (fold op b₂ b)
⊢ fold op (op b₁ b₂) (s₁ + a ::ₘ b) = op (fold op b₁ s₁) (fold op b₂ (a ::ₘ b))

Next tactic:
rw [fold_cons_left, add_cons, fold_cons_left, h, ← ha.assoc, hc.comm a,
      ha.assoc]
theorem fold_bind {ι : Type*} (s : Multiset ι) (t : ι → Multiset α) (b : ι → α) (b₀ : α) :
    (s.bind t).fold op ((s.map b).fold op b₀) =
    (s.map fun i => (t i).fold op (b i)).fold op b₀ := by
  

Proof state:
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
ι : Type u_3
s : Multiset ι
t : ι → Multiset α
b : ι → α
b₀ : α
⊢ fold op (fold op b₀ (map b s)) (bind s t) = fold op b₀ (map (fun i => fold op (b i) (t i)) s)

Next tactic:
induction' s using Multiset.induction_on with a ha ih
theorem fold_bind {ι : Type*} (s : Multiset ι) (t : ι → Multiset α) (b : ι → α) (b₀ : α) :
    (s.bind t).fold op ((s.map b).fold op b₀) =
    (s.map fun i => (t i).fold op (b i)).fold op b₀ := by
  induction' s using Multiset.induction_on with a ha ih
  · 

Proof state:
case empty
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
ι : Type u_3
t : ι → Multiset α
b : ι → α
b₀ : α
⊢ fold op (fold op b₀ (map b 0)) (bind 0 t) = fold op b₀ (map (fun i => fold op (b i) (t i)) 0)

Next tactic:
rw [zero_bind, map_zero, map_zero, fold_zero]
theorem fold_bind {ι : Type*} (s : Multiset ι) (t : ι → Multiset α) (b : ι → α) (b₀ : α) :
    (s.bind t).fold op ((s.map b).fold op b₀) =
    (s.map fun i => (t i).fold op (b i)).fold op b₀ := by
  induction' s using Multiset.induction_on with a ha ih
  · rw [zero_bind, map_zero, map_zero, fold_zero]
  · 

Proof state:
case cons
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha✝ : IsAssociative α op
ι : Type u_3
t : ι → Multiset α
b : ι → α
b₀ : α
a : ι
ha : Multiset ι
ih : fold op (fold op b₀ (map b ha)) (bind ha t) = fold op b₀ (map (fun i => fold op (b i) (t i)) ha)
⊢ fold op (fold op b₀ (map b (a ::ₘ ha))) (bind (a ::ₘ ha) t) =
    fold op b₀ (map (fun i => fold op (b i) (t i)) (a ::ₘ ha))

Next tactic:
rw [cons_bind, map_cons, map_cons, fold_cons_left, fold_cons_left, fold_add, ih]
theorem fold_distrib {f g : β → α} (u₁ u₂ : α) (s : Multiset β) :
    (s.map fun x => f x * g x).fold op (u₁ * u₂) = (s.map f).fold op u₁ * (s.map g).fold op u₂ :=
  Multiset.induction_on s (by 

Proof state:
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
f g : β → α
u₁ u₂ : α
s : Multiset β
⊢ fold op (op u₁ u₂) (map (fun x => op (f x) (g x)) 0) = op (fold op u₁ (map f 0)) (fold op u₂ (map g 0))

Next tactic:
simp
theorem fold_distrib {f g : β → α} (u₁ u₂ : α) (s : Multiset β) :
    (s.map fun x => f x * g x).fold op (u₁ * u₂) = (s.map f).fold op u₁ * (s.map g).fold op u₂ :=
  Multiset.induction_on s (by simp) (fun a b h => by
    

Proof state:
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
f g : β → α
u₁ u₂ : α
s : Multiset β
a : β
b : Multiset β
h : fold op (op u₁ u₂) (map (fun x => op (f x) (g x)) b) = op (fold op u₁ (map f b)) (fold op u₂ (map g b))
⊢ fold op (op u₁ u₂) (map (fun x => op (f x) (g x)) (a ::ₘ b)) =
    op (fold op u₁ (map f (a ::ₘ b))) (fold op u₂ (map g (a ::ₘ b)))

Next tactic:
rw [map_cons, fold_cons_left, h, map_cons, fold_cons_left, map_cons,
      fold_cons_right, ha.assoc, ← ha.assoc (g a), hc.comm (g a),
      ha.assoc, hc.comm (g a), ha.assoc]
theorem fold_hom {op' : β → β → β} [IsCommutative β op'] [IsAssociative β op'] {m : α → β}
    (hm : ∀ x y, m (op x y) = op' (m x) (m y)) (b : α) (s : Multiset α) :
    (s.map m).fold op' (m b) = m (s.fold op b) :=
  Multiset.induction_on s (by 

Proof state:
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
op' : β → β → β
inst✝¹ : IsCommutative β op'
inst✝ : IsAssociative β op'
m : α → β
hm : ∀ (x y : α), m (op x y) = op' (m x) (m y)
b : α
s : Multiset α
⊢ fold op' (m b) (map m 0) = m (fold op b 0)

Next tactic:
simp
theorem fold_hom {op' : β → β → β} [IsCommutative β op'] [IsAssociative β op'] {m : α → β}
    (hm : ∀ x y, m (op x y) = op' (m x) (m y)) (b : α) (s : Multiset α) :
    (s.map m).fold op' (m b) = m (s.fold op b) :=
  Multiset.induction_on s (by simp) (by 

Proof state:
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
op' : β → β → β
inst✝¹ : IsCommutative β op'
inst✝ : IsAssociative β op'
m : α → β
hm : ∀ (x y : α), m (op x y) = op' (m x) (m y)
b : α
s : Multiset α
⊢ ∀ ⦃a : α⦄ {s : Multiset α},
    fold op' (m b) (map m s) = m (fold op b s) → fold op' (m b) (map m (a ::ₘ s)) = m (fold op b (a ::ₘ s))

Next tactic:
simp (config := { contextual := true }) [hm]
theorem fold_union_inter [DecidableEq α] (s₁ s₂ : Multiset α) (b₁ b₂ : α) :
    ((s₁ ∪ s₂).fold op b₁ * (s₁ ∩ s₂).fold op b₂) = s₁.fold op b₁ * s₂.fold op b₂ := by
  

Proof state:
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
inst✝ : DecidableEq α
s₁ s₂ : Multiset α
b₁ b₂ : α
⊢ op (fold op b₁ (s₁ ∪ s₂)) (fold op b₂ (s₁ ∩ s₂)) = op (fold op b₁ s₁) (fold op b₂ s₂)

Next tactic:
rw [← fold_add op, union_add_inter, fold_add op]
@[simp]
theorem fold_dedup_idem [DecidableEq α] [hi : IsIdempotent α op] (s : Multiset α) (b : α) :
    (dedup s).fold op b = s.fold op b :=
  Multiset.induction_on s (by 

Proof state:
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
inst✝ : DecidableEq α
hi : IsIdempotent α op
s : Multiset α
b : α
⊢ fold op b (dedup 0) = fold op b 0

Next tactic:
simp
@[simp]
theorem fold_dedup_idem [DecidableEq α] [hi : IsIdempotent α op] (s : Multiset α) (b : α) :
    (dedup s).fold op b = s.fold op b :=
  Multiset.induction_on s (by simp) fun a s IH => by
    

Proof state:
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
inst✝ : DecidableEq α
hi : IsIdempotent α op
s✝ : Multiset α
b a : α
s : Multiset α
IH : fold op b (dedup s) = fold op b s
⊢ fold op b (dedup (a ::ₘ s)) = fold op b (a ::ₘ s)

Next tactic:
by_cases h : a ∈ s
@[simp]
theorem fold_dedup_idem [DecidableEq α] [hi : IsIdempotent α op] (s : Multiset α) (b : α) :
    (dedup s).fold op b = s.fold op b :=
  Multiset.induction_on s (by simp) fun a s IH => by
    by_cases h : a ∈ s <;> 

Proof state:
case pos
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
inst✝ : DecidableEq α
hi : IsIdempotent α op
s✝ : Multiset α
b a : α
s : Multiset α
IH : fold op b (dedup s) = fold op b s
h : a ∈ s
⊢ fold op b (dedup (a ::ₘ s)) = fold op b (a ::ₘ s)

Next tactic:
simp [IH, h]
@[simp]
theorem fold_dedup_idem [DecidableEq α] [hi : IsIdempotent α op] (s : Multiset α) (b : α) :
    (dedup s).fold op b = s.fold op b :=
  Multiset.induction_on s (by simp) fun a s IH => by
    by_cases h : a ∈ s <;> 

Proof state:
case neg
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
inst✝ : DecidableEq α
hi : IsIdempotent α op
s✝ : Multiset α
b a : α
s : Multiset α
IH : fold op b (dedup s) = fold op b s
h : a ∉ s
⊢ fold op b (dedup (a ::ₘ s)) = fold op b (a ::ₘ s)

Next tactic:
simp [IH, h]
@[simp]
theorem fold_dedup_idem [DecidableEq α] [hi : IsIdempotent α op] (s : Multiset α) (b : α) :
    (dedup s).fold op b = s.fold op b :=
  Multiset.induction_on s (by simp) fun a s IH => by
    by_cases h : a ∈ s <;> simp [IH, h]
    

Proof state:
case pos
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
inst✝ : DecidableEq α
hi : IsIdempotent α op
s✝ : Multiset α
b a : α
s : Multiset α
IH : fold op b (dedup s) = fold op b s
h : a ∈ s
⊢ fold op b s = op a (fold op b s)

Next tactic:
show fold op b s = op a (fold op b s)
@[simp]
theorem fold_dedup_idem [DecidableEq α] [hi : IsIdempotent α op] (s : Multiset α) (b : α) :
    (dedup s).fold op b = s.fold op b :=
  Multiset.induction_on s (by simp) fun a s IH => by
    by_cases h : a ∈ s <;> simp [IH, h]
    show fold op b s = op a (fold op b s)
    

Proof state:
case pos
α : Type u_1
β : Type u_2
op : α → α → α
hc : IsCommutative α op
ha : IsAssociative α op
inst✝ : DecidableEq α
hi : IsIdempotent α op
s✝ : Multiset α
b a : α
s : Multiset α
IH : fold op b (dedup s) = fold op b s
h : a ∈ s
⊢ fold op b s = op a (fold op b s)

Next tactic:
rw [← cons_erase h, fold_cons_left, ← ha.assoc, hi.idempotent]
theorem max_le_of_forall_le {α : Type*} [CanonicallyLinearOrderedAddCommMonoid α] (l : Multiset α)
    (n : α) (h : ∀ x ∈ l, x ≤ n) : l.fold max ⊥ ≤ n := by
  

Proof state:
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : CanonicallyLinearOrderedAddCommMonoid α
l : Multiset α
n : α
h : ∀ x ∈ l, x ≤ n
⊢ fold max ⊥ l ≤ n

Next tactic:
induction l using Quotient.inductionOn
theorem max_le_of_forall_le {α : Type*} [CanonicallyLinearOrderedAddCommMonoid α] (l : Multiset α)
    (n : α) (h : ∀ x ∈ l, x ≤ n) : l.fold max ⊥ ≤ n := by
  induction l using Quotient.inductionOn
  

Proof state:
case h
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : CanonicallyLinearOrderedAddCommMonoid α
n : α
a✝ : List α
h : ∀ x ∈ ⟦a✝⟧, x ≤ n
⊢ fold max ⊥ ⟦a✝⟧ ≤ n

Next tactic:
simpa using List.max_le_of_forall_le _ _ h
theorem le_smul_dedup [DecidableEq α] (s : Multiset α) : ∃ n : ℕ, s ≤ n • dedup s :=
  ⟨(s.map fun a => count a s).fold max 0,
    le_iff_count.2 fun a => by
      

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a : α
⊢ count a s ≤ count a (fold max 0 (map (fun a => count a s) s) • dedup s)

Next tactic:
rw [count_nsmul]
theorem le_smul_dedup [DecidableEq α] (s : Multiset α) : ∃ n : ℕ, s ≤ n • dedup s :=
  ⟨(s.map fun a => count a s).fold max 0,
    le_iff_count.2 fun a => by
      rw [count_nsmul]; 

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a : α
⊢ count a s ≤ fold max 0 (map (fun a => count a s) s) * count a (dedup s)

Next tactic:
by_cases h : a ∈ s
theorem le_smul_dedup [DecidableEq α] (s : Multiset α) : ∃ n : ℕ, s ≤ n • dedup s :=
  ⟨(s.map fun a => count a s).fold max 0,
    le_iff_count.2 fun a => by
      rw [count_nsmul]; by_cases h : a ∈ s
      · 

Proof state:
case pos
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a : α
h : a ∈ s
⊢ count a s ≤ fold max 0 (map (fun a => count a s) s) * count a (dedup s)

Next tactic:
refine' le_trans _ (Nat.mul_le_mul_left _ <| count_pos.2 <| mem_dedup.2 h)
theorem le_smul_dedup [DecidableEq α] (s : Multiset α) : ∃ n : ℕ, s ≤ n • dedup s :=
  ⟨(s.map fun a => count a s).fold max 0,
    le_iff_count.2 fun a => by
      rw [count_nsmul]; by_cases h : a ∈ s
      · refine' le_trans _ (Nat.mul_le_mul_left _ <| count_pos.2 <| mem_dedup.2 h)
        

Proof state:
case pos
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a : α
h : a ∈ s
⊢ count a s ≤ fold max 0 (map (fun a => count a s) s) * succ 0

Next tactic:
have : count a s ≤ fold max 0 (map (fun a => count a s) (a ::ₘ erase s a)) :=
          by simp [le_max_left]
theorem le_smul_dedup [DecidableEq α] (s : Multiset α) : ∃ n : ℕ, s ≤ n • dedup s :=
  ⟨(s.map fun a => count a s).fold max 0,
    le_iff_count.2 fun a => by
      rw [count_nsmul]; by_cases h : a ∈ s
      · refine' le_trans _ (Nat.mul_le_mul_left _ <| count_pos.2 <| mem_dedup.2 h)
        have : count a s ≤ fold max 0 (map (fun a => count a s) (a ::ₘ erase s a)) :=
          by 

Proof state:
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a : α
h : a ∈ s
⊢ count a s ≤ fold max 0 (map (fun a => count a s) (a ::ₘ erase s a))

Next tactic:
simp [le_max_left]
theorem le_smul_dedup [DecidableEq α] (s : Multiset α) : ∃ n : ℕ, s ≤ n • dedup s :=
  ⟨(s.map fun a => count a s).fold max 0,
    le_iff_count.2 fun a => by
      rw [count_nsmul]; by_cases h : a ∈ s
      · refine' le_trans _ (Nat.mul_le_mul_left _ <| count_pos.2 <| mem_dedup.2 h)
        have : count a s ≤ fold max 0 (map (fun a => count a s) (a ::ₘ erase s a)) :=
          by simp [le_max_left]
        

Proof state:
case pos
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a : α
h : a ∈ s
this : count a s ≤ fold max 0 (map (fun a => count a s) (a ::ₘ erase s a))
⊢ count a s ≤ fold max 0 (map (fun a => count a s) s) * succ 0

Next tactic:
rw [cons_erase h] at this
theorem le_smul_dedup [DecidableEq α] (s : Multiset α) : ∃ n : ℕ, s ≤ n • dedup s :=
  ⟨(s.map fun a => count a s).fold max 0,
    le_iff_count.2 fun a => by
      rw [count_nsmul]; by_cases h : a ∈ s
      · refine' le_trans _ (Nat.mul_le_mul_left _ <| count_pos.2 <| mem_dedup.2 h)
        have : count a s ≤ fold max 0 (map (fun a => count a s) (a ::ₘ erase s a)) :=
          by simp [le_max_left]
        rw [cons_erase h] at this
        

Proof state:
case pos
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a : α
h : a ∈ s
this : count a s ≤ fold max 0 (map (fun a => count a s) s)
⊢ count a s ≤ fold max 0 (map (fun a => count a s) s) * succ 0

Next tactic:
simpa [mul_succ] using this
theorem le_smul_dedup [DecidableEq α] (s : Multiset α) : ∃ n : ℕ, s ≤ n • dedup s :=
  ⟨(s.map fun a => count a s).fold max 0,
    le_iff_count.2 fun a => by
      rw [count_nsmul]; by_cases h : a ∈ s
      · refine' le_trans _ (Nat.mul_le_mul_left _ <| count_pos.2 <| mem_dedup.2 h)
        have : count a s ≤ fold max 0 (map (fun a => count a s) (a ::ₘ erase s a)) :=
          by simp [le_max_left]
        rw [cons_erase h] at this
        simpa [mul_succ] using this
      · 

Proof state:
case neg
α : Type u_1
β : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a : α
h : a ∉ s
⊢ count a s ≤ fold max 0 (map (fun a => count a s) s) * count a (dedup s)

Next tactic:
simp [count_eq_zero.2 h, Nat.zero_le]
theorem eq_top_of_unit_mem (x y : α) (hx : x ∈ I) (h : y * x = 1) : I = ⊤ :=
  eq_top_iff.2 fun z _ =>
    calc
      z = z * (y * x) := by 

Proof state:
α : Type u
β : Type v
inst✝ : Semiring α
I : Ideal α
a b x y : α
hx : x ∈ I
h : y * x = 1
z : α
x✝ : z ∈ ⊤
⊢ z = z * (y * x)

Next tactic:
simp [h]
theorem eq_top_iff_one : I = ⊤ ↔ (1 : α) ∈ I :=
  ⟨by 

Proof state:
α : Type u
β : Type v
inst✝ : Semiring α
I : Ideal α
a b : α
⊢ I = ⊤ → 1 ∈ I

Next tactic:
rintro rfl
theorem eq_top_iff_one : I = ⊤ ↔ (1 : α) ∈ I :=
  ⟨by rintro rfl; 

Proof state:
α : Type u
β : Type v
inst✝ : Semiring α
a b : α
⊢ 1 ∈ ⊤

Next tactic:
trivial
theorem eq_top_iff_one : I = ⊤ ↔ (1 : α) ∈ I :=
  ⟨by rintro rfl; trivial, fun h => eq_top_of_unit_mem _ _ 1 h (by 

Proof state:
α : Type u
β : Type v
inst✝ : Semiring α
I : Ideal α
a b : α
h : 1 ∈ I
⊢ 1 * 1 = 1

Next tactic:
simp
@[simp]
theorem unit_mul_mem_iff_mem {x y : α} (hy : IsUnit y) : y * x ∈ I ↔ x ∈ I := by
  

Proof state:
α : Type u
β : Type v
inst✝ : Semiring α
I : Ideal α
a b x y : α
hy : IsUnit y
⊢ y * x ∈ I ↔ x ∈ I

Next tactic:
refine' ⟨fun h => _, fun h => I.mul_mem_left y h⟩
@[simp]
theorem unit_mul_mem_iff_mem {x y : α} (hy : IsUnit y) : y * x ∈ I ↔ x ∈ I := by
  refine' ⟨fun h => _, fun h => I.mul_mem_left y h⟩
  

Proof state:
α : Type u
β : Type v
inst✝ : Semiring α
I : Ideal α
a b x y : α
hy : IsUnit y
h : y * x ∈ I
⊢ x ∈ I

Next tactic:
obtain ⟨y', hy'⟩ := hy.exists_left_inv
@[simp]
theorem unit_mul_mem_iff_mem {x y : α} (hy : IsUnit y) : y * x ∈ I ↔ x ∈ I := by
  refine' ⟨fun h => _, fun h => I.mul_mem_left y h⟩
  obtain ⟨y', hy'⟩ := hy.exists_left_inv
  

Proof state:
case intro
α : Type u
β : Type v
inst✝ : Semiring α
I : Ideal α
a b x y : α
hy : IsUnit y
h : y * x ∈ I
y' : α
hy' : y' * y = 1
⊢ x ∈ I

Next tactic:
have := I.mul_mem_left y' h
@[simp]
theorem unit_mul_mem_iff_mem {x y : α} (hy : IsUnit y) : y * x ∈ I ↔ x ∈ I := by
  refine' ⟨fun h => _, fun h => I.mul_mem_left y h⟩
  obtain ⟨y', hy'⟩ := hy.exists_left_inv
  have := I.mul_mem_left y' h
  

Proof state:
case intro
α : Type u
β : Type v
inst✝ : Semiring α
I : Ideal α
a b x y : α
hy : IsUnit y
h : y * x ∈ I
y' : α
hy' : y' * y = 1
this : y' * (y * x) ∈ I
⊢ x ∈ I

Next tactic:
rwa [← mul_assoc, hy', one_mul] at this
theorem isCompactElement_top : CompleteLattice.IsCompactElement (⊤ : Ideal α) := by
  

Proof state:
α : Type u
β : Type v
inst✝ : Semiring α
I : Ideal α
a b : α
⊢ CompleteLattice.IsCompactElement ⊤

Next tactic:
simpa only [← span_singleton_one] using Submodule.singleton_span_isCompactElement 1
theorem span_singleton_mul_left_unit {a : α} (h2 : IsUnit a) (x : α) :
    span ({a * x} : Set α) = span {x} := by
  

Proof state:
α : Type u
β : Type v
inst✝ : Semiring α
I : Ideal α
a✝ b a : α
h2 : IsUnit a
x : α
⊢ span {a * x} = span {x}

Next tactic:
apply le_antisymm
theorem span_singleton_mul_left_unit {a : α} (h2 : IsUnit a) (x : α) :
    span ({a * x} : Set α) = span {x} := by
  apply le_antisymm <;> 

Proof state:
case a
α : Type u
β : Type v
inst✝ : Semiring α
I : Ideal α
a✝ b a : α
h2 : IsUnit a
x : α
⊢ span {a * x} ≤ span {x}

Next tactic:
rw [span_singleton_le_iff_mem, mem_span_singleton']
theorem span_singleton_mul_left_unit {a : α} (h2 : IsUnit a) (x : α) :
    span ({a * x} : Set α) = span {x} := by
  apply le_antisymm <;> 

Proof state:
case a
α : Type u
β : Type v
inst✝ : Semiring α
I : Ideal α
a✝ b a : α
h2 : IsUnit a
x : α
⊢ span {x} ≤ span {a * x}

Next tactic:
rw [span_singleton_le_iff_mem, mem_span_singleton']
theorem span_singleton_mul_left_unit {a : α} (h2 : IsUnit a) (x : α) :
    span ({a * x} : Set α) = span {x} := by
  apply le_antisymm <;> rw [span_singleton_le_iff_mem, mem_span_singleton']
  

Proof state:
case a
α : Type u
β : Type v
inst✝ : Semiring α
I : Ideal α
a✝ b a : α
h2 : IsUnit a
x : α
⊢ ∃ a_1, a_1 * x = a * x
case a α : Type u β : Type v inst✝ : Semiring α I : Ideal α a✝ b a : α h2 : IsUnit a x : α ⊢ ∃ a_1, a_1 * (a * x) = x

Next tactic:
exacts [⟨a, rfl⟩, ⟨_, h2.unit.inv_mul_cancel_left x⟩]
@[simp]
theorem span_zero : span (0 : Set α) = ⊥ := by 

Proof state:
α : Type u
β : Type v
inst✝ : Semiring α
I : Ideal α
a b : α
⊢ span 0 = ⊥

Next tactic:
rw [← Set.singleton_zero, span_singleton_eq_bot]
@[simp]
theorem span_one : span (1 : Set α) = ⊤ := by 

Proof state:
α : Type u
β : Type v
inst✝ : Semiring α
I : Ideal α
a b : α
⊢ span 1 = ⊤

Next tactic:
rw [← Set.singleton_one, span_singleton_one]
theorem span_eq_top_iff_finite (s : Set α) :
    span s = ⊤ ↔ ∃ s' : Finset α, ↑s' ⊆ s ∧ span (s' : Set α) = ⊤ := by
  

Proof state:
α : Type u
β : Type v
inst✝ : Semiring α
I : Ideal α
a b : α
s : Set α
⊢ span s = ⊤ ↔ ∃ s', ↑s' ⊆ s ∧ span ↑s' = ⊤

Next tactic:
simp_rw [eq_top_iff_one]
theorem span_eq_top_iff_finite (s : Set α) :
    span s = ⊤ ↔ ∃ s' : Finset α, ↑s' ⊆ s ∧ span (s' : Set α) = ⊤ := by
  simp_rw [eq_top_iff_one]
  

Proof state:
α : Type u
β : Type v
inst✝ : Semiring α
I : Ideal α
a b : α
s : Set α
⊢ 1 ∈ span s ↔ ∃ s', ↑s' ⊆ s ∧ 1 ∈ span ↑s'

Next tactic:
exact ⟨Submodule.mem_span_finite_of_mem_span, fun ⟨s', h₁, h₂⟩ => span_mono h₁ h₂⟩
theorem mem_span_singleton_sup {S : Type*} [CommSemiring S] {x y : S} {I : Ideal S} :
    x ∈ Ideal.span {y} ⊔ I ↔ ∃ a : S, ∃ b ∈ I, a * y + b = x := by
  

Proof state:
α : Type u
β : Type v
inst✝¹ : Semiring α
I✝ : Ideal α
a b : α
S : Type u_1
inst✝ : CommSemiring S
x y : S
I : Ideal S
⊢ x ∈ span {y} ⊔ I ↔ ∃ a, ∃ b ∈ I, a * y + b = x

Next tactic:
rw [Submodule.mem_sup]
theorem mem_span_singleton_sup {S : Type*} [CommSemiring S] {x y : S} {I : Ideal S} :
    x ∈ Ideal.span {y} ⊔ I ↔ ∃ a : S, ∃ b ∈ I, a * y + b = x := by
  rw [Submodule.mem_sup]
  

Proof state:
α : Type u
β : Type v
inst✝¹ : Semiring α
I✝ : Ideal α
a b : α
S : Type u_1
inst✝ : CommSemiring S
x y : S
I : Ideal S
⊢ (∃ y_1 ∈ span {y}, ∃ z ∈ I, y_1 + z = x) ↔ ∃ a, ∃ b ∈ I, a * y + b = x

Next tactic:
constructor