aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--theories/Lists/List.v147
-rw-r--r--theories/Lists/ListDec.v103
-rw-r--r--theories/Lists/vo.itarget1
-rw-r--r--theories/Logic/FinFun.v400
-rw-r--r--theories/Logic/vo.itarget1
-rw-r--r--theories/Sorting/Permutation.v211
-rw-r--r--theories/Vectors/Fin.v36
7 files changed, 736 insertions, 163 deletions
diff --git a/theories/Lists/List.v b/theories/Lists/List.v
index d5d58efc7..d282fe8c3 100644
--- a/theories/Lists/List.v
+++ b/theories/Lists/List.v
@@ -522,7 +522,6 @@ Section Elts.
simpl in *. apply IHn. auto with arith.
Qed.
-
(*****************)
(** ** Remove *)
(*****************)
@@ -1178,6 +1177,21 @@ End Fold_Right_Recursor.
| x :: tl => if f x then Some x else find tl
end.
+ Lemma find_some l x : find l = Some x -> In x l /\ f x = true.
+ Proof.
+ induction l as [|a l IH]; simpl; [easy| ].
+ case_eq (f a); intros Ha Eq.
+ * injection Eq as ->; auto.
+ * destruct (IH Eq); auto.
+ Qed.
+
+ Lemma find_none l : find l = None -> forall x, In x l -> f x = false.
+ Proof.
+ induction l as [|a l IH]; simpl; [easy|].
+ case_eq (f a); intros Ha Eq x IN; [easy|].
+ destruct IN as [<-|IN]; auto.
+ Qed.
+
(** [partition] *)
Fixpoint partition (l:list A) : list A * list A :=
@@ -1582,6 +1596,61 @@ Section Cutting.
End Cutting.
+(**********************************************************************)
+(** ** Predicate for List addition/removal (no need for decidability) *)
+(**********************************************************************)
+
+Section Add.
+
+ Variable A : Type.
+
+ (* [Add a l l'] means that [l'] is exactly [l], with [a] added
+ once somewhere *)
+ Inductive Add (a:A) : list A -> list A -> Prop :=
+ | Add_head l : Add a l (a::l)
+ | Add_cons x l l' : Add a l l' -> Add a (x::l) (x::l').
+
+ Lemma Add_app a l1 l2 : Add a (l1++l2) (l1++a::l2).
+ Proof.
+ induction l1; simpl; now constructor.
+ Qed.
+
+ Lemma Add_split a l l' :
+ Add a l l' -> exists l1 l2, l = l1++l2 /\ l' = l1++a::l2.
+ Proof.
+ induction 1.
+ - exists nil; exists l; split; trivial.
+ - destruct IHAdd as (l1 & l2 & Hl & Hl').
+ exists (x::l1); exists l2; split; simpl; f_equal; trivial.
+ Qed.
+
+ Lemma Add_in a l l' : Add a l l' ->
+ forall x, In x l' <-> In x (a::l).
+ Proof.
+ induction 1; intros; simpl in *; rewrite ?IHAdd; tauto.
+ Qed.
+
+ Lemma Add_length a l l' : Add a l l' -> length l' = S (length l).
+ Proof.
+ induction 1; simpl; auto with arith.
+ Qed.
+
+ Lemma Add_inv a l : In a l -> exists l', Add a l' l.
+ Proof.
+ intro Ha. destruct (in_split _ _ Ha) as (l1 & l2 & ->).
+ exists (l1 ++ l2). apply Add_app.
+ Qed.
+
+ Lemma incl_Add_inv a l u v :
+ ~In a l -> incl (a::l) v -> Add a u v -> incl l u.
+ Proof.
+ intros Ha H AD y Hy.
+ assert (Hy' : In y (a::u)).
+ { rewrite <- (Add_in AD). apply H; simpl; auto. }
+ destruct Hy'; [ subst; now elim Ha | trivial ].
+ Qed.
+
+End Add.
(********************************)
(** ** Lists without redundancy *)
@@ -1595,27 +1664,32 @@ Section ReDun.
| NoDup_nil : NoDup nil
| NoDup_cons : forall x l, ~ In x l -> NoDup l -> NoDup (x::l).
- Lemma NoDup_remove_1 : forall l l' a, NoDup (l++a::l') -> NoDup (l++l').
+ Lemma NoDup_Add a l l' : Add a l l' -> (NoDup l' <-> NoDup l /\ ~In a l).
+ Proof.
+ induction 1 as [l|x l l' AD IH].
+ - split; [ inversion_clear 1; now split | now constructor ].
+ - split.
+ + inversion_clear 1. rewrite IH in *. rewrite (Add_in AD) in *.
+ simpl in *; split; try constructor; intuition.
+ + intros (N,IN). inversion_clear N. constructor.
+ * rewrite (Add_in AD); simpl in *; intuition.
+ * apply IH. split; trivial. simpl in *; intuition.
+ Qed.
+
+ Lemma NoDup_remove l l' a :
+ NoDup (l++a::l') -> NoDup (l++l') /\ ~In a (l++l').
+ Proof.
+ apply NoDup_Add. apply Add_app.
+ Qed.
+
+ Lemma NoDup_remove_1 l l' a : NoDup (l++a::l') -> NoDup (l++l').
Proof.
- induction l; simpl.
- inversion_clear 1; auto.
- inversion_clear 1.
- constructor.
- contradict H0.
- apply in_or_app; destruct (in_app_or _ _ _ H0); simpl; tauto.
- apply IHl with a0; auto.
+ intros. now apply NoDup_remove with a.
Qed.
- Lemma NoDup_remove_2 : forall l l' a, NoDup (l++a::l') -> ~In a (l++l').
+ Lemma NoDup_remove_2 l l' a : NoDup (l++a::l') -> ~In a (l++l').
Proof.
- induction l; simpl.
- inversion_clear 1; auto.
- inversion_clear 1.
- contradict H0.
- destruct H0.
- subst a0.
- apply in_or_app; right; red; auto.
- destruct (IHl _ _ H1); auto.
+ intros. now apply NoDup_remove.
Qed.
(** Alternative characterisations of being without duplicates,
@@ -1659,8 +1733,45 @@ Section ReDun.
intros i j Hi Hj E. apply eq_add_S, H; simpl; auto with arith. }
Qed.
+ (** Having [NoDup] hypotheses bring more precise facts about [incl]. *)
+
+ Lemma NoDup_incl_length l l' :
+ NoDup l -> incl l l' -> length l <= length l'.
+ Proof.
+ intros N. revert l'. induction N as [|a l Hal N IH]; simpl.
+ - auto with arith.
+ - intros l' H.
+ destruct (Add_inv a l') as (l'', AD). { apply H; simpl; auto. }
+ rewrite (Add_length AD). apply le_n_S. apply IH.
+ now apply incl_Add_inv with a l'.
+ Qed.
+
+ Lemma NoDup_length_incl l l' :
+ NoDup l -> length l' <= length l -> incl l l' -> incl l' l.
+ Proof.
+ intros N. revert l'. induction N as [|a l Hal N IH].
+ - destruct l'; easy.
+ - intros l' E H x Hx.
+ destruct (Add_inv a l') as (l'', AD). { apply H; simpl; auto. }
+ rewrite (Add_in AD) in Hx. simpl in Hx.
+ destruct Hx as [Hx|Hx]; [left; trivial|right].
+ revert x Hx. apply (IH l''); trivial.
+ * apply le_S_n. now rewrite <- (Add_length AD).
+ * now apply incl_Add_inv with a l'.
+ Qed.
+
End ReDun.
+(** NoDup and map *)
+
+(** NB: the reciprocal result holds only for injective functions,
+ see FinFun.v *)
+
+Lemma NoDup_map_inv A B (f:A->B) l : NoDup (map f l) -> NoDup l.
+Proof.
+ induction l; simpl; inversion_clear 1; subst; constructor; auto.
+ intro H. now apply (in_map f) in H.
+Qed.
(***********************************)
(** ** Sequence of natural numbers *)
diff --git a/theories/Lists/ListDec.v b/theories/Lists/ListDec.v
new file mode 100644
index 000000000..48070cbfb
--- /dev/null
+++ b/theories/Lists/ListDec.v
@@ -0,0 +1,103 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(** Decidability results about lists *)
+
+Require Import List Decidable.
+Set Implicit Arguments.
+
+Definition decidable_eq A := forall x y:A, decidable (x=y).
+
+Section Dec_in_Prop.
+Variables (A:Type)(dec:decidable_eq A).
+
+Lemma In_decidable x (l:list A) : decidable (In x l).
+Proof using A dec.
+ induction l as [|a l IH].
+ - now right.
+ - destruct (dec a x).
+ + left. now left.
+ + destruct IH; simpl; [left|right]; tauto.
+Qed.
+
+Lemma incl_decidable (l l':list A) : decidable (incl l l').
+Proof using A dec.
+ induction l as [|a l IH].
+ - left. inversion 1.
+ - destruct (In_decidable a l') as [IN|IN].
+ + destruct IH as [IC|IC].
+ * left. destruct 1; subst; auto.
+ * right. contradict IC. intros x H. apply IC; now right.
+ + right. contradict IN. apply IN; now left.
+Qed.
+
+Lemma NoDup_decidable (l:list A) : decidable (NoDup l).
+Proof using A dec.
+ induction l as [|a l IH].
+ - left; now constructor.
+ - destruct (In_decidable a l).
+ + right. inversion_clear 1. tauto.
+ + destruct IH.
+ * left. now constructor.
+ * right. inversion_clear 1. tauto.
+Qed.
+
+End Dec_in_Prop.
+
+Section Dec_in_Type.
+Variables (A:Type)(dec : forall x y:A, {x=y}+{x<>y}).
+
+Definition In_dec := List.In_dec dec. (* Already in List.v *)
+
+Lemma incl_dec (l l':list A) : {incl l l'}+{~incl l l'}.
+Proof using A dec.
+ induction l as [|a l IH].
+ - left. inversion 1.
+ - destruct (In_dec a l') as [IN|IN].
+ + destruct IH as [IC|IC].
+ * left. destruct 1; subst; auto.
+ * right. contradict IC. intros x H. apply IC; now right.
+ + right. contradict IN. apply IN; now left.
+Qed.
+
+Lemma NoDup_dec (l:list A) : {NoDup l}+{~NoDup l}.
+Proof using A dec.
+ induction l as [|a l IH].
+ - left; now constructor.
+ - destruct (In_dec a l).
+ + right. inversion_clear 1. tauto.
+ + destruct IH.
+ * left. now constructor.
+ * right. inversion_clear 1. tauto.
+Qed.
+
+End Dec_in_Type.
+
+(** An extra result: thanks to decidability, a list can be purged
+ from redundancies. *)
+
+Lemma uniquify_map A B (d:decidable_eq B)(f:A->B)(l:list A) :
+ exists l', NoDup (map f l') /\ incl (map f l) (map f l').
+Proof.
+ induction l.
+ - exists nil. simpl. split; [now constructor | red; trivial].
+ - destruct IHl as (l' & N & I).
+ destruct (In_decidable d (f a) (map f l')).
+ + exists l'; simpl; split; trivial.
+ intros x [Hx|Hx]. now subst. now apply I.
+ + exists (a::l'); simpl; split.
+ * now constructor.
+ * intros x [Hx|Hx]. subst; now left. right; now apply I.
+Qed.
+
+Lemma uniquify A (d:decidable_eq A)(l:list A) :
+ exists l', NoDup l' /\ incl l l'.
+Proof.
+ destruct (uniquify_map d id l) as (l',H).
+ exists l'. now rewrite !map_id in H.
+Qed.
diff --git a/theories/Lists/vo.itarget b/theories/Lists/vo.itarget
index 04994f593..82dd1be82 100644
--- a/theories/Lists/vo.itarget
+++ b/theories/Lists/vo.itarget
@@ -1,6 +1,7 @@
ListSet.vo
ListTactics.vo
List.vo
+ListDec.vo
SetoidList.vo
SetoidPermutation.vo
StreamMemo.vo
diff --git a/theories/Logic/FinFun.v b/theories/Logic/FinFun.v
new file mode 100644
index 000000000..f070a6889
--- /dev/null
+++ b/theories/Logic/FinFun.v
@@ -0,0 +1,400 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(** * Functions on finite domains *)
+
+(** 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.
+
+Lemma Finite_alt A (d:decidable_eq A) : Finite A <-> Finite' A.
+Proof.
+ split.
+ - intros (l,F). destruct (uniquify d l) as (l' & N & I).
+ exists l'. split; trivial.
+ intros x. apply I, F.
+ - intros (l & _ & F). now exists l.
+Qed.
+
+(** Injections characterized in term of lists *)
+
+Lemma Injective_map_NoDup A B (f:A->B) (l:list A) :
+ Injective f -> NoDup l -> NoDup (map f l).
+Proof.
+ intros Ij. induction 1 as [|x l X N IH]; simpl; constructor; trivial.
+ rewrite in_map_iff. intros (y & E & Y). apply Ij in E. now subst.
+Qed.
+
+Lemma Injective_list_carac A B (d:decidable_eq A)(f:A->B) :
+ Injective f <-> (forall l, NoDup l -> NoDup (map f l)).
+Proof.
+ split.
+ - intros. now apply Injective_map_NoDup.
+ - intros H x y E.
+ destruct (d x y); trivial.
+ assert (N : NoDup (x::y::nil)).
+ { repeat constructor; simpl; intuition. }
+ specialize (H _ N). simpl in H. rewrite E in H.
+ inversion_clear H; simpl in *; intuition.
+Qed.
+
+Lemma Injective_carac A B (l:list A) : Listing l ->
+ forall (f:A->B), Injective f <-> NoDup (map f l).
+Proof.
+ intros L f. split.
+ - intros Ij. apply Injective_map_NoDup; trivial. apply L.
+ - intros N x y E.
+ assert (X : In x l) by apply L.
+ assert (Y : In y l) by apply L.
+ apply In_nth_error in X. destruct X as (i,X).
+ apply In_nth_error in Y. destruct Y as (j,Y).
+ assert (X' := map_nth_error f _ _ X).
+ assert (Y' := map_nth_error f _ _ Y).
+ assert (i = j).
+ { rewrite NoDup_nth_error in N. apply N.
+ - rewrite <- nth_error_Some. now rewrite X'.
+ - rewrite X', Y'. now f_equal. }
+ subst j. rewrite Y in X. now injection X.
+Qed.
+
+(** Surjection characterized in term of lists *)
+
+Lemma Surjective_list_carac A B (f:A->B):
+ Surjective f <-> (forall lB, exists lA, incl lB (map f lA)).
+Proof.
+ split.
+ - intros Su.
+ induction lB as [|b lB IH].
+ + now exists nil.
+ + destruct (Su b) as (a,E).
+ destruct IH as (lA,IC).
+ exists (a::lA). simpl. rewrite E.
+ intros x [X|X]; simpl; intuition.
+ - intros H y.
+ destruct (H (y::nil)) as (lA,IC).
+ assert (IN : In y (map f lA)) by (apply (IC y); now left).
+ rewrite in_map_iff in IN. destruct IN as (x & E & _).
+ now exists x.
+Qed.
+
+Lemma Surjective_carac A B : Finite B -> decidable_eq B ->
+ forall f:A->B, Surjective f <-> (exists lA, Listing (map f lA)).
+Proof.
+ intros (lB,FB) d. split.
+ - rewrite Surjective_list_carac.
+ intros Su. destruct (Su lB) as (lA,IC).
+ destruct (uniquify_map d f lA) as (lA' & N & IC').
+ exists lA'. split; trivial.
+ intro x. apply IC', IC, FB.
+ - intros (lA & N & FA) y.
+ generalize (FA y). rewrite in_map_iff. intros (x & E & _).
+ now exists x.
+Qed.
+
+(** Main result : *)
+
+Lemma Endo_Injective_Surjective :
+ forall A, Finite A -> decidable_eq A ->
+ forall f:A->A, Injective f <-> Surjective f.
+Proof.
+ intros A F d f. rewrite (Surjective_carac F d). split.
+ - apply (Finite_alt d) in F. destruct F as (l,L).
+ rewrite (Injective_carac L); intros.
+ exists l; split; trivial.
+ destruct L as (N,F).
+ assert (I : incl l (map f l)).
+ { apply NoDup_length_incl; trivial.
+ - now rewrite map_length.
+ - intros x _. apply F. }
+ intros x. apply I, F.
+ - clear F d. intros (l,L).
+ assert (N : NoDup l). { apply (NoDup_map_inv f), L. }
+ assert (I : incl (map f l) l).
+ { apply NoDup_length_incl; trivial.
+ - now rewrite map_length.
+ - intros x _. apply L. }
+ assert (L' : Listing l).
+ { split; trivial.
+ intro x. apply I, L. }
+ apply (Injective_carac L'), L.
+Qed.
+
+(** 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.
+*)
+
+Lemma Finite_Empty_or_not A :
+ Finite A -> (A->False) \/ exists a:A,True.
+Proof.
+ intros (l,F).
+ destruct l.
+ - left; exact F.
+ - right; now exists a.
+Qed.
+
+Lemma Surjective_inverse :
+ forall A B, Finite A -> EqDec B ->
+ forall f:A->B, Surjective f ->
+ exists g:B->A, forall x, f (g x) = x.
+Proof.
+ intros A B F d f Su.
+ destruct (Finite_Empty_or_not F) as [noA | (a,_)].
+ - (* A is empty : g is obtained via False_rect *)
+ assert (noB : B -> False). { intros y. now destruct (Su y). }
+ exists (fun y => False_rect _ (noB y)).
+ intro y. destruct (noB y).
+ - (* A is inhabited by a : we use it in Option.get *)
+ destruct F as (l,F).
+ set (h := fun x k => if d (f k) x then true else false).
+ set (get := fun o => match o with Some y => y | None => a end).
+ exists (fun x => get (List.find (h x) l)).
+ intros x.
+ case_eq (find (h x) l); simpl; clear get; [intros y H|intros H].
+ * apply find_some in H. destruct H as (_,H). unfold h in H.
+ now destruct (d (f y) x) in H.
+ * exfalso.
+ destruct (Su x) as (y & Y).
+ generalize (find_none _ l H y (F y)).
+ unfold h. now destruct (d (f y) x).
+Qed.
+
+(** Same, with more knowledge on the inverse function: g.f = f.g = id *)
+
+Lemma Injective_Surjective_Bijective :
+ forall A B, Finite A -> EqDec B ->
+ forall f:A->B, Injective f -> Surjective f -> Bijective f.
+Proof.
+ intros A B F d f Ij Su.
+ destruct (Surjective_inverse F d Su) as (g, E).
+ exists g. split; trivial.
+ intros y. apply Ij. now rewrite E.
+Qed.
+
+
+(** An example of finite type : [Fin.t] *)
+
+Lemma Fin_Finite n : Finite (Fin.t n).
+Proof.
+ induction n.
+ - exists nil.
+ inversion a.
+ - destruct IHn as (l,Hl).
+ exists (Fin.F1 :: map Fin.FS l).
+ intros a. revert n a l Hl.
+ refine (@Fin.caseS _ _ _); intros.
+ + now left.
+ + right. now apply in_map.
+Qed.
+
+(** 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 : forall x n h, f2n (n2f h) = x := @Fin.to_nat_of_nat.
+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'].
+
+Lemma extend_ok n f : bFun n (@extend n f).
+Proof.
+ intros x h. unfold extend. break_dec h. apply f2n_ok.
+Qed.
+
+Lemma extend_f2n n f (x:Fin.t n) : extend f (f2n x) = f2n (f x).
+Proof.
+ generalize (n2f_f2n x). unfold extend, f2n, f2n_ok.
+ destruct (Fin.to_nat x) as (x',h); simpl.
+ break_dec h.
+ now intros ->.
+Qed.
+
+Lemma extend_n2f n f x (h:x<n) : n2f (extend_ok f h) = f (n2f h).
+Proof.
+ generalize (extend_ok f h). unfold extend in *. break_dec h. intros h'.
+ rewrite <- n2f_f2n. now apply n2f_ext.
+Qed.
+
+Lemma restrict_f2n n f hf (x:Fin.t n) :
+ f2n (@restrict n f hf x) = f (f2n x).
+Proof.
+ unfold restrict, f2n. destruct (Fin.to_nat x) as (x',h); simpl.
+ apply f2n_n2f.
+Qed.
+
+Lemma restrict_n2f n f hf x (h:x<n) :
+ @restrict n f hf (n2f h) = n2f (hf _ h).
+Proof.
+ unfold restrict. generalize (f2n_n2f h). unfold f2n.
+ destruct (Fin.to_nat (n2f h)) as (x',h'); simpl. intros ->.
+ now apply n2f_ext.
+Qed.
+
+Lemma extend_surjective n f :
+ bSurjective n (@extend n f) <-> Surjective f.
+Proof.
+ split.
+ - intros hf y.
+ destruct (hf _ (f2n_ok y)) as (x & h & Eq).
+ exists (n2f h).
+ apply f2n_inj. now rewrite <- Eq, <- extend_f2n, f2n_n2f.
+ - intros hf y hy.
+ destruct (hf (n2f hy)) as (x,Eq).
+ exists (f2n x).
+ split.
+ + apply f2n_ok.
+ + rewrite extend_f2n, Eq. apply f2n_n2f.
+Qed.
+
+Lemma extend_injective n f :
+ bInjective n (@extend n f) <-> Injective f.
+Proof.
+ split.
+ - intros hf x y Eq.
+ apply f2n_inj. apply hf; try apply f2n_ok.
+ now rewrite 2 extend_f2n, Eq.
+ - intros hf x y hx hy Eq.
+ rewrite <- (f2n_n2f hx), <- (f2n_n2f hy). f_equal.
+ apply hf.
+ rewrite <- 2 extend_n2f.
+ generalize (extend_ok f hx) (extend_ok f hy).
+ rewrite Eq. apply n2f_ext.
+Qed.
+
+Lemma restrict_surjective n f h :
+ Surjective (@restrict n f h) <-> bSurjective n f.
+Proof.
+ split.
+ - intros hf y hy.
+ destruct (hf (n2f hy)) as (x,Eq).
+ exists (f2n x).
+ split.
+ + apply f2n_ok.
+ + rewrite <- (restrict_f2n h), Eq. apply f2n_n2f.
+ - intros hf y.
+ destruct (hf _ (f2n_ok y)) as (x & hx & Eq).
+ exists (n2f hx).
+ apply f2n_inj. now rewrite restrict_f2n, f2n_n2f.
+Qed.
+
+Lemma restrict_injective n f h :
+ Injective (@restrict n f h) <-> bInjective n f.
+Proof.
+ split.
+ - intros hf x y hx hy Eq.
+ rewrite <- (f2n_n2f hx), <- (f2n_n2f hy). f_equal.
+ apply hf.
+ rewrite 2 restrict_n2f.
+ generalize (h x hx) (h y hy).
+ rewrite Eq. apply n2f_ext.
+ - intros hf x y Eq.
+ apply f2n_inj. apply hf; try apply f2n_ok.
+ now rewrite <- 2 (restrict_f2n h), Eq.
+Qed.
+
+End Fin2Restrict.
+Import Fin2Restrict.
+
+(** We can now use Proof via the equivalence ... *)
+
+Lemma bInjective_bSurjective n (f:nat->nat) :
+ bFun n f -> (bInjective n f <-> bSurjective n f).
+Proof.
+ intros h.
+ rewrite <- (restrict_injective h), <- (restrict_surjective h).
+ apply Endo_Injective_Surjective.
+ - apply Fin_Finite.
+ - intros x y. destruct (Fin.eq_dec x y); [left|right]; trivial.
+Qed.
+
+Lemma bSurjective_bBijective n (f:nat->nat) :
+ bFun n f -> bSurjective n f ->
+ exists g, bFun n g /\ forall x, x < n -> g (f x) = x /\ f (g x) = x.
+Proof.
+ intro hf.
+ rewrite <- (restrict_surjective hf). intros Su.
+ assert (Ij : Injective (restrict hf)).
+ { apply Endo_Injective_Surjective; trivial.
+ - apply Fin_Finite.
+ - intros x y. destruct (Fin.eq_dec x y); [left|right]; trivial. }
+ assert (Bi : Bijective (restrict hf)).
+ { apply Injective_Surjective_Bijective; trivial.
+ - apply Fin_Finite.
+ - exact Fin.eq_dec. }
+ destruct Bi as (g & Hg & Hg').
+ exists (extend g).
+ split.
+ - apply extend_ok.
+ - intros x Hx. split.
+ + now rewrite <- (f2n_n2f Hx), <- (restrict_f2n hf), extend_f2n, Hg.
+ + now rewrite <- (f2n_n2f Hx), extend_f2n, <- (restrict_f2n hf), Hg'.
+Qed.
diff --git a/theories/Logic/vo.itarget b/theories/Logic/vo.itarget
index ababd75e0..e703f2828 100644
--- a/theories/Logic/vo.itarget
+++ b/theories/Logic/vo.itarget
@@ -27,3 +27,4 @@ ProofIrrelevanceFacts.vo
ProofIrrelevance.vo
RelationalChoice.vo
SetIsType.vo
+FinFun.vo \ No newline at end of file
diff --git a/theories/Sorting/Permutation.v b/theories/Sorting/Permutation.v
index cf9f8ee42..acad98e5f 100644
--- a/theories/Sorting/Permutation.v
+++ b/theories/Sorting/Permutation.v
@@ -13,7 +13,7 @@
(* Adapted in May 2006 by Jean-Marc Notin from initial contents by
Laurent Théry (Huffmann contribution, October 2003) *)
-Require Import List Setoid Compare_dec Morphisms.
+Require Import List Setoid Compare_dec Morphisms FinFun.
Import ListNotations. (* For notations [] and [a;b;c] *)
Set Implicit Arguments.
@@ -174,6 +174,12 @@ Proof.
Qed.
Local Hint Resolve Permutation_cons_app.
+Lemma Permutation_Add a l l' : Add a l l' -> Permutation (a::l) l'.
+Proof.
+ induction 1; simpl; trivial.
+ rewrite perm_swap. now apply perm_skip.
+Qed.
+
Theorem Permutation_middle : forall (l1 l2:list A) a,
Permutation (a :: l1 ++ l2) (l1 ++ a :: l2).
Proof.
@@ -223,10 +229,6 @@ Proof.
eauto.
Qed.
-Ltac break_list l x l' H :=
- destruct l as [|x l']; simpl in *;
- injection H; intros; subst; clear H.
-
Theorem Permutation_nil_app_cons : forall (l l' : list A) (x : A),
~ Permutation nil (l++x::l').
Proof.
@@ -234,61 +236,51 @@ Proof.
apply Permutation_nil in HF. destruct l; discriminate.
Qed.
-Theorem Permutation_app_inv : forall (l1 l2 l3 l4:list A) a,
+Ltac InvAdd := repeat (match goal with
+ | H: Add ?x _ (_ :: _) |- _ => inversion H; clear H; subst
+ end).
+
+Ltac finish_basic_perms H :=
+ try constructor; try rewrite perm_swap; try constructor; trivial;
+ (rewrite <- H; now apply Permutation_Add) ||
+ (rewrite H; symmetry; now apply Permutation_Add).
+
+Theorem Permutation_Add_inv a l1 l2 :
+ Permutation l1 l2 -> forall l1' l2', Add a l1' l1 -> Add a l2' l2 ->
+ Permutation l1' l2'.
+Proof.
+ revert l1 l2. refine (Permutation_ind_bis _ _ _ _ _).
+ - (* nil *)
+ inversion_clear 1.
+ - (* skip *)
+ intros x l1 l2 PE IH. intros. InvAdd; try finish_basic_perms PE.
+ constructor. now apply IH.
+ - (* swap *)
+ intros x y l1 l2 PE IH. intros. InvAdd; try finish_basic_perms PE.
+ rewrite perm_swap; do 2 constructor. now apply IH.
+ - (* trans *)
+ intros l1 l l2 PE IH PE' IH' l1' l2' AD1 AD2.
+ assert (Ha : In a l). { rewrite <- PE. rewrite (Add_in AD1). simpl; auto. }
+ destruct (Add_inv _ _ Ha) as (l',AD).
+ transitivity l'; auto.
+Qed.
+
+Theorem Permutation_app_inv (l1 l2 l3 l4:list A) a :
Permutation (l1++a::l2) (l3++a::l4) -> Permutation (l1++l2) (l3 ++ l4).
Proof.
- intros l1 l2 l3 l4 a; revert l1 l2 l3 l4.
- set (P l l' :=
- forall l1 l2 l3 l4, l=l1++a::l2 -> l'=l3++a::l4 ->
- Permutation (l1++l2) (l3++l4)).
- cut (forall l l', Permutation l l' -> P l l').
- intros H; intros; eapply H; eauto.
- apply (Permutation_ind_bis P); unfold P; clear P.
- - (* nil *)
- intros; now destruct l1.
- - (* skip *)
- intros x l l' H IH; intros.
- break_list l1 b l1' H0; break_list l3 c l3' H1.
- auto.
- now rewrite H.
- now rewrite <- H.
- now rewrite (IH _ _ _ _ eq_refl eq_refl).
- - (* swap *)
- intros x y l l' Hp IH; intros.
- break_list l1 b l1' H; break_list l3 c l3' H0.
- auto.
- break_list l3' b l3'' H.
- auto.
- constructor. now rewrite Permutation_middle.
- break_list l1' c l1'' H1.
- auto.
- constructor. now rewrite Permutation_middle.
- break_list l3' d l3'' H; break_list l1' e l1'' H1.
- auto.
- rewrite perm_swap. constructor. now rewrite Permutation_middle.
- rewrite perm_swap. constructor. now rewrite Permutation_middle.
- now rewrite perm_swap, (IH _ _ _ _ eq_refl eq_refl).
- - (*trans*)
- intros.
- destruct (In_split a l') as (l'1,(l'2,H6)).
- rewrite <- H.
- subst l.
- apply in_or_app; right; red; auto.
- apply perm_trans with (l'1++l'2).
- apply (H0 _ _ _ _ H3 H6).
- apply (H2 _ _ _ _ H6 H4).
+ intros. eapply Permutation_Add_inv; eauto using Add_app.
Qed.
Theorem Permutation_cons_inv l l' a :
Permutation (a::l) (a::l') -> Permutation l l'.
Proof.
- intro H; exact (Permutation_app_inv [] l [] l' a H).
+ intro. eapply Permutation_Add_inv; eauto using Add_head.
Qed.
Theorem Permutation_cons_app_inv l l1 l2 a :
Permutation (a :: l) (l1 ++ a :: l2) -> Permutation l (l1 ++ l2).
Proof.
- intro H; exact (Permutation_app_inv [] l l1 l2 a H).
+ intro. eapply Permutation_Add_inv; eauto using Add_head, Add_app.
Qed.
Theorem Permutation_app_inv_l : forall l l1 l2,
@@ -300,14 +292,10 @@ Proof.
apply Permutation_cons_inv with a; auto.
Qed.
-Theorem Permutation_app_inv_r : forall l l1 l2,
+Theorem Permutation_app_inv_r l l1 l2 :
Permutation (l1 ++ l) (l2 ++ l) -> Permutation l1 l2.
Proof.
- induction l.
- intros l1 l2; do 2 rewrite app_nil_r; auto.
- intros.
- apply IHl.
- apply Permutation_app_inv with a; auto.
+ rewrite 2 (Permutation_app_comm _ l). apply Permutation_app_inv_l.
Qed.
Lemma Permutation_length_1_inv: forall a l, Permutation [a] l -> l = [a].
@@ -344,31 +332,6 @@ Proof.
apply Permutation_length_2_inv in H as [H|H]; injection H as -> ->; auto.
Qed.
-Let in_middle l l1 l2 (a:A) : l = l1 ++ a :: l2 ->
- forall x, In x l <-> a = x \/ In x (l1++l2).
-Proof.
- intros; subst; rewrite !in_app_iff; simpl. tauto.
-Qed.
-
-Lemma NoDup_cardinal_incl (l l' : list A) : NoDup l -> NoDup l' ->
- length l = length l' -> incl l l' -> incl l' l.
-Proof.
- intros N. revert l'. induction N as [|a l Hal Hl IH].
- - destruct l'; now auto.
- - intros l' Hl' E H x Hx.
- assert (Ha : In a l') by (apply H; simpl; auto).
- destruct (in_split _ _ Ha) as (l1 & l2 & H12). clear Ha.
- rewrite in_middle in Hx; eauto.
- destruct Hx as [Hx|Hx]; [left|right]; auto.
- apply (IH (l1++l2)); auto.
- * apply NoDup_remove_1 with a; rewrite <- H12; auto.
- * apply eq_add_S.
- simpl in E; rewrite E, H12, !app_length; simpl; auto with arith.
- * intros y Hy. assert (Hy' : In y l') by (apply H; simpl; auto).
- rewrite in_middle in Hy'; eauto.
- destruct Hy'; auto. subst y; intuition.
-Qed.
-
Lemma NoDup_Permutation l l' : NoDup l -> NoDup l' ->
(forall x:A, In x l <-> In x l') -> Permutation l l'.
Proof.
@@ -377,25 +340,25 @@ Proof.
intros Hl' H. exfalso. rewrite (H a); auto.
- intros l' Hl' H.
assert (Ha : In a l') by (apply H; simpl; auto).
- destruct (In_split _ _ Ha) as (l1 & l2 & H12).
- rewrite H12.
- apply Permutation_cons_app.
- apply IH; auto.
- * apply NoDup_remove_1 with a; rewrite <- H12; auto.
- * intro x. split; intros Hx.
- + assert (Hx' : In x l') by (apply H; simpl; auto).
- rewrite in_middle in Hx'; eauto.
- destruct Hx'; auto. subst; intuition.
- + assert (Hx' : In x l') by (rewrite (in_middle l1 l2 a); eauto).
- rewrite <- H in Hx'. destruct Hx'; auto.
- subst. destruct (NoDup_remove_2 _ _ _ Hl' Hx).
+ destruct (Add_inv _ _ Ha) as (l'' & AD).
+ rewrite <- (Permutation_Add AD).
+ apply perm_skip.
+ apply IH; clear IH.
+ * now apply (NoDup_Add AD).
+ * split.
+ + apply incl_Add_inv with a l'; trivial. intro. apply H.
+ + intro Hx.
+ assert (Hx' : In x (a::l)).
+ { apply H. rewrite (Add_in AD). now right. }
+ destruct Hx'; simpl; trivial. subst.
+ rewrite (NoDup_Add AD) in Hl'. tauto.
Qed.
Lemma NoDup_Permutation_bis l l' : NoDup l -> NoDup l' ->
- length l = length l' -> incl l l' -> Permutation l l'.
+ length l' <= length l -> incl l l' -> Permutation l l'.
Proof.
intros. apply NoDup_Permutation; auto.
- split; auto. apply NoDup_cardinal_incl; auto.
+ split; auto. apply NoDup_length_incl; trivial.
Qed.
Lemma Permutation_NoDup l l' : Permutation l l' -> NoDup l -> NoDup l'.
@@ -433,55 +396,19 @@ Qed.
End Permutation_map.
-Section Injection.
-
-Definition injective {A B} (f : A->B) :=
- forall x y, f x = f y -> x = y.
-
-Lemma injective_map_NoDup {A B} (f:A->B) (l:list A) :
- injective f -> NoDup l -> NoDup (map f l).
-Proof.
- intros Hf. induction 1 as [|x l Hx Hl IH]; simpl; constructor; trivial.
- rewrite in_map_iff. intros (y & Hy & Hy'). apply Hf in Hy. now subst.
-Qed.
-
-Lemma injective_bounded_surjective n f :
- injective f ->
- (forall x, x < n -> f x < n) ->
- (forall y, y < n -> exists x, x < n /\ f x = y).
-Proof.
- intros Hf H.
- set (l := seq 0 n).
- assert (P : incl (map f l) l).
- { intros x. rewrite in_map_iff. intros (y & <- & Hy').
- unfold l in *. rewrite in_seq in *. simpl in *.
- destruct Hy' as (_,Hy'). auto with arith. }
- assert (P' : incl l (map f l)).
- { unfold l.
- apply NoDup_cardinal_incl; auto using injective_map_NoDup, seq_NoDup.
- now rewrite map_length. }
- intros x Hx.
- assert (Hx' : In x l) by (unfold l; rewrite in_seq; auto with arith).
- apply P' in Hx'.
- rewrite in_map_iff in Hx'. destruct Hx' as (y & Hy & Hy').
- exists y; split; auto. unfold l in *; rewrite in_seq in Hy'.
- destruct Hy'; auto with arith.
-Qed.
-
Lemma nat_bijection_Permutation n f :
- injective f -> (forall x, x < n -> f x < n) ->
+ bFun n f ->
+ Injective f ->
let l := seq 0 n in Permutation (map f l) l.
Proof.
intros Hf BD.
- apply NoDup_Permutation_bis; auto using injective_map_NoDup, seq_NoDup.
+ apply NoDup_Permutation_bis; auto using Injective_map_NoDup, seq_NoDup.
* now rewrite map_length.
* intros x. rewrite in_map_iff. intros (y & <- & Hy').
rewrite in_seq in *. simpl in *.
destruct Hy' as (_,Hy'). auto with arith.
Qed.
-End Injection.
-
Section Permutation_alt.
Variable A:Type.
Implicit Type a : A.
@@ -493,7 +420,7 @@ Implicit Type l : list A.
Let adapt f n :=
let m := f (S n) in if le_lt_dec m (f 0) then m else pred m.
-Let adapt_injective f : injective f -> injective (adapt f).
+Let adapt_injective f : Injective f -> Injective (adapt f).
Proof.
unfold adapt. intros Hf x y EQ.
destruct le_lt_dec as [LE|LT]; destruct le_lt_dec as [LE'|LT'].
@@ -512,7 +439,7 @@ Proof.
now rewrite (Lt.S_pred _ _ LT), (Lt.S_pred _ _ LT'), EQ.
Qed.
-Let adapt_ok a l1 l2 f : injective f -> length l1 = f 0 ->
+Let adapt_ok a l1 l2 f : Injective f -> length l1 = f 0 ->
forall n, nth_error (l1++a::l2) (f (S n)) = nth_error (l1++l2) (adapt f n).
Proof.
unfold adapt. intros Hf E n.
@@ -531,7 +458,7 @@ Lemma Permutation_nth_error l l' :
Permutation l l' <->
(length l = length l' /\
exists f:nat->nat,
- injective f /\ forall n, nth_error l' n = nth_error l (f n)).
+ Injective f /\ forall n, nth_error l' n = nth_error l (f n)).
Proof.
split.
{ intros P.
@@ -573,8 +500,8 @@ Qed.
Lemma Permutation_nth_error_bis l l' :
Permutation l l' <->
exists f:nat->nat,
- injective f /\
- (forall n, n < length l -> f n < length l) /\
+ Injective f /\
+ bFun (length l) f /\
(forall n, nth_error l' n = nth_error l (f n)).
Proof.
rewrite Permutation_nth_error; split.
@@ -591,7 +518,10 @@ Proof.
[|apply Hf2 in LT; elim (Lt.lt_not_le _ _ LT H)].
apply Lt.le_lt_or_eq in LE. destruct LE as [LT|EQ]; trivial.
rewrite <- nth_error_Some, Hf3, nth_error_Some in LT.
- destruct (injective_bounded_surjective Hf Hf2 LT) as (y & Hy & Hy').
+ assert (Hf' : bInjective (length l) f).
+ { intros x y _ _ E. now apply Hf. }
+ rewrite (bInjective_bSurjective Hf2) in Hf'.
+ destruct (Hf' _ LT) as (y & Hy & Hy').
apply Hf in Hy'. subst y. elim (Lt.lt_irrefl _ Hy).
Qed.
@@ -600,8 +530,8 @@ Lemma Permutation_nth l l' d :
(let n := length l in
length l' = n /\
exists f:nat->nat,
- (forall x, x < n -> f x < n) /\
- (forall x y, x < n -> y < n -> f x = f y -> x = y) /\
+ bFun n f /\
+ bInjective n f /\
(forall x, x < n -> nth x l' d = nth (f x) l d)).
Proof.
split.
@@ -611,6 +541,7 @@ Proof.
apply Permutation_nth_error_bis in H.
destruct H as (f & Hf & Hf2 & Hf3).
exists f. split; [|split]; auto.
+ intros x y _ _ Hxy. now apply Hf.
intros n Hn. rewrite <- 2 nth_default_eq. unfold nth_default.
now rewrite Hf3.
- intros (E & f & Hf1 & Hf2 & Hf3).
diff --git a/theories/Vectors/Fin.v b/theories/Vectors/Fin.v
index b6ec6307c..a1e6b14d6 100644
--- a/theories/Vectors/Fin.v
+++ b/theories/Vectors/Fin.v
@@ -8,10 +8,10 @@
Require Arith_base.
-(** [fin n] is a convinient way to represent \[1 .. n\]
+(** [fin n] is a convenient way to represent \[1 .. n\]
[fin n] can be seen as a n-uplet of unit where [F1] is the first element of
-the n-uplet and [FS] set (n-1)-uplet of all the element but the first.
+the n-uplet and [FS] set (n-1)-uplet of all the elements but the first.
Author: Pierre Boutillier
Institution: PPS, INRIA 12/2010-01/2012-07/2012
@@ -103,13 +103,39 @@ Fixpoint of_nat_lt {p n : nat} : p < n -> t n :=
end
end.
+Lemma of_nat_ext {p}{n} (h h' : p < n) : of_nat_lt h = of_nat_lt h'.
+Proof.
+ now rewrite (Peano_dec.le_unique _ _ h h').
+Qed.
+
Lemma of_nat_to_nat_inv {m} (p : t m) : of_nat_lt (proj2_sig (to_nat p)) = p.
Proof.
-induction p.
- reflexivity.
- simpl; destruct (to_nat p). simpl. subst p; repeat f_equal. apply Peano_dec.le_unique.
+induction p; simpl.
+- reflexivity.
+- destruct (to_nat p); simpl in *. f_equal. subst p. apply of_nat_ext.
Qed.
+Lemma to_nat_of_nat {p}{n} (h : p < n) : proj1_sig (to_nat (of_nat_lt h)) = p.
+Proof.
+ revert n h.
+ induction p; intros; destruct n; simpl; trivial.
+ - inversion h.
+ - inversion h.
+ - set (h' := Lt.lt_S_n p n h). clearbody h'.
+ specialize (IHp n h').
+ destruct (to_nat (of_nat_lt h')); simpl in *. now f_equal.
+Qed.
+
+Lemma to_nat_inj {n} (p q : t n) :
+ proj1_sig (to_nat p) = proj1_sig (to_nat q) -> p = q.
+Proof.
+ intro H.
+ rewrite <- (of_nat_to_nat_inv p), <- (of_nat_to_nat_inv q).
+ destruct (to_nat p) as (np,hp), (to_nat q) as (nq,hq); simpl in *.
+ revert hp hq. rewrite H. apply of_nat_ext.
+Qed.
+
+
(** [weak p f] answers a function witch is the identity for the p{^ th} first
element of [fin (p + m)] and [FS (FS .. (FS (f k)))] for [FS (FS .. (FS k))]
with p FSs *)