-
Notifications
You must be signed in to change notification settings - Fork 139
/
Map.hs
182 lines (142 loc) · 5.36 KB
/
Map.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
module Map (error, mllen) where
import Language.Haskell.Liquid.Prelude
import Prelude hiding (error)
{-@ lazy error @-}
error :: a -> b
error x = error x
{-@
data Map [mllen] k a <l :: root:k -> k -> Bool, r :: root:k -> k -> Bool>
= Tip
| Bin { mSz :: Size
, mKey :: k
, mValue :: a
, mLeft :: Map <l, r> (k <l mKey>) a
, mRight :: Map <l, r> (k <r mKey>) a }
@-}
{-@ measure mllen @-}
mllen :: Map k a -> Int
{-@ mllen :: Map k a -> Nat @-}
mllen Tip = 0
mllen (Bin _ _ _ l r) = 1 + if (mllen l < mllen r) then mllen r else mllen l
{-@ measure mlen :: (Map k a) -> Int
mlen Tip = 0
mlen (Bin s k v l r) = 1 + (mlen l) + (mlen r)
@-}
{-@ invariant {v:Map k a | (mlen v) >= 0}@-}
{-@ type OMap k a = Map <{\root v -> v < root }, {\root v -> v > root}> k a @-}
data Map k a = Tip
| Bin Size k a (Map k a) (Map k a)
type Size = Int
{-@ singleton :: k -> a -> OMap k a @-}
singleton :: k -> a -> Map k a
singleton k x
= Bin 1 k x Tip Tip
{-@ insert :: Ord k => k -> a -> OMap k a -> OMap k a @-}
insert :: Ord k => k -> a -> Map k a -> Map k a
insert kx x t
= case t of
Tip -> singleton kx x
Bin sz ky y l r
-> case compare kx ky of
LT -> balance ky y (insert kx x l) r
GT -> balance ky y l (insert kx x r)
EQ -> Bin sz kx x l r
{-@ delete :: (Ord k) => k:k -> OMap k a -> OMap {v:k| (v /= k)} a @-}
delete :: Ord k => k -> Map k a -> Map k a
delete k t
= case t of
Tip -> Tip
Bin _ kx x l r
-> case compare k kx of
LT -> balance kx x (delete k l) r
GT -> balance kx x l (delete k r)
EQ -> glue kx l r
glue :: k -> Map k a -> Map k a -> Map k a
glue k Tip r = r
glue k l Tip = l
glue k l r
| size l > size r = let (km1, vm, lm) = deleteFindMax l in balance km1 vm lm r
| otherwise = let (km2, vm, rm) = deleteFindMin r in balance km2 vm l rm
deleteFindMax t
= case t of
Bin _ k x l Tip -> (k, x, l)
Bin _ k x l r -> let (km3, vm, rm) = deleteFindMax r in (km3, vm, (balance k x l rm))
Tip -> (error ms, error ms, Tip)
where ms = "Map.deleteFindMax : can not return the maximal element of an empty Map"
deleteFindMin t
= case t of
Bin _ k x Tip r -> (k, x, r)
Bin _ k x l r -> let (km4, vm, lm) = deleteFindMin l in (km4, vm, (balance k x lm r))
Tip -> (error ms, error ms, Tip)
where ms = "Map.deleteFindMin : can not return the maximal element of an empty Map"
-------------------------------------------------------------------------------
--------------------------------- BALANCE -------------------------------------
-------------------------------------------------------------------------------
delta, ratio :: Int
delta = 5
ratio = 2
balance :: k -> a -> Map k a -> Map k a -> Map k a
balance k x l r
| sizeL + sizeR <= 1 = Bin sizeX k x l r
| sizeR >= delta*sizeL = rotateL k x l r
| sizeL >= delta*sizeR = rotateR k x l r
| otherwise = Bin sizeX k x l r
where sizeL = size l
sizeR = size r
sizeX = sizeL + sizeR + 1
-- rotate
rotateL :: a -> b -> Map a b -> Map a b -> Map a b
rotateL k x l r@(Bin _ _ _ ly ry)
| size ly < ratio*size ry = singleL k x l r
| otherwise = doubleL k x l r
rotateL _ _ _ Tip = error "rotateL Tip"
rotateR :: a -> b -> Map a b -> Map a b -> Map a b
rotateR k x l@(Bin _ _ _ ly ry) r
| size ry < ratio*size ly = singleR k x l r
| otherwise = doubleR k x l r
rotateR _ _ Tip _ = error "rotateR Tip"
-- basic rotations
singleL, singleR :: a -> b -> Map a b -> Map a b -> Map a b
singleL k1 x1 t1 (Bin _ k2 x2 t2 t3) = bin k2 x2 (bin k1 x1 t1 t2) t3
singleL _ _ _ Tip = error "sinlgeL Tip"
singleR k1 x1 (Bin _ k2 x2 t1 t2) t3 = Bin 0 k2 x2 t1 (Bin 0 k1 x1 t2 t3)
singleR _ _ Tip _ = error "sinlgeR Tip"
doubleL, doubleR :: a -> b -> Map a b -> Map a b -> Map a b
doubleL k1 x1 t1 (Bin _ k2 x2 (Bin _ k3 x3 t2 t3) t4)
=bin k3 x3 (bin k1 x1 t1 t2) (bin k2 x2 t3 t4)
doubleL _ _ _ _ = error "doubleL"
doubleR k1 x1 (Bin _ k2 x2 t1 (Bin _ k3 x3 t2 t3)) t4
= bin k3 x3 (bin k2 x2 t1 t2) (bin k1 x1 t3 t4)
doubleR _ _ _ _ = error "doubleR"
bin :: k -> a -> Map k a -> Map k a -> Map k a
bin k x l r
= Bin (size l + size r + 1) k x l r
size :: Map k a -> Int
size t
= case t of
Tip -> 0
Bin sz _ _ _ _ -> sz
-- chkDel x Tip = liquidAssertB True
-- chkDel x (Bin sz k v lt rt) = liquidAssertB (not (x == k)) && chkDel x lt && chkDel x rt
-- chkMin x Tip = liquidAssertB True
-- chkMin x (Bin sz k v lt rt) = liquidAssertB (x<k) && chkMin x lt && chkMin x rt
chk Tip = liquidAssertB True
chk (Bin s k v lt rt) = chk lt && chk rt && chkl k lt && chkr k rt
chkl k Tip = liquidAssertB True
chkl k (Bin _ kl _ _ _) = liquidAssertB (kl < k)
chkr k Tip = liquidAssertB True
chkr k (Bin _ kr _ _ _) = liquidAssertB (k < kr)
key, key1, val, val1 :: Int
key = choose 0
val = choose 1
key1 = choose 0
val1 = choose 1
bst1 = insert key val Tip
bst = insert key val $ insert key1 val1 Tip
mkBst = foldl (\t (k, v) -> insert k v t) Tip
prop = chk bst1
prop1 = chk $ mkBst $ zip [1..] [1..]
propDelete = chk bst' -- && chkDel x bst'
where
x = choose 0
bst' = delete x bst