flow.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*!
  2. \file vector/neta/flow.c
  3. \brief Network Analysis library - flow in graph
  4. Computes the length of the shortest path between all pairs of nodes
  5. in the network.
  6. (C) 2009-2010 by Daniel Bundala, and the GRASS Development Team
  7. This program is free software under the GNU General Public License
  8. (>=v2). Read the file COPYING that comes with GRASS for details.
  9. \author Daniel Bundala (Google Summer of Code 2009)
  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. dglInt32_t sign(dglInt32_t x)
  19. {
  20. if (x >= 0)
  21. return 1;
  22. return -1;
  23. }
  24. /*!
  25. \brief Get max flow from source to sink.
  26. Array flow stores flow for each edge. Negative flow corresponds to a
  27. flow in opposite direction The function assumes that the edge costs
  28. correspond to edge capacities.
  29. \param graph input graph
  30. \param source_list list of sources
  31. \param sink_list list of sinks
  32. \param[out] flow max flows
  33. \return number of flows
  34. \return -1 on failure
  35. */
  36. int NetA_flow(dglGraph_s * graph, struct ilist *source_list,
  37. struct ilist *sink_list, int *flow)
  38. {
  39. int nnodes, nlines, i;
  40. dglEdgesetTraverser_s et;
  41. dglInt32_t *queue;
  42. dglInt32_t **prev;
  43. char *is_source, *is_sink;
  44. int begin, end, total_flow;
  45. nnodes = dglGet_NodeCount(graph);
  46. nlines = dglGet_EdgeCount(graph) / 2; /*each line corresponds to two edges. One in each direction */
  47. queue = (dglInt32_t *) G_calloc(nnodes + 3, sizeof(dglInt32_t));
  48. prev = (dglInt32_t **) G_calloc(nnodes + 3, sizeof(dglInt32_t *));
  49. is_source = (char *)G_calloc(nnodes + 3, sizeof(char));
  50. is_sink = (char *)G_calloc(nnodes + 3, sizeof(char));
  51. if (!queue || !prev || !is_source || !is_sink) {
  52. G_fatal_error(_("Out of memory"));
  53. return -1;
  54. }
  55. for (i = 0; i < source_list->n_values; i++)
  56. is_source[source_list->value[i]] = 1;
  57. for (i = 0; i < sink_list->n_values; i++)
  58. is_sink[sink_list->value[i]] = 1;
  59. for (i = 0; i <= nlines; i++)
  60. flow[i] = 0;
  61. total_flow = 0;
  62. while (1) {
  63. dglInt32_t node, edge_id, min_residue;
  64. int found = -1;
  65. begin = end = 0;
  66. for (i = 0; i < source_list->n_values; i++)
  67. queue[end++] = source_list->value[i];
  68. for (i = 1; i <= nnodes; i++) {
  69. prev[i] = NULL;
  70. }
  71. while (begin != end && found == -1) {
  72. dglInt32_t vertex = queue[begin++];
  73. dglInt32_t *edge, *node = dglGetNode(graph, vertex);
  74. dglEdgeset_T_Initialize(&et, graph,
  75. dglNodeGet_OutEdgeset(graph, node));
  76. for (edge = dglEdgeset_T_First(&et); edge;
  77. edge = dglEdgeset_T_Next(&et)) {
  78. dglInt32_t cap = dglEdgeGet_Cost(graph, edge);
  79. dglInt32_t id = dglEdgeGet_Id(graph, edge);
  80. dglInt32_t to =
  81. dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
  82. if (!is_source[to] && prev[to] == NULL &&
  83. cap > sign(id) * flow[abs(id)]) {
  84. prev[to] = edge;
  85. if (is_sink[to]) {
  86. found = to;
  87. break;
  88. }
  89. queue[end++] = to;
  90. }
  91. }
  92. dglEdgeset_T_Release(&et);
  93. }
  94. if (found == -1)
  95. break; /*no augmenting path */
  96. /*find minimum residual capacity along the augmenting path */
  97. node = found;
  98. edge_id = dglEdgeGet_Id(graph, prev[node]);
  99. min_residue =
  100. dglEdgeGet_Cost(graph,
  101. prev[node]) - sign(edge_id) * flow[abs(edge_id)];
  102. while (!is_source[node]) {
  103. dglInt32_t residue;
  104. edge_id = dglEdgeGet_Id(graph, prev[node]);
  105. residue =
  106. dglEdgeGet_Cost(graph,
  107. prev[node]) -
  108. sign(edge_id) * flow[abs(edge_id)];
  109. if (residue < min_residue)
  110. min_residue = residue;
  111. node = dglNodeGet_Id(graph, dglEdgeGet_Head(graph, prev[node]));
  112. }
  113. total_flow += min_residue;
  114. /*update flow along the augmenting path */
  115. node = found;
  116. while (!is_source[node]) {
  117. edge_id = dglEdgeGet_Id(graph, prev[node]);
  118. flow[abs(edge_id)] += sign(edge_id) * min_residue;
  119. node = dglNodeGet_Id(graph, dglEdgeGet_Head(graph, prev[node]));
  120. }
  121. }
  122. G_free(queue);
  123. G_free(prev);
  124. G_free(is_source);
  125. G_free(is_sink);
  126. return total_flow;
  127. }
  128. /*!
  129. \brief Calculates minimum cut between source(s) and sink(s).
  130. Flow is the array produced by NetA_flow() method when called with
  131. source_list and sink_list as the input. The output of this and
  132. NetA_flow() method should be the same.
  133. \param graph input graph
  134. \param source_list list of sources
  135. \param sink_list list of sinks
  136. \param[out] cut list of edges (cut)
  137. \return number of edges
  138. \return -1 on failure
  139. */
  140. int NetA_min_cut(dglGraph_s * graph, struct ilist *source_list,
  141. struct ilist *sink_list, int *flow, struct ilist *cut)
  142. {
  143. int nnodes, i;
  144. dglEdgesetTraverser_s et;
  145. dglInt32_t *queue;
  146. char *visited;
  147. int begin, end, total_flow;
  148. nnodes = dglGet_NodeCount(graph);
  149. queue = (dglInt32_t *) G_calloc(nnodes + 3, sizeof(dglInt32_t));
  150. visited = (char *)G_calloc(nnodes + 3, sizeof(char));
  151. if (!queue || !visited) {
  152. G_fatal_error(_("Out of memory"));
  153. return -1;
  154. }
  155. total_flow = begin = end = 0;
  156. for (i = 1; i <= nnodes; i++)
  157. visited[i] = 0;
  158. for (i = 0; i < source_list->n_values; i++) {
  159. queue[end++] = source_list->value[i];
  160. visited[source_list->value[i]] = 1;
  161. }
  162. /* find vertices reachable from source(s) using only non-saturated edges */
  163. while (begin != end) {
  164. dglInt32_t vertex = queue[begin++];
  165. dglInt32_t *edge, *node = dglGetNode(graph, vertex);
  166. dglEdgeset_T_Initialize(&et, graph,
  167. dglNodeGet_OutEdgeset(graph, node));
  168. for (edge = dglEdgeset_T_First(&et); edge;
  169. edge = dglEdgeset_T_Next(&et)) {
  170. dglInt32_t cap = dglEdgeGet_Cost(graph, edge);
  171. dglInt32_t id = dglEdgeGet_Id(graph, edge);
  172. dglInt32_t to =
  173. dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
  174. if (!visited[to] && cap > sign(id) * flow[abs(id)]) {
  175. visited[to] = 1;
  176. queue[end++] = to;
  177. }
  178. }
  179. dglEdgeset_T_Release(&et);
  180. }
  181. /*saturated edges from reachable vertices to non-reachable ones form a minimum cost */
  182. Vect_reset_list(cut);
  183. for (i = 1; i <= nnodes; i++) {
  184. if (!visited[i])
  185. continue;
  186. dglInt32_t *node, *edgeset, *edge;
  187. node = dglGetNode(graph, i);
  188. edgeset = dglNodeGet_OutEdgeset(graph, node);
  189. dglEdgeset_T_Initialize(&et, graph, edgeset);
  190. for (edge = dglEdgeset_T_First(&et); edge;
  191. edge = dglEdgeset_T_Next(&et)) {
  192. dglInt32_t to, edge_id;
  193. to = dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
  194. edge_id = abs(dglEdgeGet_Id(graph, edge));
  195. if (!visited[to] && flow[edge_id] != 0) {
  196. Vect_list_append(cut, edge_id);
  197. total_flow += abs(flow[abs(edge_id)]);
  198. }
  199. }
  200. dglEdgeset_T_Release(&et);
  201. }
  202. G_free(visited);
  203. G_free(queue);
  204. return total_flow;
  205. }
  206. /*!
  207. \brief Splits each vertex of in graph into two vertices
  208. The method splits each vertex of in graph into two vertices: in
  209. vertex and out vertex. Also, it adds an edge from an in vertex to
  210. the corresponding out vertex (capacity=2) and it adds an edge from
  211. out vertex to in vertex for each edge present in the in graph
  212. (forward capacity=1, backward capacity=0). If the id of a vertex is
  213. v then id of in vertex is 2*v-1 and of out vertex 2*v.
  214. \param in from graph
  215. \param out to graph
  216. \param node_cost list of node costs
  217. \return number of undirected edges in the graph
  218. \return -1 on failure
  219. */
  220. int NetA_split_vertices(dglGraph_s * in, dglGraph_s * out, int *node_costs)
  221. {
  222. dglInt32_t opaqueset[16] =
  223. { 360000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  224. dglNodeTraverser_s nt;
  225. dglInt32_t nnodes, edge_cnt;
  226. dglInt32_t *cur_node;
  227. nnodes = dglGet_NodeCount(in);
  228. dglInitialize(out, (dglByte_t) 1, (dglInt32_t) 0, (dglInt32_t) 0,
  229. opaqueset);
  230. dglNode_T_Initialize(&nt, in);
  231. edge_cnt = 0;
  232. dglInt32_t max_node_cost = 0;
  233. for (cur_node = dglNode_T_First(&nt); cur_node;
  234. cur_node = dglNode_T_Next(&nt)) {
  235. dglInt32_t v = dglNodeGet_Id(in, cur_node);
  236. edge_cnt++;
  237. dglInt32_t cost = 1;
  238. if (node_costs)
  239. cost = node_costs[v];
  240. if (cost > max_node_cost)
  241. max_node_cost = cost;
  242. dglAddEdge(out, 2 * v - 1, 2 * v, cost, edge_cnt);
  243. dglAddEdge(out, 2 * v, 2 * v - 1, (dglInt32_t) 0, -edge_cnt);
  244. }
  245. dglNode_T_Release(&nt);
  246. dglNode_T_Initialize(&nt, in);
  247. for (cur_node = dglNode_T_First(&nt); cur_node;
  248. cur_node = dglNode_T_Next(&nt)) {
  249. dglEdgesetTraverser_s et;
  250. dglInt32_t *edge;
  251. dglInt32_t v = dglNodeGet_Id(in, cur_node);
  252. dglEdgeset_T_Initialize(&et, in, dglNodeGet_OutEdgeset(in, cur_node));
  253. for (edge = dglEdgeset_T_First(&et); edge;
  254. edge = dglEdgeset_T_Next(&et)) {
  255. dglInt32_t to;
  256. to = dglNodeGet_Id(in, dglEdgeGet_Tail(in, edge));
  257. edge_cnt++;
  258. dglAddEdge(out, 2 * v, 2 * to - 1, max_node_cost + 1, edge_cnt);
  259. dglAddEdge(out, 2 * to - 1, 2 * v, (dglInt32_t) 0, -edge_cnt);
  260. }
  261. dglEdgeset_T_Release(&et);
  262. }
  263. dglNode_T_Release(&nt);
  264. if (dglFlatten(out) < 0)
  265. G_fatal_error(_("GngFlatten error"));
  266. return edge_cnt;
  267. }