aboutsummaryrefslogtreecommitdiffhomepage
path: root/theories/FSets/FSetAVL.v
diff options
context:
space:
mode:
authorGravatar letouzey <letouzey@85f007b7-540e-0410-9357-904b9bb8a0f7>2008-03-21 19:33:07 +0000
committerGravatar letouzey <letouzey@85f007b7-540e-0410-9357-904b9bb8a0f7>2008-03-21 19:33:07 +0000
commiteb54828e4e6a953a2694d2f3e3af177c20f1fe31 (patch)
tree278039549e75b78365ddc787db847045794020be /theories/FSets/FSetAVL.v
parent123c8683a25b34070d4874df4cdd9381d5ceac24 (diff)
One more AVL reorganisation: separate pure functions from proofs + functional scheme.
- Proofs are placed in Raw.Proofs, that may someday become an opaque module. - use Functional Scheme in this module Raw.proofs, instead of Function: less derived objects. - more cleanup. git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@10707 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'theories/FSets/FSetAVL.v')
-rw-r--r--theories/FSets/FSetAVL.v1172
1 files changed, 615 insertions, 557 deletions
diff --git a/theories/FSets/FSetAVL.v b/theories/FSets/FSetAVL.v
index e3df9feb0..442d18b57 100644
--- a/theories/FSets/FSetAVL.v
+++ b/theories/FSets/FSetAVL.v
@@ -44,7 +44,6 @@ Unset Strict Implicit.
Module Raw (Import I:Int)(X:OrderedType).
Open Local Scope Int_scope.
-Module MX := OrderedTypeFacts X.
Definition elt := X.t.
@@ -53,28 +52,11 @@ Definition elt := X.t.
Notation "a &&& b" := (if a then b else false) (at level 40, left associativity) : bool_scope.
Notation "a ||| b" := (if a then true else b) (at level 50, left associativity) : bool_scope.
-Lemma andb_alt : forall a b : bool, a &&& b = a && b.
-Proof.
- destruct a; simpl; auto.
-Qed.
-
-Lemma orb_alt : forall a b : bool, a ||| b = a || b.
-Proof.
- destruct a; simpl; auto.
-Qed.
-
-
(** Notations and helper lemma about pairs *)
Notation "s #1" := (fst s) (at level 9, format "s '#1'").
Notation "s #2" := (snd s) (at level 9, format "s '#2'").
-Lemma distr_pair : forall (A B:Type)(s:A*B)(a:A)(b:B), s = (a,b) ->
- s#1 = a /\ s#2 = b.
-Proof.
- destruct s; simpl; injection 1; auto.
-Qed.
-
(** * Trees
@@ -100,14 +82,438 @@ Fixpoint cardinal (s : tree) : nat :=
| Node l _ r _ => S (cardinal l + cardinal r)
end.
-(** * Occurrence in a tree *)
+(** * Empty Set *)
+
+Definition empty := Leaf.
+
+(** * Emptyness test *)
+
+Definition is_empty s :=
+ match s with Leaf => true | _ => false end.
+
+(** * Appartness *)
+
+(** The [mem] function is deciding appartness. It exploits the
+ binary search tree invariant to achieve logarithmic complexity. *)
+
+Fixpoint mem x s :=
+ match s with
+ | Leaf => false
+ | Node l y r _ => match X.compare x y with
+ | LT _ => mem x l
+ | EQ _ => true
+ | GT _ => mem x r
+ end
+ end.
+
+(** * Singleton set *)
+
+Definition singleton x := Node Leaf x Leaf 1.
+
+(** * Helper functions *)
+
+(** [create l x r] creates a node, assuming [l] and [r]
+ to be balanced and [|height l - height r| <= 2]. *)
+
+Definition create l x r :=
+ Node l x r (max (height l) (height r) + 1).
+
+(** [bal l x r] acts as [create], but performs one step of
+ rebalancing if necessary, i.e. assumes [|height l - height r| <= 3]. *)
+
+Definition assert_false := create.
+
+Fixpoint bal l x r :=
+ let hl := height l in
+ let hr := height r in
+ if gt_le_dec hl (hr+2) then
+ match l with
+ | Leaf => assert_false l x r
+ | Node ll lx lr _ =>
+ if ge_lt_dec (height ll) (height lr) then
+ create ll lx (create lr x r)
+ else
+ match lr with
+ | Leaf => assert_false l x r
+ | Node lrl lrx lrr _ =>
+ create (create ll lx lrl) lrx (create lrr x r)
+ end
+ end
+ else
+ if gt_le_dec hr (hl+2) then
+ match r with
+ | Leaf => assert_false l x r
+ | Node rl rx rr _ =>
+ if ge_lt_dec (height rr) (height rl) then
+ create (create l x rl) rx rr
+ else
+ match rl with
+ | Leaf => assert_false l x r
+ | Node rll rlx rlr _ =>
+ create (create l x rll) rlx (create rlr rx rr)
+ end
+ end
+ else
+ create l x r.
+
+(** * Insertion *)
+
+Fixpoint add x s := match s with
+ | Leaf => Node Leaf x Leaf 1
+ | Node l y r h =>
+ match X.compare x y with
+ | LT _ => bal (add x l) y r
+ | EQ _ => Node l y r h
+ | GT _ => bal l y (add x r)
+ end
+ end.
+
+(** * Join
+
+ Same as [bal] but does not assume anything regarding heights
+ of [l] and [r].
+*)
+
+Fixpoint join l : elt -> t -> t :=
+ match l with
+ | Leaf => add
+ | Node ll lx lr lh => fun x =>
+ fix join_aux (r:t) : t := match r with
+ | Leaf => add x l
+ | Node rl rx rr rh =>
+ if gt_le_dec lh (rh+2) then bal ll lx (join lr x r)
+ else if gt_le_dec rh (lh+2) then bal (join_aux rl) rx rr
+ else create l x r
+ end
+ end.
+
+(** * Extraction of minimum element
+
+ Morally, [remove_min] is to be applied to a non-empty tree
+ [t = Node l x r h]. Since we can't deal here with [assert false]
+ for [t=Leaf], we pre-unpack [t] (and forget about [h]).
+*)
+
+Fixpoint remove_min l x r : t*elt :=
+ match l with
+ | Leaf => (r,x)
+ | Node ll lx lr lh =>
+ let (l',m) := remove_min ll lx lr in (bal l' x r, m)
+ end.
+
+(** * Merging two trees
+
+ [merge t1 t2] builds the union of [t1] and [t2] assuming all elements
+ of [t1] to be smaller than all elements of [t2], and
+ [|height t1 - height t2| <= 2].
+*)
+
+Fixpoint merge s1 s2 := match s1,s2 with
+ | Leaf, _ => s2
+ | _, Leaf => s1
+ | _, Node l2 x2 r2 h2 =>
+ let (s2',m) := remove_min l2 x2 r2 in bal s1 m s2'
+end.
+
+(** * Deletion *)
+
+Fixpoint remove x s := match s with
+ | Leaf => Leaf
+ | Node l y r h =>
+ match X.compare x y with
+ | LT _ => bal (remove x l) y r
+ | EQ _ => merge l r
+ | GT _ => bal l y (remove x r)
+ end
+ end.
+
+(** * Minimum element *)
+
+Fixpoint min_elt s := match s with
+ | Leaf => None
+ | Node Leaf y _ _ => Some y
+ | Node l _ _ _ => min_elt l
+end.
+
+(** * Maximum element *)
+
+Fixpoint max_elt s := match s with
+ | Leaf => None
+ | Node _ y Leaf _ => Some y
+ | Node _ _ r _ => max_elt r
+end.
+
+(** * Any element *)
+
+Definition choose := min_elt.
+
+(** * Concatenation
+
+ Same as [merge] but does not assume anything about heights.
+*)
+
+Fixpoint concat s1 s2 :=
+ match s1, s2 with
+ | Leaf, _ => s2
+ | _, Leaf => s1
+ | _, Node l2 x2 r2 h2 =>
+ let (s2',m) := remove_min l2 x2 r2 in
+ join s1 m s2'
+ end.
+
+(** * Splitting
+
+ [split x s] returns a triple [(l, present, r)] where
+ - [l] is the set of elements of [s] that are [< x]
+ - [r] is the set of elements of [s] that are [> x]
+ - [present] is [true] if and only if [s] contains [x].
+*)
+
+Fixpoint split x s : t * (bool * t) := match s with
+ | Leaf => (Leaf, (false, Leaf))
+ | Node l y r h =>
+ match X.compare x y with
+ | LT _ => match split x l with
+ | (ll,(pres,rl)) => (ll, (pres, join rl y r))
+ end
+ | EQ _ => (l, (true, r))
+ | GT _ => match split x r with
+ | (rl,(pres,rr)) => (join l y rl, (pres, rr))
+ end
+ end
+ end.
+
+(** * Intersection *)
+
+Fixpoint inter s1 s2 := match s1, s2 with
+ | Leaf, _ => Leaf
+ | _, Leaf => Leaf
+ | Node l1 x1 r1 h1, Node l2 x2 r2 h2 =>
+ match split x1 s2 with
+ | (l2',(true,r2')) => join (inter l1 l2') x1 (inter r1 r2')
+ | (l2',(false,r2')) => concat (inter l1 l2') (inter r1 r2')
+ end
+ end.
+
+(** * Difference *)
+
+Fixpoint diff s1 s2 := match s1, s2 with
+ | Leaf, _ => Leaf
+ | _, Leaf => s1
+ | Node l1 x1 r1 h1, Node l2 x2 r2 h2 =>
+ match split x1 s2 with
+ | (l2',(true,r2')) => concat (diff l1 l2') (diff r1 r2')
+ | (l2',(false,r2')) => join (diff l1 l2') x1 (diff r1 r2')
+ end
+end.
+
+(** * Union *)
+
+(** In ocaml, heights of [s1] and [s2] are compared each time in order
+ to recursively perform the split on the smaller set.
+ Unfortunately, this leads to a non-structural algorithm. The
+ following code is a simplification of the ocaml version: no
+ comparison of heights. It might be slightly slower, but
+ experimentally all the tests I've made in ocaml have shown this
+ potential slowdown to be non-significant. Anyway, the exact code
+ of ocaml has also been formalized thanks to Function+measure, see
+ [ocaml_union] in [FSetFullAVL].
+*)
+
+Fixpoint union s1 s2 :=
+ match s1, s2 with
+ | Leaf, _ => s2
+ | Node _ _ _ _, Leaf => s1
+ | Node l1 x1 r1 h1, Node l2 x2 r2 h2 =>
+ let (l2',r2') := split x1 s2 in
+ join (union l1 l2') x1 (union r1 r2'#2)
+ end.
+
+(** * Elements *)
+
+(** [elements_tree_aux acc t] catenates the elements of [t] in infix
+ order to the list [acc] *)
+
+Fixpoint elements_aux (acc : list X.t) (t : tree) : list X.t :=
+ match t with
+ | Leaf => acc
+ | Node l x r _ => elements_aux (x :: elements_aux acc r) l
+ end.
+
+(** then [elements] is an instanciation with an empty [acc] *)
+
+Definition elements := elements_aux nil.
+
+(** * Filter *)
+
+Fixpoint filter_acc (f:elt->bool) acc s := match s with
+ | Leaf => acc
+ | Node l x r h =>
+ filter_acc f (filter_acc f (if f x then add x acc else acc) l) r
+ end.
+
+Definition filter f := filter_acc f Leaf.
+
+
+(** * Partition *)
+
+Fixpoint partition_acc (f:elt->bool)(acc : t*t)(s : t) : t*t :=
+ match s with
+ | Leaf => acc
+ | Node l x r _ =>
+ let (acct,accf) := acc in
+ partition_acc f
+ (partition_acc f
+ (if f x then (add x acct, accf) else (acct, add x accf)) l) r
+ end.
+
+Definition partition f := partition_acc f (Leaf,Leaf).
+
+(** * [for_all] and [exists] *)
+
+Fixpoint for_all (f:elt->bool) s := match s with
+ | Leaf => true
+ | Node l x r _ => f x &&& for_all f l &&& for_all f r
+end.
+
+Fixpoint exists_ (f:elt->bool) s := match s with
+ | Leaf => false
+ | Node l x r _ => f x ||| exists_ f l ||| exists_ f r
+end.
+
+(** * Fold *)
+
+Fixpoint fold (A : Type) (f : elt -> A -> A)(s : tree) : A -> A :=
+ fun a => match s with
+ | Leaf => a
+ | Node l x r _ => fold f r (f x (fold f l a))
+ end.
+Implicit Arguments fold [A].
+
+
+(** * Subset *)
+
+(** In ocaml, recursive calls are made on "half-trees" such as
+ (Node l1 x1 Leaf _) and (Node Leaf x1 r1 _). Instead of these
+ non-structural calls, we propose here two specialized functions for
+ these situations. This version should be almost as efficient as
+ the one of ocaml (closures as arguments may slow things a bit),
+ it is simply less compact. The exact ocaml version has also been
+ formalized (thanks to Function+measure), see [ocaml_subset] in
+ [FSetFullAVL].
+ *)
+
+Fixpoint subsetl (subset_l1:t->bool) x1 s2 : bool :=
+ match s2 with
+ | Leaf => false
+ | Node l2 x2 r2 h2 =>
+ match X.compare x1 x2 with
+ | EQ _ => subset_l1 l2
+ | LT _ => subsetl subset_l1 x1 l2
+ | GT _ => mem x1 r2 &&& subset_l1 s2
+ end
+ end.
+
+Fixpoint subsetr (subset_r1:t->bool) x1 s2 : bool :=
+ match s2 with
+ | Leaf => false
+ | Node l2 x2 r2 h2 =>
+ match X.compare x1 x2 with
+ | EQ _ => subset_r1 r2
+ | LT _ => mem x1 l2 &&& subset_r1 s2
+ | GT _ => subsetr subset_r1 x1 r2
+ end
+ end.
+
+Fixpoint subset s1 s2 : bool := match s1, s2 with
+ | Leaf, _ => true
+ | Node _ _ _ _, Leaf => false
+ | Node l1 x1 r1 h1, Node l2 x2 r2 h2 =>
+ match X.compare x1 x2 with
+ | EQ _ => subset l1 l2 &&& subset r1 r2
+ | LT _ => subsetl (subset l1) x1 l2 &&& subset r1 s2
+ | GT _ => subsetr (subset r1) x1 r2 &&& subset l1 s2
+ end
+ end.
+
+(** * A new comparison algorithm suggested by Xavier Leroy
+
+ Transformation in C.P.S. suggested by Benjamin Grégoire.
+ The original ocaml code (with non-structural recursive calls)
+ has also been formalized (thanks to Function+measure), see
+ [ocaml_compare] in [FSetFullAVL]. The following code with
+ continuations computes dramatically faster in Coq, and
+ should be almost as efficient after extraction.
+*)
+
+(** Enumeration of the elements of a tree *)
+
+Inductive enumeration :=
+ | End : enumeration
+ | More : elt -> tree -> enumeration -> enumeration.
+
+
+(** [cons t e] adds the elements of tree [t] on the head of
+ enumeration [e]. *)
+
+Fixpoint cons s e : enumeration :=
+ match s with
+ | Leaf => e
+ | Node l x r h => cons l (More x r e)
+ end.
+
+(** One step of comparison of elements *)
+
+Definition compare_more x1 (cont:enumeration->comparison) e2 :=
+ match e2 with
+ | End => Gt
+ | More x2 r2 e2 =>
+ match X.compare x1 x2 with
+ | EQ _ => cont (cons r2 e2)
+ | LT _ => Lt
+ | GT _ => Gt
+ end
+ end.
+
+(** Comparison of left tree, middle element, then right tree *)
+
+Fixpoint compare_cont s1 (cont:enumeration->comparison) e2 :=
+ match s1 with
+ | Leaf => cont e2
+ | Node l1 x1 r1 _ =>
+ compare_cont l1 (compare_more x1 (compare_cont r1 cont)) e2
+ end.
+
+(** Initial continuation *)
+
+Definition compare_end e2 :=
+ match e2 with End => Eq | _ => Lt end.
+
+(** The complete comparison *)
+
+Definition compare s1 s2 := compare_cont s1 compare_end (cons s2 End).
+
+(** * Equality test *)
+
+Definition equal s1 s2 : bool :=
+ match compare s1 s2 with
+ | Eq => true
+ | _ => false
+ end.
+
+
+
+
+(** * Invariants *)
+
+(** ** Occurrence in a tree *)
Inductive In (x : elt) : tree -> Prop :=
| IsRoot : forall l r h y, X.eq x y -> In x (Node l y r h)
| InLeft : forall l r h y, In x l -> In x (Node l y r h)
| InRight : forall l r h y, In x r -> In x (Node l y r h).
-(** * Binary search trees *)
+(** ** Binary search trees *)
(** [lt_tree x s]: all elements in [s] are smaller than [x]
(resp. greater for [gt_tree]) *)
@@ -122,11 +528,52 @@ Inductive bst : tree -> Prop :=
| BSNode : forall x l r h, bst l -> bst r ->
lt_tree x l -> gt_tree x r -> bst (Node l x r h).
+
+
+
+(** * Some shortcuts *)
+
+Definition Equal s s' := forall a : elt, In a s <-> In a s'.
+Definition Subset s s' := forall a : elt, In a s -> In a s'.
+Definition Empty s := forall a : elt, ~ In a s.
+Definition For_all (P : elt -> Prop) s := forall x, In x s -> P x.
+Definition Exists (P : elt -> Prop) s := exists x, In x s /\ P x.
+
+
+
+(** * Correctness proofs, isolated in a sub-module *)
+
+Module Proofs.
+ Module MX := OrderedTypeFacts X.
+ Module L := FSetList.Raw X.
+
+(** * Helper lemma about [orb], [andb], [pair] *)
+
+Lemma andb_alt : forall a b : bool, a &&& b = a && b.
+Proof.
+ destruct a; simpl; auto.
+Qed.
+
+Lemma orb_alt : forall a b : bool, a ||| b = a || b.
+Proof.
+ destruct a; simpl; auto.
+Qed.
+
+Lemma distr_pair : forall (A B:Type)(s:A*B)(a:A)(b:B), s = (a,b) ->
+ s#1 = a /\ s#2 = b.
+Proof.
+ destruct s; simpl; injection 1; auto.
+Qed.
+
(** * Automation and dedicated tactics *)
Hint Constructors In bst.
Hint Unfold lt_tree gt_tree.
+Tactic Notation "factornode" ident(l) ident(x) ident(r) ident(h)
+ "as" ident(s) :=
+ set (s:=Node l x r h) in *; clearbody s; clear l x r h.
+
(** A tactic to repeat [inversion_clear] on all hyps of the
form [(f (Node _ _ _ _))] *)
@@ -222,20 +669,25 @@ Qed.
Hint Resolve lt_tree_not_in lt_tree_trans gt_tree_not_in gt_tree_trans.
+(** * Inductions principles *)
-(** * Some shortcuts. *)
-
-Definition Equal s s' := forall a : elt, In a s <-> In a s'.
-Definition Subset s s' := forall a : elt, In a s -> In a s'.
-Definition Empty s := forall a : elt, ~ In a s.
-Definition For_all (P : elt -> Prop) s := forall x, In x s -> P x.
-Definition Exists (P : elt -> Prop) s := exists x, In x s /\ P x.
+Functional Scheme mem_ind := Induction for mem Sort Prop.
+Functional Scheme bal_ind := Induction for bal Sort Prop.
+Functional Scheme add_ind := Induction for add Sort Prop.
+Functional Scheme remove_min_ind := Induction for remove_min Sort Prop.
+Functional Scheme merge_ind := Induction for merge Sort Prop.
+Functional Scheme remove_ind := Induction for remove Sort Prop.
+Functional Scheme min_elt_ind := Induction for min_elt Sort Prop.
+Functional Scheme max_elt_ind := Induction for max_elt Sort Prop.
+Functional Scheme concat_ind := Induction for concat Sort Prop.
+Functional Scheme split_ind := Induction for split Sort Prop.
+Functional Scheme inter_ind := Induction for inter Sort Prop.
+Functional Scheme diff_ind := Induction for diff Sort Prop.
+Functional Scheme union_ind := Induction for union Sort Prop.
(** * Empty set *)
-Definition empty := Leaf.
-
Lemma empty_1 : Empty empty.
Proof.
intro; intro.
@@ -247,11 +699,8 @@ Proof.
auto.
Qed.
-
(** * Emptyness test *)
-Definition is_empty (s:t) := match s with Leaf => true | _ => false end.
-
Lemma is_empty_1 : forall s, Empty s -> is_empty s = true.
Proof.
destruct s as [|r x l h]; simpl; auto.
@@ -267,19 +716,6 @@ Qed.
(** * Appartness *)
-(** The [mem] function is deciding appartness. It exploits the [bst] property
- to achieve logarithmic complexity. *)
-
-Function mem (x:elt)(s:t) { struct s } : bool :=
- match s with
- | Leaf => false
- | Node l y r _ => match X.compare x y with
- | LT _ => mem x l
- | EQ _ => true
- | GT _ => mem x r
- end
- end.
-
Lemma mem_1 : forall s x, bst s -> In x s -> mem x s = true.
Proof.
intros s x; functional induction mem x s; auto; intros; try clear e0;
@@ -295,8 +731,6 @@ Qed.
(** * Singleton set *)
-Definition singleton (x : elt) := Node Leaf x Leaf 1.
-
Lemma singleton_1 : forall x y, In y (singleton x) -> X.eq x y.
Proof.
unfold singleton; intros; inv In; order.
@@ -316,12 +750,6 @@ Qed.
(** * Helper functions *)
-(** [create l x r] creates a node, assuming [l] and [r]
- to be balanced and [|height l - height r| <= 2]. *)
-
-Definition create l x r :=
- Node l x r (max (height l) (height r) + 1).
-
Lemma create_in :
forall l x r y, In y (create l x r) <-> X.eq y x \/ In y l \/ In y r.
Proof.
@@ -336,45 +764,6 @@ Proof.
Qed.
Hint Resolve create_bst.
-
-(** [bal l x r] acts as [create], but performs one step of
- rebalancing if necessary, i.e. assumes [|height l - height r| <= 3]. *)
-
-Definition assert_false := create.
-
-Function bal (l:t)(x:elt)(r:t) : t :=
- let hl := height l in
- let hr := height r in
- if gt_le_dec hl (hr+2) then
- match l with
- | Leaf => assert_false l x r
- | Node ll lx lr _ =>
- if ge_lt_dec (height ll) (height lr) then
- create ll lx (create lr x r)
- else
- match lr with
- | Leaf => assert_false l x r
- | Node lrl lrx lrr _ =>
- create (create ll lx lrl) lrx (create lrr x r)
- end
- end
- else
- if gt_le_dec hr (hl+2) then
- match r with
- | Leaf => assert_false l x r
- | Node rl rx rr _ =>
- if ge_lt_dec (height rr) (height rl) then
- create (create l x rl) rx rr
- else
- match rl with
- | Leaf => assert_false l x r
- | Node rll rlx rlr _ =>
- create (create l x rll) rlx (create rlr rx rr)
- end
- end
- else
- create l x r.
-
Lemma bal_in : forall l x r y,
In y (bal l x r) <-> X.eq y x \/ In y l \/ In y r.
Proof.
@@ -393,17 +782,8 @@ Qed.
Hint Resolve bal_bst.
-(** * Insertion *)
-Function add (x:elt)(s:t) { struct s } : t := match s with
- | Leaf => Node Leaf x Leaf 1
- | Node l y r h =>
- match X.compare x y with
- | LT _ => bal (add x l) y r
- | EQ _ => Node l y r h
- | GT _ => bal l y (add x r)
- end
- end.
+(** * Insertion *)
Lemma add_in : forall s x y,
In y (add x s) <-> X.eq y x \/ In y s.
@@ -435,26 +815,10 @@ Hint Resolve add_bst.
-(** * Join
+(** * Join *)
- Same as [bal] but does not assume anything regarding heights
- of [l] and [r].
-*)
-
-Fixpoint join (l:t) : elt -> t -> t :=
- match l with
- | Leaf => add
- | Node ll lx lr lh => fun x =>
- fix join_aux (r:t) : t := match r with
- | Leaf => add x l
- | Node rl rx rr rh =>
- if gt_le_dec lh (rh+2) then bal ll lx (join lr x r)
- else if gt_le_dec rh (lh+2) then bal (join_aux rl) rx rr
- else create l x r
- end
- end.
-
-(* Function can't deal with internal fix. Let's do its job by hand: *)
+(* Function/Functional Scheme can't deal with internal fix.
+ Let's do its job by hand: *)
Ltac join_tac :=
intro l; induction l as [| ll _ lx lr Hlr lh];
@@ -495,19 +859,7 @@ Hint Resolve join_bst.
-(** * Extraction of minimum element
-
- Morally, [remove_min] is to be applied to a non-empty tree
- [t = Node l x r h]. Since we can't deal here with [assert false]
- for [t=Leaf], we pre-unpack [t] (and forget about [h]).
-*)
-
-Function remove_min (l:t)(x:elt)(r:t) { struct l } : t*elt :=
- match l with
- | Leaf => (r,x)
- | Node ll lx lr lh =>
- let (l',m) := remove_min ll lx lr in (bal l' x r, m)
- end.
+(** * Extraction of minimum element *)
Lemma remove_min_in : forall l x r h y,
In y (Node l x r h) <->
@@ -521,7 +873,7 @@ Qed.
Lemma remove_min_bst : forall l x r h,
bst (Node l x r h) -> bst (remove_min l x r)#1.
Proof.
- intros l x r; functional induction (remove_min l x r); subst;simpl in *; intros.
+ intros l x r; functional induction (remove_min l x r); simpl; intros.
inv bst; auto.
inversion_clear H.
specialize IHp with (1:=H0); rewrite e0 in IHp; auto.
@@ -534,7 +886,7 @@ Lemma remove_min_gt_tree : forall l x r h,
bst (Node l x r h) ->
gt_tree (remove_min l x r)#2 (remove_min l x r)#1.
Proof.
- intros l x r; functional induction (remove_min l x r); subst;simpl in *; intros.
+ intros l x r; functional induction (remove_min l x r); simpl; intros.
inv bst; auto.
inversion_clear H.
specialize IHp with (1:=H0); rewrite e0 in IHp; simpl in IHp.
@@ -546,24 +898,13 @@ Hint Resolve remove_min_bst remove_min_gt_tree.
-(** * Merging two trees
-
- [merge t1 t2] builds the union of [t1] and [t2] assuming all elements
- of [t1] to be smaller than all elements of [t2], and
- [|height t1 - height t2| <= 2].
-*)
-
-Function merge (s1 s2 :t) : t:= match s1,s2 with
- | Leaf, _ => s2
- | _, Leaf => s1
- | _, Node l2 x2 r2 h2 =>
- let (s2',m) := remove_min l2 x2 r2 in bal s1 m s2'
-end.
+(** * Merging two trees *)
Lemma merge_in : forall s1 s2 y,
In y (merge s1 s2) <-> In y s1 \/ In y s2.
Proof.
- intros s1 s2; functional induction (merge s1 s2); subst; simpl in *; intros.
+ intros s1 s2; functional induction (merge s1 s2); intros;
+ try factornode _x _x0 _x1 _x2 as s1.
intuition_in.
intuition_in.
rewrite bal_in, remove_min_in, e1; simpl; intuition.
@@ -573,7 +914,8 @@ Lemma merge_bst : forall s1 s2, bst s1 -> bst s2 ->
(forall y1 y2 : elt, In y1 s1 -> In y2 s2 -> X.lt y1 y2) ->
bst (merge s1 s2).
Proof.
- intros s1 s2; functional induction (merge s1 s2); subst; simpl in *; intros; auto; clear y.
+ intros s1 s2; functional induction (merge s1 s2); intros; auto;
+ try factornode _x _x0 _x1 _x2 as s1.
apply bal_bst; auto.
change s2' with ((s2',m)#1); rewrite <-e1; eauto.
intros y Hy.
@@ -587,21 +929,10 @@ Hint Resolve merge_bst.
(** * Deletion *)
-Function remove (x:elt)(s:t) { struct s } : t := match s with
- | Leaf => Leaf
- | Node l y r h =>
- match X.compare x y with
- | LT _ => bal (remove x l) y r
- | EQ _ => merge l r
- | GT _ => bal l y (remove x r)
- end
- end.
-
Lemma remove_in : forall s x y, bst s ->
(In y (remove x s) <-> ~ X.eq y x /\ In y s).
Proof.
- intros s x; functional induction (remove x s); subst; simpl;
- intros; inv bst.
+ intros s x; functional induction (remove x s); intros; inv bst.
intuition_in.
rewrite bal_in, IHt; clear e0 IHt; intuition; [order|order|intuition_in].
rewrite merge_in; clear e0; intuition; [order|order|intuition_in].
@@ -611,8 +942,7 @@ Qed.
Lemma remove_bst : forall s x, bst s -> bst (remove x s).
Proof.
- intros s x; functional induction (remove x s); simpl;
- intros; inv bst.
+ intros s x; functional induction (remove x s); intros; inv bst.
auto.
(* LT *)
apply bal_bst; auto.
@@ -626,104 +956,80 @@ Qed.
Hint Resolve remove_bst.
-
(** * Minimum element *)
-Function min_elt (s:t) : option elt := match s with
- | Leaf => None
- | Node Leaf y _ _ => Some y
- | Node l _ _ _ => min_elt l
-end.
-
Lemma min_elt_1 : forall s x, min_elt s = Some x -> In x s.
Proof.
- intro s; functional induction (min_elt s); subst; simpl.
- inversion 1.
- inversion 1; auto.
- intros.
- destruct l; auto.
+ intro s; functional induction (min_elt s); auto; inversion 1; auto.
Qed.
Lemma min_elt_2 : forall s x y, bst s ->
min_elt s = Some x -> In y s -> ~ X.lt y x.
Proof.
- intro s; functional induction (min_elt s); subst;simpl.
+ intro s; functional induction (min_elt s);
+ try rename _x1 into l1, _x2 into x1, _x3 into r1, _x4 into h1.
inversion_clear 2.
inversion_clear 1.
inversion 1; subst.
inversion_clear 1; auto.
inversion_clear H5.
- destruct l;try contradiction.
inversion_clear 1.
simpl.
destruct l1.
inversion 1; subst.
- assert (X.lt x _x) by (apply H2; auto).
+ assert (X.lt x y) by (apply H2; auto).
inversion_clear 1; auto; order.
- assert (X.lt t _x) by auto.
+ assert (X.lt x1 y) by auto.
inversion_clear 2; auto;
- (assert (~ X.lt t x) by auto); order.
+ (assert (~ X.lt x1 x) by auto); order.
Qed.
Lemma min_elt_3 : forall s, min_elt s = None -> Empty s.
Proof.
- intro s; functional induction (min_elt s); subst;simpl.
- red; auto.
+ intro s; functional induction (min_elt s).
+ red; red; inversion 2.
inversion 1.
- destruct l;try contradiction.
- clear y;intro H0.
- destruct (IHo H0 t); auto.
+ intro H0.
+ destruct (IHo H0 _x2); auto.
Qed.
(** * Maximum element *)
-Function max_elt (s:t) : option elt := match s with
- | Leaf => None
- | Node _ y Leaf _ => Some y
- | Node _ _ r _ => max_elt r
-end.
-
Lemma max_elt_1 : forall s x, max_elt s = Some x -> In x s.
Proof.
- intro s; functional induction (max_elt s); subst;simpl.
- inversion 1.
- inversion 1; auto.
- destruct r;try contradiction; auto.
+ intro s; functional induction (max_elt s); auto; inversion 1; auto.
Qed.
Lemma max_elt_2 : forall s x y, bst s ->
max_elt s = Some x -> In y s -> ~ X.lt x y.
Proof.
- intro s; functional induction (max_elt s); subst;simpl.
+ intro s; functional induction (max_elt s);
+ try rename _x1 into l1, _x2 into x1, _x3 into r1, _x4 into h1.
inversion_clear 2.
inversion_clear 1.
inversion 1; subst.
inversion_clear 1; auto.
inversion_clear H5.
- destruct r;try contradiction.
inversion_clear 1.
- assert (X.lt _x0 t) by auto.
+ assert (X.lt y x1) by auto.
inversion_clear 2; auto;
- (assert (~ X.lt x t) by auto); order.
+ (assert (~ X.lt x x1) by auto); order.
Qed.
Lemma max_elt_3 : forall s, max_elt s = None -> Empty s.
Proof.
- intro s; functional induction (max_elt s); subst;simpl.
+ intro s; functional induction (max_elt s).
red; auto.
inversion 1.
- destruct r;try contradiction.
- intros H0; destruct (IHo H0 t); auto.
+ intros H0; destruct (IHo H0 _x2); auto.
Qed.
(** * Any element *)
-Definition choose := min_elt.
-
Lemma choose_1 : forall s x, choose s = Some x -> In x s.
Proof.
exact min_elt_1.
@@ -749,25 +1055,13 @@ Proof.
Qed.
-
-(** * Concatenation
-
- Same as [merge] but does not assume anything about heights.
-*)
-
-Function concat (s1 s2 : t) : t :=
- match s1, s2 with
- | Leaf, _ => s2
- | _, Leaf => s1
- | _, Node l2 x2 r2 h2 =>
- let (s2',m) := remove_min l2 x2 r2 in
- join s1 m s2'
- end.
+(** * Concatenation *)
Lemma concat_in : forall s1 s2 y,
In y (concat s1 s2) <-> In y s1 \/ In y s2.
Proof.
- intros s1 s2; functional induction (concat s1 s2);subst;simpl;intros.
+ intros s1 s2; functional induction (concat s1 s2); intros;
+ try factornode _x _x0 _x1 _x2 as s1.
intuition_in.
intuition_in.
rewrite join_in, remove_min_in, e1; simpl; intuition.
@@ -777,8 +1071,9 @@ Lemma concat_bst : forall s1 s2, bst s1 -> bst s2 ->
(forall y1 y2 : elt, In y1 s1 -> In y2 s2 -> X.lt y1 y2) ->
bst (concat s1 s2).
Proof.
- intros s1 s2; functional induction (concat s1 s2); subst; auto; clear y.
- intros; apply join_bst; auto.
+ intros s1 s2; functional induction (concat s1 s2); intros; auto;
+ try factornode _x _x0 _x1 _x2 as s1.
+ apply join_bst; auto.
change (bst (s2',m)#1); rewrite <-e1; eauto.
intros y Hy.
apply H1; auto.
@@ -788,33 +1083,12 @@ Qed.
Hint Resolve concat_bst.
-
-(** * Splitting
-
- [split x s] returns a triple [(l, present, r)] where
- - [l] is the set of elements of [s] that are [< x]
- - [r] is the set of elements of [s] that are [> x]
- - [present] is [true] if and only if [s] contains [x].
-*)
-
-Function split (x:elt)(s:t) { struct s } : t * (bool * t) := match s with
- | Leaf => (Leaf, (false, Leaf))
- | Node l y r h =>
- match X.compare x y with
- | LT _ => match split x l with
- | (ll,(pres,rl)) => (ll, (pres, join rl y r))
- end
- | EQ _ => (l, (true, r))
- | GT _ => match split x r with
- | (rl,(pres,rr)) => (join l y rl, (pres, rr))
- end
- end
- end.
+(** * Splitting *)
Lemma split_in_1 : forall s x y, bst s ->
(In y (split x s)#1 <-> In y s /\ X.lt y x).
Proof.
- intros s x; functional induction (split x s); subst; simpl; intros;
+ intros s x; functional induction (split x s); simpl; intros;
inv bst; try clear e0.
intuition_in.
rewrite e1 in IHp; simpl in IHp; rewrite IHp; intuition_in; order.
@@ -862,22 +1136,12 @@ Qed.
(** * Intersection *)
-Function inter (s1 s2 : t) { struct s1 } : t := match s1, s2 with
- | Leaf, _ => Leaf
- | _, Leaf => Leaf
- | Node l1 x1 r1 h1, Node l2 x2 r2 h2 =>
- match split x1 s2 with
- | (l2',(true,r2')) => join (inter l1 l2') x1 (inter r1 r2')
- | (l2',(false,r2')) => concat (inter l1 l2') (inter r1 r2')
- end
- end.
-
Lemma inter_bst_in : forall s1 s2, bst s1 -> bst s2 ->
bst (inter s1 s2) /\ (forall y, In y (inter s1 s2) <-> In y s1 /\ In y s2).
Proof.
intros s1 s2; functional induction inter s1 s2; intros B1 B2;
[intuition_in|intuition_in | | ];
- set (r:=Node l2 x2 r2 h2) in *;
+ factornode _x0 _x1 _x2 _x3 as s2;
generalize (split_bst x1 B2);
rewrite e1; simpl; destruct 1; inv bst;
destruct IHt as (IHb1,IHi1); auto;
@@ -896,7 +1160,7 @@ Proof.
(* In concat *)
intros.
rewrite concat_in, IHi1, IHi2, <- H5, <- H8, split_in_1, split_in_2; auto.
- assert (~In x1 r) by (rewrite <- split_in_3, H7; auto).
+ assert (~In x1 s2) by (rewrite <- split_in_3, H7; auto).
intuition_in.
elim H6.
apply In_1 with y; auto.
@@ -914,25 +1178,14 @@ Proof.
Qed.
-
(** * Difference *)
-Function diff (s1 s2 : t) { struct s1 } : t := match s1, s2 with
- | Leaf, _ => Leaf
- | _, Leaf => s1
- | Node l1 x1 r1 h1, Node l2 x2 r2 h2 =>
- match split x1 s2 with
- | (l2',(true,r2')) => concat (diff l1 l2') (diff r1 r2')
- | (l2',(false,r2')) => join (diff l1 l2') x1 (diff r1 r2')
- end
-end.
-
Lemma diff_bst_in : forall s1 s2, bst s1 -> bst s2 ->
bst (diff s1 s2) /\ (forall y, In y (diff s1 s2) <-> In y s1 /\ ~In y s2).
Proof.
intros s1 s2; functional induction diff s1 s2; intros B1 B2;
[intuition_in|intuition_in | | ];
- set (r:=Node l2 x2 r2 h2) in *;
+ factornode _x0 _x1 _x2 _x3 as s2;
generalize (split_bst x1 B2);
rewrite e1; simpl; destruct 1;
inv avl; inv bst;
@@ -953,7 +1206,7 @@ Proof.
(* In join *)
intros.
rewrite join_in, IHi1, IHi2, <-H5, <-H8, split_in_1, split_in_2; auto.
- assert (~In x1 r) by (rewrite <- split_in_3, H7; auto).
+ assert (~In x1 s2) by (rewrite <- split_in_3, H7; auto).
intuition_in.
elim H6.
apply In_1 with y; auto.
@@ -971,29 +1224,8 @@ Proof.
Qed.
-
(** * Union *)
-(** In ocaml, heights of [s1] and [s2] are compared each time in order
- to recursively perform the split on the smaller set.
- Unfortunately, this leads to a non-structural algorithm. The
- following code is a simplification of the ocaml version: no
- comparison of heights. It might be slightly slower, but
- experimentally all the tests I've made in ocaml have shown this
- potential slowdown to be non-significant. Anyway, the exact code
- of ocaml has also been formalized thanks to Function+measure, see
- [ocaml_union] in [FSetFullAVL].
-*)
-
-Function union (s1 s2 : t) { struct s1 } : t :=
- match s1, s2 with
- | Leaf, _ => s2
- | Node _ _ _ _, Leaf => s1
- | Node l1 x1 r1 h1, Node l2 x2 r2 h2 =>
- let (l2',r2') := split x1 s2 in
- join (union l1 l2') x1 (union r1 r2'#2)
- end.
-
Lemma union_in : forall s1 s2 y, bst s1 -> bst s2 ->
(In y (union s1 s2) <-> In y s1 \/ In y s2).
Proof.
@@ -1024,22 +1256,8 @@ Proof.
Qed.
-
(** * Elements *)
-(** [elements_tree_aux acc t] catenates the elements of [t] in infix
- order to the list [acc] *)
-
-Fixpoint elements_aux (acc : list X.t) (t : tree) {struct t} : list X.t :=
- match t with
- | Leaf => acc
- | Node l x r _ => elements_aux (x :: elements_aux acc r) l
- end.
-
-(** then [elements] is an instanciation with an empty [acc] *)
-
-Definition elements := elements_aux nil.
-
Lemma elements_aux_in : forall s acc x,
InA X.eq x (elements_aux acc s) <-> In x s \/ InA X.eq x acc.
Proof.
@@ -1108,17 +1326,9 @@ Qed.
Section F.
Variable f : elt -> bool.
-Fixpoint filter_acc (acc:t)(s:t) { struct s } : t := match s with
- | Leaf => acc
- | Node l x r h =>
- filter_acc (filter_acc (if f x then add x acc else acc) l) r
- end.
-
-Definition filter := filter_acc Leaf.
-
Lemma filter_acc_in : forall s acc,
compat_bool X.eq f -> forall x : elt,
- In x (filter_acc acc s) <-> In x acc \/ In x s /\ f x = true.
+ In x (filter_acc f acc s) <-> In x acc \/ In x s /\ f x = true.
Proof.
induction s; simpl; intros.
intuition_in.
@@ -1134,7 +1344,7 @@ Proof.
Qed.
Lemma filter_acc_bst : forall s acc, bst s -> bst acc ->
- bst (filter_acc acc s).
+ bst (filter_acc f acc s).
Proof.
induction s; simpl; auto.
intros.
@@ -1144,12 +1354,12 @@ Qed.
Lemma filter_in : forall s,
compat_bool X.eq f -> forall x : elt,
- In x (filter s) <-> In x s /\ f x = true.
+ In x (filter f s) <-> In x s /\ f x = true.
Proof.
unfold filter; intros; rewrite filter_acc_in; intuition_in.
Qed.
-Lemma filter_bst : forall s, bst s -> bst (filter s).
+Lemma filter_bst : forall s, bst s -> bst (filter f s).
Proof.
unfold filter; intros; apply filter_acc_bst; auto.
Qed.
@@ -1158,21 +1368,9 @@ Qed.
(** * Partition *)
-Fixpoint partition_acc (acc : t*t)(s : t) { struct s } : t*t :=
- match s with
- | Leaf => acc
- | Node l x r _ =>
- let (acct,accf) := acc in
- partition_acc
- (partition_acc
- (if f x then (add x acct, accf) else (acct, add x accf)) l) r
- end.
-
-Definition partition := partition_acc (Leaf,Leaf).
-
Lemma partition_acc_in_1 : forall s acc,
compat_bool X.eq f -> forall x : elt,
- In x (partition_acc acc s)#1 <->
+ In x (partition_acc f acc s)#1 <->
In x acc#1 \/ In x s /\ f x = true.
Proof.
induction s; simpl; intros.
@@ -1193,7 +1391,7 @@ Qed.
Lemma partition_acc_in_2 : forall s acc,
compat_bool X.eq f -> forall x : elt,
- In x (partition_acc acc s)#2 <->
+ In x (partition_acc f acc s)#2 <->
In x acc#2 \/ In x s /\ f x = false.
Proof.
induction s; simpl; intros.
@@ -1215,7 +1413,7 @@ Qed.
Lemma partition_in_1 : forall s,
compat_bool X.eq f -> forall x : elt,
- In x (partition s)#1 <-> In x s /\ f x = true.
+ In x (partition f s)#1 <-> In x s /\ f x = true.
Proof.
unfold partition; intros; rewrite partition_acc_in_1;
simpl in *; intuition_in.
@@ -1223,14 +1421,14 @@ Qed.
Lemma partition_in_2 : forall s,
compat_bool X.eq f -> forall x : elt,
- In x (partition s)#2 <-> In x s /\ f x = false.
+ In x (partition f s)#2 <-> In x s /\ f x = false.
Proof.
unfold partition; intros; rewrite partition_acc_in_2;
simpl in *; intuition_in.
Qed.
Lemma partition_acc_bst_1 : forall s acc, bst s -> bst acc#1 ->
- bst (partition_acc acc s)#1.
+ bst (partition_acc f acc s)#1.
Proof.
induction s; simpl; auto.
destruct acc as [acct accf]; simpl in *.
@@ -1242,7 +1440,7 @@ Proof.
Qed.
Lemma partition_acc_bst_2 : forall s acc, bst s -> bst acc#2 ->
- bst (partition_acc acc s)#2.
+ bst (partition_acc f acc s)#2.
Proof.
induction s; simpl; auto.
destruct acc as [acct accf]; simpl in *.
@@ -1253,12 +1451,12 @@ Proof.
apply IHs1; simpl; auto.
Qed.
-Lemma partition_bst_1 : forall s, bst s -> bst (partition s)#1.
+Lemma partition_bst_1 : forall s, bst s -> bst (partition f s)#1.
Proof.
unfold partition; intros; apply partition_acc_bst_1; auto.
Qed.
-Lemma partition_bst_2 : forall s, bst s -> bst (partition s)#2.
+Lemma partition_bst_2 : forall s, bst s -> bst (partition f s)#2.
Proof.
unfold partition; intros; apply partition_acc_bst_2; auto.
Qed.
@@ -1267,13 +1465,8 @@ Qed.
(** * [for_all] and [exists] *)
-Fixpoint for_all (s:t) : bool := match s with
- | Leaf => true
- | Node l x r _ => f x &&& for_all l &&& for_all r
-end.
-
Lemma for_all_1 : forall s, compat_bool X.eq f ->
- For_all (fun x => f x = true) s -> for_all s = true.
+ For_all (fun x => f x = true) s -> for_all f s = true.
Proof.
induction s; simpl; auto.
intros.
@@ -1284,7 +1477,7 @@ Proof.
Qed.
Lemma for_all_2 : forall s, compat_bool X.eq f ->
- for_all s = true -> For_all (fun x => f x = true) s.
+ for_all f s = true -> For_all (fun x => f x = true) s.
Proof.
induction s; simpl; auto; intros; red; intros; inv In.
destruct (andb_prop _ _ H0); auto.
@@ -1296,13 +1489,8 @@ Proof.
destruct (andb_prop _ _ H0); auto.
Qed.
-Fixpoint exists_ (s:t) : bool := match s with
- | Leaf => false
- | Node l x r _ => f x ||| exists_ l ||| exists_ r
-end.
-
Lemma exists_1 : forall s, compat_bool X.eq f ->
- Exists (fun x => f x = true) s -> exists_ s = true.
+ Exists (fun x => f x = true) s -> exists_ f s = true.
Proof.
induction s; simpl; destruct 2 as (x,(U,V)); inv In; rewrite ? orb_alt.
rewrite (H _ _ (X.eq_sym H0)); rewrite V; auto.
@@ -1312,7 +1500,7 @@ Proof.
Qed.
Lemma exists_2 : forall s, compat_bool X.eq f ->
- exists_ s = true -> Exists (fun x => f x = true) s.
+ exists_ f s = true -> Exists (fun x => f x = true) s.
Proof.
induction s; simpl; intros; rewrite ? orb_alt in *.
discriminate.
@@ -1329,15 +1517,6 @@ End F.
(** * Fold *)
-Module L := FSetList.Raw X.
-
-Fixpoint fold (A : Type) (f : elt -> A -> A)(s : tree) {struct s} : A -> A :=
- fun a => match s with
- | Leaf => a
- | Node l x r _ => fold f r (f x (fold f l a))
- end.
-Implicit Arguments fold [A].
-
Definition fold' (A : Type) (f : elt -> A -> A)(s : tree) :=
L.fold f (elements s).
Implicit Arguments fold' [A].
@@ -1377,53 +1556,8 @@ Proof.
apply elements_sort; auto.
Qed.
-
-
(** * Subset *)
-(** In ocaml, recursive calls are made on "half-trees" such as
- (Node l1 x1 Leaf _) and (Node Leaf x1 r1 _). Instead of these
- non-structural calls, we propose here two specialized functions for
- these situations. This version should be almost as efficient as
- the one of ocaml (closures as arguments may slow things a bit),
- it is simply less compact. The exact ocaml version has also been
- formalized (thanks to Function+measure), see [ocaml_subset] in
- [FSetFullAVL].
- *)
-
-Fixpoint subsetl (subset_l1:t->bool) x1 s2 : bool :=
- match s2 with
- | Leaf => false
- | Node l2 x2 r2 h2 =>
- match X.compare x1 x2 with
- | EQ _ => subset_l1 l2
- | LT _ => subsetl subset_l1 x1 l2
- | GT _ => mem x1 r2 &&& subset_l1 s2
- end
- end.
-
-Fixpoint subsetr (subset_r1:t->bool) x1 s2 : bool :=
- match s2 with
- | Leaf => false
- | Node l2 x2 r2 h2 =>
- match X.compare x1 x2 with
- | EQ _ => subset_r1 r2
- | LT _ => mem x1 l2 &&& subset_r1 s2
- | GT _ => subsetr subset_r1 x1 r2
- end
- end.
-
-Fixpoint subset s1 s2 : bool := match s1, s2 with
- | Leaf, _ => true
- | Node _ _ _ _, Leaf => false
- | Node l1 x1 r1 h1, Node l2 x2 r2 h2 =>
- match X.compare x1 x2 with
- | EQ _ => subset l1 l2 &&& subset r1 r2
- | LT _ => subsetl (subset l1) x1 l2 &&& subset r1 s2
- | GT _ => subsetr (subset r1) x1 r2 &&& subset l1 s2
- end
- end.
-
Lemma subsetl_12 : forall subset_l1 l1 x1 h1 s2,
bst (Node l1 x1 Leaf h1) -> bst s2 ->
(forall s, bst s -> (subset_l1 s = true <-> Subset l1 s)) ->
@@ -1527,6 +1661,9 @@ Qed.
(** ** Relations [eq] and [lt] over trees *)
+Definition eq := Equal.
+Definition lt (s1 s2 : t) : Prop := L.lt (elements s1) (elements s2).
+
Lemma eq_refl : forall s : t, Equal s s.
Proof.
unfold Equal; intuition.
@@ -1557,8 +1694,6 @@ Proof.
Qed.
Hint Resolve eq_L_eq L_eq_eq.
-Definition lt (s1 s2 : t) : Prop := L.lt (elements s1) (elements s2).
-
Definition lt_trans (s s' s'' : t) (h : lt s s')
(h' : lt s' s'') : lt s s'' := L.lt_trans h h'.
@@ -1582,21 +1717,7 @@ Qed.
Hint Resolve L_eq_cons.
-(** * A new comparison algorithm suggested by Xavier Leroy
-
- Transformation in C.P.S. suggested by Benjamin Grégoire.
- The original ocaml code (with non-structural recursive calls)
- has also been formalized (thanks to Function+measure), see
- [ocaml_compare] in [FSetFullAVL]. The following code with
- continuations computes dramatically faster in Coq, and
- should be almost as efficient after extraction.
-*)
-
-(** ** Enumeration of the elements of a tree *)
-
-Inductive enumeration :=
- | End : enumeration
- | More : elt -> tree -> enumeration -> enumeration.
+(** * A new comparison algorithm suggested by Xavier Leroy *)
(** [flatten_e e] returns the list of elements of [e] i.e. the list
of elements actually compared *)
@@ -1606,22 +1727,6 @@ Fixpoint flatten_e (e : enumeration) : list elt := match e with
| More x t r => x :: elements t ++ flatten_e r
end.
-(** [sorted_e e] expresses that elements in the enumeration [e] are
- sorted, and that all trees in [e] are binary search trees. *)
-
-Inductive In_e (x:elt) : enumeration -> Prop :=
- | InEHd1 :
- forall (y : elt) (s : tree) (e : enumeration),
- X.eq x y -> In_e x (More y s e)
- | InEHd2 :
- forall (y : elt) (s : tree) (e : enumeration),
- In x s -> In_e x (More y s e)
- | InETl :
- forall (y : elt) (s : tree) (e : enumeration),
- In_e x e -> In_e x (More y s e).
-
-Hint Constructors In_e.
-
Lemma elements_app :
forall s acc, elements_aux acc s = elements s ++ acc.
Proof.
@@ -1640,8 +1745,6 @@ Proof.
rewrite !elements_app, <- !app_nil_end, !app_ass; auto.
Qed.
-(** key lemma for correctness *)
-
Lemma flatten_e_elements :
forall l x r h e,
elements l ++ flatten_e (More x r e) = elements (Node l x r h) ++ flatten_e e.
@@ -1649,15 +1752,6 @@ Proof.
intros; simpl; apply compare_flatten_1.
Qed.
-(** [cons t e] adds the elements of tree [t] on the head of
- enumeration [e]. *)
-
-Fixpoint cons s e : enumeration :=
- match s with
- | Leaf => e
- | Node l x r h => cons l (More x r e)
- end.
-
Lemma cons_1 : forall s e,
flatten_e (cons s e) = elements s ++ flatten_e e.
Proof.
@@ -1665,37 +1759,6 @@ Proof.
rewrite IHs1; apply flatten_e_elements.
Qed.
-(** One step of comparison of elements *)
-
-Definition compare_more x1 (cont:enumeration->comparison) e2 :=
- match e2 with
- | End => Gt
- | More x2 r2 e2 =>
- match X.compare x1 x2 with
- | EQ _ => cont (cons r2 e2)
- | LT _ => Lt
- | GT _ => Gt
- end
- end.
-
-(** Comparison of left tree, middle element, then right tree *)
-
-Fixpoint compare_cont s1 (cont:enumeration->comparison) e2 :=
- match s1 with
- | Leaf => cont e2
- | Node l1 x1 r1 _ =>
- compare_cont l1 (compare_more x1 (compare_cont r1 cont)) e2
- end.
-
-(** Initial continuation *)
-
-Definition compare_end e2 :=
- match e2 with End => Eq | _ => Lt end.
-
-(** The complete comparison *)
-
-Definition compare s1 s2 := compare_cont s1 compare_end (cons s2 End).
-
(** Correctness of this comparison *)
Definition Cmp c :=
@@ -1754,12 +1817,6 @@ Qed.
(** * Equality test *)
-Definition equal s1 s2 : bool :=
- match compare s1 s2 with
- | Eq => true
- | _ => false
- end.
-
Lemma equal_1 : forall s1 s2, bst s1 -> bst s2 ->
Equal s1 s2 -> equal s1 s2 = true.
Proof.
@@ -1778,6 +1835,8 @@ generalize (compare_Cmp s1 s2);
destruct compare; auto; discriminate.
Qed.
+End Proofs.
+
End Raw.
@@ -1795,6 +1854,7 @@ Module IntMake (I:Int)(X: OrderedType) <: S with Module E := X.
Module E := X.
Module Raw := Raw I X.
+ Import Raw.Proofs.
Record bst := Bst {this :> Raw.t; is_bst : Raw.bst this}.
Definition t := bst.
@@ -1808,18 +1868,18 @@ Module IntMake (I:Int)(X: OrderedType) <: S with Module E := X.
Definition Exists (P : elt -> Prop) (s:t) := exists x, In x s /\ P x.
Lemma In_1 : forall (s:t)(x y:elt), E.eq x y -> In x s -> In y s.
- Proof. intro s; exact (@Raw.In_1 s). Qed.
+ Proof. intro s; exact (@In_1 s). Qed.
Definition mem (x:elt)(s:t) : bool := Raw.mem x s.
- Definition empty : t := Bst Raw.empty_bst.
+ Definition empty : t := Bst empty_bst.
Definition is_empty (s:t) : bool := Raw.is_empty s.
- Definition singleton (x:elt) : t := Bst (Raw.singleton_bst x).
- Definition add (x:elt)(s:t) : t := Bst (Raw.add_bst x (is_bst s)).
- Definition remove (x:elt)(s:t) : t := Bst (Raw.remove_bst x (is_bst s)).
- Definition inter (s s':t) : t := Bst (Raw.inter_bst (is_bst s) (is_bst s')).
- Definition union (s s':t) : t := Bst (Raw.union_bst (is_bst s) (is_bst s')).
- Definition diff (s s':t) : t := Bst (Raw.diff_bst (is_bst s) (is_bst s')).
+ Definition singleton (x:elt) : t := Bst (singleton_bst x).
+ Definition add (x:elt)(s:t) : t := Bst (add_bst x (is_bst s)).
+ Definition remove (x:elt)(s:t) : t := Bst (remove_bst x (is_bst s)).
+ Definition inter (s s':t) : t := Bst (inter_bst (is_bst s) (is_bst s')).
+ Definition union (s s':t) : t := Bst (union_bst (is_bst s) (is_bst s')).
+ Definition diff (s s':t) : t := Bst (diff_bst (is_bst s) (is_bst s')).
Definition elements (s:t) : list elt := Raw.elements s.
Definition min_elt (s:t) : option elt := Raw.min_elt s.
Definition max_elt (s:t) : option elt := Raw.max_elt s.
@@ -1827,24 +1887,24 @@ Module IntMake (I:Int)(X: OrderedType) <: S with Module E := X.
Definition fold (B : Type) (f : elt -> B -> B) (s:t) : B -> B := Raw.fold f s.
Definition cardinal (s:t) : nat := Raw.cardinal s.
Definition filter (f : elt -> bool) (s:t) : t :=
- Bst (Raw.filter_bst f (is_bst s)).
+ Bst (filter_bst f (is_bst s)).
Definition for_all (f : elt -> bool) (s:t) : bool := Raw.for_all f s.
Definition exists_ (f : elt -> bool) (s:t) : bool := Raw.exists_ f s.
Definition partition (f : elt -> bool) (s:t) : t * t :=
let p := Raw.partition f s in
- (@Bst (fst p) (Raw.partition_bst_1 f (is_bst s)),
- @Bst (snd p) (Raw.partition_bst_2 f (is_bst s))).
+ (@Bst (fst p) (partition_bst_1 f (is_bst s)),
+ @Bst (snd p) (partition_bst_2 f (is_bst s))).
Definition equal (s s':t) : bool := Raw.equal s s'.
Definition subset (s s':t) : bool := Raw.subset s s'.
Definition eq (s s':t) : Prop := Raw.Equal s s'.
- Definition lt (s s':t) : Prop := Raw.lt s s'.
+ Definition lt (s s':t) : Prop := Raw.Proofs.lt s s'.
Definition compare (s s':t) : Compare lt eq s s'.
Proof.
intros (s,b) (s',b').
- generalize (Raw.compare_Cmp s s').
+ generalize (compare_Cmp s s').
destruct Raw.compare; intros; [apply EQ|apply LT|apply GT]; red; auto.
Defined.
@@ -1856,113 +1916,111 @@ Module IntMake (I:Int)(X: OrderedType) <: S with Module E := X.
Hint Resolve is_bst.
Lemma mem_1 : In x s -> mem x s = true.
- Proof. exact (Raw.mem_1 (is_bst s)). Qed.
+ Proof. exact (mem_1 (is_bst s)). Qed.
Lemma mem_2 : mem x s = true -> In x s.
- Proof. exact (@Raw.mem_2 s x). Qed.
+ Proof. exact (@mem_2 s x). Qed.
Lemma equal_1 : Equal s s' -> equal s s' = true.
- Proof. exact (Raw.equal_1 (is_bst s) (is_bst s')). Qed.
+ Proof. exact (equal_1 (is_bst s) (is_bst s')). Qed.
Lemma equal_2 : equal s s' = true -> Equal s s'.
- Proof. exact (@Raw.equal_2 s s'). Qed.
+ Proof. exact (@equal_2 s s'). Qed.
Ltac wrap t H := unfold t, In; simpl; rewrite H; auto; intuition.
Lemma subset_1 : Subset s s' -> subset s s' = true.
- Proof. wrap subset Raw.subset_12. Qed.
+ Proof. wrap subset subset_12. Qed.
Lemma subset_2 : subset s s' = true -> Subset s s'.
- Proof. wrap subset Raw.subset_12. Qed.
+ Proof. wrap subset subset_12. Qed.
Lemma empty_1 : Empty empty.
- Proof. exact Raw.empty_1. Qed.
+ Proof. exact empty_1. Qed.
Lemma is_empty_1 : Empty s -> is_empty s = true.
- Proof. exact (@Raw.is_empty_1 s). Qed.
+ Proof. exact (@is_empty_1 s). Qed.
Lemma is_empty_2 : is_empty s = true -> Empty s.
- Proof. exact (@Raw.is_empty_2 s). Qed.
+ Proof. exact (@is_empty_2 s). Qed.
Lemma add_1 : E.eq x y -> In y (add x s).
- Proof. wrap add Raw.add_in. Qed.
+ Proof. wrap add add_in. Qed.
Lemma add_2 : In y s -> In y (add x s).
- Proof. wrap add Raw.add_in. Qed.
+ Proof. wrap add add_in. Qed.
Lemma add_3 : ~ E.eq x y -> In y (add x s) -> In y s.
- Proof. wrap add Raw.add_in. elim H; auto. Qed.
+ Proof. wrap add add_in. elim H; auto. Qed.
Lemma remove_1 : E.eq x y -> ~ In y (remove x s).
- Proof. wrap remove Raw.remove_in. Qed.
+ Proof. wrap remove remove_in. Qed.
Lemma remove_2 : ~ E.eq x y -> In y s -> In y (remove x s).
- Proof. wrap remove Raw.remove_in. Qed.
+ Proof. wrap remove remove_in. Qed.
Lemma remove_3 : In y (remove x s) -> In y s.
- Proof. wrap remove Raw.remove_in. Qed.
+ Proof. wrap remove remove_in. Qed.
Lemma singleton_1 : In y (singleton x) -> E.eq x y.
- Proof. exact (@Raw.singleton_1 x y). Qed.
+ Proof. exact (@singleton_1 x y). Qed.
Lemma singleton_2 : E.eq x y -> In y (singleton x).
- Proof. exact (@Raw.singleton_2 x y). Qed.
+ Proof. exact (@singleton_2 x y). Qed.
Lemma union_1 : In x (union s s') -> In x s \/ In x s'.
- Proof. wrap union Raw.union_in. Qed.
+ Proof. wrap union union_in. Qed.
Lemma union_2 : In x s -> In x (union s s').
- Proof. wrap union Raw.union_in. Qed.
+ Proof. wrap union union_in. Qed.
Lemma union_3 : In x s' -> In x (union s s').
- Proof. wrap union Raw.union_in. Qed.
+ Proof. wrap union union_in. Qed.
Lemma inter_1 : In x (inter s s') -> In x s.
- Proof. wrap inter Raw.inter_in. Qed.
+ Proof. wrap inter inter_in. Qed.
Lemma inter_2 : In x (inter s s') -> In x s'.
- Proof. wrap inter Raw.inter_in. Qed.
+ Proof. wrap inter inter_in. Qed.
Lemma inter_3 : In x s -> In x s' -> In x (inter s s').
- Proof. wrap inter Raw.inter_in. Qed.
+ Proof. wrap inter inter_in. Qed.
Lemma diff_1 : In x (diff s s') -> In x s.
- Proof. wrap diff Raw.diff_in. Qed.
+ Proof. wrap diff diff_in. Qed.
Lemma diff_2 : In x (diff s s') -> ~ In x s'.
- Proof. wrap diff Raw.diff_in. Qed.
+ Proof. wrap diff diff_in. Qed.
Lemma diff_3 : In x s -> ~ In x s' -> In x (diff s s').
- Proof. wrap diff Raw.diff_in. Qed.
+ Proof. wrap diff diff_in. Qed.
Lemma fold_1 : forall (A : Type) (i : A) (f : elt -> A -> A),
fold f s i = fold_left (fun a e => f e a) (elements s) i.
- Proof.
- unfold fold, elements; intros; apply Raw.fold_1; auto.
- Qed.
+ Proof. unfold fold, elements; intros; apply fold_1; auto. Qed.
Lemma cardinal_1 : cardinal s = length (elements s).
Proof.
- unfold cardinal, elements; intros; apply Raw.elements_cardinal; auto.
+ unfold cardinal, elements; intros; apply elements_cardinal; auto.
Qed.
Section Filter.
Variable f : elt -> bool.
Lemma filter_1 : compat_bool E.eq f -> In x (filter f s) -> In x s.
- Proof. intro. wrap filter Raw.filter_in. Qed.
+ Proof. intro. wrap filter filter_in. Qed.
Lemma filter_2 : compat_bool E.eq f -> In x (filter f s) -> f x = true.
- Proof. intro. wrap filter Raw.filter_in. Qed.
+ Proof. intro. wrap filter filter_in. Qed.
Lemma filter_3 : compat_bool E.eq f -> In x s -> f x = true -> In x (filter f s).
- Proof. intro. wrap filter Raw.filter_in. Qed.
+ Proof. intro. wrap filter filter_in. Qed.
Lemma for_all_1 : compat_bool E.eq f -> For_all (fun x => f x = true) s -> for_all f s = true.
- Proof. exact (@Raw.for_all_1 f s). Qed.
+ Proof. exact (@for_all_1 f s). Qed.
Lemma for_all_2 : compat_bool E.eq f -> for_all f s = true -> For_all (fun x => f x = true) s.
- Proof. exact (@Raw.for_all_2 f s). Qed.
+ Proof. exact (@for_all_2 f s). Qed.
Lemma exists_1 : compat_bool E.eq f -> Exists (fun x => f x = true) s -> exists_ f s = true.
- Proof. exact (@Raw.exists_1 f s). Qed.
+ Proof. exact (@exists_1 f s). Qed.
Lemma exists_2 : compat_bool E.eq f -> exists_ f s = true -> Exists (fun x => f x = true) s.
- Proof. exact (@Raw.exists_2 f s). Qed.
+ Proof. exact (@exists_2 f s). Qed.
Lemma partition_1 : compat_bool E.eq f ->
Equal (fst (partition f s)) (filter f s).
Proof.
unfold partition, filter, Equal, In; simpl ;intros H a.
- rewrite Raw.partition_in_1, Raw.filter_in; intuition.
+ rewrite partition_in_1, filter_in; intuition.
Qed.
Lemma partition_2 : compat_bool E.eq f ->
Equal (snd (partition f s)) (filter (fun x => negb (f x)) s).
Proof.
unfold partition, filter, Equal, In; simpl ;intros H a.
- rewrite Raw.partition_in_2, Raw.filter_in; intuition.
+ rewrite partition_in_2, filter_in; intuition.
rewrite H2; auto.
destruct (f a); auto.
red; intros; f_equal.
@@ -1972,47 +2030,47 @@ Module IntMake (I:Int)(X: OrderedType) <: S with Module E := X.
End Filter.
Lemma elements_1 : In x s -> InA E.eq x (elements s).
- Proof. wrap elements Raw.elements_in. Qed.
+ Proof. wrap elements elements_in. Qed.
Lemma elements_2 : InA E.eq x (elements s) -> In x s.
- Proof. wrap elements Raw.elements_in. Qed.
+ Proof. wrap elements elements_in. Qed.
Lemma elements_3 : sort E.lt (elements s).
- Proof. exact (Raw.elements_sort (is_bst s)). Qed.
+ Proof. exact (elements_sort (is_bst s)). Qed.
Lemma elements_3w : NoDupA E.eq (elements s).
- Proof. exact (Raw.elements_nodup (is_bst s)). Qed.
+ Proof. exact (elements_nodup (is_bst s)). Qed.
Lemma min_elt_1 : min_elt s = Some x -> In x s.
- Proof. exact (@Raw.min_elt_1 s x). Qed.
+ Proof. exact (@min_elt_1 s x). Qed.
Lemma min_elt_2 : min_elt s = Some x -> In y s -> ~ E.lt y x.
- Proof. exact (@Raw.min_elt_2 s x y (is_bst s)). Qed.
+ Proof. exact (@min_elt_2 s x y (is_bst s)). Qed.
Lemma min_elt_3 : min_elt s = None -> Empty s.
- Proof. exact (@Raw.min_elt_3 s). Qed.
+ Proof. exact (@min_elt_3 s). Qed.
Lemma max_elt_1 : max_elt s = Some x -> In x s.
- Proof. exact (@Raw.max_elt_1 s x). Qed.
+ Proof. exact (@max_elt_1 s x). Qed.
Lemma max_elt_2 : max_elt s = Some x -> In y s -> ~ E.lt x y.
- Proof. exact (@Raw.max_elt_2 s x y (is_bst s)). Qed.
+ Proof. exact (@max_elt_2 s x y (is_bst s)). Qed.
Lemma max_elt_3 : max_elt s = None -> Empty s.
- Proof. exact (@Raw.max_elt_3 s). Qed.
+ Proof. exact (@max_elt_3 s). Qed.
Lemma choose_1 : choose s = Some x -> In x s.
- Proof. exact (@Raw.choose_1 s x). Qed.
+ Proof. exact (@choose_1 s x). Qed.
Lemma choose_2 : choose s = None -> Empty s.
- Proof. exact (@Raw.choose_2 s). Qed.
+ Proof. exact (@choose_2 s). Qed.
Lemma choose_3 : choose s = Some x -> choose s' = Some y ->
Equal s s' -> E.eq x y.
- Proof. exact (@Raw.choose_3 _ _ (is_bst s) (is_bst s') x y). Qed.
+ Proof. exact (@choose_3 _ _ (is_bst s) (is_bst s') x y). Qed.
Lemma eq_refl : eq s s.
- Proof. exact (Raw.eq_refl s). Qed.
+ Proof. exact (eq_refl s). Qed.
Lemma eq_sym : eq s s' -> eq s' s.
- Proof. exact (@Raw.eq_sym s s'). Qed.
+ Proof. exact (@eq_sym s s'). Qed.
Lemma eq_trans : eq s s' -> eq s' s'' -> eq s s''.
- Proof. exact (@Raw.eq_trans s s' s''). Qed.
+ Proof. exact (@eq_trans s s' s''). Qed.
Lemma lt_trans : lt s s' -> lt s' s'' -> lt s s''.
- Proof. exact (@Raw.lt_trans s s' s''). Qed.
+ Proof. exact (@lt_trans s s' s''). Qed.
Lemma lt_not_eq : lt s s' -> ~eq s s'.
- Proof. exact (@Raw.lt_not_eq _ _ (is_bst s) (is_bst s')). Qed.
+ Proof. exact (@lt_not_eq _ _ (is_bst s) (is_bst s')). Qed.
End Specs.
End IntMake.