Library Icharate.Lib.listAux

Set Implicit Arguments.
Require Export permutation.
Require Export ZArith.


Fixpoint constructList(n:nat):list nat:=
match n with
| 0=> nil
|(S k)=>0::(constructList k)
end.

Fixpoint getSubLists (A:Set)(l1:list A) (n:nat) {struct n}:
  option (list A *list A):=
 match l1, n with
 |nil , _ => None
 |cons a l , O => Some (nil , l1)
 |cons a l, S m=>
    match getSubLists l m with
           | None =>None
           | Some ( pair l1 l2) =>Some (cons a l1, l2)
              end
 end.

Lemma map_length:forall (A B:Set)(f:A->B)(l:list A),
                  length (map f l)=length l.
Proof.
 intros.
 elim l.
 simpl in |- *.
 auto.
 simpl in |- *.
 auto with arith.
Qed.

Lemma forall_eq_list:forall (A:Set)(l1 l2:list A) ,
    (forall i:nat, nth_error l1 i=nth_error l2 i)->
     l1=l2.

intros A0 l1.
elim l1.
simpl in |- *.
intros.
cut (nth_error l2 0 = None).
simpl in |- *.
case l2.
auto.
discriminate 1.
eauto.
rewrite <- (H 0).
auto.
intros.
cut (nth_error l2 0 = Some a).
generalize H0; case l2.
simpl in |- *.
discriminate 2.
intros.
simpl in H2.
injection H2; intros; subst.
cut (l = l0).
intro; subst; auto.
apply H.
intro i.
replace (nth_error l i) with (nth_error (a :: l) (S i)).
replace (nth_error l0 i) with (nth_error (a :: l0) (S i)).
auto.
simpl in |- *; auto.
simpl in |- *; auto.
rewrite <- (H0 0); auto.
Qed.

Lemma nth_map:forall(A B:Set)(f:A->B)(l:list A) (a:A)(i:nat),
                nth_error l i=Some a->
                nth_error (map f l) i=Some (f a).
Proof.
 intros A B f l; elim l; intros.
 generalize H; case i; simpl in |- *.
 discriminate 1.
 discriminate 2.
 simpl in |- *.
 generalize H0; case i.
 simpl in |- *.
 injection 1; intro; subst; auto.
 simpl in |- *.
 auto.
Qed.

Lemma nth_sup_length:forall (A:Set)(l1:list A) i ,
              length l1 <=i ->
              nth_error l1 i=None.
Proof.
 intros A0 l1.
 elim l1.
 simpl in |- *.
 intro i; case i.
 simpl in |- *; auto.
 simpl in |- *.
 auto.
 intros.
 generalize H0; clear H0.
 simpl in |- *; case i.
 intro.
 inversion H0.
 simpl in |- *.
 intro; auto with arith.
Qed.

Definition sum_all(l:list Z):Z:=
op_all Zplus (0%Z) l.

Lemma nth_error_length:forall (A:Set)(n:nat)(l:list A),
                        n<length l->
                       (exists a:A, nth_error l n=Some a).
Proof.
 intros A n l; generalize n; elim l; intros.
 simpl in H; absurd (n0 < 0); auto with arith.
 simpl in |- *.
 generalize H0; case n0; intros.
 exists a; auto.
 simpl in |- *.
 simpl in H1.
 apply H.
 auto with arith.
Qed.

Lemma nth_error_some_length:forall(A:Set)(n:nat)(l:list A)a,
                           nth_error l n=Some a->
                           n<length l.
Proof.
 intros.
 case (le_lt_dec (length l) n).
 intro.
 rewrite nth_sup_length in H.
 discriminate H.
 auto.
 auto.
Qed.

Lemma nth_error_app:forall (A:Set)(l1 l2:list A) (n:A)(i:nat),
                      nth_error (l1++l2) i=Some n->
                      nth_error l1 i =Some n \/
                      (i>=length l1/\nth_error l2 (i-length l1)=Some n).
Proof.
 intros A l1; elim l1; intros.
 simpl in H.
 right.
 simpl in |- *.
 rewrite <- minus_n_O; split;auto with arith.
 rewrite <- app_comm_cons in H0.
 generalize H0; clear H0; case i.
 simpl in |- *.
 intro; left; auto.
 simpl in |- *.
 intros.
 elim (H l2 n n0 H0).
 tauto.
 intro H1; decompose [and] H1; clear H1.
 right; split; auto with arith.
Qed.

Lemma nth_error_fst_app:forall (A:Set)(l1 l2:list A) (n:A)(i:nat),
                            nth_error l1 i =Some n ->
                            nth_error (l1++l2) i=Some n.
Proof.
 intros A l1; elim l1.
 intros l2 n i; case i.
 simpl in |- *; discriminate 1.
 discriminate 1.
 intros.
 generalize H0; case i.
 simpl in |- *.
 auto.
 simpl in |- *.
 auto.
Qed.

Lemma nth_error_scd_app:forall (A:Set)(l1 l2:list A) (n:A)(i:nat),
                            nth_error l2 i =Some n ->
                            nth_error (l1++l2) (i+length l1)=Some n.
Proof.
 intros A0 l1; elim l1.
 simpl in |- *.
 intros.
 replace (i + 0) with i.
 auto.
 omega.
 simpl in |- *.
 intros.
 replace (i + S (length l)) with (S (i + length l)).
 simpl in |- *.
 auto.
 omega.
Qed.

Inductive extract_opt (A:Set):list A ->list (option A)->Prop:=
|exnil:extract_opt nil nil
|excons:forall l1 l2 a, extract_opt l1 l2 ->extract_opt (a::l1) ((Some
a)::l2).

Lemma extract_one:forall (A:Set)(l1:list A) l3,
                     extract_opt l1 l3->
                     forall l2,extract_opt l2 l3->
                     l1 =l2.
Proof.
 induction 1.
 inversion 1.
 auto.
 inversion 1.
 cut (l1 = l3).
 intro; subst; auto.
 auto.
Qed.

Lemma extract_app:forall (A:Set)(l1 :list (option A))l3,
                   extract_opt l3 l1->
                  forall l4 l2, extract_opt l4 l2->
                   extract_opt (l3++l4) (l1++l2).
Proof.
 induction 1.
 simpl in |- *.
 auto.
 simpl in |- *.
 intros; constructor.
 auto.
Qed.

Lemma extract_permut:forall (A:Set)(l1 l2:list (option A)),
                     permut l1 l2->
                    forall l1', extract_opt l1' l1->
                     (exists l2', extract_opt l2' l2).
Proof.
 induction 1.
 intros.
 exists l1'; auto.
 intros.
 inversion H0.
 elim (IHpermut _ H3).
 intros.
 exists (a0 :: x).
 constructor; auto.
 inversion 1.
 exists (l1 ++ a0 :: nil).
 apply extract_app.
 auto.
 constructor.
 constructor.
 intros.
 elim (IHpermut1 _ H1).
 intros l4 H2.
 elim (IHpermut2 _ H2); intros l5 H3.
 exists l5; auto.
Qed.

Lemma permut_extract:forall (A:Set)(l1' l2':list (option A)),
                       permut l1' l2'->
                      forall l1 l2, extract_opt l1 l1'->
                                    extract_opt l2 l2'->
                                    permut l1 l2.
Proof.
 induction 1.
 intros.
 replace l1 with l2.
 constructor.
 eapply extract_one; eauto.
 inversion 1; intros.
 inversion H5.
 subst.
 constructor.
 auto.
 inversion 1.
 intro.
 subst.
 replace l2 with (l0 ++ a0 :: nil).
 constructor.
 eapply extract_one.
 eapply extract_app.
 eauto.
 constructor 2.
 constructor.
 auto.
 intros.
 elim (extract_permut H H1).
 intros.
 econstructor.
 eauto.
 auto.
Qed.

Lemma extract_forall:forall (A:Set)(l1:list A)l2,
                     length l1=length l2->
                     (forall i a , nth_error l1 i=Some a->
                                   nth_error l2 i=Some(Some a))->
                      extract_opt l1 l2.
Proof.
 intros A l1; elim l1.
 intro l2; case l2.
 intros; constructor.
 simpl in |- *; discriminate 1.
 simpl in |- *.
 intros a l H l2; case l2.
 discriminate 1.
 simpl in |- *.
 intros.
 replace o with (Some a).
 constructor.
 apply H.
 omega.
 intros.
 replace (nth_error l0 i) with (nth_error (o :: l0) (S i)).
 apply H1.
 simpl in |- *; auto.
 simpl in |- *; auto.
 cut (nth_error (o :: l0) 0 = Some (Some a)).
 simpl in |- *.
 injection 1; auto.
 apply H1; simpl in |- *; auto.
Qed.

Fixpoint isIncl (A:Set)(l1 l2:list A){struct l1}:Prop:=
match l1 with
|nil=> True
|a1::l=>In a1 l2 /\(isIncl l l2)
end.

Fixpoint distinct_elts (A:Set)(l1:list A){struct l1}:Prop:=
match l1 with
|nil => True
|a::l=>~In a l /\distinct_elts l
end.

Fixpoint noInter (A:Set)(l1 l2:list A){struct l1}:Prop:=
match l1 with
| nil =>True
| a::l=> ~In a l2 /\noInter l l2
end.

Lemma distinct_app:forall (A:Set) (l1 l2:list A),
                   distinct_elts l1 ->
                   distinct_elts l2->
                   noInter l1 l2 ->
                   distinct_elts (l1++l2).
Proof.
 intros A l1; elim l1; simpl in |- *.
 auto.
 intros.
 split.
 red in |- *.
 intro H3.
 elim (in_app_or _ _ _ H3).
 elim H0; tauto.
 elim H2; auto.
 apply H; tauto.
Qed.

Lemma add_in:forall(A:Set)(l1 l2:list A)a b,
                    add_somewhere a l1 l2->
                    In b l1->
                    In b l2.
Proof.
 induction 1.
 simpl in |- *; tauto.
 simpl in |- *; induction 1.
 tauto.
 right; auto.
Qed.

Lemma isIncl_in:forall (A:Set)(l1 l2:list A)a,
                 isIncl l1 l2->
                 In a l1->
                 In a l2.
Proof.
 intros A l1; elim l1; simpl in |- *.
 tauto.
 intros.
 elim H1.
 intro; subst; tauto.
 intros; elim H0; eauto.
Qed.

Lemma noInter_app:forall (A:Set)(l1 l2 l3:list A),
                   noInter l1 l3->
                   noInter l2 l3->
                   noInter (l1++l2) l3.
Proof.
 intros A l1; elim l1.
 simpl in |- *; auto.
 simpl in |- *.
 intros.
 split.
 tauto.
 apply H; tauto.
Qed.

Lemma isIncl_app:forall (A:Set)(l1 l2 l3:list A),
                 isIncl l1 l3->
                 isIncl l2 l3->
                 isIncl (l1++l2) l3.
Proof.
 intros A l1; elim l1; simpl in |- *.
 auto.
 intros.
 case H0; split.
 auto.
 auto.
Qed.

Lemma distinct_add:forall (A:Set)(l1 l2:list A)a,
                    add_somewhere a l1 l2->
                    distinct_elts l2->
                    distinct_elts l1.
Proof.
 induction 1.
 simpl in |- *; tauto.
 simpl in |- *; intros.
 elim H0; split.
 red in |- *; intro.
 elim H1; eapply add_in; eauto.
 auto.
Qed.

Require Import PermutSetoid.

Section permt.
Variable A:Set.
Variable decA :forall (a1 a2:A),{a1=a2}+{a1<>a2}.

Lemma multiplicity_0_notIn:forall(l1 :list A)a,
                           ~In a l1->
                           multiplicity (list_contents (eq (A:=A))
                           decA l1) a=0.
Proof.
 intro l1; elim l1.
 simpl in |- *; auto.
 simpl in |- *.
 intros.
 case (decA a a0).
 intro; case H0.
 tauto.
 intro; rewrite H.
 auto.
 elim (In_dec decA a0 l).
 intro; elim H0; tauto.
 auto.
Qed.

Lemma multiplicity_one_distinct:forall(l1 :list A)a,
                           In a l1->
                           distinct_elts l1->
                           multiplicity (list_contents (eq (A:=A))
                           decA l1) a=1.
Proof.
 intro l1; elim l1.
 simpl in |- *; tauto.
 simpl in |- *.
 intros.
 decompose [and] H1;clear H1.
 case H0.
 intro.
 case (decA a a0).
 intro;subst.
 rewrite multiplicity_0_notIn; auto.
 intro H4; case H4; auto.
 intro.
 case (decA a a0).
 intro; subst.
 elim H2; auto.
 intro; rewrite H;auto.
Qed.

Lemma incl_distinct_permut :forall (l1 l2:list A),
                 isIncl l1 l2 ->
                 isIncl l2 l1 ->
                 distinct_elts l1->
                 distinct_elts l2 ->
                 permut l1 l2.
Proof.
 intros; apply eqmset_to_ind with decA.
 unfold permutation in |- *.
 unfold meq in |- *.
 intros.
 elim (In_dec decA a l1).
 intro.
 rewrite multiplicity_one_distinct.
 rewrite multiplicity_one_distinct.
 auto.
 eapply isIncl_in; eauto.
 auto.
 auto.
 auto.
 intro.
 rewrite multiplicity_0_notIn.
 rewrite multiplicity_0_notIn.
 auto.
 red in |- *; intro.
 case b.
 eapply isIncl_in; eauto.
 auto.
Qed.

End permt.