l3lab/ntp-mathlib huggingface dataset:
theorem ι_injective (i : D.J) : Function.Injective (𝖣.ι i) := by
  intro x y h
  rcases (D.ι_eq_iff_rel _ _ _ _).mp h with (⟨⟨⟩⟩ | ⟨_, e₁, e₂⟩)
  · 

Proof state:
case inl.refl
D : GlueData
i : D.J
x : (forget TopCat).obj (GlueData.U D.toGlueData i)
h : (GlueData.ι D.toGlueData i) x = (GlueData.ι D.toGlueData i) x
⊢ x = x

Next tactic:
rfl
theorem ι_injective (i : D.J) : Function.Injective (𝖣.ι i) := by
  intro x y h
  rcases (D.ι_eq_iff_rel _ _ _ _).mp h with (⟨⟨⟩⟩ | ⟨_, e₁, e₂⟩)
  · rfl
  · 

Proof state:
case inr.intro.intro
D : GlueData
i : D.J
x y : (forget TopCat).obj (GlueData.U D.toGlueData i)
h : (GlueData.ι D.toGlueData i) x = (GlueData.ι D.toGlueData i) y
w✝ : ↑(GlueData.V D.toGlueData ({ fst := i, snd := x }.fst, { fst := i, snd := y }.fst))
e₁ : (GlueData.f D.toGlueData { fst := i, snd := x }.fst { fst := i, snd := y }.fst) w✝ = { fst := i, snd := x }.snd
e₂ :
  (GlueData.f D.toGlueData { fst := i, snd := y }.fst { fst := i, snd := x }.fst)
      ((GlueData.t D.toGlueData { fst := i, snd := x }.fst { fst := i, snd := y }.fst) w✝) =
    { fst := i, snd := y }.snd
⊢ x = y

Next tactic:
dsimp only at *
theorem ι_injective (i : D.J) : Function.Injective (𝖣.ι i) := by
  intro x y h
  rcases (D.ι_eq_iff_rel _ _ _ _).mp h with (⟨⟨⟩⟩ | ⟨_, e₁, e₂⟩)
  · rfl
  · dsimp only at *
    -- porting note: there were `cases e₁` and `cases e₂`, instead of the `rw`
    

Proof state:
case inr.intro.intro
D : GlueData
i : D.J
x y : (forget TopCat).obj (GlueData.U D.toGlueData i)
h : (GlueData.ι D.toGlueData i) x = (GlueData.ι D.toGlueData i) y
w✝ : ↑(GlueData.V D.toGlueData ({ fst := i, snd := x }.fst, { fst := i, snd := y }.fst))
e₁ : (GlueData.f D.toGlueData i i) w✝ = x
e₂ : (GlueData.f D.toGlueData i i) ((GlueData.t D.toGlueData i i) w✝) = y
⊢ x = y

Next tactic:
rw [← e₁, ← e₂]
theorem ι_injective (i : D.J) : Function.Injective (𝖣.ι i) := by
  intro x y h
  rcases (D.ι_eq_iff_rel _ _ _ _).mp h with (⟨⟨⟩⟩ | ⟨_, e₁, e₂⟩)
  · rfl
  · dsimp only at *
    -- porting note: there were `cases e₁` and `cases e₂`, instead of the `rw`
    rw [← e₁, ← e₂]
    

Proof state:
case inr.intro.intro
D : GlueData
i : D.J
x y : (forget TopCat).obj (GlueData.U D.toGlueData i)
h : (GlueData.ι D.toGlueData i) x = (GlueData.ι D.toGlueData i) y
w✝ : ↑(GlueData.V D.toGlueData ({ fst := i, snd := x }.fst, { fst := i, snd := y }.fst))
e₁ : (GlueData.f D.toGlueData i i) w✝ = x
e₂ : (GlueData.f D.toGlueData i i) ((GlueData.t D.toGlueData i i) w✝) = y
⊢ (GlueData.f D.toGlueData i i) w✝ = (GlueData.f D.toGlueData i i) ((GlueData.t D.toGlueData i i) w✝)

Next tactic:
simp
theorem image_inter (i j : D.J) :
    Set.range (𝖣.ι i) ∩ Set.range (𝖣.ι j) = Set.range (D.f i j ≫ 𝖣.ι _) := by
  

Proof state:
D : GlueData
i j : D.J
⊢ Set.range ⇑(GlueData.ι D.toGlueData i) ∩ Set.range ⇑(GlueData.ι D.toGlueData j) =
    Set.range ⇑(GlueData.f D.toGlueData i j ≫ GlueData.ι D.toGlueData i)

Next tactic:
ext x
theorem image_inter (i j : D.J) :
    Set.range (𝖣.ι i) ∩ Set.range (𝖣.ι j) = Set.range (D.f i j ≫ 𝖣.ι _) := by
  ext x
  

Proof state:
case h
D : GlueData
i j : D.J
x : (forget TopCat).obj (GlueData.glued D.toGlueData)
⊢ x ∈ Set.range ⇑(GlueData.ι D.toGlueData i) ∩ Set.range ⇑(GlueData.ι D.toGlueData j) ↔
    x ∈ Set.range ⇑(GlueData.f D.toGlueData i j ≫ GlueData.ι D.toGlueData i)

Next tactic:
constructor
theorem image_inter (i j : D.J) :
    Set.range (𝖣.ι i) ∩ Set.range (𝖣.ι j) = Set.range (D.f i j ≫ 𝖣.ι _) := by
  ext x
  constructor
  · 

Proof state:
case h.mp
D : GlueData
i j : D.J
x : (forget TopCat).obj (GlueData.glued D.toGlueData)
⊢ x ∈ Set.range ⇑(GlueData.ι D.toGlueData i) ∩ Set.range ⇑(GlueData.ι D.toGlueData j) →
    x ∈ Set.range ⇑(GlueData.f D.toGlueData i j ≫ GlueData.ι D.toGlueData i)

Next tactic:
rintro ⟨⟨x₁, eq₁⟩, ⟨x₂, eq₂⟩⟩
theorem image_inter (i j : D.J) :
    Set.range (𝖣.ι i) ∩ Set.range (𝖣.ι j) = Set.range (D.f i j ≫ 𝖣.ι _) := by
  ext x
  constructor
  · rintro ⟨⟨x₁, eq₁⟩, ⟨x₂, eq₂⟩⟩
    

Proof state:
case h.mp.intro.intro.intro
D : GlueData
i j : D.J
x : (forget TopCat).obj (GlueData.glued D.toGlueData)
x₁ : (forget TopCat).obj (GlueData.U D.toGlueData i)
eq₁ : (GlueData.ι D.toGlueData i) x₁ = x
x₂ : (forget TopCat).obj (GlueData.U D.toGlueData j)
eq₂ : (GlueData.ι D.toGlueData j) x₂ = x
⊢ x ∈ Set.range ⇑(GlueData.f D.toGlueData i j ≫ GlueData.ι D.toGlueData i)

Next tactic:
obtain ⟨⟨⟩⟩ | ⟨y, e₁, -⟩ := (D.ι_eq_iff_rel _ _ _ _).mp (eq₁.trans eq₂.symm)
theorem image_inter (i j : D.J) :
    Set.range (𝖣.ι i) ∩ Set.range (𝖣.ι j) = Set.range (D.f i j ≫ 𝖣.ι _) := by
  ext x
  constructor
  · rintro ⟨⟨x₁, eq₁⟩, ⟨x₂, eq₂⟩⟩
    obtain ⟨⟨⟩⟩ | ⟨y, e₁, -⟩ := (D.ι_eq_iff_rel _ _ _ _).mp (eq₁.trans eq₂.symm)
    · 

Proof state:
case h.mp.intro.intro.intro.inl.refl
D : GlueData
i : D.J
x : (forget TopCat).obj (GlueData.glued D.toGlueData)
x₁ : (forget TopCat).obj (GlueData.U D.toGlueData i)
eq₁ eq₂ : (GlueData.ι D.toGlueData i) x₁ = x
⊢ x ∈ Set.range ⇑(GlueData.f D.toGlueData i i ≫ GlueData.ι D.toGlueData i)

Next tactic:
exact ⟨inv (D.f i i) x₁, by
        -- Porting note: was `simp [eq₁]`
        -- See https://github.com/leanprover-community/mathlib4/issues/5026
        rw [TopCat.comp_app]
        erw [CategoryTheory.IsIso.inv_hom_id_apply]
        rw [eq₁]⟩
theorem image_inter (i j : D.J) :
    Set.range (𝖣.ι i) ∩ Set.range (𝖣.ι j) = Set.range (D.f i j ≫ 𝖣.ι _) := by
  ext x
  constructor
  · rintro ⟨⟨x₁, eq₁⟩, ⟨x₂, eq₂⟩⟩
    obtain ⟨⟨⟩⟩ | ⟨y, e₁, -⟩ := (D.ι_eq_iff_rel _ _ _ _).mp (eq₁.trans eq₂.symm)
    · exact ⟨inv (D.f i i) x₁, by
        -- Porting note: was `simp [eq₁]`
        -- See https://github.com/leanprover-community/mathlib4/issues/5026
        

Proof state:
D : GlueData
i : D.J
x : (forget TopCat).obj (GlueData.glued D.toGlueData)
x₁ : (forget TopCat).obj (GlueData.U D.toGlueData i)
eq₁ eq₂ : (GlueData.ι D.toGlueData i) x₁ = x
⊢ (GlueData.f D.toGlueData i i ≫ GlueData.ι D.toGlueData i) ((inv (GlueData.f D.toGlueData i i)) x₁) = x

Next tactic:
rw [TopCat.comp_app]
theorem image_inter (i j : D.J) :
    Set.range (𝖣.ι i) ∩ Set.range (𝖣.ι j) = Set.range (D.f i j ≫ 𝖣.ι _) := by
  ext x
  constructor
  · rintro ⟨⟨x₁, eq₁⟩, ⟨x₂, eq₂⟩⟩
    obtain ⟨⟨⟩⟩ | ⟨y, e₁, -⟩ := (D.ι_eq_iff_rel _ _ _ _).mp (eq₁.trans eq₂.symm)
    · exact ⟨inv (D.f i i) x₁, by
        -- Porting note: was `simp [eq₁]`
        -- See https://github.com/leanprover-community/mathlib4/issues/5026
        rw [TopCat.comp_app]
        

Proof state:
D : GlueData
i : D.J
x : (forget TopCat).obj (GlueData.glued D.toGlueData)
x₁ : (forget TopCat).obj (GlueData.U D.toGlueData i)
eq₁ eq₂ : (GlueData.ι D.toGlueData i) x₁ = x
⊢ (GlueData.ι D.toGlueData i) ((GlueData.f D.toGlueData i i) ((inv (GlueData.f D.toGlueData i i)) x₁)) = x

Next tactic:
erw [CategoryTheory.IsIso.inv_hom_id_apply]
theorem image_inter (i j : D.J) :
    Set.range (𝖣.ι i) ∩ Set.range (𝖣.ι j) = Set.range (D.f i j ≫ 𝖣.ι _) := by
  ext x
  constructor
  · rintro ⟨⟨x₁, eq₁⟩, ⟨x₂, eq₂⟩⟩
    obtain ⟨⟨⟩⟩ | ⟨y, e₁, -⟩ := (D.ι_eq_iff_rel _ _ _ _).mp (eq₁.trans eq₂.symm)
    · exact ⟨inv (D.f i i) x₁, by
        -- Porting note: was `simp [eq₁]`
        -- See https://github.com/leanprover-community/mathlib4/issues/5026
        rw [TopCat.comp_app]
        erw [CategoryTheory.IsIso.inv_hom_id_apply]
        

Proof state:
D : GlueData
i : D.J
x : (forget TopCat).obj (GlueData.glued D.toGlueData)
x₁ : (forget TopCat).obj (GlueData.U D.toGlueData i)
eq₁ eq₂ : (GlueData.ι D.toGlueData i) x₁ = x
⊢ (GlueData.ι D.toGlueData i) x₁ = x

Next tactic:
rw [eq₁]
theorem image_inter (i j : D.J) :
    Set.range (𝖣.ι i) ∩ Set.range (𝖣.ι j) = Set.range (D.f i j ≫ 𝖣.ι _) := by
  ext x
  constructor
  · rintro ⟨⟨x₁, eq₁⟩, ⟨x₂, eq₂⟩⟩
    obtain ⟨⟨⟩⟩ | ⟨y, e₁, -⟩ := (D.ι_eq_iff_rel _ _ _ _).mp (eq₁.trans eq₂.symm)
    · exact ⟨inv (D.f i i) x₁, by
        -- Porting note: was `simp [eq₁]`
        -- See https://github.com/leanprover-community/mathlib4/issues/5026
        rw [TopCat.comp_app]
        erw [CategoryTheory.IsIso.inv_hom_id_apply]
        rw [eq₁]⟩
    · -- Porting note: was
      -- dsimp only at *; substs e₁ eq₁; exact ⟨y, by simp⟩
      

Proof state:
case h.mp.intro.intro.intro.inr.intro.intro
D : GlueData
i j : D.J
x : (forget TopCat).obj (GlueData.glued D.toGlueData)
x₁ : (forget TopCat).obj (GlueData.U D.toGlueData i)
eq₁ : (GlueData.ι D.toGlueData i) x₁ = x
x₂ : (forget TopCat).obj (GlueData.U D.toGlueData j)
eq₂ : (GlueData.ι D.toGlueData j) x₂ = x
y : ↑(GlueData.V D.toGlueData ({ fst := i, snd := x₁ }.fst, { fst := j, snd := x₂ }.fst))
e₁ : (GlueData.f D.toGlueData { fst := i, snd := x₁ }.fst { fst := j, snd := x₂ }.fst) y = { fst := i, snd := x₁ }.snd
⊢ x ∈ Set.range ⇑(GlueData.f D.toGlueData i j ≫ GlueData.ι D.toGlueData i)

Next tactic:
dsimp only at *
theorem image_inter (i j : D.J) :
    Set.range (𝖣.ι i) ∩ Set.range (𝖣.ι j) = Set.range (D.f i j ≫ 𝖣.ι _) := by
  ext x
  constructor
  · rintro ⟨⟨x₁, eq₁⟩, ⟨x₂, eq₂⟩⟩
    obtain ⟨⟨⟩⟩ | ⟨y, e₁, -⟩ := (D.ι_eq_iff_rel _ _ _ _).mp (eq₁.trans eq₂.symm)
    · exact ⟨inv (D.f i i) x₁, by
        -- Porting note: was `simp [eq₁]`
        -- See https://github.com/leanprover-community/mathlib4/issues/5026
        rw [TopCat.comp_app]
        erw [CategoryTheory.IsIso.inv_hom_id_apply]
        rw [eq₁]⟩
    · -- Porting note: was
      -- dsimp only at *; substs e₁ eq₁; exact ⟨y, by simp⟩
      dsimp only at *
      

Proof state:
case h.mp.intro.intro.intro.inr.intro.intro
D : GlueData
i j : D.J
x : (forget TopCat).obj (GlueData.glued D.toGlueData)
x₁ : (forget TopCat).obj (GlueData.U D.toGlueData i)
eq₁ : (GlueData.ι D.toGlueData i) x₁ = x
x₂ : (forget TopCat).obj (GlueData.U D.toGlueData j)
eq₂ : (GlueData.ι D.toGlueData j) x₂ = x
y : ↑(GlueData.V D.toGlueData ({ fst := i, snd := x₁ }.fst, { fst := j, snd := x₂ }.fst))
e₁ : (GlueData.f D.toGlueData i j) y = x₁
⊢ x ∈ Set.range ⇑(GlueData.f D.toGlueData i j ≫ GlueData.ι D.toGlueData i)

Next tactic:
substs eq₁
theorem image_inter (i j : D.J) :
    Set.range (𝖣.ι i) ∩ Set.range (𝖣.ι j) = Set.range (D.f i j ≫ 𝖣.ι _) := by
  ext x
  constructor
  · rintro ⟨⟨x₁, eq₁⟩, ⟨x₂, eq₂⟩⟩
    obtain ⟨⟨⟩⟩ | ⟨y, e₁, -⟩ := (D.ι_eq_iff_rel _ _ _ _).mp (eq₁.trans eq₂.symm)
    · exact ⟨inv (D.f i i) x₁, by
        -- Porting note: was `simp [eq₁]`
        -- See https://github.com/leanprover-community/mathlib4/issues/5026
        rw [TopCat.comp_app]
        erw [CategoryTheory.IsIso.inv_hom_id_apply]
        rw [eq₁]⟩
    · -- Porting note: was
      -- dsimp only at *; substs e₁ eq₁; exact ⟨y, by simp⟩
      dsimp only at *
      substs eq₁
      

Proof state:
case h.mp.intro.intro.intro.inr.intro.intro
D : GlueData
i j : D.J
x₁ : (forget TopCat).obj (GlueData.U D.toGlueData i)
x₂ : (forget TopCat).obj (GlueData.U D.toGlueData j)
y : ↑(GlueData.V D.toGlueData ({ fst := i, snd := x₁ }.fst, { fst := j, snd := x₂ }.fst))
e₁ : (GlueData.f D.toGlueData i j) y = x₁
eq₂ : (GlueData.ι D.toGlueData j) x₂ = (GlueData.ι D.toGlueData i) x₁
⊢ (GlueData.ι D.toGlueData i) x₁ ∈ Set.range ⇑(GlueData.f D.toGlueData i j ≫ GlueData.ι D.toGlueData i)

Next tactic:
exact ⟨y, by simp [e₁]⟩
theorem image_inter (i j : D.J) :
    Set.range (𝖣.ι i) ∩ Set.range (𝖣.ι j) = Set.range (D.f i j ≫ 𝖣.ι _) := by
  ext x
  constructor
  · rintro ⟨⟨x₁, eq₁⟩, ⟨x₂, eq₂⟩⟩
    obtain ⟨⟨⟩⟩ | ⟨y, e₁, -⟩ := (D.ι_eq_iff_rel _ _ _ _).mp (eq₁.trans eq₂.symm)
    · exact ⟨inv (D.f i i) x₁, by
        -- Porting note: was `simp [eq₁]`
        -- See https://github.com/leanprover-community/mathlib4/issues/5026
        rw [TopCat.comp_app]
        erw [CategoryTheory.IsIso.inv_hom_id_apply]
        rw [eq₁]⟩
    · -- Porting note: was
      -- dsimp only at *; substs e₁ eq₁; exact ⟨y, by simp⟩
      dsimp only at *
      substs eq₁
      exact ⟨y, by 

Proof state:
D : GlueData
i j : D.J
x₁ : (forget TopCat).obj (GlueData.U D.toGlueData i)
x₂ : (forget TopCat).obj (GlueData.U D.toGlueData j)
y : ↑(GlueData.V D.toGlueData ({ fst := i, snd := x₁ }.fst, { fst := j, snd := x₂ }.fst))
e₁ : (GlueData.f D.toGlueData i j) y = x₁
eq₂ : (GlueData.ι D.toGlueData j) x₂ = (GlueData.ι D.toGlueData i) x₁
⊢ (GlueData.f D.toGlueData i j ≫ GlueData.ι D.toGlueData i) y = (GlueData.ι D.toGlueData i) x₁

Next tactic:
simp [e₁]
theorem image_inter (i j : D.J) :
    Set.range (𝖣.ι i) ∩ Set.range (𝖣.ι j) = Set.range (D.f i j ≫ 𝖣.ι _) := by
  ext x
  constructor
  · rintro ⟨⟨x₁, eq₁⟩, ⟨x₂, eq₂⟩⟩
    obtain ⟨⟨⟩⟩ | ⟨y, e₁, -⟩ := (D.ι_eq_iff_rel _ _ _ _).mp (eq₁.trans eq₂.symm)
    · exact ⟨inv (D.f i i) x₁, by
        -- Porting note: was `simp [eq₁]`
        -- See https://github.com/leanprover-community/mathlib4/issues/5026
        rw [TopCat.comp_app]
        erw [CategoryTheory.IsIso.inv_hom_id_apply]
        rw [eq₁]⟩
    · -- Porting note: was
      -- dsimp only at *; substs e₁ eq₁; exact ⟨y, by simp⟩
      dsimp only at *
      substs eq₁
      exact ⟨y, by simp [e₁]⟩
  · 

Proof state:
case h.mpr
D : GlueData
i j : D.J
x : (forget TopCat).obj (GlueData.glued D.toGlueData)
⊢ x ∈ Set.range ⇑(GlueData.f D.toGlueData i j ≫ GlueData.ι D.toGlueData i) →
    x ∈ Set.range ⇑(GlueData.ι D.toGlueData i) ∩ Set.range ⇑(GlueData.ι D.toGlueData j)

Next tactic:
rintro ⟨x, hx⟩
theorem image_inter (i j : D.J) :
    Set.range (𝖣.ι i) ∩ Set.range (𝖣.ι j) = Set.range (D.f i j ≫ 𝖣.ι _) := by
  ext x
  constructor
  · rintro ⟨⟨x₁, eq₁⟩, ⟨x₂, eq₂⟩⟩
    obtain ⟨⟨⟩⟩ | ⟨y, e₁, -⟩ := (D.ι_eq_iff_rel _ _ _ _).mp (eq₁.trans eq₂.symm)
    · exact ⟨inv (D.f i i) x₁, by
        -- Porting note: was `simp [eq₁]`
        -- See https://github.com/leanprover-community/mathlib4/issues/5026
        rw [TopCat.comp_app]
        erw [CategoryTheory.IsIso.inv_hom_id_apply]
        rw [eq₁]⟩
    · -- Porting note: was
      -- dsimp only at *; substs e₁ eq₁; exact ⟨y, by simp⟩
      dsimp only at *
      substs eq₁
      exact ⟨y, by simp [e₁]⟩
  · rintro ⟨x, hx⟩
    

Proof state:
case h.mpr.intro
D : GlueData
i j : D.J
x✝ : (forget TopCat).obj (GlueData.glued D.toGlueData)
x : (forget TopCat).obj (GlueData.V D.toGlueData (i, j))
hx : (GlueData.f D.toGlueData i j ≫ GlueData.ι D.toGlueData i) x = x✝
⊢ x✝ ∈ Set.range ⇑(GlueData.ι D.toGlueData i) ∩ Set.range ⇑(GlueData.ι D.toGlueData j)

Next tactic:
exact ⟨⟨D.f i j x, hx⟩, ⟨D.f j i (D.t _ _ x), by simp [← hx]⟩⟩
theorem image_inter (i j : D.J) :
    Set.range (𝖣.ι i) ∩ Set.range (𝖣.ι j) = Set.range (D.f i j ≫ 𝖣.ι _) := by
  ext x
  constructor
  · rintro ⟨⟨x₁, eq₁⟩, ⟨x₂, eq₂⟩⟩
    obtain ⟨⟨⟩⟩ | ⟨y, e₁, -⟩ := (D.ι_eq_iff_rel _ _ _ _).mp (eq₁.trans eq₂.symm)
    · exact ⟨inv (D.f i i) x₁, by
        -- Porting note: was `simp [eq₁]`
        -- See https://github.com/leanprover-community/mathlib4/issues/5026
        rw [TopCat.comp_app]
        erw [CategoryTheory.IsIso.inv_hom_id_apply]
        rw [eq₁]⟩
    · -- Porting note: was
      -- dsimp only at *; substs e₁ eq₁; exact ⟨y, by simp⟩
      dsimp only at *
      substs eq₁
      exact ⟨y, by simp [e₁]⟩
  · rintro ⟨x, hx⟩
    exact ⟨⟨D.f i j x, hx⟩, ⟨D.f j i (D.t _ _ x), by 

Proof state:
D : GlueData
i j : D.J
x✝ : (forget TopCat).obj (GlueData.glued D.toGlueData)
x : (forget TopCat).obj (GlueData.V D.toGlueData (i, j))
hx : (GlueData.f D.toGlueData i j ≫ GlueData.ι D.toGlueData i) x = x✝
⊢ (GlueData.ι D.toGlueData j) ((GlueData.f D.toGlueData j i) ((GlueData.t D.toGlueData i j) x)) = x✝

Next tactic:
simp [← hx]
theorem preimage_range (i j : D.J) : 𝖣.ι j ⁻¹' Set.range (𝖣.ι i) = Set.range (D.f j i) := by
  

Proof state:
D : GlueData
i j : D.J
⊢ ⇑(GlueData.ι D.toGlueData j) ⁻¹' Set.range ⇑(GlueData.ι D.toGlueData i) = Set.range ⇑(GlueData.f D.toGlueData j i)

Next tactic:
rw [← Set.preimage_image_eq (Set.range (D.f j i)) (D.ι_injective j), ← Set.image_univ, ←
    Set.image_univ, ← Set.image_comp, ← coe_comp, Set.image_univ, Set.image_univ, ← image_inter,
    Set.preimage_range_inter]
theorem preimage_image_eq_image (i j : D.J) (U : Set (𝖣.U i)) :
    𝖣.ι j ⁻¹' (𝖣.ι i '' U) = D.f _ _ '' ((D.t j i ≫ D.f _ _) ⁻¹' U) := by
  

Proof state:
D : GlueData
i j : D.J
U : Set ↑(GlueData.U D.toGlueData i)
⊢ ⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U) =
    ⇑(GlueData.f D.toGlueData j i) '' (⇑(GlueData.t D.toGlueData j i ≫ GlueData.f D.toGlueData i j) ⁻¹' U)

Next tactic:
have : D.f _ _ ⁻¹' (𝖣.ι j ⁻¹' (𝖣.ι i '' U)) = (D.t j i ≫ D.f _ _) ⁻¹' U := by
    ext x
    conv_rhs => rw [← Set.preimage_image_eq U (D.ι_injective _)]
    generalize 𝖣.ι i '' U = U'
    simp
theorem preimage_image_eq_image (i j : D.J) (U : Set (𝖣.U i)) :
    𝖣.ι j ⁻¹' (𝖣.ι i '' U) = D.f _ _ '' ((D.t j i ≫ D.f _ _) ⁻¹' U) := by
  have : D.f _ _ ⁻¹' (𝖣.ι j ⁻¹' (𝖣.ι i '' U)) = (D.t j i ≫ D.f _ _) ⁻¹' U := by
    

Proof state:
D : GlueData
i j : D.J
U : Set ↑(GlueData.U D.toGlueData i)
⊢ ⇑(GlueData.f D.toGlueData j i) ⁻¹' (⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U)) =
    ⇑(GlueData.t D.toGlueData j i ≫ GlueData.f D.toGlueData i j) ⁻¹' U

Next tactic:
ext x
theorem preimage_image_eq_image (i j : D.J) (U : Set (𝖣.U i)) :
    𝖣.ι j ⁻¹' (𝖣.ι i '' U) = D.f _ _ '' ((D.t j i ≫ D.f _ _) ⁻¹' U) := by
  have : D.f _ _ ⁻¹' (𝖣.ι j ⁻¹' (𝖣.ι i '' U)) = (D.t j i ≫ D.f _ _) ⁻¹' U := by
    ext x
    

Proof state:
case h
D : GlueData
i j : D.J
U : Set ↑(GlueData.U D.toGlueData i)
x : (forget TopCat).obj (GlueData.V D.toGlueData (j, i))
⊢ x ∈ ⇑(GlueData.f D.toGlueData j i) ⁻¹' (⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U)) ↔
    x ∈ ⇑(GlueData.t D.toGlueData j i ≫ GlueData.f D.toGlueData i j) ⁻¹' U

Next tactic:
conv_rhs => rw [← Set.preimage_image_eq U (D.ι_injective _)]
theorem preimage_image_eq_image (i j : D.J) (U : Set (𝖣.U i)) :
    𝖣.ι j ⁻¹' (𝖣.ι i '' U) = D.f _ _ '' ((D.t j i ≫ D.f _ _) ⁻¹' U) := by
  have : D.f _ _ ⁻¹' (𝖣.ι j ⁻¹' (𝖣.ι i '' U)) = (D.t j i ≫ D.f _ _) ⁻¹' U := by
    ext x
    conv_rhs => 

Proof state:
D : GlueData
i j : D.J
U : Set ↑(GlueData.U D.toGlueData i)
x : (forget TopCat).obj (GlueData.V D.toGlueData (j, i))
| x ∈ ⇑(GlueData.t D.toGlueData j i ≫ GlueData.f D.toGlueData i j) ⁻¹' U

Next tactic:
rw [← Set.preimage_image_eq U (D.ι_injective _)]
theorem preimage_image_eq_image (i j : D.J) (U : Set (𝖣.U i)) :
    𝖣.ι j ⁻¹' (𝖣.ι i '' U) = D.f _ _ '' ((D.t j i ≫ D.f _ _) ⁻¹' U) := by
  have : D.f _ _ ⁻¹' (𝖣.ι j ⁻¹' (𝖣.ι i '' U)) = (D.t j i ≫ D.f _ _) ⁻¹' U := by
    ext x
    conv_rhs => rw [← Set.preimage_image_eq U (D.ι_injective _)]
    

Proof state:
case h
D : GlueData
i j : D.J
U : Set ↑(GlueData.U D.toGlueData i)
x : (forget TopCat).obj (GlueData.V D.toGlueData (j, i))
⊢ x ∈ ⇑(GlueData.f D.toGlueData j i) ⁻¹' (⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U)) ↔
    x ∈
      ⇑(GlueData.t D.toGlueData j i ≫ GlueData.f D.toGlueData i j) ⁻¹'
        (⇑(GlueData.ι D.toGlueData i) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U))

Next tactic:
generalize 𝖣.ι i '' U = U'
theorem preimage_image_eq_image (i j : D.J) (U : Set (𝖣.U i)) :
    𝖣.ι j ⁻¹' (𝖣.ι i '' U) = D.f _ _ '' ((D.t j i ≫ D.f _ _) ⁻¹' U) := by
  have : D.f _ _ ⁻¹' (𝖣.ι j ⁻¹' (𝖣.ι i '' U)) = (D.t j i ≫ D.f _ _) ⁻¹' U := by
    ext x
    conv_rhs => rw [← Set.preimage_image_eq U (D.ι_injective _)]
    generalize 𝖣.ι i '' U = U'
    

Proof state:
case h
D : GlueData
i j : D.J
U : Set ↑(GlueData.U D.toGlueData i)
x : (forget TopCat).obj (GlueData.V D.toGlueData (j, i))
U' : Set ((forget TopCat).obj (GlueData.glued D.toGlueData))
⊢ x ∈ ⇑(GlueData.f D.toGlueData j i) ⁻¹' (⇑(GlueData.ι D.toGlueData j) ⁻¹' U') ↔
    x ∈ ⇑(GlueData.t D.toGlueData j i ≫ GlueData.f D.toGlueData i j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) ⁻¹' U')

Next tactic:
simp
theorem preimage_image_eq_image (i j : D.J) (U : Set (𝖣.U i)) :
    𝖣.ι j ⁻¹' (𝖣.ι i '' U) = D.f _ _ '' ((D.t j i ≫ D.f _ _) ⁻¹' U) := by
  have : D.f _ _ ⁻¹' (𝖣.ι j ⁻¹' (𝖣.ι i '' U)) = (D.t j i ≫ D.f _ _) ⁻¹' U := by
    ext x
    conv_rhs => rw [← Set.preimage_image_eq U (D.ι_injective _)]
    generalize 𝖣.ι i '' U = U'
    simp
  

Proof state:
D : GlueData
i j : D.J
U : Set ↑(GlueData.U D.toGlueData i)
this :
  ⇑(GlueData.f D.toGlueData j i) ⁻¹' (⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U)) =
    ⇑(GlueData.t D.toGlueData j i ≫ GlueData.f D.toGlueData i j) ⁻¹' U
⊢ ⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U) =
    ⇑(GlueData.f D.toGlueData j i) '' (⇑(GlueData.t D.toGlueData j i ≫ GlueData.f D.toGlueData i j) ⁻¹' U)

Next tactic:
rw [← this, Set.image_preimage_eq_inter_range]
theorem preimage_image_eq_image (i j : D.J) (U : Set (𝖣.U i)) :
    𝖣.ι j ⁻¹' (𝖣.ι i '' U) = D.f _ _ '' ((D.t j i ≫ D.f _ _) ⁻¹' U) := by
  have : D.f _ _ ⁻¹' (𝖣.ι j ⁻¹' (𝖣.ι i '' U)) = (D.t j i ≫ D.f _ _) ⁻¹' U := by
    ext x
    conv_rhs => rw [← Set.preimage_image_eq U (D.ι_injective _)]
    generalize 𝖣.ι i '' U = U'
    simp
  rw [← this, Set.image_preimage_eq_inter_range]
  

Proof state:
D : GlueData
i j : D.J
U : Set ↑(GlueData.U D.toGlueData i)
this :
  ⇑(GlueData.f D.toGlueData j i) ⁻¹' (⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U)) =
    ⇑(GlueData.t D.toGlueData j i ≫ GlueData.f D.toGlueData i j) ⁻¹' U
⊢ ⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U) =
    ⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U) ∩ Set.range ⇑(GlueData.f D.toGlueData j i)

Next tactic:
symm
theorem preimage_image_eq_image (i j : D.J) (U : Set (𝖣.U i)) :
    𝖣.ι j ⁻¹' (𝖣.ι i '' U) = D.f _ _ '' ((D.t j i ≫ D.f _ _) ⁻¹' U) := by
  have : D.f _ _ ⁻¹' (𝖣.ι j ⁻¹' (𝖣.ι i '' U)) = (D.t j i ≫ D.f _ _) ⁻¹' U := by
    ext x
    conv_rhs => rw [← Set.preimage_image_eq U (D.ι_injective _)]
    generalize 𝖣.ι i '' U = U'
    simp
  rw [← this, Set.image_preimage_eq_inter_range]
  symm
  

Proof state:
D : GlueData
i j : D.J
U : Set ↑(GlueData.U D.toGlueData i)
this :
  ⇑(GlueData.f D.toGlueData j i) ⁻¹' (⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U)) =
    ⇑(GlueData.t D.toGlueData j i ≫ GlueData.f D.toGlueData i j) ⁻¹' U
⊢ ⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U) ∩ Set.range ⇑(GlueData.f D.toGlueData j i) =
    ⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U)

Next tactic:
apply Set.inter_eq_self_of_subset_left
theorem preimage_image_eq_image (i j : D.J) (U : Set (𝖣.U i)) :
    𝖣.ι j ⁻¹' (𝖣.ι i '' U) = D.f _ _ '' ((D.t j i ≫ D.f _ _) ⁻¹' U) := by
  have : D.f _ _ ⁻¹' (𝖣.ι j ⁻¹' (𝖣.ι i '' U)) = (D.t j i ≫ D.f _ _) ⁻¹' U := by
    ext x
    conv_rhs => rw [← Set.preimage_image_eq U (D.ι_injective _)]
    generalize 𝖣.ι i '' U = U'
    simp
  rw [← this, Set.image_preimage_eq_inter_range]
  symm
  apply Set.inter_eq_self_of_subset_left
  

Proof state:
case a
D : GlueData
i j : D.J
U : Set ↑(GlueData.U D.toGlueData i)
this :
  ⇑(GlueData.f D.toGlueData j i) ⁻¹' (⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U)) =
    ⇑(GlueData.t D.toGlueData j i ≫ GlueData.f D.toGlueData i j) ⁻¹' U
⊢ ⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U) ⊆ Set.range ⇑(GlueData.f D.toGlueData j i)

Next tactic:
rw [← D.preimage_range i j]
theorem preimage_image_eq_image (i j : D.J) (U : Set (𝖣.U i)) :
    𝖣.ι j ⁻¹' (𝖣.ι i '' U) = D.f _ _ '' ((D.t j i ≫ D.f _ _) ⁻¹' U) := by
  have : D.f _ _ ⁻¹' (𝖣.ι j ⁻¹' (𝖣.ι i '' U)) = (D.t j i ≫ D.f _ _) ⁻¹' U := by
    ext x
    conv_rhs => rw [← Set.preimage_image_eq U (D.ι_injective _)]
    generalize 𝖣.ι i '' U = U'
    simp
  rw [← this, Set.image_preimage_eq_inter_range]
  symm
  apply Set.inter_eq_self_of_subset_left
  rw [← D.preimage_range i j]
  

Proof state:
case a
D : GlueData
i j : D.J
U : Set ↑(GlueData.U D.toGlueData i)
this :
  ⇑(GlueData.f D.toGlueData j i) ⁻¹' (⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U)) =
    ⇑(GlueData.t D.toGlueData j i ≫ GlueData.f D.toGlueData i j) ⁻¹' U
⊢ ⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U) ⊆
    ⇑(GlueData.ι D.toGlueData j) ⁻¹' Set.range ⇑(GlueData.ι D.toGlueData i)

Next tactic:
exact Set.preimage_mono (Set.image_subset_range _ _)
theorem preimage_image_eq_image' (i j : D.J) (U : Set (𝖣.U i)) :
    𝖣.ι j ⁻¹' (𝖣.ι i '' U) = (D.t i j ≫ D.f _ _) '' (D.f _ _ ⁻¹' U) := by
  

Proof state:
D : GlueData
i j : D.J
U : Set ↑(GlueData.U D.toGlueData i)
⊢ ⇑(GlueData.ι D.toGlueData j) ⁻¹' (⇑(GlueData.ι D.toGlueData i) '' U) =
    ⇑(GlueData.t D.toGlueData i j ≫ GlueData.f D.toGlueData j i) '' (⇑(GlueData.f D.toGlueData i j) ⁻¹' U)

Next tactic:
convert D.preimage_image_eq_image i j U using 1