Changeset 2140
- Timestamp:
- 06/30/08 15:15:47 (4 months ago)
- Author:
- mspiegel
- Message:
[Library] a working basic implementation of skip tree data structure, with test cases to probabilistically prove correctness. Also added
list append to PureList?.fsi and PureList?.fss.
- Files:
- trunk/Library/PureList.fsi (modified) (1 diff)
- trunk/Library/PureList.fss (modified) (2 diffs)
- trunk/Library/incomplete/SkipTree.fsi (modified) (1 diff)
- trunk/Library/incomplete/SkipTree.fss (modified) (20 diffs)
- trunk/Library/incomplete/SkipTreeTest.fss (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/Library/PureList.fsi
r1832 r2140 59 59 by the elements of %f% *) 60 60 append(f:List[\E\]): List[\E\] 61 (** the operator %||% performs the %append% operation *) 62 opr ||(self, other:List[\E\]): List[\E\] 61 63 (** %addLeft% and %addRight% add an element to the left or right of 62 the list, respectively *) 64 the list, respectively *) 63 65 addLeft(e:E):List[\E\] 64 66 addRight(e:E):List[\E\] trunk/Library/PureList.fss
r1825 r2140 52 52 getter extractRight(): Maybe[\(List[\E\],E)\] 53 53 append(f:List[\E\]): List[\E\] 54 opr ||(self, other:List[\E\]): List[\E\] 54 55 addLeft(e:E):List[\E\] 55 56 addRight(e:E):List[\E\] … … 129 130 it.generate[\R\](r,body) 130 131 seq(self): SequentialGenerator[\E\] = SeqListGenerator[\E\](it) 132 opr ||(self, other:List[\E\]): List[\E\] = append(other) 131 133 append(f:List[\E\]): PureList[\E\] = 132 134 append(f.generate[\PureList[\E\]\](PLConcat[\E\],singleton[\E\])) trunk/Library/incomplete/SkipTree.fsi
r2137 r2140 20 20 21 21 trait SkipTree[\Key,Value\] 22 23 getter toString():String 24 25 opr |self| : ZZ32 22 26 23 27 (** Takes a querykey as input and returns either a Just[\Value\] trunk/Library/incomplete/SkipTree.fss
r2139 r2140 17 17 18 18 component SkipTree 19 import List.{...}19 import PureList.{...} 20 20 21 21 … … 23 23 24 24 trait SkipTree[\Key,Value\] 25 26 getter toString():String 27 28 opr |self| : ZZ32 25 29 26 30 (** Takes a querykey as input and returns either a %Just[\Value\]% … … 55 59 **) 56 60 verify():() 61 62 57 63 58 64 end … … 61 67 62 68 object EmptySkipTree[\Key,Value\] extends { SkipTree[\Key,Value\] } 69 70 getter toString():String = "(EMPTY)" 71 72 opr |self| : ZZ32 = 0 63 73 64 74 find(querykey : Key) : Maybe[\Value\] = Nothing[\Value\] … … 67 77 newheight = randomLevel() 68 78 root = LeafNode[\Key,Value\](newkey, newvalue, newheight) 69 NonEmptySkipTree[\Key,Value\](root ')79 NonEmptySkipTree[\Key,Value\](root) 70 80 end 71 81 72 82 verify():() = () 83 73 84 74 85 end … … 77 88 78 89 object NonEmptySkipTree[\Key,Value\](root : Node[\Key,Value\]) extends { SkipTree[\Key,Value\] } 90 91 getter toString():String = root.toString() 92 93 opr |self| : ZZ32 = |root| 79 94 80 95 find(querykey : Key) : Maybe[\Value\] = root.find(querykey) … … 90 105 end 91 106 92 verify():() = root.verify() 107 verify():() = root.verify() 93 108 94 109 end … … 104 119 105 120 getter toString() : String = keys "" values "" children " h" height 121 122 opr |self| : ZZ32 = |keys| + children.generate[\Number\](SumReduction, 123 fn (child) => typecase child of 124 Just[\Node[\Key,Value\]\] => |child.get()| 125 else => 0 end) 126 127 128 opr =(self, other:Node[\Key,Value\]): Boolean = 129 if self SEQV other then true 130 else 131 (keys = other.keys AND values = other.values 132 AND children = other.children AND height = other.height) 133 end 106 134 107 135 … … 117 145 childIndex = insertionPoint(parentIndex) 118 146 typecase child = children[childIndex] of 119 Just[\ Value\] => child.get().find(querykey)147 Just[\Node[\Key,Value\]\] => child.get().find(querykey) 120 148 else => Nothing[\Value\] 121 149 end … … 147 175 typecase child = children[i] of 148 176 Just[\Node[\Key,Value\]\] => 149 newchild = child.get().insert(newkey,newvalue,newheight)177 newchild = Just[\Node[\Key,Value\]\](child.get().insert(newkey,newvalue,newheight)) 150 178 else => 151 newchild = LeafNode[\Key,Value\](newkey,newvalue,newheight)152 end 153 newchildren = children[0 # i] || <| newchild |> || children[(i + 1):]179 newchild = Just[\Node[\Key,Value\]\](LeafNode[\Key,Value\](newkey,newvalue,newheight)) 180 end 181 newchildren = children[0 # i].addRight(newchild) || children[(i + 1) : (|children| - 1)] 154 182 Node[\Key,Value\](keys,values,newchildren,height) 155 183 end … … 159 187 private insertEqualHeight(newkey:Key, newvalue:Value) : Node[\Key,Value\] = do 160 188 i = insertionPoint(binarySearch[\Key\](keys,newkey)) 161 newkeys = keys[0#i] || <| newkey |> || keys[i:]162 newvalues = values[0#i] || <| newvalue |> || values[i:]189 newkeys = keys[0#i].addRight(newkey) || keys[i:(|keys| - 1)] 190 newvalues = values[0#i].addRight(newvalue) || values[i : (|values| - 1)] 163 191 (newleft, newright) = 164 (filter (newkey, children[i], true),165 filter (newkey, children[i], false))166 leftchildren = children[0#i] || <|[\Maybe[\Node[\Key,Value\]\]\] newleft |>167 rightchildren = <|[\Maybe[\Node[\Key,Value\]\]\] newright |> || children[(i + 1):]192 (filterTarget(newkey, children[i], true), 193 filterTarget(newkey, children[i], false)) 194 leftchildren = children[0#i].addRight(newleft) 195 rightchildren = children[(i + 1):(|children| - 1)].addLeft(newright) 168 196 newchildren = leftchildren || rightchildren 169 197 Node[\Key,Value\](newkeys,newvalues,newchildren,height) … … 175 203 newkeys = singleton[\Key\](newkey) 176 204 newvalues = singleton[\Value\](newvalue) 177 (newleft,newright) = (filter (newkey, Just[\Node[\Key,Value\]\](self), true),178 filter (newkey, Just[\Node[\Key,Value\]\](self), false))179 newchildren = <| newleft, newright |>205 (newleft,newright) = (filterTarget(newkey, Just[\Node[\Key,Value\]\](self), true), 206 filterTarget(newkey, Just[\Node[\Key,Value\]\](self), false)) 207 newchildren = <|[\Maybe[\Node[\Key,Value\]\]\] newleft, newright |> 180 208 Node[\Key,Value\](newkeys,newvalues,newchildren,newheight) 181 209 end 182 210 183 211 184 private filter (newkey : Key,212 private filterTarget(newkey : Key, 185 213 target : Maybe[\Node[\Key,Value\]\], 186 214 lessThanOrEquals : Boolean) … … 226 254 newkeys = keys[0 # insertIndex] 227 255 newvalues = values[0 # insertIndex] 228 newchildren = children[0 # insertIndex] || <| filteredChild |>256 newchildren = children[0 # insertIndex].addRight(filteredChild) 229 257 Just[\Node[\Key,Value\]\](Node[\Key,Value\](newkeys,newvalues,newchildren,height)) 230 258 end … … 235 263 filteredChild : Maybe[\Node[\Key,Value\]\]) 236 264 : Maybe[\Node[\Key,Value\]\] = do 237 if insertIndex = keys.size()then265 if insertIndex = |keys| then 238 266 filteredChild 239 267 else 240 newkeys = keys[insertIndex :]241 newvalues = values[insertIndex :]242 newchildren = <|[\Maybe[\Node[\Key,Value\]\]\] filteredChild |> || children[(insertIndex + 1):]268 newkeys = keys[insertIndex : (|keys| - 1)] 269 newvalues = values[insertIndex : (|values| - 1)] 270 newchildren = children[(insertIndex + 1) : |children| - 1].addLeft(filteredChild) 243 271 Just[\Node[\Key,Value\]\](Node[\Key,Value\](newkeys,newvalues,newchildren,height)) 244 272 end … … 264 292 265 293 largestKey():Key = do 266 typecase child = children[ children.size()- 1] of294 typecase child = children[|children| - 1] of 267 295 Just[\Node[\Key,Value\]\] => child.get().largestKey() 268 else => keys[ keys.size()- 1]296 else => keys[|keys| - 1] 269 297 end 270 298 end … … 285 313 fail(toString() " : Size of children is not equal to size of keys plus one") 286 314 end 287 for i <- 0 # ( keys.size()- 1) do315 for i <- 0 # (|keys| - 1) do 288 316 if keys[i] >= keys[i + 1] then 289 317 fail(toString() " : Keys " keys[i] " and " keys[i + 1] " are not in sorted order") 290 318 end 291 319 end 292 for i <- 0 # keys.size()do320 for i <- 0 # |keys| do 293 321 typecase child = children[i] of 294 322 Just[\Node[\Key,Value\]\] => do … … 309 337 end 310 338 (* recusively check non-empty children *) 311 for i <- 0 # children.size()do339 for i <- 0 # |children| do 312 340 typecase child = children[i] of 313 341 Just[\Node[\Key,Value\]\] => child.get().verify() … … 346 374 * otherwise, (-(insertion point) - 1). The insertion point is defined 347 375 * as the point at which the key would be inserted into the list: 348 * the index of the first element greater than the key, or list.size()376 * the index of the first element greater than the key, or |list| 349 377 * if all elements in the list are less than the specified key. 350 378 * Note that this guarantees that the return value will be %>=% 0 … … 352 380 **) 353 381 binarySearch[\T\](list : List[\T\], key : T) : ZZ32 = do 354 if list.size()<= 8 then (* base case *)355 index:ZZ32 := - list.size()- 1382 if |list| <= 8 then (* base case *) 383 index:ZZ32 := - |list| - 1 356 384 label loop 357 for i <- seq(0 # list.size()) do385 for i <- seq(0 # |list|) do 358 386 if list[i] = key then 359 387 index := i … … 367 395 index 368 396 else (* recursive step *) 369 split = list.size()DIV 2397 split = |list| DIV 2 370 398 if (key < list[split]) then 371 399 binarySearch[\T\](list[0 # split], key) 372 400 else 373 right = binarySearch[\T\](list[split: ], key)401 right = binarySearch[\T\](list[split:(|list| - 1)], key) 374 402 if right >= 0 then right + split 375 403 else right - split end trunk/Library/incomplete/SkipTreeTest.fss
r2138 r2140 19 19 component SkipTreeTest 20 20 import SkipTree.{...} 21 import List.{...}21 import PureList.{...} 22 22 export Executable 23 23 24 run(args:String...):() = do 25 leaf = LeafNode[\ZZ32,ZZ32\](7,1,3) 26 println leaf.toString() 27 println leaf.find(3) 28 println leaf.find(7) 29 testList = <| 5, 10, 15, 20 |> 30 assert(binarySearch[\ZZ32\](testList, 2), -1) 31 assert(binarySearch[\ZZ32\](testList, 5), 0) 32 assert(binarySearch[\ZZ32\](testList, 7), -2) 33 assert(binarySearch[\ZZ32\](testList, 10), 1) 34 assert(binarySearch[\ZZ32\](testList, 13), -3) 35 assert(binarySearch[\ZZ32\](testList, 15), 2) 36 assert(binarySearch[\ZZ32\](testList, 17), -4) 37 assert(binarySearch[\ZZ32\](testList, 20), 3) 38 assert(binarySearch[\ZZ32\](testList, 23), -5) 24 testBinarySearch():() = do 25 testList = <| 5, 10, 15, 20 |> 26 assert(binarySearch[\ZZ32\](testList, 2), -1) 27 assert(binarySearch[\ZZ32\](testList, 5), 0) 28 assert(binarySearch[\ZZ32\](testList, 7), -2) 29 assert(binarySearch[\ZZ32\](testList, 10), 1) 30 assert(binarySearch[\ZZ32\](testList, 13), -3) 31 assert(binarySearch[\ZZ32\](testList, 15), 2) 32 assert(binarySearch[\ZZ32\](testList, 17), -4) 33 assert(binarySearch[\ZZ32\](testList, 20), 3) 34 assert(binarySearch[\ZZ32\](testList, 23), -5) 35 end 39 36 40 println leaf.insert(5,2,4).toString() 41 foo = leaf.insert(5,2,3) 42 println foo.toString() 43 foo.verify(); 44 45 (** tree = SkipTree[\ZZ32,ZZ32\](Just[\Node[\ZZ32,ZZ32\]\](leaf)) *) 37 testLeafInsert1():() = do 38 a = LeafNode[\ZZ32,String\](7,"foo",3) 39 observed = a.insert(5, "bar", 2) 40 41 keys = <| 7 |> 42 values = <| "foo" |> 43 children = <|[\Maybe[\Node[\ZZ32,String\]\]\] 44 Just[\Node[\ZZ32,String\]\](LeafNode[\ZZ32,String\](5,"bar",2)), 45 Nothing[\Node[\ZZ32,String\]\] |> 46 47 expected = Node[\ZZ32,String\](keys,values,children,3) 48 49 assert(observed,expected) 50 51 end 52 53 testLeafInsert2():() = do 54 a = LeafNode[\ZZ32,String\](7,"foo",3) 55 observed = a.insert(5, "bar", 3) 56 57 keys = <| 5,7 |> 58 values = <| "bar","foo" |> 59 children = <|[\Maybe[\Node[\ZZ32,String\]\]\] 60 Nothing[\Node[\ZZ32,String\]\], 61 Nothing[\Node[\ZZ32,String\]\], 62 Nothing[\Node[\ZZ32,String\]\] |> 63 64 expected = Node[\ZZ32,String\](keys,values,children,3) 65 66 assert(observed,expected) 67 68 end 69 70 testLeafInsert3():() = do 71 a = LeafNode[\ZZ32,String\](7,"foo",3) 72 observed = a.insert(5, "bar", 4) 73 74 keys = <| 5 |> 75 values = <| "bar" |> 76 children = <|[\Maybe[\Node[\ZZ32,String\]\]\] 77 Nothing[\Node[\ZZ32,String\]\], 78 Just[\Node[\ZZ32,String\]\](LeafNode[\ZZ32,String\](7,"foo",3)) |> 79 80 81 expected = Node[\ZZ32,String\](keys,values,children,4) 82 83 assert(observed,expected) 84 85 end 46 86 47 87 48 88 89 testProbabilisticSkipTreeInsert():() = do 90 for i <- 1 # 4 do 91 tree:SkipTree[\ZZ32,ZZ32\] := EmptySkipTree[\ZZ32,ZZ32\] 92 for j <- seq(1 # narrow(|\ random(64) /|)) do 93 newkey = narrow(|\ random(1024) /|) 94 newvalue = newkey 95 oldvalue = tree.find(newkey) 96 newTree = tree.insert(newkey, newvalue) 97 newTree.verify() 98 if oldvalue.isEmpty() AND (|tree| + 1 =/= |newTree|) then 99 fail("Skip Tree has not grown on attempt to insert a new key!") 100 elif NOT oldvalue.isEmpty() AND (|tree| =/= |newTree|) then 101 fail("Skip Tree has grown on attempt to insert an existing key!") 102 end 103 tree := newTree 104 end 105 end 106 end 49 107 50 end (* run(args:String...):() *) 108 109 run(args:String...):() = do 110 testBinarySearch() 111 testLeafInsert1() 112 testLeafInsert2() 113 testLeafInsert3() 114 testProbabilisticSkipTreeInsert() 115 116 117 end 51 118 52 119 end (* component SkipTreeTest *)
Download in other formats:
Powered by Trac 0.10.3
By Edgewall Software.Visit the Trac open source project at
http://trac.edgewall.org/
