l3lab/ntp-mathlib huggingface dataset:
theorem isRight_left (h : LiftRel r s x (inr d)) : x.isRight := by 

Proof state:
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
r : α → γ → Prop
s : β → δ → Prop
x : α ⊕ β
y : γ ⊕ δ
a : α
b : β
c : γ
d : δ
h : LiftRel r s x (inr d)
⊢ isRight x = true

Next tactic:
cases h
theorem isRight_left (h : LiftRel r s x (inr d)) : x.isRight := by cases h; 

Proof state:
case inr
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
r : α → γ → Prop
s : β → δ → Prop
y : γ ⊕ δ
a : α
b : β
c : γ
d : δ
b✝ : β
a✝ : s b✝ d
⊢ isRight (inr b✝) = true

Next tactic:
rfl
theorem isRight_right (h : LiftRel r s (inr b) y) : y.isRight := by 

Proof state:
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
r : α → γ → Prop
s : β → δ → Prop
x : α ⊕ β
y : γ ⊕ δ
a : α
b : β
c : γ
d : δ
h : LiftRel r s (inr b) y
⊢ isRight y = true

Next tactic:
cases h
theorem isRight_right (h : LiftRel r s (inr b) y) : y.isRight := by cases h; 

Proof state:
case inr
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
r : α → γ → Prop
s : β → δ → Prop
x : α ⊕ β
a : α
b : β
c : γ
d d✝ : δ
a✝ : s b d✝
⊢ isRight (inr d✝) = true

Next tactic:
rfl
theorem exists_of_isLeft_left (h₁ : LiftRel r s x y) (h₂ : x.isLeft) :
    ∃ a c, r a c ∧ x = inl a ∧ y = inl c := by
  

Proof state:
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
r : α → γ → Prop
s : β → δ → Prop
x : α ⊕ β
y : γ ⊕ δ
a : α
b : β
c : γ
d : δ
h₁ : LiftRel r s x y
h₂ : isLeft x = true
⊢ ∃ a c, r a c ∧ x = inl a ∧ y = inl c

Next tactic:
rcases isLeft_iff.mp h₂ with ⟨_, rfl⟩
theorem exists_of_isLeft_left (h₁ : LiftRel r s x y) (h₂ : x.isLeft) :
    ∃ a c, r a c ∧ x = inl a ∧ y = inl c := by
  rcases isLeft_iff.mp h₂ with ⟨_, rfl⟩
  

Proof state:
case intro
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
r : α → γ → Prop
s : β → δ → Prop
y : γ ⊕ δ
a : α
b : β
c : γ
d : δ
w✝ : α
h₁ : LiftRel r s (inl w✝) y
h₂ : isLeft (inl w✝) = true
⊢ ∃ a c, r a c ∧ inl w✝ = inl a ∧ y = inl c

Next tactic:
simp only [liftRel_iff, false_and, and_false, exists_false, or_false] at h₁
theorem exists_of_isLeft_left (h₁ : LiftRel r s x y) (h₂ : x.isLeft) :
    ∃ a c, r a c ∧ x = inl a ∧ y = inl c := by
  rcases isLeft_iff.mp h₂ with ⟨_, rfl⟩
  simp only [liftRel_iff, false_and, and_false, exists_false, or_false] at h₁
  

Proof state:
case intro
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
r : α → γ → Prop
s : β → δ → Prop
y : γ ⊕ δ
a : α
b : β
c : γ
d : δ
w✝ : α
h₂ : isLeft (inl w✝) = true
h₁ : ∃ a c, r a c ∧ inl w✝ = inl a ∧ y = inl c
⊢ ∃ a c, r a c ∧ inl w✝ = inl a ∧ y = inl c

Next tactic:
exact h₁
theorem exists_of_isRight_left (h₁ : LiftRel r s x y) (h₂ : x.isRight) :
    ∃ b d, s b d ∧ x = inr b ∧ y = inr d := by
  

Proof state:
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
r : α → γ → Prop
s : β → δ → Prop
x : α ⊕ β
y : γ ⊕ δ
a : α
b : β
c : γ
d : δ
h₁ : LiftRel r s x y
h₂ : isRight x = true
⊢ ∃ b d, s b d ∧ x = inr b ∧ y = inr d

Next tactic:
rcases isRight_iff.mp h₂ with ⟨_, rfl⟩
theorem exists_of_isRight_left (h₁ : LiftRel r s x y) (h₂ : x.isRight) :
    ∃ b d, s b d ∧ x = inr b ∧ y = inr d := by
  rcases isRight_iff.mp h₂ with ⟨_, rfl⟩
  

Proof state:
case intro
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
r : α → γ → Prop
s : β → δ → Prop
y : γ ⊕ δ
a : α
b : β
c : γ
d : δ
w✝ : β
h₁ : LiftRel r s (inr w✝) y
h₂ : isRight (inr w✝) = true
⊢ ∃ b d, s b d ∧ inr w✝ = inr b ∧ y = inr d

Next tactic:
simp only [liftRel_iff, false_and, and_false, exists_false, false_or] at h₁
theorem exists_of_isRight_left (h₁ : LiftRel r s x y) (h₂ : x.isRight) :
    ∃ b d, s b d ∧ x = inr b ∧ y = inr d := by
  rcases isRight_iff.mp h₂ with ⟨_, rfl⟩
  simp only [liftRel_iff, false_and, and_false, exists_false, false_or] at h₁
  

Proof state:
case intro
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
r : α → γ → Prop
s : β → δ → Prop
y : γ ⊕ δ
a : α
b : β
c : γ
d : δ
w✝ : β
h₂ : isRight (inr w✝) = true
h₁ : ∃ b d, s b d ∧ inr w✝ = inr b ∧ y = inr d
⊢ ∃ b d, s b d ∧ inr w✝ = inr b ∧ y = inr d

Next tactic:
exact h₁
@[simp]
theorem map_surjective {f : α → γ} {g : β → δ} :
    Surjective (Sum.map f g) ↔ Surjective f ∧ Surjective g :=
  ⟨ fun h => ⟨
      (fun c => by
        

Proof state:
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
f : α → γ
g : β → δ
h : Surjective (Sum.map f g)
c : γ
⊢ ∃ a, f a = c

Next tactic:
obtain ⟨a | b, h⟩ := h (inl c)
@[simp]
theorem map_surjective {f : α → γ} {g : β → δ} :
    Surjective (Sum.map f g) ↔ Surjective f ∧ Surjective g :=
  ⟨ fun h => ⟨
      (fun c => by
        obtain ⟨a | b, h⟩ := h (inl c)
        · 

Proof state:
case intro.inl
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
f : α → γ
g : β → δ
h✝ : Surjective (Sum.map f g)
c : γ
a : α
h : Sum.map f g (inl a) = inl c
⊢ ∃ a, f a = c

Next tactic:
exact ⟨a, inl_injective h⟩
@[simp]
theorem map_surjective {f : α → γ} {g : β → δ} :
    Surjective (Sum.map f g) ↔ Surjective f ∧ Surjective g :=
  ⟨ fun h => ⟨
      (fun c => by
        obtain ⟨a | b, h⟩ := h (inl c)
        · exact ⟨a, inl_injective h⟩
        · 

Proof state:
case intro.inr
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
f : α → γ
g : β → δ
h✝ : Surjective (Sum.map f g)
c : γ
b : β
h : Sum.map f g (inr b) = inl c
⊢ ∃ a, f a = c

Next tactic:
cases h
@[simp]
theorem map_surjective {f : α → γ} {g : β → δ} :
    Surjective (Sum.map f g) ↔ Surjective f ∧ Surjective g :=
  ⟨ fun h => ⟨
      (fun c => by
        obtain ⟨a | b, h⟩ := h (inl c)
        · exact ⟨a, inl_injective h⟩
        · cases h),
      (fun d => by
        

Proof state:
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
f : α → γ
g : β → δ
h : Surjective (Sum.map f g)
d : δ
⊢ ∃ a, g a = d

Next tactic:
obtain ⟨a | b, h⟩ := h (inr d)
@[simp]
theorem map_surjective {f : α → γ} {g : β → δ} :
    Surjective (Sum.map f g) ↔ Surjective f ∧ Surjective g :=
  ⟨ fun h => ⟨
      (fun c => by
        obtain ⟨a | b, h⟩ := h (inl c)
        · exact ⟨a, inl_injective h⟩
        · cases h),
      (fun d => by
        obtain ⟨a | b, h⟩ := h (inr d)
        · 

Proof state:
case intro.inl
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
f : α → γ
g : β → δ
h✝ : Surjective (Sum.map f g)
d : δ
a : α
h : Sum.map f g (inl a) = inr d
⊢ ∃ a, g a = d

Next tactic:
cases h
@[simp]
theorem map_surjective {f : α → γ} {g : β → δ} :
    Surjective (Sum.map f g) ↔ Surjective f ∧ Surjective g :=
  ⟨ fun h => ⟨
      (fun c => by
        obtain ⟨a | b, h⟩ := h (inl c)
        · exact ⟨a, inl_injective h⟩
        · cases h),
      (fun d => by
        obtain ⟨a | b, h⟩ := h (inr d)
        · cases h
        · 

Proof state:
case intro.inr
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
f : α → γ
g : β → δ
h✝ : Surjective (Sum.map f g)
d : δ
b : β
h : Sum.map f g (inr b) = inr d
⊢ ∃ a, g a = d

Next tactic:
exact ⟨b, inr_injective h⟩
theorem elim_update_left [DecidableEq α] [DecidableEq β] (f : α → γ) (g : β → γ) (i : α) (c : γ) :
    Sum.elim (Function.update f i c) g = Function.update (Sum.elim f g) (inl i) c := by
  

Proof state:
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → γ
g : β → γ
i : α
c : γ
⊢ Sum.elim (update f i c) g = update (Sum.elim f g) (inl i) c

Next tactic:
ext x
theorem elim_update_left [DecidableEq α] [DecidableEq β] (f : α → γ) (g : β → γ) (i : α) (c : γ) :
    Sum.elim (Function.update f i c) g = Function.update (Sum.elim f g) (inl i) c := by
  ext x
  

Proof state:
case h
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → γ
g : β → γ
i : α
c : γ
x : α ⊕ β
⊢ Sum.elim (update f i c) g x = update (Sum.elim f g) (inl i) c x

Next tactic:
rcases x with x | x
theorem elim_update_left [DecidableEq α] [DecidableEq β] (f : α → γ) (g : β → γ) (i : α) (c : γ) :
    Sum.elim (Function.update f i c) g = Function.update (Sum.elim f g) (inl i) c := by
  ext x
  rcases x with x | x
  · 

Proof state:
case h.inl
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → γ
g : β → γ
i : α
c : γ
x : α
⊢ Sum.elim (update f i c) g (inl x) = update (Sum.elim f g) (inl i) c (inl x)

Next tactic:
by_cases h : x = i
theorem elim_update_left [DecidableEq α] [DecidableEq β] (f : α → γ) (g : β → γ) (i : α) (c : γ) :
    Sum.elim (Function.update f i c) g = Function.update (Sum.elim f g) (inl i) c := by
  ext x
  rcases x with x | x
  · by_cases h : x = i
    · 

Proof state:
case pos
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → γ
g : β → γ
i : α
c : γ
x : α
h : x = i
⊢ Sum.elim (update f i c) g (inl x) = update (Sum.elim f g) (inl i) c (inl x)

Next tactic:
subst h
theorem elim_update_left [DecidableEq α] [DecidableEq β] (f : α → γ) (g : β → γ) (i : α) (c : γ) :
    Sum.elim (Function.update f i c) g = Function.update (Sum.elim f g) (inl i) c := by
  ext x
  rcases x with x | x
  · by_cases h : x = i
    · subst h
      

Proof state:
case pos
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → γ
g : β → γ
c : γ
x : α
⊢ Sum.elim (update f x c) g (inl x) = update (Sum.elim f g) (inl x) c (inl x)

Next tactic:
simp
theorem elim_update_left [DecidableEq α] [DecidableEq β] (f : α → γ) (g : β → γ) (i : α) (c : γ) :
    Sum.elim (Function.update f i c) g = Function.update (Sum.elim f g) (inl i) c := by
  ext x
  rcases x with x | x
  · by_cases h : x = i
    · subst h
      simp
    · 

Proof state:
case neg
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → γ
g : β → γ
i : α
c : γ
x : α
h : ¬x = i
⊢ Sum.elim (update f i c) g (inl x) = update (Sum.elim f g) (inl i) c (inl x)

Next tactic:
simp [h]
theorem elim_update_left [DecidableEq α] [DecidableEq β] (f : α → γ) (g : β → γ) (i : α) (c : γ) :
    Sum.elim (Function.update f i c) g = Function.update (Sum.elim f g) (inl i) c := by
  ext x
  rcases x with x | x
  · by_cases h : x = i
    · subst h
      simp
    · simp [h]
  · 

Proof state:
case h.inr
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → γ
g : β → γ
i : α
c : γ
x : β
⊢ Sum.elim (update f i c) g (inr x) = update (Sum.elim f g) (inl i) c (inr x)

Next tactic:
simp
theorem elim_update_right [DecidableEq α] [DecidableEq β] (f : α → γ) (g : β → γ) (i : β) (c : γ) :
    Sum.elim f (Function.update g i c) = Function.update (Sum.elim f g) (inr i) c := by
  

Proof state:
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → γ
g : β → γ
i : β
c : γ
⊢ Sum.elim f (update g i c) = update (Sum.elim f g) (inr i) c

Next tactic:
ext x
theorem elim_update_right [DecidableEq α] [DecidableEq β] (f : α → γ) (g : β → γ) (i : β) (c : γ) :
    Sum.elim f (Function.update g i c) = Function.update (Sum.elim f g) (inr i) c := by
  ext x
  

Proof state:
case h
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → γ
g : β → γ
i : β
c : γ
x : α ⊕ β
⊢ Sum.elim f (update g i c) x = update (Sum.elim f g) (inr i) c x

Next tactic:
rcases x with x | x
theorem elim_update_right [DecidableEq α] [DecidableEq β] (f : α → γ) (g : β → γ) (i : β) (c : γ) :
    Sum.elim f (Function.update g i c) = Function.update (Sum.elim f g) (inr i) c := by
  ext x
  rcases x with x | x
  · 

Proof state:
case h.inl
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → γ
g : β → γ
i : β
c : γ
x : α
⊢ Sum.elim f (update g i c) (inl x) = update (Sum.elim f g) (inr i) c (inl x)

Next tactic:
simp
theorem elim_update_right [DecidableEq α] [DecidableEq β] (f : α → γ) (g : β → γ) (i : β) (c : γ) :
    Sum.elim f (Function.update g i c) = Function.update (Sum.elim f g) (inr i) c := by
  ext x
  rcases x with x | x
  · simp
  · 

Proof state:
case h.inr
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → γ
g : β → γ
i : β
c : γ
x : β
⊢ Sum.elim f (update g i c) (inr x) = update (Sum.elim f g) (inr i) c (inr x)

Next tactic:
by_cases h : x = i
theorem elim_update_right [DecidableEq α] [DecidableEq β] (f : α → γ) (g : β → γ) (i : β) (c : γ) :
    Sum.elim f (Function.update g i c) = Function.update (Sum.elim f g) (inr i) c := by
  ext x
  rcases x with x | x
  · simp
  · by_cases h : x = i
    · 

Proof state:
case pos
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → γ
g : β → γ
i : β
c : γ
x : β
h : x = i
⊢ Sum.elim f (update g i c) (inr x) = update (Sum.elim f g) (inr i) c (inr x)

Next tactic:
subst h
theorem elim_update_right [DecidableEq α] [DecidableEq β] (f : α → γ) (g : β → γ) (i : β) (c : γ) :
    Sum.elim f (Function.update g i c) = Function.update (Sum.elim f g) (inr i) c := by
  ext x
  rcases x with x | x
  · simp
  · by_cases h : x = i
    · subst h
      

Proof state:
case pos
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → γ
g : β → γ
c : γ
x : β
⊢ Sum.elim f (update g x c) (inr x) = update (Sum.elim f g) (inr x) c (inr x)

Next tactic:
simp
theorem elim_update_right [DecidableEq α] [DecidableEq β] (f : α → γ) (g : β → γ) (i : β) (c : γ) :
    Sum.elim f (Function.update g i c) = Function.update (Sum.elim f g) (inr i) c := by
  ext x
  rcases x with x | x
  · simp
  · by_cases h : x = i
    · subst h
      simp
    · 

Proof state:
case neg
α : Type u
α' : Type w
β : Type v
β' : Type x
γ : Type u_1
δ : Type u_2
inst✝¹ : DecidableEq α
inst✝ : DecidableEq β
f : α → γ
g : β → γ
i : β
c : γ
x : β
h : ¬x = i
⊢ Sum.elim f (update g i c) (inr x) = update (Sum.elim f g) (inr i) c (inr x)

Next tactic:
simp [h]
theorem coe_join :
    ∀ L : List (List α), join (L.map ((↑) : List α → Multiset α) : Multiset (Multiset α)) = L.join
  | [] => rfl
  | l :: L => by
      -- Porting note: was `congr_arg (fun s : Multiset α => ↑l + s) (coe_join L)`
      

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
l : List α
L : List (List α)
⊢ join ↑(List.map ofList (l :: L)) = ↑(List.join (l :: L))

Next tactic:
simp only [join, List.map, coe_sum, List.sum_cons, List.join, ← coe_add, ← coe_join L]
@[simp]
theorem mem_join {a S} : a ∈ @join α S ↔ ∃ s ∈ S, a ∈ s :=
  Multiset.induction_on S (by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
S : Multiset (Multiset α)
⊢ a ∈ join 0 ↔ ∃ s ∈ 0, a ∈ s

Next tactic:
simp
@[simp]
theorem mem_join {a S} : a ∈ @join α S ↔ ∃ s ∈ S, a ∈ s :=
  Multiset.induction_on S (by simp) <| by
    

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
S : Multiset (Multiset α)
⊢ ∀ ⦃a_1 : Multiset α⦄ {s : Multiset (Multiset α)},
    (a ∈ join s ↔ ∃ s_1 ∈ s, a ∈ s_1) → (a ∈ join (a_1 ::ₘ s) ↔ ∃ s_1 ∈ a_1 ::ₘ s, a ∈ s_1)

Next tactic:
simp (config := { contextual := true }) [or_and_right, exists_or]
@[simp]
theorem card_join (S) : card (@join α S) = sum (map card S) :=
  Multiset.induction_on S (by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
S : Multiset (Multiset α)
⊢ card (join 0) = sum (map (⇑card) 0)

Next tactic:
simp
@[simp]
theorem card_join (S) : card (@join α S) = sum (map card S) :=
  Multiset.induction_on S (by simp) (by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
S : Multiset (Multiset α)
⊢ ∀ ⦃a : Multiset α⦄ {s : Multiset (Multiset α)},
    card (join s) = sum (map (⇑card) s) → card (join (a ::ₘ s)) = sum (map (⇑card) (a ::ₘ s))

Next tactic:
simp
theorem rel_join {r : α → β → Prop} {s t} (h : Rel (Rel r) s t) : Rel r s.join t.join := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
r : α → β → Prop
s : Multiset (Multiset α)
t : Multiset (Multiset β)
h : Rel (Rel r) s t
⊢ Rel r (join s) (join t)

Next tactic:
induction h
theorem rel_join {r : α → β → Prop} {s t} (h : Rel (Rel r) s t) : Rel r s.join t.join := by
  induction h
  

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

Next tactic:
case zero => simp
theorem rel_join {r : α → β → Prop} {s t} (h : Rel (Rel r) s t) : Rel r s.join t.join := by
  induction h
  

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

Next tactic:
case zero => simp
theorem rel_join {r : α → β → Prop} {s t} (h : Rel (Rel r) s t) : Rel r s.join t.join := by
  induction h
  case zero => 

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

Next tactic:
simp
theorem rel_join {r : α → β → Prop} {s t} (h : Rel (Rel r) s t) : Rel r s.join t.join := by
  induction h
  case zero => simp
  

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

Next tactic:
case cons a b s t hab hst ih => simpa using hab.add ih
theorem rel_join {r : α → β → Prop} {s t} (h : Rel (Rel r) s t) : Rel r s.join t.join := by
  induction h
  case zero => simp
  

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

Next tactic:
case cons a b s t hab hst ih => simpa using hab.add ih
theorem rel_join {r : α → β → Prop} {s t} (h : Rel (Rel r) s t) : Rel r s.join t.join := by
  induction h
  case zero => simp
  case cons a b s t hab hst ih => 

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

Next tactic:
simpa using hab.add ih
@[simp]
theorem coe_bind (l : List α) (f : α → List β) : (@bind α β l fun a => f a) = l.bind f := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f✝ g : α → Multiset β
l : List α
f : α → List β
⊢ (bind ↑l fun a => ↑(f a)) = ↑(List.bind l f)

Next tactic:
rw [List.bind, ← coe_join, List.map_map]
@[simp]
theorem coe_bind (l : List α) (f : α → List β) : (@bind α β l fun a => f a) = l.bind f := by
  rw [List.bind, ← coe_join, List.map_map]
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f✝ g : α → Multiset β
l : List α
f : α → List β
⊢ (bind ↑l fun a => ↑(f a)) = join ↑(List.map (ofList ∘ f) l)

Next tactic:
rfl
@[simp]
theorem cons_bind : (a ::ₘ s).bind f = f a + s.bind f := by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f g : α → Multiset β
⊢ bind (a ::ₘ s) f = f a + bind s f

Next tactic:
simp [bind]
@[simp]
theorem singleton_bind : bind {a} f = f a := by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f g : α → Multiset β
⊢ bind {a} f = f a

Next tactic:
simp [bind]
@[simp]
theorem add_bind : (s + t).bind f = s.bind f + t.bind f := by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f g : α → Multiset β
⊢ bind (s + t) f = bind s f + bind t f

Next tactic:
simp [bind]
@[simp]
theorem bind_zero : s.bind (fun _ => 0 : α → Multiset β) = 0 := by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f g : α → Multiset β
⊢ (bind s fun x => 0) = 0

Next tactic:
simp [bind, join, nsmul_zero]
@[simp]
theorem bind_add : (s.bind fun a => f a + g a) = s.bind f + s.bind g := by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f g : α → Multiset β
⊢ (bind s fun a => f a + g a) = bind s f + bind s g

Next tactic:
simp [bind, join]
@[simp]
theorem bind_cons (f : α → β) (g : α → Multiset β) :
    (s.bind fun a => f a ::ₘ g a) = map f s + s.bind g :=
  Multiset.induction_on s (by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f✝ g✝ : α → Multiset β
f : α → β
g : α → Multiset β
⊢ (bind 0 fun a => f a ::ₘ g a) = map f 0 + bind 0 g

Next tactic:
simp
@[simp]
theorem bind_cons (f : α → β) (g : α → Multiset β) :
    (s.bind fun a => f a ::ₘ g a) = map f s + s.bind g :=
  Multiset.induction_on s (by simp)
    (by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f✝ g✝ : α → Multiset β
f : α → β
g : α → Multiset β
⊢ ∀ ⦃a : α⦄ {s : Multiset α},
    (bind s fun a => f a ::ₘ g a) = map f s + bind s g →
      (bind (a ::ₘ s) fun a => f a ::ₘ g a) = map f (a ::ₘ s) + bind (a ::ₘ s) g

Next tactic:
simp (config := { contextual := true }) [add_comm, add_left_comm, add_assoc]
@[simp]
theorem bind_singleton (f : α → β) : (s.bind fun x => ({f x} : Multiset β)) = map f s :=
  Multiset.induction_on s (by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f✝ g : α → Multiset β
f : α → β
⊢ (bind 0 fun x => {f x}) = map f 0

Next tactic:
rw [zero_bind, map_zero]
@[simp]
theorem bind_singleton (f : α → β) : (s.bind fun x => ({f x} : Multiset β)) = map f s :=
  Multiset.induction_on s (by rw [zero_bind, map_zero]) (by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f✝ g : α → Multiset β
f : α → β
⊢ ∀ ⦃a : α⦄ {s : Multiset α}, (bind s fun x => {f x}) = map f s → (bind (a ::ₘ s) fun x => {f x}) = map f (a ::ₘ s)

Next tactic:
simp [singleton_add]
@[simp]
theorem mem_bind {b s} {f : α → Multiset β} : b ∈ bind s f ↔ ∃ a ∈ s, b ∈ f a := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s✝ t : Multiset α
f✝ g : α → Multiset β
b : β
s : Multiset α
f : α → Multiset β
⊢ b ∈ bind s f ↔ ∃ a ∈ s, b ∈ f a

Next tactic:
simp [bind]
@[simp]
theorem card_bind : card (s.bind f) = (s.map (card ∘ f)).sum := by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f g : α → Multiset β
⊢ card (bind s f) = sum (map (⇑card ∘ f) s)

Next tactic:
simp [bind]
theorem bind_congr {f g : α → Multiset β} {m : Multiset α} :
    (∀ a ∈ m, f a = g a) → bind m f = bind m g := by 

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f✝ g✝ f g : α → Multiset β
m : Multiset α
⊢ (∀ a ∈ m, f a = g a) → bind m f = bind m g

Next tactic:
simp (config := { contextual := true }) [bind]
theorem bind_hcongr {β' : Type v} {m : Multiset α} {f : α → Multiset β} {f' : α → Multiset β'}
    (h : β = β') (hf : ∀ a ∈ m, HEq (f a) (f' a)) : HEq (bind m f) (bind m f') := by
  

Proof state:
α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f✝ g : α → Multiset β
β' : Type v
m : Multiset α
f : α → Multiset β
f' : α → Multiset β'
h : β = β'
hf : ∀ a ∈ m, HEq (f a) (f' a)
⊢ HEq (bind m f) (bind m f')

Next tactic:
subst h