-- Mathlib/MeasureTheory/MeasurableSpace/Pi.lean
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)

Proof state:
case intro.a.h.intro.intro
ι : Type u_1
α : ι → Type u_2
inst✝ : Finite ι
C : (i : ι) → Set (Set (α i))
val✝ : Encodable ι
i : ι
s : Set (α 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 : univ.pi (update (fun i' => iUnion (t i')) i (⋃ x, s)) = univ.pi fun k => ⋃ j, update (fun i' => t i' j) i s k
⊢ MeasurableSet (⋃ x, univ.pi fun a => update (fun i' => t i' (x a)) i s a)

Tactic:
apply MeasurableSet.iUnion

Result:
case intro.a.h.intro.intro.h
ι : Type u_1
α : ι → Type u_2
inst✝ : Finite ι
C : (i : ι) → Set (Set (α i))
val✝ : Encodable ι
i : ι
s : Set (α 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 : univ.pi (update (fun i' => iUnion (t i')) i (⋃ x, s)) = univ.pi fun k => ⋃ j, update (fun i' => t i' j) i s k
⊢ ∀ (b : ι → ℕ), MeasurableSet (univ.pi fun a => update (fun i' => t i' (b a)) i s a)

Proof state:
case intro.a.h.intro.intro.h.ht.h
ι : Type u_1
α : ι → Type u_2
inst✝ : Finite ι
C : (i : ι) → Set (Set (α i))
val✝ : Encodable ι
i : ι
s : Set (α 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 : univ.pi (update (fun i' => iUnion (t i')) i (⋃ x, s)) = univ.pi fun k => ⋃ j, update (fun i' => t i' j) i s k
n : ι → ℕ
j : ι
a✝ : j ∈ univ
⊢ update (fun i' => t i' (n j)) i s j ∈ C j

Tactic:
by_cases h : j = i

Result:
case pos
ι : Type u_1
α : ι → Type u_2
inst✝ : Finite ι
C : (i : ι) → Set (Set (α i))
val✝ : Encodable ι
i : ι
s : Set (α 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 : univ.pi (update (fun i' => iUnion (t i')) i (⋃ x, s)) = univ.pi 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

case neg
ι : Type u_1
α : ι → Type u_2
inst✝ : Finite ι
C : (i : ι) → Set (Set (α i))
val✝ : Encodable ι
i : ι
s : Set (α 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 : univ.pi (update (fun i' => iUnion (t i')) i (⋃ x, s)) = univ.pi 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

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

Tactic:
apply MeasurableSet.iInter

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

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

Tactic:
apply @measurable_pi_apply _ _ (fun i => generateFrom (C i))

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

Proof state:
case intro.a.h.intro.intro.h
ι : Type u_1
α : ι → Type u_2
inst✝ : Finite ι
C : (i : ι) → Set (Set (α i))
val✝ : Encodable ι
i : ι
s : Set (α 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 : univ.pi (update (fun i' => iUnion (t i')) i (⋃ x, s)) = univ.pi fun k => ⋃ j, update (fun i' => t i' j) i s k
⊢ ∀ (b : ι → ℕ), MeasurableSet (univ.pi fun a => update (fun i' => t i' (b a)) i s a)

Tactic:
intro n

Result:
case intro.a.h.intro.intro.h
ι : Type u_1
α : ι → Type u_2
inst✝ : Finite ι
C : (i : ι) → Set (Set (α i))
val✝ : Encodable ι
i : ι
s : Set (α 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 : univ.pi (update (fun i' => iUnion (t i')) i (⋃ x, s)) = univ.pi fun k => ⋃ j, update (fun i' => t i' j) i s k
n : ι → ℕ
⊢ MeasurableSet (univ.pi fun a => update (fun i' => t i' (n a)) i s a)

Proof state:
case intro.a.h.intro.intro.h.ht
ι : Type u_1
α : ι → Type u_2
inst✝ : Finite ι
C : (i : ι) → Set (Set (α i))
val✝ : Encodable ι
i : ι
s : Set (α 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 : univ.pi (update (fun i' => iUnion (t i')) i (⋃ x, s)) = univ.pi fun k => ⋃ j, update (fun i' => t i' j) i s k
n : ι → ℕ
⊢ (univ.pi fun a => update (fun i' => t i' (n a)) i s a) ∈ univ.pi '' univ.pi C

Tactic:
apply mem_image_of_mem

Result:
case intro.a.h.intro.intro.h.ht.h
ι : Type u_1
α : ι → Type u_2
inst✝ : Finite ι
C : (i : ι) → Set (Set (α i))
val✝ : Encodable ι
i : ι
s : Set (α 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 : univ.pi (update (fun i' => iUnion (t i')) i (⋃ x, s)) = univ.pi fun k => ⋃ j, update (fun i' => t i' j) i s k
n : ι → ℕ
⊢ (fun a => update (fun i' => t i' (n a)) i s a) ∈ univ.pi C