l3lab/ntp-mathlib huggingface dataset:
/-- Split coequalizers are absolute: they are preserved by any functor. -/
@[simps]
def IsSplitCoequalizer.map {Z : C} {π : Y ⟶ Z} (q : IsSplitCoequalizer f g π) (F : C ⥤ D) :
    IsSplitCoequalizer (F.map f) (F.map g) (F.map π)
    where
  rightSection := F.map q.rightSection
  leftSection := F.map q.leftSection
  condition := by rw [← F.map_comp, q.condition, F.map_comp]
  rightSection_π := by rw [← F.map_comp, q.rightSection_π, F.map_id]
  leftSection_bottom := by rw [← F.map_comp, q.leftSection_bottom, F.map_id]
  leftSection_top := by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C ⥤ D
X Y : C
f g : X ⟶ Y
Z : C
π : Y ⟶ Z
q : IsSplitCoequalizer f g π
F : C ⥤ D
⊢ F.map q.leftSection ≫ F.map f = F.map π ≫ F.map q.rightSection

Next tactic:
rw [← F.map_comp, q.leftSection_top, F.map_comp]
/--
The cofork induced by a split coequalizer is a coequalizer, justifying the name. In some cases it
is more convenient to show a given cofork is a coequalizer by showing it is split.
-/
def IsSplitCoequalizer.isCoequalizer {Z : C} {h : Y ⟶ Z} (t : IsSplitCoequalizer f g h) :
    IsColimit t.asCofork :=
  Cofork.IsColimit.mk' _ fun s =>
    ⟨t.rightSection ≫ s.π, by
      

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C ⥤ D
X Y : C
f g : X ⟶ Y
Z : C
h : Y ⟶ Z
t : IsSplitCoequalizer f g h
s : Cofork f g
⊢ Cofork.π (asCofork t) ≫ t.rightSection ≫ Cofork.π s = Cofork.π s

Next tactic:
dsimp
/--
The cofork induced by a split coequalizer is a coequalizer, justifying the name. In some cases it
is more convenient to show a given cofork is a coequalizer by showing it is split.
-/
def IsSplitCoequalizer.isCoequalizer {Z : C} {h : Y ⟶ Z} (t : IsSplitCoequalizer f g h) :
    IsColimit t.asCofork :=
  Cofork.IsColimit.mk' _ fun s =>
    ⟨t.rightSection ≫ s.π, by
      dsimp
      

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C ⥤ D
X Y : C
f g : X ⟶ Y
Z : C
h : Y ⟶ Z
t : IsSplitCoequalizer f g h
s : Cofork f g
⊢ h ≫ t.rightSection ≫ Cofork.π s = Cofork.π s

Next tactic:
rw [← t.leftSection_top_assoc, s.condition, t.leftSection_bottom_assoc]
/--
The cofork induced by a split coequalizer is a coequalizer, justifying the name. In some cases it
is more convenient to show a given cofork is a coequalizer by showing it is split.
-/
def IsSplitCoequalizer.isCoequalizer {Z : C} {h : Y ⟶ Z} (t : IsSplitCoequalizer f g h) :
    IsColimit t.asCofork :=
  Cofork.IsColimit.mk' _ fun s =>
    ⟨t.rightSection ≫ s.π, by
      dsimp
      rw [← t.leftSection_top_assoc, s.condition, t.leftSection_bottom_assoc], fun hm => by
      

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C ⥤ D
X Y : C
f g : X ⟶ Y
Z : C
h : Y ⟶ Z
t : IsSplitCoequalizer f g h
s : Cofork f g
m✝ :
  ((Functor.const WalkingParallelPair).obj (asCofork t).pt).obj WalkingParallelPair.one ⟶
    ((Functor.const WalkingParallelPair).obj s.pt).obj WalkingParallelPair.one
hm : Cofork.π (asCofork t) ≫ m✝ = Cofork.π s
⊢ m✝ = t.rightSection ≫ Cofork.π s

Next tactic:
simp [← hm]
/-- Boxes formed by π-systems form a π-system. -/
theorem IsPiSystem.pi {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsPiSystem (C i)) :
    IsPiSystem (pi univ '' pi univ C) := by
  

Proof state:
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
C : (i : ι) → Set (Set (α i))
hC : ∀ (i : ι), IsPiSystem (C i)
⊢ IsPiSystem (Set.pi univ '' Set.pi univ C)

Next tactic:
rintro _ ⟨s₁, hs₁, rfl⟩ _ ⟨s₂, hs₂, rfl⟩ hst
/-- Boxes formed by π-systems form a π-system. -/
theorem IsPiSystem.pi {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsPiSystem (C i)) :
    IsPiSystem (pi univ '' pi univ C) := by
  rintro _ ⟨s₁, hs₁, rfl⟩ _ ⟨s₂, hs₂, rfl⟩ hst
  

Proof state:
case intro.intro.intro.intro
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
C : (i : ι) → Set (Set (α i))
hC : ∀ (i : ι), IsPiSystem (C i)
s₁ : (i : ι) → Set (α i)
hs₁ : s₁ ∈ Set.pi univ C
s₂ : (i : ι) → Set (α i)
hs₂ : s₂ ∈ Set.pi univ C
hst : Set.Nonempty (Set.pi univ s₁ ∩ Set.pi univ s₂)
⊢ Set.pi univ s₁ ∩ Set.pi univ s₂ ∈ Set.pi univ '' Set.pi univ C

Next tactic:
rw [← pi_inter_distrib] at hst ⊢
/-- Boxes formed by π-systems form a π-system. -/
theorem IsPiSystem.pi {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsPiSystem (C i)) :
    IsPiSystem (pi univ '' pi univ C) := by
  rintro _ ⟨s₁, hs₁, rfl⟩ _ ⟨s₂, hs₂, rfl⟩ hst
  rw [← pi_inter_distrib] at hst ⊢; 

Proof state:
case intro.intro.intro.intro
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
C : (i : ι) → Set (Set (α i))
hC : ∀ (i : ι), IsPiSystem (C i)
s₁ : (i : ι) → Set (α i)
hs₁ : s₁ ∈ Set.pi univ C
s₂ : (i : ι) → Set (α i)
hs₂ : s₂ ∈ Set.pi univ C
hst : Set.Nonempty (Set.pi univ fun i => s₁ i ∩ s₂ i)
⊢ (Set.pi univ fun i => s₁ i ∩ s₂ i) ∈ Set.pi univ '' Set.pi univ C

Next tactic:
rw [univ_pi_nonempty_iff] at hst
/-- Boxes formed by π-systems form a π-system. -/
theorem IsPiSystem.pi {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsPiSystem (C i)) :
    IsPiSystem (pi univ '' pi univ C) := by
  rintro _ ⟨s₁, hs₁, rfl⟩ _ ⟨s₂, hs₂, rfl⟩ hst
  rw [← pi_inter_distrib] at hst ⊢; rw [univ_pi_nonempty_iff] at hst
  

Proof state:
case intro.intro.intro.intro
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
C : (i : ι) → Set (Set (α i))
hC : ∀ (i : ι), IsPiSystem (C i)
s₁ : (i : ι) → Set (α i)
hs₁ : s₁ ∈ Set.pi univ C
s₂ : (i : ι) → Set (α i)
hs₂ : s₂ ∈ Set.pi univ C
hst : ∀ (i : ι), Set.Nonempty (s₁ i ∩ s₂ i)
⊢ (Set.pi univ fun i => s₁ i ∩ s₂ i) ∈ Set.pi univ '' Set.pi univ C

Next tactic:
exact mem_image_of_mem _ fun i _ => hC i _ (hs₁ i (mem_univ i)) _ (hs₂ i (mem_univ i)) (hst i)
/-- Boxes of countably spanning sets are countably spanning. -/
theorem IsCountablySpanning.pi {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) :
    IsCountablySpanning (pi univ '' pi univ C) := by
  

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

Next tactic:
choose s h1s h2s using hC
/-- Boxes of countably spanning sets are countably spanning. -/
theorem IsCountablySpanning.pi {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) :
    IsCountablySpanning (pi univ '' pi univ C) := by
  choose s h1s h2s using hC
  

Proof state:
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝¹ : Finite ι
inst✝ : Finite ι'
C : (i : ι) → Set (Set (α i))
s : (i : ι) → ℕ → Set (α i)
h1s : ∀ (i : ι) (n : ℕ), s i n ∈ C i
h2s : ∀ (i : ι), ⋃ n, s i n = univ
⊢ IsCountablySpanning (Set.pi univ '' Set.pi univ C)

Next tactic:
cases nonempty_encodable (ι → ℕ)
/-- Boxes of countably spanning sets are countably spanning. -/
theorem IsCountablySpanning.pi {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) :
    IsCountablySpanning (pi univ '' pi univ C) := by
  choose s h1s h2s using hC
  cases nonempty_encodable (ι → ℕ)
  

Proof state:
case intro
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝¹ : Finite ι
inst✝ : Finite ι'
C : (i : ι) → Set (Set (α i))
s : (i : ι) → ℕ → Set (α i)
h1s : ∀ (i : ι) (n : ℕ), s i n ∈ C i
h2s : ∀ (i : ι), ⋃ n, s i n = univ
val✝ : Encodable (ι → ℕ)
⊢ IsCountablySpanning (Set.pi univ '' Set.pi univ C)

Next tactic:
let e : ℕ → ι → ℕ := fun n => (@decode (ι → ℕ) _ n).iget
/-- Boxes of countably spanning sets are countably spanning. -/
theorem IsCountablySpanning.pi {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) :
    IsCountablySpanning (pi univ '' pi univ C) := by
  choose s h1s h2s using hC
  cases nonempty_encodable (ι → ℕ)
  let e : ℕ → ι → ℕ := fun n => (@decode (ι → ℕ) _ n).iget
  

Proof state:
case intro
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝¹ : Finite ι
inst✝ : Finite ι'
C : (i : ι) → Set (Set (α i))
s : (i : ι) → ℕ → Set (α i)
h1s : ∀ (i : ι) (n : ℕ), s i n ∈ C i
h2s : ∀ (i : ι), ⋃ n, s i n = univ
val✝ : Encodable (ι → ℕ)
e : ℕ → ι → ℕ := fun n => Option.iget (decode n)
⊢ IsCountablySpanning (Set.pi univ '' Set.pi univ C)

Next tactic:
refine' ⟨fun n => Set.pi univ fun i => s i (e n i), fun n =>
    mem_image_of_mem _ fun i _ => h1s i _, _⟩
/-- Boxes of countably spanning sets are countably spanning. -/
theorem IsCountablySpanning.pi {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) :
    IsCountablySpanning (pi univ '' pi univ C) := by
  choose s h1s h2s using hC
  cases nonempty_encodable (ι → ℕ)
  let e : ℕ → ι → ℕ := fun n => (@decode (ι → ℕ) _ n).iget
  refine' ⟨fun n => Set.pi univ fun i => s i (e n i), fun n =>
    mem_image_of_mem _ fun i _ => h1s i _, _⟩
  

Proof state:
case intro
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝¹ : Finite ι
inst✝ : Finite ι'
C : (i : ι) → Set (Set (α i))
s : (i : ι) → ℕ → Set (α i)
h1s : ∀ (i : ι) (n : ℕ), s i n ∈ C i
h2s : ∀ (i : ι), ⋃ n, s i n = univ
val✝ : Encodable (ι → ℕ)
e : ℕ → ι → ℕ := fun n => Option.iget (decode n)
⊢ ⋃ n, (fun n => Set.pi univ fun i => s i (e n i)) n = univ

Next tactic:
simp_rw [(surjective_decode_iget (ι → ℕ)).iUnion_comp fun x => Set.pi univ fun i => s i (x i),
    iUnion_univ_pi s, h2s, pi_univ]
/-- 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
  

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

Next tactic:
cases nonempty_encodable ι
/-- 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 ι
  

Proof state:
case 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 ι
⊢ MeasurableSpace.pi = generateFrom (Set.pi univ '' Set.pi univ C)

Next tactic:
apply le_antisymm
/-- 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
  · 

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 ι
⊢ MeasurableSpace.pi ≤ generateFrom (Set.pi univ '' Set.pi univ C)

Next tactic:
refine' iSup_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 _; 

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 ι
⊢ ∀ (i : ι),
    MeasurableSpace.comap (fun b => b i) ((fun i => generateFrom (C i)) i) ≤ generateFrom (Set.pi univ '' Set.pi univ C)

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; 

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 ι
i : ι
⊢ MeasurableSpace.comap (fun b => b i) ((fun i => generateFrom (C i)) i) ≤ generateFrom (Set.pi univ '' Set.pi univ C)

Next tactic:
rw [comap_generateFrom]
/-- 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]
    

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 ι
i : ι
⊢ generateFrom ((preimage fun b => b i) '' C i) ≤ generateFrom (Set.pi univ '' Set.pi univ C)

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; 

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 ι
i : ι
⊢ ∀ t ∈ (preimage fun b => b i) '' C i, 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⟩; 

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 ι
i : ι
s : Set ((fun i => α i) i)
hs : s ∈ C i
⊢ MeasurableSet ((fun b => b i) ⁻¹' s)

Next tactic:
dsimp
/-- 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
    

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 ι
i : ι
s : Set ((fun i => α i) i)
hs : s ∈ C i
⊢ MeasurableSet ((fun b => b i) ⁻¹' s)

Next tactic:
choose t h1t h2t using hC
/-- 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
    

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))
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
⊢ MeasurableSet ((fun b => b i) ⁻¹' s)

Next tactic:
simp_rw [eval_preimage, ← h2t]
/-- 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]
    

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))
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
⊢ MeasurableSet (Set.pi univ (update (fun i => ⋃ n, t i n) i s))

Next tactic:
rw [← @iUnion_const _ ℕ _ s]
/-- 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]
    

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))
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
⊢ MeasurableSet (Set.pi univ (update (fun i => ⋃ n, t i n) i (⋃ x, s)))

Next tactic:
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]
/-- 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
      

Proof state:
ι : 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
⊢ 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

Next tactic:
ext
/-- 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; 

Proof state:
case h
ι : 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
x✝ : (i : ι) → α i
⊢ x✝ ∈ Set.pi univ (update (fun i' => iUnion (t i')) i (⋃ x, s)) ↔
    x✝ ∈ Set.pi univ fun k => ⋃ j, update (fun i' => t i' j) i s k

Next tactic:
simp_rw [mem_univ_pi]
/-- 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]; 

Proof state:
case h
ι : 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
x✝ : (i : ι) → α i
⊢ (∀ (i_1 : ι), x✝ i_1 ∈ update (fun i' => iUnion (t i')) i (⋃ x, s) i_1) ↔
    ∀ (i_1 : ι), x✝ i_1 ∈ ⋃ j, update (fun i' => t i' j) i s i_1

Next tactic:
apply forall_congr'
/-- 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'; 

Proof state:
case h.h
ι : 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
x✝ : (i : ι) → α i
⊢ ∀ (a : ι), x✝ a ∈ update (fun i' => iUnion (t i')) i (⋃ x, s) a ↔ x✝ a ∈ ⋃ j, update (fun i' => t i' j) i s a

Next tactic:
intro i'