l3lab/ntp-mathlib huggingface dataset:
/-- Let `M'` be a manifold whose chart structure is given by an open embedding `e'` into its model
space `H'`. Then the smoothness of `e' ∘ f : M → H'` implies the smoothness of `f`.

This is useful, for example, when `e' ∘ f = g ∘ e` for smooth maps `e : M → X` and `g : X → H'`. -/
lemma ContMDiff.of_comp_openEmbedding {f : M → M'} (hf : ContMDiff I I' n (e' ∘ f)) :
    haveI := h'.singletonChartedSpace; ContMDiff I I' n f := by
  have : f = (h'.toPartialHomeomorph e').symm ∘ e' ∘ f := by
    ext
    rw [Function.comp_apply, Function.comp_apply, OpenEmbedding.toPartialHomeomorph_left_inv]
  rw [this]
  apply @ContMDiffOn.comp_contMDiff _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    h'.singletonChartedSpace _ _ (range e') _ (contMDiffOn_openEmbedding_symm h') hf
  

Proof state:
𝕜 : Type u_1
inst✝³⁹ : NontriviallyNormedField 𝕜
E : Type u_2
inst✝³⁸ : NormedAddCommGroup E
inst✝³⁷ : NormedSpace 𝕜 E
H : Type u_3
inst✝³⁶ : TopologicalSpace H
I : ModelWithCorners 𝕜 E H
M : Type u_4
inst✝³⁵ : TopologicalSpace M
inst✝³⁴ : ChartedSpace H M
inst✝³³ : SmoothManifoldWithCorners I M
E' : Type u_5
inst✝³² : NormedAddCommGroup E'
inst✝³¹ : NormedSpace 𝕜 E'
H' : Type u_6
inst✝³⁰ : TopologicalSpace H'
I' : ModelWithCorners 𝕜 E' H'
M' : Type u_7
inst✝²⁹ : TopologicalSpace M'
inst✝²⁸ : ChartedSpace H' M'
inst✝²⁷ : SmoothManifoldWithCorners I' M'
E'' : Type u_8
inst✝²⁶ : NormedAddCommGroup E''
inst✝²⁵ : NormedSpace 𝕜 E''
H'' : Type u_9
inst✝²⁴ : TopologicalSpace H''
I'' : ModelWithCorners 𝕜 E'' H''
M'' : Type u_10
inst✝²³ : TopologicalSpace M''
inst✝²² : ChartedSpace H'' M''
F : Type u_11
inst✝²¹ : NormedAddCommGroup F
inst✝²⁰ : NormedSpace 𝕜 F
G : Type u_12
inst✝¹⁹ : TopologicalSpace G
J : ModelWithCorners 𝕜 F G
N : Type u_13
inst✝¹⁸ : TopologicalSpace N
inst✝¹⁷ : ChartedSpace G N
inst✝¹⁶ : SmoothManifoldWithCorners J N
F' : Type u_14
inst✝¹⁵ : NormedAddCommGroup F'
inst✝¹⁴ : NormedSpace 𝕜 F'
G' : Type u_15
inst✝¹³ : TopologicalSpace G'
J' : ModelWithCorners 𝕜 F' G'
N' : Type u_16
inst✝¹² : TopologicalSpace N'
inst✝¹¹ : ChartedSpace G' N'
inst✝¹⁰ : SmoothManifoldWithCorners J' N'
F₁ : Type u_17
inst✝⁹ : NormedAddCommGroup F₁
inst✝⁸ : NormedSpace 𝕜 F₁
F₂ : Type u_18
inst✝⁷ : NormedAddCommGroup F₂
inst✝⁶ : NormedSpace 𝕜 F₂
F₃ : Type u_19
inst✝⁵ : NormedAddCommGroup F₃
inst✝⁴ : NormedSpace 𝕜 F₃
F₄ : Type u_20
inst✝³ : NormedAddCommGroup F₄
inst✝² : NormedSpace 𝕜 F₄
e✝ : PartialHomeomorph M H
e'✝ : PartialHomeomorph M' H'
f✝ f₁ : M → M'
s s₁ t : Set M
x : M
m n✝ : ℕ∞
inst✝¹ : Nonempty M
e : M → H
h : OpenEmbedding e
inst✝ : Nonempty M'
e' : M' → H'
h' : OpenEmbedding e'
n : WithTop ℕ
f : M → M'
hf : ContMDiff I I' n (e' ∘ f)
this : f = ↑(PartialHomeomorph.symm (OpenEmbedding.toPartialHomeomorph e' h')) ∘ e' ∘ f
⊢ ∀ (x : M), (e' ∘ f) x ∈ range e'

Next tactic:
simp
/-- If `R` is a presieve in the grothendieck topology on `Opens X`, the covering family associated
to `R` really is _covering_, i.e. the union of all open sets equals `U`.
-/
theorem iSup_eq_of_mem_grothendieck (hR : Sieve.generate R ∈ Opens.grothendieckTopology X U) :
    iSup (coveringOfPresieve U R) = U := by
  

Proof state:
X : TopCat
U : Opens ↑X
R : Presieve U
hR : Sieve.generate R ∈ GrothendieckTopology.sieves (Opens.grothendieckTopology ↑X) U
⊢ iSup (coveringOfPresieve U R) = U

Next tactic:
apply le_antisymm
/-- If `R` is a presieve in the grothendieck topology on `Opens X`, the covering family associated
to `R` really is _covering_, i.e. the union of all open sets equals `U`.
-/
theorem iSup_eq_of_mem_grothendieck (hR : Sieve.generate R ∈ Opens.grothendieckTopology X U) :
    iSup (coveringOfPresieve U R) = U := by
  apply le_antisymm
  · 

Proof state:
case a
X : TopCat
U : Opens ↑X
R : Presieve U
hR : Sieve.generate R ∈ GrothendieckTopology.sieves (Opens.grothendieckTopology ↑X) U
⊢ iSup (coveringOfPresieve U R) ≤ U

Next tactic:
refine' iSup_le _
/-- If `R` is a presieve in the grothendieck topology on `Opens X`, the covering family associated
to `R` really is _covering_, i.e. the union of all open sets equals `U`.
-/
theorem iSup_eq_of_mem_grothendieck (hR : Sieve.generate R ∈ Opens.grothendieckTopology X U) :
    iSup (coveringOfPresieve U R) = U := by
  apply le_antisymm
  · refine' iSup_le _
    

Proof state:
case a
X : TopCat
U : Opens ↑X
R : Presieve U
hR : Sieve.generate R ∈ GrothendieckTopology.sieves (Opens.grothendieckTopology ↑X) U
⊢ ∀ (i : (V : Opens ↑X) × { f // R f }), coveringOfPresieve U R i ≤ U

Next tactic:
intro f
/-- If `R` is a presieve in the grothendieck topology on `Opens X`, the covering family associated
to `R` really is _covering_, i.e. the union of all open sets equals `U`.
-/
theorem iSup_eq_of_mem_grothendieck (hR : Sieve.generate R ∈ Opens.grothendieckTopology X U) :
    iSup (coveringOfPresieve U R) = U := by
  apply le_antisymm
  · refine' iSup_le _
    intro f
    

Proof state:
case a
X : TopCat
U : Opens ↑X
R : Presieve U
hR : Sieve.generate R ∈ GrothendieckTopology.sieves (Opens.grothendieckTopology ↑X) U
f : (V : Opens ↑X) × { f // R f }
⊢ coveringOfPresieve U R f ≤ U

Next tactic:
exact f.2.1.le
/-- If `R` is a presieve in the grothendieck topology on `Opens X`, the covering family associated
to `R` really is _covering_, i.e. the union of all open sets equals `U`.
-/
theorem iSup_eq_of_mem_grothendieck (hR : Sieve.generate R ∈ Opens.grothendieckTopology X U) :
    iSup (coveringOfPresieve U R) = U := by
  apply le_antisymm
  · refine' iSup_le _
    intro f
    exact f.2.1.le
  

Proof state:
case a
X : TopCat
U : Opens ↑X
R : Presieve U
hR : Sieve.generate R ∈ GrothendieckTopology.sieves (Opens.grothendieckTopology ↑X) U
⊢ U ≤ iSup (coveringOfPresieve U R)

Next tactic:
intro x hxU
/-- If `R` is a presieve in the grothendieck topology on `Opens X`, the covering family associated
to `R` really is _covering_, i.e. the union of all open sets equals `U`.
-/
theorem iSup_eq_of_mem_grothendieck (hR : Sieve.generate R ∈ Opens.grothendieckTopology X U) :
    iSup (coveringOfPresieve U R) = U := by
  apply le_antisymm
  · refine' iSup_le _
    intro f
    exact f.2.1.le
  intro x hxU
  

Proof state:
case a
X : TopCat
U : Opens ↑X
R : Presieve U
hR : Sieve.generate R ∈ GrothendieckTopology.sieves (Opens.grothendieckTopology ↑X) U
x : ↑X
hxU : x ∈ ↑U
⊢ x ∈ ↑(iSup (coveringOfPresieve U R))

Next tactic:
rw [Opens.coe_iSup, Set.mem_iUnion]
/-- If `R` is a presieve in the grothendieck topology on `Opens X`, the covering family associated
to `R` really is _covering_, i.e. the union of all open sets equals `U`.
-/
theorem iSup_eq_of_mem_grothendieck (hR : Sieve.generate R ∈ Opens.grothendieckTopology X U) :
    iSup (coveringOfPresieve U R) = U := by
  apply le_antisymm
  · refine' iSup_le _
    intro f
    exact f.2.1.le
  intro x hxU
  rw [Opens.coe_iSup, Set.mem_iUnion]
  

Proof state:
case a
X : TopCat
U : Opens ↑X
R : Presieve U
hR : Sieve.generate R ∈ GrothendieckTopology.sieves (Opens.grothendieckTopology ↑X) U
x : ↑X
hxU : x ∈ ↑U
⊢ ∃ i, x ∈ ↑(coveringOfPresieve U R i)

Next tactic:
obtain ⟨V, iVU, ⟨W, iVW, iWU, hiWU, -⟩, hxV⟩ := hR x hxU
/-- If `R` is a presieve in the grothendieck topology on `Opens X`, the covering family associated
to `R` really is _covering_, i.e. the union of all open sets equals `U`.
-/
theorem iSup_eq_of_mem_grothendieck (hR : Sieve.generate R ∈ Opens.grothendieckTopology X U) :
    iSup (coveringOfPresieve U R) = U := by
  apply le_antisymm
  · refine' iSup_le _
    intro f
    exact f.2.1.le
  intro x hxU
  rw [Opens.coe_iSup, Set.mem_iUnion]
  obtain ⟨V, iVU, ⟨W, iVW, iWU, hiWU, -⟩, hxV⟩ := hR x hxU
  

Proof state:
case a.intro.intro.intro.intro.intro.intro.intro
X : TopCat
U : Opens ↑X
R : Presieve U
hR : Sieve.generate R ∈ GrothendieckTopology.sieves (Opens.grothendieckTopology ↑X) U
x : ↑X
hxU : x ∈ ↑U
V : Opens ↑X
iVU : V ⟶ U
hxV : x ∈ V
W : Opens ↑X
iVW : V ⟶ W
iWU : W ⟶ U
hiWU : R iWU
⊢ ∃ i, x ∈ ↑(coveringOfPresieve U R i)

Next tactic:
exact ⟨⟨W, ⟨iWU, hiWU⟩⟩, iVW.le hxV⟩
/-- Given a presieve `R` on `Y`, if we take its associated family of opens via
    `coveringOfPresieve` (which may not cover `Y` if `R` is not covering), and take
    the presieve on `Y` associated to the family of opens via `presieveOfCoveringAux`,
    then we get back the original presieve `R`. -/
@[simp]
theorem covering_presieve_eq_self {Y : Opens X} (R : Presieve Y) :
    presieveOfCoveringAux (coveringOfPresieve Y R) Y = R := by
  

Proof state:
X : TopCat
Y : Opens ↑X
R : Presieve Y
⊢ presieveOfCoveringAux (coveringOfPresieve Y R) Y = R

Next tactic:
funext Z
/-- Given a presieve `R` on `Y`, if we take its associated family of opens via
    `coveringOfPresieve` (which may not cover `Y` if `R` is not covering), and take
    the presieve on `Y` associated to the family of opens via `presieveOfCoveringAux`,
    then we get back the original presieve `R`. -/
@[simp]
theorem covering_presieve_eq_self {Y : Opens X} (R : Presieve Y) :
    presieveOfCoveringAux (coveringOfPresieve Y R) Y = R := by
  funext Z
  

Proof state:
case h
X : TopCat
Y : Opens ↑X
R : Presieve Y
Z : Opens ↑X
⊢ presieveOfCoveringAux (coveringOfPresieve Y R) Y = R

Next tactic:
ext f
/-- Given a presieve `R` on `Y`, if we take its associated family of opens via
    `coveringOfPresieve` (which may not cover `Y` if `R` is not covering), and take
    the presieve on `Y` associated to the family of opens via `presieveOfCoveringAux`,
    then we get back the original presieve `R`. -/
@[simp]
theorem covering_presieve_eq_self {Y : Opens X} (R : Presieve Y) :
    presieveOfCoveringAux (coveringOfPresieve Y R) Y = R := by
  funext Z
  ext f
  

Proof state:
case h.h
X : TopCat
Y : Opens ↑X
R : Presieve Y
Z : Opens ↑X
f : Z ⟶ Y
⊢ f ∈ presieveOfCoveringAux (coveringOfPresieve Y R) Y ↔ f ∈ R

Next tactic:
exact ⟨fun ⟨⟨_, f', h⟩, rfl⟩ => by rwa [Subsingleton.elim f f'], fun h => ⟨⟨Z, f, h⟩, rfl⟩⟩
/-- Given a presieve `R` on `Y`, if we take its associated family of opens via
    `coveringOfPresieve` (which may not cover `Y` if `R` is not covering), and take
    the presieve on `Y` associated to the family of opens via `presieveOfCoveringAux`,
    then we get back the original presieve `R`. -/
@[simp]
theorem covering_presieve_eq_self {Y : Opens X} (R : Presieve Y) :
    presieveOfCoveringAux (coveringOfPresieve Y R) Y = R := by
  funext Z
  ext f
  exact ⟨fun ⟨⟨_, f', h⟩, rfl⟩ => by 

Proof state:
X : TopCat
Y : Opens ↑X
R : Presieve Y
Z : Opens ↑X
f : Z ⟶ Y
x✝ : f ∈ presieveOfCoveringAux (coveringOfPresieve Y R) Y
f' : Z ⟶ Y
h : R f'
⊢ f ∈ R

Next tactic:
rwa [Subsingleton.elim f f']
/-- The sieve generated by `presieveOfCovering U` is a member of the grothendieck topology.
-/
theorem mem_grothendieckTopology :
    Sieve.generate (presieveOfCovering U) ∈ Opens.grothendieckTopology X (iSup U) := by
  

Proof state:
X : TopCat
ι : Type v
U : ι → Opens ↑X
⊢ Sieve.generate (presieveOfCovering U) ∈ GrothendieckTopology.sieves (Opens.grothendieckTopology ↑X) (iSup U)

Next tactic:
intro x hx
/-- The sieve generated by `presieveOfCovering U` is a member of the grothendieck topology.
-/
theorem mem_grothendieckTopology :
    Sieve.generate (presieveOfCovering U) ∈ Opens.grothendieckTopology X (iSup U) := by
  intro x hx
  

Proof state:
X : TopCat
ι : Type v
U : ι → Opens ↑X
x : ↑X
hx : x ∈ iSup U
⊢ ∃ U_1 f, (Sieve.generate (presieveOfCovering U)).arrows f ∧ x ∈ U_1

Next tactic:
obtain ⟨i, hxi⟩ := Opens.mem_iSup.mp hx
/-- The sieve generated by `presieveOfCovering U` is a member of the grothendieck topology.
-/
theorem mem_grothendieckTopology :
    Sieve.generate (presieveOfCovering U) ∈ Opens.grothendieckTopology X (iSup U) := by
  intro x hx
  obtain ⟨i, hxi⟩ := Opens.mem_iSup.mp hx
  

Proof state:
case intro
X : TopCat
ι : Type v
U : ι → Opens ↑X
x : ↑X
hx : x ∈ iSup U
i : ι
hxi : x ∈ U i
⊢ ∃ U_1 f, (Sieve.generate (presieveOfCovering U)).arrows f ∧ x ∈ U_1

Next tactic:
exact ⟨U i, Opens.leSupr U i, ⟨U i, 𝟙 _, Opens.leSupr U i, ⟨i, rfl⟩, Category.id_comp _⟩, hxi⟩
theorem coverDense_iff_isBasis [Category ι] (B : ι ⥤ Opens X) :
    B.IsCoverDense (Opens.grothendieckTopology X) ↔ Opens.IsBasis (Set.range B.obj) := by
  

Proof state:
X : TopCat
ι : Type u_1
inst✝ : Category.{u_2, u_1} ι
B : ι ⥤ Opens ↑X
⊢ Functor.IsCoverDense B (Opens.grothendieckTopology ↑X) ↔ Opens.IsBasis (Set.range B.obj)

Next tactic:
rw [Opens.isBasis_iff_nbhd]
theorem coverDense_iff_isBasis [Category ι] (B : ι ⥤ Opens X) :
    B.IsCoverDense (Opens.grothendieckTopology X) ↔ Opens.IsBasis (Set.range B.obj) := by
  rw [Opens.isBasis_iff_nbhd]
  

Proof state:
X : TopCat
ι : Type u_1
inst✝ : Category.{u_2, u_1} ι
B : ι ⥤ Opens ↑X
⊢ Functor.IsCoverDense B (Opens.grothendieckTopology ↑X) ↔
    ∀ {U : Opens ↑X} {x : ↑X}, x ∈ U → ∃ U' ∈ Set.range B.obj, x ∈ U' ∧ U' ≤ U

Next tactic:
constructor
theorem coverDense_iff_isBasis [Category ι] (B : ι ⥤ Opens X) :
    B.IsCoverDense (Opens.grothendieckTopology X) ↔ Opens.IsBasis (Set.range B.obj) := by
  rw [Opens.isBasis_iff_nbhd]
  constructor; 

Proof state:
case mp
X : TopCat
ι : Type u_1
inst✝ : Category.{u_2, u_1} ι
B : ι ⥤ Opens ↑X
⊢ Functor.IsCoverDense B (Opens.grothendieckTopology ↑X) →
    ∀ {U : Opens ↑X} {x : ↑X}, x ∈ U → ∃ U' ∈ Set.range B.obj, x ∈ U' ∧ U' ≤ U
case mpr
X : TopCat
ι : Type u_1
inst✝ : Category.{u_2, u_1} ι
B : ι ⥤ Opens ↑X
⊢ (∀ {U : Opens ↑X} {x : ↑X}, x ∈ U → ∃ U' ∈ Set.range B.obj, x ∈ U' ∧ U' ≤ U) →
    Functor.IsCoverDense B (Opens.grothendieckTopology ↑X)

Next tactic:
intro hd U x hx
theorem coverDense_iff_isBasis [Category ι] (B : ι ⥤ Opens X) :
    B.IsCoverDense (Opens.grothendieckTopology X) ↔ Opens.IsBasis (Set.range B.obj) := by
  rw [Opens.isBasis_iff_nbhd]
  constructor; intro hd U x hx; 

Proof state:
case mp
X : TopCat
ι : Type u_1
inst✝ : Category.{u_2, u_1} ι
B : ι ⥤ Opens ↑X
hd : Functor.IsCoverDense B (Opens.grothendieckTopology ↑X)
U : Opens ↑X
x : ↑X
hx : x ∈ U
⊢ ∃ U' ∈ Set.range B.obj, x ∈ U' ∧ U' ≤ U
case mpr
X : TopCat
ι : Type u_1
inst✝ : Category.{u_2, u_1} ι
B : ι ⥤ Opens ↑X
⊢ (∀ {U : Opens ↑X} {x : ↑X}, x ∈ U → ∃ U' ∈ Set.range B.obj, x ∈ U' ∧ U' ≤ U) →
    Functor.IsCoverDense B (Opens.grothendieckTopology ↑X)

Next tactic:
rcases hd.1 U x hx with ⟨V, f, ⟨i, f₁, f₂, _⟩, hV⟩
theorem coverDense_iff_isBasis [Category ι] (B : ι ⥤ Opens X) :
    B.IsCoverDense (Opens.grothendieckTopology X) ↔ Opens.IsBasis (Set.range B.obj) := by
  rw [Opens.isBasis_iff_nbhd]
  constructor; intro hd U x hx; rcases hd.1 U x hx with ⟨V, f, ⟨i, f₁, f₂, _⟩, hV⟩
  

Proof state:
case mp.intro.intro.intro.intro.mk
X : TopCat
ι : Type u_1
inst✝ : Category.{u_2, u_1} ι
B : ι ⥤ Opens ↑X
hd : Functor.IsCoverDense B (Opens.grothendieckTopology ↑X)
U : Opens ↑X
x : ↑X
hx : x ∈ U
V : Opens ↑X
f : V ⟶ U
hV : x ∈ V
i : ι
f₁ : V ⟶ B.obj i
f₂ : B.obj i ⟶ U
fac✝ : f₁ ≫ f₂ = f
⊢ ∃ U' ∈ Set.range B.obj, x ∈ U' ∧ U' ≤ U
case mpr
X : TopCat
ι : Type u_1
inst✝ : Category.{u_2, u_1} ι
B : ι ⥤ Opens ↑X
⊢ (∀ {U : Opens ↑X} {x : ↑X}, x ∈ U → ∃ U' ∈ Set.range B.obj, x ∈ U' ∧ U' ≤ U) →
    Functor.IsCoverDense B (Opens.grothendieckTopology ↑X)

Next tactic:
exact ⟨B.obj i, ⟨i, rfl⟩, f₁.le hV, f₂.le⟩
theorem coverDense_iff_isBasis [Category ι] (B : ι ⥤ Opens X) :
    B.IsCoverDense (Opens.grothendieckTopology X) ↔ Opens.IsBasis (Set.range B.obj) := by
  rw [Opens.isBasis_iff_nbhd]
  constructor; intro hd U x hx; rcases hd.1 U x hx with ⟨V, f, ⟨i, f₁, f₂, _⟩, hV⟩
  exact ⟨B.obj i, ⟨i, rfl⟩, f₁.le hV, f₂.le⟩
  

Proof state:
case mpr
X : TopCat
ι : Type u_1
inst✝ : Category.{u_2, u_1} ι
B : ι ⥤ Opens ↑X
⊢ (∀ {U : Opens ↑X} {x : ↑X}, x ∈ U → ∃ U' ∈ Set.range B.obj, x ∈ U' ∧ U' ≤ U) →
    Functor.IsCoverDense B (Opens.grothendieckTopology ↑X)

Next tactic:
intro hb
theorem coverDense_iff_isBasis [Category ι] (B : ι ⥤ Opens X) :
    B.IsCoverDense (Opens.grothendieckTopology X) ↔ Opens.IsBasis (Set.range B.obj) := by
  rw [Opens.isBasis_iff_nbhd]
  constructor; intro hd U x hx; rcases hd.1 U x hx with ⟨V, f, ⟨i, f₁, f₂, _⟩, hV⟩
  exact ⟨B.obj i, ⟨i, rfl⟩, f₁.le hV, f₂.le⟩
  intro hb; 

Proof state:
case mpr
X : TopCat
ι : Type u_1
inst✝ : Category.{u_2, u_1} ι
B : ι ⥤ Opens ↑X
hb : ∀ {U : Opens ↑X} {x : ↑X}, x ∈ U → ∃ U' ∈ Set.range B.obj, x ∈ U' ∧ U' ≤ U
⊢ Functor.IsCoverDense B (Opens.grothendieckTopology ↑X)

Next tactic:
constructor
theorem coverDense_iff_isBasis [Category ι] (B : ι ⥤ Opens X) :
    B.IsCoverDense (Opens.grothendieckTopology X) ↔ Opens.IsBasis (Set.range B.obj) := by
  rw [Opens.isBasis_iff_nbhd]
  constructor; intro hd U x hx; rcases hd.1 U x hx with ⟨V, f, ⟨i, f₁, f₂, _⟩, hV⟩
  exact ⟨B.obj i, ⟨i, rfl⟩, f₁.le hV, f₂.le⟩
  intro hb; constructor; 

Proof state:
case mpr.is_cover
X : TopCat
ι : Type u_1
inst✝ : Category.{u_2, u_1} ι
B : ι ⥤ Opens ↑X
hb : ∀ {U : Opens ↑X} {x : ↑X}, x ∈ U → ∃ U' ∈ Set.range B.obj, x ∈ U' ∧ U' ≤ U
⊢ ∀ (U : Opens ↑X), Sieve.coverByImage B U ∈ GrothendieckTopology.sieves (Opens.grothendieckTopology ↑X) U

Next tactic:
intro U x hx
theorem coverDense_iff_isBasis [Category ι] (B : ι ⥤ Opens X) :
    B.IsCoverDense (Opens.grothendieckTopology X) ↔ Opens.IsBasis (Set.range B.obj) := by
  rw [Opens.isBasis_iff_nbhd]
  constructor; intro hd U x hx; rcases hd.1 U x hx with ⟨V, f, ⟨i, f₁, f₂, _⟩, hV⟩
  exact ⟨B.obj i, ⟨i, rfl⟩, f₁.le hV, f₂.le⟩
  intro hb; constructor; intro U x hx; 

Proof state:
case mpr.is_cover
X : TopCat
ι : Type u_1
inst✝ : Category.{u_2, u_1} ι
B : ι ⥤ Opens ↑X
hb : ∀ {U : Opens ↑X} {x : ↑X}, x ∈ U → ∃ U' ∈ Set.range B.obj, x ∈ U' ∧ U' ≤ U
U : Opens ↑X
x : ↑X
hx : x ∈ U
⊢ ∃ U_1 f, (Sieve.coverByImage B U).arrows f ∧ x ∈ U_1

Next tactic:
rcases hb hx with ⟨_, ⟨i, rfl⟩, hx, hi⟩
theorem coverDense_iff_isBasis [Category ι] (B : ι ⥤ Opens X) :
    B.IsCoverDense (Opens.grothendieckTopology X) ↔ Opens.IsBasis (Set.range B.obj) := by
  rw [Opens.isBasis_iff_nbhd]
  constructor; intro hd U x hx; rcases hd.1 U x hx with ⟨V, f, ⟨i, f₁, f₂, _⟩, hV⟩
  exact ⟨B.obj i, ⟨i, rfl⟩, f₁.le hV, f₂.le⟩
  intro hb; constructor; intro U x hx; rcases hb hx with ⟨_, ⟨i, rfl⟩, hx, hi⟩
  

Proof state:
case mpr.is_cover.intro.intro.intro.intro
X : TopCat
ι : Type u_1
inst✝ : Category.{u_2, u_1} ι
B : ι ⥤ Opens ↑X
hb : ∀ {U : Opens ↑X} {x : ↑X}, x ∈ U → ∃ U' ∈ Set.range B.obj, x ∈ U' ∧ U' ≤ U
U : Opens ↑X
x : ↑X
hx✝ : x ∈ U
i : ι
hx : x ∈ B.obj i
hi : B.obj i ≤ U
⊢ ∃ U_1 f, (Sieve.coverByImage B U).arrows f ∧ x ∈ U_1

Next tactic:
exact ⟨B.obj i, ⟨⟨hi⟩⟩, ⟨⟨i, 𝟙 _, ⟨⟨hi⟩⟩, rfl⟩⟩, hx⟩
theorem OpenEmbedding.compatiblePreserving (hf : OpenEmbedding f) :
    CompatiblePreserving (Opens.grothendieckTopology Y) hf.isOpenMap.functor := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f : X ⟶ Y
F : TopCat.Presheaf C Y
hf : OpenEmbedding ⇑f
⊢ CompatiblePreserving (Opens.grothendieckTopology ↑Y) (IsOpenMap.functor (_ : IsOpenMap ⇑f))

Next tactic:
haveI : Mono f := (TopCat.mono_iff_injective f).mpr hf.inj
theorem OpenEmbedding.compatiblePreserving (hf : OpenEmbedding f) :
    CompatiblePreserving (Opens.grothendieckTopology Y) hf.isOpenMap.functor := by
  haveI : Mono f := (TopCat.mono_iff_injective f).mpr hf.inj
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f : X ⟶ Y
F : TopCat.Presheaf C Y
hf : OpenEmbedding ⇑f
this : Mono f
⊢ CompatiblePreserving (Opens.grothendieckTopology ↑Y) (IsOpenMap.functor (_ : IsOpenMap ⇑f))

Next tactic:
apply compatiblePreservingOfDownwardsClosed
theorem OpenEmbedding.compatiblePreserving (hf : OpenEmbedding f) :
    CompatiblePreserving (Opens.grothendieckTopology Y) hf.isOpenMap.functor := by
  haveI : Mono f := (TopCat.mono_iff_injective f).mpr hf.inj
  apply compatiblePreservingOfDownwardsClosed
  

Proof state:
case hF
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f : X ⟶ Y
F : TopCat.Presheaf C Y
hf : OpenEmbedding ⇑f
this : Mono f
⊢ {c : Opens ↑X} →
    {d : Opens ↑Y} →
      (d ⟶ (IsOpenMap.functor (_ : IsOpenMap ⇑f)).obj c) →
        (c' : Opens ↑X) × ((IsOpenMap.functor (_ : IsOpenMap ⇑f)).obj c' ≅ d)

Next tactic:
intro U V i
theorem OpenEmbedding.compatiblePreserving (hf : OpenEmbedding f) :
    CompatiblePreserving (Opens.grothendieckTopology Y) hf.isOpenMap.functor := by
  haveI : Mono f := (TopCat.mono_iff_injective f).mpr hf.inj
  apply compatiblePreservingOfDownwardsClosed
  intro U V i
  

Proof state:
case hF
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f : X ⟶ Y
F : TopCat.Presheaf C Y
hf : OpenEmbedding ⇑f
this : Mono f
U : Opens ↑X
V : Opens ↑Y
i : V ⟶ (IsOpenMap.functor (_ : IsOpenMap ⇑f)).obj U
⊢ (c' : Opens ↑X) × ((IsOpenMap.functor (_ : IsOpenMap ⇑f)).obj c' ≅ V)

Next tactic:
refine' ⟨(Opens.map f).obj V, eqToIso <| Opens.ext <| Set.image_preimage_eq_of_subset fun x h ↦ _⟩
theorem OpenEmbedding.compatiblePreserving (hf : OpenEmbedding f) :
    CompatiblePreserving (Opens.grothendieckTopology Y) hf.isOpenMap.functor := by
  haveI : Mono f := (TopCat.mono_iff_injective f).mpr hf.inj
  apply compatiblePreservingOfDownwardsClosed
  intro U V i
  refine' ⟨(Opens.map f).obj V, eqToIso <| Opens.ext <| Set.image_preimage_eq_of_subset fun x h ↦ _⟩
  

Proof state:
case hF
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f : X ⟶ Y
F : TopCat.Presheaf C Y
hf : OpenEmbedding ⇑f
this : Mono f
U : Opens ↑X
V : Opens ↑Y
i : V ⟶ (IsOpenMap.functor (_ : IsOpenMap ⇑f)).obj U
x : ↑Y
h : x ∈ V.1
⊢ x ∈ Set.range fun x => f x

Next tactic:
obtain ⟨_, _, rfl⟩ := i.le h
theorem OpenEmbedding.compatiblePreserving (hf : OpenEmbedding f) :
    CompatiblePreserving (Opens.grothendieckTopology Y) hf.isOpenMap.functor := by
  haveI : Mono f := (TopCat.mono_iff_injective f).mpr hf.inj
  apply compatiblePreservingOfDownwardsClosed
  intro U V i
  refine' ⟨(Opens.map f).obj V, eqToIso <| Opens.ext <| Set.image_preimage_eq_of_subset fun x h ↦ _⟩
  obtain ⟨_, _, rfl⟩ := i.le h
  

Proof state:
case hF.intro.intro
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f : X ⟶ Y
F : TopCat.Presheaf C Y
hf : OpenEmbedding ⇑f
this : Mono f
U : Opens ↑X
V : Opens ↑Y
i : V ⟶ (IsOpenMap.functor (_ : IsOpenMap ⇑f)).obj U
w✝ : (forget TopCat).obj X
left✝ : w✝ ∈ ↑U
h : f w✝ ∈ V.1
⊢ f w✝ ∈ Set.range fun x => f x

Next tactic:
exact ⟨_, rfl⟩
theorem IsOpenMap.coverPreserving (hf : IsOpenMap f) :
    CoverPreserving (Opens.grothendieckTopology X) (Opens.grothendieckTopology Y) hf.functor := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f : X ⟶ Y
F : TopCat.Presheaf C Y
hf : IsOpenMap ⇑f
⊢ CoverPreserving (Opens.grothendieckTopology ↑X) (Opens.grothendieckTopology ↑Y) (functor hf)

Next tactic:
constructor
theorem IsOpenMap.coverPreserving (hf : IsOpenMap f) :
    CoverPreserving (Opens.grothendieckTopology X) (Opens.grothendieckTopology Y) hf.functor := by
  constructor
  

Proof state:
case cover_preserve
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f : X ⟶ Y
F : TopCat.Presheaf C Y
hf : IsOpenMap ⇑f
⊢ ∀ {U : Opens ↑X} {S : Sieve U},
    S ∈ GrothendieckTopology.sieves (Opens.grothendieckTopology ↑X) U →
      Sieve.functorPushforward (functor hf) S ∈
        GrothendieckTopology.sieves (Opens.grothendieckTopology ↑Y) ((functor hf).obj U)

Next tactic:
rintro U S hU _ ⟨x, hx, rfl⟩
theorem IsOpenMap.coverPreserving (hf : IsOpenMap f) :
    CoverPreserving (Opens.grothendieckTopology X) (Opens.grothendieckTopology Y) hf.functor := by
  constructor
  rintro U S hU _ ⟨x, hx, rfl⟩
  

Proof state:
case cover_preserve.intro.intro
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f : X ⟶ Y
F : TopCat.Presheaf C Y
hf : IsOpenMap ⇑f
U : Opens ↑X
S : Sieve U
hU : S ∈ GrothendieckTopology.sieves (Opens.grothendieckTopology ↑X) U
x : (forget TopCat).obj X
hx : x ∈ ↑U
⊢ ∃ U_1 f_1, (Sieve.functorPushforward (functor hf) S).arrows f_1 ∧ f x ∈ U_1

Next tactic:
obtain ⟨V, i, hV, hxV⟩ := hU x hx
theorem IsOpenMap.coverPreserving (hf : IsOpenMap f) :
    CoverPreserving (Opens.grothendieckTopology X) (Opens.grothendieckTopology Y) hf.functor := by
  constructor
  rintro U S hU _ ⟨x, hx, rfl⟩
  obtain ⟨V, i, hV, hxV⟩ := hU x hx
  

Proof state:
case cover_preserve.intro.intro.intro.intro.intro
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f : X ⟶ Y
F : TopCat.Presheaf C Y
hf : IsOpenMap ⇑f
U : Opens ↑X
S : Sieve U
hU : S ∈ GrothendieckTopology.sieves (Opens.grothendieckTopology ↑X) U
x : (forget TopCat).obj X
hx : x ∈ ↑U
V : Opens ↑X
i : V ⟶ U
hV : S.arrows i
hxV : x ∈ V
⊢ ∃ U_1 f_1, (Sieve.functorPushforward (functor hf) S).arrows f_1 ∧ f x ∈ U_1

Next tactic:
exact ⟨_, hf.functor.map i, ⟨_, i, 𝟙 _, hV, rfl⟩, Set.mem_image_of_mem f hxV⟩