l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem inter_replicate (s : Multiset α) (n : ℕ) (x : α) :
    s ∩ replicate n x = replicate (min (s.count x) n) x := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s✝ s : Multiset α
n : ℕ
x : α
⊢ s ∩ replicate n x = replicate (min (count x s) n) x

Next tactic:
rw [inter_comm, replicate_inter, min_comm]
@[ext]
theorem addHom_ext [AddZeroClass β] ⦃f g : Multiset α →+ β⦄ (h : ∀ x, f {x} = g {x}) : f = g := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : AddZeroClass β
f g : Multiset α →+ β
h : ∀ (x : α), f {x} = g {x}
⊢ f = g

Next tactic:
ext s
@[ext]
theorem addHom_ext [AddZeroClass β] ⦃f g : Multiset α →+ β⦄ (h : ∀ x, f {x} = g {x}) : f = g := by
  ext s
  

Proof state:
case h
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : AddZeroClass β
f g : Multiset α →+ β
h : ∀ (x : α), f {x} = g {x}
s : Multiset α
⊢ f s = g s

Next tactic:
induction' s using Multiset.induction_on with a s ih
@[ext]
theorem addHom_ext [AddZeroClass β] ⦃f g : Multiset α →+ β⦄ (h : ∀ x, f {x} = g {x}) : f = g := by
  ext s
  induction' s using Multiset.induction_on with a s ih
  · 

Proof state:
case h.empty
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : AddZeroClass β
f g : Multiset α →+ β
h : ∀ (x : α), f {x} = g {x}
⊢ f 0 = g 0

Next tactic:
simp only [_root_.map_zero]
@[ext]
theorem addHom_ext [AddZeroClass β] ⦃f g : Multiset α →+ β⦄ (h : ∀ x, f {x} = g {x}) : f = g := by
  ext s
  induction' s using Multiset.induction_on with a s ih
  · simp only [_root_.map_zero]
  · 

Proof state:
case h.cons
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : AddZeroClass β
f g : Multiset α →+ β
h : ∀ (x : α), f {x} = g {x}
a : α
s : Multiset α
ih : f s = g s
⊢ f (a ::ₘ s) = g (a ::ₘ s)

Next tactic:
simp only [← singleton_add, _root_.map_add, ih, h]
@[simp]
theorem map_le_map_iff {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:
classical
    refine' ⟨fun h => le_iff_count.mpr fun a => _, map_le_map⟩
    simpa [count_map_eq_count' f _ hf] using le_iff_count.mp h (f a)
@[simp]
theorem map_le_map_iff {f : α → β} (hf : Function.Injective f) {s t : Multiset α} :
    s.map f ≤ t.map f ↔ s ≤ t := by
  classical
    

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:
refine' ⟨fun h => le_iff_count.mpr fun a => _, map_le_map⟩
@[simp]
theorem map_le_map_iff {f : α → β} (hf : Function.Injective f) {s t : Multiset α} :
    s.map f ≤ t.map f ↔ s ≤ t := by
  classical
    refine' ⟨fun h => le_iff_count.mpr fun a => _, map_le_map⟩
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
f : α → β
hf : Injective f
s t : Multiset α
h : map f s ≤ map f t
a : α
⊢ count a s ≤ count a t

Next tactic:
simpa [count_map_eq_count' f _ hf] using le_iff_count.mp h (f a)
theorem count_eq_card_filter_eq [DecidableEq α] (s : Multiset α) (a : α) :
    s.count a = card (s.filter (a = ·)) := by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
inst✝ : DecidableEq α
s : Multiset α
a : α
⊢ count a s = card (filter (fun x => a = x) s)

Next tactic:
rw [count, countP_eq_card_filter]
/--
Mapping a multiset through a predicate and counting the `True`s yields the cardinality of the set
filtered by the predicate. Note that this uses the notion of a multiset of `Prop`s - due to the
decidability requirements of `count`, the decidability instance on the LHS is different from the
RHS. In particular, the decidability instance on the left leaks `Classical.decEq`.
See [here](https://github.com/leanprover-community/mathlib/pull/11306#discussion_r782286812)
for more discussion.
-/
@[simp]
theorem map_count_True_eq_filter_card (s : Multiset α) (p : α → Prop) [DecidablePred p] :
    (s.map p).count True = card (s.filter p) := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
s : Multiset α
p : α → Prop
inst✝ : DecidablePred p
⊢ count True (map p s) = card (filter p s)

Next tactic:
simp only [count_eq_card_filter_eq, map_filter, card_map, Function.comp.left_id,
    eq_true_eq_id, Function.comp_apply]
theorem rel_refl_of_refl_on {m : Multiset α} {r : α → α → Prop} : (∀ x ∈ m, r x x) → Rel r m m := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m : Multiset α
r : α → α → Prop
⊢ (∀ x ∈ m, r x x) → Rel r m m

Next tactic:
refine' m.induction_on _ _
theorem rel_refl_of_refl_on {m : Multiset α} {r : α → α → Prop} : (∀ x ∈ m, r x x) → Rel r m m := by
  refine' m.induction_on _ _
  · 

Proof state:
case refine'_1
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m : Multiset α
r : α → α → Prop
⊢ (∀ x ∈ 0, r x x) → Rel r 0 0

Next tactic:
intros
theorem rel_refl_of_refl_on {m : Multiset α} {r : α → α → Prop} : (∀ x ∈ m, r x x) → Rel r m m := by
  refine' m.induction_on _ _
  · intros
    

Proof state:
case refine'_1
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m : Multiset α
r : α → α → Prop
a✝ : ∀ x ∈ 0, r x x
⊢ Rel r 0 0

Next tactic:
apply Rel.zero
theorem rel_refl_of_refl_on {m : Multiset α} {r : α → α → Prop} : (∀ x ∈ m, r x x) → Rel r m m := by
  refine' m.induction_on _ _
  · intros
    apply Rel.zero
  · 

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

Next tactic:
intro a m ih h
theorem rel_refl_of_refl_on {m : Multiset α} {r : α → α → Prop} : (∀ x ∈ m, r x x) → Rel r m m := by
  refine' m.induction_on _ _
  · intros
    apply Rel.zero
  · intro a m ih h
    

Proof state:
case refine'_2
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p : γ → δ → Prop
m✝ : Multiset α
r : α → α → Prop
a : α
m : Multiset α
ih : (∀ x ∈ m, r x x) → Rel r m m
h : ∀ x ∈ a ::ₘ m, r x x
⊢ Rel r (a ::ₘ m) (a ::ₘ m)

Next tactic:
exact Rel.cons (h _ (mem_cons_self _ _)) (ih fun _ ha => h _ (mem_cons_of_mem ha))
theorem rel_eq {s t : Multiset α} : Rel (· = ·) s t ↔ s = t := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s t : Multiset α
⊢ Rel (fun x x_1 => x = x_1) s t ↔ s = t

Next tactic:
constructor
theorem rel_eq {s t : Multiset α} : Rel (· = ·) s t ↔ s = t := by
  constructor
  · 

Proof state:
case mp
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s t : Multiset α
⊢ Rel (fun x x_1 => x = x_1) s t → s = t

Next tactic:
intro h
theorem rel_eq {s t : Multiset α} : Rel (· = ·) s t ↔ s = t := by
  constructor
  · intro h
    

Proof state:
case mp
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s t : Multiset α
h : Rel (fun x x_1 => x = x_1) s t
⊢ s = t

Next tactic:
induction h
theorem rel_eq {s t : Multiset α} : Rel (· = ·) s t ↔ s = t := by
  constructor
  · intro h
    induction h <;> 

Proof state:
case mp.zero
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s t : Multiset α
⊢ 0 = 0

Next tactic:
simp [*]
theorem rel_eq {s t : Multiset α} : Rel (· = ·) s t ↔ s = t := by
  constructor
  · intro h
    induction h <;> 

Proof state:
case mp.cons
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s t : Multiset α
a✝² b✝ : α
as✝ bs✝ : Multiset α
a✝¹ : a✝² = b✝
a✝ : Rel (fun x x_1 => x = x_1) as✝ bs✝
a_ih✝ : as✝ = bs✝
⊢ a✝² ::ₘ as✝ = b✝ ::ₘ bs✝

Next tactic:
simp [*]
theorem rel_eq {s t : Multiset α} : Rel (· = ·) s t ↔ s = t := by
  constructor
  · intro h
    induction h <;> simp [*]
  · 

Proof state:
case mpr
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s t : Multiset α
⊢ s = t → Rel (fun x x_1 => x = x_1) s t

Next tactic:
intro h
theorem rel_eq {s t : Multiset α} : Rel (· = ·) s t ↔ s = t := by
  constructor
  · intro h
    induction h <;> simp [*]
  · intro h
    

Proof state:
case mpr
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s t : Multiset α
h : s = t
⊢ Rel (fun x x_1 => x = x_1) s t

Next tactic:
subst h
theorem rel_eq {s t : Multiset α} : Rel (· = ·) s t ↔ s = t := by
  constructor
  · intro h
    induction h <;> simp [*]
  · intro h
    subst h
    

Proof state:
case mpr
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s : Multiset α
⊢ Rel (fun x x_1 => x = x_1) s s

Next tactic:
exact rel_eq_refl
theorem Rel.mono {r p : α → β → Prop} {s t} (hst : Rel r s t)
    (h : ∀ a ∈ s, ∀ b ∈ t, r a b → p a b) : Rel p s t := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p✝ : γ → δ → Prop
r p : α → β → Prop
s : Multiset α
t : Multiset β
hst : Rel r s t
h : ∀ a ∈ s, ∀ b ∈ t, r a b → p a b
⊢ Rel p s t

Next tactic:
induction hst
theorem Rel.mono {r p : α → β → Prop} {s t} (hst : Rel r s t)
    (h : ∀ a ∈ s, ∀ b ∈ t, r a b → p a b) : Rel p s t := by
  induction hst
  

Proof state:
case zero
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p✝ : γ → δ → Prop
r p : α → β → Prop
s : Multiset α
t : Multiset β
h : ∀ a ∈ 0, ∀ b ∈ 0, r a b → p a b
⊢ Rel p 0 0
case cons
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p✝ : γ → δ → Prop
r p : α → β → Prop
s : Multiset α
t : Multiset β
a✝² : α
b✝ : β
as✝ : Multiset α
bs✝ : Multiset β
a✝¹ : r a✝² b✝
a✝ : Rel r as✝ bs✝
a_ih✝ : (∀ a ∈ as✝, ∀ b ∈ bs✝, r a b → p a b) → Rel p as✝ bs✝
h : ∀ a ∈ a✝² ::ₘ as✝, ∀ b ∈ b✝ ::ₘ bs✝, r a b → p a b
⊢ Rel p (a✝² ::ₘ as✝) (b✝ ::ₘ bs✝)

Next tactic:
case zero => exact Rel.zero
theorem Rel.mono {r p : α → β → Prop} {s t} (hst : Rel r s t)
    (h : ∀ a ∈ s, ∀ b ∈ t, r a b → p a b) : Rel p s t := by
  induction hst
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p✝ : γ → δ → Prop
r p : α → β → Prop
s : Multiset α
t : Multiset β
h : ∀ a ∈ 0, ∀ b ∈ 0, r a b → p a b
⊢ Rel p 0 0

Next tactic:
case zero => exact Rel.zero
theorem Rel.mono {r p : α → β → Prop} {s t} (hst : Rel r s t)
    (h : ∀ a ∈ s, ∀ b ∈ t, r a b → p a b) : Rel p s t := by
  induction hst
  case zero => 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p✝ : γ → δ → Prop
r p : α → β → Prop
s : Multiset α
t : Multiset β
h : ∀ a ∈ 0, ∀ b ∈ 0, r a b → p a b
⊢ Rel p 0 0

Next tactic:
exact Rel.zero
theorem Rel.mono {r p : α → β → Prop} {s t} (hst : Rel r s t)
    (h : ∀ a ∈ s, ∀ b ∈ t, r a b → p a b) : Rel p s t := by
  induction hst
  case zero => exact Rel.zero
  

Proof state:
case cons
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p✝ : γ → δ → Prop
r p : α → β → Prop
s : Multiset α
t : Multiset β
a✝² : α
b✝ : β
as✝ : Multiset α
bs✝ : Multiset β
a✝¹ : r a✝² b✝
a✝ : Rel r as✝ bs✝
a_ih✝ : (∀ a ∈ as✝, ∀ b ∈ bs✝, r a b → p a b) → Rel p as✝ bs✝
h : ∀ a ∈ a✝² ::ₘ as✝, ∀ b ∈ b✝ ::ₘ bs✝, r a b → p a b
⊢ Rel p (a✝² ::ₘ as✝) (b✝ ::ₘ bs✝)

Next tactic:
case
    cons a b s t hab _hst ih =>
    apply Rel.cons (h a (mem_cons_self _ _) b (mem_cons_self _ _) hab)
    exact ih fun a' ha' b' hb' h' => h a' (mem_cons_of_mem ha') b' (mem_cons_of_mem hb') h'
theorem Rel.mono {r p : α → β → Prop} {s t} (hst : Rel r s t)
    (h : ∀ a ∈ s, ∀ b ∈ t, r a b → p a b) : Rel p s t := by
  induction hst
  case zero => exact Rel.zero
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p✝ : γ → δ → Prop
r p : α → β → Prop
s✝ : Multiset α
t✝ : Multiset β
a : α
b : β
s : Multiset α
t : Multiset β
hab : r a b
_hst : Rel r s t
ih : (∀ a ∈ s, ∀ b ∈ t, r a b → p a b) → Rel p s t
h : ∀ a_1 ∈ a ::ₘ s, ∀ b_1 ∈ b ::ₘ t, r a_1 b_1 → p a_1 b_1
⊢ Rel p (a ::ₘ s) (b ::ₘ t)

Next tactic:
case
    cons a b s t hab _hst ih =>
    apply Rel.cons (h a (mem_cons_self _ _) b (mem_cons_self _ _) hab)
    exact ih fun a' ha' b' hb' h' => h a' (mem_cons_of_mem ha') b' (mem_cons_of_mem hb') h'
theorem Rel.mono {r p : α → β → Prop} {s t} (hst : Rel r s t)
    (h : ∀ a ∈ s, ∀ b ∈ t, r a b → p a b) : Rel p s t := by
  induction hst
  case zero => exact Rel.zero
  case
    cons a b s t hab _hst ih =>
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p✝ : γ → δ → Prop
r p : α → β → Prop
s✝ : Multiset α
t✝ : Multiset β
a : α
b : β
s : Multiset α
t : Multiset β
hab : r a b
_hst : Rel r s t
ih : (∀ a ∈ s, ∀ b ∈ t, r a b → p a b) → Rel p s t
h : ∀ a_1 ∈ a ::ₘ s, ∀ b_1 ∈ b ::ₘ t, r a_1 b_1 → p a_1 b_1
⊢ Rel p (a ::ₘ s) (b ::ₘ t)

Next tactic:
apply Rel.cons (h a (mem_cons_self _ _) b (mem_cons_self _ _) hab)
theorem Rel.mono {r p : α → β → Prop} {s t} (hst : Rel r s t)
    (h : ∀ a ∈ s, ∀ b ∈ t, r a b → p a b) : Rel p s t := by
  induction hst
  case zero => exact Rel.zero
  case
    cons a b s t hab _hst ih =>
    apply Rel.cons (h a (mem_cons_self _ _) b (mem_cons_self _ _) hab)
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r✝ : α → β → Prop
p✝ : γ → δ → Prop
r p : α → β → Prop
s✝ : Multiset α
t✝ : Multiset β
a : α
b : β
s : Multiset α
t : Multiset β
hab : r a b
_hst : Rel r s t
ih : (∀ a ∈ s, ∀ b ∈ t, r a b → p a b) → Rel p s t
h : ∀ a_1 ∈ a ::ₘ s, ∀ b_1 ∈ b ::ₘ t, r a_1 b_1 → p a_1 b_1
⊢ Rel p s t

Next tactic:
exact ih fun a' ha' b' hb' h' => h a' (mem_cons_of_mem ha') b' (mem_cons_of_mem hb') h'
theorem Rel.add {s t u v} (hst : Rel r s t) (huv : Rel r u v) : Rel r (s + u) (t + v) := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s : Multiset α
t : Multiset β
u : Multiset α
v : Multiset β
hst : Rel r s t
huv : Rel r u v
⊢ Rel r (s + u) (t + v)

Next tactic:
induction hst
theorem Rel.add {s t u v} (hst : Rel r s t) (huv : Rel r u v) : Rel r (s + u) (t + v) := by
  induction hst
  

Proof state:
case zero
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s : Multiset α
t : Multiset β
u : Multiset α
v : Multiset β
huv : Rel r u v
⊢ Rel r (0 + u) (0 + v)
case cons
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s : Multiset α
t : Multiset β
u : Multiset α
v : Multiset β
huv : Rel r u v
a✝² : α
b✝ : β
as✝ : Multiset α
bs✝ : Multiset β
a✝¹ : r a✝² b✝
a✝ : Rel r as✝ bs✝
a_ih✝ : Rel r (as✝ + u) (bs✝ + v)
⊢ Rel r (a✝² ::ₘ as✝ + u) (b✝ ::ₘ bs✝ + v)

Next tactic:
case zero => simpa using huv
theorem Rel.add {s t u v} (hst : Rel r s t) (huv : Rel r u v) : Rel r (s + u) (t + v) := by
  induction hst
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s : Multiset α
t : Multiset β
u : Multiset α
v : Multiset β
huv : Rel r u v
⊢ Rel r (0 + u) (0 + v)

Next tactic:
case zero => simpa using huv
theorem Rel.add {s t u v} (hst : Rel r s t) (huv : Rel r u v) : Rel r (s + u) (t + v) := by
  induction hst
  case zero => 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s : Multiset α
t : Multiset β
u : Multiset α
v : Multiset β
huv : Rel r u v
⊢ Rel r (0 + u) (0 + v)

Next tactic:
simpa using huv
theorem Rel.add {s t u v} (hst : Rel r s t) (huv : Rel r u v) : Rel r (s + u) (t + v) := by
  induction hst
  case zero => simpa using huv
  

Proof state:
case cons
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s : Multiset α
t : Multiset β
u : Multiset α
v : Multiset β
huv : Rel r u v
a✝² : α
b✝ : β
as✝ : Multiset α
bs✝ : Multiset β
a✝¹ : r a✝² b✝
a✝ : Rel r as✝ bs✝
a_ih✝ : Rel r (as✝ + u) (bs✝ + v)
⊢ Rel r (a✝² ::ₘ as✝ + u) (b✝ ::ₘ bs✝ + v)

Next tactic:
case cons a b s t hab hst ih => simpa using ih.cons hab
theorem Rel.add {s t u v} (hst : Rel r s t) (huv : Rel r u v) : Rel r (s + u) (t + v) := by
  induction hst
  case zero => simpa using huv
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s✝ : Multiset α
t✝ : Multiset β
u : Multiset α
v : Multiset β
huv : Rel r u v
a : α
b : β
s : Multiset α
t : Multiset β
hab : r a b
hst : Rel r s t
ih : Rel r (s + u) (t + v)
⊢ Rel r (a ::ₘ s + u) (b ::ₘ t + v)

Next tactic:
case cons a b s t hab hst ih => simpa using ih.cons hab
theorem Rel.add {s t u v} (hst : Rel r s t) (huv : Rel r u v) : Rel r (s + u) (t + v) := by
  induction hst
  case zero => simpa using huv
  case cons a b s t hab hst ih => 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s✝ : Multiset α
t✝ : Multiset β
u : Multiset α
v : Multiset β
huv : Rel r u v
a : α
b : β
s : Multiset α
t : Multiset β
hab : r a b
hst : Rel r s t
ih : Rel r (s + u) (t + v)
⊢ Rel r (a ::ₘ s + u) (b ::ₘ t + v)

Next tactic:
simpa using ih.cons hab
theorem rel_flip_eq {s t : Multiset α} : Rel (fun a b => b = a) s t ↔ s = t :=
  show Rel (flip (· = ·)) s t ↔ s = t by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
s t : Multiset α
⊢ Rel (flip fun x x_1 => x = x_1) s t ↔ s = t

Next tactic:
rw [rel_flip, rel_eq, eq_comm]
@[simp]
theorem rel_zero_left {b : Multiset β} : Rel r 0 b ↔ b = 0 := by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
b : Multiset β
⊢ Rel r 0 b ↔ b = 0

Next tactic:
rw [Rel_iff]
@[simp]
theorem rel_zero_left {b : Multiset β} : Rel r 0 b ↔ b = 0 := by rw [Rel_iff]; 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
b : Multiset β
⊢ (0 = 0 ∧ b = 0 ∨ ∃ a b_1 as bs, r a b_1 ∧ Rel r as bs ∧ 0 = a ::ₘ as ∧ b = b_1 ::ₘ bs) ↔ b = 0

Next tactic:
simp
@[simp]
theorem rel_zero_right {a : Multiset α} : Rel r a 0 ↔ a = 0 := by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
a : Multiset α
⊢ Rel r a 0 ↔ a = 0

Next tactic:
rw [Rel_iff]
@[simp]
theorem rel_zero_right {a : Multiset α} : Rel r a 0 ↔ a = 0 := by rw [Rel_iff]; 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
a : Multiset α
⊢ (a = 0 ∧ 0 = 0 ∨ ∃ a_1 b as bs, r a_1 b ∧ Rel r as bs ∧ a = a_1 ::ₘ as ∧ 0 = b ::ₘ bs) ↔ a = 0

Next tactic:
simp
theorem rel_cons_left {a as bs} :
    Rel r (a ::ₘ as) bs ↔ ∃ b bs', r a b ∧ Rel r as bs' ∧ bs = b ::ₘ bs' := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
a : α
as : Multiset α
bs : Multiset β
⊢ Rel r (a ::ₘ as) bs ↔ ∃ b bs', r a b ∧ Rel r as bs' ∧ bs = b ::ₘ bs'

Next tactic:
constructor
theorem rel_cons_left {a as bs} :
    Rel r (a ::ₘ as) bs ↔ ∃ b bs', r a b ∧ Rel r as bs' ∧ bs = b ::ₘ bs' := by
  constructor
  · 

Proof state:
case mp
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
a : α
as : Multiset α
bs : Multiset β
⊢ Rel r (a ::ₘ as) bs → ∃ b bs', r a b ∧ Rel r as bs' ∧ bs = b ::ₘ bs'

Next tactic:
generalize hm : a ::ₘ as = m
theorem rel_cons_left {a as bs} :
    Rel r (a ::ₘ as) bs ↔ ∃ b bs', r a b ∧ Rel r as bs' ∧ bs = b ::ₘ bs' := by
  constructor
  · generalize hm : a ::ₘ as = m
    

Proof state:
case mp
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
a : α
as : Multiset α
bs : Multiset β
m : Multiset α
hm : a ::ₘ as = m
⊢ Rel r m bs → ∃ b bs', r a b ∧ Rel r as bs' ∧ bs = b ::ₘ bs'

Next tactic:
intro h
theorem rel_cons_left {a as bs} :
    Rel r (a ::ₘ as) bs ↔ ∃ b bs', r a b ∧ Rel r as bs' ∧ bs = b ::ₘ bs' := by
  constructor
  · generalize hm : a ::ₘ as = m
    intro h
    

Proof state:
case mp
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
a : α
as : Multiset α
bs : Multiset β
m : Multiset α
hm : a ::ₘ as = m
h : Rel r m bs
⊢ ∃ b bs', r a b ∧ Rel r as bs' ∧ bs = b ::ₘ bs'

Next tactic:
induction h generalizing as
theorem rel_cons_left {a as bs} :
    Rel r (a ::ₘ as) bs ↔ ∃ b bs', r a b ∧ Rel r as bs' ∧ bs = b ::ₘ bs' := by
  constructor
  · generalize hm : a ::ₘ as = m
    intro h
    induction h generalizing as
    

Proof state:
case mp.zero
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
a : α
bs : Multiset β
m as : Multiset α
hm : a ::ₘ as = 0
⊢ ∃ b bs', r a b ∧ Rel r as bs' ∧ 0 = b ::ₘ bs'
case mp.cons
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
a : α
bs : Multiset β
m : Multiset α
a✝² : α
b✝ : β
as✝ : Multiset α
bs✝ : Multiset β
a✝¹ : r a✝² b✝
a✝ : Rel r as✝ bs✝
a_ih✝ : ∀ {as : Multiset α}, a ::ₘ as = as✝ → ∃ b bs', r a b ∧ Rel r as bs' ∧ bs✝ = b ::ₘ bs'
as : Multiset α
hm : a ::ₘ as = a✝² ::ₘ as✝
⊢ ∃ b bs', r a b ∧ Rel r as bs' ∧ b✝ ::ₘ bs✝ = b ::ₘ bs'

Next tactic:
case zero => simp at hm
theorem rel_cons_left {a as bs} :
    Rel r (a ::ₘ as) bs ↔ ∃ b bs', r a b ∧ Rel r as bs' ∧ bs = b ::ₘ bs' := by
  constructor
  · generalize hm : a ::ₘ as = m
    intro h
    induction h generalizing as
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
a : α
bs : Multiset β
m as : Multiset α
hm : a ::ₘ as = 0
⊢ ∃ b bs', r a b ∧ Rel r as bs' ∧ 0 = b ::ₘ bs'

Next tactic:
case zero => simp at hm
theorem rel_cons_left {a as bs} :
    Rel r (a ::ₘ as) bs ↔ ∃ b bs', r a b ∧ Rel r as bs' ∧ bs = b ::ₘ bs' := by
  constructor
  · generalize hm : a ::ₘ as = m
    intro h
    induction h generalizing as
    case zero => 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
a : α
bs : Multiset β
m as : Multiset α
hm : a ::ₘ as = 0
⊢ ∃ b bs', r a b ∧ Rel r as bs' ∧ 0 = b ::ₘ bs'

Next tactic:
simp at hm
theorem rel_cons_left {a as bs} :
    Rel r (a ::ₘ as) bs ↔ ∃ b bs', r a b ∧ Rel r as bs' ∧ bs = b ::ₘ bs' := by
  constructor
  · generalize hm : a ::ₘ as = m
    intro h
    induction h generalizing as
    case zero => simp at hm
    

Proof state:
case mp.cons
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
a : α
bs : Multiset β
m : Multiset α
a✝² : α
b✝ : β
as✝ : Multiset α
bs✝ : Multiset β
a✝¹ : r a✝² b✝
a✝ : Rel r as✝ bs✝
a_ih✝ : ∀ {as : Multiset α}, a ::ₘ as = as✝ → ∃ b bs', r a b ∧ Rel r as bs' ∧ bs✝ = b ::ₘ bs'
as : Multiset α
hm : a ::ₘ as = a✝² ::ₘ as✝
⊢ ∃ b bs', r a b ∧ Rel r as bs' ∧ b✝ ::ₘ bs✝ = b ::ₘ bs'

Next tactic:
case
      cons a' b as' bs ha'b h ih =>
      rcases cons_eq_cons.1 hm with (⟨eq₁, eq₂⟩ | ⟨_h, cs, eq₁, eq₂⟩)
      · subst eq₁
        subst eq₂
        exact ⟨b, bs, ha'b, h, rfl⟩
      · rcases ih eq₂.symm with ⟨b', bs', h₁, h₂, eq⟩
        exact ⟨b', b ::ₘ bs', h₁, eq₁.symm ▸ Rel.cons ha'b h₂, eq.symm ▸ cons_swap _ _ _⟩
theorem rel_cons_left {a as bs} :
    Rel r (a ::ₘ as) bs ↔ ∃ b bs', r a b ∧ Rel r as bs' ∧ bs = b ::ₘ bs' := by
  constructor
  · generalize hm : a ::ₘ as = m
    intro h
    induction h generalizing as
    case zero => simp at hm
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
a : α
bs✝ : Multiset β
m : Multiset α
a' : α
b : β
as' : Multiset α
bs : Multiset β
ha'b : r a' b
h : Rel r as' bs
ih : ∀ {as : Multiset α}, a ::ₘ as = as' → ∃ b bs', r a b ∧ Rel r as bs' ∧ bs = b ::ₘ bs'
as : Multiset α
hm : a ::ₘ as = a' ::ₘ as'
⊢ ∃ b_1 bs', r a b_1 ∧ Rel r as bs' ∧ b ::ₘ bs = b_1 ::ₘ bs'

Next tactic:
case
      cons a' b as' bs ha'b h ih =>
      rcases cons_eq_cons.1 hm with (⟨eq₁, eq₂⟩ | ⟨_h, cs, eq₁, eq₂⟩)
      · subst eq₁
        subst eq₂
        exact ⟨b, bs, ha'b, h, rfl⟩
      · rcases ih eq₂.symm with ⟨b', bs', h₁, h₂, eq⟩
        exact ⟨b', b ::ₘ bs', h₁, eq₁.symm ▸ Rel.cons ha'b h₂, eq.symm ▸ cons_swap _ _ _⟩
theorem rel_cons_left {a as bs} :
    Rel r (a ::ₘ as) bs ↔ ∃ b bs', r a b ∧ Rel r as bs' ∧ bs = b ::ₘ bs' := by
  constructor
  · generalize hm : a ::ₘ as = m
    intro h
    induction h generalizing as
    case zero => simp at hm
    case
      cons a' b as' bs ha'b h ih =>
      

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
p : γ → δ → Prop
a : α
bs✝ : Multiset β
m : Multiset α
a' : α
b : β
as' : Multiset α
bs : Multiset β
ha'b : r a' b
h : Rel r as' bs
ih : ∀ {as : Multiset α}, a ::ₘ as = as' → ∃ b bs', r a b ∧ Rel r as bs' ∧ bs = b ::ₘ bs'
as : Multiset α
hm : a ::ₘ as = a' ::ₘ as'
⊢ ∃ b_1 bs', r a b_1 ∧ Rel r as bs' ∧ b ::ₘ bs = b_1 ::ₘ bs'

Next tactic:
rcases cons_eq_cons.1 hm with (⟨eq₁, eq₂⟩ | ⟨_h, cs, eq₁, eq₂⟩)