l3lab/ntp-mathlib huggingface dataset:
/-- Generalized version of `bind` allowing `f` to only be defined on the support of `p`.
  `p.bind f` is equivalent to `p.bindOnSupport (fun a _ ↦ f a)`, see `bindOnSupport_eq_bind`. -/
def bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF β) : PMF β :=
  ⟨fun b => ∑' a, p a * if h : p a = 0 then 0 else f a h b, ENNReal.summable.hasSum_iff.2 (by
    

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

Next tactic:
refine' ENNReal.tsum_comm.trans (_root_.trans (tsum_congr fun a => _) p.tsum_coe)
/-- Generalized version of `bind` allowing `f` to only be defined on the support of `p`.
  `p.bind f` is equivalent to `p.bindOnSupport (fun a _ ↦ f a)`, see `bindOnSupport_eq_bind`. -/
def bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF β) : PMF β :=
  ⟨fun b => ∑' a, p a * if h : p a = 0 then 0 else f a h b, ENNReal.summable.hasSum_iff.2 (by
    refine' ENNReal.tsum_comm.trans (_root_.trans (tsum_congr fun a => _) p.tsum_coe)
    

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

Next tactic:
simp_rw [ENNReal.tsum_mul_left]
/-- Generalized version of `bind` allowing `f` to only be defined on the support of `p`.
  `p.bind f` is equivalent to `p.bindOnSupport (fun a _ ↦ f a)`, see `bindOnSupport_eq_bind`. -/
def bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF β) : PMF β :=
  ⟨fun b => ∑' a, p a * if h : p a = 0 then 0 else f a h b, ENNReal.summable.hasSum_iff.2 (by
    refine' ENNReal.tsum_comm.trans (_root_.trans (tsum_congr fun a => _) p.tsum_coe)
    simp_rw [ENNReal.tsum_mul_left]
    

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

Next tactic:
split_ifs with h
/-- Generalized version of `bind` allowing `f` to only be defined on the support of `p`.
  `p.bind f` is equivalent to `p.bindOnSupport (fun a _ ↦ f a)`, see `bindOnSupport_eq_bind`. -/
def bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF β) : PMF β :=
  ⟨fun b => ∑' a, p a * if h : p a = 0 then 0 else f a h b, ENNReal.summable.hasSum_iff.2 (by
    refine' ENNReal.tsum_comm.trans (_root_.trans (tsum_congr fun a => _) p.tsum_coe)
    simp_rw [ENNReal.tsum_mul_left]
    split_ifs with h
    · 

Proof state:
case pos
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f : (a : α) → a ∈ support p → PMF β
a : α
h : p a = 0
⊢ p a * ∑' (i : β), 0 = p a

Next tactic:
simp only [h, zero_mul]
/-- Generalized version of `bind` allowing `f` to only be defined on the support of `p`.
  `p.bind f` is equivalent to `p.bindOnSupport (fun a _ ↦ f a)`, see `bindOnSupport_eq_bind`. -/
def bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF β) : PMF β :=
  ⟨fun b => ∑' a, p a * if h : p a = 0 then 0 else f a h b, ENNReal.summable.hasSum_iff.2 (by
    refine' ENNReal.tsum_comm.trans (_root_.trans (tsum_congr fun a => _) p.tsum_coe)
    simp_rw [ENNReal.tsum_mul_left]
    split_ifs with h
    · simp only [h, zero_mul]
    · 

Proof state:
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f : (a : α) → a ∈ support p → PMF β
a : α
h : ¬p a = 0
⊢ p a * ∑' (i : β), (f a h) i = p a

Next tactic:
rw [(f a h).tsum_coe, mul_one]
@[simp]
theorem support_bindOnSupport :
    (p.bindOnSupport f).support = ⋃ (a : α) (h : a ∈ p.support), (f a h).support := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f : (a : α) → a ∈ support p → PMF β
⊢ support (bindOnSupport p f) = ⋃ a, ⋃ (h : a ∈ support p), support (f a h)

Next tactic:
refine' Set.ext fun b => _
@[simp]
theorem support_bindOnSupport :
    (p.bindOnSupport f).support = ⋃ (a : α) (h : a ∈ p.support), (f a h).support := by
  refine' Set.ext fun b => _
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f : (a : α) → a ∈ support p → PMF β
b : β
⊢ b ∈ support (bindOnSupport p f) ↔ b ∈ ⋃ a, ⋃ (h : a ∈ support p), support (f a h)

Next tactic:
simp only [ENNReal.tsum_eq_zero, not_or, mem_support_iff, bindOnSupport_apply, Ne.def, not_forall,
    mul_eq_zero, Set.mem_iUnion]
@[simp]
theorem support_bindOnSupport :
    (p.bindOnSupport f).support = ⋃ (a : α) (h : a ∈ p.support), (f a h).support := by
  refine' Set.ext fun b => _
  simp only [ENNReal.tsum_eq_zero, not_or, mem_support_iff, bindOnSupport_apply, Ne.def, not_forall,
    mul_eq_zero, Set.mem_iUnion]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f : (a : α) → a ∈ support p → PMF β
b : β
⊢ (∃ x, ¬p x = 0 ∧ ¬(if h : p x = 0 then 0 else (f x h) b) = 0) ↔
    ∃ i, ∃ (h : ¬p i = 0), ¬(f i (_ : i ∈ support p)) b = 0

Next tactic:
exact
    ⟨fun hb =>
      let ⟨a, ⟨ha, ha'⟩⟩ := hb
      ⟨a, ha, by simpa [ha] using ha'⟩,
      fun hb =>
      let ⟨a, ha, ha'⟩ := hb
      ⟨a, ⟨ha, by simpa [(mem_support_iff _ a).1 ha] using ha'⟩⟩⟩
@[simp]
theorem support_bindOnSupport :
    (p.bindOnSupport f).support = ⋃ (a : α) (h : a ∈ p.support), (f a h).support := by
  refine' Set.ext fun b => _
  simp only [ENNReal.tsum_eq_zero, not_or, mem_support_iff, bindOnSupport_apply, Ne.def, not_forall,
    mul_eq_zero, Set.mem_iUnion]
  exact
    ⟨fun hb =>
      let ⟨a, ⟨ha, ha'⟩⟩ := hb
      ⟨a, ha, by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f : (a : α) → a ∈ support p → PMF β
b : β
hb : ∃ x, ¬p x = 0 ∧ ¬(if h : p x = 0 then 0 else (f x h) b) = 0
a : α
ha : ¬p a = 0
ha' : ¬(if h : p a = 0 then 0 else (f a h) b) = 0
⊢ ¬(f a (_ : a ∈ support p)) b = 0

Next tactic:
simpa [ha] using ha'
@[simp]
theorem support_bindOnSupport :
    (p.bindOnSupport f).support = ⋃ (a : α) (h : a ∈ p.support), (f a h).support := by
  refine' Set.ext fun b => _
  simp only [ENNReal.tsum_eq_zero, not_or, mem_support_iff, bindOnSupport_apply, Ne.def, not_forall,
    mul_eq_zero, Set.mem_iUnion]
  exact
    ⟨fun hb =>
      let ⟨a, ⟨ha, ha'⟩⟩ := hb
      ⟨a, ha, by simpa [ha] using ha'⟩,
      fun hb =>
      let ⟨a, ha, ha'⟩ := hb
      ⟨a, ⟨ha, by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f : (a : α) → a ∈ support p → PMF β
b : β
hb : ∃ i, ∃ (h : ¬p i = 0), ¬(f i (_ : i ∈ support p)) b = 0
a : α
ha : ¬p a = 0
ha' : ¬(f a (_ : a ∈ support p)) b = 0
⊢ ¬(if h : p a = 0 then 0 else (f a h) b) = 0

Next tactic:
simpa [(mem_support_iff _ a).1 ha] using ha'
theorem mem_support_bindOnSupport_iff (b : β) :
    b ∈ (p.bindOnSupport f).support ↔ ∃ (a : α) (h : a ∈ p.support), b ∈ (f a h).support := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f : (a : α) → a ∈ support p → PMF β
b : β
⊢ b ∈ support (bindOnSupport p f) ↔ ∃ a, ∃ (h : a ∈ support p), b ∈ support (f a h)

Next tactic:
simp only [support_bindOnSupport, Set.mem_setOf_eq, Set.mem_iUnion]
/-- `bindOnSupport` reduces to `bind` if `f` doesn't depend on the additional hypothesis. -/
@[simp]
theorem bindOnSupport_eq_bind (p : PMF α) (f : α → PMF β) :
    (p.bindOnSupport fun a _ => f a) = p.bind f := by
  

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

Next tactic:
ext b
/-- `bindOnSupport` reduces to `bind` if `f` doesn't depend on the additional hypothesis. -/
@[simp]
theorem bindOnSupport_eq_bind (p : PMF α) (f : α → PMF β) :
    (p.bindOnSupport fun a _ => f a) = p.bind f := by
  ext b
  

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

Next tactic:
have : ∀ a, ite (p a = 0) 0 (p a * f a b) = p a * f a b :=
    fun a => ite_eq_right_iff.2 fun h => h.symm ▸ symm (zero_mul <| f a b)
/-- `bindOnSupport` reduces to `bind` if `f` doesn't depend on the additional hypothesis. -/
@[simp]
theorem bindOnSupport_eq_bind (p : PMF α) (f : α → PMF β) :
    (p.bindOnSupport fun a _ => f a) = p.bind f := by
  ext b
  have : ∀ a, ite (p a = 0) 0 (p a * f a b) = p a * f a b :=
    fun a => ite_eq_right_iff.2 fun h => h.symm ▸ symm (zero_mul <| f a b)
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
p✝ : PMF α
f✝ : (a : α) → a ∈ support p✝ → PMF β
p : PMF α
f : α → PMF β
b : β
this : ∀ (a : α), (if p a = 0 then 0 else p a * (f a) b) = p a * (f a) b
⊢ (bindOnSupport p fun a x => f a) b = (bind p f) b

Next tactic:
simp only [bindOnSupport_apply fun a _ => f a, p.bind_apply f, dite_eq_ite, mul_ite,
    mul_zero, this]
theorem bindOnSupport_eq_zero_iff (b : β) :
    p.bindOnSupport f b = 0 ↔ ∀ (a) (ha : p a ≠ 0), f a ha b = 0 := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f : (a : α) → a ∈ support p → PMF β
b : β
⊢ (bindOnSupport p f) b = 0 ↔ ∀ (a : α) (ha : p a ≠ 0), (f a ha) b = 0

Next tactic:
simp only [bindOnSupport_apply, ENNReal.tsum_eq_zero, mul_eq_zero, or_iff_not_imp_left]
theorem bindOnSupport_eq_zero_iff (b : β) :
    p.bindOnSupport f b = 0 ↔ ∀ (a) (ha : p a ≠ 0), f a ha b = 0 := by
  simp only [bindOnSupport_apply, ENNReal.tsum_eq_zero, mul_eq_zero, or_iff_not_imp_left]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f : (a : α) → a ∈ support p → PMF β
b : β
⊢ (∀ (i : α), ¬p i = 0 → (if h : p i = 0 then 0 else (f i h) b) = 0) ↔ ∀ (a : α) (ha : p a ≠ 0), (f a ha) b = 0

Next tactic:
exact ⟨fun h a ha => Trans.trans (dif_neg ha).symm (h a ha),
    fun h a ha => Trans.trans (dif_neg ha) (h a ha)⟩
@[simp]
theorem pure_bindOnSupport (a : α) (f : ∀ (a' : α) (_ : a' ∈ (pure a).support), PMF β) :
    (pure a).bindOnSupport f = f a ((mem_support_pure_iff a a).mpr rfl) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f✝ : (a : α) → a ∈ support p → PMF β
a : α
f : (a' : α) → a' ∈ support (pure a) → PMF β
⊢ bindOnSupport (pure a) f = f a (_ : a ∈ support (pure a))

Next tactic:
refine' PMF.ext fun b => _
@[simp]
theorem pure_bindOnSupport (a : α) (f : ∀ (a' : α) (_ : a' ∈ (pure a).support), PMF β) :
    (pure a).bindOnSupport f = f a ((mem_support_pure_iff a a).mpr rfl) := by
  refine' PMF.ext fun b => _
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
p : PMF α
f✝ : (a : α) → a ∈ support p → PMF β
a : α
f : (a' : α) → a' ∈ support (pure a) → PMF β
b : β
⊢ (bindOnSupport (pure a) f) b = (f a (_ : a ∈ support (pure a))) b

Next tactic:
simp only [bindOnSupport_apply, pure_apply]
@[simp]
theorem pure_bindOnSupport (a : α) (f : ∀ (a' : α) (_ : a' ∈ (pure a).support), PMF β) :
    (pure a).bindOnSupport f = f a ((mem_support_pure_iff a a).mpr rfl) := by
  refine' PMF.ext fun b => _
  simp only [bindOnSupport_apply, pure_apply]
  

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

Next tactic:
refine' _root_.trans (tsum_congr fun a' => _) (tsum_ite_eq a _)
@[simp]
theorem pure_bindOnSupport (a : α) (f : ∀ (a' : α) (_ : a' ∈ (pure a).support), PMF β) :
    (pure a).bindOnSupport f = f a ((mem_support_pure_iff a a).mpr rfl) := by
  refine' PMF.ext fun b => _
  simp only [bindOnSupport_apply, pure_apply]
  refine' _root_.trans (tsum_congr fun a' => _) (tsum_ite_eq a _)
  

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

Next tactic:
by_cases h : a' = a
@[simp]
theorem pure_bindOnSupport (a : α) (f : ∀ (a' : α) (_ : a' ∈ (pure a).support), PMF β) :
    (pure a).bindOnSupport f = f a ((mem_support_pure_iff a a).mpr rfl) := by
  refine' PMF.ext fun b => _
  simp only [bindOnSupport_apply, pure_apply]
  refine' _root_.trans (tsum_congr fun a' => _) (tsum_ite_eq a _)
  by_cases h : a' = a <;> 

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

Next tactic:
simp [h]
@[simp]
theorem pure_bindOnSupport (a : α) (f : ∀ (a' : α) (_ : a' ∈ (pure a).support), PMF β) :
    (pure a).bindOnSupport f = f a ((mem_support_pure_iff a a).mpr rfl) := by
  refine' PMF.ext fun b => _
  simp only [bindOnSupport_apply, pure_apply]
  refine' _root_.trans (tsum_congr fun a' => _) (tsum_ite_eq a _)
  by_cases h : a' = a <;> 

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

Next tactic:
simp [h]
theorem bindOnSupport_pure (p : PMF α) : (p.bindOnSupport fun a _ => pure a) = p := by
  

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

Next tactic:
simp only [PMF.bind_pure, PMF.bindOnSupport_eq_bind]
@[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
  

Proof state:
α : 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 γ
⊢ bindOnSupport (bindOnSupport p f) g =
    bindOnSupport p fun a ha => bindOnSupport (f a ha) fun b hb => g b (_ : b ∈ support (bindOnSupport p f))

Next tactic:
refine' PMF.ext fun 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 => _
  

Proof state:
α : 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 : γ
⊢ (bindOnSupport (bindOnSupport p f) g) a =
    (bindOnSupport p fun a ha => bindOnSupport (f a ha) fun b hb => g b (_ : b ∈ support (bindOnSupport p f))) a

Next tactic:
dsimp only [bindOnSupport_apply]
@[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]
  

Proof state:
α : 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_1 : β),
      (∑' (a : α), p a * if h : p a = 0 then 0 else (f a h) a_1) *
        if h : (∑' (a : α), p a * if h : p a = 0 then 0 else (f a h) a_1) = 0 then 0 else (g a_1 h) a) =
    ∑' (a_1 : α),
      p a_1 *
        if h : p a_1 = 0 then 0
        else
          ∑' (a_2 : β),
            (f a_1 h) a_2 * if h : (f a_1 h) a_2 = 0 then 0 else (g a_2 (_ : a_2 ∈ support (bindOnSupport p f))) a

Next tactic:
simp only [← tsum_dite_right, ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm]
@[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]
  

Proof state:
α : 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_1 : β) (i : α),
      (p i * if h : p i = 0 then 0 else (f i h) a_1) *
        if h : (∑' (a : α), p a * if h : p a = 0 then 0 else (f a h) a_1) = 0 then 0 else (g a_1 h) a) =
    ∑' (a_1 : α) (i : β),
      p a_1 *
        if h : p a_1 = 0 then 0
        else (f a_1 h) i * if h : (f a_1 h) i = 0 then 0 else (g i (_ : i ∈ support (bindOnSupport p f))) a

Next tactic:
simp only [ENNReal.tsum_eq_zero, dite_eq_left_iff]
@[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]
  

Proof state:
α : 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_1 : β) (i : α),
      (p i * if h : p i = 0 then 0 else (f i h) a_1) *
        if h : ∀ (i : α), (p i * if h : p i = 0 then 0 else (f i h) a_1) = 0 then 0
        else (g a_1 (_ : ¬(∑' (a : α), p a * if h : p a = 0 then 0 else (f a h) a_1) = 0)) a) =
    ∑' (a_1 : α) (i : β),
      p a_1 *
        if h : p a_1 = 0 then 0
        else (f a_1 h) i * if h : (f a_1 h) i = 0 then 0 else (g i (_ : i ∈ support (bindOnSupport p f))) a

Next tactic:
refine' ENNReal.tsum_comm.trans (tsum_congr fun a' => tsum_congr fun b => _)
@[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 => _)
  

Proof state:
α : 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 : β
⊢ ((p a' * if h : p a' = 0 then 0 else (f a' h) b) *
      if h : ∀ (i : α), (p i * if h : p i = 0 then 0 else (f i h) b) = 0 then 0
      else (g b (_ : ¬(∑' (a : α), p a * if h : p a = 0 then 0 else (f a h) b) = 0)) a) =
    p a' *
      if h : p a' = 0 then 0
      else (f a' h) b * if h : (f a' h) b = 0 then 0 else (g b (_ : b ∈ support (bindOnSupport p f))) a

Next tactic:
split_ifs with h _ h_1 _ h_2
@[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
  

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
_ : ∀ (i : α), (p i * if h : p i = 0 then 0 else (f i h) b) = 0
⊢ p a' * 0 * 0 = p a' * 0
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
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)
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)
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)
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:
any_goals 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
_ : ∀ (i : α), (p i * if h : p i = 0 then 0 else (f i h) b) = 0
⊢ p a' * 0 * 0 = p a' * 0

Next tactic:
ring1