Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
(************************************************************************)
(* * The Coq Proof Assistant / The Coq Development Team *)
(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
(* <O___,, * (see CREDITS file for the list of authors) *)
(* \VV/ **************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
Main result : for functions f:A→A with finite A,
f injective <-> f bijective <-> f surjective.
Require Import List Compare_dec EqNat Decidable ListDec. Require Fin. Set Implicit Arguments.
General definitions
Definition Injective {A B} (f : A->B) := forall x y, f x = f y -> x = y. Definition Surjective {A B} (f : A->B) := forall y, exists x, f x = y. Definition Bijective {A B} (f : A->B) := exists g:B->A, (forall x, g (f x) = x) /\ (forall y, f (g y) = y).
Finiteness is defined here via exhaustive list enumeration
Definition Full {A:Type} (l:list A) := forall a:A, In a l. Definition Finite (A:Type) := exists (l:list A), Full l.
In many following proofs, it will be convenient to have
list enumerations without duplicates. As soon as we have
decidability of equality (in Prop), this is equivalent
to the previous notion.
Definition Listing {A:Type} (l:list A) := NoDup l /\ Full l. Definition Finite' (A:Type) := exists (l:list A), Listing l.A:Typed:decidable_eq AFinite A <-> Finite' AA:Typed:decidable_eq AFinite A <-> Finite' AA:Typed:decidable_eq AFinite A -> Finite' AA:Typed:decidable_eq AFinite' A -> Finite AA:Typed:decidable_eq AFinite A -> Finite' AA:Typed:decidable_eq Al:list AF:Full lFinite' AA:Typed:decidable_eq Al:list AF:Full ll':list AN:NoDup l'I:incl l l'Finite' AA:Typed:decidable_eq Al:list AF:Full ll':list AN:NoDup l'I:incl l l'Listing l'A:Typed:decidable_eq Al:list AF:Full ll':list AN:NoDup l'I:incl l l'Full l'apply I, F.A:Typed:decidable_eq Al:list AF:Full ll':list AN:NoDup l'I:incl l l'x:AIn x l'A:Typed:decidable_eq AFinite' A -> Finite Anow exists l. Qed.A:Typed:decidable_eq Al:list AF:Full lFinite A
Injections characterized in term of lists
A, B:Typef:A -> Bl:list AInjective f -> NoDup l -> NoDup (map f l)A, B:Typef:A -> Bl:list AInjective f -> NoDup l -> NoDup (map f l)A, B:Typef:A -> Bl:list AIj:Injective fNoDup l -> NoDup (map f l)A, B:Typef:A -> BIj:Injective fx:Al:list AX:~ In x lN:NoDup lIH:NoDup (map f l)~ In (f x) (map f l)A, B:Typef:A -> BIj:Injective fx:Al:list AX:~ In x lN:NoDup lIH:NoDup (map f l)~ (exists x0 : A, f x0 = f x /\ In x0 l)A, B:Typef:A -> BIj:Injective fx:Al:list AX:~ In x lN:NoDup lIH:NoDup (map f l)y:AE:f y = f xY:In y lFalsenow subst. Qed.A, B:Typef:A -> BIj:Injective fx:Al:list AX:~ In x lN:NoDup lIH:NoDup (map f l)y:AE:y = xY:In y lFalseA, B:Typed:decidable_eq Af:A -> BInjective f <-> (forall l : list A, NoDup l -> NoDup (map f l))A, B:Typed:decidable_eq Af:A -> BInjective f <-> (forall l : list A, NoDup l -> NoDup (map f l))A, B:Typed:decidable_eq Af:A -> BInjective f -> forall l : list A, NoDup l -> NoDup (map f l)A, B:Typed:decidable_eq Af:A -> B(forall l : list A, NoDup l -> NoDup (map f l)) -> Injective fA, B:Typed:decidable_eq Af:A -> BInjective f -> forall l : list A, NoDup l -> NoDup (map f l)now apply Injective_map_NoDup.A, B:Typed:decidable_eq Af:A -> BH:Injective fl:list AH0:NoDup lNoDup (map f l)A, B:Typed:decidable_eq Af:A -> B(forall l : list A, NoDup l -> NoDup (map f l)) -> Injective fA, B:Typed:decidable_eq Af:A -> BH:forall l : list A, NoDup l -> NoDup (map f l)x, y:AE:f x = f yx = yA, B:Typed:decidable_eq Af:A -> BH:forall l : list A, NoDup l -> NoDup (map f l)x, y:AE:f x = f yH0:x <> yx = yA, B:Typed:decidable_eq Af:A -> BH:forall l : list A, NoDup l -> NoDup (map f l)x, y:AE:f x = f yH0:x <> yNoDup (x :: y :: nil)A, B:Typed:decidable_eq Af:A -> BH:forall l : list A, NoDup l -> NoDup (map f l)x, y:AE:f x = f yH0:x <> yN:NoDup (x :: y :: nil)x = yrepeat constructor; simpl; intuition.A, B:Typed:decidable_eq Af:A -> BH:forall l : list A, NoDup l -> NoDup (map f l)x, y:AE:f x = f yH0:x <> yNoDup (x :: y :: nil)A, B:Typed:decidable_eq Af:A -> BH:forall l : list A, NoDup l -> NoDup (map f l)x, y:AE:f x = f yH0:x <> yN:NoDup (x :: y :: nil)x = yA, B:Typed:decidable_eq Af:A -> Bx, y:AH:NoDup (map f (x :: y :: nil))E:f x = f yH0:x <> yN:NoDup (x :: y :: nil)x = yA, B:Typed:decidable_eq Af:A -> Bx, y:AH:NoDup (f x :: f y :: nil)E:f x = f yH0:x <> yN:NoDup (x :: y :: nil)x = yinversion_clear H; simpl in *; intuition. Qed.A, B:Typed:decidable_eq Af:A -> Bx, y:AH:NoDup (f y :: f y :: nil)E:f x = f yH0:x <> yN:NoDup (x :: y :: nil)x = yA, B:Typel:list AListing l -> forall f : A -> B, Injective f <-> NoDup (map f l)A, B:Typel:list AListing l -> forall f : A -> B, Injective f <-> NoDup (map f l)A, B:Typel:list AL:Listing lf:A -> BInjective f <-> NoDup (map f l)A, B:Typel:list AL:Listing lf:A -> BInjective f -> NoDup (map f l)A, B:Typel:list AL:Listing lf:A -> BNoDup (map f l) -> Injective fA, B:Typel:list AL:Listing lf:A -> BInjective f -> NoDup (map f l)A, B:Typel:list AL:Listing lf:A -> BIj:Injective fNoDup (map f l)apply L.A, B:Typel:list AL:Listing lf:A -> BIj:Injective fNoDup lA, B:Typel:list AL:Listing lf:A -> BNoDup (map f l) -> Injective fA, B:Typel:list AL:Listing lf:A -> BN:NoDup (map f l)x, y:AE:f x = f yx = yA, B:Typel:list AL:Listing lf:A -> BN:NoDup (map f l)x, y:AE:f x = f yX:In x lx = yA, B:Typel:list AL:Listing lf:A -> BN:NoDup (map f l)x, y:AE:f x = f yX:In x lY:In y lx = yA, B:Typel:list AL:Listing lf:A -> BN:NoDup (map f l)x, y:AE:f x = f yX:exists n : nat, nth_error l n = Some xY:In y lx = yA, B:Typel:list AL:Listing lf:A -> BN:NoDup (map f l)x, y:AE:f x = f yi:natX:nth_error l i = Some xY:In y lx = yA, B:Typel:list AL:Listing lf:A -> BN:NoDup (map f l)x, y:AE:f x = f yi:natX:nth_error l i = Some xY:exists n : nat, nth_error l n = Some yx = yA, B:Typel:list AL:Listing lf:A -> BN:NoDup (map f l)x, y:AE:f x = f yi:natX:nth_error l i = Some xj:natY:nth_error l j = Some yx = yA, B:Typel:list AL:Listing lf:A -> BN:NoDup (map f l)x, y:AE:f x = f yi:natX:nth_error l i = Some xj:natY:nth_error l j = Some yX':nth_error (map f l) i = Some (f x)x = yA, B:Typel:list AL:Listing lf:A -> BN:NoDup (map f l)x, y:AE:f x = f yi:natX:nth_error l i = Some xj:natY:nth_error l j = Some yX':nth_error (map f l) i = Some (f x)Y':nth_error (map f l) j = Some (f y)x = yA, B:Typel:list AL:Listing lf:A -> BN:NoDup (map f l)x, y:AE:f x = f yi:natX:nth_error l i = Some xj:natY:nth_error l j = Some yX':nth_error (map f l) i = Some (f x)Y':nth_error (map f l) j = Some (f y)i = jA, B:Typel:list AL:Listing lf:A -> BN:NoDup (map f l)x, y:AE:f x = f yi:natX:nth_error l i = Some xj:natY:nth_error l j = Some yX':nth_error (map f l) i = Some (f x)Y':nth_error (map f l) j = Some (f y)H:i = jx = yA, B:Typel:list AL:Listing lf:A -> BN:NoDup (map f l)x, y:AE:f x = f yi:natX:nth_error l i = Some xj:natY:nth_error l j = Some yX':nth_error (map f l) i = Some (f x)Y':nth_error (map f l) j = Some (f y)i = jA, B:Typel:list AL:Listing lf:A -> BN:forall i0 j0 : nat, i0 < length (map f l) -> nth_error (map f l) i0 = nth_error (map f l) j0 -> i0 = j0x, y:AE:f x = f yi:natX:nth_error l i = Some xj:natY:nth_error l j = Some yX':nth_error (map f l) i = Some (f x)Y':nth_error (map f l) j = Some (f y)i = jA, B:Typel:list AL:Listing lf:A -> BN:forall i0 j0 : nat, i0 < length (map f l) -> nth_error (map f l) i0 = nth_error (map f l) j0 -> i0 = j0x, y:AE:f x = f yi:natX:nth_error l i = Some xj:natY:nth_error l j = Some yX':nth_error (map f l) i = Some (f x)Y':nth_error (map f l) j = Some (f y)i < length (map f l)A, B:Typel:list AL:Listing lf:A -> BN:forall i0 j0 : nat, i0 < length (map f l) -> nth_error (map f l) i0 = nth_error (map f l) j0 -> i0 = j0x, y:AE:f x = f yi:natX:nth_error l i = Some xj:natY:nth_error l j = Some yX':nth_error (map f l) i = Some (f x)Y':nth_error (map f l) j = Some (f y)nth_error (map f l) i = nth_error (map f l) jA, B:Typel:list AL:Listing lf:A -> BN:forall i0 j0 : nat, i0 < length (map f l) -> nth_error (map f l) i0 = nth_error (map f l) j0 -> i0 = j0x, y:AE:f x = f yi:natX:nth_error l i = Some xj:natY:nth_error l j = Some yX':nth_error (map f l) i = Some (f x)Y':nth_error (map f l) j = Some (f y)i < length (map f l)now rewrite X'.A, B:Typel:list AL:Listing lf:A -> BN:forall i0 j0 : nat, i0 < length (map f l) -> nth_error (map f l) i0 = nth_error (map f l) j0 -> i0 = j0x, y:AE:f x = f yi:natX:nth_error l i = Some xj:natY:nth_error l j = Some yX':nth_error (map f l) i = Some (f x)Y':nth_error (map f l) j = Some (f y)nth_error (map f l) i <> NoneA, B:Typel:list AL:Listing lf:A -> BN:forall i0 j0 : nat, i0 < length (map f l) -> nth_error (map f l) i0 = nth_error (map f l) j0 -> i0 = j0x, y:AE:f x = f yi:natX:nth_error l i = Some xj:natY:nth_error l j = Some yX':nth_error (map f l) i = Some (f x)Y':nth_error (map f l) j = Some (f y)nth_error (map f l) i = nth_error (map f l) jnow f_equal.A, B:Typel:list AL:Listing lf:A -> BN:forall i0 j0 : nat, i0 < length (map f l) -> nth_error (map f l) i0 = nth_error (map f l) j0 -> i0 = j0x, y:AE:f x = f yi:natX:nth_error l i = Some xj:natY:nth_error l j = Some yX':nth_error (map f l) i = Some (f x)Y':nth_error (map f l) j = Some (f y)Some (f x) = Some (f y)A, B:Typel:list AL:Listing lf:A -> BN:NoDup (map f l)x, y:AE:f x = f yi:natX:nth_error l i = Some xj:natY:nth_error l j = Some yX':nth_error (map f l) i = Some (f x)Y':nth_error (map f l) j = Some (f y)H:i = jx = yA, B:Typel:list AL:Listing lf:A -> BN:NoDup (map f l)x, y:AE:f x = f yi:natX:nth_error l i = Some xY:nth_error l i = Some yX':nth_error (map f l) i = Some (f x)Y':nth_error (map f l) i = Some (f y)x = ynow injection X. Qed.A, B:Typel:list AL:Listing lf:A -> BN:NoDup (map f l)x, y:AE:f x = f yi:natX:Some y = Some xY:nth_error l i = Some yX':nth_error (map f l) i = Some (f x)Y':nth_error (map f l) i = Some (f y)x = y
Surjection characterized in term of lists
A, B:Typef:A -> BSurjective f <-> (forall lB : list B, exists lA : list A, incl lB (map f lA))A, B:Typef:A -> BSurjective f <-> (forall lB : list B, exists lA : list A, incl lB (map f lA))A, B:Typef:A -> BSurjective f -> forall lB : list B, exists lA : list A, incl lB (map f lA)A, B:Typef:A -> B(forall lB : list B, exists lA : list A, incl lB (map f lA)) -> Surjective fA, B:Typef:A -> BSurjective f -> forall lB : list B, exists lA : list A, incl lB (map f lA)A, B:Typef:A -> BSu:Surjective fforall lB : list B, exists lA : list A, incl lB (map f lA)A, B:Typef:A -> BSu:Surjective fexists lA : list A, incl nil (map f lA)A, B:Typef:A -> BSu:Surjective fb:BlB:list BIH:exists lA : list A, incl lB (map f lA)exists lA : list A, incl (b :: lB) (map f lA)now exists nil.A, B:Typef:A -> BSu:Surjective fexists lA : list A, incl nil (map f lA)A, B:Typef:A -> BSu:Surjective fb:BlB:list BIH:exists lA : list A, incl lB (map f lA)exists lA : list A, incl (b :: lB) (map f lA)A, B:Typef:A -> BSu:Surjective fb:BlB:list BIH:exists lA : list A, incl lB (map f lA)a:AE:f a = bexists lA : list A, incl (b :: lB) (map f lA)A, B:Typef:A -> BSu:Surjective fb:BlB:list BlA:list AIC:incl lB (map f lA)a:AE:f a = bexists lA0 : list A, incl (b :: lB) (map f lA0)A, B:Typef:A -> BSu:Surjective fb:BlB:list BlA:list AIC:incl lB (map f lA)a:AE:f a = bincl (b :: lB) (map f (a :: lA))A, B:Typef:A -> BSu:Surjective fb:BlB:list BlA:list AIC:incl lB (map f lA)a:AE:f a = bincl (b :: lB) (f a :: map f lA)intros x [X|X]; simpl; intuition.A, B:Typef:A -> BSu:Surjective fb:BlB:list BlA:list AIC:incl lB (map f lA)a:AE:f a = bincl (b :: lB) (b :: map f lA)A, B:Typef:A -> B(forall lB : list B, exists lA : list A, incl lB (map f lA)) -> Surjective fA, B:Typef:A -> BH:forall lB : list B, exists lA : list A, incl lB (map f lA)y:Bexists x : A, f x = yA, B:Typef:A -> BH:forall lB : list B, exists lA0 : list A, incl lB (map f lA0)y:BlA:list AIC:incl (y :: nil) (map f lA)exists x : A, f x = yA, B:Typef:A -> BH:forall lB : list B, exists lA0 : list A, incl lB (map f lA0)y:BlA:list AIC:incl (y :: nil) (map f lA)IN:In y (map f lA)exists x : A, f x = yA, B:Typef:A -> BH:forall lB : list B, exists lA0 : list A, incl lB (map f lA0)y:BlA:list AIC:incl (y :: nil) (map f lA)IN:exists x : A, f x = y /\ In x lAexists x : A, f x = ynow exists x. Qed.A, B:Typef:A -> BH:forall lB : list B, exists lA0 : list A, incl lB (map f lA0)y:BlA:list AIC:incl (y :: nil) (map f lA)x:AE:f x = yexists x0 : A, f x0 = yA, B:TypeFinite B -> decidable_eq B -> forall f : A -> B, Surjective f <-> (exists lA : list A, Listing (map f lA))A, B:TypeFinite B -> decidable_eq B -> forall f : A -> B, Surjective f <-> (exists lA : list A, Listing (map f lA))A, B:TypelB:list BFB:Full lBd:decidable_eq Bforall f : A -> B, Surjective f <-> (exists lA : list A, Listing (map f lA))A, B:TypelB:list BFB:Full lBd:decidable_eq Bf:A -> BSurjective f -> exists lA : list A, Listing (map f lA)A, B:TypelB:list BFB:Full lBd:decidable_eq Bf:A -> B(exists lA : list A, Listing (map f lA)) -> Surjective fA, B:TypelB:list BFB:Full lBd:decidable_eq Bf:A -> BSurjective f -> exists lA : list A, Listing (map f lA)A, B:TypelB:list BFB:Full lBd:decidable_eq Bf:A -> B(forall lB0 : list B, exists lA : list A, incl lB0 (map f lA)) -> exists lA : list A, Listing (map f lA)A, B:TypelB:list BFB:Full lBd:decidable_eq Bf:A -> BSu:forall lB0 : list B, exists lA : list A, incl lB0 (map f lA)exists lA : list A, Listing (map f lA)A, B:TypelB:list BFB:Full lBd:decidable_eq Bf:A -> BSu:forall lB0 : list B, exists lA0 : list A, incl lB0 (map f lA0)lA:list AIC:incl lB (map f lA)exists lA0 : list A, Listing (map f lA0)A, B:TypelB:list BFB:Full lBd:decidable_eq Bf:A -> BSu:forall lB0 : list B, exists lA0 : list A, incl lB0 (map f lA0)lA:list AIC:incl lB (map f lA)lA':list AN:NoDup (map f lA')IC':incl (map f lA) (map f lA')exists lA0 : list A, Listing (map f lA0)A, B:TypelB:list BFB:Full lBd:decidable_eq Bf:A -> BSu:forall lB0 : list B, exists lA0 : list A, incl lB0 (map f lA0)lA:list AIC:incl lB (map f lA)lA':list AN:NoDup (map f lA')IC':incl (map f lA) (map f lA')Listing (map f lA')A, B:TypelB:list BFB:Full lBd:decidable_eq Bf:A -> BSu:forall lB0 : list B, exists lA0 : list A, incl lB0 (map f lA0)lA:list AIC:incl lB (map f lA)lA':list AN:NoDup (map f lA')IC':incl (map f lA) (map f lA')Full (map f lA')apply IC', IC, FB.A, B:TypelB:list BFB:Full lBd:decidable_eq Bf:A -> BSu:forall lB0 : list B, exists lA0 : list A, incl lB0 (map f lA0)lA:list AIC:incl lB (map f lA)lA':list AN:NoDup (map f lA')IC':incl (map f lA) (map f lA')x:BIn x (map f lA')A, B:TypelB:list BFB:Full lBd:decidable_eq Bf:A -> B(exists lA : list A, Listing (map f lA)) -> Surjective fA, B:TypelB:list BFB:Full lBd:decidable_eq Bf:A -> BlA:list AN:NoDup (map f lA)FA:Full (map f lA)y:Bexists x : A, f x = yA, B:TypelB:list BFB:Full lBd:decidable_eq Bf:A -> BlA:list AN:NoDup (map f lA)FA:Full (map f lA)y:BIn y (map f lA) -> exists x : A, f x = yA, B:TypelB:list BFB:Full lBd:decidable_eq Bf:A -> BlA:list AN:NoDup (map f lA)FA:Full (map f lA)y:B(exists x : A, f x = y /\ In x lA) -> exists x : A, f x = ynow exists x. Qed.A, B:TypelB:list BFB:Full lBd:decidable_eq Bf:A -> BlA:list AN:NoDup (map f lA)FA:Full (map f lA)y:Bx:AE:f x = yexists x0 : A, f x0 = y
Main result :
forall A : Type, Finite A -> decidable_eq A -> forall f : A -> A, Injective f <-> Surjective fforall A : Type, Finite A -> decidable_eq A -> forall f : A -> A, Injective f <-> Surjective fA:TypeF:Finite Ad:decidable_eq Af:A -> AInjective f <-> Surjective fA:TypeF:Finite Ad:decidable_eq Af:A -> AInjective f <-> (exists lA : list A, Listing (map f lA))A:TypeF:Finite Ad:decidable_eq Af:A -> AInjective f -> exists lA : list A, Listing (map f lA)A:TypeF:Finite Ad:decidable_eq Af:A -> A(exists lA : list A, Listing (map f lA)) -> Injective fA:TypeF:Finite Ad:decidable_eq Af:A -> AInjective f -> exists lA : list A, Listing (map f lA)A:TypeF:Finite' Ad:decidable_eq Af:A -> AInjective f -> exists lA : list A, Listing (map f lA)A:Typel:list AL:Listing ld:decidable_eq Af:A -> AInjective f -> exists lA : list A, Listing (map f lA)A:Typel:list AL:Listing ld:decidable_eq Af:A -> AH:NoDup (map f l)exists lA : list A, Listing (map f lA)A:Typel:list AL:Listing ld:decidable_eq Af:A -> AH:NoDup (map f l)Full (map f l)A:Typel:list AN:NoDup lF:Full ld:decidable_eq Af:A -> AH:NoDup (map f l)Full (map f l)A:Typel:list AN:NoDup lF:Full ld:decidable_eq Af:A -> AH:NoDup (map f l)incl l (map f l)A:Typel:list AN:NoDup lF:Full ld:decidable_eq Af:A -> AH:NoDup (map f l)I:incl l (map f l)Full (map f l)A:Typel:list AN:NoDup lF:Full ld:decidable_eq Af:A -> AH:NoDup (map f l)incl l (map f l)A:Typel:list AN:NoDup lF:Full ld:decidable_eq Af:A -> AH:NoDup (map f l)length l <= length (map f l)A:Typel:list AN:NoDup lF:Full ld:decidable_eq Af:A -> AH:NoDup (map f l)incl (map f l) lnow rewrite map_length.A:Typel:list AN:NoDup lF:Full ld:decidable_eq Af:A -> AH:NoDup (map f l)length l <= length (map f l)A:Typel:list AN:NoDup lF:Full ld:decidable_eq Af:A -> AH:NoDup (map f l)incl (map f l) lapply F.A:Typel:list AN:NoDup lF:Full ld:decidable_eq Af:A -> AH:NoDup (map f l)x:AIn x lA:Typel:list AN:NoDup lF:Full ld:decidable_eq Af:A -> AH:NoDup (map f l)I:incl l (map f l)Full (map f l)apply I, F.A:Typel:list AN:NoDup lF:Full ld:decidable_eq Af:A -> AH:NoDup (map f l)I:incl l (map f l)x:AIn x (map f l)A:TypeF:Finite Ad:decidable_eq Af:A -> A(exists lA : list A, Listing (map f lA)) -> Injective fA:Typef:A -> A(exists lA : list A, Listing (map f lA)) -> Injective fA:Typef:A -> Al:list AL:Listing (map f l)Injective fA:Typef:A -> Al:list AL:Listing (map f l)NoDup lA:Typef:A -> Al:list AL:Listing (map f l)N:NoDup lInjective fapply (NoDup_map_inv f), L.A:Typef:A -> Al:list AL:Listing (map f l)NoDup lA:Typef:A -> Al:list AL:Listing (map f l)N:NoDup lInjective fA:Typef:A -> Al:list AL:Listing (map f l)N:NoDup lincl (map f l) lA:Typef:A -> Al:list AL:Listing (map f l)N:NoDup lI:incl (map f l) lInjective fA:Typef:A -> Al:list AL:Listing (map f l)N:NoDup lincl (map f l) lA:Typef:A -> Al:list AL:Listing (map f l)N:NoDup llength (map f l) <= length lA:Typef:A -> Al:list AL:Listing (map f l)N:NoDup lincl l (map f l)now rewrite map_length.A:Typef:A -> Al:list AL:Listing (map f l)N:NoDup llength (map f l) <= length lA:Typef:A -> Al:list AL:Listing (map f l)N:NoDup lincl l (map f l)apply L.A:Typef:A -> Al:list AL:Listing (map f l)N:NoDup lx:AIn x (map f l)A:Typef:A -> Al:list AL:Listing (map f l)N:NoDup lI:incl (map f l) lInjective fA:Typef:A -> Al:list AL:Listing (map f l)N:NoDup lI:incl (map f l) lListing lA:Typef:A -> Al:list AL:Listing (map f l)N:NoDup lI:incl (map f l) lL':Listing lInjective fA:Typef:A -> Al:list AL:Listing (map f l)N:NoDup lI:incl (map f l) lListing lA:Typef:A -> Al:list AL:Listing (map f l)N:NoDup lI:incl (map f l) lFull lapply I, L.A:Typef:A -> Al:list AL:Listing (map f l)N:NoDup lI:incl (map f l) lx:AIn x lapply (Injective_carac L'), L. Qed.A:Typef:A -> Al:list AL:Listing (map f l)N:NoDup lI:incl (map f l) lL':Listing lInjective f
An injective and surjective function is bijective.
We need here stronger hypothesis : decidability of equality in Type.
Definition EqDec (A:Type) := forall x y:A, {x=y}+{x<>y}.
First, we show that a surjective f has an inverse function g such that
f.g = id.
(* NB: instead of (Finite A), we could ask for (RecEnum A) with: Definition RecEnum A := exists h:nat->A, surjective h. *)A:TypeFinite A -> (A -> False) \/ (exists _ : A, True)A:TypeFinite A -> (A -> False) \/ (exists _ : A, True)A:Typel:list AF:Full l(A -> False) \/ (exists _ : A, True)A:TypeF:Full nil(A -> False) \/ (exists _ : A, True)A:Typea:Al:list AF:Full (a :: l)(A -> False) \/ (exists _ : A, True)left; exact F.A:TypeF:Full nil(A -> False) \/ (exists _ : A, True)right; now exists a. Qed.A:Typea:Al:list AF:Full (a :: l)(A -> False) \/ (exists _ : A, True)forall A B : Type, Finite A -> EqDec B -> forall f : A -> B, Surjective f -> exists g : B -> A, forall x : B, f (g x) = xforall A B : Type, Finite A -> EqDec B -> forall f : A -> B, Surjective f -> exists g : B -> A, forall x : B, f (g x) = xA, B:TypeF:Finite Ad:EqDec Bf:A -> BSu:Surjective fexists g : B -> A, forall x : B, f (g x) = xA, B:TypeF:Finite Ad:EqDec Bf:A -> BSu:Surjective fnoA:A -> Falseexists g : B -> A, forall x : B, f (g x) = xA, B:TypeF:Finite Ad:EqDec Bf:A -> BSu:Surjective fa:Aexists g : B -> A, forall x : B, f (g x) = xA, B:TypeF:Finite Ad:EqDec Bf:A -> BSu:Surjective fnoA:A -> Falseexists g : B -> A, forall x : B, f (g x) = xA, B:TypeF:Finite Ad:EqDec Bf:A -> BSu:Surjective fnoA:A -> FalseB -> FalseA, B:TypeF:Finite Ad:EqDec Bf:A -> BSu:Surjective fnoA:A -> FalsenoB:B -> Falseexists g : B -> A, forall x : B, f (g x) = xA, B:TypeF:Finite Ad:EqDec Bf:A -> BSu:Surjective fnoA:A -> FalseB -> Falsenow destruct (Su y).A, B:TypeF:Finite Ad:EqDec Bf:A -> BSu:Surjective fnoA:A -> Falsey:BFalseA, B:TypeF:Finite Ad:EqDec Bf:A -> BSu:Surjective fnoA:A -> FalsenoB:B -> Falseexists g : B -> A, forall x : B, f (g x) = xA, B:TypeF:Finite Ad:EqDec Bf:A -> BSu:Surjective fnoA:A -> FalsenoB:B -> Falseforall x : B, f (False_rect A (noB x)) = xdestruct (noB y).A, B:TypeF:Finite Ad:EqDec Bf:A -> BSu:Surjective fnoA:A -> FalsenoB:B -> Falsey:Bf (False_rect A (noB y)) = yA, B:TypeF:Finite Ad:EqDec Bf:A -> BSu:Surjective fa:Aexists g : B -> A, forall x : B, f (g x) = xA, B:Typel:list AF:Full ld:EqDec Bf:A -> BSu:Surjective fa:Aexists g : B -> A, forall x : B, f (g x) = xA, B:Typel:list AF:Full ld:EqDec Bf:A -> BSu:Surjective fa:Ah:=fun (x : B) (k : A) => if d (f k) x then true else false:B -> A -> boolexists g : B -> A, forall x : B, f (g x) = xA, B:Typel:list AF:Full ld:EqDec Bf:A -> BSu:Surjective fa:Ah:=fun (x : B) (k : A) => if d (f k) x then true else false:B -> A -> boolget:=fun o : option A => match o with | Some y => y | None => a end:option A -> Aexists g : B -> A, forall x : B, f (g x) = xA, B:Typel:list AF:Full ld:EqDec Bf:A -> BSu:Surjective fa:Ah:=fun (x : B) (k : A) => if d (f k) x then true else false:B -> A -> boolget:=fun o : option A => match o with | Some y => y | None => a end:option A -> Aforall x : B, f (get (find (h x) l)) = xA, B:Typel:list AF:Full ld:EqDec Bf:A -> BSu:Surjective fa:Ah:=fun (x0 : B) (k : A) => if d (f k) x0 then true else false:B -> A -> boolget:=fun o : option A => match o with | Some y => y | None => a end:option A -> Ax:Bf (get (find (h x) l)) = xA, B:Typel:list AF:Full ld:EqDec Bf:A -> BSu:Surjective fa:Ah:=fun (x0 : B) (k : A) => if d (f k) x0 then true else false:B -> A -> boolx:By:AH:find (h x) l = Some yf y = xA, B:Typel:list AF:Full ld:EqDec Bf:A -> BSu:Surjective fa:Ah:=fun (x0 : B) (k : A) => if d (f k) x0 then true else false:B -> A -> boolx:BH:find (h x) l = Nonef a = xA, B:Typel:list AF:Full ld:EqDec Bf:A -> BSu:Surjective fa:Ah:=fun (x0 : B) (k : A) => if d (f k) x0 then true else false:B -> A -> boolx:By:AH:find (h x) l = Some yf y = xA, B:Typel:list AF:Full ld:EqDec Bf:A -> BSu:Surjective fa:Ah:=fun (x0 : B) (k : A) => if d (f k) x0 then true else false:B -> A -> boolx:By:AH:In y l /\ h x y = truef y = xA, B:Typel:list AF:Full ld:EqDec Bf:A -> BSu:Surjective fa:Ah:=fun (x0 : B) (k : A) => if d (f k) x0 then true else false:B -> A -> boolx:By:AH:h x y = truef y = xnow destruct (d (f y) x) in H.A, B:Typel:list AF:Full ld:EqDec Bf:A -> BSu:Surjective fa:Ah:=fun (x0 : B) (k : A) => if d (f k) x0 then true else false:B -> A -> boolx:By:AH:(if d (f y) x then true else false) = truef y = xA, B:Typel:list AF:Full ld:EqDec Bf:A -> BSu:Surjective fa:Ah:=fun (x0 : B) (k : A) => if d (f k) x0 then true else false:B -> A -> boolx:BH:find (h x) l = Nonef a = xA, B:Typel:list AF:Full ld:EqDec Bf:A -> BSu:Surjective fa:Ah:=fun (x0 : B) (k : A) => if d (f k) x0 then true else false:B -> A -> boolx:BH:find (h x) l = NoneFalseA, B:Typel:list AF:Full ld:EqDec Bf:A -> BSu:Surjective fa:Ah:=fun (x0 : B) (k : A) => if d (f k) x0 then true else false:B -> A -> boolx:BH:find (h x) l = Noney:AY:f y = xFalseA, B:Typel:list AF:Full ld:EqDec Bf:A -> BSu:Surjective fa:Ah:=fun (x0 : B) (k : A) => if d (f k) x0 then true else false:B -> A -> boolx:BH:find (h x) l = Noney:AY:f y = xh x y = false -> Falsenow destruct (d (f y) x). Qed.A, B:Typel:list AF:Full ld:EqDec Bf:A -> BSu:Surjective fa:Ah:=fun (x0 : B) (k : A) => if d (f k) x0 then true else false:B -> A -> boolx:BH:find (h x) l = Noney:AY:f y = x(if d (f y) x then true else false) = false -> False
Same, with more knowledge on the inverse function: g.f = f.g = id
forall A B : Type, Finite A -> EqDec B -> forall f : A -> B, Injective f -> Surjective f -> Bijective fforall A B : Type, Finite A -> EqDec B -> forall f : A -> B, Injective f -> Surjective f -> Bijective fA, B:TypeF:Finite Ad:EqDec Bf:A -> BIj:Injective fSu:Surjective fBijective fA, B:TypeF:Finite Ad:EqDec Bf:A -> BIj:Injective fSu:Surjective fg:B -> AE:forall x : B, f (g x) = xBijective fA, B:TypeF:Finite Ad:EqDec Bf:A -> BIj:Injective fSu:Surjective fg:B -> AE:forall x : B, f (g x) = x(forall x : A, g (f x) = x) /\ (forall y : B, f (g y) = y)A, B:TypeF:Finite Ad:EqDec Bf:A -> BIj:Injective fSu:Surjective fg:B -> AE:forall x : B, f (g x) = xforall x : A, g (f x) = xA, B:TypeF:Finite Ad:EqDec Bf:A -> BIj:Injective fSu:Surjective fg:B -> AE:forall x : B, f (g x) = xy:Ag (f y) = ynow rewrite E. Qed.A, B:TypeF:Finite Ad:EqDec Bf:A -> BIj:Injective fSu:Surjective fg:B -> AE:forall x : B, f (g x) = xy:Af (g (f y)) = f y
An example of finite type : Fin.t
n:natFinite (Fin.t n)n:natFinite (Fin.t n)Finite (Fin.t 0)n:natIHn:Finite (Fin.t n)Finite (Fin.t (S n))Finite (Fin.t 0)red;inversion a.Full niln:natIHn:Finite (Fin.t n)Finite (Fin.t (S n))n:natl:list (Fin.t n)Hl:Full lFinite (Fin.t (S n))n:natl:list (Fin.t n)Hl:Full lFull (Fin.F1 :: map Fin.FS l)n:natl:list (Fin.t n)Hl:Full la:Fin.t (S n)In a (Fin.F1 :: map Fin.FS l)forall (n : nat) (a : Fin.t (S n)) (l : list (Fin.t n)), Full l -> In a (Fin.F1 :: map Fin.FS l)n:natl:list (Fin.t n)Hl:Full lIn Fin.F1 (Fin.F1 :: map Fin.FS l)n:natp:Fin.t nl:list (Fin.t n)Hl:Full lIn (Fin.FS p) (Fin.F1 :: map Fin.FS l)now left.n:natl:list (Fin.t n)Hl:Full lIn Fin.F1 (Fin.F1 :: map Fin.FS l)n:natp:Fin.t nl:list (Fin.t n)Hl:Full lIn (Fin.FS p) (Fin.F1 :: map Fin.FS l)now apply in_map. Qed.n:natp:Fin.t nl:list (Fin.t n)Hl:Full lIn (Fin.FS p) (map Fin.FS l)
Instead of working on a finite subset of nat, another
solution is to use restricted nat→nat functions, and
to consider them only below a certain bound n.
Definition bFun n (f:nat->nat) := forall x, x < n -> f x < n. Definition bInjective n (f:nat->nat) := forall x y, x < n -> y < n -> f x = f y -> x = y. Definition bSurjective n (f:nat->nat) := forall y, y < n -> exists x, x < n /\ f x = y.
We show that this is equivalent to the use of Fin.t n.
Module Fin2Restrict. Notation n2f := Fin.of_nat_lt. Definition f2n {n} (x:Fin.t n) := proj1_sig (Fin.to_nat x). Definition f2n_ok n (x:Fin.t n) : f2n x < n := proj2_sig (Fin.to_nat x). Definition n2f_f2n : forall n x, n2f (f2n_ok x) = x := @Fin.of_nat_to_nat_inv. Definition f2n_n2f x n h : f2n (n2f h) = x := f_equal (@proj1_sig _ _) (@Fin.to_nat_of_nat x n h). Definition n2f_ext : forall x n h h', n2f h = n2f h' := @Fin.of_nat_ext. Definition f2n_inj : forall n x y, f2n x = f2n y -> x = y := @Fin.to_nat_inj. Definition extend n (f:Fin.t n -> Fin.t n) : (nat->nat) := fun x => match le_lt_dec n x with | left _ => 0 | right h => f2n (f (n2f h)) end. Definition restrict n (f:nat->nat)(hf : bFun n f) : (Fin.t n -> Fin.t n) := fun x => let (x',h) := Fin.to_nat x in n2f (hf _ h). Ltac break_dec H := let H' := fresh "H" in destruct le_lt_dec as [H'|H']; [elim (Lt.le_not_lt _ _ H' H) |try rewrite (n2f_ext H' H) in *; try clear H'].n:natf:Fin.t n -> Fin.t nbFun n (extend f)n:natf:Fin.t n -> Fin.t nbFun n (extend f)n:natf:Fin.t n -> Fin.t nx:nath:x < nextend f x < nn:natf:Fin.t n -> Fin.t nx:nath:x < nmatch le_lt_dec n x with | left _ => 0 | right h0 => f2n (f (n2f h0)) end < napply f2n_ok. Qed.n:natf:Fin.t n -> Fin.t nx:nath:x < nf2n (f (n2f h)) < nn:natf:Fin.t n -> Fin.t nx:Fin.t nextend f (f2n x) = f2n (f x)n:natf:Fin.t n -> Fin.t nx:Fin.t nextend f (f2n x) = f2n (f x)n:natf:Fin.t n -> Fin.t nx:Fin.t nn2f (f2n_ok x) = x -> extend f (f2n x) = f2n (f x)n:natf:Fin.t n -> Fin.t nx:Fin.t nn2f (proj2_sig (Fin.to_nat x)) = x -> match le_lt_dec n (proj1_sig (Fin.to_nat x)) with | left _ => 0 | right h => proj1_sig (Fin.to_nat (f (n2f h))) end = proj1_sig (Fin.to_nat (f x))n:natf:Fin.t n -> Fin.t nx:Fin.t nx':nath:x' < nn2f h = x -> match le_lt_dec n x' with | left _ => 0 | right h0 => proj1_sig (Fin.to_nat (f (n2f h0))) end = proj1_sig (Fin.to_nat (f x))now intros ->. Qed.n:natf:Fin.t n -> Fin.t nx:Fin.t nx':nath:x' < nn2f h = x -> proj1_sig (Fin.to_nat (f (n2f h))) = proj1_sig (Fin.to_nat (f x))n:natf:Fin.t n -> Fin.t nx:nath:x < nn2f (extend_ok f h) = f (n2f h)n:natf:Fin.t n -> Fin.t nx:nath:x < nn2f (extend_ok f h) = f (n2f h)n:natf:Fin.t n -> Fin.t nx:nath:x < nforall l : extend f x < n, n2f l = f (n2f h)n:natf:Fin.t n -> Fin.t nx:nath:x < nforall l : match le_lt_dec n x with | left _ => 0 | right h0 => f2n (f (n2f h0)) end < n, n2f l = f (n2f h)n:natf:Fin.t n -> Fin.t nx:nath:x < nforall l : f2n (f (n2f h)) < n, n2f l = f (n2f h)n:natf:Fin.t n -> Fin.t nx:nath:x < nh':f2n (f (n2f h)) < nn2f h' = f (n2f h)now apply n2f_ext. Qed.n:natf:Fin.t n -> Fin.t nx:nath:x < nh':f2n (f (n2f h)) < nn2f h' = n2f (f2n_ok (f (n2f h)))n:natf:nat -> nathf:bFun n fx:Fin.t nf2n (restrict hf x) = f (f2n x)n:natf:nat -> nathf:bFun n fx:Fin.t nf2n (restrict hf x) = f (f2n x)n:natf:nat -> nathf:bFun n fx:Fin.t nproj1_sig (Fin.to_nat (let (x', h) := Fin.to_nat x in n2f (hf x' h))) = f (proj1_sig (Fin.to_nat x))apply f2n_n2f. Qed.n:natf:nat -> nathf:bFun n fx:Fin.t nx':nath:x' < nproj1_sig (Fin.to_nat (n2f (hf x' h))) = f x'n:natf:nat -> nathf:bFun n fx:nath:x < nrestrict hf (n2f h) = n2f (hf x h)n:natf:nat -> nathf:bFun n fx:nath:x < nrestrict hf (n2f h) = n2f (hf x h)n:natf:nat -> nathf:bFun n fx:nath:x < n(let (x', h0) := Fin.to_nat (n2f h) in n2f (hf x' h0)) = n2f (hf x h)n:natf:nat -> nathf:bFun n fx:nath:x < nf2n (n2f h) = x -> (let (x', h0) := Fin.to_nat (n2f h) in n2f (hf x' h0)) = n2f (hf x h)n:natf:nat -> nathf:bFun n fx:nath:x < nproj1_sig (Fin.to_nat (n2f h)) = x -> (let (x', h0) := Fin.to_nat (n2f h) in n2f (hf x' h0)) = n2f (hf x h)n:natf:nat -> nathf:bFun n fx:nath:x < nx':nath':x' < nx' = x -> n2f (hf x' h') = n2f (hf x h)now apply n2f_ext. Qed.n:natf:nat -> nathf:bFun n fx:nath, h':x < nn2f (hf x h') = n2f (hf x h)n:natf:Fin.t n -> Fin.t nbSurjective n (extend f) <-> Surjective fn:natf:Fin.t n -> Fin.t nbSurjective n (extend f) <-> Surjective fn:natf:Fin.t n -> Fin.t nbSurjective n (extend f) -> Surjective fn:natf:Fin.t n -> Fin.t nSurjective f -> bSurjective n (extend f)n:natf:Fin.t n -> Fin.t nbSurjective n (extend f) -> Surjective fn:natf:Fin.t n -> Fin.t nhf:bSurjective n (extend f)y:Fin.t nexists x : Fin.t n, f x = yn:natf:Fin.t n -> Fin.t nhf:bSurjective n (extend f)y:Fin.t nx:nath:x < nEq:extend f x = f2n yexists x0 : Fin.t n, f x0 = yn:natf:Fin.t n -> Fin.t nhf:bSurjective n (extend f)y:Fin.t nx:nath:x < nEq:extend f x = f2n yf (n2f h) = ynow rewrite <- Eq, <- extend_f2n, f2n_n2f.n:natf:Fin.t n -> Fin.t nhf:bSurjective n (extend f)y:Fin.t nx:nath:x < nEq:extend f x = f2n yf2n (f (n2f h)) = f2n yn:natf:Fin.t n -> Fin.t nSurjective f -> bSurjective n (extend f)n:natf:Fin.t n -> Fin.t nhf:Surjective fy:nathy:y < nexists x : nat, x < n /\ extend f x = yn:natf:Fin.t n -> Fin.t nhf:Surjective fy:nathy:y < nx:Fin.t nEq:f x = n2f hyexists x0 : nat, x0 < n /\ extend f x0 = yn:natf:Fin.t n -> Fin.t nhf:Surjective fy:nathy:y < nx:Fin.t nEq:f x = n2f hyf2n x < n /\ extend f (f2n x) = yn:natf:Fin.t n -> Fin.t nhf:Surjective fy:nathy:y < nx:Fin.t nEq:f x = n2f hyf2n x < nn:natf:Fin.t n -> Fin.t nhf:Surjective fy:nathy:y < nx:Fin.t nEq:f x = n2f hyextend f (f2n x) = yapply f2n_ok.n:natf:Fin.t n -> Fin.t nhf:Surjective fy:nathy:y < nx:Fin.t nEq:f x = n2f hyf2n x < nn:natf:Fin.t n -> Fin.t nhf:Surjective fy:nathy:y < nx:Fin.t nEq:f x = n2f hyextend f (f2n x) = yapply f2n_n2f. Qed.n:natf:Fin.t n -> Fin.t nhf:Surjective fy:nathy:y < nx:Fin.t nEq:f x = n2f hyf2n (n2f hy) = yn:natf:Fin.t n -> Fin.t nbInjective n (extend f) <-> Injective fn:natf:Fin.t n -> Fin.t nbInjective n (extend f) <-> Injective fn:natf:Fin.t n -> Fin.t nbInjective n (extend f) -> Injective fn:natf:Fin.t n -> Fin.t nInjective f -> bInjective n (extend f)n:natf:Fin.t n -> Fin.t nbInjective n (extend f) -> Injective fn:natf:Fin.t n -> Fin.t nhf:bInjective n (extend f)x, y:Fin.t nEq:f x = f yx = yn:natf:Fin.t n -> Fin.t nhf:bInjective n (extend f)x, y:Fin.t nEq:f x = f yf2n x = f2n ynow rewrite 2 extend_f2n, Eq.n:natf:Fin.t n -> Fin.t nhf:bInjective n (extend f)x, y:Fin.t nEq:f x = f yextend f (f2n x) = extend f (f2n y)n:natf:Fin.t n -> Fin.t nInjective f -> bInjective n (extend f)n:natf:Fin.t n -> Fin.t nhf:Injective fx, y:nathx:x < nhy:y < nEq:extend f x = extend f yx = yn:natf:Fin.t n -> Fin.t nhf:Injective fx, y:nathx:x < nhy:y < nEq:extend f x = extend f yf2n (n2f hx) = f2n (n2f hy)n:natf:Fin.t n -> Fin.t nhf:Injective fx, y:nathx:x < nhy:y < nEq:extend f x = extend f yn2f hx = n2f hyn:natf:Fin.t n -> Fin.t nhf:Injective fx, y:nathx:x < nhy:y < nEq:extend f x = extend f yf (n2f hx) = f (n2f hy)n:natf:Fin.t n -> Fin.t nhf:Injective fx, y:nathx:x < nhy:y < nEq:extend f x = extend f yn2f (extend_ok f hx) = n2f (extend_ok f hy)n:natf:Fin.t n -> Fin.t nhf:Injective fx, y:nathx:x < nhy:y < nEq:extend f x = extend f yforall (l : extend f x < n) (l0 : extend f y < n), n2f l = n2f l0apply n2f_ext. Qed.n:natf:Fin.t n -> Fin.t nhf:Injective fx, y:nathx:x < nhy:y < nEq:extend f x = extend f yforall l l0 : extend f y < n, n2f l = n2f l0n:natf:nat -> nath:bFun n fSurjective (restrict h) <-> bSurjective n fn:natf:nat -> nath:bFun n fSurjective (restrict h) <-> bSurjective n fn:natf:nat -> nath:bFun n fSurjective (restrict h) -> bSurjective n fn:natf:nat -> nath:bFun n fbSurjective n f -> Surjective (restrict h)n:natf:nat -> nath:bFun n fSurjective (restrict h) -> bSurjective n fn:natf:nat -> nath:bFun n fhf:Surjective (restrict h)y:nathy:y < nexists x : nat, x < n /\ f x = yn:natf:nat -> nath:bFun n fhf:Surjective (restrict h)y:nathy:y < nx:Fin.t nEq:restrict h x = n2f hyexists x0 : nat, x0 < n /\ f x0 = yn:natf:nat -> nath:bFun n fhf:Surjective (restrict h)y:nathy:y < nx:Fin.t nEq:restrict h x = n2f hyf2n x < n /\ f (f2n x) = yn:natf:nat -> nath:bFun n fhf:Surjective (restrict h)y:nathy:y < nx:Fin.t nEq:restrict h x = n2f hyf2n x < nn:natf:nat -> nath:bFun n fhf:Surjective (restrict h)y:nathy:y < nx:Fin.t nEq:restrict h x = n2f hyf (f2n x) = yapply f2n_ok.n:natf:nat -> nath:bFun n fhf:Surjective (restrict h)y:nathy:y < nx:Fin.t nEq:restrict h x = n2f hyf2n x < nn:natf:nat -> nath:bFun n fhf:Surjective (restrict h)y:nathy:y < nx:Fin.t nEq:restrict h x = n2f hyf (f2n x) = yapply f2n_n2f.n:natf:nat -> nath:bFun n fhf:Surjective (restrict h)y:nathy:y < nx:Fin.t nEq:restrict h x = n2f hyf2n (n2f hy) = yn:natf:nat -> nath:bFun n fbSurjective n f -> Surjective (restrict h)n:natf:nat -> nath:bFun n fhf:bSurjective n fy:Fin.t nexists x : Fin.t n, restrict h x = yn:natf:nat -> nath:bFun n fhf:bSurjective n fy:Fin.t nx:nathx:x < nEq:f x = f2n yexists x0 : Fin.t n, restrict h x0 = yn:natf:nat -> nath:bFun n fhf:bSurjective n fy:Fin.t nx:nathx:x < nEq:f x = f2n yrestrict h (n2f hx) = ynow rewrite restrict_f2n, f2n_n2f. Qed.n:natf:nat -> nath:bFun n fhf:bSurjective n fy:Fin.t nx:nathx:x < nEq:f x = f2n yf2n (restrict h (n2f hx)) = f2n yn:natf:nat -> nath:bFun n fInjective (restrict h) <-> bInjective n fn:natf:nat -> nath:bFun n fInjective (restrict h) <-> bInjective n fn:natf:nat -> nath:bFun n fInjective (restrict h) -> bInjective n fn:natf:nat -> nath:bFun n fbInjective n f -> Injective (restrict h)n:natf:nat -> nath:bFun n fInjective (restrict h) -> bInjective n fn:natf:nat -> nath:bFun n fhf:Injective (restrict h)x, y:nathx:x < nhy:y < nEq:f x = f yx = yn:natf:nat -> nath:bFun n fhf:Injective (restrict h)x, y:nathx:x < nhy:y < nEq:f x = f yf2n (n2f hx) = f2n (n2f hy)n:natf:nat -> nath:bFun n fhf:Injective (restrict h)x, y:nathx:x < nhy:y < nEq:f x = f yn2f hx = n2f hyn:natf:nat -> nath:bFun n fhf:Injective (restrict h)x, y:nathx:x < nhy:y < nEq:f x = f yrestrict h (n2f hx) = restrict h (n2f hy)n:natf:nat -> nath:bFun n fhf:Injective (restrict h)x, y:nathx:x < nhy:y < nEq:f x = f yn2f (h x hx) = n2f (h y hy)n:natf:nat -> nath:bFun n fhf:Injective (restrict h)x, y:nathx:x < nhy:y < nEq:f x = f yforall (l : f x < n) (l0 : f y < n), n2f l = n2f l0apply n2f_ext.n:natf:nat -> nath:bFun n fhf:Injective (restrict h)x, y:nathx:x < nhy:y < nEq:f x = f yforall l l0 : f y < n, n2f l = n2f l0n:natf:nat -> nath:bFun n fbInjective n f -> Injective (restrict h)n:natf:nat -> nath:bFun n fhf:bInjective n fx, y:Fin.t nEq:restrict h x = restrict h yx = yn:natf:nat -> nath:bFun n fhf:bInjective n fx, y:Fin.t nEq:restrict h x = restrict h yf2n x = f2n ynow rewrite <- 2 (restrict_f2n h), Eq. Qed. End Fin2Restrict. Import Fin2Restrict.n:natf:nat -> nath:bFun n fhf:bInjective n fx, y:Fin.t nEq:restrict h x = restrict h yf (f2n x) = f (f2n y)
We can now use Proof via the equivalence ...
n:natf:nat -> natbFun n f -> bInjective n f <-> bSurjective n fn:natf:nat -> natbFun n f -> bInjective n f <-> bSurjective n fn:natf:nat -> nath:bFun n fbInjective n f <-> bSurjective n fn:natf:nat -> nath:bFun n fInjective (restrict h) <-> Surjective (restrict h)n:natf:nat -> nath:bFun n fFinite (Fin.t n)n:natf:nat -> nath:bFun n fdecidable_eq (Fin.t n)apply Fin_Finite.n:natf:nat -> nath:bFun n fFinite (Fin.t n)n:natf:nat -> nath:bFun n fdecidable_eq (Fin.t n)destruct (Fin.eq_dec x y); [left|right]; trivial. Qed.n:natf:nat -> nath:bFun n fx, y:Fin.t ndecidable (x = y)n:natf:nat -> natbFun n f -> bSurjective n f -> exists g : nat -> nat, bFun n g /\ (forall x : nat, x < n -> g (f x) = x /\ f (g x) = x)n:natf:nat -> natbFun n f -> bSurjective n f -> exists g : nat -> nat, bFun n g /\ (forall x : nat, x < n -> g (f x) = x /\ f (g x) = x)n:natf:nat -> nathf:bFun n fbSurjective n f -> exists g : nat -> nat, bFun n g /\ (forall x : nat, x < n -> g (f x) = x /\ f (g x) = x)n:natf:nat -> nathf:bFun n fSurjective (restrict hf) -> exists g : nat -> nat, bFun n g /\ (forall x : nat, x < n -> g (f x) = x /\ f (g x) = x)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)exists g : nat -> nat, bFun n g /\ (forall x : nat, x < n -> g (f x) = x /\ f (g x) = x)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Injective (restrict hf)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)exists g : nat -> nat, bFun n g /\ (forall x : nat, x < n -> g (f x) = x /\ f (g x) = x)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Injective (restrict hf)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Finite (Fin.t n)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)decidable_eq (Fin.t n)apply Fin_Finite.n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Finite (Fin.t n)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)decidable_eq (Fin.t n)destruct (Fin.eq_dec x y); [left|right]; trivial.n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)x, y:Fin.t ndecidable (x = y)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)exists g : nat -> nat, bFun n g /\ (forall x : nat, x < n -> g (f x) = x /\ f (g x) = x)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)Bijective (restrict hf)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)Bi:Bijective (restrict hf)exists g : nat -> nat, bFun n g /\ (forall x : nat, x < n -> g (f x) = x /\ f (g x) = x)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)Bijective (restrict hf)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)Finite (Fin.t n)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)EqDec (Fin.t n)apply Fin_Finite.n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)Finite (Fin.t n)exact Fin.eq_dec.n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)EqDec (Fin.t n)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)Bi:Bijective (restrict hf)exists g : nat -> nat, bFun n g /\ (forall x : nat, x < n -> g (f x) = x /\ f (g x) = x)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)g:Fin.t n -> Fin.t nHg:forall x : Fin.t n, g (restrict hf x) = xHg':forall y : Fin.t n, restrict hf (g y) = yexists g0 : nat -> nat, bFun n g0 /\ (forall x : nat, x < n -> g0 (f x) = x /\ f (g0 x) = x)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)g:Fin.t n -> Fin.t nHg:forall x : Fin.t n, g (restrict hf x) = xHg':forall y : Fin.t n, restrict hf (g y) = ybFun n (extend g) /\ (forall x : nat, x < n -> extend g (f x) = x /\ f (extend g x) = x)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)g:Fin.t n -> Fin.t nHg:forall x : Fin.t n, g (restrict hf x) = xHg':forall y : Fin.t n, restrict hf (g y) = ybFun n (extend g)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)g:Fin.t n -> Fin.t nHg:forall x : Fin.t n, g (restrict hf x) = xHg':forall y : Fin.t n, restrict hf (g y) = yforall x : nat, x < n -> extend g (f x) = x /\ f (extend g x) = xapply extend_ok.n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)g:Fin.t n -> Fin.t nHg:forall x : Fin.t n, g (restrict hf x) = xHg':forall y : Fin.t n, restrict hf (g y) = ybFun n (extend g)n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)g:Fin.t n -> Fin.t nHg:forall x : Fin.t n, g (restrict hf x) = xHg':forall y : Fin.t n, restrict hf (g y) = yforall x : nat, x < n -> extend g (f x) = x /\ f (extend g x) = xn:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)g:Fin.t n -> Fin.t nHg:forall x0 : Fin.t n, g (restrict hf x0) = x0Hg':forall y : Fin.t n, restrict hf (g y) = yx:natHx:x < nextend g (f x) = x /\ f (extend g x) = xn:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)g:Fin.t n -> Fin.t nHg:forall x0 : Fin.t n, g (restrict hf x0) = x0Hg':forall y : Fin.t n, restrict hf (g y) = yx:natHx:x < nextend g (f x) = xn:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)g:Fin.t n -> Fin.t nHg:forall x0 : Fin.t n, g (restrict hf x0) = x0Hg':forall y : Fin.t n, restrict hf (g y) = yx:natHx:x < nf (extend g x) = xnow rewrite <- (f2n_n2f Hx), <- (restrict_f2n hf), extend_f2n, Hg.n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)g:Fin.t n -> Fin.t nHg:forall x0 : Fin.t n, g (restrict hf x0) = x0Hg':forall y : Fin.t n, restrict hf (g y) = yx:natHx:x < nextend g (f x) = xnow rewrite <- (f2n_n2f Hx), extend_f2n, <- (restrict_f2n hf), Hg'. Qed.n:natf:nat -> nathf:bFun n fSu:Surjective (restrict hf)Ij:Injective (restrict hf)g:Fin.t n -> Fin.t nHg:forall x0 : Fin.t n, g (restrict hf x0) = x0Hg':forall y : Fin.t n, restrict hf (g y) = yx:natHx:x < nf (extend g x) = x