l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem bindOnSupport_bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF β)
    (g : ∀ b ∈ (p.bindOnSupport f).support, PMF γ) :
    (p.bindOnSupport f).bindOnSupport g =
      p.bindOnSupport fun a ha =>
        (f a ha).bindOnSupport fun b hb =>
          g b ((mem_support_bindOnSupport_iff f b).mpr ⟨a, ha, hb⟩) := by
  refine' PMF.ext fun a => _
  dsimp only [bindOnSupport_apply]
  simp only [← tsum_dite_right, ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
  simp only [ENNReal.tsum_eq_zero, dite_eq_left_iff]
  refine' ENNReal.tsum_comm.trans (tsum_congr fun a' => tsum_congr fun b => _)
  split_ifs with h _ h_1 _ h_2
  any_goals 

Proof state:
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
f : (a : α) → a ∈ support p → PMF β
g : (b : β) → b ∈ support (bindOnSupport p f) → PMF γ
a : γ
a' : α
b : β
h : p a' = 0
_ : ¬∀ (i : α), (p i * if h : p i = 0 then 0 else (f i h) b) = 0
⊢ p a' * 0 * (g b (_ : ¬(∑' (a : α), p a * if h : p a = 0 then 0 else (f a h) b) = 0)) a = p a' * 0

Next tactic:
ring1
@[simp]
theorem bindOnSupport_bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF β)
    (g : ∀ b ∈ (p.bindOnSupport f).support, PMF γ) :
    (p.bindOnSupport f).bindOnSupport g =
      p.bindOnSupport fun a ha =>
        (f a ha).bindOnSupport fun b hb =>
          g b ((mem_support_bindOnSupport_iff f b).mpr ⟨a, ha, hb⟩) := by
  refine' PMF.ext fun a => _
  dsimp only [bindOnSupport_apply]
  simp only [← tsum_dite_right, ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
  simp only [ENNReal.tsum_eq_zero, dite_eq_left_iff]
  refine' ENNReal.tsum_comm.trans (tsum_congr fun a' => tsum_congr fun b => _)
  split_ifs with h _ h_1 _ h_2
  any_goals 

Proof state:
case pos
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
f : (a : α) → a ∈ support p → PMF β
g : (b : β) → b ∈ support (bindOnSupport p f) → PMF γ
a : γ
a' : α
b : β
h : ¬p a' = 0
h_1 : ∀ (i : α), (p i * if h : p i = 0 then 0 else (f i h) b) = 0
_ : (f a' h) b = 0
⊢ p a' * (f a' h) b * 0 = p a' * ((f a' h) b * 0)

Next tactic:
ring1
@[simp]
theorem bindOnSupport_bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF β)
    (g : ∀ b ∈ (p.bindOnSupport f).support, PMF γ) :
    (p.bindOnSupport f).bindOnSupport g =
      p.bindOnSupport fun a ha =>
        (f a ha).bindOnSupport fun b hb =>
          g b ((mem_support_bindOnSupport_iff f b).mpr ⟨a, ha, hb⟩) := by
  refine' PMF.ext fun a => _
  dsimp only [bindOnSupport_apply]
  simp only [← tsum_dite_right, ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
  simp only [ENNReal.tsum_eq_zero, dite_eq_left_iff]
  refine' ENNReal.tsum_comm.trans (tsum_congr fun a' => tsum_congr fun b => _)
  split_ifs with h _ h_1 _ h_2
  any_goals 

Proof state:
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
f : (a : α) → a ∈ support p → PMF β
g : (b : β) → b ∈ support (bindOnSupport p f) → PMF γ
a : γ
a' : α
b : β
h : ¬p a' = 0
h_1 : ∀ (i : α), (p i * if h : p i = 0 then 0 else (f i h) b) = 0
_ : ¬(f a' h) b = 0
⊢ p a' * (f a' h) b * 0 = p a' * ((f a' h) b * (g b (_ : b ∈ support (bindOnSupport p f))) a)

Next tactic:
ring1
@[simp]
theorem bindOnSupport_bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF β)
    (g : ∀ b ∈ (p.bindOnSupport f).support, PMF γ) :
    (p.bindOnSupport f).bindOnSupport g =
      p.bindOnSupport fun a ha =>
        (f a ha).bindOnSupport fun b hb =>
          g b ((mem_support_bindOnSupport_iff f b).mpr ⟨a, ha, hb⟩) := by
  refine' PMF.ext fun a => _
  dsimp only [bindOnSupport_apply]
  simp only [← tsum_dite_right, ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
  simp only [ENNReal.tsum_eq_zero, dite_eq_left_iff]
  refine' ENNReal.tsum_comm.trans (tsum_congr fun a' => tsum_congr fun b => _)
  split_ifs with h _ h_1 _ h_2
  any_goals 

Proof state:
case pos
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
f : (a : α) → a ∈ support p → PMF β
g : (b : β) → b ∈ support (bindOnSupport p f) → PMF γ
a : γ
a' : α
b : β
h : ¬p a' = 0
h_1 : ¬∀ (i : α), (p i * if h : p i = 0 then 0 else (f i h) b) = 0
h_2 : (f a' h) b = 0
⊢ p a' * (f a' h) b * (g b (_ : ¬(∑' (a : α), p a * if h : p a = 0 then 0 else (f a h) b) = 0)) a =
    p a' * ((f a' h) b * 0)

Next tactic:
ring1
@[simp]
theorem bindOnSupport_bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF β)
    (g : ∀ b ∈ (p.bindOnSupport f).support, PMF γ) :
    (p.bindOnSupport f).bindOnSupport g =
      p.bindOnSupport fun a ha =>
        (f a ha).bindOnSupport fun b hb =>
          g b ((mem_support_bindOnSupport_iff f b).mpr ⟨a, ha, hb⟩) := by
  refine' PMF.ext fun a => _
  dsimp only [bindOnSupport_apply]
  simp only [← tsum_dite_right, ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
  simp only [ENNReal.tsum_eq_zero, dite_eq_left_iff]
  refine' ENNReal.tsum_comm.trans (tsum_congr fun a' => tsum_congr fun b => _)
  split_ifs with h _ h_1 _ h_2
  any_goals 

Proof state:
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
f : (a : α) → a ∈ support p → PMF β
g : (b : β) → b ∈ support (bindOnSupport p f) → PMF γ
a : γ
a' : α
b : β
h : ¬p a' = 0
h_1 : ¬∀ (i : α), (p i * if h : p i = 0 then 0 else (f i h) b) = 0
h_2 : ¬(f a' h) b = 0
⊢ p a' * (f a' h) b * (g b (_ : ¬(∑' (a : α), p a * if h : p a = 0 then 0 else (f a h) b) = 0)) a =
    p a' * ((f a' h) b * (g b (_ : b ∈ support (bindOnSupport p f))) a)

Next tactic:
ring1
@[simp]
theorem bindOnSupport_bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF β)
    (g : ∀ b ∈ (p.bindOnSupport f).support, PMF γ) :
    (p.bindOnSupport f).bindOnSupport g =
      p.bindOnSupport fun a ha =>
        (f a ha).bindOnSupport fun b hb =>
          g b ((mem_support_bindOnSupport_iff f b).mpr ⟨a, ha, hb⟩) := by
  refine' PMF.ext fun a => _
  dsimp only [bindOnSupport_apply]
  simp only [← tsum_dite_right, ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
  simp only [ENNReal.tsum_eq_zero, dite_eq_left_iff]
  refine' ENNReal.tsum_comm.trans (tsum_congr fun a' => tsum_congr fun b => _)
  split_ifs with h _ h_1 _ h_2
  any_goals ring1
  · 

Proof state:
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
f : (a : α) → a ∈ support p → PMF β
g : (b : β) → b ∈ support (bindOnSupport p f) → PMF γ
a : γ
a' : α
b : β
h : ¬p a' = 0
h_1 : ∀ (i : α), (p i * if h : p i = 0 then 0 else (f i h) b) = 0
_ : ¬(f a' h) b = 0
⊢ p a' * (f a' h) b * 0 = p a' * ((f a' h) b * (g b (_ : b ∈ support (bindOnSupport p f))) a)

Next tactic:
have := h_1 a'
@[simp]
theorem bindOnSupport_bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF β)
    (g : ∀ b ∈ (p.bindOnSupport f).support, PMF γ) :
    (p.bindOnSupport f).bindOnSupport g =
      p.bindOnSupport fun a ha =>
        (f a ha).bindOnSupport fun b hb =>
          g b ((mem_support_bindOnSupport_iff f b).mpr ⟨a, ha, hb⟩) := by
  refine' PMF.ext fun a => _
  dsimp only [bindOnSupport_apply]
  simp only [← tsum_dite_right, ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
  simp only [ENNReal.tsum_eq_zero, dite_eq_left_iff]
  refine' ENNReal.tsum_comm.trans (tsum_congr fun a' => tsum_congr fun b => _)
  split_ifs with h _ h_1 _ h_2
  any_goals ring1
  · have := h_1 a'
    

Proof state:
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
f : (a : α) → a ∈ support p → PMF β
g : (b : β) → b ∈ support (bindOnSupport p f) → PMF γ
a : γ
a' : α
b : β
h : ¬p a' = 0
h_1 : ∀ (i : α), (p i * if h : p i = 0 then 0 else (f i h) b) = 0
_ : ¬(f a' h) b = 0
this : (p a' * if h : p a' = 0 then 0 else (f a' h) b) = 0
⊢ p a' * (f a' h) b * 0 = p a' * ((f a' h) b * (g b (_ : b ∈ support (bindOnSupport p f))) a)

Next tactic:
simp? [h] at this says simp only [h, dite_false, mul_eq_zero, false_or] at this
@[simp]
theorem bindOnSupport_bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF β)
    (g : ∀ b ∈ (p.bindOnSupport f).support, PMF γ) :
    (p.bindOnSupport f).bindOnSupport g =
      p.bindOnSupport fun a ha =>
        (f a ha).bindOnSupport fun b hb =>
          g b ((mem_support_bindOnSupport_iff f b).mpr ⟨a, ha, hb⟩) := by
  refine' PMF.ext fun a => _
  dsimp only [bindOnSupport_apply]
  simp only [← tsum_dite_right, ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
  simp only [ENNReal.tsum_eq_zero, dite_eq_left_iff]
  refine' ENNReal.tsum_comm.trans (tsum_congr fun a' => tsum_congr fun b => _)
  split_ifs with h _ h_1 _ h_2
  any_goals ring1
  · have := h_1 a'
    simp? [h] at this says 

Proof state:
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
f : (a : α) → a ∈ support p → PMF β
g : (b : β) → b ∈ support (bindOnSupport p f) → PMF γ
a : γ
a' : α
b : β
h : ¬p a' = 0
h_1 : ∀ (i : α), (p i * if h : p i = 0 then 0 else (f i h) b) = 0
_ : ¬(f a' h) b = 0
this : (p a' * if h : p a' = 0 then 0 else (f a' h) b) = 0
⊢ p a' * (f a' h) b * 0 = p a' * ((f a' h) b * (g b (_ : b ∈ support (bindOnSupport p f))) a)

Next tactic:
simp only [h, dite_false, mul_eq_zero, false_or] at this
@[simp]
theorem bindOnSupport_bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF β)
    (g : ∀ b ∈ (p.bindOnSupport f).support, PMF γ) :
    (p.bindOnSupport f).bindOnSupport g =
      p.bindOnSupport fun a ha =>
        (f a ha).bindOnSupport fun b hb =>
          g b ((mem_support_bindOnSupport_iff f b).mpr ⟨a, ha, hb⟩) := by
  refine' PMF.ext fun a => _
  dsimp only [bindOnSupport_apply]
  simp only [← tsum_dite_right, ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
  simp only [ENNReal.tsum_eq_zero, dite_eq_left_iff]
  refine' ENNReal.tsum_comm.trans (tsum_congr fun a' => tsum_congr fun b => _)
  split_ifs with h _ h_1 _ h_2
  any_goals ring1
  · have := h_1 a'
    simp? [h] at this says simp only [h, dite_false, mul_eq_zero, false_or] at this
    

Proof state:
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
f : (a : α) → a ∈ support p → PMF β
g : (b : β) → b ∈ support (bindOnSupport p f) → PMF γ
a : γ
a' : α
b : β
h : ¬p a' = 0
h_1 : ∀ (i : α), (p i * if h : p i = 0 then 0 else (f i h) b) = 0
_ : ¬(f a' h) b = 0
this : (f a' (_ : ¬p a' = 0)) b = 0
⊢ p a' * (f a' h) b * 0 = p a' * ((f a' h) b * (g b (_ : b ∈ support (bindOnSupport p f))) a)

Next tactic:
contradiction
@[simp]
theorem bindOnSupport_bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF β)
    (g : ∀ b ∈ (p.bindOnSupport f).support, PMF γ) :
    (p.bindOnSupport f).bindOnSupport g =
      p.bindOnSupport fun a ha =>
        (f a ha).bindOnSupport fun b hb =>
          g b ((mem_support_bindOnSupport_iff f b).mpr ⟨a, ha, hb⟩) := by
  refine' PMF.ext fun a => _
  dsimp only [bindOnSupport_apply]
  simp only [← tsum_dite_right, ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
  simp only [ENNReal.tsum_eq_zero, dite_eq_left_iff]
  refine' ENNReal.tsum_comm.trans (tsum_congr fun a' => tsum_congr fun b => _)
  split_ifs with h _ h_1 _ h_2
  any_goals ring1
  · have := h_1 a'
    simp? [h] at this says simp only [h, dite_false, mul_eq_zero, false_or] at this
    contradiction
  · 

Proof state:
case pos
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
f : (a : α) → a ∈ support p → PMF β
g : (b : β) → b ∈ support (bindOnSupport p f) → PMF γ
a : γ
a' : α
b : β
h : ¬p a' = 0
h_1 : ¬∀ (i : α), (p i * if h : p i = 0 then 0 else (f i h) b) = 0
h_2 : (f a' h) b = 0
⊢ p a' * (f a' h) b * (g b (_ : ¬(∑' (a : α), p a * if h : p a = 0 then 0 else (f a h) b) = 0)) a =
    p a' * ((f a' h) b * 0)

Next tactic:
simp [h_2]
theorem bindOnSupport_comm (p : PMF α) (q : PMF β) (f : ∀ a ∈ p.support, ∀ b ∈ q.support, PMF γ) :
    (p.bindOnSupport fun a ha => q.bindOnSupport (f a ha)) =
      q.bindOnSupport fun b hb => p.bindOnSupport fun a ha => f a ha b hb := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
q : PMF β
f : (a : α) → a ∈ support p → (b : β) → b ∈ support q → PMF γ
⊢ (bindOnSupport p fun a ha => bindOnSupport q (f a ha)) =
    bindOnSupport q fun b hb => bindOnSupport p fun a ha => f a ha b hb

Next tactic:
apply PMF.ext
theorem bindOnSupport_comm (p : PMF α) (q : PMF β) (f : ∀ a ∈ p.support, ∀ b ∈ q.support, PMF γ) :
    (p.bindOnSupport fun a ha => q.bindOnSupport (f a ha)) =
      q.bindOnSupport fun b hb => p.bindOnSupport fun a ha => f a ha b hb := by
  apply PMF.ext; 

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
q : PMF β
f : (a : α) → a ∈ support p → (b : β) → b ∈ support q → PMF γ
⊢ ∀ (x : γ),
    (bindOnSupport p fun a ha => bindOnSupport q (f a ha)) x =
      (bindOnSupport q fun b hb => bindOnSupport p fun a ha => f a ha b hb) x

Next tactic:
rintro c
theorem bindOnSupport_comm (p : PMF α) (q : PMF β) (f : ∀ a ∈ p.support, ∀ b ∈ q.support, PMF γ) :
    (p.bindOnSupport fun a ha => q.bindOnSupport (f a ha)) =
      q.bindOnSupport fun b hb => p.bindOnSupport fun a ha => f a ha b hb := by
  apply PMF.ext; rintro c
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
q : PMF β
f : (a : α) → a ∈ support p → (b : β) → b ∈ support q → PMF γ
c : γ
⊢ (bindOnSupport p fun a ha => bindOnSupport q (f a ha)) c =
    (bindOnSupport q fun b hb => bindOnSupport p fun a ha => f a ha b hb) c

Next tactic:
simp only [ENNReal.coe_eq_coe.symm, bindOnSupport_apply, ← tsum_dite_right,
    ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
theorem bindOnSupport_comm (p : PMF α) (q : PMF β) (f : ∀ a ∈ p.support, ∀ b ∈ q.support, PMF γ) :
    (p.bindOnSupport fun a ha => q.bindOnSupport (f a ha)) =
      q.bindOnSupport fun b hb => p.bindOnSupport fun a ha => f a ha b hb := by
  apply PMF.ext; rintro c
  simp only [ENNReal.coe_eq_coe.symm, bindOnSupport_apply, ← tsum_dite_right,
    ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
q : PMF β
f : (a : α) → a ∈ support p → (b : β) → b ∈ support q → PMF γ
c : γ
⊢ (∑' (a : α) (i : β), p a * if h : p a = 0 then 0 else q i * if h : q i = 0 then 0 else (f a (_ : ¬p a = 0) i h) c) =
    ∑' (a : β) (i : α), q a * if h : q a = 0 then 0 else p i * if h : p i = 0 then 0 else (f i h a (_ : ¬q a = 0)) c

Next tactic:
refine' _root_.trans ENNReal.tsum_comm (tsum_congr fun b => tsum_congr fun a => _)
theorem bindOnSupport_comm (p : PMF α) (q : PMF β) (f : ∀ a ∈ p.support, ∀ b ∈ q.support, PMF γ) :
    (p.bindOnSupport fun a ha => q.bindOnSupport (f a ha)) =
      q.bindOnSupport fun b hb => p.bindOnSupport fun a ha => f a ha b hb := by
  apply PMF.ext; rintro c
  simp only [ENNReal.coe_eq_coe.symm, bindOnSupport_apply, ← tsum_dite_right,
    ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
  refine' _root_.trans ENNReal.tsum_comm (tsum_congr fun b => tsum_congr fun a => _)
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
q : PMF β
f : (a : α) → a ∈ support p → (b : β) → b ∈ support q → PMF γ
c : γ
b : β
a : α
⊢ (p a * if h : p a = 0 then 0 else q b * if h : q b = 0 then 0 else (f a (_ : ¬p a = 0) b h) c) =
    q b * if h : q b = 0 then 0 else p a * if h : p a = 0 then 0 else (f a h b (_ : ¬q b = 0)) c

Next tactic:
split_ifs with h1 h2 h2
theorem bindOnSupport_comm (p : PMF α) (q : PMF β) (f : ∀ a ∈ p.support, ∀ b ∈ q.support, PMF γ) :
    (p.bindOnSupport fun a ha => q.bindOnSupport (f a ha)) =
      q.bindOnSupport fun b hb => p.bindOnSupport fun a ha => f a ha b hb := by
  apply PMF.ext; rintro c
  simp only [ENNReal.coe_eq_coe.symm, bindOnSupport_apply, ← tsum_dite_right,
    ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
  refine' _root_.trans ENNReal.tsum_comm (tsum_congr fun b => tsum_congr fun a => _)
  split_ifs with h1 h2 h2 <;> 

Proof state:
case pos
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
q : PMF β
f : (a : α) → a ∈ support p → (b : β) → b ∈ support q → PMF γ
c : γ
b : β
a : α
h1 : p a = 0
h2 : q b = 0
⊢ p a * 0 = q b * 0

Next tactic:
ring
theorem bindOnSupport_comm (p : PMF α) (q : PMF β) (f : ∀ a ∈ p.support, ∀ b ∈ q.support, PMF γ) :
    (p.bindOnSupport fun a ha => q.bindOnSupport (f a ha)) =
      q.bindOnSupport fun b hb => p.bindOnSupport fun a ha => f a ha b hb := by
  apply PMF.ext; rintro c
  simp only [ENNReal.coe_eq_coe.symm, bindOnSupport_apply, ← tsum_dite_right,
    ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
  refine' _root_.trans ENNReal.tsum_comm (tsum_congr fun b => tsum_congr fun a => _)
  split_ifs with h1 h2 h2 <;> 

Proof state:
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
q : PMF β
f : (a : α) → a ∈ support p → (b : β) → b ∈ support q → PMF γ
c : γ
b : β
a : α
h1 : p a = 0
h2 : ¬q b = 0
⊢ p a * 0 = q b * (p a * 0)

Next tactic:
ring
theorem bindOnSupport_comm (p : PMF α) (q : PMF β) (f : ∀ a ∈ p.support, ∀ b ∈ q.support, PMF γ) :
    (p.bindOnSupport fun a ha => q.bindOnSupport (f a ha)) =
      q.bindOnSupport fun b hb => p.bindOnSupport fun a ha => f a ha b hb := by
  apply PMF.ext; rintro c
  simp only [ENNReal.coe_eq_coe.symm, bindOnSupport_apply, ← tsum_dite_right,
    ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
  refine' _root_.trans ENNReal.tsum_comm (tsum_congr fun b => tsum_congr fun a => _)
  split_ifs with h1 h2 h2 <;> 

Proof state:
case pos
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
q : PMF β
f : (a : α) → a ∈ support p → (b : β) → b ∈ support q → PMF γ
c : γ
b : β
a : α
h1 : ¬p a = 0
h2 : q b = 0
⊢ p a * (q b * 0) = q b * 0

Next tactic:
ring
theorem bindOnSupport_comm (p : PMF α) (q : PMF β) (f : ∀ a ∈ p.support, ∀ b ∈ q.support, PMF γ) :
    (p.bindOnSupport fun a ha => q.bindOnSupport (f a ha)) =
      q.bindOnSupport fun b hb => p.bindOnSupport fun a ha => f a ha b hb := by
  apply PMF.ext; rintro c
  simp only [ENNReal.coe_eq_coe.symm, bindOnSupport_apply, ← tsum_dite_right,
    ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
  refine' _root_.trans ENNReal.tsum_comm (tsum_congr fun b => tsum_congr fun a => _)
  split_ifs with h1 h2 h2 <;> 

Proof state:
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
q : PMF β
f : (a : α) → a ∈ support p → (b : β) → b ∈ support q → PMF γ
c : γ
b : β
a : α
h1 : ¬p a = 0
h2 : ¬q b = 0
⊢ p a * (q b * (f a (_ : ¬p a = 0) b h2) c) = q b * (p a * (f a h1 b (_ : ¬q b = 0)) c)

Next tactic:
ring
@[simp]
theorem toOuterMeasure_bindOnSupport_apply :
    (p.bindOnSupport f).toOuterMeasure s =
      ∑' a, p a * if h : p a = 0 then 0 else (f a h).toOuterMeasure s := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f : (a : α) → a ∈ support p → PMF β
s : Set β
⊢ ↑(toOuterMeasure (bindOnSupport p f)) s = ∑' (a : α), p a * if h : p a = 0 then 0 else ↑(toOuterMeasure (f a h)) s

Next tactic:
simp only [toOuterMeasure_apply, Set.indicator_apply, bindOnSupport_apply]
@[simp]
theorem toOuterMeasure_bindOnSupport_apply :
    (p.bindOnSupport f).toOuterMeasure s =
      ∑' a, p a * if h : p a = 0 then 0 else (f a h).toOuterMeasure s := by
  simp only [toOuterMeasure_apply, Set.indicator_apply, bindOnSupport_apply]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f : (a : α) → a ∈ support p → PMF β
s : Set β
⊢ (∑' (x : β), if x ∈ s then ∑' (a : α), p a * if h : p a = 0 then 0 else (f a h) x else 0) =
    ∑' (a : α), p a * if h : p a = 0 then 0 else ∑' (x : β), if x ∈ s then (f a (_ : ¬p a = 0)) x else 0

Next tactic:
calc
    (∑' b, ite (b ∈ s) (∑' a, p a * dite (p a = 0) (fun h => 0) fun h => f a h b) 0) =
        ∑' (b) (a), ite (b ∈ s) (p a * dite (p a = 0) (fun h => 0) fun h => f a h b) 0 :=
      tsum_congr fun b => by split_ifs with hbs <;> simp only [eq_self_iff_true, tsum_zero]
    _ = ∑' (a) (b), ite (b ∈ s) (p a * dite (p a = 0) (fun h => 0) fun h => f a h b) 0 :=
      ENNReal.tsum_comm
    _ = ∑' a, p a * ∑' b, ite (b ∈ s) (dite (p a = 0) (fun h => 0) fun h => f a h b) 0 :=
      (tsum_congr fun a => by simp only [← ENNReal.tsum_mul_left, mul_ite, mul_zero])
    _ = ∑' a, p a * dite (p a = 0) (fun h => 0) fun h => ∑' b, ite (b ∈ s) (f a h b) 0 :=
      tsum_congr fun a => by split_ifs with ha <;> simp only [ite_self, tsum_zero, eq_self_iff_true]
@[simp]
theorem toOuterMeasure_bindOnSupport_apply :
    (p.bindOnSupport f).toOuterMeasure s =
      ∑' a, p a * if h : p a = 0 then 0 else (f a h).toOuterMeasure s := by
  simp only [toOuterMeasure_apply, Set.indicator_apply, bindOnSupport_apply]
  calc
    (∑' b, ite (b ∈ s) (∑' a, p a * dite (p a = 0) (fun h => 0) fun h => f a h b) 0) =
        ∑' (b) (a), ite (b ∈ s) (p a * dite (p a = 0) (fun h => 0) fun h => f a h b) 0 :=
      tsum_congr fun b => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f : (a : α) → a ∈ support p → PMF β
s : Set β
b : β
⊢ (if b ∈ s then ∑' (a : α), p a * if h : p a = 0 then 0 else (f a h) b else 0) =
    ∑' (a : α), if b ∈ s then p a * if h : p a = 0 then 0 else (f a h) b else 0

Next tactic:
split_ifs with hbs
@[simp]
theorem toOuterMeasure_bindOnSupport_apply :
    (p.bindOnSupport f).toOuterMeasure s =
      ∑' a, p a * if h : p a = 0 then 0 else (f a h).toOuterMeasure s := by
  simp only [toOuterMeasure_apply, Set.indicator_apply, bindOnSupport_apply]
  calc
    (∑' b, ite (b ∈ s) (∑' a, p a * dite (p a = 0) (fun h => 0) fun h => f a h b) 0) =
        ∑' (b) (a), ite (b ∈ s) (p a * dite (p a = 0) (fun h => 0) fun h => f a h b) 0 :=
      tsum_congr fun b => by split_ifs with hbs <;> 

Proof state:
case pos
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f : (a : α) → a ∈ support p → PMF β
s : Set β
b : β
hbs : b ∈ s
⊢ (∑' (a : α), p a * if h : p a = 0 then 0 else (f a h) b) = ∑' (a : α), p a * if h : p a = 0 then 0 else (f a h) b

Next tactic:
simp only [eq_self_iff_true, tsum_zero]
@[simp]
theorem toOuterMeasure_bindOnSupport_apply :
    (p.bindOnSupport f).toOuterMeasure s =
      ∑' a, p a * if h : p a = 0 then 0 else (f a h).toOuterMeasure s := by
  simp only [toOuterMeasure_apply, Set.indicator_apply, bindOnSupport_apply]
  calc
    (∑' b, ite (b ∈ s) (∑' a, p a * dite (p a = 0) (fun h => 0) fun h => f a h b) 0) =
        ∑' (b) (a), ite (b ∈ s) (p a * dite (p a = 0) (fun h => 0) fun h => f a h b) 0 :=
      tsum_congr fun b => by split_ifs with hbs <;> 

Proof state:
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f : (a : α) → a ∈ support p → PMF β
s : Set β
b : β
hbs : b ∉ s
⊢ 0 = ∑' (a : α), 0

Next tactic:
simp only [eq_self_iff_true, tsum_zero]
@[simp]
theorem toOuterMeasure_bindOnSupport_apply :
    (p.bindOnSupport f).toOuterMeasure s =
      ∑' a, p a * if h : p a = 0 then 0 else (f a h).toOuterMeasure s := by
  simp only [toOuterMeasure_apply, Set.indicator_apply, bindOnSupport_apply]
  calc
    (∑' b, ite (b ∈ s) (∑' a, p a * dite (p a = 0) (fun h => 0) fun h => f a h b) 0) =
        ∑' (b) (a), ite (b ∈ s) (p a * dite (p a = 0) (fun h => 0) fun h => f a h b) 0 :=
      tsum_congr fun b => by split_ifs with hbs <;> simp only [eq_self_iff_true, tsum_zero]
    _ = ∑' (a) (b), ite (b ∈ s) (p a * dite (p a = 0) (fun h => 0) fun h => f a h b) 0 :=
      ENNReal.tsum_comm
    _ = ∑' a, p a * ∑' b, ite (b ∈ s) (dite (p a = 0) (fun h => 0) fun h => f a h b) 0 :=
      (tsum_congr fun a => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f : (a : α) → a ∈ support p → PMF β
s : Set β
a : α
⊢ (∑' (b : β), if b ∈ s then p a * if h : p a = 0 then 0 else (f a h) b else 0) =
    p a * ∑' (b : β), if b ∈ s then if h : p a = 0 then 0 else (f a h) b else 0

Next tactic:
simp only [← ENNReal.tsum_mul_left, mul_ite, mul_zero]