path.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*!
  2. \file vector/neta/path.c
  3. \brief Network Analysis library - shortest path
  4. Shortest paths from a set of nodes.
  5. (C) 2009-2010 by Daniel Bundala, and the GRASS Development Team
  6. This program is free software under the GNU General Public License
  7. (>=v2). Read the file COPYING that comes with GRASS for details.
  8. \author Daniel Bundala (Google Summer of Code 2009)
  9. \author Markus Metz
  10. */
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <grass/gis.h>
  14. #include <grass/vector.h>
  15. #include <grass/glocale.h>
  16. #include <grass/dgl/graph.h>
  17. #include <grass/neta.h>
  18. /*!
  19. \brief Computes shortest paths to every node from nodes in "from".
  20. Array "dst" contains the cost of the path or -1 if the node is not
  21. reachable. Prev contains edges from predecessor along the shortest
  22. path.
  23. \param graph input graph
  24. \param from list of 'from' positions
  25. \param[out] dst array of costs to reach nodes
  26. \param[out] prev array of edges from predecessor along the shortest path
  27. \return 0 on success
  28. \return -1 on failure
  29. */
  30. int NetA_distance_from_points(dglGraph_s *graph, struct ilist *from,
  31. int *dst, dglInt32_t **prev)
  32. {
  33. int i, nnodes;
  34. dglHeap_s heap;
  35. int have_node_costs;
  36. dglInt32_t ncost;
  37. nnodes = dglGet_NodeCount(graph);
  38. dglEdgesetTraverser_s et;
  39. /* initialize costs and edge list */
  40. for (i = 1; i <= nnodes; i++) {
  41. dst[i] = -1;
  42. prev[i] = NULL;
  43. }
  44. ncost = 0;
  45. have_node_costs = dglGet_NodeAttrSize(graph);
  46. dglHeapInit(&heap);
  47. for (i = 0; i < from->n_values; i++) {
  48. int v = from->value[i];
  49. if (dst[v] == 0)
  50. continue; /* ignore duplicates */
  51. dst[v] = 0; /* make sure all from nodes are processed first */
  52. dglHeapData_u heap_data;
  53. heap_data.ul = v;
  54. dglHeapInsertMin(&heap, 0, ' ', heap_data);
  55. }
  56. while (1) {
  57. dglInt32_t v, dist;
  58. dglHeapNode_s heap_node;
  59. dglHeapData_u heap_data;
  60. dglInt32_t *edge;
  61. dglInt32_t *node;
  62. if (!dglHeapExtractMin(&heap, &heap_node))
  63. break;
  64. v = heap_node.value.ul;
  65. dist = heap_node.key;
  66. if (dst[v] < dist)
  67. continue;
  68. node = dglGetNode(graph, v);
  69. if (have_node_costs && prev[v]) {
  70. memcpy(&ncost, dglNodeGet_Attr(graph, node),
  71. sizeof(ncost));
  72. if (ncost > 0)
  73. dist += ncost;
  74. /* do not go through closed nodes */
  75. if (ncost < 0)
  76. continue;
  77. }
  78. dglEdgeset_T_Initialize(&et, graph,
  79. dglNodeGet_OutEdgeset(graph, node));
  80. for (edge = dglEdgeset_T_First(&et); edge;
  81. edge = dglEdgeset_T_Next(&et)) {
  82. dglInt32_t *to = dglEdgeGet_Tail(graph, edge);
  83. dglInt32_t to_id = dglNodeGet_Id(graph, to);
  84. dglInt32_t d = dglEdgeGet_Cost(graph, edge);
  85. if (dst[to_id] < 0 || dst[to_id] > dist + d) {
  86. dst[to_id] = dist + d;
  87. prev[to_id] = edge;
  88. heap_data.ul = to_id;
  89. dglHeapInsertMin(&heap, dist + d, ' ', heap_data);
  90. }
  91. }
  92. dglEdgeset_T_Release(&et);
  93. }
  94. dglHeapFree(&heap, NULL);
  95. return 0;
  96. }
  97. /*!
  98. \brief Computes shortest paths from every node to nodes in "to".
  99. Array "dst" contains the cost of the path or -1 if the node is not
  100. reachable. Nxt contains edges from successor along the shortest
  101. path. This method does reverse search starting with "to" nodes and
  102. going backward.
  103. \param graph input graph
  104. \param to list of 'to' positions
  105. \param[out] dst array of costs to reach nodes
  106. \param[out] nxt array of edges from successor along the shortest path
  107. \return 0 on success
  108. \return -1 on failure
  109. */
  110. int NetA_distance_to_points(dglGraph_s *graph, struct ilist *to,
  111. int *dst, dglInt32_t **nxt)
  112. {
  113. int i, nnodes;
  114. dglHeap_s heap;
  115. dglEdgesetTraverser_s et;
  116. int have_node_costs;
  117. dglInt32_t ncost;
  118. nnodes = dglGet_NodeCount(graph);
  119. /* initialize costs and edge list */
  120. for (i = 1; i <= nnodes; i++) {
  121. dst[i] = -1;
  122. nxt[i] = NULL;
  123. }
  124. if (graph->Version < 2) {
  125. G_warning("Directed graph must be version 2 or 3 for NetA_distance_to_points()");
  126. return -1;
  127. }
  128. ncost = 0;
  129. have_node_costs = dglGet_NodeAttrSize(graph);
  130. dglHeapInit(&heap);
  131. for (i = 0; i < to->n_values; i++) {
  132. int v = to->value[i];
  133. if (dst[v] == 0)
  134. continue; /* ignore duplicates */
  135. dst[v] = 0; /* make sure all to nodes are processed first */
  136. dglHeapData_u heap_data;
  137. heap_data.ul = v;
  138. dglHeapInsertMin(&heap, 0, ' ', heap_data);
  139. }
  140. while (1) {
  141. dglInt32_t v, dist;
  142. dglHeapNode_s heap_node;
  143. dglHeapData_u heap_data;
  144. dglInt32_t *edge;
  145. dglInt32_t *node;
  146. if (!dglHeapExtractMin(&heap, &heap_node))
  147. break;
  148. v = heap_node.value.ul;
  149. dist = heap_node.key;
  150. if (dst[v] < dist)
  151. continue;
  152. node = dglGetNode(graph, v);
  153. if (have_node_costs && nxt[v]) {
  154. memcpy(&ncost, dglNodeGet_Attr(graph, node),
  155. sizeof(ncost));
  156. if (ncost > 0)
  157. dist += ncost;
  158. /* do not go through closed nodes */
  159. if (ncost < 0)
  160. continue;
  161. }
  162. dglEdgeset_T_Initialize(&et, graph,
  163. dglNodeGet_InEdgeset(graph, node));
  164. for (edge = dglEdgeset_T_First(&et); edge;
  165. edge = dglEdgeset_T_Next(&et)) {
  166. dglInt32_t *from = dglEdgeGet_Head(graph, edge);
  167. dglInt32_t from_id = dglNodeGet_Id(graph, from);
  168. dglInt32_t d = dglEdgeGet_Cost(graph, edge);
  169. if (dst[from_id] < 0 || dst[from_id] > dist + d) {
  170. dst[from_id] = dist + d;
  171. nxt[from_id] = edge;
  172. heap_data.ul = from_id;
  173. dglHeapInsertMin(&heap, dist + d, ' ', heap_data);
  174. }
  175. }
  176. dglEdgeset_T_Release(&et);
  177. }
  178. dglHeapFree(&heap, NULL);
  179. return 0;
  180. }
  181. /*!
  182. \brief Find a path (minimum number of edges) from 'from' to 'to'
  183. using only edges flagged as valid in 'edges'. Edge costs are not
  184. considered. Closed nodes are not traversed.
  185. Precisely, edge with id I is used if edges[abs(i)] == 1. List
  186. stores the indices of lines on the path. The method returns the
  187. number of edges or -1 if no path exists.
  188. \param graph input graph
  189. \param from 'from' position
  190. \param to 'to' position
  191. \param edges array of edges indicating whether an edge should be used
  192. \param[out] list list of edges
  193. \return number of edges
  194. \return -1 on failure
  195. */
  196. int NetA_find_path(dglGraph_s * graph, int from, int to, int *edges,
  197. struct ilist *list)
  198. {
  199. dglInt32_t **prev, *queue;
  200. dglEdgesetTraverser_s et;
  201. char *vis;
  202. int begin, end, cur, nnodes;
  203. int have_node_costs;
  204. dglInt32_t ncost;
  205. nnodes = dglGet_NodeCount(graph);
  206. prev = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *));
  207. queue = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
  208. vis = (char *)G_calloc(nnodes + 1, sizeof(char));
  209. if (!prev || !queue || !vis) {
  210. G_fatal_error(_("Out of memory"));
  211. return -1;
  212. }
  213. Vect_reset_list(list);
  214. ncost = 0;
  215. have_node_costs = dglGet_NodeAttrSize(graph);
  216. begin = 0;
  217. end = 1;
  218. vis[from] = 'y';
  219. queue[0] = from;
  220. prev[from] = NULL;
  221. while (begin != end) {
  222. dglInt32_t vertex = queue[begin++];
  223. dglInt32_t *edge, *node;
  224. if (vertex == to)
  225. break;
  226. /* do not go through closed nodes */
  227. if (have_node_costs && prev[vertex]) {
  228. memcpy(&ncost, dglNodeGet_Attr(graph, dglEdgeGet_Tail(graph, edge)),
  229. sizeof(ncost));
  230. if (ncost < 0)
  231. continue;
  232. }
  233. node = dglGetNode(graph, vertex);
  234. dglEdgeset_T_Initialize(&et, graph,
  235. dglNodeGet_OutEdgeset(graph, node));
  236. for (edge = dglEdgeset_T_First(&et); edge;
  237. edge = dglEdgeset_T_Next(&et)) {
  238. dglInt32_t edge_id = labs(dglEdgeGet_Id(graph, edge));
  239. dglInt32_t node_id =
  240. dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
  241. if (edges[edge_id] && !vis[node_id]) {
  242. vis[node_id] = 'y';
  243. prev[node_id] = edge;
  244. queue[end++] = node_id;
  245. }
  246. }
  247. dglEdgeset_T_Release(&et);
  248. }
  249. G_free(queue);
  250. if (!vis[to]) {
  251. G_free(prev);
  252. G_free(vis);
  253. return -1;
  254. }
  255. cur = to;
  256. while (prev[cur] != NULL) {
  257. Vect_list_append(list, labs(dglEdgeGet_Id(graph, prev[cur])));
  258. cur = dglNodeGet_Id(graph, dglEdgeGet_Head(graph, prev[cur]));
  259. }
  260. G_free(prev);
  261. G_free(vis);
  262. return list->n_values;
  263. }