/- Clara L"oh 2021 -/ import tactic -- standard proof tactics open classical -- we want to work in classical logic /- # Injective, surjective, bijective maps -/ /- Injectivitiy -/ def is_injective (X : Type*) (Y : Type*) (f : X → Y) := ∀ x : X, ∀ x' : X, (f x = f x') → (x = x') /- Surjectivity -/ def is_surjective (X : Type*) (Y : Type*) (f : X → Y) := ∀ y : Y, ∃ x : X, f x = y /- Bijectivity -/ def is_bijective (X : Type*) (Y : Type*) (f : X → Y) := (is_injective X Y f) ∧ (is_surjective X Y f) /- Simple inheritance properties of injective, surjective, bijective maps-/ lemma bij_inj (X : Type*) (Y : Type*) (f : X → Y) (f_bijective: is_bijective X Y f) : is_injective X Y f := -- we extract the correct part of the and-statement -- in the definition of is_bijective by {exact and.elim_left f_bijective} -- alternatively: by {exact f_bijective.1} lemma bij_surj (X : Type*) (Y : Type*) (f : X → Y) (f_bijective: is_bijective X Y f) : is_surjective X Y f := -- we extract the correct part of the and-statement -- in the definition of is_bijective by {exact and.elim_right f_bijective} -- alternatively: by {exact f_bijective.2} lemma surj_inj_bij (X : Type*) (Y : Type*) (f : X → Y) (f_surjective: is_surjective X Y f) (f_injective: is_injective X Y f) : is_bijective X Y f := -- we construct the and-statement -- in the definition of is_bijective -- in the correct order by {exact and.intro f_injective f_surjective} /- If a composition is injective, then the first map is injective -/ lemma inj_comp_injfirst (X : Type*) (Y : Type*) (Z : Type*) (f : X → Y) (g : Y → Z) (gf_injective : is_injective X Z (g ∘ f)) : is_injective X Y f := begin -- we prove the all-statement (double ∀) -- in the definition of is_injective assume x : X, assume x' : X, -- we assume the hypothesis of the implication -- in the definition of is_injective assume f_xx' : f x = f x', -- and then show that this implies x = x', -- using injectivity of g ∘ f have gf_xx' : (g ∘ f) x = (g ∘ f) x', from calc (g ∘ f) x = g (f x) : by {simp} ... = g (f x') : by {simp[f_xx']} ... = (g ∘ f) x' : by {simp}, show x = x', by {apply gf_injective, apply gf_xx'}, end /- If a composition is surjective, then the last map is surjective -/ lemma surj_comp_surjsecond (X : Type*) (Y : Type*) (Z : Type*) (f : X → Y) (g : Y → Z) (gf_surjective : is_surjective X Z (g ∘ f)) : is_surjective Y Z g := begin -- we prove the all-statement -- in the definition of is_surjective assume z : Z, -- we use surjectivity of g ∘ f have ex_x : ∃ x : X, (g ∘ f) x = z, by {exact gf_surjective z}, -- we extract such a preimage rcases ex_x with ⟨ x : X, gf_x_z⟩, -- and use it to define a g-preimage of z let y : Y := f x, -- we construct the existential statement -- in the definition of is_surjective, -- by using the example y use y, -- it remains to show that y indeed is a g-preimage of z show g y = z, from calc g y = g (f x) : by {simp} ... = (g ∘ f) x : by {simp} ... = z : by {exact gf_x_z}, end /- If the square of a self-map is bijective, then the self-map is bijective -/ lemma square_bij_bij (X : Type*) (f : X → X) (ff_bijective: is_bijective X X (f ∘ f)) : is_bijective X X f := begin -- the map f is injective have f_injective: is_injective X X f, from begin -- the composition f ∘ f is bijective, whence injective have ff_injective, by {exact bij_inj X X (f ∘ f) ff_bijective}, -- thus, the first map (namely f) is injective show _, by {exact inj_comp_injfirst X X X f f ff_injective}, end, -- the map f is surjective have f_surjective: is_surjective X X f, from begin -- the composition f ∘ f is bijective, wehnce surjective have ff_surjective, by {exact bij_surj _ _ (f ∘ f) ff_bijective}, -- thus, the second map (namely f) is surjective show _, by {exact surj_comp_surjsecond _ _ _ f f ff_surjective}, end, -- thus, f is bijective show is_bijective X X f, by {exact and.intro f_injective f_surjective}, -- alternatively: by {exact surj_inj_bij X X f f_surjective f_injective} end /- Some simple examples -/ /- The map {1,2,3} -> {1,2,3}, 1 -> 1, 2 -> 1, 3 -> 2 is neither injective nor surjective -/ inductive A : Type | A_1 | A_2 | A_3 def f : A → A | A.A_1 := A.A_1 | A.A_2 := A.A_1 | A.A_3 := A.A_2 lemma not_inj_f : ¬ is_injective A A f := begin -- idea: f A_1 = f A_2, even though A_1 ≠ A_2 let x : A := A.A_1, let x' : A := A.A_2, -- x and x' are witnesses for non-injectivity: have f_xx'_x_neg_x' : f x = f x' ∧ x ≠ x', from begin have f_xx' : f x = f x', by {simp[f]}, have x_neg_x' : x ≠ x', by {finish}, show _, by {exact and.intro f_xx' x_neg_x'}, end, -- we move the negation to the innermost formula, -- use x and x' as examples for the existential quantifier, -- and then conclude via f_xx'_x_neg_x' show _, from begin unfold is_injective, push_neg, use x, use x', exact f_xx'_x_neg_x', end end lemma not_surj_f : ¬ is_surjective A A f := begin -- we first move the negation through the all-quantifier refine not_forall_of_exists_not _, show ∃ y : A, ¬(∃ x : A, f x = y), by begin -- we show that A_3 does not lie in the image use A.A_3, have A3_not_in_im : ∀ x : A, ¬ f x = A.A_3, from begin assume x : A, -- we now just consider all three cases cases x, case A.A_1 : {simp[f]}, -- alternatively: {finish} case A.A_2 : {simp[f]}, case A.A_3 : {simp[f]}, end, show _, by {simp at *, exact A3_not_in_im} end end /- The map {1,2} -> {1,2}, 1 -> 2, 2 -> 1 is bijective -/ inductive B | B_1 | B_2 def g : B → B | B.B_1 := B.B_2 | B.B_2 := B.B_1 lemma bij_g : is_bijective B B g := begin -- we check injectivity and surjectivity -- by going through all the cases have inj_g : is_injective B B g, from begin assume x : B, assume x' : B, assume g_xx' : g x = g x', cases x, case B.B_1 : begin cases x', finish, finish end, case B.B_2 : begin cases x', finish, finish end, end, have surj_g : is_surjective B B g, from begin assume y : B, cases y, case B.B_1 : begin use B.B_2, finish end, case B.B_2 : begin use B.B_1, finish end, end, show _, by {exact surj_inj_bij _ _ g surj_g inj_g} end /- And (parts of) the same thing, but with (types from) sets instead of sum types -/ def set_123 : set ℕ := {1,2,3} lemma one_in_123 : 1 ∈ set_123 := by {fconstructor,linarith} lemma two_in_123 : 2 ∈ set_123 := by {apply or.inr, finish} lemma three_in_123 : 3 ∈ set_123 := by {apply or.inr, finish} def map_const1 : set_123 → set_123 --({1,2,3} : set ℕ) → ({1,2,3} : set ℕ) := λ ⟨x, _⟩, ⟨1, one_in_123⟩ def f' : set_123 → set_123 := λ ⟨x, x_in_123⟩, if x = 3 then ⟨ 2, two_in_123 ⟩ else ⟨ 1, one_in_123 ⟩ lemma not_inj_f' : ¬ is_injective set_123 set_123 f' := begin -- idea: f' 1 = f' 2, even though 1 ≠ 2 let x1 : ↥set_123 := ⟨ 1, one_in_123 ⟩, let x2 : ↥set_123 := ⟨ 2, two_in_123 ⟩, -- we move the negation through the first all-quantifier refine (not_forall.mpr _), -- we use A_1 as first input use x1, -- we move the negation through the second all-quantifier refine (not_forall.mpr _), -- we use A_2 as second input use x2, -- we use the definition of f' by {finish}, end