changeset 94:affdf00759d8

Red-black insert
author Adam Chlipala <adamc@hcoop.net>
date Tue, 07 Oct 2008 20:15:12 -0400
parents a08e82c646a5
children 7804f9d5249f
files src/MoreDep.v
diffstat 1 files changed, 161 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/MoreDep.v	Tue Oct 07 16:50:46 2008 -0400
+++ b/src/MoreDep.v	Tue Oct 07 20:15:12 2008 -0400
@@ -344,6 +344,167 @@
 Qed.
 
 
+(** Dependently-Typed Red-Black Trees *)
+
+Inductive color : Set := Red | Black.
+
+Inductive rbtree : color -> nat -> Set :=
+| Leaf : rbtree Black 0
+| RedNode : forall n, rbtree Black n -> nat-> rbtree Black n -> rbtree Red n
+| BlackNode : forall c1 c2 n, rbtree c1 n -> nat -> rbtree c2 n -> rbtree Black (S n).
+
+Inductive rtree : nat -> Set :=
+| RedNode' : forall c1 c2 n, rbtree c1 n -> nat -> rbtree c2 n -> rtree n.
+
+Notation "{< x >}" := (existT _ _ x).
+
+Definition balance1 n (a : rtree n) (data : nat) c2 :=
+  match a in rtree n return rbtree c2 n -> { c : color & rbtree c (S n) } with
+    | RedNode' _ _ _ t1 y t2 =>
+      match t1 in rbtree c n return rbtree _ n -> rbtree c2 n -> { c : color & rbtree c (S n) } with
+        | RedNode _ a x b => fun c d => {<RedNode (BlackNode a x b) y (BlackNode c data d)>}
+        | t1' => fun t2 =>
+          match t2 in rbtree c n return rbtree _ n -> rbtree c2 n -> { c : color & rbtree c (S n) } with
+            | RedNode _ b x c => fun a d => {<RedNode (BlackNode a y b) x (BlackNode c data d)>}
+            | b => fun a t => {<BlackNode a data b>}
+          end t1'
+      end t2
+  end.
+
+Definition balance2 n (a : rtree n) (data : nat) c2 :=
+  match a in rtree n return rbtree c2 n -> { c : color & rbtree c (S n) } with
+    | RedNode' _ _ _ t1 z t2 =>
+      match t1 in rbtree c n return rbtree _ n -> rbtree c2 n -> { c : color & rbtree c (S n) } with
+        | RedNode _ b y c => fun d a => {<RedNode (BlackNode a data b) y (BlackNode c z d)>}
+        | t1' => fun t2 =>
+          match t2 in rbtree c n return rbtree _ n -> rbtree c2 n -> { c : color & rbtree c (S n) } with
+            | RedNode _ c z' d => fun b a => {<RedNode (BlackNode a data b) z (BlackNode c z' d)>}
+            | b => fun t a => {<BlackNode a data b>}
+          end t1'
+      end t2
+  end.
+
+Section insert.
+  Variable x : nat.
+
+  Definition insResult c n :=
+    match c with
+      | Red => rtree n
+      | Black => { c' : color & rbtree c' n }
+    end.
+
+  Fixpoint ins c n (t : rbtree c n) {struct t} : insResult c n :=
+    match t in (rbtree c n) return (insResult c n) with
+      | Leaf => {< RedNode Leaf x Leaf >}
+      | RedNode _ a y b =>
+        if le_lt_dec x y
+          then RedNode' (projT2 (ins a)) y b
+          else RedNode' a y (projT2 (ins b))
+      | BlackNode c1 c2 _ a y b =>
+        if le_lt_dec x y
+          then
+            match c1 return insResult c1 _ -> _ with
+              | Red => fun ins_a => balance1 ins_a y b
+              | _ => fun ins_a => {< BlackNode (projT2 ins_a) y b >}
+            end (ins a)
+          else
+            match c2 return insResult c2 _ -> _ with
+              | Red => fun ins_b => balance2 ins_b y a
+              | _ => fun ins_b => {< BlackNode a y (projT2 ins_b) >}
+            end (ins b)
+    end.
+
+  Definition insertResult c n :=
+    match c with
+      | Red => rbtree Black (S n)
+      | Black => { c' : color & rbtree c' n }
+    end.
+
+  Definition makeBlack c n : insResult c n -> insertResult c n :=
+    match c return insResult c n -> insertResult c n with
+      | Red => fun r =>
+        match r in rtree n return insertResult Red n with
+          | RedNode' _ _ _ a x b => BlackNode a x b
+        end
+      | Black => fun r => r
+    end.
+
+  Implicit Arguments makeBlack [c n].
+
+  Definition insert c n (t : rbtree c n) : insertResult c n :=
+    makeBlack (ins t).
+
+  Fixpoint present c n (t : rbtree c n) {struct t} : bool :=
+    match t with
+      | Leaf => false
+      | RedNode _ a y b =>
+        if eq_nat_dec x y
+          then true
+          else if le_lt_dec x y
+            then present a
+            else present b
+      | BlackNode _ _ _ a y b =>
+        if eq_nat_dec x y
+          then true
+          else if le_lt_dec x y
+            then present a
+            else present b
+    end.
+
+  Definition rpresent n (t : rtree n) : bool :=
+    match t with
+      | RedNode' _ _ _ a y b =>
+        if eq_nat_dec x y
+          then true
+          else if le_lt_dec x y
+            then present a
+            else present b
+    end.
+End insert.
+
+
+Require Import Max Min.
+
+Section depth.
+  Variable f : nat -> nat -> nat.
+
+  Fixpoint depth c n (t : rbtree c n) {struct t} : nat :=
+    match t with
+      | Leaf => 0
+      | RedNode _ t1 _ t2 => S (f (depth t1) (depth t2))
+      | BlackNode _ _ _ t1 _ t2 => S (f (depth t1) (depth t2))
+    end.
+End depth.
+
+Theorem depth_min : forall c n (t : rbtree c n), depth min t >= n.
+  induction t; crush;
+    match goal with
+      | [ |- context[min ?X ?Y] ] => destruct (min_dec X Y)
+    end; crush.
+Qed.
+
+Lemma depth_max' : forall c n (t : rbtree c n), match c with
+                                                  | Red => depth max t <= 2 * n + 1
+                                                  | Black => depth max t <= 2 * n
+                                                end.
+  induction t; crush;
+    match goal with
+      | [ |- context[max ?X ?Y] ] => destruct (max_dec X Y)
+    end; crush.
+
+  destruct c1; crush.
+  destruct c2; crush.
+Qed.
+
+Theorem depth_max : forall c n (t : rbtree c n), depth max t <= 2 * n + 1.
+  intros; generalize (depth_max' t); destruct c; crush.
+Qed.
+
+Theorem balanced : forall c n (t : rbtree c n), 2 * depth min t + 1 >= depth max t.
+  intros; generalize (depth_min t); generalize (depth_max t); crush.
+Qed.
+
+
 (** * A Certified Regular Expression Matcher *)
 
 (** Another interesting example is regular expressions with dependent types that express which predicates over strings particular regexps implement.  We can then assign a dependent type to a regular expression matching function, guaranteeing that it always decides the string property that we expect it to decide.