flow.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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. int have_node_costs;
  46. dglInt32_t ncost;
  47. nnodes = dglGet_NodeCount(graph);
  48. nlines = dglGet_EdgeCount(graph) / 2; /*each line corresponds to two edges. One in each direction */
  49. queue = (dglInt32_t *) G_calloc(nnodes + 3, sizeof(dglInt32_t));
  50. prev = (dglInt32_t **) G_calloc(nnodes + 3, sizeof(dglInt32_t *));
  51. is_source = (char *)G_calloc(nnodes + 3, sizeof(char));
  52. is_sink = (char *)G_calloc(nnodes + 3, sizeof(char));
  53. if (!queue || !prev || !is_source || !is_sink) {
  54. G_fatal_error(_("Out of memory"));
  55. return -1;
  56. }
  57. for (i = 0; i < source_list->n_values; i++)
  58. is_source[source_list->value[i]] = 1;
  59. for (i = 0; i < sink_list->n_values; i++)
  60. is_sink[sink_list->value[i]] = 1;
  61. for (i = 0; i <= nlines; i++)
  62. flow[i] = 0;
  63. ncost = 0;
  64. have_node_costs = dglGet_NodeAttrSize(graph);
  65. total_flow = 0;
  66. while (1) {
  67. dglInt32_t node, edge_id, min_residue;
  68. int found = -1;
  69. begin = end = 0;
  70. for (i = 0; i < source_list->n_values; i++)
  71. queue[end++] = source_list->value[i];
  72. for (i = 1; i <= nnodes; i++) {
  73. prev[i] = NULL;
  74. }
  75. while (begin != end && found == -1) {
  76. dglInt32_t vertex = queue[begin++];
  77. dglInt32_t *edge, *node = dglGetNode(graph, vertex);
  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 cap = dglEdgeGet_Cost(graph, edge);
  83. dglInt32_t id = dglEdgeGet_Id(graph, edge);
  84. dglInt32_t to =
  85. dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
  86. if (!is_source[to] && prev[to] == NULL &&
  87. cap > sign(id) * flow[labs(id)]) {
  88. prev[to] = edge;
  89. if (is_sink[to]) {
  90. found = to;
  91. break;
  92. }
  93. /* do not go through closed nodes */
  94. if (have_node_costs) {
  95. memcpy(&ncost, dglNodeGet_Attr(graph, dglEdgeGet_Tail(graph, edge)),
  96. sizeof(ncost));
  97. }
  98. if (ncost >= 0)
  99. queue[end++] = to;
  100. }
  101. }
  102. dglEdgeset_T_Release(&et);
  103. }
  104. if (found == -1)
  105. break; /*no augmenting path */
  106. /*find minimum residual capacity along the augmenting path */
  107. node = found;
  108. edge_id = dglEdgeGet_Id(graph, prev[node]);
  109. min_residue =
  110. dglEdgeGet_Cost(graph,
  111. prev[node]) - sign(edge_id) * flow[labs(edge_id)];
  112. while (!is_source[node]) {
  113. dglInt32_t residue;
  114. edge_id = dglEdgeGet_Id(graph, prev[node]);
  115. residue =
  116. dglEdgeGet_Cost(graph,
  117. prev[node]) -
  118. sign(edge_id) * flow[labs(edge_id)];
  119. if (residue < min_residue)
  120. min_residue = residue;
  121. node = dglNodeGet_Id(graph, dglEdgeGet_Head(graph, prev[node]));
  122. }
  123. total_flow += min_residue;
  124. /*update flow along the augmenting path */
  125. node = found;
  126. while (!is_source[node]) {
  127. edge_id = dglEdgeGet_Id(graph, prev[node]);
  128. flow[labs(edge_id)] += sign(edge_id) * min_residue;
  129. node = dglNodeGet_Id(graph, dglEdgeGet_Head(graph, prev[node]));
  130. }
  131. }
  132. G_free(queue);
  133. G_free(prev);
  134. G_free(is_source);
  135. G_free(is_sink);
  136. return total_flow;
  137. }
  138. /*!
  139. \brief Calculates minimum cut between source(s) and sink(s).
  140. Flow is the array produced by NetA_flow() method when called with
  141. source_list and sink_list as the input. The output of this and
  142. NetA_flow() method should be the same.
  143. \param graph input graph
  144. \param source_list list of sources
  145. \param sink_list list of sinks
  146. \param flow
  147. \param[out] cut list of edges (cut)
  148. \return number of edges
  149. \return -1 on failure
  150. */
  151. int NetA_min_cut(dglGraph_s * graph, struct ilist *source_list,
  152. struct ilist *sink_list, int *flow, struct ilist *cut)
  153. {
  154. int nnodes, i;
  155. dglEdgesetTraverser_s et;
  156. dglInt32_t *queue;
  157. char *visited;
  158. int begin, end, total_flow;
  159. nnodes = dglGet_NodeCount(graph);
  160. queue = (dglInt32_t *) G_calloc(nnodes + 3, sizeof(dglInt32_t));
  161. visited = (char *)G_calloc(nnodes + 3, sizeof(char));
  162. if (!queue || !visited) {
  163. G_fatal_error(_("Out of memory"));
  164. return -1;
  165. }
  166. total_flow = begin = end = 0;
  167. for (i = 1; i <= nnodes; i++)
  168. visited[i] = 0;
  169. for (i = 0; i < source_list->n_values; i++) {
  170. queue[end++] = source_list->value[i];
  171. visited[source_list->value[i]] = 1;
  172. }
  173. /* find vertices reachable from source(s) using only non-saturated edges */
  174. while (begin != end) {
  175. dglInt32_t vertex = queue[begin++];
  176. dglInt32_t *edge, *node = dglGetNode(graph, vertex);
  177. dglEdgeset_T_Initialize(&et, graph,
  178. dglNodeGet_OutEdgeset(graph, node));
  179. for (edge = dglEdgeset_T_First(&et); edge;
  180. edge = dglEdgeset_T_Next(&et)) {
  181. dglInt32_t cap = dglEdgeGet_Cost(graph, edge);
  182. dglInt32_t id = dglEdgeGet_Id(graph, edge);
  183. dglInt32_t to =
  184. dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
  185. if (!visited[to] && cap > sign(id) * flow[labs(id)]) {
  186. visited[to] = 1;
  187. queue[end++] = to;
  188. }
  189. }
  190. dglEdgeset_T_Release(&et);
  191. }
  192. /*saturated edges from reachable vertices to non-reachable ones form a minimum cost */
  193. Vect_reset_list(cut);
  194. for (i = 1; i <= nnodes; i++) {
  195. if (!visited[i])
  196. continue;
  197. dglInt32_t *node, *edgeset, *edge;
  198. node = dglGetNode(graph, i);
  199. edgeset = dglNodeGet_OutEdgeset(graph, node);
  200. dglEdgeset_T_Initialize(&et, graph, edgeset);
  201. for (edge = dglEdgeset_T_First(&et); edge;
  202. edge = dglEdgeset_T_Next(&et)) {
  203. dglInt32_t to, edge_id;
  204. to = dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
  205. edge_id = labs(dglEdgeGet_Id(graph, edge));
  206. if (!visited[to] && flow[edge_id] != 0) {
  207. Vect_list_append(cut, edge_id);
  208. total_flow += abs(flow[labs(edge_id)]);
  209. }
  210. }
  211. dglEdgeset_T_Release(&et);
  212. }
  213. G_free(visited);
  214. G_free(queue);
  215. return total_flow;
  216. }
  217. /*!
  218. \brief Splits each vertex of in graph into two vertices
  219. The method splits each vertex of in graph into two vertices: in
  220. vertex and out vertex. Also, it adds an edge from an in vertex to
  221. the corresponding out vertex (capacity=2) and it adds an edge from
  222. out vertex to in vertex for each edge present in the in graph
  223. (forward capacity=1, backward capacity=0). If the id of a vertex is
  224. v then id of in vertex is 2*v-1 and of out vertex 2*v.
  225. \param in from graph
  226. \param out to graph
  227. \param node_costs list of node costs
  228. \return number of undirected edges in the graph
  229. \return -1 on failure
  230. */
  231. int NetA_split_vertices(dglGraph_s * in, dglGraph_s * out, int *node_costs)
  232. {
  233. dglInt32_t opaqueset[16] =
  234. { 360000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  235. dglNodeTraverser_s nt;
  236. dglInt32_t nnodes, edge_cnt;
  237. dglInt32_t *cur_node;
  238. nnodes = dglGet_NodeCount(in);
  239. dglInitialize(out, (dglByte_t) 1, (dglInt32_t) 0, (dglInt32_t) 0,
  240. opaqueset);
  241. dglNode_T_Initialize(&nt, in);
  242. edge_cnt = 0;
  243. dglInt32_t max_node_cost = 0;
  244. for (cur_node = dglNode_T_First(&nt); cur_node;
  245. cur_node = dglNode_T_Next(&nt)) {
  246. dglInt32_t v = dglNodeGet_Id(in, cur_node);
  247. edge_cnt++;
  248. dglInt32_t cost = 1;
  249. if (node_costs)
  250. cost = node_costs[v];
  251. /* skip closed nodes */
  252. if (cost < 0)
  253. continue;
  254. if (cost > max_node_cost)
  255. max_node_cost = cost;
  256. dglAddEdge(out, 2 * v - 1, 2 * v, cost, edge_cnt);
  257. dglAddEdge(out, 2 * v, 2 * v - 1, (dglInt32_t) 0, -edge_cnt);
  258. }
  259. dglNode_T_Release(&nt);
  260. dglNode_T_Initialize(&nt, in);
  261. for (cur_node = dglNode_T_First(&nt); cur_node;
  262. cur_node = dglNode_T_Next(&nt)) {
  263. dglEdgesetTraverser_s et;
  264. dglInt32_t *edge;
  265. dglInt32_t v = dglNodeGet_Id(in, cur_node);
  266. dglInt32_t cost = 1;
  267. if (node_costs)
  268. cost = node_costs[v];
  269. /* skip closed nodes */
  270. if (cost < 0)
  271. continue;
  272. dglEdgeset_T_Initialize(&et, in, dglNodeGet_OutEdgeset(in, cur_node));
  273. for (edge = dglEdgeset_T_First(&et); edge;
  274. edge = dglEdgeset_T_Next(&et)) {
  275. dglInt32_t to;
  276. to = dglNodeGet_Id(in, dglEdgeGet_Tail(in, edge));
  277. edge_cnt++;
  278. dglAddEdge(out, 2 * v, 2 * to - 1, max_node_cost + 1, edge_cnt);
  279. dglAddEdge(out, 2 * to - 1, 2 * v, (dglInt32_t) 0, -edge_cnt);
  280. }
  281. dglEdgeset_T_Release(&et);
  282. }
  283. dglNode_T_Release(&nt);
  284. if (dglFlatten(out) < 0)
  285. G_fatal_error(_("GngFlatten error"));
  286. return edge_cnt;
  287. }