[m-rev.] For review 1/2: Beefed up the pqueue implementation.

Paul Bone paul at bone.id.au
Sun Nov 24 15:42:14 AEDT 2013


Branches: master

For review by anyone.

Submitted on behalf of Michael Richter <ttmrichter at gmail.com>

---

Beefed up the pqueue implementation.

library/pqueue.m:
    Added predicates is_empty/1, peek/3, peek_key/2, peek_value/2,
    det_peek/3, merge/3.  Added functions det_peek_key/1, det_peek_value/1.

    Also reformatted code to fit within 76 columns.
---
 library/pqueue.m | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 80 insertions(+), 5 deletions(-)

diff --git a/library/pqueue.m b/library/pqueue.m
index 99f1b13..48e2d11 100644
--- a/library/pqueue.m
+++ b/library/pqueue.m
@@ -40,6 +40,10 @@
 :- func pqueue.init = pqueue(K, V).
 :- pred pqueue.init(pqueue(K, V)::out) is det.
 
+    % Test if a priority queue is empty.
+    %
+:- pred pqueue.is_empty(pqueue(K, V)::in) is semidet.
+
     % Insert a value V with key K into a priority queue
     % and return the new priority queue.
     %
@@ -47,6 +51,27 @@
 :- pred pqueue.insert(K::in, V::in, pqueue(K, V)::in, pqueue(K, V)::out)
     is det.
 
+    % Extract the smallest key/value pair from the priority queue without
+    % removing it.  Fails if the priority queue is empty.
+    %
+:- pred pqueue.peek(pqueue(K, V)::in, K::out, V::out) is semidet.
+
+    % Extract the smallest key from the priority queue without removing it.
+    % Fails if the priority queue is empty.
+    %
+:- pred pqueue.peek_key(pqueue(K, V)::in, K::out) is semidet.
+
+    % Extract the smallest value from the priority queue without removing
+    % it.  Fails if the priority queue is empty.
+    %
+:- pred pqueue.peek_value(pqueue(K, V)::in, V::out) is semidet.
+
+    % As above, but calls error/1 if the priority queue is empty.
+    %
+:- pred pqueue.det_peek(pqueue(K, V)::in, K::out, V::out) is det.
+:- func pqueue.det_peek_key(pqueue(K, V)) = K.
+:- func pqueue.det_peek_value(pqueue(K, V)) = V.
+
     % Remove the smallest item from the priority queue.
     % Fails if the priority queue is empty.
     %
@@ -58,11 +83,18 @@
 :- pred pqueue.det_remove(K::out, V::out, pqueue(K, V)::in, pqueue(K, V)::out)
     is det.
 
+    % Merges all the entries of one priority queue with another, returning
+    % the merged list.
+:- func pqueue.merge(pqueue(K, V), pqueue(K, V)) = pqueue(K, V).
+:- pred pqueue.merge(pqueue(K, V)::in, pqueue(K, V)::in, pqueue(K, V)::out)
+    is det.
+
     % Extract all the items from a priority queue by repeated
     % removal, and place them in an association list.
     %
 :- func pqueue.to_assoc_list(pqueue(K, V)) = assoc_list(K, V).
-:- pred pqueue.to_assoc_list(pqueue(K, V)::in, assoc_list(K, V)::out) is det.
+:- pred pqueue.to_assoc_list(pqueue(K, V)::in, assoc_list(K, V)::out)
+    is det.
 
     % Insert all the key-value pairs in an association list
     % into a priority queue.
@@ -106,6 +138,28 @@ pqueue.init(empty).
 
 %---------------------------------------------------------------------------%
 
+pqueue.is_empty(empty).
+
+%---------------------------------------------------------------------------%
+
+pqueue.peek(pqueue(_, K, V, _, _), K, V).
+pqueue.peek_key(pqueue(_, K, _, _, _), K).
+pqueue.peek_value(pqueue(_, _, V, _, _), V).
+
+%---------------------------------------------------------------------------%
+
+pqueue.det_peek(PQ, K, V) :-
+    ( pqueue.peek(PQ, J, T) ->
+        K = J, V = T
+    ;
+        unexpected($file, $pred, "empty priority queue")
+    ).
+
+pqueue.det_peek_key(PQ) = K :- pqueue.det_peek(PQ, K, _).
+pqueue.det_peek_value(PQ) = V :- pqueue.det_peek(PQ, _, V).
+
+%---------------------------------------------------------------------------%
+
 pqueue.insert(!.PQ, K, V) = !:PQ :-
     pqueue.insert(K, V, !PQ).
 
@@ -132,8 +186,8 @@ pqueue.insert_2(K, V, pqueue(D0, K0, V0, L0, R0), empty,
         pqueue(D0, K0, V0, L0, R0), pqueue(0, K, V, empty, empty)).
 pqueue.insert_2(K, V, empty, pqueue(D0, K0, V0, L0, R0),
         pqueue(0, K, V, empty, empty), pqueue(D0, K0, V0, L0, R0)).
-pqueue.insert_2(K, V, pqueue(D0, K0, V0, L0, R0), pqueue(D1, K1, V1, L1, R1),
-        PQ1, PQ2) :-
+pqueue.insert_2(K, V, pqueue(D0, K0, V0, L0, R0),
+                pqueue(D1, K1, V1, L1, R1), PQ1, PQ2) :-
     ( D0 > D1 ->
         pqueue.insert(K, V, pqueue(D1, K1, V1, L1, R1), PQ2),
         PQ1 = pqueue(D0, K0, V0, L0, R0)
@@ -149,8 +203,8 @@ pqueue.det_remove(K, V, !PQ) :-
         K = K0,
         V = V0
       else
-        error("pqueue.det_remove/4: empty priority queue")
-    ). 
+        unexpected($file, $pred, "empty priority queue")
+    ).
 
 pqueue.remove(K, V, pqueue(_, K, V, L0, R0), PQ) :-
     pqueue.remove_2(L0, R0, PQ).
@@ -177,6 +231,27 @@ pqueue.remove_2(pqueue(D0, K0, V0, L0, R0), pqueue(D1, K1, V1, L1, R1), PQ) :-
 
 %---------------------------------------------------------------------------%
 
+pqueue.merge(A, B) = C :-
+    pqueue.merge(A, B, C).
+
+pqueue.merge(A, B, C) :-
+  ( pqueue.length(A) =< pqueue.length(B) ->
+      pqueue.merge2(A, B, C)
+  ;
+      pqueue.merge2(B, A, C) ).
+
+:- pred pqueue.merge2(pqueue(K, V)::in, pqueue(K, V)::in, pqueue(K, V)::out)
+    is det.
+
+pqueue.merge2(empty,                   B,     B).
+pqueue.merge2(A at pqueue(_, _, _, _, _), empty, A).
+pqueue.merge2(pqueue(_, K, V, L, R),   !.PQ at pqueue(_, _, _, _, _), !:PQ) :-
+    pqueue.merge2(L, !PQ),
+    pqueue.merge2(R, !PQ),
+    pqueue.insert(K, V, !PQ).
+
+%---------------------------------------------------------------------------%
+
 pqueue.to_assoc_list(PQ) = AL :-
     pqueue.to_assoc_list(PQ, AL).
 
-- 
1.8.4.rc3




More information about the reviews mailing list