l3lab/ntp-mathlib huggingface dataset:
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  

Proof state:
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
⊢ IsOpen s ↔ ∀ f ∈ s, ∃ I u, (∀ a ∈ I, IsOpen (u a) ∧ f a ∈ u a) ∧ Set.pi (↑I) u ⊆ s

Next tactic:
rw [isOpen_iff_nhds]
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  

Proof state:
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
⊢ (∀ a ∈ s, 𝓝 a ≤ 𝓟 s) ↔ ∀ f ∈ s, ∃ I u, (∀ a ∈ I, IsOpen (u a) ∧ f a ∈ u a) ∧ Set.pi (↑I) u ⊆ s

Next tactic:
simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  

Proof state:
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
⊢ (∀ a ∈ s, ∃ I t, (∀ (i : ι), ∃ t_1 ⊆ t i, IsOpen t_1 ∧ a i ∈ t_1) ∧ Set.pi (↑I) t ⊆ s) ↔
    ∀ f ∈ s, ∃ I u, (∀ a ∈ I, IsOpen (u a) ∧ f a ∈ u a) ∧ Set.pi (↑I) u ⊆ s

Next tactic:
refine ball_congr fun a _ => ⟨?_, ?_⟩
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  refine ball_congr fun a _ => ⟨?_, ?_⟩
  · 

Proof state:
case refine_1
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
a : (a : ι) → π a
x✝ : a ∈ s
⊢ (∃ I t, (∀ (i : ι), ∃ t_1 ⊆ t i, IsOpen t_1 ∧ a i ∈ t_1) ∧ Set.pi (↑I) t ⊆ s) →
    ∃ I u, (∀ a_2 ∈ I, IsOpen (u a_2) ∧ a a_2 ∈ u a_2) ∧ Set.pi (↑I) u ⊆ s

Next tactic:
rintro ⟨I, t, ⟨h1, h2⟩⟩
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  refine ball_congr fun a _ => ⟨?_, ?_⟩
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    

Proof state:
case refine_1.intro.intro.intro
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
a : (a : ι) → π a
x✝ : a ∈ s
I : Finset ι
t : (i : ι) → Set (π i)
h1 : ∀ (i : ι), ∃ t_1 ⊆ t i, IsOpen t_1 ∧ a i ∈ t_1
h2 : Set.pi (↑I) t ⊆ s
⊢ ∃ I u, (∀ a_1 ∈ I, IsOpen (u a_1) ∧ a a_1 ∈ u a_1) ∧ Set.pi (↑I) u ⊆ s

Next tactic:
refine ⟨I, fun a => eval a '' (I : Set ι).pi fun a => (h1 a).choose, fun i hi => ?_, ?_⟩
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  refine ball_congr fun a _ => ⟨?_, ?_⟩
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => eval a '' (I : Set ι).pi fun a => (h1 a).choose, fun i hi => ?_, ?_⟩
    · 

Proof state:
case refine_1.intro.intro.intro.refine_1
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
a : (a : ι) → π a
x✝ : a ∈ s
I : Finset ι
t : (i : ι) → Set (π i)
h1 : ∀ (i : ι), ∃ t_1 ⊆ t i, IsOpen t_1 ∧ a i ∈ t_1
h2 : Set.pi (↑I) t ⊆ s
i : ι
hi : i ∈ I
⊢ IsOpen ((fun a_1 => eval a_1 '' Set.pi ↑I fun a_2 => Exists.choose (_ : ∃ t_1 ⊆ t a_2, IsOpen t_1 ∧ a a_2 ∈ t_1)) i) ∧
    a i ∈ (fun a_1 => eval a_1 '' Set.pi ↑I fun a_2 => Exists.choose (_ : ∃ t_1 ⊆ t a_2, IsOpen t_1 ∧ a a_2 ∈ t_1)) i

Next tactic:
simp_rw [Set.eval_image_pi (Finset.mem_coe.mpr hi)
          (pi_nonempty_iff.mpr fun i => ⟨_, fun _ => (h1 i).choose_spec.2.2⟩)]
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  refine ball_congr fun a _ => ⟨?_, ?_⟩
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => eval a '' (I : Set ι).pi fun a => (h1 a).choose, fun i hi => ?_, ?_⟩
    · simp_rw [Set.eval_image_pi (Finset.mem_coe.mpr hi)
          (pi_nonempty_iff.mpr fun i => ⟨_, fun _ => (h1 i).choose_spec.2.2⟩)]
      

Proof state:
case refine_1.intro.intro.intro.refine_1
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
a : (a : ι) → π a
x✝ : a ∈ s
I : Finset ι
t : (i : ι) → Set (π i)
h1 : ∀ (i : ι), ∃ t_1 ⊆ t i, IsOpen t_1 ∧ a i ∈ t_1
h2 : Set.pi (↑I) t ⊆ s
i : ι
hi : i ∈ I
⊢ IsOpen (Exists.choose (_ : ∃ t_1 ⊆ t i, IsOpen t_1 ∧ a i ∈ t_1)) ∧
    a i ∈ Exists.choose (_ : ∃ t_1 ⊆ t i, IsOpen t_1 ∧ a i ∈ t_1)

Next tactic:
exact (h1 i).choose_spec.2
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  refine ball_congr fun a _ => ⟨?_, ?_⟩
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => eval a '' (I : Set ι).pi fun a => (h1 a).choose, fun i hi => ?_, ?_⟩
    · simp_rw [Set.eval_image_pi (Finset.mem_coe.mpr hi)
          (pi_nonempty_iff.mpr fun i => ⟨_, fun _ => (h1 i).choose_spec.2.2⟩)]
      exact (h1 i).choose_spec.2
    · 

Proof state:
case refine_1.intro.intro.intro.refine_2
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
a : (a : ι) → π a
x✝ : a ∈ s
I : Finset ι
t : (i : ι) → Set (π i)
h1 : ∀ (i : ι), ∃ t_1 ⊆ t i, IsOpen t_1 ∧ a i ∈ t_1
h2 : Set.pi (↑I) t ⊆ s
⊢ (Set.pi ↑I fun a_1 => eval a_1 '' Set.pi ↑I fun a_2 => Exists.choose (_ : ∃ t_1 ⊆ t a_2, IsOpen t_1 ∧ a a_2 ∈ t_1)) ⊆
    s

Next tactic:
exact Subset.trans
        (Set.pi_mono fun i hi => (Set.eval_image_pi_subset hi).trans (h1 i).choose_spec.1) h2
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  refine ball_congr fun a _ => ⟨?_, ?_⟩
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => eval a '' (I : Set ι).pi fun a => (h1 a).choose, fun i hi => ?_, ?_⟩
    · simp_rw [Set.eval_image_pi (Finset.mem_coe.mpr hi)
          (pi_nonempty_iff.mpr fun i => ⟨_, fun _ => (h1 i).choose_spec.2.2⟩)]
      exact (h1 i).choose_spec.2
    · exact Subset.trans
        (Set.pi_mono fun i hi => (Set.eval_image_pi_subset hi).trans (h1 i).choose_spec.1) h2
  · 

Proof state:
case refine_2
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
a : (a : ι) → π a
x✝ : a ∈ s
⊢ (∃ I u, (∀ a_1 ∈ I, IsOpen (u a_1) ∧ a a_1 ∈ u a_1) ∧ Set.pi (↑I) u ⊆ s) →
    ∃ I t, (∀ (i : ι), ∃ t_1 ⊆ t i, IsOpen t_1 ∧ a i ∈ t_1) ∧ Set.pi (↑I) t ⊆ s

Next tactic:
rintro ⟨I, t, ⟨h1, h2⟩⟩
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  refine ball_congr fun a _ => ⟨?_, ?_⟩
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => eval a '' (I : Set ι).pi fun a => (h1 a).choose, fun i hi => ?_, ?_⟩
    · simp_rw [Set.eval_image_pi (Finset.mem_coe.mpr hi)
          (pi_nonempty_iff.mpr fun i => ⟨_, fun _ => (h1 i).choose_spec.2.2⟩)]
      exact (h1 i).choose_spec.2
    · exact Subset.trans
        (Set.pi_mono fun i hi => (Set.eval_image_pi_subset hi).trans (h1 i).choose_spec.1) h2
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    

Proof state:
case refine_2.intro.intro.intro
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
a : (a : ι) → π a
x✝ : a ∈ s
I : Finset ι
t : (a : ι) → Set (π a)
h1 : ∀ a_1 ∈ I, IsOpen (t a_1) ∧ a a_1 ∈ t a_1
h2 : Set.pi (↑I) t ⊆ s
⊢ ∃ I t, (∀ (i : ι), ∃ t_1 ⊆ t i, IsOpen t_1 ∧ a i ∈ t_1) ∧ Set.pi (↑I) t ⊆ s

Next tactic:
refine ⟨I, fun a => ite (a ∈ I) (t a) Set.univ, fun i => ?_, ?_⟩
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  refine ball_congr fun a _ => ⟨?_, ?_⟩
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => eval a '' (I : Set ι).pi fun a => (h1 a).choose, fun i hi => ?_, ?_⟩
    · simp_rw [Set.eval_image_pi (Finset.mem_coe.mpr hi)
          (pi_nonempty_iff.mpr fun i => ⟨_, fun _ => (h1 i).choose_spec.2.2⟩)]
      exact (h1 i).choose_spec.2
    · exact Subset.trans
        (Set.pi_mono fun i hi => (Set.eval_image_pi_subset hi).trans (h1 i).choose_spec.1) h2
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => ite (a ∈ I) (t a) Set.univ, fun i => ?_, ?_⟩
    · 

Proof state:
case refine_2.intro.intro.intro.refine_1
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
a : (a : ι) → π a
x✝ : a ∈ s
I : Finset ι
t : (a : ι) → Set (π a)
h1 : ∀ a_1 ∈ I, IsOpen (t a_1) ∧ a a_1 ∈ t a_1
h2 : Set.pi (↑I) t ⊆ s
i : ι
⊢ ∃ t_1 ⊆ (fun a => if a ∈ I then t a else univ) i, IsOpen t_1 ∧ a i ∈ t_1

Next tactic:
by_cases hi : i ∈ I
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  refine ball_congr fun a _ => ⟨?_, ?_⟩
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => eval a '' (I : Set ι).pi fun a => (h1 a).choose, fun i hi => ?_, ?_⟩
    · simp_rw [Set.eval_image_pi (Finset.mem_coe.mpr hi)
          (pi_nonempty_iff.mpr fun i => ⟨_, fun _ => (h1 i).choose_spec.2.2⟩)]
      exact (h1 i).choose_spec.2
    · exact Subset.trans
        (Set.pi_mono fun i hi => (Set.eval_image_pi_subset hi).trans (h1 i).choose_spec.1) h2
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => ite (a ∈ I) (t a) Set.univ, fun i => ?_, ?_⟩
    · by_cases hi : i ∈ I
      · 

Proof state:
case pos
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
a : (a : ι) → π a
x✝ : a ∈ s
I : Finset ι
t : (a : ι) → Set (π a)
h1 : ∀ a_1 ∈ I, IsOpen (t a_1) ∧ a a_1 ∈ t a_1
h2 : Set.pi (↑I) t ⊆ s
i : ι
hi : i ∈ I
⊢ ∃ t_1 ⊆ (fun a => if a ∈ I then t a else univ) i, IsOpen t_1 ∧ a i ∈ t_1

Next tactic:
use t i
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  refine ball_congr fun a _ => ⟨?_, ?_⟩
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => eval a '' (I : Set ι).pi fun a => (h1 a).choose, fun i hi => ?_, ?_⟩
    · simp_rw [Set.eval_image_pi (Finset.mem_coe.mpr hi)
          (pi_nonempty_iff.mpr fun i => ⟨_, fun _ => (h1 i).choose_spec.2.2⟩)]
      exact (h1 i).choose_spec.2
    · exact Subset.trans
        (Set.pi_mono fun i hi => (Set.eval_image_pi_subset hi).trans (h1 i).choose_spec.1) h2
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => ite (a ∈ I) (t a) Set.univ, fun i => ?_, ?_⟩
    · by_cases hi : i ∈ I
      · use t i
        

Proof state:
case h
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
a : (a : ι) → π a
x✝ : a ∈ s
I : Finset ι
t : (a : ι) → Set (π a)
h1 : ∀ a_1 ∈ I, IsOpen (t a_1) ∧ a a_1 ∈ t a_1
h2 : Set.pi (↑I) t ⊆ s
i : ι
hi : i ∈ I
⊢ t i ⊆ (fun a => if a ∈ I then t a else univ) i ∧ IsOpen (t i) ∧ a i ∈ t i

Next tactic:
simp_rw [if_pos hi]
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  refine ball_congr fun a _ => ⟨?_, ?_⟩
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => eval a '' (I : Set ι).pi fun a => (h1 a).choose, fun i hi => ?_, ?_⟩
    · simp_rw [Set.eval_image_pi (Finset.mem_coe.mpr hi)
          (pi_nonempty_iff.mpr fun i => ⟨_, fun _ => (h1 i).choose_spec.2.2⟩)]
      exact (h1 i).choose_spec.2
    · exact Subset.trans
        (Set.pi_mono fun i hi => (Set.eval_image_pi_subset hi).trans (h1 i).choose_spec.1) h2
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => ite (a ∈ I) (t a) Set.univ, fun i => ?_, ?_⟩
    · by_cases hi : i ∈ I
      · use t i
        simp_rw [if_pos hi]
        

Proof state:
case h
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
a : (a : ι) → π a
x✝ : a ∈ s
I : Finset ι
t : (a : ι) → Set (π a)
h1 : ∀ a_1 ∈ I, IsOpen (t a_1) ∧ a a_1 ∈ t a_1
h2 : Set.pi (↑I) t ⊆ s
i : ι
hi : i ∈ I
⊢ t i ⊆ t i ∧ IsOpen (t i) ∧ a i ∈ t i

Next tactic:
exact ⟨Subset.rfl, (h1 i) hi⟩
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  refine ball_congr fun a _ => ⟨?_, ?_⟩
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => eval a '' (I : Set ι).pi fun a => (h1 a).choose, fun i hi => ?_, ?_⟩
    · simp_rw [Set.eval_image_pi (Finset.mem_coe.mpr hi)
          (pi_nonempty_iff.mpr fun i => ⟨_, fun _ => (h1 i).choose_spec.2.2⟩)]
      exact (h1 i).choose_spec.2
    · exact Subset.trans
        (Set.pi_mono fun i hi => (Set.eval_image_pi_subset hi).trans (h1 i).choose_spec.1) h2
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => ite (a ∈ I) (t a) Set.univ, fun i => ?_, ?_⟩
    · by_cases hi : i ∈ I
      · use t i
        simp_rw [if_pos hi]
        exact ⟨Subset.rfl, (h1 i) hi⟩
      · 

Proof state:
case neg
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
a : (a : ι) → π a
x✝ : a ∈ s
I : Finset ι
t : (a : ι) → Set (π a)
h1 : ∀ a_1 ∈ I, IsOpen (t a_1) ∧ a a_1 ∈ t a_1
h2 : Set.pi (↑I) t ⊆ s
i : ι
hi : i ∉ I
⊢ ∃ t_1 ⊆ (fun a => if a ∈ I then t a else univ) i, IsOpen t_1 ∧ a i ∈ t_1

Next tactic:
use Set.univ
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  refine ball_congr fun a _ => ⟨?_, ?_⟩
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => eval a '' (I : Set ι).pi fun a => (h1 a).choose, fun i hi => ?_, ?_⟩
    · simp_rw [Set.eval_image_pi (Finset.mem_coe.mpr hi)
          (pi_nonempty_iff.mpr fun i => ⟨_, fun _ => (h1 i).choose_spec.2.2⟩)]
      exact (h1 i).choose_spec.2
    · exact Subset.trans
        (Set.pi_mono fun i hi => (Set.eval_image_pi_subset hi).trans (h1 i).choose_spec.1) h2
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => ite (a ∈ I) (t a) Set.univ, fun i => ?_, ?_⟩
    · by_cases hi : i ∈ I
      · use t i
        simp_rw [if_pos hi]
        exact ⟨Subset.rfl, (h1 i) hi⟩
      · use Set.univ
        

Proof state:
case h
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
a : (a : ι) → π a
x✝ : a ∈ s
I : Finset ι
t : (a : ι) → Set (π a)
h1 : ∀ a_1 ∈ I, IsOpen (t a_1) ∧ a a_1 ∈ t a_1
h2 : Set.pi (↑I) t ⊆ s
i : ι
hi : i ∉ I
⊢ univ ⊆ (fun a => if a ∈ I then t a else univ) i ∧ IsOpen univ ∧ a i ∈ univ

Next tactic:
simp_rw [if_neg hi]
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  refine ball_congr fun a _ => ⟨?_, ?_⟩
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => eval a '' (I : Set ι).pi fun a => (h1 a).choose, fun i hi => ?_, ?_⟩
    · simp_rw [Set.eval_image_pi (Finset.mem_coe.mpr hi)
          (pi_nonempty_iff.mpr fun i => ⟨_, fun _ => (h1 i).choose_spec.2.2⟩)]
      exact (h1 i).choose_spec.2
    · exact Subset.trans
        (Set.pi_mono fun i hi => (Set.eval_image_pi_subset hi).trans (h1 i).choose_spec.1) h2
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => ite (a ∈ I) (t a) Set.univ, fun i => ?_, ?_⟩
    · by_cases hi : i ∈ I
      · use t i
        simp_rw [if_pos hi]
        exact ⟨Subset.rfl, (h1 i) hi⟩
      · use Set.univ
        simp_rw [if_neg hi]
        

Proof state:
case h
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
a : (a : ι) → π a
x✝ : a ∈ s
I : Finset ι
t : (a : ι) → Set (π a)
h1 : ∀ a_1 ∈ I, IsOpen (t a_1) ∧ a a_1 ∈ t a_1
h2 : Set.pi (↑I) t ⊆ s
i : ι
hi : i ∉ I
⊢ univ ⊆ univ ∧ IsOpen univ ∧ a i ∈ univ

Next tactic:
exact ⟨Subset.rfl, isOpen_univ, mem_univ _⟩
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  refine ball_congr fun a _ => ⟨?_, ?_⟩
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => eval a '' (I : Set ι).pi fun a => (h1 a).choose, fun i hi => ?_, ?_⟩
    · simp_rw [Set.eval_image_pi (Finset.mem_coe.mpr hi)
          (pi_nonempty_iff.mpr fun i => ⟨_, fun _ => (h1 i).choose_spec.2.2⟩)]
      exact (h1 i).choose_spec.2
    · exact Subset.trans
        (Set.pi_mono fun i hi => (Set.eval_image_pi_subset hi).trans (h1 i).choose_spec.1) h2
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => ite (a ∈ I) (t a) Set.univ, fun i => ?_, ?_⟩
    · by_cases hi : i ∈ I
      · use t i
        simp_rw [if_pos hi]
        exact ⟨Subset.rfl, (h1 i) hi⟩
      · use Set.univ
        simp_rw [if_neg hi]
        exact ⟨Subset.rfl, isOpen_univ, mem_univ _⟩
    · 

Proof state:
case refine_2.intro.intro.intro.refine_2
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
a : (a : ι) → π a
x✝ : a ∈ s
I : Finset ι
t : (a : ι) → Set (π a)
h1 : ∀ a_1 ∈ I, IsOpen (t a_1) ∧ a a_1 ∈ t a_1
h2 : Set.pi (↑I) t ⊆ s
⊢ (Set.pi ↑I fun a => if a ∈ I then t a else univ) ⊆ s

Next tactic:
rw [← Set.univ_pi_ite]
theorem isOpen_pi_iff {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ (I : Finset ι) (u : ∀ a, Set (π a)),
        (∀ a, a ∈ I → IsOpen (u a) ∧ f a ∈ u a) ∧ (I : Set ι).pi u ⊆ s := by
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  refine ball_congr fun a _ => ⟨?_, ?_⟩
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => eval a '' (I : Set ι).pi fun a => (h1 a).choose, fun i hi => ?_, ?_⟩
    · simp_rw [Set.eval_image_pi (Finset.mem_coe.mpr hi)
          (pi_nonempty_iff.mpr fun i => ⟨_, fun _ => (h1 i).choose_spec.2.2⟩)]
      exact (h1 i).choose_spec.2
    · exact Subset.trans
        (Set.pi_mono fun i hi => (Set.eval_image_pi_subset hi).trans (h1 i).choose_spec.1) h2
  · rintro ⟨I, t, ⟨h1, h2⟩⟩
    refine ⟨I, fun a => ite (a ∈ I) (t a) Set.univ, fun i => ?_, ?_⟩
    · by_cases hi : i ∈ I
      · use t i
        simp_rw [if_pos hi]
        exact ⟨Subset.rfl, (h1 i) hi⟩
      · use Set.univ
        simp_rw [if_neg hi]
        exact ⟨Subset.rfl, isOpen_univ, mem_univ _⟩
    · rw [← Set.univ_pi_ite]
      

Proof state:
case refine_2.intro.intro.intro.refine_2
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
s : Set ((a : ι) → π a)
a : (a : ι) → π a
x✝ : a ∈ s
I : Finset ι
t : (a : ι) → Set (π a)
h1 : ∀ a_1 ∈ I, IsOpen (t a_1) ∧ a a_1 ∈ t a_1
h2 : Set.pi (↑I) t ⊆ s
⊢ (Set.pi univ fun i => if i ∈ ↑I then if i ∈ I then t i else univ else univ) ⊆ s

Next tactic:
simp only [← ite_and, ← Finset.mem_coe, and_self_iff, Set.univ_pi_ite, h2]
theorem isOpen_pi_iff' [Finite ι] {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ u : ∀ a, Set (π a), (∀ a, IsOpen (u a) ∧ f a ∈ u a) ∧ Set.univ.pi u ⊆ s := by
  

Proof state:
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝¹ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
inst✝ : Finite ι
s : Set ((a : ι) → π a)
⊢ IsOpen s ↔ ∀ f ∈ s, ∃ u, (∀ (a : ι), IsOpen (u a) ∧ f a ∈ u a) ∧ Set.pi univ u ⊆ s

Next tactic:
cases nonempty_fintype ι
theorem isOpen_pi_iff' [Finite ι] {s : Set (∀ a, π a)} :
    IsOpen s ↔
      ∀ f, f ∈ s → ∃ u : ∀ a, Set (π a), (∀ a, IsOpen (u a) ∧ f a ∈ u a) ∧ Set.univ.pi u ⊆ s := by
  cases nonempty_fintype ι
  

Proof state:
case intro
α : Type u
β : Type v
γ : Type u_1
δ : Type u_2
ε : Type u_3
ζ : Type u_4
ι : Type u_5
π : ι → Type u_6
κ : Type u_7
inst✝¹ : TopologicalSpace α
T : (i : ι) → TopologicalSpace (π i)
f : α → (i : ι) → π i
inst✝ : Finite ι
s : Set ((a : ι) → π a)
val✝ : Fintype ι
⊢ IsOpen s ↔ ∀ f ∈ s, ∃ u, (∀ (a : ι), IsOpen (u a) ∧ f a ∈ u a) ∧ Set.pi univ u ⊆ s

Next tactic:
rw [isOpen_iff_nhds]