Files
mercury/library/pqueue.m
Zoltan Somogyi 6909674f14 Bring these modules up to date with our current style guidelines.
Estimated hours taken: 8
Branches: main

library/*.m:
	Bring these modules up to date with our current style guidelines.
	Use predmode declarations where appropriate. Use state variable syntax
	where appropriate. Reorder arguments where this makes it possible to
	to use state variable syntax. Standardize format of predicate
	description comments. Standardize indentation.
2004-03-15 23:49:36 +00:00

163 lines
5.2 KiB
Mathematica

%---------------------------------------------------------------------------%
% Copyright (C) 1994-1995, 1997, 1999, 2003-2004 The University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB in the Mercury distribution.
%---------------------------------------------------------------------------%
%
% file pqueue.m - implements a priority queue ADT.
% main author: conway.
% stability: high.
%
% A pqueue is a priority queue. A priority queue holds a collection
% of key-value pairs; the interface provides operations to create
% an empty priority queue, to insert a key-value pair into a priority
% queue, and to remove the element with the lowest key.
%
% Insertion/removal is not guaranteed to be "stable"; that is,
% if you insert two values with the same key, the order in which
% they will be removed is unspecified.
%
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- module pqueue.
:- interface.
:- import_module assoc_list.
:- type pqueue(_K, _V).
% Create an empty priority queue
:- pred pqueue__init(pqueue(_K, _V)::out) is det.
:- func pqueue__init = pqueue(_K, _V).
% Insert a value V with key K into a priority queue
% and return the new priority queue.
:- pred pqueue__insert(pqueue(K, V)::in, K::in, V::in, pqueue(K, V)::out)
is det.
:- func pqueue__insert(pqueue(K, V), K, V) = pqueue(K, V).
% Remove the smallest item from the priority queue.
:- pred pqueue__remove(pqueue(K, V)::in, K::out, V::out, pqueue(K, V)::out)
is semidet.
% Extract all the items from a priority queue by
% repeated removal, and place them in an association
% list.
:- pred pqueue__to_assoc_list(pqueue(K, V)::in, assoc_list(K, V)::out) is det.
:- func pqueue__to_assoc_list(pqueue(K, V)) = assoc_list(K, V).
% Insert all the key-value pairs in an association list
% into a priority queue.
:- pred pqueue__assoc_list_to_pqueue(assoc_list(K, V)::in, pqueue(K, V)::out)
is det.
:- func pqueue__assoc_list_to_pqueue(assoc_list(K, V)) = pqueue(K, V).
%---------------------------------------------------------------------------%
:- implementation.
:- import_module int, list, std_util.
:- type pqueue(K, V)
---> empty
; pqueue(int, K, V, pqueue(K, V), pqueue(K, V)).
%---------------------------------------------------------------------------%
pqueue__init(empty).
%---------------------------------------------------------------------------%
pqueue__insert(empty, K, V, pqueue(0, K, V, empty, empty)).
pqueue__insert(pqueue(D0, K0, V0, L0, R0), K, V, PQ) :-
D = D0 + 1,
compare(CMP, K, K0),
( CMP = (<) ->
K1 = K,
V1 = V,
pqueue__insert_2(K0, V0, L0, R0, L, R)
;
K1 = K0,
V1 = V0,
pqueue__insert_2(K, V, L0, R0, L, R)
),
PQ = pqueue(D, K1 ,V1, L, R).
:- pred pqueue__insert_2(K::in, V::in, pqueue(K, V)::in, pqueue(K, V)::in,
pqueue(K, V)::out, pqueue(K, V)::out) is det.
pqueue__insert_2(K, V, empty, empty, pqueue(0, K, V, empty, empty), empty).
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) :-
( D0 > D1 ->
pqueue__insert(pqueue(D1, K1, V1, L1, R1), K, V, PQ2),
PQ1 = pqueue(D0, K0, V0, L0, R0)
;
pqueue__insert(pqueue(D0, K0, V0, L0, R0), K, V, PQ1),
PQ2 = pqueue(D1, K1, V1, L1, R1)
).
%---------------------------------------------------------------------------%
pqueue__remove(pqueue(_, K, V, L0, R0), K, V, PQ) :-
pqueue__remove_2(L0, R0, PQ).
:- pred pqueue__remove_2(pqueue(K, V)::in, pqueue(K, V)::in, pqueue(K, V)::out)
is det.
pqueue__remove_2(empty, empty, empty).
pqueue__remove_2(empty, pqueue(D, K, V, L, R), pqueue(D, K, V, L, R)).
pqueue__remove_2(pqueue(D, K, V, L, R), empty, pqueue(D, K, V, L, R)).
pqueue__remove_2(pqueue(D0, K0, V0, L0, R0), pqueue(D1, K1, V1, L1, R1), PQ) :-
compare(CMP, K0, K1),
( CMP = (<) ->
D0M1 = D0 - 1,
int__max(D0M1, D1, D),
pqueue__remove_2(L0, R0, PQ0),
PQ = pqueue(D, K0, V0, PQ0, pqueue(D1, K1, V1, L1, R1))
;
D1M1 = D0 - 1,
int__max(D1M1, D1, D),
pqueue__remove_2(L1, R1, PQ1),
PQ = pqueue(D, K1, V1, PQ1, pqueue(D0, K0, V0, L0, R0))
).
%---------------------------------------------------------------------------%
pqueue__to_assoc_list(Q0, L) :-
( pqueue__remove(Q0, K, V, Q1) ->
pqueue__to_assoc_list(Q1, L0),
L = [K - V | L0]
;
L = []
).
pqueue__assoc_list_to_pqueue([], Q) :-
pqueue__init(Q).
pqueue__assoc_list_to_pqueue([K - V | L], Q) :-
pqueue__assoc_list_to_pqueue(L, Q0),
pqueue__insert(Q0, K, V, Q).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
% Ralph Becket <rwab1@cl.cam.ac.uk> 29/04/99
% Functional forms added.
pqueue__init = PQ :-
pqueue__init(PQ).
pqueue__insert(PQ1, K, V) = PQ2 :-
pqueue__insert(PQ1, K, V, PQ2).
pqueue__to_assoc_list(PQ) = AL :-
pqueue__to_assoc_list(PQ, AL).
pqueue__assoc_list_to_pqueue(AL) = PQ2 :-
pqueue__assoc_list_to_pqueue(AL, PQ2).