l3lab/ntp-mathlib huggingface dataset:
/-- The image of an open set in the source is open. -/
theorem image_isOpen_of_isOpen {s : Set α} (hs : IsOpen s) (h : s ⊆ e.source) :
    IsOpen (e '' s) := by
  have : e '' s = e.target ∩ e.symm ⁻¹' s := e.toPartialEquiv.image_eq_target_inter_inv_preimage h
  rw [this]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set α
hs : IsOpen s
h : s ⊆ e.source
this : ↑e '' s = e.target ∩ ↑(PartialHomeomorph.symm e) ⁻¹' s
⊢ IsOpen (e.target ∩ ↑(PartialHomeomorph.symm e) ⁻¹' s)

Next tactic:
exact e.continuousOn_symm.isOpen_inter_preimage e.open_target hs
/-- A `PartialEquiv` with continuous open forward map and open source is a `PartialHomeomorph`. -/
def ofContinuousOpenRestrict (e : PartialEquiv α β) (hc : ContinuousOn e e.source)
    (ho : IsOpenMap (e.source.restrict e)) (hs : IsOpen e.source) : PartialHomeomorph α β where
  toPartialEquiv := e
  open_source := hs
  open_target := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e✝ : PartialHomeomorph α β
e' : PartialHomeomorph β γ
e : PartialEquiv α β
hc : ContinuousOn (↑e) e.source
ho : IsOpenMap (restrict e.source ↑e)
hs : IsOpen e.source
⊢ IsOpen e.target

Next tactic:
simpa only [range_restrict, e.image_source_eq_target] using ho.isOpen_range
theorem restr_source' (s : Set α) (hs : IsOpen s) : (e.restr s).source = e.source ∩ s := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set α
hs : IsOpen s
⊢ (PartialHomeomorph.restr e s).toPartialEquiv.source = e.source ∩ s

Next tactic:
rw [e.restr_source, hs.interior_eq]
theorem restr_toPartialEquiv' (s : Set α) (hs : IsOpen s) :
    (e.restr s).toPartialEquiv = e.toPartialEquiv.restr s := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set α
hs : IsOpen s
⊢ (PartialHomeomorph.restr e s).toPartialEquiv = PartialEquiv.restr e.toPartialEquiv s

Next tactic:
rw [e.restr_toPartialEquiv, hs.interior_eq]
theorem restr_source_inter (s : Set α) : e.restr (e.source ∩ s) = e.restr s := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set α
⊢ PartialHomeomorph.restr e (e.source ∩ s) = PartialHomeomorph.restr e s

Next tactic:
refine' PartialHomeomorph.ext _ _ (fun x => rfl) (fun x => rfl) _
theorem restr_source_inter (s : Set α) : e.restr (e.source ∩ s) = e.restr s := by
  refine' PartialHomeomorph.ext _ _ (fun x => rfl) (fun x => rfl) _
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set α
⊢ (PartialHomeomorph.restr e (e.source ∩ s)).toPartialEquiv.source = (PartialHomeomorph.restr e s).toPartialEquiv.source

Next tactic:
simp [e.open_source.interior_eq, ← inter_assoc]
@[simp, mfld_simps]
theorem ofSet_univ_eq_refl : ofSet univ isOpen_univ = PartialHomeomorph.refl α := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set α
hs : IsOpen s
⊢ ofSet univ (_ : IsOpen univ) = PartialHomeomorph.refl α

Next tactic:
ext
@[simp, mfld_simps]
theorem ofSet_univ_eq_refl : ofSet univ isOpen_univ = PartialHomeomorph.refl α := by ext <;> 

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set α
hs : IsOpen s
x✝ : α
⊢ ↑(ofSet univ (_ : IsOpen univ)) x✝ = ↑(PartialHomeomorph.refl α) x✝

Next tactic:
simp
@[simp, mfld_simps]
theorem ofSet_univ_eq_refl : ofSet univ isOpen_univ = PartialHomeomorph.refl α := by ext <;> 

Proof state:
case hinv
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set α
hs : IsOpen s
x✝ : α
⊢ ↑(PartialHomeomorph.symm (ofSet univ (_ : IsOpen univ))) x✝ = ↑(PartialHomeomorph.symm (PartialHomeomorph.refl α)) x✝

Next tactic:
simp
@[simp, mfld_simps]
theorem ofSet_univ_eq_refl : ofSet univ isOpen_univ = PartialHomeomorph.refl α := by ext <;> 

Proof state:
case hs.h
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set α
hs : IsOpen s
x✝ : α
⊢ x✝ ∈ (ofSet univ (_ : IsOpen univ)).toPartialEquiv.source ↔ x✝ ∈ (PartialHomeomorph.refl α).toPartialEquiv.source

Next tactic:
simp
/-- Composing two partial homeomorphisms, by restricting to the maximal domain where their
composition is well defined. -/
protected def trans : PartialHomeomorph α γ :=
  PartialHomeomorph.trans' (e.symm.restrOpen e'.source e'.open_source).symm
    (e'.restrOpen e.target e.open_target) (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
⊢ (PartialHomeomorph.symm
          (PartialHomeomorph.restrOpen (PartialHomeomorph.symm e) e'.source
            (_ : IsOpen e'.source))).toPartialEquiv.target =
    (PartialHomeomorph.restrOpen e' e.target (_ : IsOpen e.target)).toPartialEquiv.source

Next tactic:
simp [inter_comm]
theorem trans_ofSet {s : Set β} (hs : IsOpen s) : e.trans (ofSet s hs) = e.restr (e ⁻¹' s) :=
  PartialHomeomorph.ext _ _ (fun _ => rfl) (fun _ => rfl) <| by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set β
hs : IsOpen s
⊢ (PartialHomeomorph.trans e (ofSet s hs)).toPartialEquiv.source =
    (PartialHomeomorph.restr e (↑e ⁻¹' s)).toPartialEquiv.source

Next tactic:
rw [trans_source, restr_source, ofSet_source, ← preimage_interior, hs.interior_eq]
theorem trans_of_set' {s : Set β} (hs : IsOpen s) :
    e.trans (ofSet s hs) = e.restr (e.source ∩ e ⁻¹' s) := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set β
hs : IsOpen s
⊢ PartialHomeomorph.trans e (ofSet s hs) = PartialHomeomorph.restr e (e.source ∩ ↑e ⁻¹' s)

Next tactic:
rw [trans_ofSet, restr_source_inter]
theorem ofSet_trans {s : Set α} (hs : IsOpen s) : (ofSet s hs).trans e = e.restr s :=
  PartialHomeomorph.ext _ _ (fun x => rfl) (fun x => rfl) <| by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set α
hs : IsOpen s
⊢ (PartialHomeomorph.trans (ofSet s hs) e).toPartialEquiv.source = (PartialHomeomorph.restr e s).toPartialEquiv.source

Next tactic:
simp [hs.interior_eq, inter_comm]
theorem ofSet_trans' {s : Set α} (hs : IsOpen s) :
    (ofSet s hs).trans e = e.restr (e.source ∩ s) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set α
hs : IsOpen s
⊢ PartialHomeomorph.trans (ofSet s hs) e = PartialHomeomorph.restr e (e.source ∩ s)

Next tactic:
rw [ofSet_trans, restr_source_inter]
@[simp, mfld_simps]
theorem ofSet_trans_ofSet {s : Set α} (hs : IsOpen s) {s' : Set α} (hs' : IsOpen s') :
    (ofSet s hs).trans (ofSet s' hs') = ofSet (s ∩ s') (IsOpen.inter hs hs') := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set α
hs : IsOpen s
s' : Set α
hs' : IsOpen s'
⊢ PartialHomeomorph.trans (ofSet s hs) (ofSet s' hs') = ofSet (s ∩ s') (_ : IsOpen (s ∩ s'))

Next tactic:
rw [(ofSet s hs).trans_ofSet hs']
@[simp, mfld_simps]
theorem ofSet_trans_ofSet {s : Set α} (hs : IsOpen s) {s' : Set α} (hs' : IsOpen s') :
    (ofSet s hs).trans (ofSet s' hs') = ofSet (s ∩ s') (IsOpen.inter hs hs') := by
  rw [(ofSet s hs).trans_ofSet hs']
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set α
hs : IsOpen s
s' : Set α
hs' : IsOpen s'
⊢ PartialHomeomorph.restr (ofSet s hs) (↑(ofSet s hs) ⁻¹' s') = ofSet (s ∩ s') (_ : IsOpen (s ∩ s'))

Next tactic:
ext
@[simp, mfld_simps]
theorem ofSet_trans_ofSet {s : Set α} (hs : IsOpen s) {s' : Set α} (hs' : IsOpen s') :
    (ofSet s hs).trans (ofSet s' hs') = ofSet (s ∩ s') (IsOpen.inter hs hs') := by
  rw [(ofSet s hs).trans_ofSet hs']
  ext <;> 

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set α
hs : IsOpen s
s' : Set α
hs' : IsOpen s'
x✝ : α
⊢ ↑(PartialHomeomorph.restr (ofSet s hs) (↑(ofSet s hs) ⁻¹' s')) x✝ = ↑(ofSet (s ∩ s') (_ : IsOpen (s ∩ s'))) x✝

Next tactic:
simp [hs'.interior_eq]
@[simp, mfld_simps]
theorem ofSet_trans_ofSet {s : Set α} (hs : IsOpen s) {s' : Set α} (hs' : IsOpen s') :
    (ofSet s hs).trans (ofSet s' hs') = ofSet (s ∩ s') (IsOpen.inter hs hs') := by
  rw [(ofSet s hs).trans_ofSet hs']
  ext <;> 

Proof state:
case hinv
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set α
hs : IsOpen s
s' : Set α
hs' : IsOpen s'
x✝ : α
⊢ ↑(PartialHomeomorph.symm (PartialHomeomorph.restr (ofSet s hs) (↑(ofSet s hs) ⁻¹' s'))) x✝ =
    ↑(PartialHomeomorph.symm (ofSet (s ∩ s') (_ : IsOpen (s ∩ s')))) x✝

Next tactic:
simp [hs'.interior_eq]
@[simp, mfld_simps]
theorem ofSet_trans_ofSet {s : Set α} (hs : IsOpen s) {s' : Set α} (hs' : IsOpen s') :
    (ofSet s hs).trans (ofSet s' hs') = ofSet (s ∩ s') (IsOpen.inter hs hs') := by
  rw [(ofSet s hs).trans_ofSet hs']
  ext <;> 

Proof state:
case hs.h
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
s : Set α
hs : IsOpen s
s' : Set α
hs' : IsOpen s'
x✝ : α
⊢ x✝ ∈ (PartialHomeomorph.restr (ofSet s hs) (↑(ofSet s hs) ⁻¹' s')).toPartialEquiv.source ↔
    x✝ ∈ (ofSet (s ∩ s') (_ : IsOpen (s ∩ s'))).toPartialEquiv.source

Next tactic:
simp [hs'.interior_eq]
theorem Set.EqOn.restr_eqOn_source {e e' : PartialHomeomorph α β}
    (h : EqOn e e' (e.source ∩ e'.source)) : e.restr e'.source ≈ e'.restr e.source := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e✝ : PartialHomeomorph α β
e'✝ : PartialHomeomorph β γ
e e' : PartialHomeomorph α β
h : EqOn (↑e) (↑e') (e.source ∩ e'.source)
⊢ PartialHomeomorph.restr e e'.source ≈ PartialHomeomorph.restr e' e.source

Next tactic:
constructor
theorem Set.EqOn.restr_eqOn_source {e e' : PartialHomeomorph α β}
    (h : EqOn e e' (e.source ∩ e'.source)) : e.restr e'.source ≈ e'.restr e.source := by
  constructor
  · 

Proof state:
case left
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e✝ : PartialHomeomorph α β
e'✝ : PartialHomeomorph β γ
e e' : PartialHomeomorph α β
h : EqOn (↑e) (↑e') (e.source ∩ e'.source)
⊢ (PartialHomeomorph.restr e e'.source).toPartialEquiv.source =
    (PartialHomeomorph.restr e' e.source).toPartialEquiv.source

Next tactic:
rw [e'.restr_source' _ e.open_source]
theorem Set.EqOn.restr_eqOn_source {e e' : PartialHomeomorph α β}
    (h : EqOn e e' (e.source ∩ e'.source)) : e.restr e'.source ≈ e'.restr e.source := by
  constructor
  · rw [e'.restr_source' _ e.open_source]
    

Proof state:
case left
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e✝ : PartialHomeomorph α β
e'✝ : PartialHomeomorph β γ
e e' : PartialHomeomorph α β
h : EqOn (↑e) (↑e') (e.source ∩ e'.source)
⊢ (PartialHomeomorph.restr e e'.source).toPartialEquiv.source = e'.source ∩ e.source

Next tactic:
rw [e.restr_source' _ e'.open_source]
theorem Set.EqOn.restr_eqOn_source {e e' : PartialHomeomorph α β}
    (h : EqOn e e' (e.source ∩ e'.source)) : e.restr e'.source ≈ e'.restr e.source := by
  constructor
  · rw [e'.restr_source' _ e.open_source]
    rw [e.restr_source' _ e'.open_source]
    

Proof state:
case left
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e✝ : PartialHomeomorph α β
e'✝ : PartialHomeomorph β γ
e e' : PartialHomeomorph α β
h : EqOn (↑e) (↑e') (e.source ∩ e'.source)
⊢ e.source ∩ e'.source = e'.source ∩ e.source

Next tactic:
exact Set.inter_comm _ _
theorem Set.EqOn.restr_eqOn_source {e e' : PartialHomeomorph α β}
    (h : EqOn e e' (e.source ∩ e'.source)) : e.restr e'.source ≈ e'.restr e.source := by
  constructor
  · rw [e'.restr_source' _ e.open_source]
    rw [e.restr_source' _ e'.open_source]
    exact Set.inter_comm _ _
  · 

Proof state:
case right
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e✝ : PartialHomeomorph α β
e'✝ : PartialHomeomorph β γ
e e' : PartialHomeomorph α β
h : EqOn (↑e) (↑e') (e.source ∩ e'.source)
⊢ EqOn (↑(PartialHomeomorph.restr e e'.source)) (↑(PartialHomeomorph.restr e' e.source))
    (PartialHomeomorph.restr e e'.source).toPartialEquiv.source

Next tactic:
rw [e.restr_source' _ e'.open_source]
theorem Set.EqOn.restr_eqOn_source {e e' : PartialHomeomorph α β}
    (h : EqOn e e' (e.source ∩ e'.source)) : e.restr e'.source ≈ e'.restr e.source := by
  constructor
  · rw [e'.restr_source' _ e.open_source]
    rw [e.restr_source' _ e'.open_source]
    exact Set.inter_comm _ _
  · rw [e.restr_source' _ e'.open_source]
    

Proof state:
case right
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e✝ : PartialHomeomorph α β
e'✝ : PartialHomeomorph β γ
e e' : PartialHomeomorph α β
h : EqOn (↑e) (↑e') (e.source ∩ e'.source)
⊢ EqOn (↑(PartialHomeomorph.restr e e'.source)) (↑(PartialHomeomorph.restr e' e.source)) (e.source ∩ e'.source)

Next tactic:
refine' (EqOn.trans _ h).trans _
theorem Set.EqOn.restr_eqOn_source {e e' : PartialHomeomorph α β}
    (h : EqOn e e' (e.source ∩ e'.source)) : e.restr e'.source ≈ e'.restr e.source := by
  constructor
  · rw [e'.restr_source' _ e.open_source]
    rw [e.restr_source' _ e'.open_source]
    exact Set.inter_comm _ _
  · rw [e.restr_source' _ e'.open_source]
    refine' (EqOn.trans _ h).trans _ <;> 

Proof state:
case right.refine'_1
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e✝ : PartialHomeomorph α β
e'✝ : PartialHomeomorph β γ
e e' : PartialHomeomorph α β
h : EqOn (↑e) (↑e') (e.source ∩ e'.source)
⊢ EqOn (↑(PartialHomeomorph.restr e e'.source)) (↑e) (e.source ∩ e'.source)

Next tactic:
simp only [mfld_simps, eqOn_refl]
theorem Set.EqOn.restr_eqOn_source {e e' : PartialHomeomorph α β}
    (h : EqOn e e' (e.source ∩ e'.source)) : e.restr e'.source ≈ e'.restr e.source := by
  constructor
  · rw [e'.restr_source' _ e.open_source]
    rw [e.restr_source' _ e'.open_source]
    exact Set.inter_comm _ _
  · rw [e.restr_source' _ e'.open_source]
    refine' (EqOn.trans _ h).trans _ <;> 

Proof state:
case right.refine'_2
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e✝ : PartialHomeomorph α β
e'✝ : PartialHomeomorph β γ
e e' : PartialHomeomorph α β
h : EqOn (↑e) (↑e') (e.source ∩ e'.source)
⊢ EqOn (↑e') (↑(PartialHomeomorph.restr e' e.source)) (e.source ∩ e'.source)

Next tactic:
simp only [mfld_simps, eqOn_refl]
theorem prod_eq_prod_of_nonempty {e₁ e₁' : PartialHomeomorph α β} {e₂ e₂' : PartialHomeomorph γ δ}
    (h : (e₁.prod e₂).source.Nonempty) : e₁.prod e₂ = e₁'.prod e₂' ↔ e₁ = e₁' ∧ e₂ = e₂' := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
e₁ e₁' : PartialHomeomorph α β
e₂ e₂' : PartialHomeomorph γ δ
h : Set.Nonempty (prod e₁ e₂).toPartialEquiv.source
⊢ prod e₁ e₂ = prod e₁' e₂' ↔ e₁ = e₁' ∧ e₂ = e₂'

Next tactic:
obtain ⟨⟨x, y⟩, -⟩ := id h
theorem prod_eq_prod_of_nonempty {e₁ e₁' : PartialHomeomorph α β} {e₂ e₂' : PartialHomeomorph γ δ}
    (h : (e₁.prod e₂).source.Nonempty) : e₁.prod e₂ = e₁'.prod e₂' ↔ e₁ = e₁' ∧ e₂ = e₂' := by
  obtain ⟨⟨x, y⟩, -⟩ := id h
  

Proof state:
case intro.mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
e₁ e₁' : PartialHomeomorph α β
e₂ e₂' : PartialHomeomorph γ δ
h : Set.Nonempty (prod e₁ e₂).toPartialEquiv.source
x : α
y : γ
⊢ prod e₁ e₂ = prod e₁' e₂' ↔ e₁ = e₁' ∧ e₂ = e₂'

Next tactic:
haveI : Nonempty α := ⟨x⟩
theorem prod_eq_prod_of_nonempty {e₁ e₁' : PartialHomeomorph α β} {e₂ e₂' : PartialHomeomorph γ δ}
    (h : (e₁.prod e₂).source.Nonempty) : e₁.prod e₂ = e₁'.prod e₂' ↔ e₁ = e₁' ∧ e₂ = e₂' := by
  obtain ⟨⟨x, y⟩, -⟩ := id h
  haveI : Nonempty α := ⟨x⟩
  

Proof state:
case intro.mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
e₁ e₁' : PartialHomeomorph α β
e₂ e₂' : PartialHomeomorph γ δ
h : Set.Nonempty (prod e₁ e₂).toPartialEquiv.source
x : α
y : γ
this : Nonempty α
⊢ prod e₁ e₂ = prod e₁' e₂' ↔ e₁ = e₁' ∧ e₂ = e₂'

Next tactic:
haveI : Nonempty β := ⟨e₁ x⟩
theorem prod_eq_prod_of_nonempty {e₁ e₁' : PartialHomeomorph α β} {e₂ e₂' : PartialHomeomorph γ δ}
    (h : (e₁.prod e₂).source.Nonempty) : e₁.prod e₂ = e₁'.prod e₂' ↔ e₁ = e₁' ∧ e₂ = e₂' := by
  obtain ⟨⟨x, y⟩, -⟩ := id h
  haveI : Nonempty α := ⟨x⟩
  haveI : Nonempty β := ⟨e₁ x⟩
  

Proof state:
case intro.mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
e₁ e₁' : PartialHomeomorph α β
e₂ e₂' : PartialHomeomorph γ δ
h : Set.Nonempty (prod e₁ e₂).toPartialEquiv.source
x : α
y : γ
this✝ : Nonempty α
this : Nonempty β
⊢ prod e₁ e₂ = prod e₁' e₂' ↔ e₁ = e₁' ∧ e₂ = e₂'

Next tactic:
haveI : Nonempty γ := ⟨y⟩
theorem prod_eq_prod_of_nonempty {e₁ e₁' : PartialHomeomorph α β} {e₂ e₂' : PartialHomeomorph γ δ}
    (h : (e₁.prod e₂).source.Nonempty) : e₁.prod e₂ = e₁'.prod e₂' ↔ e₁ = e₁' ∧ e₂ = e₂' := by
  obtain ⟨⟨x, y⟩, -⟩ := id h
  haveI : Nonempty α := ⟨x⟩
  haveI : Nonempty β := ⟨e₁ x⟩
  haveI : Nonempty γ := ⟨y⟩
  

Proof state:
case intro.mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
e₁ e₁' : PartialHomeomorph α β
e₂ e₂' : PartialHomeomorph γ δ
h : Set.Nonempty (prod e₁ e₂).toPartialEquiv.source
x : α
y : γ
this✝¹ : Nonempty α
this✝ : Nonempty β
this : Nonempty γ
⊢ prod e₁ e₂ = prod e₁' e₂' ↔ e₁ = e₁' ∧ e₂ = e₂'

Next tactic:
haveI : Nonempty δ := ⟨e₂ y⟩
theorem prod_eq_prod_of_nonempty {e₁ e₁' : PartialHomeomorph α β} {e₂ e₂' : PartialHomeomorph γ δ}
    (h : (e₁.prod e₂).source.Nonempty) : e₁.prod e₂ = e₁'.prod e₂' ↔ e₁ = e₁' ∧ e₂ = e₂' := by
  obtain ⟨⟨x, y⟩, -⟩ := id h
  haveI : Nonempty α := ⟨x⟩
  haveI : Nonempty β := ⟨e₁ x⟩
  haveI : Nonempty γ := ⟨y⟩
  haveI : Nonempty δ := ⟨e₂ y⟩
  

Proof state:
case intro.mk
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
e₁ e₁' : PartialHomeomorph α β
e₂ e₂' : PartialHomeomorph γ δ
h : Set.Nonempty (prod e₁ e₂).toPartialEquiv.source
x : α
y : γ
this✝² : Nonempty α
this✝¹ : Nonempty β
this✝ : Nonempty γ
this : Nonempty δ
⊢ prod e₁ e₂ = prod e₁' e₂' ↔ e₁ = e₁' ∧ e₂ = e₂'

Next tactic:
simp_rw [PartialHomeomorph.ext_iff, prod_apply, prod_symm_apply, prod_source, Prod.ext_iff,
    Set.prod_eq_prod_iff_of_nonempty h, forall_and, Prod.forall, forall_const,
    and_assoc, and_left_comm]
theorem prod_eq_prod_of_nonempty' {e₁ e₁' : PartialHomeomorph α β} {e₂ e₂' : PartialHomeomorph γ δ}
    (h : (e₁'.prod e₂').source.Nonempty) : e₁.prod e₂ = e₁'.prod e₂' ↔ e₁ = e₁' ∧ e₂ = e₂' := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : TopologicalSpace α
inst✝² : TopologicalSpace β
inst✝¹ : TopologicalSpace γ
inst✝ : TopologicalSpace δ
e : PartialHomeomorph α β
e' : PartialHomeomorph β γ
e₁ e₁' : PartialHomeomorph α β
e₂ e₂' : PartialHomeomorph γ δ
h : Set.Nonempty (prod e₁' e₂').toPartialEquiv.source
⊢ prod e₁ e₂ = prod e₁' e₂' ↔ e₁ = e₁' ∧ e₂ = e₂'

Next tactic:
rw [eq_comm, prod_eq_prod_of_nonempty h, eq_comm, @eq_comm _ e₂']
/-- Combine two `PartialHomeomorph`s with disjoint sources and disjoint targets. We reuse
`PartialHomeomorph.piecewise` then override `toPartialEquiv` to `PartialEquiv.disjointUnion`.
This way we have better definitional equalities for `source` and `target`. -/
def disjointUnion (e e' : PartialHomeomorph α β) [∀ x, Decidable (x ∈ e.source)]
    [∀ y, Decidable (y ∈ e.target)] (Hs : Disjoint e.source e'.source)
    (Ht : Disjoint e.target e'.target) : PartialHomeomorph α β :=
  (e.piecewise e' e.source e.target e.isImage_source_target
        (e'.isImage_source_target_of_disjoint e Hs.symm Ht.symm)
        (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝⁵ : TopologicalSpace α
inst✝⁴ : TopologicalSpace β
inst✝³ : TopologicalSpace γ
inst✝² : TopologicalSpace δ
e✝ : PartialHomeomorph α β
e'✝ : PartialHomeomorph β γ
e e' : PartialHomeomorph α β
inst✝¹ : (x : α) → Decidable (x ∈ e.source)
inst✝ : (y : β) → Decidable (y ∈ e.target)
Hs : Disjoint e.source e'.source
Ht : Disjoint e.target e'.target
⊢ e.source ∩ frontier e.source = e'.source ∩ frontier e.source

Next tactic:
rw [e.open_source.inter_frontier_eq, (Hs.symm.frontier_right e'.open_source).inter_eq]