Qcert.Basic.Util.RList


Section RList.



  Section misc.
    Context {A:Type}.

    Definition singleton {A} (x:A) : list A := x::nil.

    Lemma is_nil_dec (l:list A) : {l = nil} + {l nil}.

    Fixpoint lflatten (l:list (list A)) : list A :=
      match l with
      | nilnil
      | l1 :: l'
        l1 ++ (lflatten l')
      end.

    Lemma flat_map_app {B} (f:Alist B) l1 l2 :
      flat_map f (l1 ++ l2) = flat_map f l1 ++ flat_map f l2.

    Lemma map_nil f l :
      map f l = (@nil A) l = (@nil A).

    Lemma eq_means_same_length :
       (l1 l2:list A),
        l1 = l2 (length l1) = (length l2).

    Lemma app_cons_middle (l1 l2:list A) (a:A) :
      l1 ++ (a::l2) = (l1 ++ (a::nil))++l2.

  End misc.

  Lemma map_app_break {A B:Type} (f:AB) {a b c} :
    map f a = b ++ c
    {b':list A & {c' : list A | a = b' ++ c' b = map f b' c = map f c'}}.

  Lemma map_inj_strong {A B} (f g:AB) (l1 l2:list A)
        (inj: (x y:A), In (f x) (map f l1) In (g y) (map g l2) f x = g y x = y) :
    map f l1 = map g l2
    l1 = l2.

  Lemma map_inj {A B} (f g:AB) (l1 l2:list A)
        (inj: (x y:A), f x = g y x = y) :
    map f l1 = map g l2
    l1 = l2.

  Section folds.
    Context {A B C: Type}.

    Lemma fold_left_map
          (f:A C A) (g:BC) (l:list B) (init:A) :
      fold_left f (map g l) init = fold_left (fun a bf a (g b)) l init.

    Lemma fold_left_ext
          (f g:A B A) (l:list B) (init:A) :
      ( x y, f x y = g x y)
      fold_left f l init = fold_left g l init.

    Lemma fold_right_app_map_singleton l :
    fold_right (fun a b : list Aa ++ b) nil
              (map (fun x : A ⇒ (x::nil)) l) = l.

  Lemma fold_right_perm (f : A A A)
        (assoc: x y z : A, f x (f y z) = f (f x y) z)
        (comm: x y : A, f x y = f y x) (l1 l2:list A) (unit:A)
        (perm:Permutation l1 l2) :
    fold_right f unit l1 = fold_right f unit l2.

  End folds.

  Section filter.
    Context {A:Type}.

    Lemma filter_length :
       (p:A bool), (l:list A),
          length l length (filter p l).

    Lemma filter_smaller :
       (p:A bool), (l:list A), (x:A),
            filter p l x::l.

    Lemma filter_filter :
       (p:A bool), (s:list A),
          filter p (filter p s) = filter p s.

    Lemma filter_not_filter:
       (p:A bool), (s:list A),
            filter p (filter (fun xnegb (p x)) s) = nil.

    Lemma filter_id_implies_pred :
       (p:A bool), (l:list A),
          filter p l = l (y:A), (In y l (p y = true)).

    Lemma filter_nil_implies_not_pred :
       (p:A bool), (l:list A),
          filter p l = nil (y:A), (In y l (p y = false)).

    Lemma filter_comm:
       (x:list A) (p1 p2: A bool),
        (filter p1 (filter p2 x)) = (filter p2 (filter p1 x)).

    Lemma filter_and:
       (x:list A) (p1 p2: A bool),
        (filter p1 (filter p2 x)) = (filter (fun aandb (p1 a) (p2 a)) x).

    Lemma filter_eq:
       (p1 p2:A bool),
        ( x:A, p1 x = p2 x) ( l:list A, filter p1 l = filter p2 l).

    Lemma false_filter_nil {f} {l:list A} :
      ( x, In x l f x = false) filter f l = nil.

    Lemma filter_app (f:Abool) l1 l2 :
      filter f (l1 ++ l2) = filter f l1 ++ filter f l2.

    Lemma Forall_filter {P} {l:list A} f :
      Forall P l Forall P (filter f l).

    Lemma find_filter f (l:list A) : find f l = hd_error (filter f l).

    Lemma filter_ext (f g : A bool) (l : list A) :
      ( x, In x l f x = g x)
      filter f l = filter g l.

    Lemma true_filter (f : A bool) (l : list A) :
      ( x : A, In x l f x = true) filter f l = l.

  End filter.


        Lemma forall_in_dec {A:Type} P (l:list A)
          (dec: x, In x l {P x} + {¬ P x}):
      { x, In x l P x} + {¬ x, In x l P x}.

    Lemma exists_in_dec {A:Type} P (l:list A)
          (dec: x, In x l {P x} + {¬ P x}):
      { x, In x l P x} + {¬ x, In x l P x}.

    Lemma exists_nforall_in_dec {A:Type} P (l:list A)
          (dec: x, In x l {P x} + {¬ P x}):
      { x, In x l P x} + { x, In x l ¬P x}.

      Lemma existsb_ex {A : Type} (f : A bool) (l : list A) :
       existsb f l = true {x : A | In x l f x = true}.

  Section perm_equiv.
    Context {A:Type}.
    Context {eqdec:EqDec A eq}.

    Definition ldeqA := (@Permutation A).

    Definition rbag := list A.

    Global Instance perm_equiv : Equivalence (@Permutation A).
  End perm_equiv.

  Section list2.
    Context {A B:Type}.

    Section fb2.
      Context (f:ABbool).
      Fixpoint forallb2 (l1:list A) (l2:list B): bool :=
        match l1,l2 with
          | nil, niltrue
          | a1::l1, a2::l2f a1 a2 && forallb2 l1 l2
          | _, _false
        end.

      Lemma forallb2_forallb : (l1:list A) (l2:list B),
                                 (length l1 = length l2)
                                 forallb (fun xyf (fst xy) (snd xy)) (combine l1 l2) = forallb2 l1 l2.

      Lemma forallb2_forallb_true : (l1:list A) (l2:list B),
                                      (length l1 = length l2 forallb (fun xyf (fst xy) (snd xy)) (combine l1 l2) = true)
                                      
                                      forallb2 l1 l2 = true.

      Lemma forallb2_Forallb : l1 l2, forallb2 l1 l2 = true Forall2 (fun x yf x y = true) l1 l2.

    End fb2.

    Lemma Forall2_incl : (f1 f2:ABProp) l1 l2,
                           ( x y, In x l1 In y l2 f1 x y f2 x y)
                           Forall2 f1 l1 l2 Forall2 f2 l1 l2.

    Lemma forallb2_eq : (f1 f2:ABbool) l1 l2,
                          ( x y, In x l1 In y l2 f1 x y = f2 x y)
                          forallb2 f1 l1 l2 = forallb2 f2 l1 l2.

  End list2.

  Section forall2.

    Lemma forallb2_sym {A B} : (f:ABbool) {l1 l2},
      forallb2 f l1 l2 = forallb2 (fun x yf y x) l2 l1.

    Lemma Forall2_map {A B C D} (f:CDProp) (g:AC) (h:BD) a b:
      Forall2 (fun x yf (g x) (h y)) a b Forall2 f (map g a) (map h b).

    Lemma Forall2_map_f {A B C D} (f:CDProp) (g:AC) (h:BD) a b:
      Forall2 (fun x yf (g x) (h y)) a b Forall2 f (map g a) (map h b).

    Lemma Forall2_map_b {A B C D} (f:CDProp) (g:AC) (h:BD) a b:
      Forall2 f (map g a) (map h b) Forall2 (fun x yf (g x) (h y)) a b.

    Lemma Forall2_length {A B} (f:ABProp) a b:
      Forall2 f a b length a = length b.

    Global Instance Forall2_refl {A} R `{Reflexive A R} : Reflexive (Forall2 R).

    Global Instance Forall2_sym {A} R `{Symmetric A R} : Symmetric (Forall2 R).

    Global Instance Forall2_trans {A} R `{Transitive A R} : Transitive (Forall2 R).

  Global Instance Forall2_pre {A} R `{PreOrder A R} : PreOrder (Forall2 R).

  Global Instance Forall2_part_eq {A} R `{PartialOrder A eq R } :
    PartialOrder eq (Forall2 R).

  Lemma Forall2_trans_relations_weak {A B C}
        (R1:ABProp) (R2:BCProp) (R3:ACProp):
    ( a b c, R1 a b R2 b c R3 a c)
     a b c, Forall2 R1 a b Forall2 R2 b c Forall2 R3 a c.

    Lemma Forall2_eq {A} (l1 l2:list A): Forall2 eq l1 l2 l1 = l2.

    Lemma Forall2_flip {A B} {P:ABProp} {l1 l2} :
      Forall2 P l1 l2 Forall2 (fun x yP y x) l2 l1.

    Lemma Forall2_In_l {A B} {P:ABProp} {l1 l2 a} :
      Forall2 P l1 l2
      In a l1
       b,
        In b l2
        P a b.

    Lemma Forall2_In_r {A B} {P:ABProp} {l1 l2 b} :
      Forall2 P l1 l2
      In b l2
       a,
        In a l1
        P a b.

  Lemma Forall2_app_tail_inv {A B} P l1 l2 a1 a2 :
     @Forall2 A B P (l1 ++ (a1::nil)) (l2 ++ (a2::nil))
     Forall2 P l1 l2 P a1 a2.

  Lemma filter_Forall2_same {A B} P f g (l1:list A) (l2:list B) :
    Forall2 P l1 l2
    map f l1 = map g l2
    Forall2 P (filter f l1) (filter g l2).

  Lemma Forall2_map_Forall {A B:Type} (P:ABProp) (f:AB) l :
    Forall2 P l (map f l) Forall (fun xP x (f x)) l.

  End forall2.

  Section forallb_ordpairs.

    Fixpoint forallb_ordpairs {A} f (l:list A)
      := match l with
         | niltrue
         | x::lsforallb (f x) ls && forallb_ordpairs f ls
         end.

    Lemma forallb_ordpairs_ForallOrdPairs {A} f (l:list A) :
      forallb_ordpairs f l = true (ForallOrdPairs (fun x yf x y = true) l).

    Lemma forallb_ordpairs_ext {A} f1 f2 (l:list A) :
      ( x y, In x l In y l f1 x y = f2 x y)
      forallb_ordpairs f1 l = forallb_ordpairs f2 l.

    Fixpoint forallb_ordpairs_refl {A} (f:AAbool) (l:list A)
      := match l with
         | niltrue
         | x::lsforallb (f x) (x::ls) && forallb_ordpairs_refl f ls
         end.

    Lemma forallb_ordpairs_refl_conj A f (l:list A) :
      forallb_ordpairs_refl f l = forallb_ordpairs f l && forallb (fun xf x x) l.

        Lemma forallb_ordpairs_app_cons {A} f (l:list A) x :
    forallb_ordpairs f l = true
    forallb (fun yf y x) l = true
    forallb_ordpairs f (l ++ x::nil) = true.

  Lemma forallb_ordpairs_refl_app_cons {A} f (l:list A) x :
    forallb_ordpairs_refl f l = true
    f x x = true
    forallb (fun yf y x) l = true
    forallb_ordpairs_refl f (l ++ x::nil) = true.

  End forallb_ordpairs.

  Lemma app_cons_cons_expand {A} (l:list A) a b :
    l ++ a::b::nil = (l ++ a ::nil)++b::nil.

  Section remove.
    Context {A:Type}.
    Context {eqdec:EqDec A eq}.

    Lemma remove_in_neq
          (l : list A) (x y : A) : x y
                                   (In x l In x (remove eqdec y l)).

    Lemma list_in_remove_impl_diff x y l:
      In x (remove eqdec y l) x y.

    Lemma list_remove_append_distrib:
       (v:A) (l1 l2:list A),
        remove eqdec v l1 ++ remove eqdec v l2 = remove eqdec v (l1 ++ l2).

    Lemma list_remove_idempotent:
       v l,
        remove eqdec v (remove eqdec v l) = remove eqdec v l.

    Lemma list_remove_commute:
       v1 v2 l,
        remove eqdec v1 (remove eqdec v2 l) = remove eqdec v2 (remove eqdec v1 l).

    Remark list_remove_in v1 v2 l1 l2:
      (In v1 l1 In v1 l2)
      In v1 (remove eqdec v2 l1) In v1 (remove eqdec v2 l2).

    Lemma remove_inv v n l:
      In v (remove eqdec n l) In v l v n.

    Lemma not_in_remove_impl_not_in:
       x v l,
        x v
        ¬ In x (remove eqdec v l)
        ¬ In x l.

    Fixpoint remove_all (x : A) (l : list A) : list A :=
      match l with
      | nilnil
      | y::tlif (x == y) then (remove_all x tl) else y::(remove_all x tl)
      end.

    Global Instance remove_all_proper : Proper (eq ==> ldeqA ==> ldeqA) remove_all.

    Lemma remove_all_filter x l:
      remove_all x l = filter (nequiv_decb x) l.

    Lemma remove_all_app (v:A) l1 l2
      : remove_all v (l1 ++ l2) = remove_all v l1 ++ remove_all v l2.

    Lemma fold_left_remove_all_In {l init a} :
      In a (fold_left (fun (a : list A) (b : A) ⇒
                       filter (nequiv_decb b) a) l init)
       In a init ¬ In a l.

  End remove.

  Lemma nin_remove {A} dec (l:list A) a :
    ¬ In a l remove dec a l = l.

  Section repall.
    Context {A:Type}.
    Context `{eqdec:EqDec A eq}.

    Definition replace_all l v n
      := map (fun xif eqdec x v then n else x) l.

    Lemma replace_all_nin l v n :
      ¬ In v l
      map (fun xif eqdec x v then n else x) l = l.

    Lemma replace_all_remove_neq l v0 v n:
      v v0 n v0
      remove eqdec v0
             (map (fun xif eqdec x v then n else x)
                  l) =
      (map (fun xif eqdec x v then n else x)
           (remove eqdec v0 l)).

    Lemma remove_replace_all_nin l v v' :
      ¬ In v' l
      remove eqdec v' (replace_all l v v') =
      remove eqdec v l.

    Definition flat_replace_all l (v:A) n
      := flat_map (fun xif eqdec x v then n else (x::nil)) l.

    Lemma flat_replace_all_nil l (v:A) :
      flat_replace_all l v nil = @remove_all A eqdec v l.

    Lemma flat_replace_all_app l1 l2 (v:A) n
      : flat_replace_all (l1 ++ l2) v n
        = flat_replace_all l1 v n ++ flat_replace_all l2 v n.

    Lemma fold_left_remove_all_nil_in_inv {B} {x ps l}:
      In x (fold_left
              (fun (h : list nat) (xy : nat × B) ⇒
                 remove_all (fst xy) h)
              ps l)
      In x l.

    Lemma fold_left_remove_all_nil_in_inv' {x ps l}:
      In x (fold_left
              (fun (h : list nat) (xy : nat) ⇒
                 remove_all xy h)
              ps l)
      In x l.

    Lemma fold_left_remove_all_nil_in_not_inv' {x ps l}:
      In x (fold_left
              (fun (h : list nat) (xy : nat ) ⇒
                 remove_all xy h)
              ps l)
      ¬ In x ps.

    Lemma replace_all_remove_eq (l : list A) (v n : A) :
      map (fun x : Aif eqdec x v then n else x) (remove eqdec v l) = (remove eqdec v l).

  End repall.

  Section incl.

    Definition cut_down_to {A B} {dec:EqDec A eq} (l:list (A×B)) (l2:list A) :=
      filter (fun aexistsb (fun z(fst a) ==b z) l2) l.

    Lemma cut_down_to_in
          {A B} {dec:EqDec A eq}
          (l:list (A×B)) l2 a :
      In a (cut_down_to l l2) In a l In (fst a) l2 .

    Lemma cut_down_to_app {A B} {dec:EqDec A eq}
          (l l':list (A×B)) l2 :
      cut_down_to (l++l') l2 = cut_down_to l l2 ++ cut_down_to l' l2.

    Lemma incl_dec {A} {dec:EqDec A eq} (l1 l2:list A) :
      {incl l1 l2} + {¬ incl l1 l2}.

    Global Instance incl_pre A : PreOrder (@incl A).

    Lemma set_inter_contained {A} dec (l l':list A):
      ( a, In a l In a l')
      set_inter dec l l' = l.

    Lemma set_inter_idempotent {A} dec (l:list A):
      set_inter dec l l = l.

    Lemma set_inter_comm_in {A} dec a b :
      ( x, In x (@set_inter A dec a b) In x (set_inter dec b a)) .

   Lemma nincl_exists {A} {dec:EqDec A eq} (l1 l2:list A) :
     ¬ incl l1 l2 {x | In x l1 ¬ In x l2}.

  End incl.

  Section equivlist.
    Context {A:Type}.

    Definition equivlist (l l':list A)
      := x, In x l In x l'.

    Global Instance equivlist_equiv : Equivalence equivlist.

    Global Instance Permutation_equivlist :
      subrelation (@Permutation A) equivlist.

    Lemma equivlist_in {l1 l2} : equivlist l1 l2 ( x:A, In x l1 In x l2).

    Lemma equivlist_incls (l1 l2:list A) :
      equivlist l1 l2 (incl l1 l2 incl l2 l1).

    Global Instance equivlist_In_proper : Proper (eq ==> equivlist ==> iff) (@In A).

    Lemma equivlist_dec {dec:EqDec A eq} (l1 l2:list A) :
      {equivlist l1 l2} + {¬ equivlist l1 l2}.

    Lemma equivlist_nil {l:list A} : equivlist l nil l = nil.

    Lemma app_idempotent_equivlist (l:list A) :
      equivlist (l++l) l.

    Lemma app_commutative_equivlist (l1 l2:list A) :
      equivlist (l1++l2) (l2++l1).

    Lemma app_contained_equivlist (a b:list A) :
      incl b a
      equivlist (a ++ b) a.

    Lemma set_inter_equivlist dec a b :
      equivlist (@set_inter A dec a b) (set_inter dec b a) .

    Global Instance set_inter_equivlist_proper dec : Proper (equivlist ==> equivlist ==> equivlist) (@set_inter A dec).

  Lemma equivlist_cons l1 l2 (s:A) :
    equivlist l1 l2
    equivlist (s::l1) (s::l2).

  Global Instance equivlist_filter :
    Proper (eq ==> equivlist ==> equivlist) (@filter A).

  Global Instance equivlist_remove_all {dec:EqDec A eq} :
    Proper (eq ==> equivlist ==> equivlist) (@remove_all A dec).

    Lemma incl_list_dec (dec: x y:A, {x = y} + {x y}) (l1 l2:list A) : {( x, In x l1 In x l2)} + {~( x, In x l1 In x l2)}.

  End equivlist.

      Lemma set_inter_assoc {A} dec a b c:
        @set_inter A dec (set_inter dec a b) c
        = set_inter dec a (set_inter dec b c).

  Section Assym_over.

    Definition asymmetric_over {A} R (l:list A) :=
       x y, In x l In y l ¬R x y ¬R y x x = y.

    Lemma asymmetric_asymmetric_over {A} {R} :
      ( x y:A, ¬R x y ¬R y x x = y)
       l, asymmetric_over R l .

    Lemma asymmetric_over_incl {A} {R} {l2:list A}
      : asymmetric_over R l2
         l1,
          ( x, In x l1 In x l2)
          asymmetric_over R l1.

    Lemma asymmetric_over_equivlist {A} {R} {l1 l2:list A} :
      equivlist l1 l2
      (asymmetric_over R l1
       asymmetric_over R l2).

    Lemma asymmetric_over_cons_inv {A} {R} {a:A} {l1} :
      asymmetric_over R (a::l1)
      asymmetric_over R l1.


    Lemma asymmetric_over_swap {A} R {a b:A} {l1} :
      asymmetric_over R (a::b::l1)
      asymmetric_over R (b::a::l1).

  End Assym_over.


  Global Instance perm_in {A} : Proper (eq ==> (@Permutation A) ==> iff) (@In A).

  Lemma NoDup_perm' {A:Type} {a b:list A} : NoDup a Permutation a b NoDup b.

  Global Instance NoDup_perm {A:Type} :
    Proper (@Permutation A ==> iff) (@NoDup A).

  Lemma NoDup_Permutation' {A : Type} (l l' : list A) :
    NoDup l
    NoDup l' equivlist l l' Permutation l l'.

  Lemma NoDup_rev {A:Type} (l:list A) : NoDup (rev l) NoDup l.

  Lemma NoDup_app_inv {A:Type} {a b:list A} : NoDup (a++b) NoDup a.


  Lemma NoDup_app_inv2 {A:Type} {a b:list A} : NoDup (a++b) NoDup b.

  Lemma NoDup_dec {A:Type} {dec:EqDec A eq} (l:list A): {NoDup l} + {¬NoDup l}.

  Section disj.
    Definition disjoint {A:Type} (l1 l2:list A)
      := x, In x l1 In x l2 False.

    Lemma NoDup_app_dis {A:Type} (a b:list A) :
      NoDup (a++b) disjoint a b.

    Lemma disjoint_cons_inv1 {A:Type} {a:A} {l1 l2} :
      disjoint (a :: l1) l2 disjoint l1 l2 ¬ In a l2.

    Lemma disjoint_app_l {A} (l1 l2 l3:list A) :
    disjoint (l1 ++ l2) l3 (disjoint l1 l3 disjoint l2 l3).

   Lemma disjoint_app_r {A} (l1 l2 l3:list A) :
    disjoint l1 (l2 ++ l3) (disjoint l1 l2 disjoint l1 l3).

    Lemma NoDup_app {A:Type} {a b:list A} :
      disjoint a b NoDup a NoDup b NoDup (a++b).

    Global Instance disjoint_sym {A:Type} : Symmetric (@disjoint A).

  End disj.

  Lemma unmap_NoDup {A B} (f:AB) l :
    NoDup (map f l) NoDup l.

  Lemma map_inj_NoDup {A B} (f:AB)
            (inj: x y, f x = f y x = y) (l:list A) :
        NoDup l
        NoDup (map f l).

  Lemma filter_NoDup {A} (f:Abool) l :
    NoDup l NoDup (filter f l).

  Fixpoint zip {A B} (l1:list A) (l2: list B) : option (list (A × B)) :=
    match l1 with
    | nil
      match l2 with
      | nilSome nil
      | _None
      end
    | x1 :: l1'
      match l2 with
      | nilNone
      | x2 :: l2'
        match zip l1' l2' with
        | NoneNone
        | Some l3
          Some ((x1, x2) :: l3)
        end
      end
    end.

End RList.