File: bellman-ford.sml

package info (click to toggle)
mlton 20210117%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 58,464 kB
  • sloc: ansic: 27,682; sh: 4,455; asm: 3,569; lisp: 2,879; makefile: 2,347; perl: 1,169; python: 191; pascal: 68; javascript: 7
file content (50 lines) | stat: -rw-r--r-- 1,470 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
(*
 * This module implements the Bellman Ford algorithm for single source
 * shortest paths.
 *
 * -- Allen
 *)

functor BellmanFord(Num : ABELIAN_GROUP_WITH_INF) : 
    sig include SINGLE_SOURCE_SHORTEST_PATHS 
        exception NegativeCycle
    end =
struct

   structure Num = Num
   structure G   = Graph
   structure A   = Array

   exception NegativeCycle

   fun single_source_shortest_paths {graph=G.GRAPH G,s,weight} =
   let val N      = #capacity G ()
       val dist   = A.array(N, Num.inf)
       val pred   = A.array(N, ~1)
       val count  = A.array(N, 0)
       fun driver([],[])  = ()
         | driver([],B)   = driver(rev B,[])
         | driver(u::A,B) = driver(iterate(u,A,B))
       and iterate(u,A,B) =
           let val n = Int.+(A.sub(count,u), 1)
               val _ = A.update(count,u,n)
               val _ = if n >= N then raise NegativeCycle else ()
               val du = A.sub(dist,u)
               fun relax([],A,B) = (A,B)
                 | relax((e as (_,v,_))::es,A,B) =
                   let val c = Num.+(du,weight e)
                   in  if Num.<(c,A.sub(dist,v)) then
                        (A.update(dist,v,c); A.update(pred,v,u);
                         relax(es,A,v::B))
                       else relax(es,A,B)
                   end
           in  relax(#out_edges G u,A,B) 
           end
   in  A.update(dist,s,Num.zero);
       driver([s],[]);
       { dist = dist,
         pred = pred
       }
   end
end