root/trunk/Library/Heap.fss

Revision 4130, 12.1 KB (checked in by sukyoungryu, 3 months ago)

[disambiguator] Fixed handling getters and setters in ExprDisambiguator?. Fixed libraries and tests using getters.

Line 
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
18component Heap
19export Heap
20
21(************************************************************
22 * Mergeable, pure priority queues (heaps).                 *)
23
24(** At the moment we're baking off several potential priority queue
25  implementations, based on part on some advice from "Purely
26  Functional Data Structures" by Okasaki.
27
28  * Pairing Heaps, the current default:
29    O(1) merge
30    O(lg n) amortized extractMinimum, with O(n) worst case.  The worst
31    case is proportional to the number of deferred merge operations
32    performed with the min; if you merge n entries tree-fashion rather
33    than 1 at a time you should obtain O(lg n) worst case performance
34    as well.  The heap(gen) function will follow the merge structure
35    of the underlying generator; for a well-written generator this
36    will be sufficient to give good performance.
37
38  * Lazy-esque pairing heaps (supposedly slower but actually easier in
39  some ways to implement than pairing heaps, and avoiding a potential
40  stack overflow in the latter).  These don't seem to be quite as
41  whizzy in this setting as ordinary Pairing Heaps.
42    O(lg n) merge
43    O(lg n) worst-case extractMinimum
44
45  * Splay heaps (noted as "fastest in practice", borne out by other
46    experiments).  Problem: O(n) merge operation, vs O(lg n) for
47    everything else.  If we build heaps by performing reductions over
48    a generator, with each iteration generating a few elements, this
49    will be a problem.  This is not yet implemented.
50
51   Minimum complete implementation of Heap[\K,V\]:
52     empty
53     singleton
54     isEmpty
55     extractMinimum
56     merge(Heap[\K,V\])
57 **)
58trait Heap[\K,V\] extends Generator[\(K,V)\]
59    (** Given an instance of Heap[\K,V\], get the empty Heap[\K,V\] **)
60    getter empty(): Heap[\K,V\]
61    (** Get the (key,value) pair with minimal associated key **)
62    getter minimum(): Maybe[\(K,V)\] =
63        if (k,v,_) <- extractMinimum() then
64            Just[\(K,V)\](k,v)
65        else
66            Nothing[\(K,V)\]
67        end
68    (** Check the invariants on the heap. **)
69    check(): Heap[\K,V\]
70    (** Given an instance of Heap[\K,V\], generate a singleton Heap[\K,V\] **)
71    singleton(k:K, v:V): Heap[\K,V\]
72    (** Return a heap that contains the key-value pairings in both of
73        the heaps passed in. **)
74    merge(h:Heap[\K,V\]): Heap[\K,V\]
75    (** Return a heap that contains the additional key-value pairs **)
76    insert(k:K, v:V): Heap[\K,V\] = self.merge(self.singleton[\K,V\](k,v))
77    (** Extract the (key,value) pair with minimal associated key,
78     along with a heap with that key and value pair removed. **)
79    extractMinimum(): Maybe[\(K,V,Heap[\K,V\])\]
80    (** Delete the minimum (key,value) pair (if any) from the heap,
81        and return the resulting heap. *)
82    deleteMinimum(): Heap[\K,V\] =
83        if (_,_,r) <- extractMinimum() then r else self end
84    (** We generate elements by repeated splitting.  This is fairly
85        allocation-intensive (O(n) worst case) but gives reasonable
86        parallelism. **)
87    generate[\R\](r: Reduction[\R\], body: (K,V)->R): R = do
88        go(n:ZZ32, h: Heap[\K,V\]): R =
89            if h.isEmpty then
90                r.empty
91            else
92                kvs = array[\(K,V)\](n)
93                hh : Heap[\K,V\] := h
94                i : ZZ32 := 0
95                while NOT hh.isEmpty AND i < n do
96                    (k,v,hhh) = hh.extractMinimum().get
97                    kvs.init(i,(k,v))
98                    i += 1
99                    hh := hhh
100                end
101                r.join(kvs[0#i].generate[\R\](r,body),go(n+n, hh))
102            end
103        go(8,self)
104      end
105end
106
107object HeapMerge[\K,V\](boiler: Heap[\K,V\])
108        extends CommutativeMonoidReduction[\Heap[\K,V\]\]
109    getter asString():String = "Heap merge reduction"
110    getter empty(): Heap[\K,V\] = boiler.empty
111    join(a:Heap[\K,V\], b:Heap[\K,V\]): Heap[\K,V\] = a.merge(b)
112end
113
114hm[\K,V\](boiler: Heap[\K,V\]):HeapMerge[\K,V\] = HeapMerge[\K,V\](boiler)
115
116trait Pairing[\K,V\] extends Heap[\K,V\]
117        comprises { EmptyP[\K,V\], NodeP[\K,V\] }
118    getter empty(): Pairing[\K,V\] = EmptyP[\K,V\]
119    getter asDebugString(): String
120    singleton(k:K, v:V): Pairing[\K,V\] = do
121        e = self.empty
122        NodeP[\K,V\](k,v,e,e)
123      end
124    (* emk merges a node and all its siblings. *)
125    emk(e: EmptyP[\K,V\]): Pairing[\K,V\]
126    (* ems merges a node with its left sibling, then merges that with
127       its remaining siblings. *)
128    ems(e: EmptyP[\K,V\], leftSib: NodeP[\K,V\]): NodeP[\K,V\]
129end
130
131object EmptyP[\K,V\] extends Pairing[\K,V\]
132    getter isEmpty(): Boolean = true
133    getter minimum(): Nothing[\(K,V)\] = Nothing[\(K,V)\]
134    getter asDebugString(): String = "E"
135    check(): EmptyP[\K,V\] = self
136    check(pk:K):Boolean = true
137    merge(h:Heap[\K,V\]): Heap[\K,V\] = h
138    merge(h:Pairing[\K,V\]): Pairing[\K,V\] = h
139    insert(k:K, v:V): Pairing[\K,V\] = NodeP[\K,V\](k,v,self,self)
140    extractMinimum(): Nothing[\(K,V,Pairing[\K,V\])\] = Nothing[\(K,V,Pairing[\K,V\])\]
141    emk(e: EmptyP[\K,V\]): Pairing[\K,V\] = self
142    ems(_: EmptyP[\K,V\], leftSib: NodeP[\K,V\]): NodeP[\K,V\] = leftSib
143    generate[\R\](r: Reduction[\R\], body: (K,V)->R): R = r.empty
144end
145
146object NodeP[\K,V\](k:K, v:V, sibs: Pairing[\K,V\], kids: Pairing[\K,V\])
147        extends Pairing[\K,V\]
148    getter isEmpty(): Boolean = false
149    getter minimum(): Just[\(K,V)\] = Just[\(K,V)\](k,v)
150    getter asDebugString():String = "N(" k "," v "," sibs.asDebugString "," kids.asDebugString ")"
151    check():Heap[\K,V\] = do
152        if NOT sibs.isEmpty then
153            println( //"FAIL: Non-empty sibs in:" // self.asDebugString// )
154            fail("dying")
155        end
156        if NOT kids.check(k) then
157            println( //"FAIL: heap structure violation in:" // self.asDebugString// )
158        end
159        self
160      end
161    check(pk:K):Boolean = pk <= k AND sibs.check(pk) AND kids.check(k)
162    merge(other:Heap[\K,V\]): Heap[\K,V\] = merge(pairing[\K,V\](other))
163    merge(_:Pairing[\K,V\]): Pairing[\K,V\] =
164        fail("Pairing but not NodeP/EmptyP")
165    merge(_:EmptyP[\K,V\]): Pairing[\K,V\] = self
166    merge(h:NodeP[\K,V\]): Pairing[\K,V\] = merge(self.empty,h)
167    merge(e:EmptyP[\K,V\], _:EmptyP[\K,V\]): Pairing[\K,V\] = self
168    merge(e:EmptyP[\K,V\], h:NodeP[\K,V\]): Pairing[\K,V\] =
169        if h.k <= k then
170            NodeP[\K,V\](h.k, h.v, e, NodeP[\K,V\](  k,   v, h.kids,   kids))
171        else
172            NodeP[\K,V\](  k,   v, e, NodeP[\K,V\](h.k, h.v,   kids, h.kids))
173        end
174    insert(k':K, v':V): Pairing[\K,V\] =
175        if k' <= k then (* ' *)
176            NodeP[\K,V\](k',v',self.empty,self)
177        else
178            e = self.empty
179            NodeP[\K,V\](k,v,e,NodeP[\K,V\](k',v',kids,e))
180        end
181    extractMinimum(): Just[\(K,V,Pairing[\K,V\])\] =
182        Just[\(K,V,Pairing[\K,V\])\](k,v,kids.emk(self.empty))
183(*
184    emk(e: EmptyP[\K,V\]): Pairing[\K,V\] = do
185        res : Pairing[\K,V\] = e
186        todo : Pairing[\K,V\] := self
187        while NOT todo.isEmpty do
188            (m,td) = if todo.sibs.isEmpty then
189                         (todo,e)
190                     else
191                         (todo.merge(e,todo.sibs),todo.sibs.sibs)
192                     end
193            res := m.merge(e,res)
194            todo := td
195        end
196        res
197      end
198*)
199    emk(e: EmptyP[\K,V\]): Pairing[\K,V\] = sibs.ems(e,self)
200    ems(e: EmptyP[\K,V\], leftSib: NodeP[\K,V\]): NodeP[\K,V\] =
201        merge(e,leftSib).merge(e,sibs.emk(e))
202end
203
204emptyPairing[\K,V\](): Pairing[\K,V\] = EmptyP[\K,V\]
205singletonPairing[\K,V\](k:K, v:V): Pairing[\K,V\] =
206    emptyPairing[\K,V\]().singleton(k,v)
207
208pairing[\K,V\](g:Generator[\(K,V)\]): Pairing[\K,V\] = do
209    e = emptyPairing[\K,V\]()
210    g.generate[\Heap[\K,V\]\](
211        hm[\K,V\](e),
212        fn (k:K, v:V): Pairing[\K,V\] => e.singleton(k,v))
213  end
214
215(************************************************************
216 * Not actually lazy pairing heaps; these are actuallly more
217 * eager in that they merge siblings incrementally on insertion.
218 *)
219
220trait LazyPairing[\K,V\] extends Heap[\K,V\]
221        comprises { EmptyLP[\K,V\], NodeLP[\K,V\] }
222    getter empty(): LazyPairing[\K,V\] = EmptyLP[\K,V\]
223    getter asDebugString(): String
224    singleton(k:K, v:V): LazyPairing[\K,V\] = do
225        e = self.empty
226        NodeLP[\K,V\](k,v,e,e)
227      end
228    (** link the min over the max, with the current node pending. **)
229    plink(e:EmptyLP[\K,V\],mn:NodeLP[\K,V\],mx:NodeLP[\K,V\]):NodeLP[\K,V\]
230end
231
232object EmptyLP[\K,V\] extends LazyPairing[\K,V\]
233    getter isEmpty(): Boolean = true
234    getter minimum(): Nothing[\(K,V)\] = Nothing[\(K,V)\]
235    getter asDebugString(): String = "EL"
236    check():Heap[\K,V\] = self
237    check(pk:K):Boolean = true
238    merge(h:Heap[\K,V\]): Heap[\K,V\] = h
239    merge(h:LazyPairing[\K,V\]): LazyPairing[\K,V\] = h
240    insert(k:K, v:V): LazyPairing[\K,V\] = NodeLP[\K,V\](k,v,self,self)
241    extractMinimum(): Nothing[\(K,V,LazyPairing[\K,V\])\] = Nothing[\(K,V,LazyPairing[\K,V\])\]
242    plink(e:EmptyLP[\K,V\],mn:NodeLP[\K,V\],mx:NodeLP[\K,V\]):NodeLP[\K,V\] =
243        NodeLP[\K,V\](mn.k,mn.v,mx,mn.kids)
244    generate[\R\](r: Reduction[\R\], body: (K,V)->R): R = r.empty
245end
246
247object NodeLP[\K,V\](k:K, v:V, pending: LazyPairing[\K,V\], kids: LazyPairing[\K,V\])
248        extends LazyPairing[\K,V\]
249    getter isEmpty(): Boolean = false
250    getter minimum(): Just[\(K,V)\] = Just[\(K,V)\](k,v)
251    getter asDebugString():String = "NL(" k "," v "," pending.asDebugString "," kids.asDebugString ")"
252    check():Heap[\K,V\] = do
253        if NOT kids.check(k) then
254            println( //"FAIL: heap structure violation in:" // self.asDebugString// )
255        end
256        self
257      end
258    check(pk:K):Boolean = pk <= k AND pending.check(k) AND kids.check(k)
259    merge(other:Heap[\K,V\]): Heap[\K,V\] = merge(lazy[\K,V\](other))
260    merge(_:LazyPairing[\K,V\]): LazyPairing[\K,V\] =
261        fail("LazyPairing but not NodeLP/EmptyLP")
262    merge(_:EmptyLP[\K,V\]): LazyPairing[\K,V\] = self
263    merge(h:NodeLP[\K,V\]): LazyPairing[\K,V\] = merge(self.empty,h)
264    merge(e:EmptyLP[\K,V\], _:EmptyLP[\K,V\]): LazyPairing[\K,V\] = self
265    merge(e:EmptyLP[\K,V\], h:NodeLP[\K,V\]): LazyPairing[\K,V\] =
266        if h.k <= k then
267            h.link(e,self)
268        else
269            self.link(e,h)
270        end
271    insert(k':K, v':V): LazyPairing[\K,V\] =
272        if k' <= k then (* ' *)
273            NodeLP[\K,V\](k',v',self,self.empty)
274        else
275            e = self.empty
276            link(e,NodeLP[\K,V\](k',v',e,e))
277        end
278    extractMinimum(): Just[\(K,V,LazyPairing[\K,V\])\] =
279        Just[\(K,V,LazyPairing[\K,V\])\](k,v,pending.merge(kids))
280    link(e:EmptyLP[\K,V\],n:NodeLP[\K,V\]):NodeLP[\K,V\] =
281        pending.plink(e,self,n)
282    plink(e:EmptyLP[\K,V\],mn:NodeLP[\K,V\],mx:NodeLP[\K,V\]):NodeLP[\K,V\] =
283        NodeLP[\K,V\](mn.k,mn.v,e,self.merge(mx).merge(mn.kids))
284end
285
286emptyLazy[\K,V\](): LazyPairing[\K,V\] = EmptyLP[\K,V\]
287singletonLazy[\K,V\](k:K, v:V): LazyPairing[\K,V\] =
288    emptyLazy[\K,V\]().singleton(k,v)
289
290lazy[\K,V\](g:Generator[\(K,V)\]): Heap[\K,V\] = do
291    e : Heap[\K,V\] = emptyLazy[\K,V\]()
292    g.generate[\Heap[\K,V\]\](
293        hm[\K,V\](e),
294        fn (k:K, v:V): LazyPairing[\K,V\] => e.singleton(k,v))
295  end
296
297(************************************************************
298 * And the winner is...
299 * Non-lazy pairing heaps!
300 ************************************************************)
301
302emptyHeap[\K,V\](): Pairing[\K,V\] = emptyPairing[\K,V\]()
303singletonHeap[\K,V\](k:K, v:V): Pairing[\K,V\] = singletonPairing[\K,V\](k,v)
304heap[\K,V\](g:Generator[\(K,V)\]): Pairing[\K,V\] = pairing[\K,V\](g)
305
306end
Note: See TracBrowser for help on using the browser.