l3lab/ntp-mathlib huggingface dataset:
theorem exists_mem_of_rel_of_mem {r : α → β → Prop} {s : Multiset α} {t : Multiset β}
    (h : Rel r s t) : ∀ {a : α}, a ∈ s → ∃ b ∈ t, r a b := by
  induction' h with x y s t hxy _hst ih
  · simp
  · intro a ha
    cases' mem_cons.1 ha with ha ha
    · exact ⟨y, mem_cons_self _ _, ha.symm ▸ hxy⟩
    · 

Proof state:
case cons.inr
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
r : α → β → Prop
s✝ : Multiset α
t✝ : Multiset β
x : α
y : β
s : Multiset α
t : Multiset β
hxy : r x y
_hst : Rel r s t
ih : ∀ {a : α}, a ∈ s → ∃ b ∈ t, r a b
a : α
ha✝ : a ∈ x ::ₘ s
ha : a ∈ s
⊢ ∃ b ∈ y ::ₘ t, r a b

Next tactic:
rcases ih ha with ⟨b, hbt, hab⟩
theorem exists_mem_of_rel_of_mem {r : α → β → Prop} {s : Multiset α} {t : Multiset β}
    (h : Rel r s t) : ∀ {a : α}, a ∈ s → ∃ b ∈ t, r a b := by
  induction' h with x y s t hxy _hst ih
  · simp
  · intro a ha
    cases' mem_cons.1 ha with ha ha
    · exact ⟨y, mem_cons_self _ _, ha.symm ▸ hxy⟩
    · rcases ih ha with ⟨b, hbt, hab⟩
      

Proof state:
case cons.inr.intro.intro
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
r : α → β → Prop
s✝ : Multiset α
t✝ : Multiset β
x : α
y : β
s : Multiset α
t : Multiset β
hxy : r x y
_hst : Rel r s t
ih : ∀ {a : α}, a ∈ s → ∃ b ∈ t, r a b
a : α
ha✝ : a ∈ x ::ₘ s
ha : a ∈ s
b : β
hbt : b ∈ t
hab : r a b
⊢ ∃ b ∈ y ::ₘ t, r a b

Next tactic:
exact ⟨b, mem_cons.2 (Or.inr hbt), hab⟩
theorem rel_of_forall {m1 m2 : Multiset α} {r : α → α → Prop} (h : ∀ a b, a ∈ m1 → b ∈ m2 → r a b)
    (hc : card m1 = card m2) : m1.Rel r m2 := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m1 m2 : Multiset α
r : α → α → Prop
h : ∀ (a b : α), a ∈ m1 → b ∈ m2 → r a b
hc : card m1 = card m2
⊢ Rel r m1 m2

Next tactic:
revert m1
theorem rel_of_forall {m1 m2 : Multiset α} {r : α → α → Prop} (h : ∀ a b, a ∈ m1 → b ∈ m2 → r a b)
    (hc : card m1 = card m2) : m1.Rel r m2 := by
  revert m1
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m2 : Multiset α
r : α → α → Prop
⊢ ∀ {m1 : Multiset α}, (∀ (a b : α), a ∈ m1 → b ∈ m2 → r a b) → card m1 = card m2 → Rel r m1 m2

Next tactic:
refine' @(m2.induction_on _ _)
theorem rel_of_forall {m1 m2 : Multiset α} {r : α → α → Prop} (h : ∀ a b, a ∈ m1 → b ∈ m2 → r a b)
    (hc : card m1 = card m2) : m1.Rel r m2 := by
  revert m1
  refine' @(m2.induction_on _ _)
  · 

Proof state:
case refine'_1
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m2 : Multiset α
r : α → α → Prop
⊢ ∀ {m1 : Multiset α}, (∀ (a b : α), a ∈ m1 → b ∈ 0 → r a b) → card m1 = card 0 → Rel r m1 0

Next tactic:
intro m _h hc
theorem rel_of_forall {m1 m2 : Multiset α} {r : α → α → Prop} (h : ∀ a b, a ∈ m1 → b ∈ m2 → r a b)
    (hc : card m1 = card m2) : m1.Rel r m2 := by
  revert m1
  refine' @(m2.induction_on _ _)
  · intro m _h hc
    

Proof state:
case refine'_1
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m2 : Multiset α
r : α → α → Prop
m : Multiset α
_h : ∀ (a b : α), a ∈ m → b ∈ 0 → r a b
hc : card m = card 0
⊢ Rel r m 0

Next tactic:
rw [rel_zero_right, ← card_eq_zero, hc, card_zero]
theorem rel_of_forall {m1 m2 : Multiset α} {r : α → α → Prop} (h : ∀ a b, a ∈ m1 → b ∈ m2 → r a b)
    (hc : card m1 = card m2) : m1.Rel r m2 := by
  revert m1
  refine' @(m2.induction_on _ _)
  · intro m _h hc
    rw [rel_zero_right, ← card_eq_zero, hc, card_zero]
  · 

Proof state:
case refine'_2
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m2 : Multiset α
r : α → α → Prop
⊢ ∀ ⦃a : α⦄ {s : Multiset α},
    (∀ {m1 : Multiset α}, (∀ (a b : α), a ∈ m1 → b ∈ s → r a b) → card m1 = card s → Rel r m1 s) →
      ∀ {m1 : Multiset α},
        (∀ (a_2 b : α), a_2 ∈ m1 → b ∈ a ::ₘ s → r a_2 b) → card m1 = card (a ::ₘ s) → Rel r m1 (a ::ₘ s)

Next tactic:
intro a t ih m h hc
theorem rel_of_forall {m1 m2 : Multiset α} {r : α → α → Prop} (h : ∀ a b, a ∈ m1 → b ∈ m2 → r a b)
    (hc : card m1 = card m2) : m1.Rel r m2 := by
  revert m1
  refine' @(m2.induction_on _ _)
  · intro m _h hc
    rw [rel_zero_right, ← card_eq_zero, hc, card_zero]
  · intro a t ih m h hc
    

Proof state:
case refine'_2
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m2 : Multiset α
r : α → α → Prop
a : α
t : Multiset α
ih : ∀ {m1 : Multiset α}, (∀ (a b : α), a ∈ m1 → b ∈ t → r a b) → card m1 = card t → Rel r m1 t
m : Multiset α
h : ∀ (a_1 b : α), a_1 ∈ m → b ∈ a ::ₘ t → r a_1 b
hc : card m = card (a ::ₘ t)
⊢ Rel r m (a ::ₘ t)

Next tactic:
rw [card_cons] at hc
theorem rel_of_forall {m1 m2 : Multiset α} {r : α → α → Prop} (h : ∀ a b, a ∈ m1 → b ∈ m2 → r a b)
    (hc : card m1 = card m2) : m1.Rel r m2 := by
  revert m1
  refine' @(m2.induction_on _ _)
  · intro m _h hc
    rw [rel_zero_right, ← card_eq_zero, hc, card_zero]
  · intro a t ih m h hc
    rw [card_cons] at hc
    

Proof state:
case refine'_2
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m2 : Multiset α
r : α → α → Prop
a : α
t : Multiset α
ih : ∀ {m1 : Multiset α}, (∀ (a b : α), a ∈ m1 → b ∈ t → r a b) → card m1 = card t → Rel r m1 t
m : Multiset α
h : ∀ (a_1 b : α), a_1 ∈ m → b ∈ a ::ₘ t → r a_1 b
hc : card m = card t + 1
⊢ Rel r m (a ::ₘ t)

Next tactic:
obtain ⟨b, hb⟩ := card_pos_iff_exists_mem.1 (show 0 < card m from hc.symm ▸ Nat.succ_pos _)
theorem rel_of_forall {m1 m2 : Multiset α} {r : α → α → Prop} (h : ∀ a b, a ∈ m1 → b ∈ m2 → r a b)
    (hc : card m1 = card m2) : m1.Rel r m2 := by
  revert m1
  refine' @(m2.induction_on _ _)
  · intro m _h hc
    rw [rel_zero_right, ← card_eq_zero, hc, card_zero]
  · intro a t ih m h hc
    rw [card_cons] at hc
    obtain ⟨b, hb⟩ := card_pos_iff_exists_mem.1 (show 0 < card m from hc.symm ▸ Nat.succ_pos _)
    

Proof state:
case refine'_2.intro
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m2 : Multiset α
r : α → α → Prop
a : α
t : Multiset α
ih : ∀ {m1 : Multiset α}, (∀ (a b : α), a ∈ m1 → b ∈ t → r a b) → card m1 = card t → Rel r m1 t
m : Multiset α
h : ∀ (a_1 b : α), a_1 ∈ m → b ∈ a ::ₘ t → r a_1 b
hc : card m = card t + 1
b : α
hb : b ∈ m
⊢ Rel r m (a ::ₘ t)

Next tactic:
obtain ⟨m', rfl⟩ := exists_cons_of_mem hb
theorem rel_of_forall {m1 m2 : Multiset α} {r : α → α → Prop} (h : ∀ a b, a ∈ m1 → b ∈ m2 → r a b)
    (hc : card m1 = card m2) : m1.Rel r m2 := by
  revert m1
  refine' @(m2.induction_on _ _)
  · intro m _h hc
    rw [rel_zero_right, ← card_eq_zero, hc, card_zero]
  · intro a t ih m h hc
    rw [card_cons] at hc
    obtain ⟨b, hb⟩ := card_pos_iff_exists_mem.1 (show 0 < card m from hc.symm ▸ Nat.succ_pos _)
    obtain ⟨m', rfl⟩ := exists_cons_of_mem hb
    

Proof state:
case refine'_2.intro.intro
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m2 : Multiset α
r : α → α → Prop
a : α
t : Multiset α
ih : ∀ {m1 : Multiset α}, (∀ (a b : α), a ∈ m1 → b ∈ t → r a b) → card m1 = card t → Rel r m1 t
b : α
m' : Multiset α
h : ∀ (a_1 b_1 : α), a_1 ∈ b ::ₘ m' → b_1 ∈ a ::ₘ t → r a_1 b_1
hc : card (b ::ₘ m') = card t + 1
hb : b ∈ b ::ₘ m'
⊢ Rel r (b ::ₘ m') (a ::ₘ t)

Next tactic:
refine' rel_cons_right.mpr ⟨b, m', h _ _ hb (mem_cons_self _ _), ih _ _, rfl⟩
theorem rel_of_forall {m1 m2 : Multiset α} {r : α → α → Prop} (h : ∀ a b, a ∈ m1 → b ∈ m2 → r a b)
    (hc : card m1 = card m2) : m1.Rel r m2 := by
  revert m1
  refine' @(m2.induction_on _ _)
  · intro m _h hc
    rw [rel_zero_right, ← card_eq_zero, hc, card_zero]
  · intro a t ih m h hc
    rw [card_cons] at hc
    obtain ⟨b, hb⟩ := card_pos_iff_exists_mem.1 (show 0 < card m from hc.symm ▸ Nat.succ_pos _)
    obtain ⟨m', rfl⟩ := exists_cons_of_mem hb
    refine' rel_cons_right.mpr ⟨b, m', h _ _ hb (mem_cons_self _ _), ih _ _, rfl⟩
    · 

Proof state:
case refine'_2.intro.intro.refine'_1
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m2 : Multiset α
r : α → α → Prop
a : α
t : Multiset α
ih : ∀ {m1 : Multiset α}, (∀ (a b : α), a ∈ m1 → b ∈ t → r a b) → card m1 = card t → Rel r m1 t
b : α
m' : Multiset α
h : ∀ (a_1 b_1 : α), a_1 ∈ b ::ₘ m' → b_1 ∈ a ::ₘ t → r a_1 b_1
hc : card (b ::ₘ m') = card t + 1
hb : b ∈ b ::ₘ m'
⊢ ∀ (a b : α), a ∈ m' → b ∈ t → r a b

Next tactic:
exact fun _ _ ha hb => h _ _ (mem_cons_of_mem ha) (mem_cons_of_mem hb)
theorem rel_of_forall {m1 m2 : Multiset α} {r : α → α → Prop} (h : ∀ a b, a ∈ m1 → b ∈ m2 → r a b)
    (hc : card m1 = card m2) : m1.Rel r m2 := by
  revert m1
  refine' @(m2.induction_on _ _)
  · intro m _h hc
    rw [rel_zero_right, ← card_eq_zero, hc, card_zero]
  · intro a t ih m h hc
    rw [card_cons] at hc
    obtain ⟨b, hb⟩ := card_pos_iff_exists_mem.1 (show 0 < card m from hc.symm ▸ Nat.succ_pos _)
    obtain ⟨m', rfl⟩ := exists_cons_of_mem hb
    refine' rel_cons_right.mpr ⟨b, m', h _ _ hb (mem_cons_self _ _), ih _ _, rfl⟩
    · exact fun _ _ ha hb => h _ _ (mem_cons_of_mem ha) (mem_cons_of_mem hb)
    · 

Proof state:
case refine'_2.intro.intro.refine'_2
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m2 : Multiset α
r : α → α → Prop
a : α
t : Multiset α
ih : ∀ {m1 : Multiset α}, (∀ (a b : α), a ∈ m1 → b ∈ t → r a b) → card m1 = card t → Rel r m1 t
b : α
m' : Multiset α
h : ∀ (a_1 b_1 : α), a_1 ∈ b ::ₘ m' → b_1 ∈ a ::ₘ t → r a_1 b_1
hc : card (b ::ₘ m') = card t + 1
hb : b ∈ b ::ₘ m'
⊢ card m' = card t

Next tactic:
simpa using hc
theorem rel_replicate_left {m : Multiset α} {a : α} {r : α → α → Prop} {n : ℕ} :
    (replicate n a).Rel r m ↔ card m = n ∧ ∀ x, x ∈ m → r a x :=
  ⟨fun h =>
    ⟨(card_eq_card_of_rel h).symm.trans (card_replicate _ _), fun x hx => by
      

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m : Multiset α
a : α
r : α → α → Prop
n : ℕ
h : Rel r (replicate n a) m
x : α
hx : x ∈ m
⊢ r a x

Next tactic:
obtain ⟨b, hb1, hb2⟩ := exists_mem_of_rel_of_mem (rel_flip.2 h) hx
theorem rel_replicate_left {m : Multiset α} {a : α} {r : α → α → Prop} {n : ℕ} :
    (replicate n a).Rel r m ↔ card m = n ∧ ∀ x, x ∈ m → r a x :=
  ⟨fun h =>
    ⟨(card_eq_card_of_rel h).symm.trans (card_replicate _ _), fun x hx => by
      obtain ⟨b, hb1, hb2⟩ := exists_mem_of_rel_of_mem (rel_flip.2 h) hx
      

Proof state:
case intro.intro
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m : Multiset α
a : α
r : α → α → Prop
n : ℕ
h : Rel r (replicate n a) m
x : α
hx : x ∈ m
b : α
hb1 : b ∈ replicate n a
hb2 : flip r x b
⊢ r a x

Next tactic:
rwa [eq_of_mem_replicate hb1] at hb2
protected nonrec -- Porting note: added
theorem Rel.trans (r : α → α → Prop) [IsTrans α r] {s t u : Multiset α} (r1 : Rel r s t)
    (r2 : Rel r t u) : Rel r s u := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
r : α → α → Prop
inst✝ : IsTrans α r
s t u : Multiset α
r1 : Rel r s t
r2 : Rel r t u
⊢ Rel r s u

Next tactic:
induction' t using Multiset.induction_on with x t ih generalizing s u
protected nonrec -- Porting note: added
theorem Rel.trans (r : α → α → Prop) [IsTrans α r] {s t u : Multiset α} (r1 : Rel r s t)
    (r2 : Rel r t u) : Rel r s u := by
  induction' t using Multiset.induction_on with x t ih generalizing s u
  · 

Proof state:
case empty
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
r : α → α → Prop
inst✝ : IsTrans α r
s u : Multiset α
r1 : Rel r s 0
r2 : Rel r 0 u
⊢ Rel r s u

Next tactic:
rw [rel_zero_right.mp r1, rel_zero_left.mp r2, rel_zero_left]
protected nonrec -- Porting note: added
theorem Rel.trans (r : α → α → Prop) [IsTrans α r] {s t u : Multiset α} (r1 : Rel r s t)
    (r2 : Rel r t u) : Rel r s u := by
  induction' t using Multiset.induction_on with x t ih generalizing s u
  · rw [rel_zero_right.mp r1, rel_zero_left.mp r2, rel_zero_left]
  · 

Proof state:
case cons
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
r : α → α → Prop
inst✝ : IsTrans α r
x : α
t : Multiset α
ih : ∀ {s u : Multiset α}, Rel r s t → Rel r t u → Rel r s u
s u : Multiset α
r1 : Rel r s (x ::ₘ t)
r2 : Rel r (x ::ₘ t) u
⊢ Rel r s u

Next tactic:
obtain ⟨a, as, ha1, ha2, rfl⟩ := rel_cons_right.mp r1
protected nonrec -- Porting note: added
theorem Rel.trans (r : α → α → Prop) [IsTrans α r] {s t u : Multiset α} (r1 : Rel r s t)
    (r2 : Rel r t u) : Rel r s u := by
  induction' t using Multiset.induction_on with x t ih generalizing s u
  · rw [rel_zero_right.mp r1, rel_zero_left.mp r2, rel_zero_left]
  · obtain ⟨a, as, ha1, ha2, rfl⟩ := rel_cons_right.mp r1
    

Proof state:
case cons.intro.intro.intro.intro
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
r : α → α → Prop
inst✝ : IsTrans α r
x : α
t : Multiset α
ih : ∀ {s u : Multiset α}, Rel r s t → Rel r t u → Rel r s u
u : Multiset α
r2 : Rel r (x ::ₘ t) u
a : α
as : Multiset α
ha1 : r a x
ha2 : Rel r as t
r1 : Rel r (a ::ₘ as) (x ::ₘ t)
⊢ Rel r (a ::ₘ as) u

Next tactic:
obtain ⟨b, bs, hb1, hb2, rfl⟩ := rel_cons_left.mp r2
protected nonrec -- Porting note: added
theorem Rel.trans (r : α → α → Prop) [IsTrans α r] {s t u : Multiset α} (r1 : Rel r s t)
    (r2 : Rel r t u) : Rel r s u := by
  induction' t using Multiset.induction_on with x t ih generalizing s u
  · rw [rel_zero_right.mp r1, rel_zero_left.mp r2, rel_zero_left]
  · obtain ⟨a, as, ha1, ha2, rfl⟩ := rel_cons_right.mp r1
    obtain ⟨b, bs, hb1, hb2, rfl⟩ := rel_cons_left.mp r2
    

Proof state:
case cons.intro.intro.intro.intro.intro.intro.intro.intro
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
r : α → α → Prop
inst✝ : IsTrans α r
x : α
t : Multiset α
ih : ∀ {s u : Multiset α}, Rel r s t → Rel r t u → Rel r s u
a : α
as : Multiset α
ha1 : r a x
ha2 : Rel r as t
r1 : Rel r (a ::ₘ as) (x ::ₘ t)
b : α
bs : Multiset α
hb1 : r x b
hb2 : Rel r t bs
r2 : Rel r (x ::ₘ t) (b ::ₘ bs)
⊢ Rel r (a ::ₘ as) (b ::ₘ bs)

Next tactic:
exact Multiset.Rel.cons (_root_.trans ha1 hb1) (ih ha2 hb2)
theorem Rel.countP_eq (r : α → α → Prop) [IsTrans α r] [IsSymm α r] {s t : Multiset α} (x : α)
    [DecidablePred (r x)] (h : Rel r s t) : countP (r x) s = countP (r x) t := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
r : α → α → Prop
inst✝² : IsTrans α r
inst✝¹ : IsSymm α r
s t : Multiset α
x : α
inst✝ : DecidablePred (r x)
h : Rel r s t
⊢ countP (r x) s = countP (r x) t

Next tactic:
induction' s using Multiset.induction_on with y s ih generalizing t
theorem Rel.countP_eq (r : α → α → Prop) [IsTrans α r] [IsSymm α r] {s t : Multiset α} (x : α)
    [DecidablePred (r x)] (h : Rel r s t) : countP (r x) s = countP (r x) t := by
  induction' s using Multiset.induction_on with y s ih generalizing t
  · 

Proof state:
case empty
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
r : α → α → Prop
inst✝² : IsTrans α r
inst✝¹ : IsSymm α r
x : α
inst✝ : DecidablePred (r x)
t : Multiset α
h : Rel r 0 t
⊢ countP (r x) 0 = countP (r x) t

Next tactic:
rw [rel_zero_left.mp h]
theorem Rel.countP_eq (r : α → α → Prop) [IsTrans α r] [IsSymm α r] {s t : Multiset α} (x : α)
    [DecidablePred (r x)] (h : Rel r s t) : countP (r x) s = countP (r x) t := by
  induction' s using Multiset.induction_on with y s ih generalizing t
  · rw [rel_zero_left.mp h]
  · 

Proof state:
case cons
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
r : α → α → Prop
inst✝² : IsTrans α r
inst✝¹ : IsSymm α r
x : α
inst✝ : DecidablePred (r x)
y : α
s : Multiset α
ih : ∀ {t : Multiset α}, Rel r s t → countP (r x) s = countP (r x) t
t : Multiset α
h : Rel r (y ::ₘ s) t
⊢ countP (r x) (y ::ₘ s) = countP (r x) t

Next tactic:
obtain ⟨b, bs, hb1, hb2, rfl⟩ := rel_cons_left.mp h
theorem Rel.countP_eq (r : α → α → Prop) [IsTrans α r] [IsSymm α r] {s t : Multiset α} (x : α)
    [DecidablePred (r x)] (h : Rel r s t) : countP (r x) s = countP (r x) t := by
  induction' s using Multiset.induction_on with y s ih generalizing t
  · rw [rel_zero_left.mp h]
  · obtain ⟨b, bs, hb1, hb2, rfl⟩ := rel_cons_left.mp h
    

Proof state:
case cons.intro.intro.intro.intro
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
r : α → α → Prop
inst✝² : IsTrans α r
inst✝¹ : IsSymm α r
x : α
inst✝ : DecidablePred (r x)
y : α
s : Multiset α
ih : ∀ {t : Multiset α}, Rel r s t → countP (r x) s = countP (r x) t
b : α
bs : Multiset α
hb1 : r y b
hb2 : Rel r s bs
h : Rel r (y ::ₘ s) (b ::ₘ bs)
⊢ countP (r x) (y ::ₘ s) = countP (r x) (b ::ₘ bs)

Next tactic:
rw [countP_cons, countP_cons, ih hb2]
theorem Rel.countP_eq (r : α → α → Prop) [IsTrans α r] [IsSymm α r] {s t : Multiset α} (x : α)
    [DecidablePred (r x)] (h : Rel r s t) : countP (r x) s = countP (r x) t := by
  induction' s using Multiset.induction_on with y s ih generalizing t
  · rw [rel_zero_left.mp h]
  · obtain ⟨b, bs, hb1, hb2, rfl⟩ := rel_cons_left.mp h
    rw [countP_cons, countP_cons, ih hb2]
    

Proof state:
case cons.intro.intro.intro.intro
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
r : α → α → Prop
inst✝² : IsTrans α r
inst✝¹ : IsSymm α r
x : α
inst✝ : DecidablePred (r x)
y : α
s : Multiset α
ih : ∀ {t : Multiset α}, Rel r s t → countP (r x) s = countP (r x) t
b : α
bs : Multiset α
hb1 : r y b
hb2 : Rel r s bs
h : Rel r (y ::ₘ s) (b ::ₘ bs)
⊢ (countP (r x) bs + if r x y then 1 else 0) = countP (r x) bs + if r x b then 1 else 0

Next tactic:
simp only [decide_eq_true_eq, add_right_inj]
theorem Rel.countP_eq (r : α → α → Prop) [IsTrans α r] [IsSymm α r] {s t : Multiset α} (x : α)
    [DecidablePred (r x)] (h : Rel r s t) : countP (r x) s = countP (r x) t := by
  induction' s using Multiset.induction_on with y s ih generalizing t
  · rw [rel_zero_left.mp h]
  · obtain ⟨b, bs, hb1, hb2, rfl⟩ := rel_cons_left.mp h
    rw [countP_cons, countP_cons, ih hb2]
    simp only [decide_eq_true_eq, add_right_inj]
    

Proof state:
case cons.intro.intro.intro.intro
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
r : α → α → Prop
inst✝² : IsTrans α r
inst✝¹ : IsSymm α r
x : α
inst✝ : DecidablePred (r x)
y : α
s : Multiset α
ih : ∀ {t : Multiset α}, Rel r s t → countP (r x) s = countP (r x) t
b : α
bs : Multiset α
hb1 : r y b
hb2 : Rel r s bs
h : Rel r (y ::ₘ s) (b ::ₘ bs)
⊢ (if r x y then 1 else 0) = if r x b then 1 else 0

Next tactic:
refine' (if_congr ⟨fun h => _root_.trans h hb1, fun h => _root_.trans h (symm hb1)⟩ rfl rfl)
theorem map_eq_map {f : α → β} (hf : Function.Injective f) {s t : Multiset α} :
    s.map f = t.map f ↔ s = t := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
f : α → β
hf : Injective f
s t : Multiset α
⊢ map f s = map f t ↔ s = t

Next tactic:
rw [← rel_eq, ← rel_eq, rel_map]
theorem map_eq_map {f : α → β} (hf : Function.Injective f) {s t : Multiset α} :
    s.map f = t.map f ↔ s = t := by
  rw [← rel_eq, ← rel_eq, rel_map]
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
f : α → β
hf : Injective f
s t : Multiset α
⊢ Rel (fun a b => f a = f b) s t ↔ Rel (fun x x_1 => x = x_1) s t

Next tactic:
simp only [hf.eq_iff]
lemma filter_attach' (s : Multiset α) (p : {a // a ∈ s} → Prop) [DecidableEq α]
    [DecidablePred p] :
    s.attach.filter p =
      (s.filter fun x ↦ ∃ h, p ⟨x, h⟩).attach.map (Subtype.map id fun x ↦ mem_of_mem_filter) := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
s : Multiset α
p : { a // a ∈ s } → Prop
inst✝¹ : DecidableEq α
inst✝ : DecidablePred p
⊢ filter p (attach s) =
    map (Subtype.map id (_ : ∀ x ∈ filter (fun x => ∃ (h : x ∈ s), p { val := x, property := h }) s, x ∈ s))
      (attach (filter (fun x => ∃ (h : x ∈ s), p { val := x, property := h }) s))

Next tactic:
classical
  refine' Multiset.map_injective Subtype.val_injective _
  rw [map_filter' _ Subtype.val_injective]
  simp only [Function.comp, Subtype.exists, coe_mk,
    exists_and_right, exists_eq_right, attach_map_val, map_map, map_coe, id.def]
lemma filter_attach' (s : Multiset α) (p : {a // a ∈ s} → Prop) [DecidableEq α]
    [DecidablePred p] :
    s.attach.filter p =
      (s.filter fun x ↦ ∃ h, p ⟨x, h⟩).attach.map (Subtype.map id fun x ↦ mem_of_mem_filter) := by
  classical
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
s : Multiset α
p : { a // a ∈ s } → Prop
inst✝¹ : DecidableEq α
inst✝ : DecidablePred p
⊢ filter p (attach s) =
    map (Subtype.map id (_ : ∀ x ∈ filter (fun x => ∃ (h : x ∈ s), p { val := x, property := h }) s, x ∈ s))
      (attach (filter (fun x => ∃ (h : x ∈ s), p { val := x, property := h }) s))

Next tactic:
refine' Multiset.map_injective Subtype.val_injective _
lemma filter_attach' (s : Multiset α) (p : {a // a ∈ s} → Prop) [DecidableEq α]
    [DecidablePred p] :
    s.attach.filter p =
      (s.filter fun x ↦ ∃ h, p ⟨x, h⟩).attach.map (Subtype.map id fun x ↦ mem_of_mem_filter) := by
  classical
  refine' Multiset.map_injective Subtype.val_injective _
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
s : Multiset α
p : { a // a ∈ s } → Prop
inst✝¹ : DecidableEq α
inst✝ : DecidablePred p
⊢ map val (filter p (attach s)) =
    map val
      (map (Subtype.map id (_ : ∀ x ∈ filter (fun x => ∃ (h : x ∈ s), p { val := x, property := h }) s, x ∈ s))
        (attach (filter (fun x => ∃ (h : x ∈ s), p { val := x, property := h }) s)))

Next tactic:
rw [map_filter' _ Subtype.val_injective]
lemma filter_attach' (s : Multiset α) (p : {a // a ∈ s} → Prop) [DecidableEq α]
    [DecidablePred p] :
    s.attach.filter p =
      (s.filter fun x ↦ ∃ h, p ⟨x, h⟩).attach.map (Subtype.map id fun x ↦ mem_of_mem_filter) := by
  classical
  refine' Multiset.map_injective Subtype.val_injective _
  rw [map_filter' _ Subtype.val_injective]
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
s : Multiset α
p : { a // a ∈ s } → Prop
inst✝¹ : DecidableEq α
inst✝ : DecidablePred p
⊢ filter (fun b => ∃ a, p a ∧ ↑a = b) (map val (attach s)) =
    map val
      (map (Subtype.map id (_ : ∀ x ∈ filter (fun x => ∃ (h : x ∈ s), p { val := x, property := h }) s, x ∈ s))
        (attach (filter (fun x => ∃ (h : x ∈ s), p { val := x, property := h }) s)))

Next tactic:
simp only [Function.comp, Subtype.exists, coe_mk,
    exists_and_right, exists_eq_right, attach_map_val, map_map, map_coe, id.def]
theorem map_mk_eq_map_mk_of_rel {r : α → α → Prop} {s t : Multiset α} (hst : s.Rel r t) :
    s.map (Quot.mk r) = t.map (Quot.mk r) :=
  Rel.recOn hst rfl fun hab _hst ih => by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
r : α → α → Prop
s t : Multiset α
hst : Rel r s t
a✝ b✝ : α
as✝ bs✝ : Multiset α
hab : r a✝ b✝
_hst : Rel r as✝ bs✝
ih : map (Quot.mk r) as✝ = map (Quot.mk r) bs✝
⊢ map (Quot.mk r) (a✝ ::ₘ as✝) = map (Quot.mk r) (b✝ ::ₘ bs✝)

Next tactic:
simp [ih, Quot.sound hab]
theorem disjoint_iff_ne {s t : Multiset α} : Disjoint s t ↔ ∀ a ∈ s, ∀ b ∈ t, a ≠ b := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
s t : Multiset α
⊢ Disjoint s t ↔ ∀ a ∈ s, ∀ b ∈ t, a ≠ b

Next tactic:
simp [disjoint_left, imp_not_comm]
@[simp]
theorem singleton_disjoint {l : Multiset α} {a : α} : Disjoint {a} l ↔ a ∉ l := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
l : Multiset α
a : α
⊢ Disjoint {a} l ↔ a ∉ l

Next tactic:
simp [Disjoint]
@[simp]
theorem disjoint_singleton {l : Multiset α} {a : α} : Disjoint l {a} ↔ a ∉ l := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
l : Multiset α
a : α
⊢ Disjoint l {a} ↔ a ∉ l

Next tactic:
rw [disjoint_comm, singleton_disjoint]
@[simp]
theorem disjoint_add_left {s t u : Multiset α} : Disjoint (s + t) u ↔ Disjoint s u ∧ Disjoint t u :=
  by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
s t u : Multiset α
⊢ Disjoint (s + t) u ↔ Disjoint s u ∧ Disjoint t u

Next tactic:
simp [Disjoint, or_imp, forall_and]
@[simp]
theorem disjoint_add_right {s t u : Multiset α} :
    Disjoint s (t + u) ↔ Disjoint s t ∧ Disjoint s u := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
s t u : Multiset α
⊢ Disjoint s (t + u) ↔ Disjoint s t ∧ Disjoint s u

Next tactic:
rw [disjoint_comm, disjoint_add_left]