Built with
doc-gen4 , running Lean4.
Bubbles (
) indicate interactive fragments: hover for details, tap to reveal contents.
Use
Ctrl+↑ Ctrl+↓ to navigate,
Ctrl+🖱️ to focus.
On Mac, use
Cmd instead of
Ctrl .
/-
Copyright (c) 2019 Sébastien Gouëzel. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Sébastien Gouëzel
! This file was ported from Lean 3 source module logic.equiv.local_equiv
! leanprover-community/mathlib commit aba57d4d3dae35460225919dcd82fe91355162f9
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathlib.Data.Set.Function
import Mathlib.Logic.Equiv.Defs
import Mathlib.Logic.Equiv.MfldSimpsAttr
import Mathlib.Tactic.Core
/-!
# Local equivalences
This files defines equivalences between subsets of given types.
An element `e` of `LocalEquiv α β` is made of two maps `e.toFun` and `e.invFun` respectively
from α to β and from β to α (just like equivs), which are inverse to each other on the subsets
`e.source` and `e.target` of respectively α and β.
They are designed in particular to define charts on manifolds.
The main functionality is `e.trans f`, which composes the two local equivalences by restricting
the source and target to the maximal set where the composition makes sense.
As for equivs, we register a coercion to functions and use it in our simp normal form: we write
`e x` and `e.symm y` instead of `e.toFun x` and `e.invFun y`.
## Main definitions
`Equiv.toLocalEquiv`: associating a local equiv to an equiv, with source = target = univ
`LocalEquiv.symm` : the inverse of a local equiv
`LocalEquiv.trans` : the composition of two local equivs
`LocalEquiv.refl` : the identity local equiv
`LocalEquiv.ofSet` : the identity on a set `s`
`EqOnSource` : equivalence relation describing the "right" notion of equality for local
equivs (see below in implementation notes)
## Implementation notes
There are at least three possible implementations of local equivalences:
* equivs on subtypes
* pairs of functions taking values in `Option α` and `Option β`, equal to none where the local
equivalence is not defined
* pairs of functions defined everywhere, keeping the source and target as additional data
Each of these implementations has pros and cons.
* When dealing with subtypes, one still need to define additional API for composition and
restriction of domains. Checking that one always belongs to the right subtype makes things very
tedious, and leads quickly to DTT hell (as the subtype `u ∩ v` is not the "same" as `v ∩ u`, for
instance).
* With option-valued functions, the composition is very neat (it is just the usual composition, and
the domain is restricted automatically). These are implemented in `PEquiv.lean`. For manifolds,
where one wants to discuss thoroughly the smoothness of the maps, this creates however a lot of
overhead as one would need to extend all classes of smoothness to option-valued maps.
* The `LocalEquiv` version as explained above is easier to use for manifolds. The drawback is that
there is extra useless data (the values of `toFun` and `invFun` outside of `source` and `target`).
In particular, the equality notion between local equivs is not "the right one", i.e., coinciding
source and target and equality there. Moreover, there are no local equivs in this sense between
an empty type and a nonempty type. Since empty types are not that useful, and since one almost never
needs to talk about equal local equivs, this is not an issue in practice.
Still, we introduce an equivalence relation `EqOnSource` that captures this right notion of
equality, and show that many properties are invariant under this equivalence relation.
### Local coding conventions
If a lemma deals with the intersection of a set with either source or target of a `LocalEquiv`,
then it should use `e.source ∩ s` or `e.target ∩ t`, not `s ∩ e.source` or `t ∩ e.target`.
-/
open Lean Meta Elab Tactic
/-! Implementation of the `mfld_set_tac` tactic for working with the domains of partially-defined
functions (`LocalEquiv`, `LocalHomeomorph`, etc).
This is in a separate file from `Mathlib.Logic.Equiv.MfldSimpsAttr` because attributes need a new
file to become functional.
-/
-- register in the simpset `mfld_simps` several lemmas that are often useful when dealing
-- with manifolds
attribute [ mfld_simps ]
id.def : ∀ {α : Sort u} (a : α ), id a = a id.def Function.comp.left_id : ∀ {α : Sort u₁} {β : Sort u₂} (f : α → β ), id ∘ f = f Function.comp.left_id Set.mem_setOf_eq : ∀ {α : Type u} {x : α } {p : α → Prop }, (x ∈ { y | p y } ) = p x Set.mem_setOf_eq Set.image_eq_empty : ∀ {α : Type u_1} {β : Type u_2} {f : α → β } {s : Set α }, f '' s = ∅ ↔ s = ∅ Set.image_eq_empty Set.univ_inter : ∀ {α : Type u} (a : Set α ), Set.univ ∩ a = a Set.univ_inter Set.preimage_univ : ∀ {α : Type u_1} {β : Type u_2} {f : α → β }, f ⁻¹' Set.univ = Set.univ Set.preimage_univ
Set.prod_mk_mem_set_prod_eq : ∀ {α : Type u_2} {β : Type u_1} {s : Set α } {t : Set β } {a : α } {b : β }, ((a , b ) ∈ s ×ˢ t ) = (a ∈ s ∧ b ∈ t ) Set.prod_mk_mem_set_prod_eq and_true_iff Set.mem_univ : ∀ {α : Type u} (x : α ), x ∈ Set.univ Set.mem_univ Set.mem_image_of_mem : ∀ {α : Type u_1} {β : Type u_2} (f : α → β ) {x : α } {a : Set α }, x ∈ a → f x ∈ f '' a Set.mem_image_of_mem true_and_iff
Set.mem_inter_iff : ∀ {α : Type u} (x : α ) (a b : Set α ), x ∈ a ∩ b ↔ x ∈ a ∧ x ∈ b Set.mem_inter_iff Set.mem_preimage : ∀ {α : Type u_2} {β : Type u_1} {f : α → β } {s : Set β } {a : α }, a ∈ f ⁻¹' s ↔ f a ∈ s Set.mem_preimage Function.comp_apply : ∀ {β : Sort u_1} {δ : Sort u_2} {α : Sort u_3} {f : β → δ } {g : α → β } {x : α }, (f ∘ g ) x = f (g x ) Function.comp_apply Set.inter_subset_left : ∀ {α : Type u} (s t : Set α ), s ∩ t ⊆ s Set.inter_subset_left Set.mem_prod : ∀ {α : Type u_1} {β : Type u_2} {s : Set α } {t : Set β } {p : α × β }, p ∈ s ×ˢ t ↔ p .fst ∈ s ∧ p .snd ∈ t Set.mem_prod
Set.range_id Set.range_prod_map and_self_iff : ∀ (p : Prop ), p ∧ p ↔ p and_self_iff Set.mem_range_self : ∀ {α : Type u_1} {ι : Sort u_2} {f : ι → α } (i : ι ), f i ∈ Set.range f Set.mem_range_self eq_self_iff_true : ∀ {α : Sort u_1} (a : α ), a = a ↔ True eq_self_iff_true forall_const
forall_true_iff Set.inter_univ : ∀ {α : Type u} (a : Set α ), a ∩ Set.univ = a Set.inter_univ Set.preimage_id : ∀ {α : Type u_1} {s : Set α }, id ⁻¹' s = s Set.preimage_id Function.comp.right_id : ∀ {α : Sort u₁} {β : Sort u₂} (f : α → β ), f ∘ id = f Function.comp.right_id not_false_iff and_imp : ∀ {a b c : Prop }, a ∧ b → c ↔ a → b → c and_imp
Set.prod_inter_prod : ∀ {α : Type u_1} {β : Type u_2} {s₁ s₂ : Set α } {t₁ t₂ : Set β }, s₁ ×ˢ t₁ ∩ s₂ ×ˢ t₂ = (s₁ ∩ s₂ ) ×ˢ (t₁ ∩ t₂ ) Set.prod_inter_prod Set.univ_prod_univ : ∀ {α : Type u_1} {β : Type u_2}, Set.univ ×ˢ Set.univ = Set.univ Set.univ_prod_univ true_or_iff or_true_iff Prod.map_mk : ∀ {α : Type u_3} {β : Type u_4} {γ : Type u_1} {δ : Type u_2} (f : α → γ ) (g : β → δ ) (a : α ) (b : β ),
Prod.map f g (a , b ) = (f a , g b ) Prod.map_mk Set.preimage_inter
heq_iff_eq : ∀ {α : Sort u_1} {a b : α }, HEq a b ↔ a = b heq_iff_eq Equiv.sigmaEquivProd_apply Equiv.sigmaEquivProd_symm_apply Subtype.coe_mk : ∀ {α : Sort u_1} {p : α → Prop } (a : α ) (h : p a ), ↑{ val := a , property := h } = a Subtype.coe_mk
Equiv.toFun_as_coe : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ), e .toFun = ↑e Equiv.toFun_as_coe Equiv.invFun_as_coe : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ), e .invFun = ↑e .symm Equiv.invFun_as_coe
/-- Common `@[simps]` configuration options used for manifold-related declarations. -/
def mfld_cfg : Simps.Config where
attrs := [ `mfld_simps ]
fullyApplied := false
#align mfld_cfg mfld_cfg
namespace Tactic.MfldSetTac
/-- A very basic tactic to show that sets showing up in manifolds coincide or are included
in one another. -/
elab ( name := mfldSetTac ) "mfld_set_tac" : tactic => withMainContext do
let g ← getMainGoal
let goalTy := (← instantiateMVars (← g.getDecl).type) : ?m.1299
(← instantiateMVars (← instantiateMVars (← g.getDecl).type) : ?m.1299
(← g . getDecl ) (← instantiateMVars (← g.getDecl).type) : ?m.1299
. type (← instantiateMVars (← g.getDecl).type) : ?m.1299
) . getAppFnArgs
match goalTy with
| ( `` Eq , #[ _ty , _e₁ , _e₂ ]) =>
evalTactic (← `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps])))) : ?m.2420
(← `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
`(tactic| (
`(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
apply `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
Set.ext; `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
intro `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
my_y
`(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
constructor `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
<;>
· `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
intro `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
h_my_y
`(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
try `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
( `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
simp `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
`(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
only `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
[*, mfld_simps] `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
at `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
h_my_y; `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
simp `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
`(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
only `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.1409 ?m.1412
[*, mfld_simps]))) (← `(tactic| (
apply Set.ext; intro my_y
constructor <;>
· intro h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps])))) : ?m.2420
)
| ( `` Subset , #[ _ty , _inst , _e₁ , _e₂ ]) =>
evalTactic (← `(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps])))) : ?m.2906
(← `(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.2646 ?m.2649
`(tactic| (
`(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.2646 ?m.2649
intro `(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.2646 ?m.2649
my_y h_my_y
`(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.2646 ?m.2649
try `(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.2646 ?m.2649
( `(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.2646 ?m.2649
simp `(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.2646 ?m.2649
`(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.2646 ?m.2649
only `(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.2646 ?m.2649
[*, mfld_simps] `(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.2646 ?m.2649
at `(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.2646 ?m.2649
h_my_y; `(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.2646 ?m.2649
simp `(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.2646 ?m.2649
`(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.2646 ?m.2649
only `(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps]))) : ?m.2646 ?m.2649
[*, mfld_simps]))) (← `(tactic| (
intro my_y h_my_y
try (simp only [*, mfld_simps] at h_my_y; simp only [*, mfld_simps])))) : ?m.2906
)
| _ => throwError "goal should be an equality or an inclusion" : ?m.3026 ?m.3027
throwError throwError "goal should be an equality or an inclusion" : ?m.3026 ?m.3027
"goal should be an equality or an inclusion"
attribute [ mfld_simps ] and_true eq_self_iff_true : ∀ {α : Sort u_1} (a : α ), a = a ↔ True eq_self_iff_true Function.comp_apply : ∀ {β : Sort u_1} {δ : Sort u_2} {α : Sort u_3} {f : β → δ } {g : α → β } {x : α }, (f ∘ g ) x = f (g x ) Function.comp_apply
end Tactic.MfldSetTac
open Function Set
variable { α : Type _ : Type (?u.29260+1) Type _} { β : Type _ : Type (?u.18434+1) Type _} { γ : Type _ : Type (?u.40256+1) Type _} { δ : Type _ : Type (?u.24668+1) Type _}
/-- Local equivalence between subsets `source` and `target` of `α` and `β` respectively. The
(global) maps `toFun : α → β` and `invFun : β → α` map `source` to `target` and conversely, and are
inverse to each other there. The values of `toFun` outside of `source` and of `invFun` outside of
`target` are irrelevant. -/
structure LocalEquiv ( α : Type _ : Type (?u.16161+1) Type _) ( β : Type _ : Type (?u.16164+1) Type _) where
/-- The global function which has a local inverse. Its value outside of the `source` subset is
irrelevant. -/
toFun : α → β
/-- The local inverse to `toFun`. Its value outside of the `target` subset is irrelevant. -/
invFun : β → α
/-- The domain of the local equivalence. -/
source : Set α
/-- The codomain of the local equivalence. -/
target : Set β
/-- The proposition that elements of `source` are mapped to elements of `target`. -/
map_source' : ∀ ⦃ x ⦄, x ∈ source → toFun x ∈ target
/-- The proposition that elements of `target` are mapped to elements of `source`. -/
map_target' : ∀ ⦃ x ⦄, x ∈ target → invFun x ∈ source
/-- The proposition that `invFun` is a local left-inverse of `toFun` on `source`. -/
left_inv' : ∀ ⦃ x ⦄, x ∈ source → invFun ( toFun x ) = x
/-- The proposition that `invFun` is a local right-inverse of `toFun` on `target`. -/
right_inv' : ∀ ⦃ x ⦄, x ∈ target → toFun ( invFun x ) = x
#align local_equiv LocalEquiv
namespace LocalEquiv
variable ( e : LocalEquiv : Type ?u.39079 → Type ?u.39078 → Type (max?u.39079?u.39078) LocalEquiv α β ) ( e' : LocalEquiv : Type ?u.24816 → Type ?u.24815 → Type (max?u.24816?u.24815) LocalEquiv β γ )
instance [ Inhabited : Sort ?u.17336 → Sort (max1?u.17336) Inhabited α ] [ Inhabited : Sort ?u.17339 → Sort (max1?u.17339) Inhabited β ] : Inhabited : Sort ?u.17342 → Sort (max1?u.17342) Inhabited ( LocalEquiv : Type ?u.17344 → Type ?u.17343 → Type (max?u.17344?u.17343) LocalEquiv α β ) :=
⟨⟨ const : {α : Sort ?u.17374} → (β : Sort ?u.17373) → α → β → α const α default , const : {α : Sort ?u.17500} → (β : Sort ?u.17499) → α → β → α const β default , ∅ , ∅ , mapsTo_empty : ∀ {α : Type ?u.17715} {β : Type ?u.17714} (f : α → β ) (t : Set β ), MapsTo f ∅ t mapsTo_empty _ _ , mapsTo_empty : ∀ {α : Type ?u.17738} {β : Type ?u.17737} (f : α → β ) (t : Set β ), MapsTo f ∅ t mapsTo_empty _ _ , eqOn_empty : ∀ {α : Type ?u.17760} {β : Type ?u.17761} (f₁ f₂ : α → β ), EqOn f₁ f₂ ∅ eqOn_empty _ _ ,
eqOn_empty : ∀ {α : Type ?u.17778} {β : Type ?u.17779} (f₁ f₂ : α → β ), EqOn f₁ f₂ ∅ eqOn_empty _ _ ⟩⟩
/-- The inverse of a local equiv -/
protected def symm : LocalEquiv : Type ?u.17922 → Type ?u.17921 → Type (max?u.17922?u.17921) LocalEquiv β α where
toFun := e . invFun
invFun := e . toFun
source := e . target
target := e . source
map_source' := e . map_target' : ∀ {α : Type ?u.17959} {β : Type ?u.17958} (self : LocalEquiv α β ) ⦃x : β ⦄, x ∈ self .target → invFun self x ∈ self .source map_target'
map_target' := e . map_source' : ∀ {α : Type ?u.17967} {β : Type ?u.17966} (self : LocalEquiv α β ) ⦃x : α ⦄, x ∈ self .source → toFun self x ∈ self .target map_source'
left_inv' := e . right_inv'
right_inv' := e . left_inv'
#align local_equiv.symm LocalEquiv.symm
instance : CoeFun ( LocalEquiv : Type ?u.18204 → Type ?u.18203 → Type (max?u.18204?u.18203) LocalEquiv α β ) fun _ => α → β :=
⟨ LocalEquiv.toFun ⟩
/-- See Note [custom simps projection] -/
def Simps.symm_apply ( e : LocalEquiv : Type ?u.18452 → Type ?u.18451 → Type (max?u.18452?u.18451) LocalEquiv α β ) : β → α :=
e . symm
#align local_equiv.simps.symm_apply LocalEquiv.Simps.symm_apply
initialize_simps_projections LocalEquiv ( toFun → apply , invFun → symm_apply )
-- Porting note: this can be proven with `dsimp only`
-- @[simp, mfld_simps]
-- theorem coe_mk (f : α → β) (g s t ml mr il ir) : (LocalEquiv.mk f g s t ml mr il ir : α → β) = f
-- := by dsimp only
-- #align local_equiv.coe_mk LocalEquiv.coe_mk
#noalign local_equiv.coe_mk
@[ simp , mfld_simps ]
theorem coe_symm_mk : ∀ {α : Type u_1} {β : Type u_2} (f : α → β ) (g : β → α ) (s : Set α ) (t : Set β ) (ml : ∀ ⦃x : α ⦄, x ∈ s → f x ∈ t )
(mr : ∀ ⦃x : β ⦄, x ∈ t → g x ∈ s ) (il : ∀ ⦃x : α ⦄, x ∈ s → g (f x ) = x ) (ir : ∀ ⦃x : β ⦄, x ∈ t → f (g x ) = x ),
(LocalEquiv.symm
{ toFun := f , invFun := g , source := s , target := t , map_source' := ml , map_target' := mr , left_inv' := il ,
right_inv' := ir } ).toFun = g coe_symm_mk ( f : α → β ) ( g s t ml mr il ir : ∀ ⦃x : β ⦄, x ∈ t → f (g x ) = x ir ) :
(( LocalEquiv.mk : {α : Type ?u.18775} →
{β : Type ?u.18774} →
(toFun : α → β ) →
(invFun : β → α ) →
(source : Set α ) →
(target : Set β ) →
(∀ ⦃x : α ⦄, x ∈ source → toFun x ∈ target ) →
(∀ ⦃x : β ⦄, x ∈ target → invFun x ∈ source ) →
(∀ ⦃x : α ⦄, x ∈ source → invFun (toFun x ) = x ) →
(∀ ⦃x : β ⦄, x ∈ target → toFun (invFun x ) = x ) → LocalEquiv α β LocalEquiv.mk f g s t ml mr il ir ). symm : β → α ) = g :=
rfl : ∀ {α : Sort ?u.18866} {a : α }, a = a rfl
#align local_equiv.coe_symm_mk LocalEquiv.coe_symm_mk : ∀ {α : Type u_1} {β : Type u_2} (f : α → β ) (g : β → α ) (s : Set α ) (t : Set β ) (ml : ∀ ⦃x : α ⦄, x ∈ s → f x ∈ t )
(mr : ∀ ⦃x : β ⦄, x ∈ t → g x ∈ s ) (il : ∀ ⦃x : α ⦄, x ∈ s → g (f x ) = x ) (ir : ∀ ⦃x : β ⦄, x ∈ t → f (g x ) = x ),
(LocalEquiv.symm
{ toFun := f , invFun := g , source := s , target := t , map_source' := ml , map_target' := mr , left_inv' := il ,
right_inv' := ir } ).toFun = g LocalEquiv.coe_symm_mk
-- Porting note: this is now a syntactic tautology
-- @[simp, mfld_simps]
-- theorem toFun_as_coe : e.toFun = e := rfl
-- #align local_equiv.to_fun_as_coe LocalEquiv.toFun_as_coe
#noalign local_equiv.to_fun_as_coe
@[ simp , mfld_simps ]
theorem invFun_as_coe : e . invFun = e . symm :=
rfl : ∀ {α : Sort ?u.19239} {a : α }, a = a rfl
#align local_equiv.inv_fun_as_coe LocalEquiv.invFun_as_coe
@[ simp , mfld_simps ]
theorem map_source : ∀ {x : α }, x ∈ e .source → toFun e x ∈ e .target map_source { x : α } ( h : x ∈ e . source ) : e x ∈ e . target :=
e . map_source' : ∀ {α : Type ?u.19386} {β : Type ?u.19385} (self : LocalEquiv α β ) ⦃x : α ⦄, x ∈ self .source → toFun self x ∈ self .target map_source' h
#align local_equiv.map_source LocalEquiv.map_source
@[ simp , mfld_simps ]
theorem map_target { x : β } ( h : x ∈ e . target ) : e . symm x ∈ e . source :=
e . map_target' : ∀ {α : Type ?u.19585} {β : Type ?u.19584} (self : LocalEquiv α β ) ⦃x : β ⦄, x ∈ self .target → invFun self x ∈ self .source map_target' h
#align local_equiv.map_target LocalEquiv.map_target
@[ simp , mfld_simps ]
theorem left_inv { x : α } ( h : x ∈ e . source ) : e . symm ( e x ) = x :=
e . left_inv' h
#align local_equiv.left_inv LocalEquiv.left_inv
@[ simp , mfld_simps ]
theorem right_inv { x : β } ( h : x ∈ e . target ) : e ( e . symm x ) = x :=
e . right_inv' h
#align local_equiv.right_inv LocalEquiv.right_inv
theorem eq_symm_apply { x : α } { y : β } ( hx : x ∈ e . source ) ( hy : y ∈ e . target ) :
x = e . symm y ↔ e x = y :=
⟨ fun h => by rw [ ← e . right_inv hy , h ] , fun h => by rw [ ← e . left_inv hx , h ] ⟩
#align local_equiv.eq_symm_apply LocalEquiv.eq_symm_apply
protected theorem mapsTo : MapsTo e e . source e . target := fun _ => e . map_source
#align local_equiv.maps_to LocalEquiv.mapsTo
theorem symm_mapsTo : MapsTo e . symm e . target e . source :=
e . symm . mapsTo
#align local_equiv.symm_maps_to LocalEquiv.symm_mapsTo
protected theorem leftInvOn : LeftInvOn : {α : Type ?u.20518} → {β : Type ?u.20517} → (β → α ) → (α → β ) → Set α → Prop LeftInvOn e . symm e e . source := fun _ => e . left_inv
#align local_equiv.left_inv_on LocalEquiv.leftInvOn
protected theorem rightInvOn : RightInvOn : {α : Type ?u.20658} → {β : Type ?u.20657} → (β → α ) → (α → β ) → Set β → Prop RightInvOn e . symm e e . target := fun _ => e . right_inv
#align local_equiv.right_inv_on LocalEquiv.rightInvOn
protected theorem invOn : InvOn : {α : Type ?u.20798} → {β : Type ?u.20797} → (β → α ) → (α → β ) → Set α → Set β → Prop InvOn e . symm e e . source e . target :=
⟨ e . leftInvOn , e . rightInvOn ⟩
#align local_equiv.inv_on LocalEquiv.invOn
protected theorem injOn : InjOn e e . source :=
e . leftInvOn . injOn
#align local_equiv.inj_on LocalEquiv.injOn
protected theorem bijOn : BijOn e e . source e . target :=
e . invOn . bijOn e . mapsTo e . symm_mapsTo
#align local_equiv.bij_on LocalEquiv.bijOn
protected theorem surjOn : SurjOn e e . source e . target :=
e . bijOn . surjOn
#align local_equiv.surj_on LocalEquiv.surjOn
/-- Associate a `LocalEquiv` to an `Equiv`. -/
@[ simps ( config := mfld_cfg )]
def _root_.Equiv.toLocalEquiv ( e : α ≃ β ) : LocalEquiv : Type ?u.21346 → Type ?u.21345 → Type (max?u.21346?u.21345) LocalEquiv α β where
toFun := e
invFun := e . symm : {α : Sort ?u.21424} → {β : Sort ?u.21423} → α ≃ β → β ≃ α symm
source := univ
target := univ
map_source' _ _ := mem_univ : ∀ {α : Type ?u.21511} (x : α ), x ∈ univ mem_univ _
map_target' _ _ := mem_univ : ∀ {α : Type ?u.21531} (x : α ), x ∈ univ mem_univ _
left_inv' x _ := e . left_inv : ∀ {α : Sort ?u.21552} {β : Sort ?u.21551} (self : α ≃ β ), LeftInverse self .invFun self .toFun left_inv x
right_inv' x _ := e . right_inv x
#align equiv.to_local_equiv Equiv.toLocalEquiv
#align equiv.to_local_equiv_symm_apply Equiv.toLocalEquiv_symm_apply
#align equiv.to_local_equiv_target Equiv.toLocalEquiv_target
#align equiv.to_local_equiv_apply Equiv.toLocalEquiv_apply
#align equiv.to_local_equiv_source Equiv.toLocalEquiv_source
instance inhabitedOfEmpty [ IsEmpty α ] [ IsEmpty β ] : Inhabited : Sort ?u.21977 → Sort (max1?u.21977) Inhabited ( LocalEquiv : Type ?u.21979 → Type ?u.21978 → Type (max?u.21979?u.21978) LocalEquiv α β ) :=
⟨(( Equiv.equivEmpty α ). trans : {α : Sort ?u.21995} → {β : Sort ?u.21994} → {γ : Sort ?u.21993} → α ≃ β → β ≃ γ → α ≃ γ trans ( Equiv.equivEmpty β ). symm : {α : Sort ?u.22011} → {β : Sort ?u.22010} → α ≃ β → β ≃ α symm ). toLocalEquiv ⟩
#align local_equiv.inhabited_of_empty LocalEquiv.inhabitedOfEmpty
/-- Create a copy of a `LocalEquiv` providing better definitional equalities. -/
@[ simps : ∀ {α : Type u_1} {β : Type u_2} (e : LocalEquiv α β ) (f : α → β ) (hf : e .toFun = f ) (g : β → α )
(hg : (LocalEquiv.symm e ).toFun = g ) (s : Set α ) (hs : e .source = s ) (t : Set β ) (ht : e .target = t ),
(copy e f hf g hg s hs t ht ).target = t simps ( config := { fullyApplied := false })]
def copy ( e : LocalEquiv : Type ?u.22114 → Type ?u.22113 → Type (max?u.22114?u.22113) LocalEquiv α β ) ( f : α → β ) ( hf : ⇑ e = f ) ( g : β → α ) ( hg : ⇑ e . symm = g ) ( s : Set α )
( hs : e . source = s ) ( t : Set β ) ( ht : e . target = t ) :
LocalEquiv : Type ?u.22239 → Type ?u.22238 → Type (max?u.22239?u.22238) LocalEquiv α β where
toFun := f
invFun := g
source := s
target := t
map_source' _ := ht ▸ hs ▸ hf ▸ e . map_source
map_target' _ := hs ▸ ht ▸ hg ▸ e . map_target
left_inv' _ := hs ▸ hf ▸ hg ▸ e . left_inv
right_inv' _ := ht ▸ hf ▸ hg ▸ e . right_inv
#align local_equiv.copy LocalEquiv.copy
#align local_equiv.copy_source LocalEquiv.copy_source : ∀ {α : Type u_1} {β : Type u_2} (e : LocalEquiv α β ) (f : α → β ) (hf : e .toFun = f ) (g : β → α )
(hg : (LocalEquiv.symm e ).toFun = g ) (s : Set α ) (hs : e .source = s ) (t : Set β ) (ht : e .target = t ),
(copy e f hf g hg s hs t ht ).source = s LocalEquiv.copy_source
#align local_equiv.copy_apply LocalEquiv.copy_apply : ∀ {α : Type u_1} {β : Type u_2} (e : LocalEquiv α β ) (f : α → β ) (hf : e .toFun = f ) (g : β → α )
(hg : (LocalEquiv.symm e ).toFun = g ) (s : Set α ) (hs : e .source = s ) (t : Set β ) (ht : e .target = t ),
(copy e f hf g hg s hs t ht ).toFun = f LocalEquiv.copy_apply
#align local_equiv.copy_symm_apply LocalEquiv.copy_symm_apply
#align local_equiv.copy_target LocalEquiv.copy_target : ∀ {α : Type u_1} {β : Type u_2} (e : LocalEquiv α β ) (f : α → β ) (hf : e .toFun = f ) (g : β → α )
(hg : (LocalEquiv.symm e ).toFun = g ) (s : Set α ) (hs : e .source = s ) (t : Set β ) (ht : e .target = t ),
(copy e f hf g hg s hs t ht ).target = t LocalEquiv.copy_target
theorem copy_eq ( e : LocalEquiv : Type ?u.23015 → Type ?u.23014 → Type (max?u.23015?u.23014) LocalEquiv α β ) ( f : α → β ) ( hf : ⇑ e = f ) ( g : β → α ) ( hg : ⇑ e . symm = g )
( s : Set α ) ( hs : e . source = s ) ( t : Set β ) ( ht : e . target = t ) :
e . copy f hf g hg s hs t ht = e := by
copy e f hf g hg s hs t ht = e substs f g s t
copy e f hf g hg s hs t ht = e cases e α : Type u_1β : Type u_2γ : Type ?u.23000δ : Type ?u.23003e : LocalEquiv α β e' : LocalEquiv β γ toFun✝ : α → β invFun✝ : β → α source✝ : Set α target✝ : Set β map_source'✝ : ∀ ⦃x : α ⦄, x ∈ source✝ → toFun✝ x ∈ target✝ map_target'✝ : ∀ ⦃x : β ⦄, x ∈ target✝ → invFun✝ x ∈ source✝ left_inv'✝ : ∀ ⦃x : α ⦄, x ∈ source✝ → invFun✝ (toFun✝ x ) = x right_inv'✝ : ∀ ⦃x : β ⦄, x ∈ target✝ → toFun✝ (invFun✝ x ) = x mk copy
{ toFun := toFun✝ , invFun := invFun✝ , source := source✝ , target := target✝ , map_source' := map_source'✝ ,
map_target' := map_target'✝ , left_inv' := left_inv'✝ , right_inv' := right_inv'✝ }
{ toFun := toFun✝ , invFun := invFun✝ , source := source✝ , target := target✝ , map_source' := map_source'✝ ,
map_target' := map_target'✝ , left_inv' := left_inv'✝ , right_inv' := right_inv'✝ } .toFun
(_ :
{ toFun := toFun✝ , invFun := invFun✝ , source := source✝ , target := target✝ , map_source' := map_source'✝ ,
map_target' := map_target'✝ , left_inv' := left_inv'✝ , right_inv' := right_inv'✝ } .toFun = { toFun := toFun✝ , invFun := invFun✝ , source := source✝ , target := target✝ , map_source' := map_source'✝ ,
map_target' := map_target'✝ , left_inv' := left_inv'✝ , right_inv' := right_inv'✝ } .toFun )
(LocalEquiv.symm
{ toFun := toFun✝ , invFun := invFun✝ , source := source✝ , target := target✝ , map_source' := map_source'✝ ,
map_target' := map_target'✝ , left_inv' := left_inv'✝ , right_inv' := right_inv'✝ } ).toFun
(_ :
(LocalEquiv.symm
{ toFun := toFun✝ , invFun := invFun✝ , source := source✝ , target := target✝ , map_source' := map_source'✝ ,
map_target' := map_target'✝ , left_inv' := left_inv'✝ , right_inv' := right_inv'✝ } ).toFun = (LocalEquiv.symm
{ toFun := toFun✝ , invFun := invFun✝ , source := source✝ , target := target✝ , map_source' := map_source'✝ ,
map_target' := map_target'✝ , left_inv' := left_inv'✝ , right_inv' := right_inv'✝ } ).toFun )
{ toFun := toFun✝ , invFun := invFun✝ , source := source✝ , target := target✝ , map_source' := map_source'✝ ,
map_target' := map_target'✝ , left_inv' := left_inv'✝ , right_inv' := right_inv'✝ } .source
(_ :
{ toFun := toFun✝ , invFun := invFun✝ , source := source✝ , target := target✝ , map_source' := map_source'✝ ,
map_target' := map_target'✝ , left_inv' := left_inv'✝ , right_inv' := right_inv'✝ } .source = { toFun := toFun✝ , invFun := invFun✝ , source := source✝ , target := target✝ , map_source' := map_source'✝ ,
map_target' := map_target'✝ , left_inv' := left_inv'✝ , right_inv' := right_inv'✝ } .source )
{ toFun := toFun✝ , invFun := invFun✝ , source := source✝ , target := target✝ , map_source' := map_source'✝ ,
map_target' := map_target'✝ , left_inv' := left_inv'✝ , right_inv' := right_inv'✝ } .target
(_ :
{ toFun := toFun✝ , invFun := invFun✝ , source := source✝ , target := target✝ , map_source' := map_source'✝ ,
map_target' := map_target'✝ , left_inv' := left_inv'✝ , right_inv' := right_inv'✝ } .target = { toFun := toFun✝ , invFun := invFun✝ , source := source✝ , target := target✝ , map_source' := map_source'✝ ,
map_target' := map_target'✝ , left_inv' := left_inv'✝ , right_inv' := right_inv'✝ } .target ) = { toFun := toFun✝ , invFun := invFun✝ , source := source✝ , target := target✝ , map_source' := map_source'✝ ,
map_target' := map_target'✝ , left_inv' := left_inv'✝ , right_inv' := right_inv'✝ }
copy e f hf g hg s hs t ht = e rfl
#align local_equiv.copy_eq LocalEquiv.copy_eq : ∀ {α : Type u_1} {β : Type u_2} (e : LocalEquiv α β ) (f : α → β ) (hf : e .toFun = f ) (g : β → α )
(hg : (LocalEquiv.symm e ).toFun = g ) (s : Set α ) (hs : e .source = s ) (t : Set β ) (ht : e .target = t ),
copy e f hf g hg s hs t ht = e LocalEquiv.copy_eq
/-- Associate to a `LocalEquiv` an `Equiv` between the source and the target. -/
protected def toEquiv : e . source ≃ e . target where
toFun x := ⟨ e x , e . map_source x . mem : ∀ {α : Type ?u.23860} {s : Set α } (p : ↑s ), ↑p ∈ s mem⟩
invFun y := ⟨ e . symm y , e . map_target y . mem : ∀ {α : Type ?u.24024} {s : Set α } (p : ↑s ), ↑p ∈ s mem⟩
left_inv := fun ⟨_, hx ⟩ => Subtype.eq : ∀ {α : Type ?u.24083} {p : α → Prop } {a1 a2 : { x // p x } }, ↑a1 = ↑a2 → a1 = a2 Subtype.eq <| e . left_inv hx
right_inv := fun ⟨_, hy ⟩ => Subtype.eq : ∀ {α : Type ?u.24241} {p : α → Prop } {a1 a2 : { x // p x } }, ↑a1 = ↑a2 → a1 = a2 Subtype.eq <| e . right_inv hy
#align local_equiv.to_equiv LocalEquiv.toEquiv : {α : Type u_1} → {β : Type u_2} → (e : LocalEquiv α β ) → ↑e .source ≃ ↑e .target LocalEquiv.toEquiv
@[ simp , mfld_simps ]
theorem symm_source : e . symm . source = e . target :=
rfl : ∀ {α : Sort ?u.24701} {a : α }, a = a rfl
#align local_equiv.symm_source LocalEquiv.symm_source
@[ simp , mfld_simps ]
theorem symm_target : e . symm . target = e . source :=
rfl : ∀ {α : Sort ?u.24771} {a : α }, a = a rfl
#align local_equiv.symm_target LocalEquiv.symm_target
@[ simp , mfld_simps ]
theorem symm_symm : e . symm . symm = e := by
cases e α : Type u_1β : Type u_2γ : Type ?u.24805δ : Type ?u.24808e' : LocalEquiv β γ toFun✝ : α → β invFun✝ : β → α source✝ : Set α target✝ : Set β map_source'✝ : ∀ ⦃x : α ⦄, x ∈ source✝ → toFun✝ x ∈ target✝ map_target'✝ : ∀ ⦃x : β ⦄, x ∈ target✝ → invFun✝ x ∈ source✝ left_inv'✝ : ∀ ⦃x : α ⦄, x ∈ source✝ → invFun✝ (toFun✝ x ) = x right_inv'✝ : ∀ ⦃x : β ⦄, x ∈ target✝ → toFun✝ (invFun✝ x ) = x mk LocalEquiv.symm
(LocalEquiv.symm
{ toFun := toFun✝ , invFun := invFun✝ , source := source✝ , target := target✝ , map_source' := map_source'✝ ,
map_target' := map_target'✝ , left_inv' := left_inv'✝ , right_inv' := right_inv'✝ } ) = { toFun := toFun✝ , invFun := invFun✝ , source := source✝ , target := target✝ , map_source' := map_source'✝ ,
map_target' := map_target'✝ , left_inv' := left_inv'✝ , right_inv' := right_inv'✝ }
rfl
#align local_equiv.symm_symm LocalEquiv.symm_symm
theorem image_source_eq_target : e .toFun '' e .source = e .targetimage_source_eq_target : e '' e . source = e . target :=
e . bijOn . image_eq : ∀ {α : Type ?u.25075} {β : Type ?u.25076} {s : Set α } {t : Set β } {f : α → β }, BijOn f s t → f '' s = t image_eq
#align local_equiv.image_source_eq_target LocalEquiv.image_source_eq_target : ∀ {α : Type u_2} {β : Type u_1} (e : LocalEquiv α β ), e .toFun '' e .source = e .target LocalEquiv.image_source_eq_target
theorem forall_mem_target : ∀ {α : Type u_2} {β : Type u_1} (e : LocalEquiv α β ) {p : β → Prop },
(∀ (y : β ), y ∈ e .target → p y ) ↔ ∀ (x : α ), x ∈ e .source → p (toFun e x ) forall_mem_target { p : β → Prop } : (∀ y ∈ e . target , p y ) ↔ ∀ x ∈ e . source , p ( e x ) := by
(∀ (y : β ), y ∈ e .target → p y ) ↔ ∀ (x : α ), x ∈ e .source → p (toFun e x ) rw [ (∀ (y : β ), y ∈ e .target → p y ) ↔ ∀ (x : α ), x ∈ e .source → p (toFun e x ) ← image_source_eq_target : ∀ {α : Type ?u.25248} {β : Type ?u.25247} (e : LocalEquiv α β ), e .toFun '' e .source = e .target image_source_eq_target, (∀ (y : β ), y ∈ e .toFun '' e .source → p y ) ↔ ∀ (x : α ), x ∈ e .source → p (toFun e x ) (∀ (y : β ), y ∈ e .target → p y ) ↔ ∀ (x : α ), x ∈ e .source → p (toFun e x ) ball_image_iff : ∀ {α : Type ?u.25274} {β : Type ?u.25275} {f : α → β } {s : Set α } {p : β → Prop },
(∀ (y : β ), y ∈ f '' s → p y ) ↔ ∀ (x : α ), x ∈ s → p (f x ) ball_image_iff(∀ (x : α ), x ∈ e .source → p (toFun e x ) ) ↔ ∀ (x : α ), x ∈ e .source → p (toFun e x ) ]
#align local_equiv.forall_mem_target LocalEquiv.forall_mem_target : ∀ {α : Type u_2} {β : Type u_1} (e : LocalEquiv α β ) {p : β → Prop },
(∀ (y : β ), y ∈ e .target → p y ) ↔ ∀ (x : α ), x ∈ e .source → p (toFun e x ) LocalEquiv.forall_mem_target
theorem exists_mem_target : ∀ {p : β → Prop }, (∃ y , y ∈ e .target ∧ p y ) ↔ ∃ x , x ∈ e .source ∧ p (toFun e x ) exists_mem_target { p : β → Prop } : (∃ y ∈ e . target , p y ) ↔ ∃ x ∈ e . source , p ( e x ) := by
(∃ y , y ∈ e .target ∧ p y ) ↔ ∃ x , x ∈ e .source ∧ p (toFun e x ) rw [ (∃ y , y ∈ e .target ∧ p y ) ↔ ∃ x , x ∈ e .source ∧ p (toFun e x ) ← image_source_eq_target : ∀ {α : Type ?u.25460} {β : Type ?u.25459} (e : LocalEquiv α β ), e .toFun '' e .source = e .target image_source_eq_target, (∃ y , y ∈ e .toFun '' e .source ∧ p y ) ↔ ∃ x , x ∈ e .source ∧ p (toFun e x ) (∃ y , y ∈ e .target ∧ p y ) ↔ ∃ x , x ∈ e .source ∧ p (toFun e x ) bex_image_iff : ∀ {α : Type ?u.25480} {β : Type ?u.25481} {f : α → β } {s : Set α } {p : β → Prop },
(∃ y , y ∈ f '' s ∧ p y ) ↔ ∃ x , x ∈ s ∧ p (f x ) bex_image_iff]
#align local_equiv.exists_mem_target LocalEquiv.exists_mem_target : ∀ {α : Type u_2} {β : Type u_1} (e : LocalEquiv α β ) {p : β → Prop },
(∃ y , y ∈ e .target ∧ p y ) ↔ ∃ x , x ∈ e .source ∧ p (toFun e x ) LocalEquiv.exists_mem_target
/-- We say that `t : Set β` is an image of `s : Set α` under a local equivalence if
any of the following equivalent conditions hold:
* `e '' (e.source ∩ s) = e.target ∩ t`;
* `e.source ∩ e ⁻¹ t = e.source ∩ s`;
* `∀ x ∈ e.source, e x ∈ t ↔ x ∈ s` (this one is used in the definition).
-/
def IsImage ( s : Set α ) ( t : Set β ) : Prop :=
∀ ⦃ x ⦄, x ∈ e . source → ( e x ∈ t ↔ x ∈ s )
#align local_equiv.is_image LocalEquiv.IsImage
namespace IsImage
variable { e } { s : Set α } { t : Set β } { x : α } { y : β }
theorem apply_mem_iff ( h : e . IsImage s t ) ( hx : x ∈ e . source ) : e x ∈ t ↔ x ∈ s :=
h hx
#align local_equiv.is_image.apply_mem_iff LocalEquiv.IsImage.apply_mem_iff
theorem symm_apply_mem_iff ( h : e . IsImage s t ) : ∀ ⦃ y ⦄, y ∈ e . target → ( e . symm y ∈ s ↔ y ∈ t ) :=
e . forall_mem_target : ∀ {α : Type ?u.26022} {β : Type ?u.26021} (e : LocalEquiv α β ) {p : β → Prop },
(∀ (y : β ), y ∈ e .target → p y ) ↔ ∀ (x : α ), x ∈ e .source → p (toFun e x ) forall_mem_target. mpr : ∀ {a b : Prop }, (a ↔ b ) → b → a mpr fun x hx => by rw [ e . left_inv hx , h hx ]
#align local_equiv.is_image.symm_apply_mem_iff LocalEquiv.IsImage.symm_apply_mem_iff
protected theorem symm ( h : e . IsImage s t ) : e . symm . IsImage t s :=
h . symm_apply_mem_iff
#align local_equiv.is_image.symm LocalEquiv.IsImage.symm
@[ simp ]
theorem symm_iff : e . symm . IsImage t s ↔ e . IsImage s t :=
⟨ fun h => h . symm , fun h => h . symm ⟩
#align local_equiv.is_image.symm_iff LocalEquiv.IsImage.symm_iff
protected theorem mapsTo ( h : e . IsImage s t ) : MapsTo e ( e . source ∩ s ) ( e . target ∩ t ) :=
fun _ hx => ⟨ e . mapsTo hx . 1 : ∀ {a b : Prop }, a ∧ b → a 1, ( h hx . 1 : ∀ {a b : Prop }, a ∧ b → a 1). 2 : ∀ {a b : Prop }, (a ↔ b ) → b → a 2 hx . 2 : ∀ {a b : Prop }, a ∧ b → b 2⟩
#align local_equiv.is_image.maps_to LocalEquiv.IsImage.mapsTo
theorem symm_mapsTo ( h : e . IsImage s t ) : MapsTo e . symm ( e . target ∩ t ) ( e . source ∩ s ) :=
h . symm . mapsTo
#align local_equiv.is_image.symm_maps_to LocalEquiv.IsImage.symm_mapsTo
/-- Restrict a `LocalEquiv` to a pair of corresponding sets. -/
@[ simps ( config := { fullyApplied := false })]
def restr ( h : e . IsImage s t ) : LocalEquiv : Type ?u.26826 → Type ?u.26825 → Type (max?u.26826?u.26825) LocalEquiv α β where
toFun := e
invFun := e . symm
source := e . source ∩ s
target := e . target ∩ t
map_source' := h . mapsTo
map_target' := h . symm_mapsTo
left_inv' := e . leftInvOn . mono ( inter_subset_left : ∀ {α : Type ?u.27028} (s t : Set α ), s ∩ t ⊆ s inter_subset_left _ _ )
right_inv' := e . rightInvOn . mono ( inter_subset_left : ∀ {α : Type ?u.27084} (s t : Set α ), s ∩ t ⊆ s inter_subset_left _ _ )
#align local_equiv.is_image.restr LocalEquiv.IsImage.restr
#align local_equiv.is_image.restr_apply LocalEquiv.IsImage.restr_apply
#align local_equiv.is_image.restr_source LocalEquiv.IsImage.restr_source
#align local_equiv.is_image.restr_target LocalEquiv.IsImage.restr_target
#align local_equiv.is_image.restr_symm_apply LocalEquiv.IsImage.restr_symm_apply
theorem image_eq : IsImage e s t → e .toFun '' (e .source ∩ s ) = e .target ∩ t image_eq ( h : e . IsImage s t ) : e '' ( e . source ∩ s ) = e . target ∩ t :=
h . restr . image_source_eq_target : ∀ {α : Type ?u.27613} {β : Type ?u.27612} (e : LocalEquiv α β ), e .toFun '' e .source = e .target image_source_eq_target
#align local_equiv.is_image.image_eq LocalEquiv.IsImage.image_eq
theorem symm_image_eq ( h : e . IsImage s t ) : e . symm '' ( e . target ∩ t ) = e . source ∩ s :=
h . symm . image_eq
#align local_equiv.is_image.symm_image_eq LocalEquiv.IsImage.symm_image_eq
theorem iff_preimage_eq : IsImage e s t ↔ e .source ∩ e .toFun ⁻¹' t = e .source ∩ s iff_preimage_eq : e . IsImage s t ↔ e . source ∩ e ⁻¹' t = e . source ∩ s := by
simp only [ IsImage , ext_iff : ∀ {α : Type ?u.27964} {s t : Set α }, s = t ↔ ∀ (x : α ), x ∈ s ↔ x ∈ t ext_iff, mem_inter_iff : ∀ {α : Type ?u.27982} (x : α ) (a b : Set α ), x ∈ a ∩ b ↔ x ∈ a ∧ x ∈ b mem_inter_iff, mem_preimage : ∀ {α : Type ?u.28010} {β : Type ?u.28009} {f : α → β } {s : Set β } {a : α }, a ∈ f ⁻¹' s ↔ f a ∈ s mem_preimage, and_congr_right_iff : ∀ {a b c : Prop }, (a ∧ b ↔ a ∧ c ) ↔ a → (b ↔ c ) and_congr_right_iff]
#align local_equiv.is_image.iff_preimage_eq LocalEquiv.IsImage.iff_preimage_eq
alias iff_preimage_eq ↔ preimage_eq of_preimage_eq
#align local_equiv.is_image.of_preimage_eq LocalEquiv.IsImage.of_preimage_eq
#align local_equiv.is_image.preimage_eq LocalEquiv.IsImage.preimage_eq
theorem iff_symm_preimage_eq : e . IsImage s t ↔ e . target ∩ e . symm ⁻¹' s = e . target ∩ t :=
symm_iff . symm : ∀ {a b : Prop }, (a ↔ b ) → (b ↔ a ) symm. trans : ∀ {a b c : Prop }, (a ↔ b ) → (b ↔ c ) → (a ↔ c ) trans iff_preimage_eq
#align local_equiv.is_image.iff_symm_preimage_eq LocalEquiv.IsImage.iff_symm_preimage_eq
alias iff_symm_preimage_eq ↔ symm_preimage_eq of_symm_preimage_eq
#align local_equiv.is_image.of_symm_preimage_eq LocalEquiv.IsImage.of_symm_preimage_eq
#align local_equiv.is_image.symm_preimage_eq LocalEquiv.IsImage.symm_preimage_eq
theorem of_image_eq ( h : e .toFun '' (e .source ∩ s ) = e .target ∩ t h : e '' ( e . source ∩ s ) = e . target ∩ t ) : e . IsImage s t :=
of_symm_preimage_eq <| Eq.trans : ∀ {α : Sort ?u.28643} {a b c : α }, a = b → b = c → a = c Eq.trans ( of_symm_preimage_eq rfl : ∀ {α : Sort ?u.28658} {a : α }, a = a rfl). image_eq . symm : ∀ {α : Sort ?u.28685} {a b : α }, a = b → b = a symm h : e .toFun '' (e .source ∩ s ) = e .target ∩ t h
#align local_equiv.is_image.of_image_eq LocalEquiv.IsImage.of_image_eq
theorem of_symm_image_eq ( h : e . symm '' ( e . target ∩ t ) = e . source ∩ s ) : e . IsImage s t :=
of_preimage_eq <| Eq.trans : ∀ {α : Sort ?u.28873} {a b c : α }, a = b → b = c → a = c Eq.trans ( iff_preimage_eq . 2 : ∀ {a b : Prop }, (a ↔ b ) → b → a 2 rfl : ∀ {α : Sort ?u.28892} {a : α }, a = a rfl). symm_image_eq . symm : ∀ {α : Sort ?u.28919} {a b : α }, a = b → b = a symm h
#align local_equiv.is_image.of_symm_image_eq LocalEquiv.IsImage.of_symm_image_eq
protected theorem compl ( h : e . IsImage s t ) : e . IsImage ( s ᶜ) ( t ᶜ) := fun _ hx => not_congr : ∀ {a b : Prop }, (a ↔ b ) → (¬ a ↔ ¬ b ) not_congr ( h hx )
#align local_equiv.is_image.compl LocalEquiv.IsImage.compl
protected theorem inter { s' t' } ( h : e . IsImage s t ) ( h' : e . IsImage s' t' ) :
e . IsImage ( s ∩ s' ) ( t ∩ t' ) := fun _ hx => and_congr : ∀ {a c b d : Prop }, (a ↔ c ) → (b ↔ d ) → (a ∧ b ↔ c ∧ d ) and_congr ( h hx ) ( h' hx )
#align local_equiv.is_image.inter LocalEquiv.IsImage.inter
protected theorem union { s' t' } ( h : e . IsImage s t ) ( h' : e . IsImage s' t' ) :
e . IsImage ( s ∪ s' ) ( t ∪ t' ) := fun _ hx => or_congr : ∀ {a c b d : Prop }, (a ↔ c ) → (b ↔ d ) → (a ∨ b ↔ c ∨ d ) or_congr ( h hx ) ( h' hx )
#align local_equiv.is_image.union LocalEquiv.IsImage.union
protected theorem diff { s' t' } ( h : e . IsImage s t ) ( h' : e . IsImage s' t' ) :
e . IsImage ( s \ s' ) ( t \ t' ) :=
h . inter : ∀ {α : Type ?u.29555} {