Advertisement
Guest User

Untitled

a guest
Dec 19th, 2014
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.79 KB | None | 0 0
  1. (* Minh Truong
  2. *
  3. * Language: Standard ML of New Jersey
  4. *
  5. * This structure provides an implementation of Dijstra's Algorithm for
  6. * finding the shortest distance and path between two vertices in a weighted
  7. * graph. The graph is in the form of a vector (SML's equalivalence to arrays)
  8. * of weighted adjacency lists.
  9. *
  10. *)
  11.  
  12. structure WeightedGraphAdjList =
  13. struct
  14.  
  15. (* A vector type for adjacency lists. To have a much more efficient code,
  16. * a braun vector should be used instead of a regular vector.
  17. *)
  18. structure V = Vector
  19.  
  20. (* The type of a vertex.
  21. *)
  22. type vertex = int
  23.  
  24. (* The type of an adjacency list.
  25. *)
  26. type adjlist = (vertex*real) list
  27.  
  28. (* The type of a graph.
  29. *)
  30. type graph = adjlist V.vector
  31.  
  32. type vgraph = real V.vector
  33.  
  34. type pgraph = ((vertex list)*real) V.vector
  35.  
  36. type bgraph = bool V.vector
  37.  
  38. (* Exception that is raised by functions when applied to vertices that
  39. * are not in a graph.
  40. *)
  41. exception BadVertex
  42.  
  43. exception Empty
  44.  
  45. exception BadKey
  46.  
  47. (* graph n = ({0,...n-1}, empty); i.e., the graph on n vertices
  48. * with no edges.
  49. *)
  50. fun new(n : int) : graph =
  51. V.tabulate (n, fn i => [])
  52.  
  53. (* size g = the number of vertices in g.
  54. *)
  55.  
  56. fun size( g :graph): int = V.length(g)
  57.  
  58.  
  59. (* getNeighbors(g, u) = [(v_0,w_0),...], where (v, w) = (v_i, w_i) if
  60. * and only if there is an edge from u to v_i with weight w_i.
  61. *
  62. * Raises BadVertex if u is not a vertex in g.
  63. *
  64. * In other words, getNeighbors(g, u) returns the list of pairs
  65. * (v, w) such that there is an edge from u to v of weight w in g.
  66. *)
  67. fun getNeighbors(g :graph, v: vertex): (vertex*real) list =
  68. V.sub(g,v)
  69.  
  70.  
  71. (* insert ([(x,q)_0,...,(x,q)_{n-1}],(x, q)) =
  72. * [(x,q)_0,...,(x,q)_{i-1},(x,q),(x,q)_{i+1},...,(x_{n},q_{n})],
  73. * where q_{i-1} <= q <= q_{i+1}.
  74. *)
  75. fun insert (xs : adjlist, (x, q) : vertex*real) : adjlist =
  76. let
  77. fun insert2 (xs : adjlist) : adjlist =
  78. case xs of
  79. [] => [(x, q)]
  80. | (y, z) :: ys =>
  81. if z < q then (y, z) :: (insert2(ys))
  82. else (x, q) :: xs
  83. in
  84. insert2 (xs)
  85. end
  86.  
  87. (* insertMany (q, [(y_0,q_0),...(y_{n-1},q_{n-1})]) =
  88. * insert(...insert(
  89. * insert(q, (y_0, q_0)), (y_1, q_1))...,(y_{n-1},q_{n-1})).
  90. *)
  91. fun insertMany (xs : adjlist, ys : adjlist) : adjlist =
  92. foldr (fn (y, q) => insert(q, y)) xs ys
  93.  
  94. (* updatePri(qs,x,p,[]) = qs'. qs = [(m,r)_0,...,(m,r)_{n-1}] and qs' = qs
  95. * such that for x = m_i of qs,
  96. * (m,r)_i = (m,p)_i
  97. *)
  98. fun updatePri(qs : adjlist, x : vertex, p : real, ws : adjlist) : adjlist =
  99. case qs of
  100. [] => raise Empty
  101. | (n,r)::zs => if n = x then ws@insert(zs,(x,p)) else updatePri(zs,x,p,ws@[(n,r)])
  102.  
  103. fun remove(q : adjlist) : vertex*adjlist =
  104. case q of
  105. [] => raise Empty
  106. | (x, y) :: xs => (x, xs)
  107.  
  108. (* unfin(al,boo,ml) = al'.
  109. *
  110. * this function is similar to List.filter.
  111. * al = [(x_0,r_0),...(x_{n-1},r_{n-1}].
  112. * let z = V.sub(boo,x_i). then al' = al (where al has all z(x_i) = true then
  113. * (x_i,r_i) is removed from the list).
  114. * boo is a boolean vector that keeps track of the nodes that are finished.
  115. * al' is the list with all finished neighbors removed.
  116. *)
  117. fun unfin(al:adjlist,boo: bgraph,ml:adjlist): adjlist =
  118. case al of
  119. [] => ml
  120. | (v,r)::al'=> if V.sub(boo,v) then unfin(al',boo,ml) else unfin(al',boo,(v,r)::ml)
  121.  
  122. (* findD(u,v,g,pq,g2,boo) = SOME(n). n is the shortest distance from u to v in
  123. * graph g. = NONE, if there is no path from u to v
  124. *
  125. *
  126. * pq is a a priority queue that will be updated with each iteration, it is
  127. * initially empty before any iterations.
  128. * g2 is vector whose indexes corresponds to the nodes in g, and contains
  129. * the tentative distances with each respective iterations. The tentative
  130. * distances in g2 are initially set at 0.0 for u and infinity for the rest.
  131. * boo is a boolean vector that tracks the status of each nodes, finished or
  132. * unfinished.
  133. *)
  134. fun findD(u: vertex,v: vertex, g: graph, pq: adjlist, g2: vgraph,boo:bgraph): real option =
  135. if List.length(pq) = 0 andalso V.sub(g2,v)>= Real.posInf then NONE
  136. else if List.length(pq) = 0 then SOME(V.sub(g2,v)) else
  137. let
  138. (* update(m,[(v_0,r_1),...,(v_{n-1},r_{n-1})],g2,pqq) = (g2',pqq').
  139. *
  140. * for all v_i and r_i:
  141. * if m + r_i < Vector.sub(g2,v_i) => g2' = V.update(g2,v_i,r+m)
  142. * pqq' = Q.updatePri(pqq,v_i,r+m)
  143. *)
  144. fun update(m:real, al: adjlist, g2:vgraph, pqq: adjlist): vgraph*adjlist =
  145. case al of
  146. [] => (g2,pqq)
  147. | (v',r)::al' =>
  148. let
  149. val tentdist = V.sub(g2,v')
  150. val less = r+m < tentdist
  151. val g2' = if less then V.update(g2,v',r+m) else g2
  152. val pq' = if less then updatePri(pqq,v',r+m,[]) else pqq
  153. in
  154. update(m,al', g2',pq')
  155. end
  156. val neighbors = getNeighbors(g,u)
  157. val neighbors' = unfin(neighbors,boo,[])
  158. val pq' = insertMany(pq,neighbors')
  159. val m = V.sub(g2,u)
  160. val (g2',pq'') = update(m,neighbors',g2,pq')
  161. val (u',pq''') = remove(pq'')
  162. val boo' = V.update(boo,u',true)
  163. val w =findD(u',v,g,pq''',g2',boo')
  164. in
  165. w
  166. end
  167.  
  168. fun dist(g: graph, u: vertex, v :vertex): real option =
  169. let
  170. val length = size(g)
  171. val pq = []
  172. val pq'' = insert(pq,(u,0.0))
  173. val g2 = V.tabulate(length,fn x => Real.posInf)
  174. val g2' = V.update(g2,u,0.0)
  175. val bvector = V.tabulate(length,fn x => false)
  176. val bvector' = V.update(bvector,u,true)
  177. val distance = findD(u,v,g,pq'',g2',bvector')
  178. in
  179. distance
  180. end
  181.  
  182. (* findP(u,v,[],g,pq,g2,boo) = xs = [x_0,x_1,...,x_{n-1}].
  183. * = []. if there is no path from u to v.
  184. *
  185. * xs is the minimal distance path from u to v in graph g,
  186. * where x_0 is the first vertex from u to v (that is not u), x_{n-1} = v, and
  187. * there is an edge from u_i to u_{i+1} for all 0 <= i < n-1.
  188. *
  189. * pq is a a priority queue that is initially empty before any iterations.
  190. * g2 is vector whose indexes corresponds to the nodes in g, and contains
  191. * the tentative paths and tentative distances with each respective iterations.
  192. * us is initially [] but is used to keep track of the tentative
  193. * predecessors of current u.
  194. * boo is a boolean vector that tracks the status of each node, whether they
  195. * are finished are unfinished.
  196. *)
  197. fun findP(u: vertex,v: vertex,us: vertex list,
  198. g: graph, pq: adjlist, g2: pgraph,boo:bgraph): vertex list =
  199. if u = v then us else
  200. let
  201. (* update((ys,m),[(v_0,r_1),...,(v_{n-1},r_{n-1})],g2,pqq) = (g2',pqq').
  202. *
  203. * for all v_i and r_i:
  204. * if m + r_i < Vector.sub(g2,v_i) => g2' = V.update(g2,v_i, (ys@[v_i],r+m) )
  205. * pqq' = Q.updatePri(pqq,v_i,r+m)
  206. *)
  207. fun update((ys,m):(vertex list)*real, al: adjlist,
  208. g2':pgraph, pqq: adjlist): pgraph*adjlist =
  209. case al of
  210. [] => (g2',pqq)
  211. | (v',weight)::al' =>
  212. let
  213. val (xs,tentdist) = V.sub(g2',v')
  214. val less = weight+m < tentdist
  215. val g2'' = if less then V.update(g2',v',(ys@[v'],weight+m)) else g2'
  216. val pq' = if less then updatePri(pqq,v',weight+m,[]) else pqq
  217. in
  218. update((ys,m),al', g2'',pq')
  219. end
  220. val neighbors = getNeighbors(g,u)
  221. val neighbors' = unfin(neighbors,boo,[])
  222. val pq' = insertMany(pq,neighbors')
  223. val (g2',pq'') = update(V.sub(g2,u),neighbors',g2,pq')
  224. val (u',pq''') = remove(pq'')
  225. val (zs,r) = V.sub(g2',u')
  226. val boo' = V.update(boo,u',true)
  227. val z = if List.length(pq''') = 0 then [] else findP(u',v,zs,g,pq''',g2',boo')
  228. in
  229. z
  230. end
  231. (* path (g, u, v) = [], if there is no path from u to v in g
  232. * = [u_0,...,u_{n-1}], where u_0 = u, u_{n-1} = v,
  233. * and there is an edge from u_i to u_{i+1} for all 0 <= i < n-1.
  234. * Furthermore,
  235. * sum_i(weight(g, u_i, u_{i+1}))
  236. * is minimal among all paths from u to v.
  237. *
  238. * Raises BadVertex if u or v is not a vertex in g.
  239. *
  240. * In other words, path(g, u, v) is a minimal-weight path from u to v
  241. * in g, provided such a path exists.
  242. *)
  243. fun path(g:graph, u:vertex, v: vertex): vertex list =
  244. let
  245. val length = size(g)
  246. val pq = []
  247. val pq'' = insert(pq,(u,0.0))
  248. val (u2,pq''') = remove(pq'')
  249. val g2 = V.tabulate(length,fn x =>([], Real.posInf))
  250. val g2' = V.update(g2,u,([],0.0))
  251. val bvector = V.tabulate(length, fn x => false)
  252. val bvector' = V.update(bvector,u,true)
  253. val path = findP(u,v,[],g,pq''',g2',bvector')
  254. val path' = if path = [] then [] else u::path
  255. in
  256. path'
  257. end
  258.  
  259.  
  260. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement