l3lab/ntp-mathlib huggingface dataset:
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 ι
  rw [isOpen_iff_nhds]
  

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 ι
⊢ (∀ a ∈ s, 𝓝 a ≤ 𝓟 s) ↔ ∀ f ∈ s, ∃ u, (∀ (a : ι), IsOpen (u a) ∧ f a ∈ u a) ∧ Set.pi univ u ⊆ s

Next tactic:
simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
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 ι
  rw [isOpen_iff_nhds]
  simp_rw [le_principal_iff, nhds_pi, Filter.mem_pi', mem_nhds_iff]
  

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 ι
⊢ (∀ a ∈ s, ∃ I t, (∀ (i : ι), ∃ t_1 ⊆ t i, IsOpen t_1 ∧ a i ∈ t_1) ∧ Set.pi (↑I) t ⊆ s) ↔
    ∀ f ∈ s, ∃ u, (∀ (a : ι), IsOpen (u a) ∧ f a ∈ u a) ∧ Set.pi univ u ⊆ s

Next tactic:
refine ball_congr fun a _ => ⟨?_, ?_⟩
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 ι
  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 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
inst✝ : Finite ι
s : Set ((a : ι) → π a)
val✝ : Fintype ι
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) →
    ∃ u, (∀ (a_2 : ι), IsOpen (u a_2) ∧ a a_2 ∈ u a_2) ∧ Set.pi univ u ⊆ s

Next tactic:
rintro ⟨I, t, ⟨h1, 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
  cases nonempty_fintype ι
  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 intro.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
inst✝ : Finite ι
s : Set ((a : ι) → π a)
val✝ : Fintype ι
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
⊢ ∃ u, (∀ (a_1 : ι), IsOpen (u a_1) ∧ a a_1 ∈ u a_1) ∧ Set.pi univ u ⊆ s

Next tactic:
refine
      ⟨fun i => (h1 i).choose,
        ⟨fun i => (h1 i).choose_spec.2,
          (Set.pi_mono fun i _ => (h1 i).choose_spec.1).trans (Subset.trans ?_ 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
  cases nonempty_fintype ι
  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
      ⟨fun i => (h1 i).choose,
        ⟨fun i => (h1 i).choose_spec.2,
          (Set.pi_mono fun i _ => (h1 i).choose_spec.1).trans (Subset.trans ?_ h2)⟩⟩
    

Proof state:
case intro.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
inst✝ : Finite ι
s : Set ((a : ι) → π a)
val✝ : Fintype ι
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 univ fun i => t i) ⊆ Set.pi (↑I) t

Next tactic:
rw [← Set.pi_inter_compl (I : Set ι)]
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 ι
  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
      ⟨fun i => (h1 i).choose,
        ⟨fun i => (h1 i).choose_spec.2,
          (Set.pi_mono fun i _ => (h1 i).choose_spec.1).trans (Subset.trans ?_ h2)⟩⟩
    rw [← Set.pi_inter_compl (I : Set ι)]
    

Proof state:
case intro.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
inst✝ : Finite ι
s : Set ((a : ι) → π a)
val✝ : Fintype ι
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 i => t i) ∩ Set.pi (↑I)ᶜ fun i => t i) ⊆ Set.pi (↑I) t

Next tactic:
exact inter_subset_left _ _
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 ι
  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
      ⟨fun i => (h1 i).choose,
        ⟨fun i => (h1 i).choose_spec.2,
          (Set.pi_mono fun i _ => (h1 i).choose_spec.1).trans (Subset.trans ?_ h2)⟩⟩
    rw [← Set.pi_inter_compl (I : Set ι)]
    exact inter_subset_left _ _
  · 

Proof state:
case 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
inst✝ : Finite ι
s : Set ((a : ι) → π a)
val✝ : Fintype ι
a : (a : ι) → π a
x✝ : a ∈ s
⊢ (∃ u, (∀ (a_1 : ι), IsOpen (u a_1) ∧ a a_1 ∈ u a_1) ∧ Set.pi univ u ⊆ s) →
    ∃ I t, (∀ (i : ι), ∃ t_1 ⊆ t i, IsOpen t_1 ∧ a i ∈ t_1) ∧ Set.pi (↑I) t ⊆ s

Next tactic:
exact fun ⟨u, ⟨h1, _⟩⟩ =>
      ⟨Finset.univ, u, ⟨fun i => ⟨u i, ⟨rfl.subset, h1 i⟩⟩, by rwa [Finset.coe_univ]⟩⟩
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 ι
  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
      ⟨fun i => (h1 i).choose,
        ⟨fun i => (h1 i).choose_spec.2,
          (Set.pi_mono fun i _ => (h1 i).choose_spec.1).trans (Subset.trans ?_ h2)⟩⟩
    rw [← Set.pi_inter_compl (I : Set ι)]
    exact inter_subset_left _ _
  · exact fun ⟨u, ⟨h1, _⟩⟩ =>
      ⟨Finset.univ, u, ⟨fun i => ⟨u i, ⟨rfl.subset, h1 i⟩⟩, 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)
val✝ : Fintype ι
a : (a : ι) → π a
x✝¹ : a ∈ s
x✝ : ∃ u, (∀ (a_1 : ι), IsOpen (u a_1) ∧ a a_1 ∈ u a_1) ∧ Set.pi univ u ⊆ s
u : (a : ι) → Set (π a)
h1 : ∀ (a_1 : ι), IsOpen (u a_1) ∧ a a_1 ∈ u a_1
right✝ : Set.pi univ u ⊆ s
⊢ Set.pi (↑Finset.univ) u ⊆ s

Next tactic:
rwa [Finset.coe_univ]
theorem isClosed_set_pi {i : Set ι} {s : ∀ a, Set (π a)} (hs : ∀ a ∈ i, IsClosed (s a)) :
    IsClosed (pi i 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
i : Set ι
s : (a : ι) → Set (π a)
hs : ∀ a ∈ i, IsClosed (s a)
⊢ IsClosed (Set.pi i s)

Next tactic:
rw [pi_def]
theorem isClosed_set_pi {i : Set ι} {s : ∀ a, Set (π a)} (hs : ∀ a ∈ i, IsClosed (s a)) :
    IsClosed (pi i s) := by
  rw [pi_def]; 

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
i : Set ι
s : (a : ι) → Set (π a)
hs : ∀ a ∈ i, IsClosed (s a)
⊢ IsClosed (⋂ a ∈ i, eval a ⁻¹' s a)

Next tactic:
exact isClosed_biInter fun a ha => (hs _ ha).preimage (continuous_apply _)
theorem mem_nhds_of_pi_mem_nhds {I : Set ι} {s : ∀ i, Set (π i)} (a : ∀ i, π i) (hs : I.pi s ∈ 𝓝 a)
    {i : ι} (hi : i ∈ I) : s i ∈ 𝓝 (a i) := 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
I : Set ι
s : (i : ι) → Set (π i)
a : (i : ι) → π i
hs : Set.pi I s ∈ 𝓝 a
i : ι
hi : i ∈ I
⊢ s i ∈ 𝓝 (a i)

Next tactic:
rw [nhds_pi] at hs
theorem mem_nhds_of_pi_mem_nhds {I : Set ι} {s : ∀ i, Set (π i)} (a : ∀ i, π i) (hs : I.pi s ∈ 𝓝 a)
    {i : ι} (hi : i ∈ I) : s i ∈ 𝓝 (a i) := by
  rw [nhds_pi] at hs; 

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
I : Set ι
s : (i : ι) → Set (π i)
a : (i : ι) → π i
hs : Set.pi I s ∈ Filter.pi fun i => 𝓝 (a i)
i : ι
hi : i ∈ I
⊢ s i ∈ 𝓝 (a i)

Next tactic:
exact mem_of_pi_mem_pi hs hi
theorem set_pi_mem_nhds {i : Set ι} {s : ∀ a, Set (π a)} {x : ∀ a, π a} (hi : i.Finite)
    (hs : ∀ a ∈ i, s a ∈ 𝓝 (x a)) : pi i s ∈ 𝓝 x := 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
i : Set ι
s : (a : ι) → Set (π a)
x : (a : ι) → π a
hi : Set.Finite i
hs : ∀ a ∈ i, s a ∈ 𝓝 (x a)
⊢ Set.pi i s ∈ 𝓝 x

Next tactic:
rw [pi_def, biInter_mem hi]
theorem set_pi_mem_nhds {i : Set ι} {s : ∀ a, Set (π a)} {x : ∀ a, π a} (hi : i.Finite)
    (hs : ∀ a ∈ i, s a ∈ 𝓝 (x a)) : pi i s ∈ 𝓝 x := by
  rw [pi_def, biInter_mem hi]
  

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
i : Set ι
s : (a : ι) → Set (π a)
x : (a : ι) → π a
hi : Set.Finite i
hs : ∀ a ∈ i, s a ∈ 𝓝 (x a)
⊢ ∀ i_1 ∈ i, eval i_1 ⁻¹' s i_1 ∈ 𝓝 x

Next tactic:
exact fun a ha => (continuous_apply a).continuousAt (hs a ha)
theorem set_pi_mem_nhds_iff {I : Set ι} (hI : I.Finite) {s : ∀ i, Set (π i)} (a : ∀ i, π i) :
    I.pi s ∈ 𝓝 a ↔ ∀ i : ι, i ∈ I → s i ∈ 𝓝 (a i) := 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
I : Set ι
hI : Set.Finite I
s : (i : ι) → Set (π i)
a : (i : ι) → π i
⊢ Set.pi I s ∈ 𝓝 a ↔ ∀ i ∈ I, s i ∈ 𝓝 (a i)

Next tactic:
rw [nhds_pi, pi_mem_pi_iff hI]
theorem interior_pi_set {I : Set ι} (hI : I.Finite) {s : ∀ i, Set (π i)} :
    interior (pi I s) = I.pi fun i => interior (s i) := 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
I : Set ι
hI : Set.Finite I
s : (i : ι) → Set (π i)
⊢ interior (Set.pi I s) = Set.pi I fun i => interior (s i)

Next tactic:
ext a
theorem interior_pi_set {I : Set ι} (hI : I.Finite) {s : ∀ i, Set (π i)} :
    interior (pi I s) = I.pi fun i => interior (s i) := by
  ext a
  

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
I : Set ι
hI : Set.Finite I
s : (i : ι) → Set (π i)
a : (i : ι) → π i
⊢ a ∈ interior (Set.pi I s) ↔ a ∈ Set.pi I fun i => interior (s i)

Next tactic:
simp only [Set.mem_pi, mem_interior_iff_mem_nhds, set_pi_mem_nhds_iff hI]
theorem exists_finset_piecewise_mem_of_mem_nhds [DecidableEq ι] {s : Set (∀ a, π a)} {x : ∀ a, π a}
    (hs : s ∈ 𝓝 x) (y : ∀ a, π a) : ∃ I : Finset ι, I.piecewise x y ∈ 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✝ : DecidableEq ι
s : Set ((a : ι) → π a)
x : (a : ι) → π a
hs : s ∈ 𝓝 x
y : (a : ι) → π a
⊢ ∃ I, Finset.piecewise I x y ∈ s

Next tactic:
simp only [nhds_pi, Filter.mem_pi'] at hs
theorem exists_finset_piecewise_mem_of_mem_nhds [DecidableEq ι] {s : Set (∀ a, π a)} {x : ∀ a, π a}
    (hs : s ∈ 𝓝 x) (y : ∀ a, π a) : ∃ I : Finset ι, I.piecewise x y ∈ s := by
  simp only [nhds_pi, Filter.mem_pi'] at hs
  

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✝ : DecidableEq ι
s : Set ((a : ι) → π a)
x y : (a : ι) → π a
hs : ∃ I t, (∀ (i : ι), t i ∈ 𝓝 (x i)) ∧ Set.pi (↑I) t ⊆ s
⊢ ∃ I, Finset.piecewise I x y ∈ s

Next tactic:
rcases hs with ⟨I, t, htx, hts⟩
theorem exists_finset_piecewise_mem_of_mem_nhds [DecidableEq ι] {s : Set (∀ a, π a)} {x : ∀ a, π a}
    (hs : s ∈ 𝓝 x) (y : ∀ a, π a) : ∃ I : Finset ι, I.piecewise x y ∈ s := by
  simp only [nhds_pi, Filter.mem_pi'] at hs
  rcases hs with ⟨I, t, htx, hts⟩
  

Proof state:
case 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
inst✝ : DecidableEq ι
s : Set ((a : ι) → π a)
x y : (a : ι) → π a
I : Finset ι
t : (i : ι) → Set (π i)
htx : ∀ (i : ι), t i ∈ 𝓝 (x i)
hts : Set.pi (↑I) t ⊆ s
⊢ ∃ I, Finset.piecewise I x y ∈ s

Next tactic:
refine' ⟨I, hts fun i hi => _⟩
theorem exists_finset_piecewise_mem_of_mem_nhds [DecidableEq ι] {s : Set (∀ a, π a)} {x : ∀ a, π a}
    (hs : s ∈ 𝓝 x) (y : ∀ a, π a) : ∃ I : Finset ι, I.piecewise x y ∈ s := by
  simp only [nhds_pi, Filter.mem_pi'] at hs
  rcases hs with ⟨I, t, htx, hts⟩
  refine' ⟨I, hts fun i hi => _⟩
  

Proof state:
case 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
inst✝ : DecidableEq ι
s : Set ((a : ι) → π a)
x y : (a : ι) → π a
I : Finset ι
t : (i : ι) → Set (π i)
htx : ∀ (i : ι), t i ∈ 𝓝 (x i)
hts : Set.pi (↑I) t ⊆ s
i : ι
hi : i ∈ ↑I
⊢ Finset.piecewise I x y i ∈ t i

Next tactic:
simpa [Finset.mem_coe.1 hi] using mem_of_mem_nhds (htx i)
theorem pi_generateFrom_eq {π : ι → Type*} {g : ∀ a, Set (Set (π a))} :
    (@Pi.topologicalSpace ι π fun a => generateFrom (g a)) =
      generateFrom
        { t | ∃ (s : ∀ a, Set (π a)) (i : Finset ι), (∀ a ∈ i, s a ∈ g a) ∧ t = pi (↑i) 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
π : ι → Type u_8
g : (a : ι) → Set (Set (π a))
⊢ Pi.topologicalSpace = generateFrom {t | ∃ s i, (∀ a ∈ i, s a ∈ g a) ∧ t = Set.pi (↑i) s}

Next tactic:
refine le_antisymm ?_ ?_
theorem pi_generateFrom_eq {π : ι → Type*} {g : ∀ a, Set (Set (π a))} :
    (@Pi.topologicalSpace ι π fun a => generateFrom (g a)) =
      generateFrom
        { t | ∃ (s : ∀ a, Set (π a)) (i : Finset ι), (∀ a ∈ i, s a ∈ g a) ∧ t = pi (↑i) s } := by
  refine le_antisymm ?_ ?_
  · 

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
π : ι → Type u_8
g : (a : ι) → Set (Set (π a))
⊢ Pi.topologicalSpace ≤ generateFrom {t | ∃ s i, (∀ a ∈ i, s a ∈ g a) ∧ t = Set.pi (↑i) s}

Next tactic:
apply le_generateFrom
theorem pi_generateFrom_eq {π : ι → Type*} {g : ∀ a, Set (Set (π a))} :
    (@Pi.topologicalSpace ι π fun a => generateFrom (g a)) =
      generateFrom
        { t | ∃ (s : ∀ a, Set (π a)) (i : Finset ι), (∀ a ∈ i, s a ∈ g a) ∧ t = pi (↑i) s } := by
  refine le_antisymm ?_ ?_
  · apply le_generateFrom
    

Proof state:
case refine_1.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
π : ι → Type u_8
g : (a : ι) → Set (Set (π a))
⊢ ∀ s ∈ {t | ∃ s i, (∀ a ∈ i, s a ∈ g a) ∧ t = Set.pi (↑i) s}, IsOpen s

Next tactic:
rintro _ ⟨s, i, hi, rfl⟩
theorem pi_generateFrom_eq {π : ι → Type*} {g : ∀ a, Set (Set (π a))} :
    (@Pi.topologicalSpace ι π fun a => generateFrom (g a)) =
      generateFrom
        { t | ∃ (s : ∀ a, Set (π a)) (i : Finset ι), (∀ a ∈ i, s a ∈ g a) ∧ t = pi (↑i) s } := by
  refine le_antisymm ?_ ?_
  · apply le_generateFrom
    rintro _ ⟨s, i, hi, rfl⟩
    

Proof state:
case refine_1.h.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
π : ι → Type u_8
g : (a : ι) → Set (Set (π a))
s : (a : ι) → Set (π a)
i : Finset ι
hi : ∀ a ∈ i, s a ∈ g a
⊢ IsOpen (Set.pi (↑i) s)

Next tactic:
letI := fun a => generateFrom (g a)
theorem pi_generateFrom_eq {π : ι → Type*} {g : ∀ a, Set (Set (π a))} :
    (@Pi.topologicalSpace ι π fun a => generateFrom (g a)) =
      generateFrom
        { t | ∃ (s : ∀ a, Set (π a)) (i : Finset ι), (∀ a ∈ i, s a ∈ g a) ∧ t = pi (↑i) s } := by
  refine le_antisymm ?_ ?_
  · apply le_generateFrom
    rintro _ ⟨s, i, hi, rfl⟩
    letI := fun a => generateFrom (g a)
    

Proof state:
case refine_1.h.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
π : ι → Type u_8
g : (a : ι) → Set (Set (π a))
s : (a : ι) → Set (π a)
i : Finset ι
hi : ∀ a ∈ i, s a ∈ g a
this : (a : ι) → TopologicalSpace (π a) := fun a => generateFrom (g a)
⊢ IsOpen (Set.pi (↑i) s)

Next tactic:
exact isOpen_set_pi i.finite_toSet (fun a ha => GenerateOpen.basic _ (hi a ha))
theorem pi_generateFrom_eq {π : ι → Type*} {g : ∀ a, Set (Set (π a))} :
    (@Pi.topologicalSpace ι π fun a => generateFrom (g a)) =
      generateFrom
        { t | ∃ (s : ∀ a, Set (π a)) (i : Finset ι), (∀ a ∈ i, s a ∈ g a) ∧ t = pi (↑i) s } := by
  refine le_antisymm ?_ ?_
  · apply le_generateFrom
    rintro _ ⟨s, i, hi, rfl⟩
    letI := fun a => generateFrom (g a)
    exact isOpen_set_pi i.finite_toSet (fun a ha => GenerateOpen.basic _ (hi a ha))
  · 

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
π : ι → Type u_8
g : (a : ι) → Set (Set (π a))
⊢ generateFrom {t | ∃ s i, (∀ a ∈ i, s a ∈ g a) ∧ t = Set.pi (↑i) s} ≤ Pi.topologicalSpace

Next tactic:
refine le_iInf fun a => coinduced_le_iff_le_induced.1 <| le_generateFrom fun s hs => ?_
theorem pi_generateFrom_eq {π : ι → Type*} {g : ∀ a, Set (Set (π a))} :
    (@Pi.topologicalSpace ι π fun a => generateFrom (g a)) =
      generateFrom
        { t | ∃ (s : ∀ a, Set (π a)) (i : Finset ι), (∀ a ∈ i, s a ∈ g a) ∧ t = pi (↑i) s } := by
  refine le_antisymm ?_ ?_
  · apply le_generateFrom
    rintro _ ⟨s, i, hi, rfl⟩
    letI := fun a => generateFrom (g a)
    exact isOpen_set_pi i.finite_toSet (fun a ha => GenerateOpen.basic _ (hi a ha))
  · refine le_iInf fun a => coinduced_le_iff_le_induced.1 <| le_generateFrom fun s hs => ?_
    

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
π : ι → Type u_8
g : (a : ι) → Set (Set (π a))
a : ι
s : Set (π a)
hs : s ∈ g a
⊢ IsOpen s

Next tactic:
refine GenerateOpen.basic _ ⟨update (fun a => univ) a s, {a}, ?_⟩
theorem pi_generateFrom_eq {π : ι → Type*} {g : ∀ a, Set (Set (π a))} :
    (@Pi.topologicalSpace ι π fun a => generateFrom (g a)) =
      generateFrom
        { t | ∃ (s : ∀ a, Set (π a)) (i : Finset ι), (∀ a ∈ i, s a ∈ g a) ∧ t = pi (↑i) s } := by
  refine le_antisymm ?_ ?_
  · apply le_generateFrom
    rintro _ ⟨s, i, hi, rfl⟩
    letI := fun a => generateFrom (g a)
    exact isOpen_set_pi i.finite_toSet (fun a ha => GenerateOpen.basic _ (hi a ha))
  · refine le_iInf fun a => coinduced_le_iff_le_induced.1 <| le_generateFrom fun s hs => ?_
    refine GenerateOpen.basic _ ⟨update (fun a => univ) a s, {a}, ?_⟩
    

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
π : ι → Type u_8
g : (a : ι) → Set (Set (π a))
a : ι
s : Set (π a)
hs : s ∈ g a
⊢ (∀ a_1 ∈ {a}, update (fun a => univ) a s a_1 ∈ g a_1) ∧
    (fun f => f a) ⁻¹' s = Set.pi (↑{a}) (update (fun a => univ) a s)

Next tactic:
simp [hs]
theorem pi_eq_generateFrom :
    Pi.topologicalSpace =
      generateFrom
        { g | ∃ (s : ∀ a, Set (π a)) (i : Finset ι), (∀ a ∈ i, IsOpen (s a)) ∧ g = pi (↑i) s } :=
  calc Pi.topologicalSpace
  _ = @Pi.topologicalSpace ι π fun a => generateFrom { s | IsOpen 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
⊢ Pi.topologicalSpace = Pi.topologicalSpace

Next tactic:
simp only [generateFrom_setOf_isOpen]
theorem pi_generateFrom_eq_finite {π : ι → Type*} {g : ∀ a, Set (Set (π a))} [Finite ι]
    (hg : ∀ a, ⋃₀ g a = univ) :
    (@Pi.topologicalSpace ι π fun a => generateFrom (g a)) =
      generateFrom { t | ∃ s : ∀ a, Set (π a), (∀ a, s a ∈ g a) ∧ t = pi univ 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
π : ι → Type u_8
g : (a : ι) → Set (Set (π a))
inst✝ : Finite ι
hg : ∀ (a : ι), ⋃₀ g a = univ
⊢ Pi.topologicalSpace = generateFrom {t | ∃ s, (∀ (a : ι), s a ∈ g a) ∧ t = Set.pi univ s}

Next tactic:
cases nonempty_fintype ι
theorem pi_generateFrom_eq_finite {π : ι → Type*} {g : ∀ a, Set (Set (π a))} [Finite ι]
    (hg : ∀ a, ⋃₀ g a = univ) :
    (@Pi.topologicalSpace ι π fun a => generateFrom (g a)) =
      generateFrom { t | ∃ s : ∀ a, Set (π a), (∀ a, s a ∈ g a) ∧ t = pi univ 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
π : ι → Type u_8
g : (a : ι) → Set (Set (π a))
inst✝ : Finite ι
hg : ∀ (a : ι), ⋃₀ g a = univ
val✝ : Fintype ι
⊢ Pi.topologicalSpace = generateFrom {t | ∃ s, (∀ (a : ι), s a ∈ g a) ∧ t = Set.pi univ s}

Next tactic:
rw [pi_generateFrom_eq]