Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
Try doing some basic maths questions in the Lean Theorem Prover. Functions, real numbers, equivalence relations and groups. Click on README.md and then on "Open in CoCalc with one click".
Project: Xena
Views: 18536License: APACHE
/- Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro Injective functions. -/ import data.equiv.basic data.option.basic data.subtype universes u v w x namespace function structure embedding (α : Sort*) (β : Sort*) := (to_fun : α → β) (inj : injective to_fun) infixr ` ↪ `:25 := embedding instance {α : Sort u} {β : Sort v} : has_coe_to_fun (α ↪ β) := ⟨_, embedding.to_fun⟩ end function protected def equiv.to_embedding {α : Sort u} {β : Sort v} (f : α ≃ β) : α ↪ β := ⟨f, f.injective⟩ @[simp] theorem equiv.to_embedding_coe_fn {α : Sort u} {β : Sort v} (f : α ≃ β) : (f.to_embedding : α → β) = f := rfl namespace function namespace embedding @[ext] lemma ext {α β} {f g : embedding α β} (h : ∀ x, f x = g x) : f = g := by cases f; cases g; simpa using funext h lemma ext_iff {α β} {f g : embedding α β} : (∀ x, f x = g x) ↔ f = g := ⟨ext, λ h _, by rw h⟩ @[simp] theorem to_fun_eq_coe {α β} (f : α ↪ β) : to_fun f = f := rfl @[simp] theorem coe_fn_mk {α β} (f : α → β) (i) : (@mk _ _ f i : α → β) = f := rfl theorem inj' {α β} : ∀ (f : α ↪ β), injective f | ⟨f, hf⟩ := hf @[refl] protected def refl (α : Sort*) : α ↪ α := ⟨id, injective_id⟩ @[trans] protected def trans {α β γ} (f : α ↪ β) (g : β ↪ γ) : α ↪ γ := ⟨_, injective_comp g.inj' f.inj'⟩ @[simp] theorem refl_apply {α} (x : α) : embedding.refl α x = x := rfl @[simp] theorem trans_apply {α β γ} (f : α ↪ β) (g : β ↪ γ) (a : α) : (f.trans g) a = g (f a) := rfl protected def congr {α : Sort u} {β : Sort v} {γ : Sort w} {δ : Sort x} (e₁ : α ≃ β) (e₂ : γ ≃ δ) (f : α ↪ γ) : (β ↪ δ) := (equiv.to_embedding e₁.symm).trans (f.trans e₂.to_embedding) protected noncomputable def of_surjective {α β} {f : β → α} (hf : surjective f) : α ↪ β := ⟨surj_inv hf, injective_surj_inv _⟩ protected noncomputable def equiv_of_surjective {α β} (f : α ↪ β) (hf : surjective f) : α ≃ β := equiv.of_bijective ⟨f.inj, hf⟩ protected def of_not_nonempty {α β} (hα : ¬ nonempty α) : α ↪ β := ⟨λa, (hα ⟨a⟩).elim, assume a, (hα ⟨a⟩).elim⟩ noncomputable def set_value {α β} (f : α ↪ β) (a : α) (b : β) : α ↪ β := by haveI := classical.dec; exact if h : ∃ a', f a' = b then (equiv.swap a (classical.some h)).to_embedding.trans f else ⟨λ a', if a' = a then b else f a', λ a₁ a₂ e, begin simp at e, split_ifs at e with h₁ h₂, { cc }, { cases h ⟨_, e.symm⟩ }, { cases h ⟨_, e⟩ }, { exact f.2 e } end⟩ theorem set_value_eq {α β} (f : α ↪ β) (a : α) (b : β) : set_value f a b a = b := begin rw [set_value], cases classical.dec (∃ a', f a' = b); dsimp [dite], {simp}, simp [equiv.swap_apply_left], apply classical.some_spec h end /-- Embedding into `option` -/ protected def some {α} : α ↪ option α := ⟨some, option.injective_some α⟩ def subtype {α} (p : α → Prop) : subtype p ↪ α := ⟨subtype.val, λ _ _, subtype.eq'⟩ /-- Restrict the codomain of an embedding. -/ def cod_restrict {α β} (p : set β) (f : α ↪ β) (H : ∀ a, f a ∈ p) : α ↪ p := ⟨λ a, ⟨f a, H a⟩, λ a b h, f.inj (@congr_arg _ _ _ _ subtype.val h)⟩ @[simp] theorem cod_restrict_apply {α β} (p) (f : α ↪ β) (H a) : cod_restrict p f H a = ⟨f a, H a⟩ := rfl def prod_congr {α β γ δ : Type*} (e₁ : α ↪ β) (e₂ : γ ↪ δ) : α × γ ↪ β × δ := ⟨assume ⟨a, b⟩, (e₁ a, e₂ b), assume ⟨a₁, b₁⟩ ⟨a₂, b₂⟩ h, have a₁ = a₂ ∧ b₁ = b₂, from (prod.mk.inj h).imp (assume h, e₁.inj h) (assume h, e₂.inj h), this.left ▸ this.right ▸ rfl⟩ section sum open sum def sum_congr {α β γ δ : Type*} (e₁ : α ↪ β) (e₂ : γ ↪ δ) : α ⊕ γ ↪ β ⊕ δ := ⟨assume s, match s with inl a := inl (e₁ a) | inr b := inr (e₂ b) end, assume s₁ s₂ h, match s₁, s₂, h with | inl a₁, inl a₂, h := congr_arg inl $ e₁.inj $ inl.inj h | inr b₁, inr b₂, h := congr_arg inr $ e₂.inj $ inr.inj h end⟩ @[simp] theorem sum_congr_apply_inl {α β γ δ} (e₁ : α ↪ β) (e₂ : γ ↪ δ) (a) : sum_congr e₁ e₂ (inl a) = inl (e₁ a) := rfl @[simp] theorem sum_congr_apply_inr {α β γ δ} (e₁ : α ↪ β) (e₂ : γ ↪ δ) (b) : sum_congr e₁ e₂ (inr b) = inr (e₂ b) := rfl end sum section sigma open sigma def sigma_congr_right {α : Type*} {β γ : α → Type*} (e : ∀ a, β a ↪ γ a) : sigma β ↪ sigma γ := ⟨λ ⟨a, b⟩, ⟨a, e a b⟩, λ ⟨a₁, b₁⟩ ⟨a₂, b₂⟩ h, begin injection h with h₁ h₂, subst a₂, congr, exact (e a₁).2 (eq_of_heq h₂) end⟩ end sigma def Pi_congr_right {α : Sort*} {β γ : α → Sort*} (e : ∀ a, β a ↪ γ a) : (Π a, β a) ↪ (Π a, γ a) := ⟨λf a, e a (f a), λ f₁ f₂ h, funext $ λ a, (e a).inj (congr_fun h a)⟩ def arrow_congr_left {α : Sort u} {β : Sort v} {γ : Sort w} (e : α ↪ β) : (γ → α) ↪ (γ → β) := Pi_congr_right (λ _, e) noncomputable def arrow_congr_right {α : Sort u} {β : Sort v} {γ : Sort w} [inhabited γ] (e : α ↪ β) : (α → γ) ↪ (β → γ) := by haveI := classical.prop_decidable; exact let f' : (α → γ) → (β → γ) := λf b, if h : ∃c, e c = b then f (classical.some h) else default γ in ⟨f', assume f₁ f₂ h, funext $ assume c, have ∃c', e c' = e c, from ⟨c, rfl⟩, have eq' : f' f₁ (e c) = f' f₂ (e c), from congr_fun h _, have eq_b : classical.some this = c, from e.inj $ classical.some_spec this, by simp [f', this, if_pos, eq_b] at eq'; assumption⟩ protected def subtype_map {α β} {p : α → Prop} {q : β → Prop} (f : α ↪ β) (h : ∀{{x}}, p x → q (f x)) : {x : α // p x} ↪ {y : β // q y} := ⟨subtype.map f h, subtype.map_injective h f.2⟩ open set protected def image {α β} (f : α ↪ β) : set α ↪ set β := ⟨image f, injective_image f.2⟩ end embedding end function namespace set /-- The injection map is an embedding between subsets. -/ def embedding_of_subset {α} {s t : set α} (h : s ⊆ t) : s ↪ t := ⟨λ x, ⟨x.1, h x.2⟩, λ ⟨x, hx⟩ ⟨y, hy⟩ h, by congr; injection h⟩ end set