-
Notifications
You must be signed in to change notification settings - Fork 0
/
redblack.hs
140 lines (106 loc) · 4.11 KB
/
redblack.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
-- Copyright 2016--2017, Matt Might and Lee Pike.
--
-- Adapted from a SmartCheck example:
-- https://github.com/leepike/SmartCheck/tree/master/examples/RedBlackTreesh
-- which in turn was adapted from:
-- http://matt.might.net/articles/quick-quickcheck/
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
-- Note from Matt Might:
-- Note: Benjamin Pierce's lecture notes are where I learned to
-- generate properly ordered binary search trees:
-- http://www.seas.upenn.edu/~cis552/12fa/lectures/stub/BST.html
import RedBlackSet
import Test.Extrapolate
instance (Ord a, Listable a) => Listable (RBSet a) where
tiers = cons1 fromList
-- transforms a list into an RBSet.
fromList :: Ord a => [a] -> RBSet a
fromList = foldr insert empty
-- Count the black depth of a red-black tree:
blackDepth :: RBSet a -> Maybe Int
blackDepth (E) = Just(1)
blackDepth (T R l _ r) = case (blackDepth(l),blackDepth(r)) of
(Just(n),Just(m)) -> if n == m then Just(n) else Nothing
(_,_) -> Nothing
blackDepth (T B l _ r) = case (blackDepth(l),blackDepth(r)) of
(Just(n),Just(m)) -> if n == m then Just(1+n) else Nothing
(_,_) -> Nothing
blackDepth _ = error "unhandled pattern"
-- Check for red-red violations:
prop_NoRedRed :: RBSet Int -> Bool
prop_NoRedRed E = True
prop_NoRedRed (T R (T R _ _ _) _ _) = False
prop_NoRedRed (T R _ _ (T R _ _ _)) = False
prop_NoRedRed (T _ l x r) = (prop_NoRedRed l) && (prop_NoRedRed r)
prop_NoRedRed _ = error "unhandled pattern"
-- Check for black-balanced violations:
prop_BlackBalanced :: RBSet Int -> Bool
prop_BlackBalanced t =
case blackDepth(t) of
Just _ -> True
Nothing -> False
-- Check for ordering violations:
prop_OrderedList :: Ord a => [a] -> Bool
prop_OrderedList [] = True
prop_OrderedList [x] = True
prop_OrderedList (x:y:tl) = (x < y) && (prop_OrderedList(y:tl))
prop_Ordered :: RBSet Int -> Bool
prop_Ordered t = prop_OrderedList (toAscList t)
-- Check for the validity of a red-black tree:
prop_RBValid :: RBSet Int -> Bool
prop_RBValid t = prop_NoRedRed t && prop_BlackBalanced t && prop_Ordered t
-- Insertion properties:
prop_Create5 :: Int -> Int -> Int -> Int -> Int -> Bool
prop_Create5 a b c d e =
((foldr insert empty) [a,b,c,d,e]) ==
((foldr insert empty) [b,c,d,e,a])
prop_InsertValid :: RBSet Int -> Int -> Bool
prop_InsertValid t x = prop_RBValid(insert x t)
prop_InsertMember :: RBSet Int -> Int -> Bool
prop_InsertMember t x = member x (insert x t)
prop_InsertSafe :: RBSet Int -> Int -> Int -> Bool
prop_InsertSafe t x y = member x t ==> (member x (insert y t))
prop_NoInsertPhantom :: RBSet Int -> Int -> Int -> Bool
prop_NoInsertPhantom t x y =
not (member x t) && x /= y ==> not (member x (insert y t))
-- Deletion properties:
prop_InsertDeleteValid :: RBSet Int -> Int -> Bool
prop_InsertDeleteValid t x = prop_RBValid(delete x (insert x t))
prop_DeleteValid :: RBSet Int -> Int -> Bool
prop_DeleteValid t x = prop_RBValid(delete x t)
prop_MemberDelete :: RBSet Int -> Int -> Bool
prop_MemberDelete t x = member x t ==> not (member x (delete x t))
prop_DeletePreserve :: RBSet Int -> Int -> Int -> Bool
prop_DeletePreserve t x y = x /= y ==> (member y t) == (member y (delete x t))
main :: IO ()
main = do
chk prop_BlackBalanced
-- {-
-- Insertion tests:
chk prop_Create5
chk prop_InsertValid
chk prop_InsertSafe
chk prop_NoInsertPhantom
chk prop_InsertMember
-- Deletion tests:
chk prop_InsertDeleteValid
chk prop_DeleteValid
chk prop_MemberDelete
chk prop_DeletePreserve
-- -}
where
chk :: Testable a => a -> IO ()
chk = check `for` 1080
instance Listable Color where
tiers = [[R, B], [BB, NB]]
instance Name (RBSet a) where
name _ = "h"
instance (Ord a, Express a) => Express (RBSet a) where
expr t = value "fromList" (fromList ->: t) :$ expr (toAscList t)
instance (Ord a, Generalizable a) => Generalizable (RBSet a) where
subInstances h = instances (toAscList h)
-- TODO: make LeanCheck find a counter-example to prop_BlackBalanced
-- when -DBALANCE_BUG is active or find out why it cannot find it.
-- TODO: somehow make "./eg/redblack-remove-bug" run faster.
-- (currently, it takes 2 minutes to run)