Copyright | (c) Donnacha Oisín Kidney 2021 |
---|---|
Maintainer | mail@doisinkidney.com |
Stability | experimental |
Portability | non-portable |
Safe Haskell | None |
Language | Haskell2010 |
An implementation of Dijkstra's algorithm, using the HeapT
monad.
This is taken from section 6.1.3 of the paper
- Donnacha Oisín Kidney and Nicolas Wu. 2021. Algebras for weighted search. Proc. ACM Program. Lang. 5, ICFP, Article 72 (August 2021), 30 pages. DOI:https://doi.org/10.1145/3473577
This is a pretty simple implementation of the algorithm, defined monadically, but it retains the time complexity of a standard purely functional implementation.
We use the state monad here to avoid searching from the same node more than
once (which would lead to an infinite loop). Different algorithms use
different permutations of the monad transformers: for Dijkstra's algorithm,
we use
, i.e. the HeapT
w (State
(Set
a)) aHeapT
is outside of the
State
. This means that each branch of the search proceeds with a different
state; if we switch the order (to
, for example), we
get "global" state, which has the semantics of a parser. For an example
of that, see the module MonusWeightedSearch.Examples.Parsing, where the
heap is used to implement a probabilistic parser.StateT
s (Heap
w) a
Documentation
>>>
import Prelude hiding (head)
>>>
import Data.List.NonEmpty (head)
unique :: Ord a => a -> HeapT w (State (Set a)) a Source #
checks that unique
xx
has not yet been seen in this branch of the
computation.
star :: MonadPlus m => (a -> m a) -> a -> m a Source #
This is the Kleene star on the semiring of MonadPlus
. It is analagous to
the many
function on Alternative
s.
pathed :: MonadPlus m => (a -> m a) -> a -> m (NonEmpty a) Source #
This is a version of star
which keeps track of the inputs it was given.
dijkstra :: Ord a => Graph a -> a -> [(a, Dist)] Source #
Dijkstra's algorithm. This function returns the length of the shortest path from a given vertex to every vertex in the graph.
>>>
dijkstra graph 1
[(1,0),(2,7),(3,9),(6,11),(5,20),(4,20)]
A version which actually produces the paths is shortestPaths
shortestPaths :: Ord a => Graph a -> a -> [(NonEmpty a, Dist)] Source #
Dijkstra's algorithm, which produces a path.
The only difference between this function and shortestPaths
is that this
uses pathed
rather than star
.
The following finds the shortest path from vertex 1 to 5:
>>>
filter ((5==) . head . fst) (shortestPaths graph 1)
[(5 :| [6,3,1],20)]
And it is indeed [1,3,6,5]
. (it's returned in reverse)