l3lab/ntp-mathlib huggingface dataset:
/-- The product of generated σ-algebras is the one generated by boxes, if both generating sets
  are countably spanning. -/
theorem generateFrom_pi_eq {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) :
    (@MeasurableSpace.pi _ _ fun i => generateFrom (C i)) =
    generateFrom (pi univ '' pi univ C) := by
  cases nonempty_encodable ι
  apply le_antisymm
  · refine' iSup_le _; intro i; rw [comap_generateFrom]
    apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩; dsimp
    choose t h1t h2t using hC
    simp_rw [eval_preimage, ← h2t]
    rw [← @iUnion_const _ ℕ _ s]
    have : Set.pi univ (update (fun i' : ι => iUnion (t i')) i (⋃ _ : ℕ, s)) =
        Set.pi univ fun k => ⋃ j : ℕ,
        @update ι (fun i' => Set (α i')) _ (fun i' => t i' j) i s k := by
      ext; simp_rw [mem_univ_pi]; apply forall_congr'; intro i'
      by_cases h : i' = i
      · subst h; simp
      · rw [← Ne.def] at h; simp [h]
    rw [this, ← iUnion_univ_pi]
    apply MeasurableSet.iUnion
    intro n; apply measurableSet_generateFrom
    apply mem_image_of_mem; intro j _; dsimp only
    by_cases h : j = i; subst h; rwa [update_same]; 

Proof state:
case neg
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝¹ : Finite ι
inst✝ : Finite ι'
C : (i : ι) → Set (Set (α i))
val✝ : Encodable ι
i : ι
s : Set ((fun i => α i) i)
hs : s ∈ C i
t : (i : ι) → ℕ → Set (α i)
h1t : ∀ (i : ι) (n : ℕ), t i n ∈ C i
h2t : ∀ (i : ι), ⋃ n, t i n = univ
this :
  Set.pi univ (update (fun i' => iUnion (t i')) i (⋃ x, s)) = Set.pi univ fun k => ⋃ j, update (fun i' => t i' j) i s k
n : ι → ℕ
j : ι
a✝ : j ∈ univ
h : ¬j = i
⊢ update (fun i' => t i' (n j)) i s j ∈ C j

Next tactic:
rw [update_noteq h]
/-- The product of generated σ-algebras is the one generated by boxes, if both generating sets
  are countably spanning. -/
theorem generateFrom_pi_eq {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) :
    (@MeasurableSpace.pi _ _ fun i => generateFrom (C i)) =
    generateFrom (pi univ '' pi univ C) := by
  cases nonempty_encodable ι
  apply le_antisymm
  · refine' iSup_le _; intro i; rw [comap_generateFrom]
    apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩; dsimp
    choose t h1t h2t using hC
    simp_rw [eval_preimage, ← h2t]
    rw [← @iUnion_const _ ℕ _ s]
    have : Set.pi univ (update (fun i' : ι => iUnion (t i')) i (⋃ _ : ℕ, s)) =
        Set.pi univ fun k => ⋃ j : ℕ,
        @update ι (fun i' => Set (α i')) _ (fun i' => t i' j) i s k := by
      ext; simp_rw [mem_univ_pi]; apply forall_congr'; intro i'
      by_cases h : i' = i
      · subst h; simp
      · rw [← Ne.def] at h; simp [h]
    rw [this, ← iUnion_univ_pi]
    apply MeasurableSet.iUnion
    intro n; apply measurableSet_generateFrom
    apply mem_image_of_mem; intro j _; dsimp only
    by_cases h : j = i; subst h; rwa [update_same]; rw [update_noteq h]; 

Proof state:
case neg
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝¹ : Finite ι
inst✝ : Finite ι'
C : (i : ι) → Set (Set (α i))
val✝ : Encodable ι
i : ι
s : Set ((fun i => α i) i)
hs : s ∈ C i
t : (i : ι) → ℕ → Set (α i)
h1t : ∀ (i : ι) (n : ℕ), t i n ∈ C i
h2t : ∀ (i : ι), ⋃ n, t i n = univ
this :
  Set.pi univ (update (fun i' => iUnion (t i')) i (⋃ x, s)) = Set.pi univ fun k => ⋃ j, update (fun i' => t i' j) i s k
n : ι → ℕ
j : ι
a✝ : j ∈ univ
h : ¬j = i
⊢ t j (n j) ∈ C j

Next tactic:
apply h1t
/-- The product of generated σ-algebras is the one generated by boxes, if both generating sets
  are countably spanning. -/
theorem generateFrom_pi_eq {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) :
    (@MeasurableSpace.pi _ _ fun i => generateFrom (C i)) =
    generateFrom (pi univ '' pi univ C) := by
  cases nonempty_encodable ι
  apply le_antisymm
  · refine' iSup_le _; intro i; rw [comap_generateFrom]
    apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩; dsimp
    choose t h1t h2t using hC
    simp_rw [eval_preimage, ← h2t]
    rw [← @iUnion_const _ ℕ _ s]
    have : Set.pi univ (update (fun i' : ι => iUnion (t i')) i (⋃ _ : ℕ, s)) =
        Set.pi univ fun k => ⋃ j : ℕ,
        @update ι (fun i' => Set (α i')) _ (fun i' => t i' j) i s k := by
      ext; simp_rw [mem_univ_pi]; apply forall_congr'; intro i'
      by_cases h : i' = i
      · subst h; simp
      · rw [← Ne.def] at h; simp [h]
    rw [this, ← iUnion_univ_pi]
    apply MeasurableSet.iUnion
    intro n; apply measurableSet_generateFrom
    apply mem_image_of_mem; intro j _; dsimp only
    by_cases h : j = i; subst h; rwa [update_same]; rw [update_noteq h]; apply h1t
  · 

Proof state:
case intro.a
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝¹ : Finite ι
inst✝ : Finite ι'
C : (i : ι) → Set (Set (α i))
hC : ∀ (i : ι), IsCountablySpanning (C i)
val✝ : Encodable ι
⊢ generateFrom (Set.pi univ '' Set.pi univ C) ≤ MeasurableSpace.pi

Next tactic:
apply generateFrom_le
/-- The product of generated σ-algebras is the one generated by boxes, if both generating sets
  are countably spanning. -/
theorem generateFrom_pi_eq {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) :
    (@MeasurableSpace.pi _ _ fun i => generateFrom (C i)) =
    generateFrom (pi univ '' pi univ C) := by
  cases nonempty_encodable ι
  apply le_antisymm
  · refine' iSup_le _; intro i; rw [comap_generateFrom]
    apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩; dsimp
    choose t h1t h2t using hC
    simp_rw [eval_preimage, ← h2t]
    rw [← @iUnion_const _ ℕ _ s]
    have : Set.pi univ (update (fun i' : ι => iUnion (t i')) i (⋃ _ : ℕ, s)) =
        Set.pi univ fun k => ⋃ j : ℕ,
        @update ι (fun i' => Set (α i')) _ (fun i' => t i' j) i s k := by
      ext; simp_rw [mem_univ_pi]; apply forall_congr'; intro i'
      by_cases h : i' = i
      · subst h; simp
      · rw [← Ne.def] at h; simp [h]
    rw [this, ← iUnion_univ_pi]
    apply MeasurableSet.iUnion
    intro n; apply measurableSet_generateFrom
    apply mem_image_of_mem; intro j _; dsimp only
    by_cases h : j = i; subst h; rwa [update_same]; rw [update_noteq h]; apply h1t
  · apply generateFrom_le; 

Proof state:
case intro.a.h
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝¹ : Finite ι
inst✝ : Finite ι'
C : (i : ι) → Set (Set (α i))
hC : ∀ (i : ι), IsCountablySpanning (C i)
val✝ : Encodable ι
⊢ ∀ t ∈ Set.pi univ '' Set.pi univ C, MeasurableSet t

Next tactic:
rintro _ ⟨s, hs, rfl⟩
/-- The product of generated σ-algebras is the one generated by boxes, if both generating sets
  are countably spanning. -/
theorem generateFrom_pi_eq {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) :
    (@MeasurableSpace.pi _ _ fun i => generateFrom (C i)) =
    generateFrom (pi univ '' pi univ C) := by
  cases nonempty_encodable ι
  apply le_antisymm
  · refine' iSup_le _; intro i; rw [comap_generateFrom]
    apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩; dsimp
    choose t h1t h2t using hC
    simp_rw [eval_preimage, ← h2t]
    rw [← @iUnion_const _ ℕ _ s]
    have : Set.pi univ (update (fun i' : ι => iUnion (t i')) i (⋃ _ : ℕ, s)) =
        Set.pi univ fun k => ⋃ j : ℕ,
        @update ι (fun i' => Set (α i')) _ (fun i' => t i' j) i s k := by
      ext; simp_rw [mem_univ_pi]; apply forall_congr'; intro i'
      by_cases h : i' = i
      · subst h; simp
      · rw [← Ne.def] at h; simp [h]
    rw [this, ← iUnion_univ_pi]
    apply MeasurableSet.iUnion
    intro n; apply measurableSet_generateFrom
    apply mem_image_of_mem; intro j _; dsimp only
    by_cases h : j = i; subst h; rwa [update_same]; rw [update_noteq h]; apply h1t
  · apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩
    

Proof state:
case intro.a.h.intro.intro
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝¹ : Finite ι
inst✝ : Finite ι'
C : (i : ι) → Set (Set (α i))
hC : ∀ (i : ι), IsCountablySpanning (C i)
val✝ : Encodable ι
s : (i : ι) → Set (α i)
hs : s ∈ Set.pi univ C
⊢ MeasurableSet (Set.pi univ s)

Next tactic:
rw [univ_pi_eq_iInter]
/-- The product of generated σ-algebras is the one generated by boxes, if both generating sets
  are countably spanning. -/
theorem generateFrom_pi_eq {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) :
    (@MeasurableSpace.pi _ _ fun i => generateFrom (C i)) =
    generateFrom (pi univ '' pi univ C) := by
  cases nonempty_encodable ι
  apply le_antisymm
  · refine' iSup_le _; intro i; rw [comap_generateFrom]
    apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩; dsimp
    choose t h1t h2t using hC
    simp_rw [eval_preimage, ← h2t]
    rw [← @iUnion_const _ ℕ _ s]
    have : Set.pi univ (update (fun i' : ι => iUnion (t i')) i (⋃ _ : ℕ, s)) =
        Set.pi univ fun k => ⋃ j : ℕ,
        @update ι (fun i' => Set (α i')) _ (fun i' => t i' j) i s k := by
      ext; simp_rw [mem_univ_pi]; apply forall_congr'; intro i'
      by_cases h : i' = i
      · subst h; simp
      · rw [← Ne.def] at h; simp [h]
    rw [this, ← iUnion_univ_pi]
    apply MeasurableSet.iUnion
    intro n; apply measurableSet_generateFrom
    apply mem_image_of_mem; intro j _; dsimp only
    by_cases h : j = i; subst h; rwa [update_same]; rw [update_noteq h]; apply h1t
  · apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩
    rw [univ_pi_eq_iInter]; 

Proof state:
case intro.a.h.intro.intro
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝¹ : Finite ι
inst✝ : Finite ι'
C : (i : ι) → Set (Set (α i))
hC : ∀ (i : ι), IsCountablySpanning (C i)
val✝ : Encodable ι
s : (i : ι) → Set (α i)
hs : s ∈ Set.pi univ C
⊢ MeasurableSet (⋂ i, eval i ⁻¹' s i)

Next tactic:
apply MeasurableSet.iInter
/-- The product of generated σ-algebras is the one generated by boxes, if both generating sets
  are countably spanning. -/
theorem generateFrom_pi_eq {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) :
    (@MeasurableSpace.pi _ _ fun i => generateFrom (C i)) =
    generateFrom (pi univ '' pi univ C) := by
  cases nonempty_encodable ι
  apply le_antisymm
  · refine' iSup_le _; intro i; rw [comap_generateFrom]
    apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩; dsimp
    choose t h1t h2t using hC
    simp_rw [eval_preimage, ← h2t]
    rw [← @iUnion_const _ ℕ _ s]
    have : Set.pi univ (update (fun i' : ι => iUnion (t i')) i (⋃ _ : ℕ, s)) =
        Set.pi univ fun k => ⋃ j : ℕ,
        @update ι (fun i' => Set (α i')) _ (fun i' => t i' j) i s k := by
      ext; simp_rw [mem_univ_pi]; apply forall_congr'; intro i'
      by_cases h : i' = i
      · subst h; simp
      · rw [← Ne.def] at h; simp [h]
    rw [this, ← iUnion_univ_pi]
    apply MeasurableSet.iUnion
    intro n; apply measurableSet_generateFrom
    apply mem_image_of_mem; intro j _; dsimp only
    by_cases h : j = i; subst h; rwa [update_same]; rw [update_noteq h]; apply h1t
  · apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩
    rw [univ_pi_eq_iInter]; apply MeasurableSet.iInter; 

Proof state:
case intro.a.h.intro.intro.h
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝¹ : Finite ι
inst✝ : Finite ι'
C : (i : ι) → Set (Set (α i))
hC : ∀ (i : ι), IsCountablySpanning (C i)
val✝ : Encodable ι
s : (i : ι) → Set (α i)
hs : s ∈ Set.pi univ C
⊢ ∀ (b : ι), MeasurableSet (eval b ⁻¹' s b)

Next tactic:
intro i
/-- The product of generated σ-algebras is the one generated by boxes, if both generating sets
  are countably spanning. -/
theorem generateFrom_pi_eq {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) :
    (@MeasurableSpace.pi _ _ fun i => generateFrom (C i)) =
    generateFrom (pi univ '' pi univ C) := by
  cases nonempty_encodable ι
  apply le_antisymm
  · refine' iSup_le _; intro i; rw [comap_generateFrom]
    apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩; dsimp
    choose t h1t h2t using hC
    simp_rw [eval_preimage, ← h2t]
    rw [← @iUnion_const _ ℕ _ s]
    have : Set.pi univ (update (fun i' : ι => iUnion (t i')) i (⋃ _ : ℕ, s)) =
        Set.pi univ fun k => ⋃ j : ℕ,
        @update ι (fun i' => Set (α i')) _ (fun i' => t i' j) i s k := by
      ext; simp_rw [mem_univ_pi]; apply forall_congr'; intro i'
      by_cases h : i' = i
      · subst h; simp
      · rw [← Ne.def] at h; simp [h]
    rw [this, ← iUnion_univ_pi]
    apply MeasurableSet.iUnion
    intro n; apply measurableSet_generateFrom
    apply mem_image_of_mem; intro j _; dsimp only
    by_cases h : j = i; subst h; rwa [update_same]; rw [update_noteq h]; apply h1t
  · apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩
    rw [univ_pi_eq_iInter]; apply MeasurableSet.iInter; intro i
    

Proof state:
case intro.a.h.intro.intro.h
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝¹ : Finite ι
inst✝ : Finite ι'
C : (i : ι) → Set (Set (α i))
hC : ∀ (i : ι), IsCountablySpanning (C i)
val✝ : Encodable ι
s : (i : ι) → Set (α i)
hs : s ∈ Set.pi univ C
i : ι
⊢ MeasurableSet (eval i ⁻¹' s i)

Next tactic:
apply @measurable_pi_apply _ _ (fun i => generateFrom (C i))
/-- The product of generated σ-algebras is the one generated by boxes, if both generating sets
  are countably spanning. -/
theorem generateFrom_pi_eq {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) :
    (@MeasurableSpace.pi _ _ fun i => generateFrom (C i)) =
    generateFrom (pi univ '' pi univ C) := by
  cases nonempty_encodable ι
  apply le_antisymm
  · refine' iSup_le _; intro i; rw [comap_generateFrom]
    apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩; dsimp
    choose t h1t h2t using hC
    simp_rw [eval_preimage, ← h2t]
    rw [← @iUnion_const _ ℕ _ s]
    have : Set.pi univ (update (fun i' : ι => iUnion (t i')) i (⋃ _ : ℕ, s)) =
        Set.pi univ fun k => ⋃ j : ℕ,
        @update ι (fun i' => Set (α i')) _ (fun i' => t i' j) i s k := by
      ext; simp_rw [mem_univ_pi]; apply forall_congr'; intro i'
      by_cases h : i' = i
      · subst h; simp
      · rw [← Ne.def] at h; simp [h]
    rw [this, ← iUnion_univ_pi]
    apply MeasurableSet.iUnion
    intro n; apply measurableSet_generateFrom
    apply mem_image_of_mem; intro j _; dsimp only
    by_cases h : j = i; subst h; rwa [update_same]; rw [update_noteq h]; apply h1t
  · apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩
    rw [univ_pi_eq_iInter]; apply MeasurableSet.iInter; intro i
    apply @measurable_pi_apply _ _ (fun i => generateFrom (C i))
    

Proof state:
case intro.a.h.intro.intro.h.a
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝¹ : Finite ι
inst✝ : Finite ι'
C : (i : ι) → Set (Set (α i))
hC : ∀ (i : ι), IsCountablySpanning (C i)
val✝ : Encodable ι
s : (i : ι) → Set (α i)
hs : s ∈ Set.pi univ C
i : ι
⊢ MeasurableSet (s i)

Next tactic:
exact measurableSet_generateFrom (hs i (mem_univ i))
/-- If `C` and `D` generate the σ-algebras on `α` resp. `β`, then rectangles formed by `C` and `D`
  generate the σ-algebra on `α × β`. -/
theorem generateFrom_eq_pi [h : ∀ i, MeasurableSpace (α i)] {C : ∀ i, Set (Set (α i))}
    (hC : ∀ i, generateFrom (C i) = h i) (h2C : ∀ i, IsCountablySpanning (C i)) :
    generateFrom (pi univ '' pi univ C) = MeasurableSpace.pi := by
  

Proof state:
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝¹ : Finite ι
inst✝ : Finite ι'
h : (i : ι) → MeasurableSpace (α i)
C : (i : ι) → Set (Set (α i))
hC : ∀ (i : ι), generateFrom (C i) = h i
h2C : ∀ (i : ι), IsCountablySpanning (C i)
⊢ generateFrom (Set.pi univ '' Set.pi univ C) = MeasurableSpace.pi

Next tactic:
rw [← funext hC, generateFrom_pi_eq h2C]
theorem piPremeasure_pi {s : ∀ i, Set (α i)} (hs : (pi univ s).Nonempty) :
    piPremeasure m (pi univ s) = ∏ i, m i (s i) := by 

Proof state:
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m : (i : ι) → OuterMeasure (α i)
s : (i : ι) → Set (α i)
hs : Set.Nonempty (Set.pi univ s)
⊢ piPremeasure m (Set.pi univ s) = ∏ i : ι, ↑(m i) (s i)

Next tactic:
simp [hs, piPremeasure]
theorem piPremeasure_pi' {s : ∀ i, Set (α i)} : piPremeasure m (pi univ s) = ∏ i, m i (s i) := by
  

Proof state:
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m : (i : ι) → OuterMeasure (α i)
s : (i : ι) → Set (α i)
⊢ piPremeasure m (Set.pi univ s) = ∏ i : ι, ↑(m i) (s i)

Next tactic:
cases isEmpty_or_nonempty ι
theorem piPremeasure_pi' {s : ∀ i, Set (α i)} : piPremeasure m (pi univ s) = ∏ i, m i (s i) := by
  cases isEmpty_or_nonempty ι
  · 

Proof state:
case inl
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m : (i : ι) → OuterMeasure (α i)
s : (i : ι) → Set (α i)
h✝ : IsEmpty ι
⊢ piPremeasure m (Set.pi univ s) = ∏ i : ι, ↑(m i) (s i)

Next tactic:
simp [piPremeasure]
theorem piPremeasure_pi' {s : ∀ i, Set (α i)} : piPremeasure m (pi univ s) = ∏ i, m i (s i) := by
  cases isEmpty_or_nonempty ι
  · simp [piPremeasure]
  

Proof state:
case inr
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m : (i : ι) → OuterMeasure (α i)
s : (i : ι) → Set (α i)
h✝ : Nonempty ι
⊢ piPremeasure m (Set.pi univ s) = ∏ i : ι, ↑(m i) (s i)

Next tactic:
rcases (pi univ s).eq_empty_or_nonempty with h | h
theorem piPremeasure_pi' {s : ∀ i, Set (α i)} : piPremeasure m (pi univ s) = ∏ i, m i (s i) := by
  cases isEmpty_or_nonempty ι
  · simp [piPremeasure]
  rcases (pi univ s).eq_empty_or_nonempty with h | h
  · 

Proof state:
case inr.inl
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m : (i : ι) → OuterMeasure (α i)
s : (i : ι) → Set (α i)
h✝ : Nonempty ι
h : Set.pi univ s = ∅
⊢ piPremeasure m (Set.pi univ s) = ∏ i : ι, ↑(m i) (s i)

Next tactic:
rcases univ_pi_eq_empty_iff.mp h with ⟨i, hi⟩
theorem piPremeasure_pi' {s : ∀ i, Set (α i)} : piPremeasure m (pi univ s) = ∏ i, m i (s i) := by
  cases isEmpty_or_nonempty ι
  · simp [piPremeasure]
  rcases (pi univ s).eq_empty_or_nonempty with h | h
  · rcases univ_pi_eq_empty_iff.mp h with ⟨i, hi⟩
    

Proof state:
case inr.inl.intro
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m : (i : ι) → OuterMeasure (α i)
s : (i : ι) → Set (α i)
h✝ : Nonempty ι
h : Set.pi univ s = ∅
i : ι
hi : s i = ∅
⊢ piPremeasure m (Set.pi univ s) = ∏ i : ι, ↑(m i) (s i)

Next tactic:
have : ∃ i, m i (s i) = 0 := ⟨i, by simp [hi]⟩
theorem piPremeasure_pi' {s : ∀ i, Set (α i)} : piPremeasure m (pi univ s) = ∏ i, m i (s i) := by
  cases isEmpty_or_nonempty ι
  · simp [piPremeasure]
  rcases (pi univ s).eq_empty_or_nonempty with h | h
  · rcases univ_pi_eq_empty_iff.mp h with ⟨i, hi⟩
    have : ∃ i, m i (s i) = 0 := ⟨i, by 

Proof state:
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m : (i : ι) → OuterMeasure (α i)
s : (i : ι) → Set (α i)
h✝ : Nonempty ι
h : Set.pi univ s = ∅
i : ι
hi : s i = ∅
⊢ ↑(m i) (s i) = 0

Next tactic:
simp [hi]
theorem piPremeasure_pi' {s : ∀ i, Set (α i)} : piPremeasure m (pi univ s) = ∏ i, m i (s i) := by
  cases isEmpty_or_nonempty ι
  · simp [piPremeasure]
  rcases (pi univ s).eq_empty_or_nonempty with h | h
  · rcases univ_pi_eq_empty_iff.mp h with ⟨i, hi⟩
    have : ∃ i, m i (s i) = 0 := ⟨i, by simp [hi]⟩
    

Proof state:
case inr.inl.intro
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m : (i : ι) → OuterMeasure (α i)
s : (i : ι) → Set (α i)
h✝ : Nonempty ι
h : Set.pi univ s = ∅
i : ι
hi : s i = ∅
this : ∃ i, ↑(m i) (s i) = 0
⊢ piPremeasure m (Set.pi univ s) = ∏ i : ι, ↑(m i) (s i)

Next tactic:
simpa [h, Finset.card_univ, zero_pow (Fintype.card_pos_iff.mpr ‹_›), @eq_comm _ (0 : ℝ≥0∞),
      Finset.prod_eq_zero_iff, piPremeasure]
theorem piPremeasure_pi' {s : ∀ i, Set (α i)} : piPremeasure m (pi univ s) = ∏ i, m i (s i) := by
  cases isEmpty_or_nonempty ι
  · simp [piPremeasure]
  rcases (pi univ s).eq_empty_or_nonempty with h | h
  · rcases univ_pi_eq_empty_iff.mp h with ⟨i, hi⟩
    have : ∃ i, m i (s i) = 0 := ⟨i, by simp [hi]⟩
    simpa [h, Finset.card_univ, zero_pow (Fintype.card_pos_iff.mpr ‹_›), @eq_comm _ (0 : ℝ≥0∞),
      Finset.prod_eq_zero_iff, piPremeasure]
  · 

Proof state:
case inr.inr
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m : (i : ι) → OuterMeasure (α i)
s : (i : ι) → Set (α i)
h✝ : Nonempty ι
h : Set.Nonempty (Set.pi univ s)
⊢ piPremeasure m (Set.pi univ s) = ∏ i : ι, ↑(m i) (s i)

Next tactic:
simp [h, piPremeasure]
theorem piPremeasure_pi_eval {s : Set (∀ i, α i)} :
    piPremeasure m (pi univ fun i => eval i '' s) = piPremeasure m s := by
  

Proof state:
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m : (i : ι) → OuterMeasure (α i)
s : Set ((i : ι) → α i)
⊢ piPremeasure m (Set.pi univ fun i => eval i '' s) = piPremeasure m s

Next tactic:
simp only [eval, piPremeasure_pi']
theorem piPremeasure_pi_eval {s : Set (∀ i, α i)} :
    piPremeasure m (pi univ fun i => eval i '' s) = piPremeasure m s := by
  simp only [eval, piPremeasure_pi']; 

Proof state:
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m : (i : ι) → OuterMeasure (α i)
s : Set ((i : ι) → α i)
⊢ ∏ i : ι, ↑(m i) ((fun a => a i) '' s) = piPremeasure m s

Next tactic:
rfl
theorem pi_pi_le (m : ∀ i, OuterMeasure (α i)) (s : ∀ i, Set (α i)) :
    OuterMeasure.pi m (pi univ s) ≤ ∏ i, m i (s i) := by
  

Proof state:
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m✝ m : (i : ι) → OuterMeasure (α i)
s : (i : ι) → Set (α i)
⊢ ↑(OuterMeasure.pi m) (Set.pi univ s) ≤ ∏ i : ι, ↑(m i) (s i)

Next tactic:
rcases (pi univ s).eq_empty_or_nonempty with h | h
theorem pi_pi_le (m : ∀ i, OuterMeasure (α i)) (s : ∀ i, Set (α i)) :
    OuterMeasure.pi m (pi univ s) ≤ ∏ i, m i (s i) := by
  rcases (pi univ s).eq_empty_or_nonempty with h | h; 

Proof state:
case inl
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m✝ m : (i : ι) → OuterMeasure (α i)
s : (i : ι) → Set (α i)
h : Set.pi univ s = ∅
⊢ ↑(OuterMeasure.pi m) (Set.pi univ s) ≤ ∏ i : ι, ↑(m i) (s i)
case inr
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m✝ m : (i : ι) → OuterMeasure (α i)
s : (i : ι) → Set (α i)
h : Set.Nonempty (Set.pi univ s)
⊢ ↑(OuterMeasure.pi m) (Set.pi univ s) ≤ ∏ i : ι, ↑(m i) (s i)

Next tactic:
simp [h]
theorem pi_pi_le (m : ∀ i, OuterMeasure (α i)) (s : ∀ i, Set (α i)) :
    OuterMeasure.pi m (pi univ s) ≤ ∏ i, m i (s i) := by
  rcases (pi univ s).eq_empty_or_nonempty with h | h; simp [h]
  

Proof state:
case inr
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m✝ m : (i : ι) → OuterMeasure (α i)
s : (i : ι) → Set (α i)
h : Set.Nonempty (Set.pi univ s)
⊢ ↑(OuterMeasure.pi m) (Set.pi univ s) ≤ ∏ i : ι, ↑(m i) (s i)

Next tactic:
exact (boundedBy_le _).trans_eq (piPremeasure_pi h)
theorem le_pi {m : ∀ i, OuterMeasure (α i)} {n : OuterMeasure (∀ i, α i)} :
    n ≤ OuterMeasure.pi m ↔
      ∀ s : ∀ i, Set (α i), (pi univ s).Nonempty → n (pi univ s) ≤ ∏ i, m i (s i) := by
  

Proof state:
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m✝ m : (i : ι) → OuterMeasure (α i)
n : OuterMeasure ((i : ι) → α i)
⊢ n ≤ OuterMeasure.pi m ↔
    ∀ (s : (i : ι) → Set (α i)), Set.Nonempty (Set.pi univ s) → ↑n (Set.pi univ s) ≤ ∏ i : ι, ↑(m i) (s i)

Next tactic:
rw [OuterMeasure.pi, le_boundedBy']
theorem le_pi {m : ∀ i, OuterMeasure (α i)} {n : OuterMeasure (∀ i, α i)} :
    n ≤ OuterMeasure.pi m ↔
      ∀ s : ∀ i, Set (α i), (pi univ s).Nonempty → n (pi univ s) ≤ ∏ i, m i (s i) := by
  rw [OuterMeasure.pi, le_boundedBy']; 

Proof state:
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m✝ m : (i : ι) → OuterMeasure (α i)
n : OuterMeasure ((i : ι) → α i)
⊢ (∀ (s : Set ((i : ι) → α i)), Set.Nonempty s → ↑n s ≤ piPremeasure m s) ↔
    ∀ (s : (i : ι) → Set (α i)), Set.Nonempty (Set.pi univ s) → ↑n (Set.pi univ s) ≤ ∏ i : ι, ↑(m i) (s i)

Next tactic:
constructor
theorem le_pi {m : ∀ i, OuterMeasure (α i)} {n : OuterMeasure (∀ i, α i)} :
    n ≤ OuterMeasure.pi m ↔
      ∀ s : ∀ i, Set (α i), (pi univ s).Nonempty → n (pi univ s) ≤ ∏ i, m i (s i) := by
  rw [OuterMeasure.pi, le_boundedBy']; constructor
  · 

Proof state:
case mp
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m✝ m : (i : ι) → OuterMeasure (α i)
n : OuterMeasure ((i : ι) → α i)
⊢ (∀ (s : Set ((i : ι) → α i)), Set.Nonempty s → ↑n s ≤ piPremeasure m s) →
    ∀ (s : (i : ι) → Set (α i)), Set.Nonempty (Set.pi univ s) → ↑n (Set.pi univ s) ≤ ∏ i : ι, ↑(m i) (s i)

Next tactic:
intro h s hs
theorem le_pi {m : ∀ i, OuterMeasure (α i)} {n : OuterMeasure (∀ i, α i)} :
    n ≤ OuterMeasure.pi m ↔
      ∀ s : ∀ i, Set (α i), (pi univ s).Nonempty → n (pi univ s) ≤ ∏ i, m i (s i) := by
  rw [OuterMeasure.pi, le_boundedBy']; constructor
  · intro h s hs; 

Proof state:
case mp
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝ : Fintype ι
m✝ m : (i : ι) → OuterMeasure (α i)
n : OuterMeasure ((i : ι) → α i)
h : ∀ (s : Set ((i : ι) → α i)), Set.Nonempty s → ↑n s ≤ piPremeasure m s
s : (i : ι) → Set (α i)
hs : Set.Nonempty (Set.pi univ s)
⊢ ↑n (Set.pi univ s) ≤ ∏ i : ι, ↑(m i) (s i)

Next tactic:
refine' (h _ hs).trans_eq (piPremeasure_pi hs)