| 1 | (****************************************************************************** |
|---|
| 2 | Copyright 2009 Sun Microsystems, Inc., |
|---|
| 3 | 4150 Network Circle, Santa Clara, California 95054, U.S.A. |
|---|
| 4 | All rights reserved. |
|---|
| 5 | |
|---|
| 6 | U.S. Government Rights - Commercial software. |
|---|
| 7 | Government users are subject to the Sun Microsystems, Inc. standard |
|---|
| 8 | license agreement and applicable provisions of the FAR and its supplements. |
|---|
| 9 | |
|---|
| 10 | Use is subject to license terms. |
|---|
| 11 | |
|---|
| 12 | This distribution may include materials developed by third parties. |
|---|
| 13 | |
|---|
| 14 | Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered |
|---|
| 15 | trademarks of Sun Microsystems, Inc. in the U.S. and other countries. |
|---|
| 16 | ******************************************************************************) |
|---|
| 17 | |
|---|
| 18 | (****************************************************************************** |
|---|
| 19 | |
|---|
| 20 | Prefix trees, aka Tries: implementing Sets; purely functional |
|---|
| 21 | |
|---|
| 22 | PrefixSet[\E,F\] is the type of sets where F is a zero-indexed data type storing elements of type E, supporting an operator addLeft. Indexing gives lexicographic ordering. |
|---|
| 23 | |
|---|
| 24 | At present F must be a subtype of List[\E\] (where List is defined as in List.fss). |
|---|
| 25 | |
|---|
| 26 | Future improvements: |
|---|
| 27 | |
|---|
| 28 | - When the standard collection trait hierarchy is done, we can make this code work more pleasantly and in more generality: |
|---|
| 29 | - we want F to be any type modelling List[\E\] |
|---|
| 30 | - we could demand that PrefixSet[\E,F\] model Set[\F\]. |
|---|
| 31 | - we could vary the indexing data structure for each node. For some prefix trees, it would be best to implement their children as an array. If we are indexing by lists of booleans, we would want an ad-hoc indexing structure whose lookup algorithm is an "if". |
|---|
| 32 | |
|---|
| 33 | - It would be nice to implement efficient indexing for PrefixSet. This is apparently impossible, if we are to base it on the existing Map.fss. We would need a variant of Map.fss, which disambiguates references to the number of nodes of a binary tree (which is an internal notion) and the number of elements stored (which is an external notion). Each node of a map, since it represents a whole prefix tree, can contribute many indices, not just one. |
|---|
| 34 | |
|---|
| 35 | *****************************************************************************) |
|---|
| 36 | |
|---|
| 37 | component PrefixSet |
|---|
| 38 | import Containment.{...} |
|---|
| 39 | import CovariantCollection.{...} |
|---|
| 40 | import List.{...} |
|---|
| 41 | import Map.{...} except { opr BIG UNION, opr BIG INTERSECTION, opr BIG SYMDIFF } |
|---|
| 42 | export PrefixSet |
|---|
| 43 | |
|---|
| 44 | |
|---|
| 45 | |
|---|
| 46 | |
|---|
| 47 | |
|---|
| 48 | trait PrefixSet[\E extends StandardTotalOrder[\E\], F extends List[\E\]\] |
|---|
| 49 | extends ContainmentGenerator[\F,PrefixSet[\E,F\]\] |
|---|
| 50 | |
|---|
| 51 | getter indexValuePairs():ZeroIndexed[\(ZZ32,F)\] = |
|---|
| 52 | IndexValuePrefixSetGenerator[\E,F\](self) |
|---|
| 53 | |
|---|
| 54 | getter asString():String = "{/" || (", ".join[\F\](self)) || "/}" |
|---|
| 55 | |
|---|
| 56 | getter size():ZZ32 |
|---|
| 57 | |
|---|
| 58 | getter isEmpty():Boolean = (NOT isMember()) AND children().isEmpty |
|---|
| 59 | |
|---|
| 60 | isMember():Boolean |
|---|
| 61 | children():Map[\E,PrefixSet[\E,F\]\] |
|---|
| 62 | |
|---|
| 63 | prefixGenerate[\R\](prefix:F, r:Reduction[\R\], body: F->R):R = do |
|---|
| 64 | t:R = children().generate[\R\](r, fn (k,v) => v.prefixGenerate[\R\](prefix.addRight(k),r,body)) |
|---|
| 65 | if isMember() then |
|---|
| 66 | r.join(body(prefix), t) |
|---|
| 67 | else |
|---|
| 68 | t |
|---|
| 69 | end |
|---|
| 70 | end |
|---|
| 71 | generate[\R\](r: Reduction[\R\], body:F->R):R = prefixGenerate[\R\](<|[\E\] |>, r, body) |
|---|
| 72 | |
|---|
| 73 | prefixSeqgen[\R\](prefix:F, r: Reduction[\R\], body: F->R):R = do |
|---|
| 74 | t:R = children().seqgen[\R\](r, fn (k,v) => v.prefixSeqgen[\R\](prefix.addRight(k),r,body)) |
|---|
| 75 | if isMember() then |
|---|
| 76 | r.join(body(prefix),t) |
|---|
| 77 | else |
|---|
| 78 | t |
|---|
| 79 | end |
|---|
| 80 | end |
|---|
| 81 | seqgen[\R\](r: Reduction[\R\], body: F->R):R = prefixSeqgen[\R\](<|[\E\] |>, r, body) |
|---|
| 82 | |
|---|
| 83 | seq(self): SequentialGenerator[\F\] = SeqPrefixSetGenerator[\E,F\](self) |
|---|
| 84 | |
|---|
| 85 | opr IN(x:F, self):Boolean = do |
|---|
| 86 | if (h,t) <- x.extractLeft() then |
|---|
| 87 | if z <- (children().member(h)) then |
|---|
| 88 | t IN z |
|---|
| 89 | else |
|---|
| 90 | false |
|---|
| 91 | end |
|---|
| 92 | else |
|---|
| 93 | isMember() |
|---|
| 94 | end |
|---|
| 95 | end |
|---|
| 96 | |
|---|
| 97 | |
|---|
| 98 | add(x:F): PrefixSet[\E,F\] = do |
|---|
| 99 | if (h,t) <- x.extractLeft() then |
|---|
| 100 | f(z:Maybe[\PrefixSet[\E,F\]\]):Maybe[\PrefixSet[\E,F\]\] = do |
|---|
| 101 | if a <- z then |
|---|
| 102 | Just[\PrefixSet[\E,F\]\](a.add(t)) |
|---|
| 103 | else |
|---|
| 104 | Just[\PrefixSet[\E,F\]\](emptyPrefixSet[\E,F\]().add(t)) |
|---|
| 105 | end |
|---|
| 106 | end |
|---|
| 107 | fastPrefixSet[\E,F\](isMember(),children().updateWith(f, h)) |
|---|
| 108 | else |
|---|
| 109 | fastPrefixSet[\E,F\](true,children()) |
|---|
| 110 | end |
|---|
| 111 | end |
|---|
| 112 | |
|---|
| 113 | |
|---|
| 114 | delete(x:F): PrefixSet[\E,F\] = do |
|---|
| 115 | if (h,t) <- x.extractLeft() then |
|---|
| 116 | z = children().member(h) |
|---|
| 117 | if a <- z then |
|---|
| 118 | prefixSet[\E,F\](isMember(), children().update(h,a.delete(t))) |
|---|
| 119 | else |
|---|
| 120 | self |
|---|
| 121 | end |
|---|
| 122 | else |
|---|
| 123 | prefixSet[\E,F\](false,children()) |
|---|
| 124 | end |
|---|
| 125 | end |
|---|
| 126 | |
|---|
| 127 | |
|---|
| 128 | opr =(self, s2:PrefixSet[\E,F\]):Boolean = (isMember() = s2.isMember()) AND (children() = s2.children()) |
|---|
| 129 | |
|---|
| 130 | |
|---|
| 131 | (* Expensive indexing code begins here *) |
|---|
| 132 | |
|---|
| 133 | opr[i:ZZ32]:F = do |
|---|
| 134 | if isMember() AND (i = 0) then |
|---|
| 135 | <|[\E\] |> |
|---|
| 136 | else |
|---|
| 137 | var c:ZZ32 |
|---|
| 138 | c := (if isMember() then 1 else 0 end) |
|---|
| 139 | label Search |
|---|
| 140 | for (k,v) <- seq(children()) do |
|---|
| 141 | s = v.size |
|---|
| 142 | if c + s > i then |
|---|
| 143 | exit Search with v[i-c].addLeft(k) |
|---|
| 144 | else |
|---|
| 145 | c += s |
|---|
| 146 | end |
|---|
| 147 | end |
|---|
| 148 | throw NotFound |
|---|
| 149 | end Search |
|---|
| 150 | end |
|---|
| 151 | end |
|---|
| 152 | |
|---|
| 153 | indexOf(x:F):Maybe[\ZZ32\] = do |
|---|
| 154 | if (x IN self) then |
|---|
| 155 | Just[\ZZ32\](self.indexOfMember(x)) |
|---|
| 156 | else |
|---|
| 157 | Nothing[\ZZ32\] |
|---|
| 158 | end |
|---|
| 159 | end |
|---|
| 160 | |
|---|
| 161 | indexOfMember(x:F):ZZ32 = do |
|---|
| 162 | if (h,t) <- x.extractLeft() then |
|---|
| 163 | label Search |
|---|
| 164 | var c:ZZ32 = (if isMember() then 1 else 0 end) |
|---|
| 165 | for (k,v) <- seq(children()) do |
|---|
| 166 | if (k=h) then |
|---|
| 167 | exit Search with c+v.indexOfMember(t) |
|---|
| 168 | else |
|---|
| 169 | c += v.size |
|---|
| 170 | end |
|---|
| 171 | end |
|---|
| 172 | end Search |
|---|
| 173 | else |
|---|
| 174 | 0 |
|---|
| 175 | end |
|---|
| 176 | end |
|---|
| 177 | |
|---|
| 178 | (** Split at index x, meaning left result has size = x or |
|---|
| 179 | left result has size < x and right result is empty. **) |
|---|
| 180 | splitIndex(x:ZZ32):(PrefixSet[\E,F\],PrefixSet[\E,F\]) = do |
|---|
| 181 | (a,_,b) = splitAt(self[x]) |
|---|
| 182 | (a,b.add(x)) |
|---|
| 183 | end |
|---|
| 184 | |
|---|
| 185 | prefixivgen[\R\](prefix:F, i0:ZZ32, r: Reduction[\R\], body: (ZZ32,F)->R): R = do |
|---|
| 186 | var i:ZZ32 |
|---|
| 187 | var a:R |
|---|
| 188 | if isMember() then |
|---|
| 189 | a := body(i0,prefix) |
|---|
| 190 | i := i0 + 1 |
|---|
| 191 | else |
|---|
| 192 | a := r.empty() |
|---|
| 193 | i := i0 |
|---|
| 194 | end |
|---|
| 195 | for (l,x) <- seq(children()) do |
|---|
| 196 | a := r.join(a, x.prefixivgen[\R\](prefix.addRight(l), i, r, body)) |
|---|
| 197 | i := i + |x| |
|---|
| 198 | end |
|---|
| 199 | a |
|---|
| 200 | end |
|---|
| 201 | |
|---|
| 202 | ivgen[\R\](i0:ZZ32, r: Reduction[\R\], body: (ZZ32,F)->R): R = prefixivgen[\R\](<|[\E\] |>, i0, r, body) |
|---|
| 203 | (* Expensive indexing code ends here *) |
|---|
| 204 | |
|---|
| 205 | minimum():Maybe[\F\] = if self.isEmpty then Nothing[\F\] else Just[\F\] getMinimum() end |
|---|
| 206 | getMinimum():F throws NotFound = do |
|---|
| 207 | if isMember() then |
|---|
| 208 | <|[\E\] |> |
|---|
| 209 | elif (k,v) <- children().minimum() then |
|---|
| 210 | v.getMinimum().addLeft(k) |
|---|
| 211 | else |
|---|
| 212 | throw NotFound |
|---|
| 213 | end |
|---|
| 214 | end |
|---|
| 215 | |
|---|
| 216 | maximum():Maybe[\F\] = if self.isEmpty then Nothing[\F\] else Just[\F\] getMaximum() end |
|---|
| 217 | getMaximum():F throws NotFound = do |
|---|
| 218 | if (k,v) <- children().maximum() then |
|---|
| 219 | v.getMaximum().addLeft(k) |
|---|
| 220 | else |
|---|
| 221 | <|[\E\] |> |
|---|
| 222 | end |
|---|
| 223 | end |
|---|
| 224 | |
|---|
| 225 | deleteMinimum():PrefixSet[\E,F\] = |
|---|
| 226 | if (_, res) <- extractMinimum() then res else self end |
|---|
| 227 | deleteMaximum():PrefixSet[\E,F\] = |
|---|
| 228 | if (_, res) <- extractMaximum() then res else self end |
|---|
| 229 | |
|---|
| 230 | extractMinimum():Maybe[\(F, PrefixSet[\E,F\])\] = do |
|---|
| 231 | if isMember() then |
|---|
| 232 | Just[\(F, PrefixSet[\E,F\])\](<|[\E\] |>, fastPrefixSet[\E,F\](false, children())) |
|---|
| 233 | elif (k,v,r) <- children().extractMinimum() then |
|---|
| 234 | (m,s) = v.extractMinimum().get |
|---|
| 235 | Just[\(F, PrefixSet[\E,F\])\](m.addLeft(k), prefixSet[\E,F\](false, r.add(k,s))) |
|---|
| 236 | else |
|---|
| 237 | Nothing[\(F, PrefixSet[\E,F\])\] |
|---|
| 238 | end |
|---|
| 239 | end |
|---|
| 240 | |
|---|
| 241 | extractMaximum():Maybe[\(F, PrefixSet[\E,F\])\] = do |
|---|
| 242 | if (k,v,r) <- children().extractMaximum() then |
|---|
| 243 | (m,s) = v.extractMaximum().get |
|---|
| 244 | Just[\(F, PrefixSet[\E,F\])\](m.addLeft(k), prefixSet[\E,F\](isMember(), r.add(k,s))) |
|---|
| 245 | elif isMember() then |
|---|
| 246 | Just[\(F, PrefixSet[\E,F\])\](<|[\E\] |>, emptyPrefixSet[\E,F\]()) |
|---|
| 247 | else |
|---|
| 248 | Nothing[\(F, PrefixSet[\E,F\])\] |
|---|
| 249 | end |
|---|
| 250 | end |
|---|
| 251 | |
|---|
| 252 | |
|---|
| 253 | |
|---|
| 254 | (* Concatenation: assumes that all the values on the right are greater than all those on the left. *) |
|---|
| 255 | concat(s2:PrefixSet[\E,F\]):PrefixSet[\E,F\] = do |
|---|
| 256 | leftm = children().extractMaximum() |
|---|
| 257 | rightm = s2.children().extractMinimum() |
|---|
| 258 | if (leftmaxkey,leftmaxval,left) <- leftm then |
|---|
| 259 | if (rightminkey,rightminval,right) <- rightm then |
|---|
| 260 | if leftmaxkey<rightminkey then |
|---|
| 261 | fastPrefixSet[\E,F\](isMember() OR s2.isMember(), children().concat(s2.children())) |
|---|
| 262 | else |
|---|
| 263 | fastPrefixSet[\E,F\](isMember() OR s2.isMember(), left.concat3(leftmaxkey, leftmaxval.concat(rightminval), right)) |
|---|
| 264 | end |
|---|
| 265 | else |
|---|
| 266 | self |
|---|
| 267 | end |
|---|
| 268 | else |
|---|
| 269 | s2 |
|---|
| 270 | end |
|---|
| 271 | end |
|---|
| 272 | |
|---|
| 273 | concat3(v:F, s2:PrefixSet[\E,F\]):PrefixSet[\E,F\] = do |
|---|
| 274 | leftm = children().extractMaximum() |
|---|
| 275 | rightm = s2.children().extractMinimum() |
|---|
| 276 | if NOT leftm.holds then |
|---|
| 277 | s2 |
|---|
| 278 | elif NOT rightm.holds then |
|---|
| 279 | self |
|---|
| 280 | else |
|---|
| 281 | (leftmaxkey,leftmaxval,left) = leftm.get |
|---|
| 282 | (rightminkey,rightminval,right) = rightm.get |
|---|
| 283 | |
|---|
| 284 | if (|v| = 0) then |
|---|
| 285 | if leftmaxkey<rightminkey then |
|---|
| 286 | fastPrefixSet[\E,F\](true, children().concat(s2.children())) |
|---|
| 287 | else |
|---|
| 288 | fastPrefixSet[\E,F\](isMember() OR s2.isMember(), left.concat3(leftmaxkey, leftmaxval.concat(rightminval), right)) |
|---|
| 289 | end |
|---|
| 290 | else |
|---|
| 291 | (midh, midt) = v.extractLeft() |
|---|
| 292 | if leftmaxkey<midh<rightminkey then |
|---|
| 293 | fastPrefixSet[\E,F\](isMember() OR s2.isMember(), children().concat3(midh,singletonPrefixSet(midt),s2.children())) |
|---|
| 294 | elif leftmaxkey=midh<rightminkey then |
|---|
| 295 | fastPrefixSet[\E,F\](isMember() OR s2.isMember(), left.concat3(leftmaxkey,leftmaxval.concat(singletonPrefixSet(midt)),s2.children())) |
|---|
| 296 | elif leftmaxkey<midh=rightminkey then |
|---|
| 297 | fastPrefixSet[\E,F\](isMember() OR s2.isMember(),children().concat3(rightminkey,singletonPrefixSet(midt).concat(rightminval),right)) |
|---|
| 298 | else (*) leftmaxkey=midh=rightminkey |
|---|
| 299 | fastPrefixSet[\E,F\](isMember() OR s2.isMember(),left.concat3(leftmaxkey,leftmaxval.concat3(midt,rightminval),right)) |
|---|
| 300 | end |
|---|
| 301 | end |
|---|
| 302 | end |
|---|
| 303 | end |
|---|
| 304 | |
|---|
| 305 | (* Could we replace some of the prefixSet calls with fastPrefixSet? *) |
|---|
| 306 | splitAt(x:F):(PrefixSet[\E,F\],Boolean,PrefixSet[\E,F\]) = do |
|---|
| 307 | if (h,t) <- x.extractLeft() then |
|---|
| 308 | (l,m,r) = children().splitAt(h) |
|---|
| 309 | if a <- m then |
|---|
| 310 | (lb,b,rb) = a.splitAt(t) |
|---|
| 311 | (prefixSet(isMember(), l.add(a,lb)), b, prefixSet(false, r.add(a,rb))) |
|---|
| 312 | else |
|---|
| 313 | (prefixSet(isMember(), l), false, prefixSet(isMember(), r)) |
|---|
| 314 | end |
|---|
| 315 | else |
|---|
| 316 | (emptyPrefixSet[\E,F\](), isMember(), fastPrefixSet(false, children())) |
|---|
| 317 | end |
|---|
| 318 | end |
|---|
| 319 | |
|---|
| 320 | |
|---|
| 321 | opr SUBSETEQ(self, other:PrefixSet[\E,F\]): Boolean = (other.isMember() OR NOT isMember()) AND (BIG AND[(k,v) <- children()] (k IN other.children()) AND (children()[k] SUBSETEQ (other.children())[k])) |
|---|
| 322 | opr SUBSET(self, other:PrefixSet[\E,F\]): Boolean = (NOT (self = other)) AND (self SUBSETEQ other) |
|---|
| 323 | |
|---|
| 324 | opr SUPSETEQ(self, other:PrefixSet[\E,F\]): Boolean = other SUBSETEQ self |
|---|
| 325 | opr SUPSET(self, other:PrefixSet[\E,F\]): Boolean = other SUBSET self |
|---|
| 326 | |
|---|
| 327 | opr SETCMP(self, other:PrefixSet[\E,F\]): Comparison = do |
|---|
| 328 | if (self = other) then |
|---|
| 329 | EqualTo |
|---|
| 330 | elif (self SUBSETEQ other) then |
|---|
| 331 | LessThan |
|---|
| 332 | elif (other SUBSETEQ self) then |
|---|
| 333 | GreaterThan |
|---|
| 334 | else |
|---|
| 335 | Unordered |
|---|
| 336 | end |
|---|
| 337 | end |
|---|
| 338 | |
|---|
| 339 | |
|---|
| 340 | opr |self|:ZZ32 = self.size |
|---|
| 341 | |
|---|
| 342 | opr UNION(self,s2:PrefixSet[\E,F\]):PrefixSet[\E,F\] = do |
|---|
| 343 | ifOne(k:E, v:PrefixSet[\E,F\]):Maybe[\PrefixSet[\E,F\]\] = Just[\PrefixSet[\E,F\]\](v) |
|---|
| 344 | mapOne(a:Map[\E,PrefixSet[\E,F\]\]):Map[\E,PrefixSet[\E,F\]\] = a |
|---|
| 345 | ifBoth(k:E, u:PrefixSet[\E,F\], v:PrefixSet[\E,F\]):Maybe[\PrefixSet[\E,F\]\] = Just[\PrefixSet[\E,F\]\](u UNION v) |
|---|
| 346 | fastPrefixSet[\E,F\](isMember() OR s2.isMember(), children().combine[\PrefixSet[\E,F\],PrefixSet[\E,F\]\](ifBoth,ifOne,ifOne,mapOne,mapOne,s2.children())) |
|---|
| 347 | end |
|---|
| 348 | |
|---|
| 349 | opr INTERSECTION(self,s2:PrefixSet[\E,F\]):PrefixSet[\E,F\] = do |
|---|
| 350 | ifOne(k:E, v:PrefixSet[\E,F\]):Maybe[\PrefixSet[\E,F\]\] = Nothing[\PrefixSet[\E,F\]\] |
|---|
| 351 | mapOne(a:Map[\E,PrefixSet[\E,F\]\]):Map[\E,PrefixSet[\E,F\]\] = mapping[\E,PrefixSet[\E,F\]\]() |
|---|
| 352 | ifBoth(k:E, u:PrefixSet[\E,F\], v:PrefixSet[\E,F\]):Maybe[\PrefixSet[\E,F\]\] = Just[\PrefixSet[\E,F\]\](u INTERSECTION v) |
|---|
| 353 | prefixSet[\E,F\](isMember() AND s2.isMember(), children().combine[\PrefixSet[\E,F\],PrefixSet[\E,F\]\](ifBoth,ifOne,ifOne,mapOne,mapOne,s2.children())) |
|---|
| 354 | end |
|---|
| 355 | |
|---|
| 356 | opr SYMDIFF(self,s2:PrefixSet[\E,F\]):PrefixSet[\E,F\] = do |
|---|
| 357 | ifOne(k:E, v:PrefixSet[\E,F\]):Maybe[\PrefixSet[\E,F\]\] = Just[\PrefixSet[\E,F\]\](v) |
|---|
| 358 | mapOne(a:Map[\E,PrefixSet[\E,F\]\]):Map[\E,PrefixSet[\E,F\]\] = a |
|---|
| 359 | ifBoth(k:E, u:PrefixSet[\E,F\], v:PrefixSet[\E,F\]):Maybe[\PrefixSet[\E,F\]\] = Just[\PrefixSet[\E,F\]\](u SYMDIFF v) |
|---|
| 360 | prefixSet[\E,F\](isMember() XOR s2.isMember(), children().combine[\PrefixSet[\E,F\],PrefixSet[\E,F\]\](ifBoth,ifOne,ifOne,mapOne,mapOne,s2.children())) |
|---|
| 361 | end |
|---|
| 362 | |
|---|
| 363 | opr DIFFERENCE(self,s2:PrefixSet[\E,F\]):PrefixSet[\E,F\] = do |
|---|
| 364 | ifThis(k:E, v:PrefixSet[\E,F\]):Maybe[\PrefixSet[\E,F\]\] = Just[\PrefixSet[\E,F\]\](v) |
|---|
| 365 | mapThis(a:Map[\E,PrefixSet[\E,F\]\]):Map[\E,PrefixSet[\E,F\]\] = a |
|---|
| 366 | ifThat(k:E, v:PrefixSet[\E,F\]):Maybe[\PrefixSet[\E,F\]\] = Nothing[\PrefixSet[\E,F\]\] |
|---|
| 367 | mapThat(a:Map[\E,PrefixSet[\E,F\]\]):Map[\E,PrefixSet[\E,F\]\] = mapping[\E,PrefixSet[\E,F\]\]() |
|---|
| 368 | ifBoth(k:E, u:PrefixSet[\E,F\], v:PrefixSet[\E,F\]):Maybe[\PrefixSet[\E,F\]\] = Just[\PrefixSet[\E,F\]\](u DIFFERENCE v) |
|---|
| 369 | prefixSet[\E,F\](isMember() AND NOT s2.isMember(), children().combine[\PrefixSet[\E,F\],PrefixSet[\E,F\]\](ifBoth,ifThis,ifThat,mapThis,mapThat,s2.children())) |
|---|
| 370 | end |
|---|
| 371 | |
|---|
| 372 | |
|---|
| 373 | end |
|---|
| 374 | |
|---|
| 375 | |
|---|
| 376 | |
|---|
| 377 | (* A PrefixSet with given children: 'unsafe' as it assumes it is not given any useless tree structure *) |
|---|
| 378 | object fastPrefixSet[\E extends StandardTotalOrder[\E\], F extends List[\E\]\](v:Boolean,c:Map[\E,PrefixSet[\E,F\]\]) extends PrefixSet[\E,F\] |
|---|
| 379 | getter size():ZZ32 = fixedsize |
|---|
| 380 | fixedsize:ZZ32 = (if v then 1 else 0 end) + (SUM[(k,a) <- c] a.size) |
|---|
| 381 | isMember():Boolean = v |
|---|
| 382 | children():Map[\E,PrefixSet[\E,F\]\] = c |
|---|
| 383 | end |
|---|
| 384 | |
|---|
| 385 | |
|---|
| 386 | (* A PrefixSet with given children: 'safe' as it will remove any useless tree structure *) |
|---|
| 387 | prefixSet[\E extends StandardTotalOrder[\E\], F extends List[\E\]\](v:Boolean, c:Map[\E,PrefixSet[\E,F\]\]):PrefixSet[\E,F\] = fastPrefixSet[\E,F\](v, {[\E,PrefixSet[\E,F\]\] k |-> l | (k,l)<-c, l.size =/= 0 }) |
|---|
| 388 | |
|---|
| 389 | |
|---|
| 390 | emptyPrefixSet[\E extends StandardTotalOrder[\E\], F extends List[\E\]\]():PrefixSet[\E,F\] = fastPrefixSet[\E,F\](false,mapping[\E,PrefixSet[\E,F\]\]()) |
|---|
| 391 | |
|---|
| 392 | |
|---|
| 393 | singletonPrefixSet[\E extends StandardTotalOrder[\E\], F extends List[\E\]\](x:F):PrefixSet[\E,F\] = do |
|---|
| 394 | if (h,t) <- x.extractLeft() then |
|---|
| 395 | prefixSet[\E,F\](false, singleton[\E,PrefixSet[\E,F\]\](h,singletonPrefixSet[\E,F\](t))) |
|---|
| 396 | else |
|---|
| 397 | fastPrefixSet[\E,F\](true, mapping[\E,PrefixSet[\E,F\]\]()) |
|---|
| 398 | end |
|---|
| 399 | end |
|---|
| 400 | |
|---|
| 401 | |
|---|
| 402 | |
|---|
| 403 | |
|---|
| 404 | |
|---|
| 405 | |
|---|
| 406 | |
|---|
| 407 | |
|---|
| 408 | (* Standard generator code *) |
|---|
| 409 | |
|---|
| 410 | |
|---|
| 411 | prefixSet[\E extends StandardTotalOrder[\E\], F extends List[\E\]\](g:Generator[\F\]):PrefixSet[\E,F\] = g.generate[\PrefixSet[\E,F\]\](Union[\E,F\], singletonPrefixSet[\E,F\]) |
|---|
| 412 | |
|---|
| 413 | opr {/[\E extends StandardTotalOrder[\E\], F extends List[\E\]\] fs:F... /}: PrefixSet[\E,F\] = prefixSet[\E,F\](fs) |
|---|
| 414 | |
|---|
| 415 | opr BIG {/[\E extends StandardTotalOrder[\E\], F extends List[\E\]\]/} : Comprehension[\F,PrefixSet[\E,F\],AnyCovColl,AnyCovColl\] = |
|---|
| 416 | covariantCompr[\F,PrefixSet[\E,F\]\](fn cc => prefixSet(cc.toImmutableArray())) |
|---|
| 417 | |
|---|
| 418 | opr BIG {/[\E extends StandardTotalOrder[\E\], F extends List[\E\]\] g:Generator[\F\]/}:PrefixSet[\E,F\] = |
|---|
| 419 | __bigOperatorSugar[\F,PrefixSet[\E,F\],AnyCovColl,AnyCovColl\](BIG {/[\E,F\]/}(), g) |
|---|
| 420 | |
|---|
| 421 | |
|---|
| 422 | |
|---|
| 423 | (* Standard union & intersection code *) |
|---|
| 424 | |
|---|
| 425 | object Union[\E extends StandardTotalOrder[\E\], F extends List[\E\]\] extends CommutativeMonoidReduction[\PrefixSet[\E,F\]\] |
|---|
| 426 | getter asString(): String = "Union reduction" |
|---|
| 427 | empty():PrefixSet[\E,F\] = emptyPrefixSet[\E,F\]() |
|---|
| 428 | join(a:PrefixSet[\E,F\], b:PrefixSet[\E,F\]): PrefixSet[\E,F\] = a UNION b |
|---|
| 429 | end |
|---|
| 430 | |
|---|
| 431 | opr BIG UNION[\E extends StandardTotalOrder[\E\], F extends List[\E\]\](): BigReduction[\PrefixSet[\E,F\],PrefixSet[\E,F\]\] = |
|---|
| 432 | BigReduction[\PrefixSet[\E,F\],PrefixSet[\E,F\]\](Union[\E,F\]) |
|---|
| 433 | |
|---|
| 434 | opr BIG UNION[\E extends StandardTotalOrder[\E\], F extends List[\E\]\](g: Generator[\PrefixSet[\E,F\]\]):PrefixSet[\E,F\] = |
|---|
| 435 | __bigOperatorSugar[\PrefixSet[\E,F\],PrefixSet[\E,F\],PrefixSet[\E,F\],PrefixSet[\E,F\]\](BIG UNION[\PrefixSet[\E,F\]\](), g) |
|---|
| 436 | |
|---|
| 437 | |
|---|
| 438 | |
|---|
| 439 | |
|---|
| 440 | object Intersection[\E extends StandardTotalOrder[\E\], F extends List[\E\]\] extends CommutativeMonoidReduction[\PrefixSet[\E,F\]\] |
|---|
| 441 | getter asString(): String = "Intersection reduction" |
|---|
| 442 | empty():PrefixSet[\E,F\] = emptyPrefixSet[\E,F\]() |
|---|
| 443 | join(a:PrefixSet[\E,F\], b:PrefixSet[\E,F\]): PrefixSet[\E,F\] = a INTERSECTION b |
|---|
| 444 | end |
|---|
| 445 | |
|---|
| 446 | opr BIG INTERSECTION[\E extends StandardTotalOrder[\E\], F extends List[\E\]\](): BigReduction[\PrefixSet[\E,F\],PrefixSet[\E,F\]\] = |
|---|
| 447 | BigReduction[\PrefixSet[\E,F\],PrefixSet[\E,F\]\](Intersection[\E,F\]) |
|---|
| 448 | |
|---|
| 449 | opr BIG INTERSECTION[\E extends StandardTotalOrder[\E\], F extends List[\E\]\](g: Generator[\PrefixSet[\E,F\]\]):PrefixSet[\E,F\] = |
|---|
| 450 | __bigOperatorSugar[\PrefixSet[\E,F\],PrefixSet[\E,F\],PrefixSet[\E,F\],PrefixSet[\E,F\]\](BIG INTERSECTION[\PrefixSet[\E,F\]\](), g) |
|---|
| 451 | |
|---|
| 452 | |
|---|
| 453 | |
|---|
| 454 | |
|---|
| 455 | object SymmetricDifference[\E extends StandardTotalOrder[\E\], F extends List[\E\]\] extends CommutativeMonoidReduction[\PrefixSet[\E,F\]\] |
|---|
| 456 | getter asString(): String = "Symmetric difference reduction" |
|---|
| 457 | empty():PrefixSet[\E,F\] = emptyPrefixSet[\E,F\]() |
|---|
| 458 | join(a:PrefixSet[\E,F\], b:PrefixSet[\E,F\]): PrefixSet[\E,F\] = a SYMDIFF b |
|---|
| 459 | end |
|---|
| 460 | |
|---|
| 461 | opr BIG SYMDIFF[\E extends StandardTotalOrder[\E\], F extends List[\E\]\](): BigReduction[\PrefixSet[\E,F\],PrefixSet[\E,F\]\] = |
|---|
| 462 | BigReduction[\PrefixSet[\E,F\],PrefixSet[\E,F\]\](SymmetricDifference[\E,F\]) |
|---|
| 463 | |
|---|
| 464 | opr BIG SYMDIFF[\E extends StandardTotalOrder[\E\], F extends List[\E\]\](g: Generator[\PrefixSet[\E,F\]\]):PrefixSet[\E,F\] = |
|---|
| 465 | __bigOperatorSugar[\PrefixSet[\E,F\],PrefixSet[\E,F\],PrefixSet[\E,F\],PrefixSet[\E,F\]\](BIG SYMDIFF[\PrefixSet[\E,F\]\](), g) |
|---|
| 466 | |
|---|
| 467 | |
|---|
| 468 | |
|---|
| 469 | |
|---|
| 470 | |
|---|
| 471 | |
|---|
| 472 | value object SeqPrefixSetGenerator[\E extends StandardTotalOrder[\E\],F extends List[\E\]\](s: PrefixSet[\E,F\]) |
|---|
| 473 | extends SequentialGenerator[\F\] |
|---|
| 474 | getter size():ZZ32 = |s| |
|---|
| 475 | getter isEmpty():Boolean = s.isEmpty |
|---|
| 476 | opr |self|: ZZ32 = |s| |
|---|
| 477 | generate[\R\](r: Reduction[\R\], body: F->R): R = |
|---|
| 478 | s.seqgen[\R\](r,body) |
|---|
| 479 | end |
|---|
| 480 | |
|---|
| 481 | value object IndexValuePrefixSetGenerator[\E extends StandardTotalOrder[\E\],F extends List[\E\]\](s: PrefixSet[\E,F\]) |
|---|
| 482 | extends ZeroIndexed[\(ZZ32,F)\] |
|---|
| 483 | getter size():ZZ32 = |s| |
|---|
| 484 | getter indices(): Generator[\ZZ32\] = s.indices() |
|---|
| 485 | getter isEmpty(): Boolean = s.isEmpty |
|---|
| 486 | opr |self|:ZZ32 = |s| |
|---|
| 487 | generate[\R\](r: Reduction[\R\], body: (ZZ32,F)->R): R = s.ivgen[\R\](0,r,body) |
|---|
| 488 | opr[ x:ZZ32 ]:(ZZ32,E) = (x,s[x]) |
|---|
| 489 | opr[ r:Range[\ZZ32\] ]:ZeroIndexed[\(ZZ32,F)\] = s[r].indexValuePairs |
|---|
| 490 | indexOf(i:ZZ32,v:F):Maybe[\ZZ32\] = if s[i]=v then Just[\ZZ32\](i) else Nothing[\ZZ32\] end |
|---|
| 491 | end |
|---|
| 492 | |
|---|
| 493 | |
|---|
| 494 | end |
|---|