Docs GODI Archive
Projects Blog Link DB

Search GODI:


More options
File lib/coq/user-contrib/caduceus_lists.v GODI Package apps-why
 
   caduceus_lists.v  
Require Import Why.
Require Export caduceus_why.
Require Export List.

Section MoreList.
(** this should go in List stdlib*)

Lemma not_in_cons_neq :
  forall A:Set, forall x:A, forall y l,
  ~ In x (y :: l) -> x <> y.
Proof.
unfold not.
intros; apply H; left; auto.
Qed.

Implicit Arguments not_in_cons_neq.

Lemma In_app_cons :
 forall (A:Set) (l:list A) (x:A),
   In x l ->
     exists l1 : list A, exists l2 : list A, l = app l1 (cons x l2).
Proof.
simple induction l; simpl; intuition.
exists (nil (A:=A)); exists l0; simpl; subst; auto.
elim (H x H1); clear H; intros.
elim H; clear H; intuition.
exists (cons a x0); exists x1; simpl; subst; auto.
Qed.

End MoreList.

Implicit Arguments In_app_cons [A].

(** the Coq pointer list associated to a (finite) linked list *)

Definition plist (R:Set) := list (pointer R).

Definition in_list (R:Set) := (@In (pointer R)).

(** * Paths *)

Section Paths.

Variable R: Set.

(** [(lpath t p1 l p2)] :
    there is a path from pointer [p1] to pointer [p2] using links in store [t],
    and the list of pointers along this path is [l]. *)

Inductive lpath (a: alloc_table)  (next: pointer R -> pointer R) : 
      pointer R -> plist R -> pointer R -> Prop :=
  | Path_null : forall p:pointer R, lpath a next p nil p
  | Path_cons :
      forall p1 p2:pointer R,
        ~(p1 = null) -> valid a p1 ->
        forall l:list (pointer R),
          lpath a next (next p1) l p2 -> lpath a next  p1 (cons p1 l) p2.

Hint Constructors lpath.

Lemma lpath_eq_fun : 
  forall (a: alloc_table) (f g :pointer R -> pointer R) (p q: pointer R)
(l : list (pointer R)),
 (forall p, In p l -> f p = g p) ->
 lpath a f p l q  -> lpath a g p l q
.
intros.
induction H0.
constructor.
constructor; auto.
rewrite <-  H.
apply IHlpath.
intros.
apply H.
right;auto.
left;auto.
Qed.

(** * Lists *)

(** [(llist t p l)]: there is a (finite) linked list starting from pointer [p]
    using links in store [t], and this list of pointers is [l] *)

Definition llist (a: alloc_table) (next : pointer R -> pointer R) (p:pointer R) 
  (l:plist R) :=
  lpath a next p l null.

Hint Unfold llist .

(** inductive characterization of [llist] (which could have been an
    inductive definition of [llist])  *)

Lemma llist_null :
 forall (a: alloc_table) (next : pointer R -> pointer R) (p:pointer R), 
  llist a next p nil -> p = null.
Proof.
unfold llist; inversion 1; trivial.
Qed.

Lemma llist_cons :
 forall (a: alloc_table) (next : pointer R -> pointer R) (p1 p2:pointer R) (l:plist R),
   llist a next p1 (cons p2 l) -> p1 = p2 /\ llist a next (next p2) l.
Proof.
unfold llist; inversion 1; intuition.
Qed.

Lemma llist_head :
 forall (a: alloc_table) (next : pointer R -> pointer R) (p1 p2:pointer R) (l:plist R),
   llist a next p1 (cons p2 l) -> p1 = p2.
Proof.
unfold llist; inversion 1; intuition.
Qed.

Hint Resolve llist_head.

Lemma llist_start :
 forall (a: alloc_table) (next : pointer R -> pointer R ) (p1:pointer R) (l:plist R),
   llist a next p1 l -> p1 <> null -> l = p1 :: tail l.
Proof.
unfold llist; inversion 1; intuition.
Qed.

Lemma llist_head_non_null :
 forall (a: alloc_table) (next : pointer R-> pointer R) (p1 p2:pointer R) (l:plist R),
   llist a next p1 (cons p2 l) -> p1 <> null.
Proof.
unfold llist; inversion 1; intuition.
Qed.

(** invariance of a list when updating a cell outside of this list *)

Lemma lpath_pset_same :
 forall (a: alloc_table) (m : memory (pointer R) R) (p p':pointer R) (l:plist R),
   lpath a (acc m) p l p' ->
   forall p1 p2:pointer R,
     ~ In p1 l -> lpath a (acc (upd m p1 p2)) p l p'.
Proof.
simple induction 1; intuition.
apply Path_cons; auto.
 rewrite acc_upd_neq; auto.
auto with *.
red; intro.
apply H4; subst p0; auto with *.
Qed.
Hint Resolve lpath_pset_same .

Lemma llist_pset_same :
 forall (a: alloc_table) (m : memory (pointer R) R) (p:pointer R) (l:plist R),
   llist a (acc m) p l ->
   forall p1 p2:pointer R,
     ~ In p1 l -> llist a (acc (upd m p1 p2)) p l.
Proof.
unfold llist; intros; apply lpath_pset_same; auto.
Qed.
Hint Resolve llist_pset_same .

(** [llist] is a function *)

Lemma llist_function :
 forall (a a': alloc_table) (next : pointer R -> pointer R) (l1 l2:plist R) (p:pointer R),
   llist a next p l1 -> llist a' next p l2 -> l1 = l2.
Proof.
(* induction l1; intuition. *)
(* generalize(llist_null a _ _ H). *)
(* intro h. *)
(* rewrite h in H0. *)
(* inversion H0; intuition. *)

simple induction l1; intuition.

inversion H; subst.
inversion H0; intuition.
inversion H1. subst. inversion H0. elimtype False; apply H4. auto.
inversion H0; subst.
inversion H1; subst.
apply (f_equal (cons a0)).
apply H with (next a0); auto.
Qed.

Implicit Arguments llist_function.

Lemma llist_append :
 forall (a: alloc_table) (next : pointer R -> pointer R) (l1 l2:plist R) (p:pointer R),
   llist a next p (app l1 l2) ->
    exists p' : pointer R, lpath a next p l1 p' /\ llist a next p' l2.
Proof.
simple induction l1; simpl; intuition.
exists p; auto.
inversion H0; subst.
elim (H l2 (next a0) H7); intuition.
exists x; auto.
Qed.

Implicit Arguments llist_append.

Lemma list_length_absurd :
 forall (A:Set) (l1 l2:list A), length l1 <> length l2 -> l1 <> l2.
Proof.
simple induction l1; simple induction l2; simpl; intuition idtac.
discriminate H1.
discriminate H1.
injection H2; intros.
apply (H l0); intuition.
Qed.

Lemma length_app :
 forall (A:Set) (l1 l2:list A),
   length (app l1 l2) = (length l1 + length l2)%nat.
Proof.
simple induction l1; simpl; intuition.
Qed.

(** a list starting with [p] does not contain [p] in its remaining elements *)

Lemma llist_not_starting :
 forall (a: alloc_table) (next: pointer R -> pointer R) (p:pointer R) (l:plist R),
   llist a next (next p) l -> ~ In p l.
Proof.
red; intros.
elim (In_app_cons l _ H0); intros.
elim H1; clear H1; intros.
subst l.
elim (llist_append x (cons p x0) H); intuition.
inversion H3; subst.
generalize (llist_function H9 H).
intro; apply (list_length_absurd _ x0 (app x (cons p x0))); auto.
rewrite length_app; simpl; omega.
Qed.

Lemma llist_no_rep: 
  forall (a : alloc_table)(next : pointer R ->pointer R)(p q : pointer R)
(l : plist R) , llist a next p (q :: l) -> p=q /\ ~ In p l.
unfold llist.
intros.
inversion H.
subst.
split;auto.
apply llist_not_starting with a next.
auto.
Qed.

(** * Finite lists characterization *)

(*
Inductive is_list (a: alloc_table) (next: pointer R -> pointer R) : 
   pointer R -> Prop :=
  | List_null : is_list a next null
  | List_cons :
      forall p:pointer R,
        ~(p = null) -> valid a p -> is_list a next (next p) -> is_list a next p.

Hint Constructors is_list.

Lemma is_list_llist :
 forall (a: alloc_table) (next: pointer R -> pointer R) (p:pointer R),
   is_list a next p -> exists l : plist R, llist a next p l.
Proof.
intros; elim H.
exists (nil (A:=pointer R)); intuition.
intros. elim H3; intros.
exists (cons p0 x); intuition.
Qed.

Lemma llist_is_list :
 forall (a: alloc_table) (next: pointer R -> pointer R) (l:plist R) (p:pointer R),
   llist a next p l -> is_list a next p.
Proof.
simple induction l; intuition.
inversion H; auto.
inversion H0; intuition.
Qed.
*)

Definition is_list a next p := exists l : plist R, llist a next p l.

(** * WF relation over linked lists *)


Definition Length := ((memory (pointer R) R) * (pointer R))%type.
Definition length (t : memory (pointer R) R) (p:pointer R) := (t, p).

Definition length_order (c1 c2: memory (pointer R) R * pointer R) : Prop :=
  let (t1, p1) := c1 in
  let (t2, p2) := c2 in
    exists a : alloc_table,
    exists l1 : plist R,
    exists l2 : plist R,
    llist a (acc t1) p1 l1 /\ llist a (acc t2) p2 l2 /\ (List.length l1 < List.length l2)%nat.

Lemma length_order_wf : well_founded length_order.
Proof.
apply well_founded_inv_lt_rel_compat with
 (F := fun (x:Length) n =>
         let (t, p) := x in
         exists a : alloc_table,
         exists l : plist R, llist a (acc t) p l /\ List.length l = n).
unfold length_order, inv_lt_rel.
simple destruct x; simple destruct y; intuition.
elim H; clear H; intros a H; elim H; clear H;
intros l1 H; elim H; clear H; intros l2 H.
intuition.
exists (List.length l1).
exists a; exists l1; intuition.
intuition.
elim H1; clear H1; intros a0 H1; elim H1; intros l2'; intuition.
generalize (llist_function H H4); intro; subst l2.
omega.
Qed.

Hint Resolve length_order_wf .

Lemma length_acc :
  forall a tl p,
  is_list a (acc tl) p -> p <> null ->
  length_order (length tl (acc tl p)) (length tl p).
Proof.
unfold length,length_order,is_list ; intros.
exists a.
inversion H.
destruct x.
inversion H1; subst; auto.
elim H0; auto.
exists x.
exists (p0::x).
intuition.
inversion H1; auto.
Qed.

Hint Resolve length_acc.

(** * Disjointness *)

(** [disjoint l1 l2]: no common element between lists [l1] and [l2] *)

Definition disjoint (A:Set) (l1 l2:list A) : Prop :=
  (forall x:A, In x l1 -> ~ In x l2) /\
  (forall x:A, In x l2 -> ~ In x l1).
Implicit Arguments disjoint.

Section Disjointness.

Variable A : Set.
Variables l1 l2 : list A.
Variable x : A.

Lemma disjoint_cons :
 disjoint l1 (cons x l2) -> ~ In x l2 -> disjoint (cons x l1) l2.
Proof.
unfold disjoint; intuition.
elim (in_inv H); intuition.
subst x; intuition.
apply H1 with x0; intuition.
elim (in_inv H3); intuition.
subst x; intuition.
apply H1 with x0; intuition.
Qed.

Lemma disjoint_tail : disjoint l1 l2 -> disjoint (tail l1) l2.
Proof.
unfold disjoint.
destruct l1; simpl; intuition.
apply H1 with x0; intuition.
apply H0 with x0; intuition.
Qed.

Lemma disjoint_nil_l : disjoint nil l2.
Proof.
unfold disjoint; intuition.
Qed.

Lemma disjoint_l_nil : disjoint l1 nil.
Proof.
unfold disjoint; intuition.
Qed.

Hint Resolve disjoint_cons disjoint_tail disjoint_nil_l disjoint_l_nil .

End Disjointness.

(** * Cyclicity *)

(*
Section Cyclicity.

Variable a : alloc_table.
Variable tl : pointer -> pointer.

Definition finite (p : pointer) :=
  exists r : plist,
  forall p',
  (exists lpp', lpath a tl p lpp' p') -> p'<>null -> valid a p' /\ In p' r.

Lemma finite_is_valid : forall p, p<>null -> finite p -> valid a p.
Proof.
unfold finite; intuition.
elim H0; clear H0; intuition.
assert (h : exists lpp' : plist, lpath a tl p lpp' p).
exists (@nil pointer); auto.
generalize (H0 p h); clear H0; intuition.
Save.

Definition cyclic (p : pointer) :=
  exists l1:plist, exists l2:plist, exists p',
  p'<>null /\ lpath a tl p l1 p' /\ lpath a tl p' l2 p'.

(** [cyclic] and [is_list] are exclusive *)
Lemma cyclic_is_list_exclusive : forall p,
  cyclic p -> is_list a tl p -> False.
Proof.
intros.
elim H; clear H; intros l1 H; elim H; clear H; intros l2 H;
elim H; clear H; intros p'; intuition.
elim (is_list_llist H0); clear H0; intros l0 Hl0.
unfold llist in Hl0.
Admitted.

(** when a list is finite, it is either [cyclic] or [is_list] *)
Lemma finite_cyclic_or_is_list : forall p,
  finite p -> cyclic p \/ is_list a tl p.
Proof.
Admitted.

End Cyclicity.
*)

Axiom eq_pointer_dec : forall p1 p2 : pointer R, {p1 = p2} + {p1 <> p2}.

Section NoRepetition.

Fixpoint no_rep (l:plist R) {struct l}: Prop :=
match l with
| nil => True
| (a::l) => (if In_dec eq_pointer_dec a l then False else True)  /\ no_rep l
end.

Lemma split_list :
  forall (A:Set)(x:A) l, In x l ->
  exists l1, exists l2, l = l1 ++ x :: l2.
induction l; simpl; intuition.
exists (nil :list  A); exists l; subst; auto.
elim H; clear H; intros l1 H; elim H; clear H; intros l2 H.
exists (a :: l1); exists l2; subst; auto.
Qed.

Implicit Arguments split_list.

Lemma no_rep_sublist1 :
 forall (l : plist R)(p:pointer R),
  no_rep (p::l) -> no_rep l.
intros.
destruct H.
apply H0.
Qed.

Lemma no_rep_sublist :
  forall (l l1 l2 : plist R),
  no_rep l -> l = l1 ++ l2 -> no_rep l2.
induction l.
intros.
assert (l1++l2=nil);auto.
generalize (app_eq_nil l1 l2 H1).
intuition;subst;auto.
intros.
destruct l1.
assert (a::l = l2).
auto.
subst;auto.
apply IHl with l1.
apply no_rep_sublist1 with a;auto.
rewrite <-app_comm_cons in H0.
inversion H0.
auto.
Qed.

Ltac caseq t := generalize (refl_equal t);pattern t at -1;case t.

Lemma no_rep_p : forall (p1:pointer R)(lp: plist R), no_rep(p1::lp)->
~In p1 lp.
intros.
simpl in H.
intro.
inversion_clear H.
caseq (In_dec eq_pointer_dec p1 lp).
intros i e.
rewrite e in H1.
elim H1.
intros i.
elim (i H0).
Qed.

Lemma no_rep_sublist2 : forall (l l1 l2 : plist R) (a : pointer R), no_rep l ->
l = l1 ++a::l2 -> no_rep (l1++l2).
induction l.
intros.
destruct l1.
simpl in H0.
inversion H0.
inversion H0.
intros.
induction l1.
simpl in *|-*.
apply no_rep_sublist1 with a.
inversion H0;subst.
auto.
inversion H0.
subst.
unfold no_rep.
simpl.
elim H.
intros.
destruct (In_dec eq_pointer_dec a1 (l1 ++ a0::l2) ) .
inversion H1.
destruct (In_dec eq_pointer_dec a1 (l1 ++ l2)).
elim n.
elim (in_app_or _ _ _ i).
intro; apply in_or_app; auto.
intro; apply in_or_app; intuition.
intuition.
apply IHl with a0;auto.
Qed.

Lemma no_rep_sublist_bis : forall (l2 l l1  : plist R), no_rep l ->
l = l1 ++ l2 -> no_rep l1.
induction l2.
intros.
subst.
rewrite <- app_nil_end in H.
auto.
intros.
subst.
assert ((l1 ++ a :: l2) = (l1 ++ a :: l2)).
auto.
generalize (no_rep_sublist2 (l1 ++ a :: l2) l1 l2 a H H0).
intro.
apply IHl2 with (l1++l2);auto.
Qed.

Lemma no_rep_false : forall (p1 : pointer R)(lp : plist R),
no_rep (p1 :: p1 :: lp) -> False.
intros.
unfold no_rep in H; fold no_rep in H.
inversion_clear H as [H0 H1].
destruct (In_dec eq_pointer_dec p1 (p1 :: lp)); auto with *.
Qed.

Lemma no_rep_false2 : forall (p1 : pointer R)(lp1 lp2 : plist R),
no_rep (p1 ::lp1 ++ p1 :: lp2) -> False.
intros.
simpl in H.
inversion_clear H.
destruct (In_dec eq_pointer_dec p1 (lp1 ++ p1 :: lp2)).
inversion H0.
apply n;clear n.
clear H1.
induction lp1.
simpl;left;auto.
right;auto.
Qed.

Lemma no_rep_p_bis : forall (p1:pointer R)(lp1 lp2:plist R), no_rep(lp1++p1::lp2)->
~In p1 lp1.
intros.
intro.
induction lp1.
inversion H0.
generalize (eq_pointer_dec a p1).
intros [p|p].
subst.
apply no_rep_false2 with p1 lp1 lp2;auto.
apply IHlp1.
apply no_rep_sublist1 with a;auto.
inversion H0.
elim (p H1).
auto.
Qed.


Lemma no_rep_in_app :
  forall p : pointer R,
  forall lp1 lp2a lp2b : plist R,
  no_rep (p::lp1) -> no_rep (lp2a++p::lp2b) ->
  (forall q : pointer R,
     In q (p::lp1) -> In q (lp2a++p::lp2b)) ->
  forall q : pointer R, In q lp1 -> In q (lp2a ++ lp2b).
intros.
case (eq_pointer_dec q p).
intro.
subst.
generalize  (no_rep_p _ _ H).
intuition.
intro.
assert (In q (lp2a ++ p :: lp2b) -> In q (lp2a++lp2b)).
intros.
apply in_or_app.
generalize (in_app_or lp2a (p::lp2b) q H3) .
intros [H4|H4].
left;auto.
destruct H4.
elim n;auto.
right;auto.
apply H3.
apply H1.
right;auto.
Qed.

Lemma no_rep_sublist3 : forall (l l1 l2 : plist R) ( a : pointer R), no_rep l ->
l = l1 ++a::l2 -> no_rep (a::l1++l2).
induction l as [ | p1 l].
intros l1 l2 a _ H; destruct l1; simpl in H; discriminate.
destruct l1 as [ | p1' l1]; intros l2 a H1 H2.
simpl in H2; simpl app; rewrite <- H2; trivial.
simpl in H2; injection H2; clear H2; intros; subst;
rewrite <- app_comm_cons.
inversion H1 as [H2 H3].
destruct (In_dec eq_pointer_dec p1' (l1 ++ a :: l2)) as [i | not_i].
contradiction.
split.
destruct (In_dec eq_pointer_dec a (p1' :: l1 ++ l2)) as [[i' | i'] | not_i']; trivial.
apply not_i; subst; apply in_or_app; right; left; trivial.
assert (H4 := IHl l1 l2 a H3 (refl_equal _)); simpl in H4.
destruct (In_dec eq_pointer_dec a (l1 ++ l2)) as [ _ | not_i''].
intuition.
absurd (In a (l1 ++ l2)); trivial.
rewrite app_comm_cons;
apply no_rep_sublist2 with (p1' :: l1 ++ a :: l2) a; trivial.
Qed.

Lemma no_rep_in_app2 :
  forall p : pointer R,
  forall lp1 lp2a lp2b : plist R,
  no_rep (p::lp1) -> no_rep (lp2a++p::lp2b) ->
  (forall q : pointer R,
    In q (lp2a++p::lp2b) -> In q (p::lp1)) ->
  forall q : pointer R, In q (lp2a ++ lp2b) -> In q lp1.
intros.
case (eq_pointer_dec q p).
intro.
subst.
assert (lp2a ++ p :: lp2b = lp2a ++ p :: lp2b).
auto.
generalize (no_rep_sublist2
  (lp2a ++ p :: lp2b) lp2a lp2b p H0 H3);intro.
generalize (no_rep_sublist
  (lp2a ++ p :: lp2b) lp2a (p::lp2b)  H0).
intros.
generalize (no_rep_sublist3
  (lp2a ++ p :: lp2b) lp2a lp2b p H0 H3).
intro.
inversion H6.
destruct (In_dec eq_pointer_dec p (lp2a ++ lp2b)).
inversion H7.
elim ( n H2).
intro.
assert (In q (lp2a ++ p :: lp2b)).
generalize ( in_app_or lp2a lp2b q H2).
intuition.
generalize (H1 q H3);intro.
inversion H4.
elim (n ).
auto.
auto.
Qed.

End NoRepetition.



(* consecutives pairs in a list *)

Fixpoint pair_in_list (p1:pointer R) (p2:pointer R)(l: plist R) {struct l} : Prop :=
  match l with
  | nil => False
  | b :: m => (b = p1 /\ match  m with
                                      | nil => False
                                      | c::n => c = p2
                                      end)
                                      \/ pair_in_list p1 p2 m
  end.

Lemma pair_in_list_in :
  forall (l : plist R) (p1 p2 p3: pointer R),
    pair_in_list p1 p2 (p3::l) -> In p2 l.
induction l.
simpl; tauto.
simpl; destruct l.
intros; subst; intuition.
intros; intuition.
subst; intuition.
right.
apply IHl with p1 (@null R).
simpl; right; auto.
Qed.

(* Inductive olist : pointer -> Prop := *)
(*   | List_null : is_list a next null *)
(*   | List_cons : *)
(*       forall p:pointer, *)
(*         ~(p = null) -> valid a p -> is_list a next (next p) -> is_list a next p. *)


End Paths.



This web site is published by Informatikbüro Gerd Stolpmann
Powered by Caml