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) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura, Mario Carneiro
! This file was ported from Lean 3 source module logic.equiv.defs
! leanprover-community/mathlib commit c4658a649d216f57e99621708b09dcb3dcccbd23
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathlib.Data.FunLike.Equiv
import Mathlib.Data.Quot
import Mathlib.Init.Data.Bool.Lemmas
import Mathlib.Logic.Unique
/-!
# Equivalence between types
In this file we define two types:
* `Equiv α β` a.k.a. `α ≃ β`: a bijective map `α → β` bundled with its inverse map; we use this (and
not equality!) to express that various `Type`s or `Sort`s are equivalent.
* `Equiv.Perm α`: the group of permutations `α ≃ α`. More lemmas about `Equiv.Perm` can be found in
`GroupTheory.Perm`.
Then we define
* canonical isomorphisms between various types: e.g.,
- `Equiv.refl α` is the identity map interpreted as `α ≃ α`;
* operations on equivalences: e.g.,
- `Equiv.symm e : β ≃ α` is the inverse of `e : α ≃ β`;
- `Equiv.trans e₁ e₂ : α ≃ γ` is the composition of `e₁ : α ≃ β` and `e₂ : β ≃ γ` (note the order
of the arguments!);
* definitions that transfer some instances along an equivalence. By convention, we transfer
instances from right to left.
- `Equiv.inhabited` takes `e : α ≃ β` and `[Inhabited β]` and returns `Inhabited α`;
- `Equiv.unique` takes `e : α ≃ β` and `[Unique β]` and returns `Unique α`;
- `Equiv.decidableEq` takes `e : α ≃ β` and `[DecidableEq β]` and returns `DecidableEq α`.
More definitions of this kind can be found in other files. E.g., `Data.Equiv.TransferInstance`
does it for many algebraic type classes like `Group`, `Module`, etc.
Many more such isomorphisms and operations are defined in `Logic.Equiv.Basic`.
## Tags
equivalence, congruence, bijective map
-/
open Function
universe u v w z
variable { α : Sort u } { β : Sort v } { γ : Sort w }
/-- `α ≃ β` is the type of functions from `α → β` with a two-sided inverse. -/
structure Equiv ( α : Sort _ ) ( β : Sort _ ) where
toFun : α → β
invFun : β → α
left_inv : LeftInverse : {α : Sort ?u.31} → {β : Sort ?u.30} → (β → α ) → (α → β ) → Prop LeftInverse invFun toFun
right_inv : RightInverse : {α : Sort ?u.43} → {β : Sort ?u.42} → (β → α ) → (α → β ) → Prop RightInverse invFun toFun
#align equiv Equiv
infixl :25 " ≃ " => Equiv
/-- Turn an element of a type `F` satisfying `EquivLike F α β` into an actual
`Equiv`. This is declared as the default coercion from `F` to `α ≃ β`. -/
@[ coe ]
def EquivLike.toEquiv { F } [ EquivLike F α β ] ( f : F ) : α ≃ β where
toFun := f
invFun := EquivLike.inv f
left_inv := EquivLike.left_inv f
right_inv := EquivLike.right_inv f
/-- Any type satisfying `EquivLike` can be cast into `Equiv` via `EquivLike.toEquiv`. -/
instance { F } [ EquivLike F α β ] : CoeTC : Sort ?u.9207 → Sort ?u.9206 → Sort (max(max1?u.9207)?u.9206) CoeTC F ( α ≃ β ) :=
⟨ EquivLike.toEquiv : {α : Sort ?u.9224} → {β : Sort ?u.9223} → {F : Sort ?u.9222} → [inst : EquivLike F α β ] → F → α ≃ β EquivLike.toEquiv⟩
/-- `Perm α` is the type of bijections from `α` to itself. -/
@[reducible]
def Equiv.Perm ( α : Sort _ ) :=
Equiv : Sort ?u.9326 → Sort ?u.9325 → Sort (max(max1?u.9326)?u.9325) Equiv α α
#align equiv.perm Equiv.Perm
namespace Equiv
instance : EquivLike ( α ≃ β ) α β where
coe := toFun : {α : Sort ?u.9354} → {β : Sort ?u.9353} → α ≃ β → α → β toFun
inv := invFun : {α : Sort ?u.9366} → {β : Sort ?u.9365} → α ≃ β → β → α invFun
left_inv := left_inv : ∀ {α : Sort ?u.9376} {β : Sort ?u.9375} (self : α ≃ β ), LeftInverse self .invFun self .toFun left_inv
right_inv := right_inv
coe_injective' e₁ e₂ h₁ h₂ := by α : Sort uβ : Sort vγ : Sort we₁, e₂ : α ≃ β h₁ : e₁ .toFun = e₂ .toFunh₂ : e₁ .invFun = e₂ .invFuncases e₁ α : Sort uβ : Sort vγ : Sort we₂ : α ≃ β toFun✝ : α → β invFun✝ : β → α left_inv✝ : LeftInverse invFun✝ toFun✝ right_inv✝ : Function.RightInverse invFun✝ toFun✝ h₁ : { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } .toFun = e₂ .toFunh₂ : { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } .invFun = e₂ .invFunmk { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } = e₂ ; α : Sort uβ : Sort vγ : Sort we₂ : α ≃ β toFun✝ : α → β invFun✝ : β → α left_inv✝ : LeftInverse invFun✝ toFun✝ right_inv✝ : Function.RightInverse invFun✝ toFun✝ h₁ : { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } .toFun = e₂ .toFunh₂ : { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } .invFun = e₂ .invFunmk { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } = e₂ α : Sort uβ : Sort vγ : Sort we₁, e₂ : α ≃ β h₁ : e₁ .toFun = e₂ .toFunh₂ : e₁ .invFun = e₂ .invFuncases e₂ α : Sort uβ : Sort vγ : Sort wtoFun✝¹ : α → β invFun✝¹ : β → α left_inv✝¹ : LeftInverse invFun✝¹ toFun✝¹ right_inv✝¹ : Function.RightInverse invFun✝¹ toFun✝¹ toFun✝ : α → β invFun✝ : β → α left_inv✝ : LeftInverse invFun✝ toFun✝ right_inv✝ : Function.RightInverse invFun✝ toFun✝ h₁ : { toFun := toFun✝¹ , invFun := invFun✝¹ , left_inv := left_inv✝¹ , right_inv := right_inv✝¹ } .toFun = { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } .toFunh₂ : { toFun := toFun✝¹ , invFun := invFun✝¹ , left_inv := left_inv✝¹ , right_inv := right_inv✝¹ } .invFun = { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } .invFunmk.mk { toFun := toFun✝¹ , invFun := invFun✝¹ , left_inv := left_inv✝¹ , right_inv := right_inv✝¹ } = { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } ; α : Sort uβ : Sort vγ : Sort wtoFun✝¹ : α → β invFun✝¹ : β → α left_inv✝¹ : LeftInverse invFun✝¹ toFun✝¹ right_inv✝¹ : Function.RightInverse invFun✝¹ toFun✝¹ toFun✝ : α → β invFun✝ : β → α left_inv✝ : LeftInverse invFun✝ toFun✝ right_inv✝ : Function.RightInverse invFun✝ toFun✝ h₁ : { toFun := toFun✝¹ , invFun := invFun✝¹ , left_inv := left_inv✝¹ , right_inv := right_inv✝¹ } .toFun = { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } .toFunh₂ : { toFun := toFun✝¹ , invFun := invFun✝¹ , left_inv := left_inv✝¹ , right_inv := right_inv✝¹ } .invFun = { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } .invFunmk.mk { toFun := toFun✝¹ , invFun := invFun✝¹ , left_inv := left_inv✝¹ , right_inv := right_inv✝¹ } = { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } α : Sort uβ : Sort vγ : Sort we₁, e₂ : α ≃ β h₁ : e₁ .toFun = e₂ .toFunh₂ : e₁ .invFun = e₂ .invFuncongr
/-- Helper instance when inference gets stuck on following the normal chain
`EquivLike → EmbeddingLike → FunLike → CoeFun`. -/
instance : FunLike ( α ≃ β ) α ( fun _ => β ) :=
EmbeddingLike.toFunLike
@[ simp ] theorem coe_fn_mk ( f : α → β ) ( g l r ) : ( Equiv.mk f g l r : α → β ) = f :=
rfl : ∀ {α : Sort ?u.10391} {a : α }, a = a rfl
#align equiv.coe_fn_mk Equiv.coe_fn_mk
/-- The map `(r ≃ s) → (r → s)` is injective. -/
theorem coe_fn_injective : @ Function.Injective : {α : Sort ?u.10447} → {β : Sort ?u.10446} → (α → β ) → Prop Function.Injective ( α ≃ β ) ( α → β ) ( fun e => e ) :=
FunLike.coe_injective'
#align equiv.coe_fn_injective Equiv.coe_fn_injective
protected theorem coe_inj : ∀ {α : Sort u} {β : Sort v} {e₁ e₂ : α ≃ β }, ↑e₁ = ↑e₂ ↔ e₁ = e₂ coe_inj { e₁ e₂ : α ≃ β } : ( e₁ : α → β ) = e₂ ↔ e₁ = e₂ :=
@ FunLike.coe_fn_eq : ∀ {F : Sort ?u.10906} {α : Sort ?u.10904} {β : α → Sort ?u.10905 } [i : FunLike F α β ] {f g : F }, ↑f = ↑g ↔ f = g FunLike.coe_fn_eq _ _ _ : ?m.10908 → Sort ?u.10905 _ _ e₁ e₂
#align equiv.coe_inj Equiv.coe_inj : ∀ {α : Sort u} {β : Sort v} {e₁ e₂ : α ≃ β }, ↑e₁ = ↑e₂ ↔ e₁ = e₂ Equiv.coe_inj
@[ ext ] theorem ext : ∀ {α : Sort u} {β : Sort v} {f g : α ≃ β }, (∀ (x : α ), ↑f x = ↑g x ) → f = g ext { f g : Equiv : Sort ?u.10957 → Sort ?u.10956 → Sort (max(max1?u.10957)?u.10956) Equiv α β } ( H : ∀ (x : α ), ↑f x = ↑g x H : ∀ x , f x = g x ) : f = g := FunLike.ext : ∀ {F : Sort ?u.11090} {α : Sort ?u.11091} {β : α → Sort ?u.11089 } [i : FunLike F α β ] (f g : F ),
(∀ (x : α ), ↑f x = ↑g x ) → f = g FunLike.ext f g H : ∀ (x : α ), ↑f x = ↑g x H
#align equiv.ext Equiv.ext : ∀ {α : Sort u} {β : Sort v} {f g : α ≃ β }, (∀ (x : α ), ↑f x = ↑g x ) → f = g Equiv.ext
protected theorem congr_arg : ∀ {f : α ≃ β } {x x' : α }, x = x' → ↑f x = ↑f x' congr_arg { f : Equiv : Sort ?u.11150 → Sort ?u.11149 → Sort (max(max1?u.11150)?u.11149) Equiv α β } { x x' : α } : x = x' → f x = f x' :=
FunLike.congr_arg : ∀ {F : Sort ?u.11284} {α : Sort ?u.11282} {β : Sort ?u.11283} [i : FunLike F α fun x => β ] (f : F ) {x y : α },
x = y → ↑f x = ↑f y FunLike.congr_arg f
#align equiv.congr_arg Equiv.congr_arg : ∀ {α : Sort u} {β : Sort v} {f : α ≃ β } {x x' : α }, x = x' → ↑f x = ↑f x' Equiv.congr_arg
protected theorem congr_fun : ∀ {α : Sort u} {β : Sort v} {f g : α ≃ β }, f = g → ∀ (x : α ), ↑f x = ↑g x congr_fun { f g : Equiv : Sort ?u.11339 → Sort ?u.11338 → Sort (max(max1?u.11339)?u.11338) Equiv α β } ( h : f = g ) ( x : α ) : f x = g x :=
FunLike.congr_fun : ∀ {F : Sort ?u.11470} {α : Sort ?u.11472} {β : α → Sort ?u.11471 } [i : FunLike F α β ] {f g : F },
f = g → ∀ (x : α ), ↑f x = ↑g x FunLike.congr_fun h x
#align equiv.congr_fun Equiv.congr_fun : ∀ {α : Sort u} {β : Sort v} {f g : α ≃ β }, f = g → ∀ (x : α ), ↑f x = ↑g x Equiv.congr_fun
theorem ext_iff : ∀ {f g : α ≃ β }, f = g ↔ ∀ (x : α ), ↑f x = ↑g x ext_iff { f g : Equiv : Sort ?u.11529 → Sort ?u.11528 → Sort (max(max1?u.11529)?u.11528) Equiv α β } : f = g ↔ ∀ x , f x = g x := FunLike.ext_iff : ∀ {F : Sort ?u.11659} {α : Sort ?u.11661} {β : α → Sort ?u.11660 } [i : FunLike F α β ] {f g : F },
f = g ↔ ∀ (x : α ), ↑f x = ↑g x FunLike.ext_iff
#align equiv.ext_iff Equiv.ext_iff : ∀ {α : Sort u} {β : Sort v} {f g : α ≃ β }, f = g ↔ ∀ (x : α ), ↑f x = ↑g x Equiv.ext_iff
@[ ext ] theorem Perm.ext : ∀ {σ τ : Perm α }, (∀ (x : α ), ↑σ x = ↑τ x ) → σ = τ Perm.ext { σ τ : Equiv.Perm : Sort ?u.11738 → Sort (max1?u.11738) Equiv.Perm α } ( H : ∀ (x : α ), ↑σ x = ↑τ x H : ∀ x , σ x = τ x ) : σ = τ := Equiv.ext : ∀ {α : Sort ?u.11870} {β : Sort ?u.11869} {f g : α ≃ β }, (∀ (x : α ), ↑f x = ↑g x ) → f = g Equiv.ext H : ∀ (x : α ), ↑σ x = ↑τ x H
#align equiv.perm.ext Equiv.Perm.ext : ∀ {α : Sort u} {σ τ : Perm α }, (∀ (x : α ), ↑σ x = ↑τ x ) → σ = τ Equiv.Perm.ext
protected theorem Perm.congr_arg : ∀ {f : Perm α } {x x' : α }, x = x' → ↑f x = ↑f x' Perm.congr_arg { f : Equiv.Perm : Sort ?u.11906 → Sort (max1?u.11906) Equiv.Perm α } { x x' : α } : x = x' → f x = f x' :=
Equiv.congr_arg : ∀ {α : Sort ?u.12038} {β : Sort ?u.12037} {f : α ≃ β } {x x' : α }, x = x' → ↑f x = ↑f x' Equiv.congr_arg
#align equiv.perm.congr_arg Equiv.Perm.congr_arg : ∀ {α : Sort u} {f : Perm α } {x x' : α }, x = x' → ↑f x = ↑f x' Equiv.Perm.congr_arg
protected theorem Perm.congr_fun : ∀ {α : Sort u} {f g : Perm α }, f = g → ∀ (x : α ), ↑f x = ↑g x Perm.congr_fun { f g : Equiv.Perm : Sort ?u.12077 → Sort (max1?u.12077) Equiv.Perm α } ( h : f = g ) ( x : α ) : f x = g x :=
Equiv.congr_fun : ∀ {α : Sort ?u.12208} {β : Sort ?u.12207} {f g : α ≃ β }, f = g → ∀ (x : α ), ↑f x = ↑g x Equiv.congr_fun h x
#align equiv.perm.congr_fun Equiv.Perm.congr_fun : ∀ {α : Sort u} {f g : Perm α }, f = g → ∀ (x : α ), ↑f x = ↑g x Equiv.Perm.congr_fun
theorem Perm.ext_iff : ∀ {α : Sort u} {σ τ : Perm α }, σ = τ ↔ ∀ (x : α ), ↑σ x = ↑τ x Perm.ext_iff { σ τ : Equiv.Perm : Sort ?u.12236 → Sort (max1?u.12236) Equiv.Perm α } : σ = τ ↔ ∀ x , σ x = τ x := Equiv.ext_iff : ∀ {α : Sort ?u.12369} {β : Sort ?u.12368} {f g : α ≃ β }, f = g ↔ ∀ (x : α ), ↑f x = ↑g x Equiv.ext_iff
#align equiv.perm.ext_iff Equiv.Perm.ext_iff : ∀ {α : Sort u} {σ τ : Perm α }, σ = τ ↔ ∀ (x : α ), ↑σ x = ↑τ x Equiv.Perm.ext_iff
/-- Any type is equivalent to itself. -/
@[refl] protected def refl : (α : Sort ?u.12396) → α ≃ α refl ( α : Sort _ ) : α ≃ α := ⟨ id : {α : Sort ?u.12415} → α → α id, id : {α : Sort ?u.12420} → α → α id, fun _ => rfl : ∀ {α : Sort ?u.12428} {a : α }, a = a rfl, fun _ => rfl : ∀ {α : Sort ?u.12439} {a : α }, a = a rfl⟩
#align equiv.refl Equiv.refl : (α : Sort u_1) → α ≃ α Equiv.refl
instance inhabited' : Inhabited : Sort ?u.12507 → Sort (max1?u.12507) Inhabited ( α ≃ α ) := ⟨ Equiv.refl : (α : Sort ?u.12516) → α ≃ α Equiv.refl α ⟩
/-- Inverse of an equivalence `e : α ≃ β`. -/
@[symm]
protected def symm ( e : α ≃ β ) : β ≃ α := ⟨ e . invFun : {α : Sort ?u.12601} → {β : Sort ?u.12600} → α ≃ β → β → α invFun, e . toFun : {α : Sort ?u.12610} → {β : Sort ?u.12609} → α ≃ β → α → β toFun, e . right_inv , e . left_inv : ∀ {α : Sort ?u.12622} {β : Sort ?u.12621} (self : α ≃ β ), LeftInverse self .invFun self .toFun left_inv⟩
#align equiv.symm Equiv.symm : {α : Sort u} → {β : Sort v} → α ≃ β → β ≃ α Equiv.symm
pp_extended_field_notation Equiv.symm : {α : Sort u} → {β : Sort v} → α ≃ β → β ≃ α Equiv.symm
/-- See Note [custom simps projection] -/
def Simps.symm_apply : {α : Sort u} → {β : Sort v} → α ≃ β → β → α Simps.symm_apply ( e : α ≃ β ) : β → α := e . symm : {α : Sort ?u.19960} → {β : Sort ?u.19959} → α ≃ β → β ≃ α symm
#align equiv.simps.symm_apply Equiv.Simps.symm_apply : {α : Sort u} → {β : Sort v} → α ≃ β → β → α Equiv.Simps.symm_apply
initialize_simps_projections Equiv ( toFun : (α : Sort u_1) → (β : Sort u_2) → α ≃ β → α → β toFun → apply : (α : Sort u_1) → (β : Sort u_2) → α ≃ β → α → β apply, invFun : (α : Sort u_1) → (β : Sort u_2) → α ≃ β → β → α invFun → symm_apply : {α : Sort u} → {β : Sort v} → α ≃ β → β → α symm_apply)
-- Porting note:
-- Added these lemmas as restatements of `left_inv` and `right_inv`,
-- which use the coercions.
-- We might even consider switching the names, and having these as a public API.
theorem left_inv' ( e : α ≃ β ) : Function.LeftInverse : {α : Sort ?u.20251} → {β : Sort ?u.20250} → (β → α ) → (α → β ) → Prop Function.LeftInverse e . symm : {α : Sort ?u.20255} → {β : Sort ?u.20254} → α ≃ β → β ≃ α symm e := e . left_inv : ∀ {α : Sort ?u.20396} {β : Sort ?u.20395} (self : α ≃ β ), LeftInverse self .invFun self .toFun left_inv
theorem right_inv' ( e : α ≃ β ) : Function.RightInverse : {α : Sort ?u.20421} → {β : Sort ?u.20420} → (β → α ) → (α → β ) → Prop Function.RightInverse e . symm : {α : Sort ?u.20425} → {β : Sort ?u.20424} → α ≃ β → β ≃ α symm e := e . right_inv
/-- Composition of equivalences `e₁ : α ≃ β` and `e₂ : β ≃ γ`. -/
@[trans]
protected def trans ( e₁ : α ≃ β ) ( e₂ : β ≃ γ ) : α ≃ γ :=
⟨ e₂ ∘ e₁ , e₁ . symm : {α : Sort ?u.20763} → {β : Sort ?u.20762} → α ≃ β → β ≃ α symm ∘ e₂ . symm : {α : Sort ?u.20835} → {β : Sort ?u.20834} → α ≃ β → β ≃ α symm, e₂ . left_inv : ∀ {α : Sort ?u.20910} {β : Sort ?u.20909} (self : α ≃ β ), LeftInverse self .invFun self .toFun left_inv. comp e₁ . left_inv : ∀ {α : Sort ?u.20966} {β : Sort ?u.20965} (self : α ≃ β ), LeftInverse self .invFun self .toFun left_inv, e₂ . right_inv . comp e₁ . right_inv ⟩
#align equiv.trans Equiv.trans : {α : Sort u} → {β : Sort v} → {γ : Sort w} → α ≃ β → β ≃ γ → α ≃ γ Equiv.trans
pp_extended_field_notation Equiv.trans : {α : Sort u} → {β : Sort v} → {γ : Sort w} → α ≃ β → β ≃ γ → α ≃ γ Equiv.trans
@[ simps ]
instance : Trans : {α : Sort ?u.28602} →
{β : Sort ?u.28601} →
{γ : Sort ?u.28600} →
(α → β → Sort ?u.28605 ) →
(β → γ → Sort ?u.28604 ) →
outParam (α → γ → Sort ?u.28603 ) →
Sort (max(max(max(max(max(max1?u.28605)?u.28602)?u.28601)?u.28600)?u.28604)?u.28603) Trans Equiv : Sort ?u.28610 → Sort ?u.28609 → Sort (max(max1?u.28610)?u.28609) Equiv Equiv : Sort ?u.28618 → Sort ?u.28617 → Sort (max(max1?u.28618)?u.28617) Equiv Equiv : Sort ?u.28626 → Sort ?u.28625 → Sort (max(max1?u.28626)?u.28625) Equiv where
trans := Equiv.trans : {α : Sort ?u.28671} → {β : Sort ?u.28670} → {γ : Sort ?u.28669} → α ≃ β → β ≃ γ → α ≃ γ Equiv.trans
-- porting note: this is not a syntactic tautology any more because
-- the coercion from `e` to a function is now `FunLike.coe` not `e.toFun`
@[ simp ] theorem toFun_as_coe : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ), e .toFun = ↑e toFun_as_coe ( e : α ≃ β ) : e . toFun : {α : Sort ?u.29014} → {β : Sort ?u.29013} → α ≃ β → α → β toFun = e := rfl : ∀ {α : Sort ?u.29254} {a : α }, a = a rfl
#align equiv.to_fun_as_coe Equiv.toFun_as_coe : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ), e .toFun = ↑e Equiv.toFun_as_coe
-- porting note: `simp` should prove this using `toFun_as_coe`, but it doesn't.
-- This might be a bug in `simp` -- see https://github.com/leanprover/lean4/issues/1937
-- If this issue is fixed then the simp linter probably will start complaining, and
-- this theorem can be deleted hopefully without breaking any `simp` proofs.
@[ simp ] theorem toFun_as_coe_apply : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ) (x : α ), toFun e x = ↑e x toFun_as_coe_apply ( e : α ≃ β ) ( x : α ) : e . toFun : {α : Sort ?u.29285} → {β : Sort ?u.29284} → α ≃ β → α → β toFun x = e x := rfl : ∀ {α : Sort ?u.29358} {a : α }, a = a rfl
@[ simp ] theorem invFun_as_coe : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ), e .invFun = ↑e .symm invFun_as_coe ( e : α ≃ β ) : e . invFun : {α : Sort ?u.29390} → {β : Sort ?u.29389} → α ≃ β → β → α invFun = e . symm : {α : Sort ?u.29397} → {β : Sort ?u.29396} → α ≃ β → β ≃ α symm := rfl : ∀ {α : Sort ?u.29637} {a : α }, a = a rfl
#align equiv.inv_fun_as_coe Equiv.invFun_as_coe : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ), e .invFun = ↑e .symm Equiv.invFun_as_coe
protected theorem injective ( e : α ≃ β ) : Injective : {α : Sort ?u.29665} → {β : Sort ?u.29664} → (α → β ) → Prop Injective e := EquivLike.injective e
#align equiv.injective Equiv.injective
protected theorem surjective ( e : α ≃ β ) : Surjective : {α : Sort ?u.29781} → {β : Sort ?u.29780} → (α → β ) → Prop Surjective e := EquivLike.surjective e
#align equiv.surjective Equiv.surjective
protected theorem bijective ( e : α ≃ β ) : Bijective : {α : Sort ?u.29899} → {β : Sort ?u.29898} → (α → β ) → Prop Bijective e := EquivLike.bijective e
#align equiv.bijective Equiv.bijective
protected theorem subsingleton ( e : α ≃ β ) [ Subsingleton β ] : Subsingleton α :=
e . injective . subsingleton
#align equiv.subsingleton Equiv.subsingleton
protected theorem subsingleton.symm ( e : α ≃ β ) [ Subsingleton α ] : Subsingleton β :=
e . symm : {α : Sort ?u.30073} → {β : Sort ?u.30072} → α ≃ β → β ≃ α symm. injective . subsingleton
#align equiv.subsingleton.symm Equiv.subsingleton.symm
theorem subsingleton_congr ( e : α ≃ β ) : Subsingleton α ↔ Subsingleton β :=
⟨ fun _ => e . symm : {α : Sort ?u.30138} → {β : Sort ?u.30137} → α ≃ β → β ≃ α symm. subsingleton , fun _ => e . subsingleton ⟩
#align equiv.subsingleton_congr Equiv.subsingleton_congr
instance equiv_subsingleton_cod [ Subsingleton β ] : Subsingleton ( α ≃ β ) :=
⟨ fun _ _ => Equiv.ext : ∀ {α : Sort ?u.30210} {β : Sort ?u.30209} {f g : α ≃ β }, (∀ (x : α ), ↑f x = ↑g x ) → f = g Equiv.ext fun _ => Subsingleton.elim _ _ ⟩
instance equiv_subsingleton_dom [ Subsingleton α ] : Subsingleton ( α ≃ β ) :=
⟨ fun f _ => Equiv.ext : ∀ {α : Sort ?u.30313} {β : Sort ?u.30312} {f g : α ≃ β }, (∀ (x : α ), ↑f x = ↑g x ) → f = g Equiv.ext fun _ => @ Subsingleton.elim _ ( Equiv.subsingleton.symm f ) _ _ ⟩
instance permUnique [ Subsingleton α ] : Unique : Sort ?u.30390 → Sort (max1?u.30390) Unique ( Perm : Sort ?u.30391 → Sort (max1?u.30391) Perm α ) :=
uniqueOfSubsingleton ( Equiv.refl : (α : Sort ?u.30419) → α ≃ α Equiv.refl α )
theorem Perm.subsingleton_eq_refl [ Subsingleton α ] ( e : Perm : Sort ?u.30478 → Sort (max1?u.30478) Perm α ) : e = Equiv.refl : (α : Sort ?u.30482) → α ≃ α Equiv.refl α :=
Subsingleton.elim _ _
#align equiv.perm.subsingleton_eq_refl Equiv.Perm.subsingleton_eq_refl
/-- Transfer `DecidableEq` across an equivalence. -/
protected def decidableEq ( e : α ≃ β ) [ DecidableEq : Sort ?u.30548 → Sort (max1?u.30548) DecidableEq β ] : DecidableEq : Sort ?u.30557 → Sort (max1?u.30557) DecidableEq α :=
e . injective . decidableEq
#align equiv.decidable_eq Equiv.decidableEq
theorem nonempty_congr ( e : α ≃ β ) : Nonempty α ↔ Nonempty β := Nonempty.congr e e . symm : {α : Sort ?u.30825} → {β : Sort ?u.30824} → α ≃ β → β ≃ α symm
#align equiv.nonempty_congr Equiv.nonempty_congr
protected theorem nonempty ( e : α ≃ β ) [ Nonempty β ] : Nonempty α := e . nonempty_congr . mpr : ∀ {a b : Prop }, (a ↔ b ) → b → a mpr ‹_›
#align equiv.nonempty Equiv.nonempty
/-- If `α ≃ β` and `β` is inhabited, then so is `α`. -/
protected def inhabited [ Inhabited : Sort ?u.30946 → Sort (max1?u.30946) Inhabited β ] ( e : α ≃ β ) : Inhabited : Sort ?u.30953 → Sort (max1?u.30953) Inhabited α := ⟨ e . symm : {α : Sort ?u.30963} → {β : Sort ?u.30962} → α ≃ β → β ≃ α symm default ⟩
#align equiv.inhabited Equiv.inhabited
/-- If `α ≃ β` and `β` is a singleton type, then so is `α`. -/
protected def unique [ Unique : Sort ?u.31213 → Sort (max1?u.31213) Unique β ] ( e : α ≃ β ) : Unique : Sort ?u.31220 → Sort (max1?u.31220) Unique α := e . symm : {α : Sort ?u.31225} → {β : Sort ?u.31224} → α ≃ β → β ≃ α symm. surjective . unique
#align equiv.unique Equiv.unique
/-- Equivalence between equal types. -/
protected def cast : {α β : Sort u_1} → α = β → α ≃ β cast { α β : Sort _ } ( h : α = β ) : α ≃ β :=
⟨ cast : {α β : Sort ?u.31385} → α = β → α → β cast h , cast : {α β : Sort ?u.31396} → α = β → α → β cast h . symm : ∀ {α : Sort ?u.31401} {a b : α }, a = b → b = a symm, fun _ => by cases h ; rfl , fun _ => by cases h ; rfl ⟩
#align equiv.cast Equiv.cast : {α β : Sort u_1} → α = β → α ≃ β Equiv.cast
@[ simp ] theorem coe_fn_symm_mk ( f : α → β ) ( g l r ) : (( Equiv.mk f g l r ). symm : {α : Sort ?u.31732} → {β : Sort ?u.31731} → α ≃ β → β ≃ α symm : β → α ) = g := rfl : ∀ {α : Sort ?u.31814} {a : α }, a = a rfl
#align equiv.coe_fn_symm_mk Equiv.coe_fn_symm_mk
@[ simp ] theorem coe_refl : ( Equiv.refl : (α : Sort ?u.31876) → α ≃ α Equiv.refl α : α → α ) = id : {α : Sort ?u.31940} → α → α id := rfl : ∀ {α : Sort ?u.31979} {a : α }, a = a rfl
#align equiv.coe_refl Equiv.coe_refl
/-- This cannot be a `simp` lemmas as it incorrectly matches against `e : α ≃ synonym α`, when
`synonym α` is semireducible. This makes a mess of `Multiplicative.ofAdd` etc. -/
theorem Perm.coe_subsingleton { α : Type _ : Type (?u.32011+1) Type _} [ Subsingleton α ] ( e : Perm : Sort ?u.32017 → Sort (max1?u.32017) Perm α ) : ( e : α → α ) = id : {α : Sort ?u.32093} → α → α id := by
rw [ Perm.subsingleton_eq_refl e , coe_refl ]
#align equiv.perm.coe_subsingleton Equiv.Perm.coe_subsingleton
-- porting note: marking this as `@[simp]` because `simp` doesn't fire on `coe_refl`
-- in an expression such as `Equiv.refl a x`
@[ simp ] theorem refl_apply ( x : α ) : Equiv.refl : (α : Sort ?u.32226) → α ≃ α Equiv.refl α x = x := rfl : ∀ {α : Sort ?u.32291} {a : α }, a = a rfl
#align equiv.refl_apply Equiv.refl_apply
@[ simp ] theorem coe_trans : ∀ {α : Sort u} {β : Sort v} {γ : Sort w} (f : α ≃ β ) (g : β ≃ γ ), ↑(f .trans g ) = ↑g ∘ ↑f coe_trans ( f : α ≃ β ) ( g : β ≃ γ ) : ( f . trans : {α : Sort ?u.32337} → {β : Sort ?u.32336} → {γ : Sort ?u.32335} → α ≃ β → β ≃ γ → α ≃ γ trans g : α → γ ) = g ∘ f := rfl : ∀ {α : Sort ?u.32567} {a : α }, a = a rfl
#align equiv.coe_trans Equiv.coe_trans : ∀ {α : Sort u} {β : Sort v} {γ : Sort w} (f : α ≃ β ) (g : β ≃ γ ), ↑(f .trans g ) = ↑g ∘ ↑f Equiv.coe_trans
-- porting note: marking this as `@[simp]` because `simp` doesn't fire on `coe_trans`
-- in an expression such as `Equiv.trans f g x`
@[ simp ] theorem trans_apply : ∀ {α : Sort u} {β : Sort v} {γ : Sort w} (f : α ≃ β ) (g : β ≃ γ ) (a : α ), ↑(f .trans g ) a = ↑g (↑f a ) trans_apply ( f : α ≃ β ) ( g : β ≃ γ ) ( a : α ) : ( f . trans : {α : Sort ?u.32628} → {β : Sort ?u.32627} → {γ : Sort ?u.32626} → α ≃ β → β ≃ γ → α ≃ γ trans g ) a = g ( f a ) := rfl : ∀ {α : Sort ?u.32842} {a : α }, a = a rfl
#align equiv.trans_apply Equiv.trans_apply : ∀ {α : Sort u} {β : Sort v} {γ : Sort w} (f : α ≃ β ) (g : β ≃ γ ) (a : α ), ↑(f .trans g ) a = ↑g (↑f a ) Equiv.trans_apply
@[ simp ] theorem apply_symm_apply : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ) (x : β ), ↑e (↑e .symm x ) = x apply_symm_apply ( e : α ≃ β ) ( x : β ) : e ( e . symm : {α : Sort ?u.32964} → {β : Sort ?u.32963} → α ≃ β → β ≃ α symm x ) = x := e . right_inv x
#align equiv.apply_symm_apply Equiv.apply_symm_apply : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ) (x : β ), ↑e (↑e .symm x ) = x Equiv.apply_symm_apply
@[ simp ] theorem symm_apply_apply : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ) (x : α ), ↑e .symm (↑e x ) = x symm_apply_apply ( e : α ≃ β ) ( x : α ) : e . symm : {α : Sort ?u.33093} → {β : Sort ?u.33092} → α ≃ β → β ≃ α symm ( e x ) = x := e . left_inv : ∀ {α : Sort ?u.33231} {β : Sort ?u.33230} (self : α ≃ β ), LeftInverse self .invFun self .toFun left_inv x
#align equiv.symm_apply_apply Equiv.symm_apply_apply : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ) (x : α ), ↑e .symm (↑e x ) = x Equiv.symm_apply_apply
@[ simp ] theorem symm_comp_self : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ), ↑e .symm ∘ ↑e = id symm_comp_self ( e : α ≃ β ) : e . symm : {α : Sort ?u.33292} → {β : Sort ?u.33291} → α ≃ β → β ≃ α symm ∘ e = id : {α : Sort ?u.33430} → α → α id := funext : ∀ {α : Sort ?u.33470} {β : α → Sort ?u.33469 } {f g : (x : α ) → β x }, (∀ (x : α ), f x = g x ) → f = g funext e . symm_apply_apply : ∀ {α : Sort ?u.33484} {β : Sort ?u.33483} (e : α ≃ β ) (x : α ), ↑e .symm (↑e x ) = x symm_apply_apply
#align equiv.symm_comp_self Equiv.symm_comp_self : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ), ↑e .symm ∘ ↑e = id Equiv.symm_comp_self
@[ simp ] theorem self_comp_symm : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ), ↑e ∘ ↑e .symm = id self_comp_symm ( e : α ≃ β ) : e ∘ e . symm : {α : Sort ?u.33623} → {β : Sort ?u.33622} → α ≃ β → β ≃ α symm = id : {α : Sort ?u.33693} → α → α id := funext : ∀ {α : Sort ?u.33733} {β : α → Sort ?u.33732 } {f g : (x : α ) → β x }, (∀ (x : α ), f x = g x ) → f = g funext e . apply_symm_apply : ∀ {α : Sort ?u.33747} {β : Sort ?u.33746} (e : α ≃ β ) (x : β ), ↑e (↑e .symm x ) = x apply_symm_apply
#align equiv.self_comp_symm Equiv.self_comp_symm : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ), ↑e ∘ ↑e .symm = id Equiv.self_comp_symm
@[ simp ] theorem symm_trans_apply : ∀ {α : Sort u} {β : Sort v} {γ : Sort w} (f : α ≃ β ) (g : β ≃ γ ) (a : γ ), ↑(f .trans g ).symm a = ↑f .symm (↑g .symm a ) symm_trans_apply ( f : α ≃ β ) ( g : β ≃ γ ) ( a : γ ) :
( f . trans : {α : Sort ?u.33819} → {β : Sort ?u.33818} → {γ : Sort ?u.33817} → α ≃ β → β ≃ γ → α ≃ γ trans g ). symm : {α : Sort ?u.33835} → {β : Sort ?u.33834} → α ≃ β → β ≃ α symm a = f . symm : {α : Sort ?u.33905} → {β : Sort ?u.33904} → α ≃ β → β ≃ α symm ( g . symm : {α : Sort ?u.33973} → {β : Sort ?u.33972} → α ≃ β → β ≃ α symm a ) := rfl : ∀ {α : Sort ?u.34045} {a : α }, a = a rfl
#align equiv.symm_trans_apply Equiv.symm_trans_apply : ∀ {α : Sort u} {β : Sort v} {γ : Sort w} (f : α ≃ β ) (g : β ≃ γ ) (a : γ ), ↑(f .trans g ).symm a = ↑f .symm (↑g .symm a ) Equiv.symm_trans_apply
-- The `simp` attribute is needed to make this a `dsimp` lemma.
-- `simp` will always rewrite with `Equiv.symm_symm` before this has a chance to fire.
@[ simp , nolint simpNF ] theorem symm_symm_apply : ∀ {α : Sort u} {β : Sort v} (f : α ≃ β ) (b : α ), ↑f .symm .symm b = ↑f b symm_symm_apply ( f : α ≃ β ) ( b : α ) : f . symm : {α : Sort ?u.34104} → {β : Sort ?u.34103} → α ≃ β → β ≃ α symm. symm : {α : Sort ?u.34110} → {β : Sort ?u.34109} → α ≃ β → β ≃ α symm b = f b := rfl : ∀ {α : Sort ?u.34235} {a : α }, a = a rfl
#align equiv.symm_symm_apply Equiv.symm_symm_apply : ∀ {α : Sort u} {β : Sort v} (f : α ≃ β ) (b : α ), ↑f .symm .symm b = ↑f b Equiv.symm_symm_apply
theorem apply_eq_iff_eq : ∀ {α : Sort u} {β : Sort v} (f : α ≃ β ) {x y : α }, ↑f x = ↑f y ↔ x = y apply_eq_iff_eq ( f : α ≃ β ) { x y : α } : f x = f y ↔ x = y := EquivLike.apply_eq_iff_eq : ∀ {E : Sort ?u.34412} {α : Sort ?u.34413} {β : Sort ?u.34411} [iE : EquivLike E α β ] (f : E ) {x y : α },
↑f x = ↑f y ↔ x = y EquivLike.apply_eq_iff_eq f
#align equiv.apply_eq_iff_eq Equiv.apply_eq_iff_eq : ∀ {α : Sort u} {β : Sort v} (f : α ≃ β ) {x y : α }, ↑f x = ↑f y ↔ x = y Equiv.apply_eq_iff_eq
theorem apply_eq_iff_eq_symm_apply : ∀ {α : Sort u} {β : Sort v} {x : α } {y : (fun x => β ) x } (f : α ≃ β ), ↑f x = y ↔ x = ↑f .symm y apply_eq_iff_eq_symm_apply ( f : α ≃ β ) : f x = y ↔ x = f . symm : {α : Sort ?u.34654} → {β : Sort ?u.34653} → α ≃ β → β ≃ α symm y := by
conv_lhs => rw [ ← apply_symm_apply : ∀ {α : Sort ?u.34759} {β : Sort ?u.34758} (e : α ≃ β ) (x : β ), ↑e (↑e .symm x ) = x apply_symm_apply f y ]
rw [ ↑f x = ↑f (↑f .symm y ) ↔ x = ↑f .symm y apply_eq_iff_eq : ∀ {α : Sort ?u.34799} {β : Sort ?u.34798} (f : α ≃ β ) {x y : α }, ↑f x = ↑f y ↔ x = y apply_eq_iff_eqx = ↑f .symm y ↔ x = ↑f .symm y ]
#align equiv.apply_eq_iff_eq_symm_apply Equiv.apply_eq_iff_eq_symm_apply : ∀ {α : Sort u} {β : Sort v} {x : α } {y : (fun x => β ) x } (f : α ≃ β ), ↑f x = y ↔ x = ↑f .symm y Equiv.apply_eq_iff_eq_symm_apply
@[ simp ] theorem cast_apply { α β } ( h : α = β ) ( x : α ) : Equiv.cast : {α β : Sort ?u.34887} → α = β → α ≃ β Equiv.cast h x = cast : {α β : Sort ?u.34959} → α = β → α → β cast h x := rfl : ∀ {α : Sort ?u.34972} {a : α }, a = a rfl
#align equiv.cast_apply Equiv.cast_apply
@[ simp ] theorem cast_symm { α β } ( h : α = β ) : ( Equiv.cast : {α β : Sort ?u.35028} → α = β → α ≃ β Equiv.cast h ). symm : {α : Sort ?u.35035} → {β : Sort ?u.35034} → α ≃ β → β ≃ α symm = Equiv.cast : {α β : Sort ?u.35043} → α = β → α ≃ β Equiv.cast h . symm : ∀ {α : Sort ?u.35046} {a b : α }, a = b → b = a symm := rfl : ∀ {α : Sort ?u.35062} {a : α }, a = a rfl
#align equiv.cast_symm Equiv.cast_symm
@[ simp ] theorem cast_refl { α } ( h : α = α := rfl : ∀ {α : Sort ?u.35124} {a : α }, a = a rfl) : Equiv.cast : {α β : Sort ?u.35137} → α = β → α ≃ β Equiv.cast h = Equiv.refl : (α : Sort ?u.35143) → α ≃ α Equiv.refl α := rfl : ∀ {α : Sort ?u.35150} {a : α }, a = a rfl
#align equiv.cast_refl Equiv.cast_refl
@[ simp ] theorem cast_trans { α β γ } ( h : α = β ) ( h2 : β = γ ) :
( Equiv.cast : {α β : Sort ?u.35206} → α = β → α ≃ β Equiv.cast h ). trans : {α : Sort ?u.35214} → {β : Sort ?u.35213} → {γ : Sort ?u.35212} → α ≃ β → β ≃ γ → α ≃ γ trans ( Equiv.cast : {α β : Sort ?u.35225} → α = β → α ≃ β Equiv.cast h2 ) = Equiv.cast : {α β : Sort ?u.35230} → α = β → α ≃ β Equiv.cast ( h . trans : ∀ {α : Sort ?u.35233} {a b c : α }, a = b → b = c → a = c trans h2 ) :=
ext : ∀ {α : Sort ?u.35255} {β : Sort ?u.35254} {f g : α ≃ β }, (∀ (x : α ), ↑f x = ↑g x ) → f = g ext fun x => by substs h h2 ; rfl
#align equiv.cast_trans Equiv.cast_trans
theorem cast_eq_iff_heq { α β } ( h : α = β ) { a : α } { b : β } : Equiv.cast : {α β : Sort ?u.35363} → α = β → α ≃ β Equiv.cast h a = b ↔ HEq : {α : Sort ?u.35437} → α → {β : Sort ?u.35437} → β → Prop HEq a b := by
subst h ; simp [ coe_refl ]
#align equiv.cast_eq_iff_heq Equiv.cast_eq_iff_heq : ∀ {α β : Sort u_1} (h : α = β ) {a : α } {b : β }, ↑(Equiv.cast h ) a = b ↔ HEq a b Equiv.cast_eq_iff_heq
theorem symm_apply_eq : ∀ {α : Sort u_1} {β : Sort u_2} (e : α ≃ β ) {x : β } {y : (fun x => α ) x }, ↑e .symm x = y ↔ x = ↑e y symm_apply_eq { α β } ( e : α ≃ β ) { x y } : e . symm : {α : Sort ?u.35672} → {β : Sort ?u.35671} → α ≃ β → β ≃ α symm x = y ↔ x = e y :=
⟨ fun H => by simp [ H . symm : ∀ {α : Sort ?u.35845} {a b : α }, a = b → b = a symm] , fun H => by simp [ H ] ⟩
#align equiv.symm_apply_eq Equiv.symm_apply_eq : ∀ {α : Sort u_1} {β : Sort u_2} (e : α ≃ β ) {x : β } {y : (fun x => α ) x }, ↑e .symm x = y ↔ x = ↑e y Equiv.symm_apply_eq
theorem eq_symm_apply : ∀ {α : Sort u_1} {β : Sort u_2} (e : α ≃ β ) {x : β } {y : (fun x => α ) x }, y = ↑e .symm x ↔ ↑e y = x eq_symm_apply { α β } ( e : α ≃ β ) { x y } : y = e . symm : {α : Sort ?u.36074} → {β : Sort ?u.36073} → α ≃ β → β ≃ α symm x ↔ e y = x :=
( eq_comm : ∀ {α : Sort ?u.36223} {a b : α }, a = b ↔ b = a eq_comm. trans : ∀ {a b c : Prop }, (a ↔ b ) → (b ↔ c ) → (a ↔ c ) trans e . symm_apply_eq : ∀ {α : Sort ?u.36237} {β : Sort ?u.36238} (e : α ≃ β ) {x : β } {y : (fun x => α ) x }, ↑e .symm x = y ↔ x = ↑e y symm_apply_eq). trans : ∀ {a b c : Prop }, (a ↔ b ) → (b ↔ c ) → (a ↔ c ) trans eq_comm : ∀ {α : Sort ?u.36273} {a b : α }, a = b ↔ b = a eq_comm
#align equiv.eq_symm_apply Equiv.eq_symm_apply : ∀ {α : Sort u_1} {β : Sort u_2} (e : α ≃ β ) {x : β } {y : (fun x => α ) x }, y = ↑e .symm x ↔ ↑e y = x Equiv.eq_symm_apply
@[ simp ] theorem symm_symm : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ), e .symm .symm = e symm_symm ( e : α ≃ β ) : e . symm : {α : Sort ?u.36302} → {β : Sort ?u.36301} → α ≃ β → β ≃ α symm. symm : {α : Sort ?u.36308} → {β : Sort ?u.36307} → α ≃ β → β ≃ α symm = e := by cases e mk { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } .symm .symm = { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } ; mk { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } .symm .symm = { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } rfl
#align equiv.symm_symm Equiv.symm_symm : ∀ {α : Sort u} {β : Sort v} (e : α ≃ β ), e .symm .symm = e Equiv.symm_symm
@[ simp ] theorem trans_refl ( e : α ≃ β ) : e . trans : {α : Sort ?u.36427} → {β : Sort ?u.36426} → {γ : Sort ?u.36425} → α ≃ β → β ≃ γ → α ≃ γ trans ( Equiv.refl : (α : Sort ?u.36438) → α ≃ α Equiv.refl β ) = e := by cases e mk { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } .trans (Equiv.refl β ) = { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } ; mk { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } .trans (Equiv.refl β ) = { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } rfl
#align equiv.trans_refl Equiv.trans_refl
@[ simp ] theorem refl_symm : ( Equiv.refl : (α : Sort ?u.36553) → α ≃ α Equiv.refl α ). symm : {α : Sort ?u.36555} → {β : Sort ?u.36554} → α ≃ β → β ≃ α symm = Equiv.refl : (α : Sort ?u.36563) → α ≃ α Equiv.refl α := rfl : ∀ {α : Sort ?u.36566} {a : α }, a = a rfl
#align equiv.refl_symm Equiv.refl_symm
@[ simp ] theorem refl_trans ( e : α ≃ β ) : ( Equiv.refl : (α : Sort ?u.36606) → α ≃ α Equiv.refl α ). trans : {α : Sort ?u.36609} → {β : Sort ?u.36608} → {γ : Sort ?u.36607} → α ≃ β → β ≃ γ → α ≃ γ trans e = e := by cases e mk (Equiv.refl α ).trans { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } = { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } ; mk (Equiv.refl α ).trans { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } = { toFun := toFun✝ , invFun := invFun✝ , left_inv := left_inv✝ , right_inv := right_inv✝ } rfl
#align equiv.refl_trans Equiv.refl_trans
@[ simp ] theorem symm_trans_self ( e : α ≃ β ) : e . symm : {α : Sort ?u.36739} → {β : Sort ?u.36738} → α ≃ β → β ≃ α symm. trans : {α : Sort ?u.36746} → {β : Sort ?u.36745} → {γ : Sort ?u.36744} → α ≃ β → β ≃ γ → α ≃ γ trans e = Equiv.refl : (α : Sort ?u.36759) → α ≃ α Equiv.refl β := ext : ∀ {α : Sort ?u.36766} {β : Sort ?u.36765} {f g : α ≃ β }, (∀ (x : α ), ↑f x = ↑g x ) → f = g ext <| by simp
#align equiv.symm_trans_self Equiv.symm_trans_self
@[ simp ] theorem self_trans_symm ( e : α ≃ β ) : e . trans : {α : Sort ?u.37170} → {β : Sort ?u.37169} → {γ : Sort ?u.37168} → α ≃ β → β ≃ γ → α ≃ γ trans e . symm : {α : Sort ?u.37182} → {β : Sort ?u.37181} → α ≃ β → β ≃ α symm = Equiv.refl : (α : Sort ?u.37192) → α ≃ α Equiv.refl α := ext : ∀ {α : Sort ?u.37199} {β : Sort ?u.37198} {f g : α ≃ β }, (∀ (x : α ), ↑f x = ↑g x ) → f = g ext <| by simp
#align equiv.self_trans_symm Equiv.self_trans_symm
theorem trans_assoc : ∀ {δ : Sort u_1} (ab : α ≃ β ) (bc : β ≃ γ ) (cd : γ ≃ δ ), (ab .trans bc ).trans cd = ab .trans (bc .trans cd ) trans_assoc { δ } ( ab : α ≃ β ) ( bc : β ≃ γ ) ( cd : γ ≃ δ ) :
( ab . trans : {α : Sort ?u.37607} → {β : Sort ?u.37606} → {γ : Sort ?u.37605} → α ≃ β → β ≃ γ → α ≃ γ trans bc ). trans : {α : Sort ?u.37624} → {β : Sort ?u.37623} → {γ : Sort ?u.37622} → α ≃ β → β ≃ γ → α ≃ γ trans cd = ab . trans : {α : Sort ?u.37641} → {β : Sort ?u.37640} → {γ : Sort ?u.37639} → α ≃ β → β ≃ γ → α ≃ γ trans ( bc . trans : {α : Sort ?u.37652} → {β : Sort ?u.37651} → {γ : Sort ?u.37650} → α ≃ β → β ≃ γ → α ≃ γ trans cd ) := Equiv.ext : ∀ {α : Sort ?u.37676} {β : Sort ?u.37675} {f g : α ≃ β }, (∀ (x : α ), ↑f x = ↑g x ) → f = g Equiv.ext fun _ => rfl : ∀ {α : Sort ?u.37689} {a : α }, a = a rfl
#align equiv.trans_assoc Equiv.trans_assoc : ∀ {α : Sort u} {β : Sort v} {γ : Sort w} {δ : Sort u_1} (ab : α ≃ β ) (bc : β ≃ γ ) (cd : γ ≃ δ ),
(ab .trans bc ).trans cd = ab .trans (bc .trans cd ) Equiv.trans_assoc
theorem leftInverse_symm ( f : Equiv : Sort ?u.37737 → Sort ?u.37736 → Sort (max(max1?u.37737)?u.37736) Equiv α β ) : LeftInverse : {α : Sort ?u.37741} → {β : Sort ?u.37740} → (β → α ) → (α → β ) → Prop LeftInverse f . symm : {α : Sort ?u.37745} → {β : Sort ?u.37744} → α ≃ β → β ≃ α symm f := f . left_inv : ∀ {α : Sort ?u.37886} {β : Sort ?u.37885} (self : α ≃ β ), LeftInverse self .invFun self .toFun left_inv
#align equiv.left_inverse_symm Equiv.leftInverse_symm
theorem rightInverse_symm ( f : Equiv : Sort ?u.37907 → Sort ?u.37906 → Sort (max(max1?u.37907)?u.37906) Equiv α β ) : Function.RightInverse : {α : Sort ?u.37911} → {β : Sort ?u.37910} → (β → α ) → (α → β ) → Prop Function.RightInverse f . symm : {α : Sort ?u.37915} → {β : Sort ?u.37914} → α ≃ β → β ≃ α symm f := f . right_inv
#align equiv.right_inverse_symm Equiv.rightInverse_symm
theorem injective_comp ( e : α ≃ β ) ( f : β → γ ) : Injective : {α : Sort ?u.38085} → {β : Sort ?u.38084} → (α → β ) → Prop Injective ( f ∘ e ) ↔ Injective : {α : Sort ?u.38171} → {β : Sort ?u.38170} → (α → β ) → Prop Injective f :=
EquivLike.injective_comp e f
#align equiv.injective_comp Equiv.injective_comp
theorem comp_injective ( f : α → β ) ( e : β ≃ γ ) : Injective : {α : Sort ?u.38243} → {β : Sort ?u.38242} → (α → β ) → Prop Injective ( e ∘ f ) ↔ Injective : {α : Sort ?u.38329} → {β : Sort ?u.38328} → (α → β ) → Prop Injective f :=
EquivLike.comp_injective f e
#align equiv.comp_injective Equiv.comp_injective
theorem surjective_comp ( e : α ≃ β ) ( f : β → γ ) : Surjective : {α : Sort ?u.38401} → {β : Sort ?u.38400} → (α → β ) → Prop Surjective ( f ∘ e ) ↔ Surjective : {α : Sort ?u.38487} → {β : Sort ?u.38486} → (α → β ) → Prop Surjective f :=
EquivLike.surjective_comp e f
#align equiv.surjective_comp Equiv.surjective_comp
theorem comp_surjective ( f : α → β ) ( e : β ≃ γ ) : Surjective : {α : Sort ?u.38559} → {β : Sort ?u.38558} → (α → β ) → Prop Surjective ( e ∘ f ) ↔ Surjective : {α : Sort ?u.38645} → {β : Sort ?u.38644} → (α → β ) → Prop Surjective f :=
EquivLike.comp_surjective f e
#align equiv.comp_surjective Equiv.comp_surjective
theorem bijective_comp ( e : α ≃ β ) ( f : β → γ ) : Bijective : {α : Sort ?u.38717} → {β : Sort ?u.38716} → (α → β ) → Prop Bijective ( f ∘ e ) ↔ Bijective : {α : Sort ?u.38803} → {β : Sort ?u.38802} → (α → β ) → Prop Bijective f :=
EquivLike.bijective_comp e f
#align equiv.bijective_comp Equiv.bijective_comp
theorem comp_bijective ( f : α → β ) ( e : β ≃ γ ) : Bijective : {α : Sort ?u.38875} → {β : Sort ?u.38874} → (α → β ) → Prop Bijective ( e ∘ f ) ↔ Bijective : {α : Sort ?u.38961} → {β : Sort ?u.38960} → (α → β ) → Prop Bijective f :=
EquivLike.comp_bijective f e
#align equiv.comp_bijective Equiv.comp_bijective
/-- If `α` is equivalent to `β` and `γ` is equivalent to `δ`, then the type of equivalences `α ≃ γ`
is equivalent to the type of equivalences `β ≃ δ`. -/
def equivCongr : {δ : Sort ?u.39038} → α ≃ β → γ ≃ δ → α ≃ γ ≃ (β ≃ δ ) equivCongr ( ab : α ≃ β ) ( cd : γ ≃ δ ) : ( α ≃ γ ) ≃ ( β ≃ δ ) where
toFun ac := ( ab . symm : {α : Sort ?u.39062} → {β : Sort ?u.39061} → α ≃ β → β ≃ α symm. trans : {α : Sort ?u.39069} → {β : Sort ?u.39068} → {γ : Sort ?u.39067} → α ≃ β → β ≃ γ → α ≃ γ trans ac ). trans : {α : Sort ?u.39086} → {β : Sort ?u.39085} → {γ : Sort ?u.39084} → α ≃ β → β ≃ γ → α ≃ γ trans cd
invFun bd := ab . trans : {α : Sort ?u.39108} → {β : Sort ?u.39107} → {γ : Sort ?u.39106} → α ≃ β → β ≃ γ → α ≃ γ trans <| bd . trans : {α : Sort ?u.39119} → {β : Sort ?u.39118} → {γ : Sort ?u.39117} → α ≃ β → β ≃ γ → α ≃ γ trans <| cd . symm : {α : Sort ?u.39129} → {β : Sort ?u.39128} → α ≃ β → β ≃ α symm
left_inv ac := by (fun bd => ab .trans (bd .trans cd .symm ) ) ((fun ac => (ab .symm .trans ac ).trans cd ) ac ) = ac ext x H ↑((fun bd => ab .trans (bd .trans cd .symm ) ) ((fun ac => (ab .symm .trans ac ).trans cd ) ac ) ) x = ↑ac x ; H ↑((fun bd => ab .trans (bd .trans cd .symm ) ) ((fun ac => (ab .symm .trans ac ).trans cd ) ac ) ) x = ↑ac x (fun bd => ab .trans (bd .trans cd .symm ) ) ((fun ac => (ab .symm .trans ac ).trans cd ) ac ) = ac simp only [ trans_apply : ∀ {α : Sort ?u.39202} {β : Sort ?u.39201} {γ : Sort ?u.39200} (f : α ≃ β ) (g : β ≃ γ ) (a : α ),
↑(f .trans g ) a = ↑g (↑f a ) trans_apply, comp_apply : ∀ {β : Sort ?u.39231} {δ : Sort ?u.39232} {α : Sort ?u.39233} {f : β → δ } {g : α → β } {x : α }, (f ∘ g ) x = f (g x ) comp_apply, symm_apply_apply : ∀ {α : Sort ?u.39256} {β : Sort ?u.39255} (e : α ≃ β ) (x : α ), ↑e .symm (↑e x ) = x symm_apply_apply]
right_inv ac := by (fun ac => (ab .symm .trans ac ).trans cd ) ((fun bd => ab .trans (bd .trans cd .symm ) ) ac ) = ac ext x H ↑((fun ac => (ab .symm .trans ac ).trans cd ) ((fun bd => ab .trans (bd .trans cd .symm ) ) ac ) ) x = ↑ac x ; H ↑((fun ac => (ab .symm .trans ac ).trans cd ) ((fun bd => ab .trans (bd .trans cd .symm ) ) ac ) ) x = ↑ac x (fun ac => (ab .symm .trans ac ).trans cd ) ((fun bd => ab .trans (bd .trans cd .symm ) ) ac ) = ac simp only [ trans_apply : ∀ {α : Sort ?u.39765} {β : Sort ?u.39764} {γ : Sort ?u.39763} (f : α ≃ β ) (g : β ≃ γ ) (a : α ),
↑(f .trans g ) a = ↑g (↑f a ) trans_apply, comp_apply : ∀ {β : Sort ?u.39779} {δ : Sort ?u.39780} {α : Sort ?u.39781} {f : β → δ } {g : α → β } {x : α }, (f ∘ g ) x = f (g x ) comp_apply, apply_symm_apply : ∀ {α : Sort ?u.39796} {β : Sort ?u.39795} (e : α ≃ β ) (x : β ), ↑e (↑e .symm x ) = x apply_symm_apply]
#align equiv.equiv_congr Equiv.equivCongr : {α : Sort u} → {β : Sort v} → {γ : Sort w} → {δ : Sort u_1} → α ≃ β → γ ≃ δ → α ≃ γ ≃ (β ≃ δ ) Equiv.equivCongr
@[ simp ] theorem equivCongr_refl { α β } :
( Equiv.refl : (α : Sort ?u.40423) → α ≃ α Equiv.refl α ). equivCongr : {α : Sort ?u.40427} → {β : Sort ?u.40426} → {γ : Sort ?u.40425} → {δ : Sort ?u.40424} → α ≃ β → γ ≃ δ → α ≃ γ ≃ (β ≃ δ ) equivCongr ( Equiv.refl : (α : Sort ?u.40440) → α ≃ α Equiv.refl β ) = Equiv.refl : (α : Sort ?u.40445) → α ≃ α Equiv.refl ( α ≃ β ) := by ext ; rfl
#align equiv.equiv_congr_refl Equiv.equivCongr_refl
@[ simp ] theorem equivCongr_symm { δ } ( ab : α ≃ β ) ( cd : γ ≃ δ ) :
( ab . equivCongr : {α : Sort ?u.40566} → {β : Sort ?u.40565} → {γ : Sort ?u.40564} → {δ : Sort ?u.40563} → α ≃ β → γ ≃ δ → α ≃ γ ≃ (β ≃ δ ) equivCongr cd ). symm : {α : Sort ?u.40584} → {β : Sort ?u.40583} → α ≃ β → β ≃ α symm = ab . symm : {α : Sort ?u.40593} → {β : Sort ?u.40592} → α ≃ β → β ≃ α symm. equivCongr : {α : Sort ?u.40599} → {β : Sort ?u.40598} → {γ : Sort ?u.40597} → {δ : Sort ?u.40596} → α ≃ β → γ ≃ δ → α ≃ γ ≃ (β ≃ δ ) equivCongr cd . symm : {α : Sort ?u.40613} → {β : Sort ?u.40612} → α ≃ β → β ≃ α symm := by ext ; rfl
#align equiv.equiv_congr_symm Equiv.equivCongr_symm
@[ simp ] theorem equivCongr_trans { δ ε ζ } ( ab : α ≃ β ) ( de : δ ≃ ε ) ( bc : β ≃ γ ) ( ef : ε ≃ ζ ) :
( ab . equivCongr : {α : Sort ?u.40791} → {β : Sort ?u.40790} → {γ : Sort ?u.40789} → {δ : Sort ?u.40788} → α ≃ β → γ ≃ δ → α ≃ γ ≃ (β ≃ δ ) equivCongr de ). trans : {α : Sort ?u.40810} → {β : Sort ?u.40809} → {γ : Sort ?u.40808} → α ≃ β → β ≃ γ → α ≃ γ trans ( bc . equivCongr : {α : Sort ?u.40824} → {β : Sort ?u.40823} → {γ : Sort ?u.40822} → {δ : Sort ?u.40821} → α ≃ β → γ ≃ δ → α ≃ γ ≃ (β ≃ δ ) equivCongr ef ) = ( ab . trans : {α : Sort ?u.40851} → {β : Sort ?u.40850} → {γ : Sort ?u.40849} → α ≃ β → β ≃ γ → α ≃ γ trans bc ). equivCongr : {α : Sort ?u.40865} → {β : Sort ?u.40864} → {γ : Sort ?u.40863} → {δ : Sort ?u.40862} → α ≃ β → γ ≃ δ → α ≃ γ ≃ (β ≃ δ ) equivCongr ( de . trans : {α : Sort ?u.40880} → {β : Sort ?u.40879} → {γ : Sort ?u.40878} → α ≃ β → β ≃ γ → α ≃ γ trans ef ) := by
ext ; rfl
#align equiv.equiv_congr_trans Equiv.equivCongr_trans
@[ simp ] theorem equivCongr_refl_left { α β γ } ( bg : β ≃ γ ) ( e : α ≃ β ) :
( Equiv.refl : (α : Sort ?u.41088) → α ≃ α Equiv.refl α ). equivCongr : {α : Sort ?u.41092} → {β : Sort ?u.41091} → {γ : Sort ?u.41090} → {δ : Sort ?u.41089} → α ≃ β → γ ≃ δ → α ≃ γ ≃ (β ≃ δ ) equivCongr bg e = e . trans : {α : Sort ?u.41182} → {β : Sort ?u.41181} → {γ : Sort ?u.41180} → α ≃ β → β ≃ γ → α ≃ γ trans bg := rfl : ∀ {α : Sort ?u.41203} {a : α }, a = a rfl
#align equiv.equiv_congr_refl_left