Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | (* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh |
2 | * Jagannathan, and Stephen Weeks. | |
3 | * | |
4 | * MLton is released under a BSD-style license. | |
5 | * See the file MLton-LICENSE for details. | |
6 | *) | |
7 | ||
8 | functor Dijkstra (S : SHORTEST_PATH_STRUCTS): SHORTEST_PATH = | |
9 | struct | |
10 | ||
11 | open S | |
12 | ||
13 | structure Heap = FibonacciHeap (structure Key = Weight) | |
14 | structure Elt = Heap.Elt | |
15 | ||
16 | fun shortestPath {graph, weight, source} = | |
17 | let | |
18 | val {get: Node.t -> Node.t Heap.Elt.t option, set, destroy} = | |
19 | Property.destGetSetOnce (Node.plist, Property.initConst NONE) | |
20 | val elt = valOf o get | |
21 | fun distanceOption n = Option.map (get n, Elt.key) | |
22 | val distance = valOf o distanceOption | |
23 | val fringe: Node.t Heap.t = Heap.empty () | |
24 | fun addToFringe (n: Node.t, d: Weight.t): unit = | |
25 | set (n, SOME (Heap.insert (fringe, d, n))) | |
26 | fun relax (n: Node.t, e: Edge.t): unit = | |
27 | let val n' = Edge.to e | |
28 | val d = Weight.+ (distance n, weight e) | |
29 | in case distanceOption n' of | |
30 | NONE => addToFringe (n', d) | |
31 | | SOME d' => if Weight.< (d, d') | |
32 | then Heap.decreaseKey (fringe, elt n', d) | |
33 | else () | |
34 | end | |
35 | in addToFringe (source, Weight.zero) | |
36 | ; while not (Heap.isEmpty fringe) | |
37 | do let val n = Heap.deleteMin fringe | |
38 | in List.foreach (Node.successors n, fn e => relax (n, e)) | |
39 | end | |
40 | ; distanceOption | |
41 | end | |
42 | ||
43 | end |