l3lab/ntp-mathlib huggingface dataset:
theorem Hom.cast_eq_iff_heq {u v u' v' : U} (hu : u = u') (hv : v = v') (e : u ⟶ v) (e' : u' ⟶ v') :
    e.cast hu hv = e' ↔ HEq e e' := by
  rw [Hom.cast_eq_cast]
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u v u' v' : U
hu : u = u'
hv : v = v'
e : u ⟶ v
e' : u' ⟶ v'
⊢ _root_.cast (_ : (u ⟶ v) = (u' ⟶ v')) e = e' ↔ HEq e e'

Next tactic:
exact _root_.cast_eq_iff_heq
theorem Hom.eq_cast_iff_heq {u v u' v' : U} (hu : u = u') (hv : v = v') (e : u ⟶ v) (e' : u' ⟶ v') :
    e' = e.cast hu hv ↔ HEq e' e := by
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u v u' v' : U
hu : u = u'
hv : v = v'
e : u ⟶ v
e' : u' ⟶ v'
⊢ e' = cast hu hv e ↔ HEq e' e

Next tactic:
rw [eq_comm, Hom.cast_eq_iff_heq]
theorem Hom.eq_cast_iff_heq {u v u' v' : U} (hu : u = u') (hv : v = v') (e : u ⟶ v) (e' : u' ⟶ v') :
    e' = e.cast hu hv ↔ HEq e' e := by
  rw [eq_comm, Hom.cast_eq_iff_heq]
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u v u' v' : U
hu : u = u'
hv : v = v'
e : u ⟶ v
e' : u' ⟶ v'
⊢ HEq e e' ↔ HEq e' e

Next tactic:
exact ⟨HEq.symm, HEq.symm⟩
theorem Path.cast_eq_cast {u v u' v' : U} (hu : u = u') (hv : v = v') (p : Path u v) :
    p.cast hu hv = _root_.cast (by 

Proof state:
U : Type u_1
inst✝ : Quiver U
u v u' v' : U
hu : u = u'
hv : v = v'
p : Path u v
⊢ Path u v = Path u' v'

Next tactic:
rw [hu, hv]
theorem Path.cast_eq_cast {u v u' v' : U} (hu : u = u') (hv : v = v') (p : Path u v) :
    p.cast hu hv = _root_.cast (by rw [hu, hv]) p := by
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u v u' v' : U
hu : u = u'
hv : v = v'
p : Path u v
⊢ cast hu hv p = _root_.cast (_ : Path u v = Path u' v') p

Next tactic:
subst_vars
theorem Path.cast_eq_cast {u v u' v' : U} (hu : u = u') (hv : v = v') (p : Path u v) :
    p.cast hu hv = _root_.cast (by rw [hu, hv]) p := by
  subst_vars
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u' v' : U
p : Path u' v'
⊢ cast (_ : u' = u') (_ : v' = v') p = _root_.cast (_ : Path u' v' = Path u' v') p

Next tactic:
rfl
@[simp]
theorem Path.cast_cast {u v u' v' u'' v'' : U} (p : Path u v) (hu : u = u') (hv : v = v')
    (hu' : u' = u'') (hv' : v' = v'') :
    (p.cast hu hv).cast hu' hv' = p.cast (hu.trans hu') (hv.trans hv') := by
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u v u' v' u'' v'' : U
p : Path u v
hu : u = u'
hv : v = v'
hu' : u' = u''
hv' : v' = v''
⊢ cast hu' hv' (cast hu hv p) = cast (_ : u = u'') (_ : v = v'') p

Next tactic:
subst_vars
@[simp]
theorem Path.cast_cast {u v u' v' u'' v'' : U} (p : Path u v) (hu : u = u') (hv : v = v')
    (hu' : u' = u'') (hv' : v' = v'') :
    (p.cast hu hv).cast hu' hv' = p.cast (hu.trans hu') (hv.trans hv') := by
  subst_vars
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u'' v'' : U
p : Path u'' v''
⊢ cast (_ : u'' = u'') (_ : v'' = v'') (cast (_ : u'' = u'') (_ : v'' = v'') p) = cast (_ : u'' = u'') (_ : v'' = v'') p

Next tactic:
rfl
@[simp]
theorem Path.cast_nil {u u' : U} (hu : u = u') : (Path.nil : Path u u).cast hu hu = Path.nil := by
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u u' : U
hu : u = u'
⊢ cast hu hu nil = nil

Next tactic:
subst_vars
@[simp]
theorem Path.cast_nil {u u' : U} (hu : u = u') : (Path.nil : Path u u).cast hu hu = Path.nil := by
  subst_vars
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u' : U
⊢ cast (_ : u' = u') (_ : u' = u') nil = nil

Next tactic:
rfl
theorem Path.cast_heq {u v u' v' : U} (hu : u = u') (hv : v = v') (p : Path u v) :
    HEq (p.cast hu hv) p := by
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u v u' v' : U
hu : u = u'
hv : v = v'
p : Path u v
⊢ HEq (cast hu hv p) p

Next tactic:
rw [Path.cast_eq_cast]
theorem Path.cast_heq {u v u' v' : U} (hu : u = u') (hv : v = v') (p : Path u v) :
    HEq (p.cast hu hv) p := by
  rw [Path.cast_eq_cast]
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u v u' v' : U
hu : u = u'
hv : v = v'
p : Path u v
⊢ HEq (_root_.cast (_ : Path u v = Path u' v') p) p

Next tactic:
exact _root_.cast_heq _ _
theorem Path.cast_eq_iff_heq {u v u' v' : U} (hu : u = u') (hv : v = v') (p : Path u v)
    (p' : Path u' v') : p.cast hu hv = p' ↔ HEq p p' := by
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u v u' v' : U
hu : u = u'
hv : v = v'
p : Path u v
p' : Path u' v'
⊢ cast hu hv p = p' ↔ HEq p p'

Next tactic:
rw [Path.cast_eq_cast]
theorem Path.cast_eq_iff_heq {u v u' v' : U} (hu : u = u') (hv : v = v') (p : Path u v)
    (p' : Path u' v') : p.cast hu hv = p' ↔ HEq p p' := by
  rw [Path.cast_eq_cast]
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u v u' v' : U
hu : u = u'
hv : v = v'
p : Path u v
p' : Path u' v'
⊢ _root_.cast (_ : Path u v = Path u' v') p = p' ↔ HEq p p'

Next tactic:
exact _root_.cast_eq_iff_heq
theorem Path.cast_cons {u v w u' w' : U} (p : Path u v) (e : v ⟶ w) (hu : u = u') (hw : w = w') :
    (p.cons e).cast hu hw = (p.cast hu rfl).cons (e.cast rfl hw) := by
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u v w u' w' : U
p : Path u v
e : v ⟶ w
hu : u = u'
hw : w = w'
⊢ cast hu hw (cons p e) = cons (cast hu (_ : v = v) p) (Hom.cast (_ : v = v) hw e)

Next tactic:
subst_vars
theorem Path.cast_cons {u v w u' w' : U} (p : Path u v) (e : v ⟶ w) (hu : u = u') (hw : w = w') :
    (p.cons e).cast hu hw = (p.cast hu rfl).cons (e.cast rfl hw) := by
  subst_vars
  

Proof state:
U : Type u_1
inst✝ : Quiver U
v u' w' : U
p : Path u' v
e : v ⟶ w'
⊢ cast (_ : u' = u') (_ : w' = w') (cons p e) =
    cons (cast (_ : u' = u') (_ : v = v) p) (Hom.cast (_ : v = v) (_ : w' = w') e)

Next tactic:
rfl
theorem cast_eq_of_cons_eq_cons {u v v' w : U} {p : Path u v} {p' : Path u v'} {e : v ⟶ w}
    {e' : v' ⟶ w} (h : p.cons e = p'.cons e') : p.cast rfl (obj_eq_of_cons_eq_cons h) = p' := by
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u v v' w : U
p : Path u v
p' : Path u v'
e : v ⟶ w
e' : v' ⟶ w
h : cons p e = cons p' e'
⊢ Path.cast (_ : u = u) (_ : v = v') p = p'

Next tactic:
rw [Path.cast_eq_iff_heq]
theorem cast_eq_of_cons_eq_cons {u v v' w : U} {p : Path u v} {p' : Path u v'} {e : v ⟶ w}
    {e' : v' ⟶ w} (h : p.cons e = p'.cons e') : p.cast rfl (obj_eq_of_cons_eq_cons h) = p' := by
  rw [Path.cast_eq_iff_heq]
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u v v' w : U
p : Path u v
p' : Path u v'
e : v ⟶ w
e' : v' ⟶ w
h : cons p e = cons p' e'
⊢ HEq p p'

Next tactic:
exact heq_of_cons_eq_cons h
theorem hom_cast_eq_of_cons_eq_cons {u v v' w : U} {p : Path u v} {p' : Path u v'} {e : v ⟶ w}
    {e' : v' ⟶ w} (h : p.cons e = p'.cons e') : e.cast (obj_eq_of_cons_eq_cons h) rfl = e' := by
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u v v' w : U
p : Path u v
p' : Path u v'
e : v ⟶ w
e' : v' ⟶ w
h : cons p e = cons p' e'
⊢ Hom.cast (_ : v = v') (_ : w = w) e = e'

Next tactic:
rw [Hom.cast_eq_iff_heq]
theorem hom_cast_eq_of_cons_eq_cons {u v v' w : U} {p : Path u v} {p' : Path u v'} {e : v ⟶ w}
    {e' : v' ⟶ w} (h : p.cons e = p'.cons e') : e.cast (obj_eq_of_cons_eq_cons h) rfl = e' := by
  rw [Hom.cast_eq_iff_heq]
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u v v' w : U
p : Path u v
p' : Path u v'
e : v ⟶ w
e' : v' ⟶ w
h : cons p e = cons p' e'
⊢ HEq e e'

Next tactic:
exact hom_heq_of_cons_eq_cons h
theorem eq_nil_of_length_zero {u v : U} (p : Path u v) (hzero : p.length = 0) :
    p.cast (eq_of_length_zero p hzero) rfl = Path.nil := by
  

Proof state:
U : Type u_1
inst✝ : Quiver U
u v : U
p : Path u v
hzero : length p = 0
⊢ Path.cast (_ : u = v) (_ : v = v) p = nil

Next tactic:
cases p
theorem eq_nil_of_length_zero {u v : U} (p : Path u v) (hzero : p.length = 0) :
    p.cast (eq_of_length_zero p hzero) rfl = Path.nil := by
  cases p
  · 

Proof state:
case nil
U : Type u_1
inst✝ : Quiver U
u : U
hzero : length nil = 0
⊢ Path.cast (_ : u = u) (_ : u = u) nil = nil

Next tactic:
rfl
theorem eq_nil_of_length_zero {u v : U} (p : Path u v) (hzero : p.length = 0) :
    p.cast (eq_of_length_zero p hzero) rfl = Path.nil := by
  cases p
  · rfl
  · 

Proof state:
case cons
U : Type u_1
inst✝ : Quiver U
u v b✝ : U
a✝¹ : Path u b✝
a✝ : b✝ ⟶ v
hzero : length (cons a✝¹ a✝) = 0
⊢ Path.cast (_ : u = v) (_ : v = v) (cons a✝¹ a✝) = nil

Next tactic:
simp only [Nat.succ_ne_zero, length_cons] at hzero
instance : Inhabited (FilterBasis ℕ) :=
  ⟨{  sets := range Ici
      nonempty := ⟨Ici 0, mem_range_self 0⟩
      inter_sets := by
        

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
⊢ ∀ {x y : Set ℕ}, x ∈ range Ici → y ∈ range Ici → ∃ z ∈ range Ici, z ⊆ x ∩ y

Next tactic:
rintro _ _ ⟨n, rfl⟩ ⟨m, rfl⟩
instance : Inhabited (FilterBasis ℕ) :=
  ⟨{  sets := range Ici
      nonempty := ⟨Ici 0, mem_range_self 0⟩
      inter_sets := by
        rintro _ _ ⟨n, rfl⟩ ⟨m, rfl⟩
        

Proof state:
case intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
n m : ℕ
⊢ ∃ z ∈ range Ici, z ⊆ Ici n ∩ Ici m

Next tactic:
exact ⟨Ici (max n m), mem_range_self _, Ici_inter_Ici.symm.subset⟩
/-- Constructs a filter basis from an indexed family of sets satisfying `IsBasis`. -/
protected def filterBasis {p : ι → Prop} {s : ι → Set α} (h : IsBasis p s) : FilterBasis α where
  sets := { t | ∃ i, p i ∧ s i = t }
  nonempty :=
    let ⟨i, hi⟩ := h.nonempty
    ⟨s i, ⟨i, hi, rfl⟩⟩
  inter_sets := by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
p : ι → Prop
s : ι → Set α
h : IsBasis p s
⊢ ∀ {x y : Set α},
    x ∈ {t | ∃ i, p i ∧ s i = t} → y ∈ {t | ∃ i, p i ∧ s i = t} → ∃ z ∈ {t | ∃ i, p i ∧ s i = t}, z ⊆ x ∩ y

Next tactic:
rintro _ _ ⟨i, hi, rfl⟩ ⟨j, hj, rfl⟩
/-- Constructs a filter basis from an indexed family of sets satisfying `IsBasis`. -/
protected def filterBasis {p : ι → Prop} {s : ι → Set α} (h : IsBasis p s) : FilterBasis α where
  sets := { t | ∃ i, p i ∧ s i = t }
  nonempty :=
    let ⟨i, hi⟩ := h.nonempty
    ⟨s i, ⟨i, hi, rfl⟩⟩
  inter_sets := by
    rintro _ _ ⟨i, hi, rfl⟩ ⟨j, hj, rfl⟩
    

Proof state:
case intro.intro.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
p : ι → Prop
s : ι → Set α
h : IsBasis p s
i : ι
hi : p i
j : ι
hj : p j
⊢ ∃ z ∈ {t | ∃ i, p i ∧ s i = t}, z ⊆ s i ∩ s j

Next tactic:
rcases h.inter hi hj with ⟨k, hk, hk'⟩
/-- Constructs a filter basis from an indexed family of sets satisfying `IsBasis`. -/
protected def filterBasis {p : ι → Prop} {s : ι → Set α} (h : IsBasis p s) : FilterBasis α where
  sets := { t | ∃ i, p i ∧ s i = t }
  nonempty :=
    let ⟨i, hi⟩ := h.nonempty
    ⟨s i, ⟨i, hi, rfl⟩⟩
  inter_sets := by
    rintro _ _ ⟨i, hi, rfl⟩ ⟨j, hj, rfl⟩
    rcases h.inter hi hj with ⟨k, hk, hk'⟩
    

Proof state:
case intro.intro.intro.intro.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
p : ι → Prop
s : ι → Set α
h : IsBasis p s
i : ι
hi : p i
j : ι
hj : p j
k : ι
hk : p k
hk' : s k ⊆ s i ∩ s j
⊢ ∃ z ∈ {t | ∃ i, p i ∧ s i = t}, z ⊆ s i ∩ s j

Next tactic:
exact ⟨_, ⟨k, hk, rfl⟩, hk'⟩
theorem eq_iInf_principal (B : FilterBasis α) : B.filter = ⨅ s : B.sets, 𝓟 s := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
B : FilterBasis α
⊢ FilterBasis.filter B = ⨅ s, 𝓟 ↑s

Next tactic:
have : Directed (· ≥ ·) fun s : B.sets => 𝓟 (s : Set α) := by
    rintro ⟨U, U_in⟩ ⟨V, V_in⟩
    rcases B.inter_sets U_in V_in with ⟨W, W_in, W_sub⟩
    use ⟨W, W_in⟩
    simp only [ge_iff_le, le_principal_iff, mem_principal, Subtype.coe_mk]
    exact subset_inter_iff.mp W_sub
theorem eq_iInf_principal (B : FilterBasis α) : B.filter = ⨅ s : B.sets, 𝓟 s := by
  have : Directed (· ≥ ·) fun s : B.sets => 𝓟 (s : Set α) := by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
B : FilterBasis α
⊢ Directed (fun x x_1 => x ≥ x_1) fun s => 𝓟 ↑s

Next tactic:
rintro ⟨U, U_in⟩ ⟨V, V_in⟩
theorem eq_iInf_principal (B : FilterBasis α) : B.filter = ⨅ s : B.sets, 𝓟 s := by
  have : Directed (· ≥ ·) fun s : B.sets => 𝓟 (s : Set α) := by
    rintro ⟨U, U_in⟩ ⟨V, V_in⟩
    

Proof state:
case mk.mk
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
B : FilterBasis α
U : Set α
U_in : U ∈ B.sets
V : Set α
V_in : V ∈ B.sets
⊢ ∃ z,
    (fun x x_1 => x ≥ x_1) ((fun s => 𝓟 ↑s) { val := U, property := U_in }) ((fun s => 𝓟 ↑s) z) ∧
      (fun x x_1 => x ≥ x_1) ((fun s => 𝓟 ↑s) { val := V, property := V_in }) ((fun s => 𝓟 ↑s) z)

Next tactic:
rcases B.inter_sets U_in V_in with ⟨W, W_in, W_sub⟩
theorem eq_iInf_principal (B : FilterBasis α) : B.filter = ⨅ s : B.sets, 𝓟 s := by
  have : Directed (· ≥ ·) fun s : B.sets => 𝓟 (s : Set α) := by
    rintro ⟨U, U_in⟩ ⟨V, V_in⟩
    rcases B.inter_sets U_in V_in with ⟨W, W_in, W_sub⟩
    

Proof state:
case mk.mk.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
B : FilterBasis α
U : Set α
U_in : U ∈ B.sets
V : Set α
V_in : V ∈ B.sets
W : Set α
W_in : W ∈ B.sets
W_sub : W ⊆ U ∩ V
⊢ ∃ z,
    (fun x x_1 => x ≥ x_1) ((fun s => 𝓟 ↑s) { val := U, property := U_in }) ((fun s => 𝓟 ↑s) z) ∧
      (fun x x_1 => x ≥ x_1) ((fun s => 𝓟 ↑s) { val := V, property := V_in }) ((fun s => 𝓟 ↑s) z)

Next tactic:
use ⟨W, W_in⟩
theorem eq_iInf_principal (B : FilterBasis α) : B.filter = ⨅ s : B.sets, 𝓟 s := by
  have : Directed (· ≥ ·) fun s : B.sets => 𝓟 (s : Set α) := by
    rintro ⟨U, U_in⟩ ⟨V, V_in⟩
    rcases B.inter_sets U_in V_in with ⟨W, W_in, W_sub⟩
    use ⟨W, W_in⟩
    

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
B : FilterBasis α
U : Set α
U_in : U ∈ B.sets
V : Set α
V_in : V ∈ B.sets
W : Set α
W_in : W ∈ B.sets
W_sub : W ⊆ U ∩ V
⊢ (fun x x_1 => x ≥ x_1) ((fun s => 𝓟 ↑s) { val := U, property := U_in })
      ((fun s => 𝓟 ↑s) { val := W, property := W_in }) ∧
    (fun x x_1 => x ≥ x_1) ((fun s => 𝓟 ↑s) { val := V, property := V_in })
      ((fun s => 𝓟 ↑s) { val := W, property := W_in })

Next tactic:
simp only [ge_iff_le, le_principal_iff, mem_principal, Subtype.coe_mk]
theorem eq_iInf_principal (B : FilterBasis α) : B.filter = ⨅ s : B.sets, 𝓟 s := by
  have : Directed (· ≥ ·) fun s : B.sets => 𝓟 (s : Set α) := by
    rintro ⟨U, U_in⟩ ⟨V, V_in⟩
    rcases B.inter_sets U_in V_in with ⟨W, W_in, W_sub⟩
    use ⟨W, W_in⟩
    simp only [ge_iff_le, le_principal_iff, mem_principal, Subtype.coe_mk]
    

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
B : FilterBasis α
U : Set α
U_in : U ∈ B.sets
V : Set α
V_in : V ∈ B.sets
W : Set α
W_in : W ∈ B.sets
W_sub : W ⊆ U ∩ V
⊢ W ⊆ U ∧ W ⊆ V

Next tactic:
exact subset_inter_iff.mp W_sub
theorem eq_iInf_principal (B : FilterBasis α) : B.filter = ⨅ s : B.sets, 𝓟 s := by
  have : Directed (· ≥ ·) fun s : B.sets => 𝓟 (s : Set α) := by
    rintro ⟨U, U_in⟩ ⟨V, V_in⟩
    rcases B.inter_sets U_in V_in with ⟨W, W_in, W_sub⟩
    use ⟨W, W_in⟩
    simp only [ge_iff_le, le_principal_iff, mem_principal, Subtype.coe_mk]
    exact subset_inter_iff.mp W_sub
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
B : FilterBasis α
this : Directed (fun x x_1 => x ≥ x_1) fun s => 𝓟 ↑s
⊢ FilterBasis.filter B = ⨅ s, 𝓟 ↑s

Next tactic:
ext U
theorem eq_iInf_principal (B : FilterBasis α) : B.filter = ⨅ s : B.sets, 𝓟 s := by
  have : Directed (· ≥ ·) fun s : B.sets => 𝓟 (s : Set α) := by
    rintro ⟨U, U_in⟩ ⟨V, V_in⟩
    rcases B.inter_sets U_in V_in with ⟨W, W_in, W_sub⟩
    use ⟨W, W_in⟩
    simp only [ge_iff_le, le_principal_iff, mem_principal, Subtype.coe_mk]
    exact subset_inter_iff.mp W_sub
  ext U
  

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
B : FilterBasis α
this : Directed (fun x x_1 => x ≥ x_1) fun s => 𝓟 ↑s
U : Set α
⊢ U ∈ FilterBasis.filter B ↔ U ∈ ⨅ s, 𝓟 ↑s

Next tactic:
simp [mem_filter_iff, mem_iInf_of_directed this]
protected theorem generate (B : FilterBasis α) : generate B.sets = B.filter := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
B : FilterBasis α
⊢ generate B.sets = FilterBasis.filter B

Next tactic:
apply le_antisymm
protected theorem generate (B : FilterBasis α) : generate B.sets = B.filter := by
  apply le_antisymm
  · 

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
B : FilterBasis α
⊢ generate B.sets ≤ FilterBasis.filter B

Next tactic:
intro U U_in
protected theorem generate (B : FilterBasis α) : generate B.sets = B.filter := by
  apply le_antisymm
  · intro U U_in
    

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
B : FilterBasis α
U : Set α
U_in : U ∈ FilterBasis.filter B
⊢ U ∈ generate B.sets

Next tactic:
rcases B.mem_filter_iff.mp U_in with ⟨V, V_in, h⟩
protected theorem generate (B : FilterBasis α) : generate B.sets = B.filter := by
  apply le_antisymm
  · intro U U_in
    rcases B.mem_filter_iff.mp U_in with ⟨V, V_in, h⟩
    

Proof state:
case a.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
B : FilterBasis α
U : Set α
U_in : U ∈ FilterBasis.filter B
V : Set α
V_in : V ∈ B
h : V ⊆ U
⊢ U ∈ generate B.sets

Next tactic:
exact GenerateSets.superset (GenerateSets.basic V_in) h
protected theorem generate (B : FilterBasis α) : generate B.sets = B.filter := by
  apply le_antisymm
  · intro U U_in
    rcases B.mem_filter_iff.mp U_in with ⟨V, V_in, h⟩
    exact GenerateSets.superset (GenerateSets.basic V_in) h
  · 

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
B : FilterBasis α
⊢ FilterBasis.filter B ≤ generate B.sets

Next tactic:
rw [le_generate_iff]
protected theorem generate (B : FilterBasis α) : generate B.sets = B.filter := by
  apply le_antisymm
  · intro U U_in
    rcases B.mem_filter_iff.mp U_in with ⟨V, V_in, h⟩
    exact GenerateSets.superset (GenerateSets.basic V_in) h
  · rw [le_generate_iff]
    

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
B : FilterBasis α
⊢ B.sets ⊆ (FilterBasis.filter B).sets

Next tactic:
apply mem_filter_of_mem
protected theorem mem_filter_iff (h : IsBasis p s) {U : Set α} :
    U ∈ h.filter ↔ ∃ i, p i ∧ s i ⊆ U := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
p : ι → Prop
s : ι → Set α
h : IsBasis p s
U : Set α
⊢ U ∈ IsBasis.filter h ↔ ∃ i, p i ∧ s i ⊆ U

Next tactic:
simp only [IsBasis.filter, FilterBasis.mem_filter_iff, mem_filterBasis_iff,
    exists_exists_and_eq_and]
theorem filter_eq_generate (h : IsBasis p s) : h.filter = generate { U | ∃ i, p i ∧ s i = U } := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
p : ι → Prop
s : ι → Set α
h : IsBasis p s
⊢ IsBasis.filter h = generate {U | ∃ i, p i ∧ s i = U}

Next tactic:
erw [h.filterBasis.generate]
theorem filter_eq_generate (h : IsBasis p s) : h.filter = generate { U | ∃ i, p i ∧ s i = U } := by
  erw [h.filterBasis.generate]; 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
p : ι → Prop
s : ι → Set α
h : IsBasis p s
⊢ IsBasis.filter h = FilterBasis.filter (IsBasis.filterBasis h)

Next tactic:
rfl
theorem hasBasis_generate (s : Set (Set α)) :
    (generate s).HasBasis (fun t => Set.Finite t ∧ t ⊆ s) fun t => ⋂₀ t :=
  ⟨fun U => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
l l' : Filter α
p : ι → Prop
s✝ : ι → Set α
t : Set α
i : ι
p' : ι' → Prop
s' : ι' → Set α
i' : ι'
s : Set (Set α)
U : Set α
⊢ U ∈ generate s ↔ ∃ i, (Set.Finite i ∧ i ⊆ s) ∧ ⋂₀ i ⊆ U

Next tactic:
simp only [mem_generate_iff, exists_prop, and_assoc, and_left_comm]
/-- The smallest filter basis containing a given collection of sets. -/
def FilterBasis.ofSets (s : Set (Set α)) : FilterBasis α where
  sets := sInter '' { t | Set.Finite t ∧ t ⊆ s }
  nonempty := ⟨univ, ∅, ⟨⟨finite_empty, empty_subset s⟩, sInter_empty⟩⟩
  inter_sets := by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
l l' : Filter α
p : ι → Prop
s✝ : ι → Set α
t : Set α
i : ι
p' : ι' → Prop
s' : ι' → Set α
i' : ι'
s : Set (Set α)
⊢ ∀ {x y : Set α},
    x ∈ sInter '' {t | Set.Finite t ∧ t ⊆ s} →
      y ∈ sInter '' {t | Set.Finite t ∧ t ⊆ s} → ∃ z ∈ sInter '' {t | Set.Finite t ∧ t ⊆ s}, z ⊆ x ∩ y

Next tactic:
rintro _ _ ⟨a, ⟨fina, suba⟩, rfl⟩ ⟨b, ⟨finb, subb⟩, rfl⟩
/-- The smallest filter basis containing a given collection of sets. -/
def FilterBasis.ofSets (s : Set (Set α)) : FilterBasis α where
  sets := sInter '' { t | Set.Finite t ∧ t ⊆ s }
  nonempty := ⟨univ, ∅, ⟨⟨finite_empty, empty_subset s⟩, sInter_empty⟩⟩
  inter_sets := by
    rintro _ _ ⟨a, ⟨fina, suba⟩, rfl⟩ ⟨b, ⟨finb, subb⟩, rfl⟩
    

Proof state:
case intro.intro.intro.intro.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
l l' : Filter α
p : ι → Prop
s✝ : ι → Set α
t : Set α
i : ι
p' : ι' → Prop
s' : ι' → Set α
i' : ι'
s a : Set (Set α)
fina : Set.Finite a
suba : a ⊆ s
b : Set (Set α)
finb : Set.Finite b
subb : b ⊆ s
⊢ ∃ z ∈ sInter '' {t | Set.Finite t ∧ t ⊆ s}, z ⊆ ⋂₀ a ∩ ⋂₀ b

Next tactic:
exact ⟨⋂₀ (a ∪ b), mem_image_of_mem _ ⟨fina.union finb, union_subset suba subb⟩,
        (sInter_union _ _).subset⟩
theorem HasBasis.eq_of_same_basis (hl : l.HasBasis p s) (hl' : l'.HasBasis p s) : l = l' := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
l l' : Filter α
p : ι → Prop
s : ι → Set α
t : Set α
i : ι
p' : ι' → Prop
s' : ι' → Set α
i' : ι'
hl : HasBasis l p s
hl' : HasBasis l' p s
⊢ l = l'

Next tactic:
ext t
theorem HasBasis.eq_of_same_basis (hl : l.HasBasis p s) (hl' : l'.HasBasis p s) : l = l' := by
  ext t
  

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
l l' : Filter α
p : ι → Prop
s : ι → Set α
t✝ : Set α
i : ι
p' : ι' → Prop
s' : ι' → Set α
i' : ι'
hl : HasBasis l p s
hl' : HasBasis l' p s
t : Set α
⊢ t ∈ l ↔ t ∈ l'

Next tactic:
rw [hl.mem_iff, hl'.mem_iff]
protected theorem IsBasis.hasBasis (h : IsBasis p s) : HasBasis h.filter p s :=
  ⟨fun t => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
l l' : Filter α
p : ι → Prop
s : ι → Set α
t✝ : Set α
i : ι
p' : ι' → Prop
s' : ι' → Set α
i' : ι'
h : IsBasis p s
t : Set α
⊢ t ∈ IsBasis.filter h ↔ ∃ i, p i ∧ s i ⊆ t

Next tactic:
simp only [h.mem_filter_iff, exists_prop]
theorem HasBasis.isBasis (h : l.HasBasis p s) : IsBasis p s where
  nonempty := h.ex_mem
  inter hi hj := by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
l l' : Filter α
p : ι → Prop
s : ι → Set α
t : Set α
i : ι
p' : ι' → Prop
s' : ι' → Set α
i' : ι'
h : HasBasis l p s
i✝ j✝ : ι
hi : p i✝
hj : p j✝
⊢ ∃ k, p k ∧ s k ⊆ s i✝ ∩ s j✝

Next tactic:
simpa only [h.mem_iff] using inter_mem (h.mem_of_mem hi) (h.mem_of_mem hj)
theorem HasBasis.filter_eq (h : l.HasBasis p s) : h.isBasis.filter = l := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
l l' : Filter α
p : ι → Prop
s : ι → Set α
t : Set α
i : ι
p' : ι' → Prop
s' : ι' → Set α
i' : ι'
h : HasBasis l p s
⊢ IsBasis.filter (_ : IsBasis p s) = l

Next tactic:
ext U
theorem HasBasis.filter_eq (h : l.HasBasis p s) : h.isBasis.filter = l := by
  ext U
  

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
l l' : Filter α
p : ι → Prop
s : ι → Set α
t : Set α
i : ι
p' : ι' → Prop
s' : ι' → Set α
i' : ι'
h : HasBasis l p s
U : Set α
⊢ U ∈ IsBasis.filter (_ : IsBasis p s) ↔ U ∈ l

Next tactic:
simp [h.mem_iff, IsBasis.mem_filter_iff]
theorem HasBasis.eq_generate (h : l.HasBasis p s) : l = generate { U | ∃ i, p i ∧ s i = U } := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
l l' : Filter α
p : ι → Prop
s : ι → Set α
t : Set α
i : ι
p' : ι' → Prop
s' : ι' → Set α
i' : ι'
h : HasBasis l p s
⊢ l = generate {U | ∃ i, p i ∧ s i = U}

Next tactic:
rw [← h.isBasis.filter_eq_generate, h.filter_eq]
theorem generate_eq_generate_inter (s : Set (Set α)) :
    generate s = generate (sInter '' { t | Set.Finite t ∧ t ⊆ s }) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
l l' : Filter α
p : ι → Prop
s✝ : ι → Set α
t : Set α
i : ι
p' : ι' → Prop
s' : ι' → Set α
i' : ι'
s : Set (Set α)
⊢ generate s = generate (sInter '' {t | Set.Finite t ∧ t ⊆ s})

Next tactic:
rw [← FilterBasis.ofSets_sets, FilterBasis.generate, ← (hasBasis_generate s).filter_eq]