Proposal: priority queues in containers

Louis Wasserman wasserman.louis at gmail.com
Tue Mar 16 09:54:15 EDT 2010


PROPOSAL:  Add a priority queue implementation to the containers package.
 Specific modules will include Data.PQueue.Min, Data.PQueue.Max, and
Data.PQueue.

DEADLINE:  Next Friday, Mar 26.

The ticket, #3909, is here <http://hackage.haskell.org/trac/ghc/ticket/3909>.
 It had done some bouncing around glasgow-haskell-users (mostly because I
forgot how to do a proper libraries proposal submission), and there have
been several implementations benchmarked, compared, and argued about.

DETAILS:

The proposed implementation benchmarked competitively with every alternative
implementation that we tested, and offers good asymptotics in nearly every
operation.  Specifically, we use a binomial heap, which offers

   - O(log n) worst-case union
   - O(log n) worst-case extract (this in particular was a key objective of
   ours)
   - amortized O(1), worst-case O(log n) insertion.  (In a persistent
   context, the amortized performance bound does not necessarily hold.)

This implementation seems to offer the best balance between practical
performance and asymptotic behavior.  Moreover, this implementation is
extremely memory-efficient, resulting in better performance on large data
sets.  (See the ticket for benchmarks.  The most accurate benchmarks are
towards the end.)

A couple potentially contentious design decisions:

   - There is no distinction between keys and priority values.  A utility
   type Prio p a with the instance Ord p => Ord (Prio p a) is exported to allow
   usage of distinct keys and priority values.
   - Min-queues and max queues are separated the following way:
      - Data.PQueue.Min exports the type MinQueue.
      - Data.PQueue.Max exports the type MaxQueue.  (This is implemented as
      a wrapper around MinQueue.)  The method names are the same as
      Data.PQueue.Min, but I think it's acceptable to force qualified
imports when
      using both a max-queue and a min-queue.
      - Data.PQueue adds the alias type PQueue = MinQueue, so that the
      "default" behavior is a min-queue.

These design decisions seem to be sufficient to handle most traditional uses
for priority queues.  In particular, this approach offers a superset of the
functionality offered by Java's built-in priority queue
implementation<http://java.sun.com/javase/6/docs/api/java/util/PriorityQueue.html>,
which makes the same design decisions, but of course, is all imperative and
yucky!  (Also, it offers inferior asymptotics, heh.)

I'm really satisfied with the patch as-is, modulo maybe tinkering with the
code style a little.  I'm also working on an article for TMR on priority
queues in Haskell, some of the different structures we considered, and
particularly the new more-type-safe implementation I came up with for
binomial heaps in the writing of this implementation.

Anyway, discuss, complain, et cetera.

Louis Wasserman
wasserman.louis at gmail.com
http://profiles.google.com/wasserman.louis
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/libraries/attachments/20100316/54142a5e/attachment.html


More information about the Libraries mailing list