l3lab/ntp-mathlib huggingface dataset:
theorem map_erase_of_mem [DecidableEq α] [DecidableEq β] (f : α → β)
    (s : Multiset α) {x : α} (h : x ∈ s) : (s.erase x).map f = (s.map f).erase (f x) := by
  induction' s using Multiset.induction_on with y s ih; simp
  

Proof state:
case cons
α : Type u_1
β : Type v
γ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → β
x y : α
s : Multiset α
ih : x ∈ s → map f (erase s x) = erase (map f s) (f x)
h : x ∈ y ::ₘ s
⊢ map f (erase (y ::ₘ s) x) = erase (map f (y ::ₘ s)) (f x)

Next tactic:
rcases eq_or_ne y x with rfl | hxy
theorem map_erase_of_mem [DecidableEq α] [DecidableEq β] (f : α → β)
    (s : Multiset α) {x : α} (h : x ∈ s) : (s.erase x).map f = (s.map f).erase (f x) := by
  induction' s using Multiset.induction_on with y s ih; simp
  rcases eq_or_ne y x with rfl | hxy; 

Proof state:
case cons.inl
α : Type u_1
β : Type v
γ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → β
y : α
s : Multiset α
ih : y ∈ s → map f (erase s y) = erase (map f s) (f y)
h : y ∈ y ::ₘ s
⊢ map f (erase (y ::ₘ s) y) = erase (map f (y ::ₘ s)) (f y)
case cons.inr
α : Type u_1
β : Type v
γ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → β
x y : α
s : Multiset α
ih : x ∈ s → map f (erase s x) = erase (map f s) (f x)
h : x ∈ y ::ₘ s
hxy : y ≠ x
⊢ map f (erase (y ::ₘ s) x) = erase (map f (y ::ₘ s)) (f x)

Next tactic:
simp
theorem map_erase_of_mem [DecidableEq α] [DecidableEq β] (f : α → β)
    (s : Multiset α) {x : α} (h : x ∈ s) : (s.erase x).map f = (s.map f).erase (f x) := by
  induction' s using Multiset.induction_on with y s ih; simp
  rcases eq_or_ne y x with rfl | hxy; simp
  

Proof state:
case cons.inr
α : Type u_1
β : Type v
γ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → β
x y : α
s : Multiset α
ih : x ∈ s → map f (erase s x) = erase (map f s) (f x)
h : x ∈ y ::ₘ s
hxy : y ≠ x
⊢ map f (erase (y ::ₘ s) x) = erase (map f (y ::ₘ s)) (f x)

Next tactic:
replace h : x ∈ s := by simpa [hxy.symm] using h
theorem map_erase_of_mem [DecidableEq α] [DecidableEq β] (f : α → β)
    (s : Multiset α) {x : α} (h : x ∈ s) : (s.erase x).map f = (s.map f).erase (f x) := by
  induction' s using Multiset.induction_on with y s ih; simp
  rcases eq_or_ne y x with rfl | hxy; simp
  replace h : x ∈ s := by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → β
x y : α
s : Multiset α
ih : x ∈ s → map f (erase s x) = erase (map f s) (f x)
h : x ∈ y ::ₘ s
hxy : y ≠ x
⊢ x ∈ s

Next tactic:
simpa [hxy.symm] using h
theorem map_erase_of_mem [DecidableEq α] [DecidableEq β] (f : α → β)
    (s : Multiset α) {x : α} (h : x ∈ s) : (s.erase x).map f = (s.map f).erase (f x) := by
  induction' s using Multiset.induction_on with y s ih; simp
  rcases eq_or_ne y x with rfl | hxy; simp
  replace h : x ∈ s := by simpa [hxy.symm] using h
  

Proof state:
case cons.inr
α : Type u_1
β : Type v
γ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → β
x y : α
s : Multiset α
ih : x ∈ s → map f (erase s x) = erase (map f s) (f x)
hxy : y ≠ x
h : x ∈ s
⊢ map f (erase (y ::ₘ s) x) = erase (map f (y ::ₘ s)) (f x)

Next tactic:
rw [s.erase_cons_tail hxy, map_cons, map_cons, ih h, erase_cons_tail_of_mem (mem_map_of_mem f h)]
theorem map_surjective_of_surjective {f : α → β} (hf : Function.Surjective f) :
    Function.Surjective (map f) := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
f : α → β
hf : Surjective f
⊢ Surjective (map f)

Next tactic:
intro s
theorem map_surjective_of_surjective {f : α → β} (hf : Function.Surjective f) :
    Function.Surjective (map f) := by
  intro s
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
f : α → β
hf : Surjective f
s : Multiset β
⊢ ∃ a, map f a = s

Next tactic:
induction' s using Multiset.induction_on with x s ih
theorem map_surjective_of_surjective {f : α → β} (hf : Function.Surjective f) :
    Function.Surjective (map f) := by
  intro s
  induction' s using Multiset.induction_on with x s ih
  · 

Proof state:
case empty
α : Type u_1
β : Type v
γ : Type u_2
f : α → β
hf : Surjective f
⊢ ∃ a, map f a = 0

Next tactic:
exact ⟨0, map_zero _⟩
theorem map_surjective_of_surjective {f : α → β} (hf : Function.Surjective f) :
    Function.Surjective (map f) := by
  intro s
  induction' s using Multiset.induction_on with x s ih
  · exact ⟨0, map_zero _⟩
  · 

Proof state:
case cons
α : Type u_1
β : Type v
γ : Type u_2
f : α → β
hf : Surjective f
x : β
s : Multiset β
ih : ∃ a, map f a = s
⊢ ∃ a, map f a = x ::ₘ s

Next tactic:
obtain ⟨y, rfl⟩ := hf x
theorem map_surjective_of_surjective {f : α → β} (hf : Function.Surjective f) :
    Function.Surjective (map f) := by
  intro s
  induction' s using Multiset.induction_on with x s ih
  · exact ⟨0, map_zero _⟩
  · obtain ⟨y, rfl⟩ := hf x
    

Proof state:
case cons.intro
α : Type u_1
β : Type v
γ : Type u_2
f : α → β
hf : Surjective f
s : Multiset β
ih : ∃ a, map f a = s
y : α
⊢ ∃ a, map f a = f y ::ₘ s

Next tactic:
obtain ⟨t, rfl⟩ := ih
theorem map_surjective_of_surjective {f : α → β} (hf : Function.Surjective f) :
    Function.Surjective (map f) := by
  intro s
  induction' s using Multiset.induction_on with x s ih
  · exact ⟨0, map_zero _⟩
  · obtain ⟨y, rfl⟩ := hf x
    obtain ⟨t, rfl⟩ := ih
    

Proof state:
case cons.intro.intro
α : Type u_1
β : Type v
γ : Type u_2
f : α → β
hf : Surjective f
y : α
t : Multiset α
⊢ ∃ a, map f a = f y ::ₘ map f t

Next tactic:
exact ⟨y ::ₘ t, map_cons _ _ _⟩
theorem foldr_induction' (f : α → β → β) (H : LeftCommutative f) (x : β) (q : α → Prop)
    (p : β → Prop) (s : Multiset α) (hpqf : ∀ a b, q a → p b → p (f a b)) (px : p x)
    (q_s : ∀ a ∈ s, q a) : p (foldr f H x s) := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
f : α → β → β
H : LeftCommutative f
x : β
q : α → Prop
p : β → Prop
s : Multiset α
hpqf : ∀ (a : α) (b : β), q a → p b → p (f a b)
px : p x
q_s : ∀ a ∈ s, q a
⊢ p (foldr f H x s)

Next tactic:
revert s
theorem foldr_induction' (f : α → β → β) (H : LeftCommutative f) (x : β) (q : α → Prop)
    (p : β → Prop) (s : Multiset α) (hpqf : ∀ a b, q a → p b → p (f a b)) (px : p x)
    (q_s : ∀ a ∈ s, q a) : p (foldr f H x s) := by
  revert s
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
f : α → β → β
H : LeftCommutative f
x : β
q : α → Prop
p : β → Prop
hpqf : ∀ (a : α) (b : β), q a → p b → p (f a b)
px : p x
⊢ ∀ (s : Multiset α), (∀ a ∈ s, q a) → p (foldr f H x s)

Next tactic:
refine' Multiset.induction (by simp [px]) _
theorem foldr_induction' (f : α → β → β) (H : LeftCommutative f) (x : β) (q : α → Prop)
    (p : β → Prop) (s : Multiset α) (hpqf : ∀ a b, q a → p b → p (f a b)) (px : p x)
    (q_s : ∀ a ∈ s, q a) : p (foldr f H x s) := by
  revert s
  refine' Multiset.induction (by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
f : α → β → β
H : LeftCommutative f
x : β
q : α → Prop
p : β → Prop
hpqf : ∀ (a : α) (b : β), q a → p b → p (f a b)
px : p x
⊢ (∀ a ∈ 0, q a) → p (foldr f H x 0)

Next tactic:
simp [px]
theorem foldr_induction' (f : α → β → β) (H : LeftCommutative f) (x : β) (q : α → Prop)
    (p : β → Prop) (s : Multiset α) (hpqf : ∀ a b, q a → p b → p (f a b)) (px : p x)
    (q_s : ∀ a ∈ s, q a) : p (foldr f H x s) := by
  revert s
  refine' Multiset.induction (by simp [px]) _
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
f : α → β → β
H : LeftCommutative f
x : β
q : α → Prop
p : β → Prop
hpqf : ∀ (a : α) (b : β), q a → p b → p (f a b)
px : p x
⊢ ∀ ⦃a : α⦄ {s : Multiset α},
    ((∀ a ∈ s, q a) → p (foldr f H x s)) → (∀ a_2 ∈ a ::ₘ s, q a_2) → p (foldr f H x (a ::ₘ s))

Next tactic:
intro a s hs hsa
theorem foldr_induction' (f : α → β → β) (H : LeftCommutative f) (x : β) (q : α → Prop)
    (p : β → Prop) (s : Multiset α) (hpqf : ∀ a b, q a → p b → p (f a b)) (px : p x)
    (q_s : ∀ a ∈ s, q a) : p (foldr f H x s) := by
  revert s
  refine' Multiset.induction (by simp [px]) _
  intro a s hs hsa
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
f : α → β → β
H : LeftCommutative f
x : β
q : α → Prop
p : β → Prop
hpqf : ∀ (a : α) (b : β), q a → p b → p (f a b)
px : p x
a : α
s : Multiset α
hs : (∀ a ∈ s, q a) → p (foldr f H x s)
hsa : ∀ a_1 ∈ a ::ₘ s, q a_1
⊢ p (foldr f H x (a ::ₘ s))

Next tactic:
rw [foldr_cons]
theorem foldr_induction' (f : α → β → β) (H : LeftCommutative f) (x : β) (q : α → Prop)
    (p : β → Prop) (s : Multiset α) (hpqf : ∀ a b, q a → p b → p (f a b)) (px : p x)
    (q_s : ∀ a ∈ s, q a) : p (foldr f H x s) := by
  revert s
  refine' Multiset.induction (by simp [px]) _
  intro a s hs hsa
  rw [foldr_cons]
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
f : α → β → β
H : LeftCommutative f
x : β
q : α → Prop
p : β → Prop
hpqf : ∀ (a : α) (b : β), q a → p b → p (f a b)
px : p x
a : α
s : Multiset α
hs : (∀ a ∈ s, q a) → p (foldr f H x s)
hsa : ∀ a_1 ∈ a ::ₘ s, q a_1
⊢ p (f a (foldr f H x s))

Next tactic:
have hps : ∀ x : α, x ∈ s → q x := fun x hxs => hsa x (mem_cons_of_mem hxs)
theorem foldr_induction' (f : α → β → β) (H : LeftCommutative f) (x : β) (q : α → Prop)
    (p : β → Prop) (s : Multiset α) (hpqf : ∀ a b, q a → p b → p (f a b)) (px : p x)
    (q_s : ∀ a ∈ s, q a) : p (foldr f H x s) := by
  revert s
  refine' Multiset.induction (by simp [px]) _
  intro a s hs hsa
  rw [foldr_cons]
  have hps : ∀ x : α, x ∈ s → q x := fun x hxs => hsa x (mem_cons_of_mem hxs)
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
f : α → β → β
H : LeftCommutative f
x : β
q : α → Prop
p : β → Prop
hpqf : ∀ (a : α) (b : β), q a → p b → p (f a b)
px : p x
a : α
s : Multiset α
hs : (∀ a ∈ s, q a) → p (foldr f H x s)
hsa : ∀ a_1 ∈ a ::ₘ s, q a_1
hps : ∀ x ∈ s, q x
⊢ p (f a (foldr f H x s))

Next tactic:
exact hpqf a (foldr f H x s) (hsa a (mem_cons_self a s)) (hs hps)
theorem foldl_induction' (f : β → α → β) (H : RightCommutative f) (x : β) (q : α → Prop)
    (p : β → Prop) (s : Multiset α) (hpqf : ∀ a b, q a → p b → p (f b a)) (px : p x)
    (q_s : ∀ a ∈ s, q a) : p (foldl f H x s) := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
f : β → α → β
H : RightCommutative f
x : β
q : α → Prop
p : β → Prop
s : Multiset α
hpqf : ∀ (a : α) (b : β), q a → p b → p (f b a)
px : p x
q_s : ∀ a ∈ s, q a
⊢ p (foldl f H x s)

Next tactic:
rw [foldl_swap]
theorem foldl_induction' (f : β → α → β) (H : RightCommutative f) (x : β) (q : α → Prop)
    (p : β → Prop) (s : Multiset α) (hpqf : ∀ a b, q a → p b → p (f b a)) (px : p x)
    (q_s : ∀ a ∈ s, q a) : p (foldl f H x s) := by
  rw [foldl_swap]
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
f : β → α → β
H : RightCommutative f
x : β
q : α → Prop
p : β → Prop
s : Multiset α
hpqf : ∀ (a : α) (b : β), q a → p b → p (f b a)
px : p x
q_s : ∀ a ∈ s, q a
⊢ p (foldr (fun x y => f y x) (_ : ∀ (_x _y : α) (_z : β), f (f _z _y) _x = f (f _z _x) _y) x s)

Next tactic:
exact foldr_induction' (fun x y => f y x) (fun x y z => (H _ _ _).symm) x q p s hpqf px q_s
/-- Lift of the list `pmap` operation. Map a partial function `f` over a multiset
  `s` whose elements are all in the domain of `f`. -/
nonrec def pmap {p : α → Prop} (f : ∀ a, p a → β) (s : Multiset α) : (∀ a ∈ s, p a) → Multiset β :=
  Quot.recOn' s (fun l H => ↑(pmap f l H)) fun l₁ l₂ (pp : l₁ ~ l₂) =>
    funext fun H₂ : ∀ a ∈ l₂, p a =>
      have H₁ : ∀ a ∈ l₁, p a := fun a h => H₂ a (pp.subset h)
      have : ∀ {s₂ e H}, @Eq.ndrec (Multiset α) l₁ (fun s => (∀ a ∈ s, p a) → Multiset β)
          (fun _ => ↑(pmap f l₁ H₁)) s₂ e H = ↑(pmap f l₁ H₁) := by
        

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
f : (a : α) → p a → β
s : Multiset α
l₁ l₂ : List α
pp : l₁ ~ l₂
H₂ : ∀ a ∈ l₂, p a
H₁ : ∀ a ∈ l₁, p a
⊢ ∀ {s₂ : Multiset α} {e : ↑l₁ = s₂} {H : ∀ a ∈ s₂, p a},
    Eq.ndrec (motive := fun s => (∀ a ∈ s, p a) → Multiset β) (fun x => ↑(List.pmap f l₁ H₁)) e H = ↑(List.pmap f l₁ H₁)

Next tactic:
intro s₂ e _
/-- Lift of the list `pmap` operation. Map a partial function `f` over a multiset
  `s` whose elements are all in the domain of `f`. -/
nonrec def pmap {p : α → Prop} (f : ∀ a, p a → β) (s : Multiset α) : (∀ a ∈ s, p a) → Multiset β :=
  Quot.recOn' s (fun l H => ↑(pmap f l H)) fun l₁ l₂ (pp : l₁ ~ l₂) =>
    funext fun H₂ : ∀ a ∈ l₂, p a =>
      have H₁ : ∀ a ∈ l₁, p a := fun a h => H₂ a (pp.subset h)
      have : ∀ {s₂ e H}, @Eq.ndrec (Multiset α) l₁ (fun s => (∀ a ∈ s, p a) → Multiset β)
          (fun _ => ↑(pmap f l₁ H₁)) s₂ e H = ↑(pmap f l₁ H₁) := by
        intro s₂ e _; 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
f : (a : α) → p a → β
s : Multiset α
l₁ l₂ : List α
pp : l₁ ~ l₂
H₂ : ∀ a ∈ l₂, p a
H₁ : ∀ a ∈ l₁, p a
s₂ : Multiset α
e : ↑l₁ = s₂
H✝ : ∀ a ∈ s₂, p a
⊢ Eq.ndrec (motive := fun s => (∀ a ∈ s, p a) → Multiset β) (fun x => ↑(List.pmap f l₁ H₁)) e H✝ = ↑(List.pmap f l₁ H₁)

Next tactic:
subst e
/-- Lift of the list `pmap` operation. Map a partial function `f` over a multiset
  `s` whose elements are all in the domain of `f`. -/
nonrec def pmap {p : α → Prop} (f : ∀ a, p a → β) (s : Multiset α) : (∀ a ∈ s, p a) → Multiset β :=
  Quot.recOn' s (fun l H => ↑(pmap f l H)) fun l₁ l₂ (pp : l₁ ~ l₂) =>
    funext fun H₂ : ∀ a ∈ l₂, p a =>
      have H₁ : ∀ a ∈ l₁, p a := fun a h => H₂ a (pp.subset h)
      have : ∀ {s₂ e H}, @Eq.ndrec (Multiset α) l₁ (fun s => (∀ a ∈ s, p a) → Multiset β)
          (fun _ => ↑(pmap f l₁ H₁)) s₂ e H = ↑(pmap f l₁ H₁) := by
        intro s₂ e _; subst e; 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
p : α → Prop
f : (a : α) → p a → β
s : Multiset α
l₁ l₂ : List α
pp : l₁ ~ l₂
H₂ : ∀ a ∈ l₂, p a
H₁ : ∀ a ∈ l₁, p a
H✝ : ∀ a ∈ ↑l₁, p a
⊢ Eq.ndrec (motive := fun s => (∀ a ∈ s, p a) → Multiset β) (fun x => ↑(List.pmap f l₁ H₁)) (_ : ↑l₁ = ↑l₁) H✝ =
    ↑(List.pmap f l₁ H₁)

Next tactic:
rfl
theorem sizeOf_lt_sizeOf_of_mem [SizeOf α] {x : α} {s : Multiset α} (hx : x ∈ s) :
    SizeOf.sizeOf x < SizeOf.sizeOf s := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : SizeOf α
x : α
s : Multiset α
hx : x ∈ s
⊢ sizeOf x < sizeOf s

Next tactic:
induction' s using Quot.inductionOn with l a b
theorem sizeOf_lt_sizeOf_of_mem [SizeOf α] {x : α} {s : Multiset α} (hx : x ∈ s) :
    SizeOf.sizeOf x < SizeOf.sizeOf s := by
  induction' s using Quot.inductionOn with l a b
  

Proof state:
case h
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : SizeOf α
x : α
l : List α
hx : x ∈ Quot.mk Setoid.r l
⊢ sizeOf x < sizeOf (Quot.mk Setoid.r l)

Next tactic:
exact List.sizeOf_lt_sizeOf_of_mem hx
theorem attach_cons (a : α) (m : Multiset α) :
    (a ::ₘ m).attach =
      ⟨a, mem_cons_self a m⟩ ::ₘ m.attach.map fun p => ⟨p.1, mem_cons_of_mem p.2⟩ :=
  Quotient.inductionOn m fun l =>
    congr_arg _ <|
      congr_arg (List.cons _) <| by
        

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
a : α
m : Multiset α
l : List α
⊢ List.pmap mk l (_ : ∀ x ∈ l, (fun a_2 => a_2 ∈ a ::ₘ ⟦l⟧) x) =
    List.map (fun p => { val := ↑p, property := (_ : ↑p ∈ a ::ₘ ⟦l⟧) }) (List.pmap mk l (_ : ∀ _a ∈ ⟦l⟧, _a ∈ ⟦l⟧))

Next tactic:
rw [List.map_pmap]
theorem attach_cons (a : α) (m : Multiset α) :
    (a ::ₘ m).attach =
      ⟨a, mem_cons_self a m⟩ ::ₘ m.attach.map fun p => ⟨p.1, mem_cons_of_mem p.2⟩ :=
  Quotient.inductionOn m fun l =>
    congr_arg _ <|
      congr_arg (List.cons _) <| by
        rw [List.map_pmap]; 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
a : α
m : Multiset α
l : List α
⊢ List.pmap mk l (_ : ∀ x ∈ l, (fun a_2 => a_2 ∈ a ::ₘ ⟦l⟧) x) =
    List.pmap
      (fun a_1 h =>
        { val := ↑{ val := a_1, property := h }, property := (_ : ↑{ val := a_1, property := h } ∈ a ::ₘ ⟦l⟧) })
      l (_ : ∀ _a ∈ ⟦l⟧, _a ∈ ⟦l⟧)

Next tactic:
exact List.pmap_congr _ fun _ _ _ _ => Subtype.eq rfl
/-- If `p` is a decidable predicate,
so is the predicate that all elements of a multiset satisfy `p`. -/
protected def decidableForallMultiset {p : α → Prop} [hp : ∀ a, Decidable (p a)] :
    Decidable (∀ a ∈ m, p a) :=
  Quotient.recOnSubsingleton m fun l => decidable_of_iff (∀ a ∈ l, p a) <| by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
m : Multiset α
p : α → Prop
hp : (a : α) → Decidable (p a)
l : List α
⊢ (∀ a ∈ l, p a) ↔ ∀ a ∈ ⟦l⟧, p a

Next tactic:
simp
/-- decidable equality for functions whose domain is bounded by multisets -/
instance decidableEqPiMultiset {β : α → Type*} [h : ∀ a, DecidableEq (β a)] :
    DecidableEq (∀ a ∈ m, β a) := fun f g =>
  decidable_of_iff (∀ (a) (h : a ∈ m), f a h = g a h) (by 

Proof state:
α : Type u_1
β✝ : Type v
γ : Type u_2
m : Multiset α
β : α → Type u_3
h : (a : α) → DecidableEq (β a)
f g : (a : α) → a ∈ m → β a
⊢ (∀ (a : α) (h : a ∈ m), f a h = g a h) ↔ f = g

Next tactic:
simp [Function.funext_iff]
/-- If `p` is a decidable predicate,
so is the existence of an element in a multiset satisfying `p`. -/
protected def decidableExistsMultiset {p : α → Prop} [DecidablePred p] : Decidable (∃ x ∈ m, p x) :=
  Quotient.recOnSubsingleton m fun l => decidable_of_iff (∃ a ∈ l, p a) <| by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
m : Multiset α
p : α → Prop
inst✝ : DecidablePred p
l : List α
⊢ (∃ a ∈ l, p a) ↔ ∃ x ∈ ⟦l⟧, p x

Next tactic:
simp
/-- This is a special case of `tsub_le_iff_right`, which should be used instead of this.
  This is needed to prove `OrderedSub (Multiset α)`. -/
protected theorem sub_le_iff_le_add : s - t ≤ u ↔ s ≤ u + t := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s t u : Multiset α
a b : α
⊢ s - t ≤ u ↔ s ≤ u + t

Next tactic:
revert s
/-- This is a special case of `tsub_le_iff_right`, which should be used instead of this.
  This is needed to prove `OrderedSub (Multiset α)`. -/
protected theorem sub_le_iff_le_add : s - t ≤ u ↔ s ≤ u + t := by
  revert s
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
t u : Multiset α
a b : α
⊢ ∀ {s : Multiset α}, s - t ≤ u ↔ s ≤ u + t

Next tactic:
exact @(Multiset.induction_on t (by simp [Multiset.sub_zero]) fun a t IH s => by
      simp [IH, erase_le_iff_le_cons])
/-- This is a special case of `tsub_le_iff_right`, which should be used instead of this.
  This is needed to prove `OrderedSub (Multiset α)`. -/
protected theorem sub_le_iff_le_add : s - t ≤ u ↔ s ≤ u + t := by
  revert s
  exact @(Multiset.induction_on t (by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
t u : Multiset α
a b : α
⊢ ∀ {s : Multiset α}, s - 0 ≤ u ↔ s ≤ u + 0

Next tactic:
simp [Multiset.sub_zero]
/-- This is a special case of `tsub_le_iff_right`, which should be used instead of this.
  This is needed to prove `OrderedSub (Multiset α)`. -/
protected theorem sub_le_iff_le_add : s - t ≤ u ↔ s ≤ u + t := by
  revert s
  exact @(Multiset.induction_on t (by simp [Multiset.sub_zero]) fun a t IH s => by
      

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
t✝ u : Multiset α
a✝ b a : α
t : Multiset α
IH : ∀ {s : Multiset α}, s - t ≤ u ↔ s ≤ u + t
s : Multiset α
⊢ s - a ::ₘ t ≤ u ↔ s ≤ u + a ::ₘ t

Next tactic:
simp [IH, erase_le_iff_le_cons]
theorem cons_sub_of_le (a : α) {s t : Multiset α} (h : t ≤ s) : a ::ₘ s - t = a ::ₘ (s - t) := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ t✝ u : Multiset α
a✝ b a : α
s t : Multiset α
h : t ≤ s
⊢ a ::ₘ s - t = a ::ₘ (s - t)

Next tactic:
rw [← singleton_add, ← singleton_add, add_tsub_assoc_of_le h]
theorem sub_eq_fold_erase (s t : Multiset α) : s - t = foldl erase erase_comm s t :=
  Quotient.inductionOn₂ s t fun l₁ l₂ => by
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ t✝ u : Multiset α
a b : α
s t : Multiset α
l₁ l₂ : List α
⊢ ⟦l₁⟧ - ⟦l₂⟧ = foldl erase (_ : ∀ (s : Multiset α) (a b : α), erase (erase s a) b = erase (erase s b) a) ⟦l₁⟧ ⟦l₂⟧

Next tactic:
show ofList (l₁.diff l₂) = foldl erase erase_comm l₁ l₂
theorem sub_eq_fold_erase (s t : Multiset α) : s - t = foldl erase erase_comm s t :=
  Quotient.inductionOn₂ s t fun l₁ l₂ => by
    show ofList (l₁.diff l₂) = foldl erase erase_comm l₁ l₂
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ t✝ u : Multiset α
a b : α
s t : Multiset α
l₁ l₂ : List α
⊢ ↑(List.diff l₁ l₂) = foldl erase (_ : ∀ (s : Multiset α) (a b : α), erase (erase s a) b = erase (erase s b) a) ↑l₁ ↑l₂

Next tactic:
rw [diff_eq_foldl l₁ l₂]
theorem sub_eq_fold_erase (s t : Multiset α) : s - t = foldl erase erase_comm s t :=
  Quotient.inductionOn₂ s t fun l₁ l₂ => by
    show ofList (l₁.diff l₂) = foldl erase erase_comm l₁ l₂
    rw [diff_eq_foldl l₁ l₂]
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ t✝ u : Multiset α
a b : α
s t : Multiset α
l₁ l₂ : List α
⊢ ↑(List.foldl List.erase l₁ l₂) =
    foldl erase (_ : ∀ (s : Multiset α) (a b : α), erase (erase s a) b = erase (erase s b) a) ↑l₁ ↑l₂

Next tactic:
symm
theorem sub_eq_fold_erase (s t : Multiset α) : s - t = foldl erase erase_comm s t :=
  Quotient.inductionOn₂ s t fun l₁ l₂ => by
    show ofList (l₁.diff l₂) = foldl erase erase_comm l₁ l₂
    rw [diff_eq_foldl l₁ l₂]
    symm
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ t✝ u : Multiset α
a b : α
s t : Multiset α
l₁ l₂ : List α
⊢ foldl erase (_ : ∀ (s : Multiset α) (a b : α), erase (erase s a) b = erase (erase s b) a) ↑l₁ ↑l₂ =
    ↑(List.foldl List.erase l₁ l₂)

Next tactic:
exact foldl_hom _ _ _ _ _ fun x y => rfl
@[simp]
theorem card_sub {s t : Multiset α} (h : t ≤ s) : card (s - t) = card s - card t :=
  (tsub_eq_of_eq_add_rev <| by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ t✝ u : Multiset α
a b : α
s t : Multiset α
h : t ≤ s
⊢ card s = card t + card (s - t)

Next tactic:
rw [add_comm, ← card_add, tsub_add_cancel_of_le h]
theorem union_le (h₁ : s ≤ u) (h₂ : t ≤ u) : s ∪ t ≤ u := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s t u : Multiset α
a b : α
h₁ : s ≤ u
h₂ : t ≤ u
⊢ s ∪ t ≤ u

Next tactic:
rw [← eq_union_left h₂]
theorem union_le (h₁ : s ≤ u) (h₂ : t ≤ u) : s ∪ t ≤ u := by
  rw [← eq_union_left h₂]; 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s t u : Multiset α
a b : α
h₁ : s ≤ u
h₂ : t ≤ u
⊢ s ∪ t ≤ u ∪ t

Next tactic:
exact union_le_union_right h₁ t
@[simp]
theorem map_union [DecidableEq β] {f : α → β} (finj : Function.Injective f) {s t : Multiset α} :
    map f (s ∪ t) = map f s ∪ map f t :=
  Quotient.inductionOn₂ s t fun l₁ l₂ =>
    congr_arg ofList (by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝¹ : DecidableEq α
s✝ t✝ u : Multiset α
a b : α
inst✝ : DecidableEq β
f : α → β
finj : Injective f
s t : Multiset α
l₁ l₂ : List α
⊢ List.map f (List.diff l₁ l₂ ++ l₂) = List.diff (List.map f l₁) (List.map f l₂) ++ List.map f l₂

Next tactic:
rw [List.map_append f, List.map_diff finj]
@[simp] theorem zero_union : 0 ∪ s = s := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s t u : Multiset α
a b : α
⊢ 0 ∪ s = s

Next tactic:
simp [union_def]
@[simp] theorem union_zero : s ∪ 0 = s := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s t u : Multiset α
a b : α
⊢ s ∪ 0 = s

Next tactic:
simp [union_def]
theorem inter_le_right (s : Multiset α) : ∀ t, s ∩ t ≤ t :=
  Multiset.induction_on s (fun t => (zero_inter t).symm ▸ zero_le _) fun a s IH t =>
    if h : a ∈ t then by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝¹ t✝ u : Multiset α
a✝ b : α
s✝ : Multiset α
a : α
s : Multiset α
IH : ∀ (t : Multiset α), s ∩ t ≤ t
t : Multiset α
h : a ∈ t
⊢ (a ::ₘ s) ∩ t ≤ t

Next tactic:
simpa [h] using cons_le_cons a (IH (t.erase a))
theorem inter_le_right (s : Multiset α) : ∀ t, s ∩ t ≤ t :=
  Multiset.induction_on s (fun t => (zero_inter t).symm ▸ zero_le _) fun a s IH t =>
    if h : a ∈ t then by simpa [h] using cons_le_cons a (IH (t.erase a)) else by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝¹ t✝ u : Multiset α
a✝ b : α
s✝ : Multiset α
a : α
s : Multiset α
IH : ∀ (t : Multiset α), s ∩ t ≤ t
t : Multiset α
h : a ∉ t
⊢ (a ::ₘ s) ∩ t ≤ t

Next tactic:
simp [h, IH]
theorem le_inter (h₁ : s ≤ t) (h₂ : s ≤ u) : s ≤ t ∩ u := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s t u : Multiset α
a b : α
h₁ : s ≤ t
h₂ : s ≤ u
⊢ s ≤ t ∩ u

Next tactic:
revert s u