Red-Black Trees
===============
\begin{code}
{-@ LIQUID "--no-termination" @-}
{-@ LIQUID "--diff" @-}
module RBTree (ok, bad1, bad2) where
import Language.Haskell.Liquid.Prelude
ok, bad1, bad2 :: RBTree Int
---------------------------------------------------------------------------
-- | Specifications -------------------------------------------------------
---------------------------------------------------------------------------
-- | Red-Black Trees
{-@ type RBT a = {v: RBTree a | isRB v && isBH v } @-}
{-@ measure isRB :: RBTree a -> Prop
isRB (Leaf) = true
isRB (Node c x l r) = isRB l && isRB r && (c == R => (IsB l && IsB r))
@-}
-- | Almost Red-Black Trees
{-@ type ARBT a = {v: RBTree a | isARB v && isBH v} @-}
{-@ measure isARB :: (RBTree a) -> Prop
isARB (Leaf) = true
isARB (Node c x l r) = (isRB l && isRB r)
@-}
-- | Color of a tree
{-@ measure col :: RBTree a -> Color
col (Node c x l r) = c
col (Leaf) = B
@-}
{-@ measure isB :: RBTree a -> Prop
isB (Leaf) = false
isB (Node c x l r) = c == B
@-}
{-@ predicate IsB T = not (col T == R) @-}
-- | Black Height
{-@ measure isBH :: RBTree a -> Prop
isBH (Leaf) = true
isBH (Node c x l r) = (isBH l && isBH r && bh l = bh r)
@-}
{-@ measure bh :: RBTree a -> Int
bh (Leaf) = 0
bh (Node c x l r) = bh l + if (c == R) then 0 else 1
@-}
-- | Binary Search Ordering
{-@ data RBTree a = Leaf
| Node { c :: Color
, key :: a
, left :: RBTree ({v:a | v < key})
, right :: RBTree ({v:a | key < v}) } @-}
\end{code}
{#asdad}
---------
+ **Color Invariant:** `Red` nodes have `Black` children
+ **Height Invariant:** Number of `Black` nodes equal on *all paths*
+ **Order Invariant:** Left keys < root < Right keys
Basic Type
----------
\begin{code}
data Color = R | B
data RBTree a = Leaf
| Node { c :: Color
, key :: a
, left :: RBTree a
, right :: RBTree a }
\end{code}
1. Color Invariant
------------------
`Red` nodes have `Black` children
\begin{spec}
measure isRB :: Tree a -> Prop
isRB (Leaf) = true
isRB (Node c x l r) = c == R => (isB l && isB r)
&& isRB l && isRB r
\end{spec}
where
\begin{spec}
measure isB :: Tree a -> Prop
isB (Leaf) = true
isB (Node c x l r) = c == B
\end{spec}
1. *Almost* Color Invariant
---------------------------
Color Invariant **except** at root.
\begin{spec}
measure isAlmost :: RBTree a -> Prop
isAlmost (Leaf) = true
isAlmost (Node c x l r) = isRB l && isRB r
\end{spec}
2. Height Invariant
-------------------
Number of `Black` nodes equal on **all paths**
\begin{spec}
measure isBH :: RBTree a -> Prop
isBH (Leaf) = true
isBH (Node c x l r) = bh l == bh r
&& isBH l && isBH r
\end{spec}
where
\begin{spec}
measure bh :: RBTree a -> Int
bh (Leaf) = 0
bh (Node c x l r) = bh l
+ if c == R then 0 else 1
\end{spec}
3. Order Invariant
------------------
**Binary Search Ordering**
\begin{spec}
data RBTree a
= Leaf
| Node { c :: Color
, key :: a
, left :: RBTree {v:a | v < key}
, right :: RBTree {v:a | key < v}
}
\end{spec}
Valid Red-Black Trees
---------------------
**Conjoining Specifications**
\begin{spec}
-- | Red-Black Trees
type RBT a = {v:RBTree a|isRB v && isBH v}
-- | Almost Red-Black Trees
type ARBT a = {v:RBTree a|isAlmost v && isBH v}
\end{spec}
[Details](https://github.com/ucsd-progsys/liquidhaskell/blob/master/tests/pos/RBTree.hs)
Ex: Satisfies Invariants
-------------------------
\begin{code}
{-@ ok :: RBT Int @-}
ok = Node R 2
(Node B 1 Leaf Leaf)
(Node B 3 Leaf Leaf)
\end{code}
Ex: Violates Order Invariant
----------------------------
\begin{code}
{-@ bad1 :: RBT Int @-}
bad1 = Node R 1
(Node B 2 Leaf Leaf)
(Node B 3 Leaf Leaf)
\end{code}
Ex: Violates Color Invariant
----------------------------
\begin{code}
{-@ bad2 :: RBT Int @-}
bad2 = Node R 2
(Node R 1 Leaf Leaf)
(Node B 3 Leaf Leaf)
\end{code}
Verified Red-Black Operations
-----------------------------
**Types Verify Correctness of**
+ Insertion
+ Deletion
+ Lookup ...
**In presence of rotation & rebalancing** [[details]](https://github.com/ucsd-progsys/liquidhaskell/blob/master/tests/pos/RBTree.hs)