diff options
author | 2006-05-16 16:17:43 +0000 | |
---|---|---|
committer | 2006-05-16 16:17:43 +0000 | |
commit | ed459d5dcf73d0342785d30f2515bc0fa0d06553 (patch) | |
tree | df43cc8c93f1e9c8ef6b95d02edb84e2db0cfded /theories | |
parent | a744b86438eed4d9a464cb39036f045d778b9d4f (diff) |
etoffage des notions de permutations (a la fois List.Permutation et Permutation.permutation)
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@8823 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'theories')
-rw-r--r-- | theories/Lists/List.v | 187 | ||||
-rw-r--r-- | theories/Sorting/PermutEq.v | 241 | ||||
-rw-r--r-- | theories/Sorting/PermutSetoid.v | 243 | ||||
-rw-r--r-- | theories/Sorting/Permutation.v | 43 |
4 files changed, 695 insertions, 19 deletions
diff --git a/theories/Lists/List.v b/theories/Lists/List.v index 71f8346d3..105340635 100644 --- a/theories/Lists/List.v +++ b/theories/Lists/List.v @@ -147,6 +147,14 @@ Section Facts. unfold not in |- *; intros a H; inversion_clear H. Qed. + Lemma In_split : forall x (l:list A), In x l -> exists l1, exists l2, l = l1++x::l2. + Proof. + induction l; simpl; destruct 1. + subst a; auto. + exists (@nil A); exists l; auto. + destruct (IHl H) as (l1,(l2,H0)). + exists (a::l1); exists l2; simpl; f_equal; auto. + Qed. (** Inversion *) Theorem in_inv : forall (a b:A) (l:list A), In b (a :: l) -> a = b \/ In b l. @@ -154,7 +162,6 @@ Section Facts. intros a b l H; inversion_clear H; auto. Qed. - (** Decidability of [In] *) Theorem In_dec : (forall x y:A, {x = y} + {x <> y}) -> @@ -753,6 +760,22 @@ Section ListOps. apply Permutation_trans with (l' := y :: x :: l' ++ l); constructor. apply Permutation_trans with (l' := x :: l ++ l'); auto. Qed. + + Theorem Permutation_cons_app : forall (l l1 l2:list A) a, + Permutation l (l1 ++ l2) -> Permutation (a :: l) (l1 ++ a :: l2). + Proof. + intros l l1; revert l. + induction l1. + simpl. + intros; apply perm_skip; auto. + simpl; intros. + apply perm_trans with (a0::a::l1++l2). + apply perm_skip; auto. + apply perm_trans with (a::a0::l1++l2). + apply perm_swap; auto. + apply perm_skip; auto. + Qed. + Hint Resolve Permutation_cons_app. Theorem Permutation_length : forall (l l' : list A), Permutation l l' -> length l = length l'. Proof. @@ -768,6 +791,108 @@ Section ListOps. apply Permutation_app_swap. Qed. + Theorem Permutation_ind_bis : + forall P : list A -> list A -> Prop, + P (@nil A) (@nil A) -> + (forall x l l', Permutation l l' -> P l l' -> P (x :: l) (x :: l')) -> + (forall x y l l', Permutation l l' -> P l l' -> P (y :: x :: l) (x :: y :: l')) -> + (forall l l' l'', Permutation l l' -> P l l' -> Permutation l' l'' -> P l' l'' -> P l l'') -> + forall l l', Permutation l l' -> P l l'. + Proof. + intros P Hnil Hskip Hswap Htrans. + induction 1; auto. + apply Htrans with (x::y::l); auto. + apply Hswap; auto. + induction l; auto. + apply Hskip; auto. + apply Hskip; auto. + induction l; auto. + eauto. + Qed. + + Ltac break_list l x l' H := + destruct l as [|x l']; simpl in *; + injection H; intros; subst; clear H. + + Theorem Permutation_app_inv : forall (l1 l2 l3 l4:list A) a, + Permutation (l1++a::l2) (l3++a::l4) -> Permutation (l1++l2) (l3 ++ l4). + Proof. + set (P:=fun l l' => + forall a 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; apply (H _ _ H0 a); auto. + intros; apply (Permutation_ind_bis P); unfold P; clear P; try clear H l l'; simpl; auto. + (* nil *) + intros; destruct l1; simpl in *; discriminate. + (* skip *) + intros x l l' H IH; intros. + break_list l1 b l1' H0; break_list l3 c l3' H1. + auto. + apply perm_trans with (l3'++c::l4); auto. + apply perm_trans with (l1'++a::l2); auto. + apply perm_skip. + apply (IH a l1' l2 l3' l4); auto. + (* 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. + apply perm_trans with (c::l3''++b::l4); auto. + break_list l1' c l1'' H1. + auto. + apply perm_trans with (b::l1''++c::l2); auto. + break_list l3' d l3'' H; break_list l1' e l1'' H1. + auto. + apply perm_trans with (e::a::l1''++l2); auto. + apply perm_trans with (e::l1''++a::l2); auto. + apply perm_trans with (d::a::l3''++l4); auto. + apply perm_trans with (d::l3''++a::l4); auto. + apply perm_trans with (e::d::l1''++l2); auto. + apply perm_skip; apply perm_skip. + apply (IH a l1'' l2 l3'' l4); auto. + (*trans*) + intros. + destruct (In_split a l') as (l'1,(l'2,H6)). + apply (Permutation_in a 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). + Qed. + + Theorem Permutation_cons_inv : + forall l l' a, Permutation (a::l) (a::l') -> Permutation l l'. + Proof. + intros; exact (Permutation_app_inv (@nil _) l (@nil _) l' a H). + Qed. + + Theorem Permutation_cons_app_inv : + forall l l1 l2 a, Permutation (a :: l) (l1 ++ a :: l2) -> Permutation l (l1 ++ l2). + Proof. + intros; exact (Permutation_app_inv (@nil _) l l1 l2 a H). + Qed. + + Theorem Permutation_app_inv_l : + forall l l1 l2, Permutation (l ++ l1) (l ++ l2) -> Permutation l1 l2. + Proof. + induction l; simpl; auto. + intros. + apply IHl. + apply Permutation_cons_inv with a; auto. + Qed. + + Theorem Permutation_app_inv_r : + forall l l1 l2, Permutation (l1 ++ l) (l2 ++ l) -> Permutation l1 l2. + Proof. + induction l. + intros l1 l2; do 2 rewrite <- app_nil_end; auto. + intros. + apply IHl. + apply Permutation_app_inv with a; auto. + Qed. + End Permutation. @@ -848,6 +973,13 @@ Section Map. rewrite IHl; auto. Qed. + Hint Constructors Permutation. + + Lemma Permutation_map : + forall l l', Permutation l l' -> Permutation (map l) (map l'). + Proof. + induction 1; simpl; auto; eauto. + Qed. (** [flat_map] *) @@ -892,7 +1024,6 @@ Proof. Qed. - (************************************) (** Left-to-right iterator on lists *) (************************************) @@ -1467,8 +1598,58 @@ Section ReDun. | NoDup_nil : NoDup nil | NoDup_cons : forall x l, ~ In x l -> NoDup l -> NoDup (x::l). -End ReDun. + Lemma NoDup_remove_1 : forall l l' a, NoDup (l++a::l') -> NoDup (l++l'). + Proof. + induction l; simpl. + inversion_clear 1; auto. + inversion_clear 1. + constructor. + swap H0. + apply in_or_app; destruct (in_app_or _ _ _ H); simpl; tauto. + apply IHl with a0; auto. + Qed. + Lemma NoDup_remove_2 : forall l l' a, NoDup (l++a::l') -> ~In a (l++l'). + Proof. + induction l; simpl. + inversion_clear 1; auto. + inversion_clear 1. + swap H0. + destruct H. + subst a0. + apply in_or_app; right; red; auto. + destruct (IHl _ _ H1); auto. + Qed. + + Lemma NoDup_Permutation : forall l l', + NoDup l -> NoDup l' -> (forall x, In x l <-> In x l') -> Permutation l l'. + Proof. + induction l. + destruct l'; simpl; intros. + apply perm_nil. + destruct (H1 a) as (_,H2); destruct H2; auto. + intros. + destruct (In_split a l') as (l'1,(l'2,H2)). + destruct (H1 a) as (H2,H3); simpl in *; auto. + subst l'. + apply Permutation_cons_app. + inversion_clear H. + apply IHl; auto. + apply NoDup_remove_1 with a; auto. + intro x; split; intros. + assert (In x (l'1++a::l'2)). + destruct (H1 x); simpl in *; auto. + apply in_or_app; destruct (in_app_or _ _ _ H4); auto. + destruct H5; auto. + subst x; destruct H2; auto. + assert (In x (l'1++a::l'2)). + apply in_or_app; destruct (in_app_or _ _ _ H); simpl; auto. + destruct (H1 x) as (_,H5); destruct H5; auto. + subst x. + destruct (NoDup_remove_2 _ _ _ H0 H). + Qed. + +End ReDun. (***********************************) diff --git a/theories/Sorting/PermutEq.v b/theories/Sorting/PermutEq.v new file mode 100644 index 000000000..1e4673b64 --- /dev/null +++ b/theories/Sorting/PermutEq.v @@ -0,0 +1,241 @@ +(************************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(************************************************************************) + +(*i $Id$ i*) + +Require Import Omega. +Require Import Relations. +Require Import Setoid. +Require Import List. +Require Import Multiset. +Require Import Permutation. + +Set Implicit Arguments. + +(** This file is similar to [PermutSetoid], except that the equality used here + is Coq usual one instead of a setoid equality. In particular, we can then + prove the equivalence between [List.Permutation] and + [Permutation.permutation]. +*) + +Section Perm. + +Variable A : Set. +Hypothesis eq_dec : forall x y:A, {x=y} + {~ x=y}. + +Notation permutation := (permutation _ eq_dec). +Notation list_contents := (list_contents _ eq_dec). + +(** we can use [multiplicity] to define [In] and [NoDup]. *) + +Lemma multiplicity_In : + forall l a, In a l <-> 0 < multiplicity (list_contents l) a. +Proof. +induction l. +simpl. +split; inversion 1. +simpl. +split; intros. +inversion_clear H. +subst a0. +destruct (eq_dec a a) as [_|H]; auto with arith; destruct H; auto. +destruct (eq_dec a a0) as [H1|H1]; auto with arith; simpl. +rewrite <- IHl; auto. +destruct (eq_dec a a0); auto. +simpl in H. +right; rewrite IHl; auto. +Qed. + +Lemma multiplicity_In_O : + forall l a, ~ In a l -> multiplicity (list_contents l) a = 0. +Proof. +intros l a; rewrite multiplicity_In; + destruct (multiplicity (list_contents l) a); auto. +destruct 1; auto with arith. +Qed. + +Lemma multiplicity_In_S : + forall l a, In a l -> multiplicity (list_contents l) a >= 1. +Proof. +intros l a; rewrite multiplicity_In; auto. +Qed. + +Lemma multiplicity_NoDup : + forall l, NoDup l <-> (forall a, multiplicity (list_contents l) a <= 1). +Proof. +induction l. +simpl. +split; auto with arith. +intros; apply NoDup_nil. +split; simpl. +inversion_clear 1. +rewrite IHl in H1. +intros; destruct (eq_dec a a0) as [H2|H2]; simpl; auto. +subst a0. +rewrite multiplicity_In_O; auto. +intros; constructor. +rewrite multiplicity_In. +generalize (H a). +destruct (eq_dec a a) as [H0|H0]. +destruct (multiplicity (list_contents l) a); auto with arith. +simpl; inversion 1. +inversion H3. +destruct H0; auto. +rewrite IHl; intros. +generalize (H a0); auto with arith. +destruct (eq_dec a a0); simpl; auto with arith. +Qed. + +Lemma NoDup_permut : + forall l l', NoDup l -> NoDup l' -> + (forall x, In x l <-> In x l') -> permutation l l'. +Proof. +intros. +red; unfold meq; intros. +rewrite multiplicity_NoDup in H, H0. +generalize (H a) (H0 a) (H1 a); clear H H0 H1. +do 2 rewrite multiplicity_In. +destruct 3; omega. +Qed. + +(** Permutation is compatible with In. *) +Lemma permut_In_In : + forall l1 l2 e, permutation l1 l2 -> In e l1 -> In e l2. +Proof. +unfold Permutation.permutation, meq; intros l1 l2 e P IN. +generalize (P e); clear P. +destruct (In_dec eq_dec e l2) as [H|H]; auto. +rewrite (multiplicity_In_O _ _ H). +intros. +generalize (multiplicity_In_S _ _ IN). +rewrite H0. +inversion 1. +Qed. + +Lemma permut_cons_In : + forall l1 l2 e, permutation (e :: l1) l2 -> In e l2. +Proof. +intros; eapply permut_In_In; eauto. +red; auto. +Qed. + +(** Permutation of an empty list. *) +Lemma permut_nil : + forall l, permutation l nil -> l = nil. +Proof. +intro l; destruct l as [ | e l ]; trivial. +assert (In e (e::l)) by red; auto. +intro Abs; generalize (permut_In_In _ Abs H). +inversion 1. +Qed. + +(** When used with [eq], this permutation notion is equivalent to + the one defined in [List.v]. *) + +Lemma permutation_Permutation : + forall l l', Permutation l l' <-> permutation l l'. +Proof. +split. +induction 1. +apply permut_refl. +apply permut_cons; auto. +change (permutation (y::x::l) ((x::nil)++y::l)). +apply permut_add_cons_inside; simpl; apply permut_refl. +apply permut_tran with l'; auto. +revert l'. +induction l. +intros. +rewrite (permut_nil (permut_sym H)). +apply Permutation_refl. +intros. +destruct (In_split _ _ (permut_cons_In H)) as (h2,(t2,H1)). +subst l'. +apply Permutation_cons_app. +apply IHl. +apply permut_remove_hd with a; auto. +Qed. + +(** Permutation for short lists. *) + +Lemma permut_length_1: + forall a b, permutation (a :: nil) (b :: nil) -> a=b. +Proof. +intros a b; unfold Permutation.permutation, meq; intro P; +generalize (P b); clear P; simpl. +destruct (eq_dec b b) as [H|H]; [ | destruct H; auto]. +destruct (eq_dec a b); simpl; auto; intros; discriminate. +Qed. + +Lemma permut_length_2 : + forall a1 b1 a2 b2, permutation (a1 :: b1 :: nil) (a2 :: b2 :: nil) -> + (a1=a2) /\ (b1=b2) \/ (a1=b2) /\ (a2=b1). +Proof. +intros a1 b1 a2 b2 P. +assert (H:=permut_cons_In P). +inversion_clear H. +left; split; auto. +apply permut_length_1. +red; red; intros. +generalize (P a); clear P; simpl. +destruct (eq_dec a1 a) as [H2|H2]; + destruct (eq_dec a2 a) as [H3|H3]; auto. +destruct H3; transitivity a1; auto. +destruct H2; transitivity a2; auto. +right. +inversion_clear H0; [|inversion H]. +split; auto. +apply permut_length_1. +red; red; intros. +generalize (P a); clear P; simpl. +destruct (eq_dec a1 a) as [H2|H2]; + destruct (eq_dec b2 a) as [H3|H3]; auto. +simpl; rewrite <- plus_n_Sm; inversion 1; auto. +destruct H3; transitivity a1; auto. +destruct H2; transitivity b2; auto. +Qed. + +(** Permutation is compatible with length. *) +Lemma permut_length : + forall l1 l2, permutation l1 l2 -> length l1 = length l2. +Proof. +induction l1; intros l2 H. +rewrite (permut_nil (permut_sym H)); auto. +destruct (In_split _ _ (permut_cons_In H)) as (h2,(t2,H1)). +subst l2. +rewrite app_length. +simpl; rewrite <- plus_n_Sm; f_equal. +rewrite <- app_length. +apply IHl1. +apply permut_remove_hd with a; auto. +Qed. + +Variable B : Set. +Variable eqB_dec : forall x y:B, { x=y }+{ ~x=y }. + +(** Permutation is compatible with map. *) + +Lemma permutation_map : + forall f l1 l2, permutation l1 l2 -> + Permutation.permutation _ eqB_dec (map f l1) (map f l2). +Proof. +intros f; induction l1. +intros l2 P; rewrite (permut_nil (permut_sym P)); apply permut_refl. +intros l2 P. +simpl. +destruct (In_split _ _ (permut_cons_In P)) as (h2,(t2,H1)). +subst l2. +rewrite map_app. +simpl. +apply permut_add_cons_inside. +rewrite <- map_app. +apply IHl1; auto. +apply permut_remove_hd with a; auto. +Qed. + +End Perm. + diff --git a/theories/Sorting/PermutSetoid.v b/theories/Sorting/PermutSetoid.v new file mode 100644 index 000000000..e669c5fec --- /dev/null +++ b/theories/Sorting/PermutSetoid.v @@ -0,0 +1,243 @@ +(************************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(************************************************************************) + +(*i $Id$ i*) + +Require Import Omega. +Require Import Relations. +Require Import List. +Require Import Multiset. +Require Import Permutation. +Require Import SetoidList. + +Set Implicit Arguments. + +(** This file contains additional results about permutations + with respect to an setoid equality (i.e. an equivalence relation). +*) + +Section Perm. + +Variable A : Set. +Variable eqA : relation A. +Hypothesis eqA_dec : forall x y:A, {eqA x y} + {~ eqA x y}. + +Notation permutation := (permutation _ eqA_dec). +Notation list_contents := (list_contents _ eqA_dec). + +(** The following lemmas need some knowledge on [eqA] *) + +Variable eqA_refl : forall x, eqA x x. +Variable eqA_sym : forall x y, eqA x y -> eqA y x. +Variable eqA_trans : forall x y z, eqA x y -> eqA y z -> eqA x z. + +(** we can use [multiplicity] to define [InA] and [NoDupA]. *) + +Lemma multiplicity_InA : + forall l a, InA eqA a l <-> 0 < multiplicity (list_contents l) a. +Proof. +induction l. +simpl. +split; inversion 1. +simpl. +split; intros. +inversion_clear H. +destruct (eqA_dec a a0) as [_|H1]; auto with arith. +destruct H1; auto. +destruct (eqA_dec a a0); auto with arith. +simpl; rewrite <- IHl; auto. +destruct (eqA_dec a a0) as [H0|H0]; auto. +simpl in H. +constructor 2; rewrite IHl; auto. +Qed. + +Lemma multiplicity_InA_O : + forall l a, ~ InA eqA a l -> multiplicity (list_contents l) a = 0. +Proof. +intros l a; rewrite multiplicity_InA; +destruct (multiplicity (list_contents l) a); auto with arith. +destruct 1; auto with arith. +Qed. + +Lemma multiplicity_InA_S : + forall l a, InA eqA a l -> multiplicity (list_contents l) a >= 1. +Proof. +intros l a; rewrite multiplicity_InA; auto with arith. +Qed. + +Lemma multiplicity_NoDupA : forall l, + NoDupA eqA l <-> (forall a, multiplicity (list_contents l) a <= 1). +Proof. +induction l. +simpl. +split; auto with arith. +split; simpl. +inversion_clear 1. +rewrite IHl in H1. +intros; destruct (eqA_dec a a0) as [H2|H2]; simpl; auto. +rewrite multiplicity_InA_O; auto. +swap H0. +apply InA_eqA with a0; auto. +intros; constructor. +rewrite multiplicity_InA. +generalize (H a). +destruct (eqA_dec a a) as [H0|H0]. +destruct (multiplicity (list_contents l) a); auto with arith. +simpl; inversion 1. +inversion H3. +destruct H0; auto. +rewrite IHl; intros. +generalize (H a0); auto with arith. +destruct (eqA_dec a a0); simpl; auto with arith. +Qed. + + +(** Permutation is compatible with InA. *) +Lemma permut_InA_InA : + forall l1 l2 e, permutation l1 l2 -> InA eqA e l1 -> InA eqA e l2. +Proof. +intros l1 l2 e. +do 2 rewrite multiplicity_InA. +unfold Permutation.permutation, meq. +intros H;rewrite H; auto. +Qed. + +Lemma permut_cons_InA : + forall l1 l2 e, permutation (e :: l1) l2 -> InA eqA e l2. +Proof. +intros; apply (permut_InA_InA (e:=e) H); auto. +Qed. + +(** Permutation of an empty list. *) +Lemma permut_nil : + forall l, permutation l nil -> l = nil. +Proof. +intro l; destruct l as [ | e l ]; trivial. +assert (InA eqA e (e::l)) by auto. +intro Abs; generalize (permut_InA_InA Abs H). +inversion 1. +Qed. + +(** Permutation for short lists. *) + +Lemma permut_length_1: + forall a b, permutation (a :: nil) (b :: nil) -> eqA a b. +Proof. +intros a b; unfold Permutation.permutation, meq; intro P; +generalize (P b); clear P; simpl. +destruct (eqA_dec b b) as [H|H]; [ | destruct H; auto]. +destruct (eqA_dec a b); simpl; auto; intros; discriminate. +Qed. + +Lemma permut_length_2 : + forall a1 b1 a2 b2, permutation (a1 :: b1 :: nil) (a2 :: b2 :: nil) -> + (eqA a1 a2) /\ (eqA b1 b2) \/ (eqA a1 b2) /\ (eqA a2 b1). +Proof. +intros a1 b1 a2 b2 P. +assert (H:=permut_cons_InA P). +inversion_clear H. +left; split; auto. +apply permut_length_1. +red; red; intros. +generalize (P a); clear P; simpl. +destruct (eqA_dec a1 a) as [H2|H2]; + destruct (eqA_dec a2 a) as [H3|H3]; auto. +destruct H3; apply eqA_trans with a1; auto. +destruct H2; apply eqA_trans with a2; auto. +right. +inversion_clear H0; [|inversion H]. +split; auto. +apply permut_length_1. +red; red; intros. +generalize (P a); clear P; simpl. +destruct (eqA_dec a1 a) as [H2|H2]; + destruct (eqA_dec b2 a) as [H3|H3]; auto. +simpl; rewrite <- plus_n_Sm; inversion 1; auto. +destruct H3; apply eqA_trans with a1; auto. +destruct H2; apply eqA_trans with b2; auto. +Qed. + +(** Permutation is compatible with length. *) +Lemma permut_length : + forall l1 l2, permutation l1 l2 -> length l1 = length l2. +Proof. +induction l1; intros l2 H. +rewrite (permut_nil (permut_sym H)); auto. +assert (H0:=permut_cons_InA H). +destruct (InA_split H0) as (h2,(b,(t2,(H1,H2)))). +subst l2. +rewrite app_length. +simpl; rewrite <- plus_n_Sm; f_equal. +rewrite <- app_length. +apply IHl1. +apply permut_remove_hd with b. +apply permut_tran with (a::l1); auto. +revert H1; unfold Permutation.permutation, meq; simpl. +intros; f_equal; auto. +destruct (eqA_dec b a0) as [H2|H2]; + destruct (eqA_dec a a0) as [H3|H3]; auto. +destruct H3; apply eqA_trans with b; auto. +destruct H2; apply eqA_trans with a; auto. +Qed. + +Lemma NoDupA_eqlistA_permut : + forall l l', NoDupA eqA l -> NoDupA eqA l' -> + eqlistA eqA l l' -> permutation l l'. +Proof. +intros. +red; unfold meq; intros. +rewrite multiplicity_NoDupA in H, H0. +generalize (H a) (H0 a) (H1 a); clear H H0 H1. +do 2 rewrite multiplicity_InA. +destruct 3; omega. +Qed. + + +Variable B : Set. +Variable eqB : B->B->Prop. +Variable eqB_dec : forall x y:B, { eqB x y }+{ ~eqB x y }. +Variable eqB_trans : forall x y z, eqB x y -> eqB y z -> eqB x z. + +(** Permutation is compatible with map. *) + +Lemma permut_map : + forall f, + (forall x y, eqA x y -> eqB (f x) (f y)) -> + forall l1 l2, permutation l1 l2 -> + Permutation.permutation _ eqB_dec (map f l1) (map f l2). +Proof. +intros f; induction l1. +intros l2 P; rewrite (permut_nil (permut_sym P)); apply permut_refl. +intros l2 P. +simpl. +assert (H0:=permut_cons_InA P). +destruct (InA_split H0) as (h2,(b,(t2,(H1,H2)))). +subst l2. +rewrite map_app. +simpl. +apply permut_tran with (f b :: map f l1). +revert H1; unfold Permutation.permutation, meq; simpl. +intros; f_equal; auto. +destruct (eqB_dec (f b) a0) as [H2|H2]; + destruct (eqB_dec (f a) a0) as [H3|H3]; auto. +destruct H3; apply eqB_trans with (f b); auto. +destruct H2; apply eqB_trans with (f a); auto. +apply permut_add_cons_inside. +rewrite <- map_app. +apply IHl1; auto. +apply permut_remove_hd with b. +apply permut_tran with (a::l1); auto. +revert H1; unfold Permutation.permutation, meq; simpl. +intros; f_equal; auto. +destruct (eqA_dec b a0) as [H2|H2]; + destruct (eqA_dec a a0) as [H3|H3]; auto. +destruct H3; apply eqA_trans with b; auto. +destruct H2; apply eqA_trans with a; auto. +Qed. + +End Perm. diff --git a/theories/Sorting/Permutation.v b/theories/Sorting/Permutation.v index f1b53f067..182c10e6e 100644 --- a/theories/Sorting/Permutation.v +++ b/theories/Sorting/Permutation.v @@ -13,6 +13,24 @@ Require Import List. Require Import Multiset. Require Import Arith. +(** This file define a notion of permutation for lists, based on multisets: + there exists a permutation between two lists iff every elements have + the same multiplicities in the two lists. + + Unlike [List.Permutation], the present notion of permutation requires + a decidable equality. At the same time, this definition can be used + with a non-standard equality, whereas [List.Permutation] cannot. + + The present file contains basic results, obtained without any particular + assumption on the decidable equality used. + + File [PermutSetoid] contains additional results about permutations + with respect to an setoid equality (i.e. an equivalence relation). + + Finally, file [PermutEq] concerns Coq equality : this file is similar + to the previous one, but proves in addition that [List.Permutation] + and [permutation] are equivalent in this context. +*) Set Implicit Arguments. @@ -80,29 +98,15 @@ Lemma permut_app : permutation l l' -> permutation m m' -> permutation (l ++ m) (l' ++ m'). Proof. unfold permutation in |- *; intros. -apply meq_trans with (munion (list_contents l) (list_contents m)); +apply meq_trans with (munion (list_contents l) (list_contents m)); auto with datatypes. -apply meq_trans with (munion (list_contents l') (list_contents m')); +apply meq_trans with (munion (list_contents l') (list_contents m')); auto with datatypes. apply meq_trans with (munion (list_contents l') (list_contents m)); auto with datatypes. Qed. Hint Resolve permut_app. -Lemma permut_middle : - forall (l m:list A) (a:A), permutation (a :: l ++ m) (l ++ a :: m). -Proof. -unfold permutation in |- *. -simple induction l; simpl in |- *; auto with datatypes. -intros. -apply meq_trans with - (munion (singletonBag a) - (munion (singletonBag a0) (list_contents (l0 ++ m)))); - auto with datatypes. -apply munion_perm_left; auto with datatypes. -Qed. -Hint Resolve permut_middle. - Lemma permut_add_inside : forall a l1 l2 l3 l4, permutation (l1 ++ l2) (l3 ++ l4) -> @@ -126,6 +130,13 @@ replace (a :: l) with (nil ++ a :: l); trivial; apply permut_add_inside; trivial. Qed. +Lemma permut_middle : + forall (l m:list A) (a:A), permutation (a :: l ++ m) (l ++ a :: m). +Proof. +intros; apply permut_add_cons_inside; auto. +Qed. +Hint Resolve permut_middle. + Lemma permut_sym_app : forall l1 l2, permutation (l1 ++ l2) (l2 ++ l1). Proof. |