components.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*!
  2. \file vector/neta/components.c
  3. \brief Network Analysis library - graph componets
  4. Computes strongly and weakly connected components.
  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. */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <grass/gis.h>
  13. #include <grass/vector.h>
  14. #include <grass/glocale.h>
  15. #include <grass/dgl/graph.h>
  16. /*!
  17. \brief Computes weekly connected components
  18. \param graph input graph
  19. \param[out] component list of components
  20. \return number of components
  21. \return -1 on failure
  22. */
  23. int NetA_weakly_connected_components(dglGraph_s * graph, int *component)
  24. {
  25. int nnodes;
  26. dglInt32_t *stack;
  27. int *visited;
  28. int stack_size, components;
  29. dglInt32_t *cur_node;
  30. dglNodeTraverser_s nt;
  31. components = 0;
  32. nnodes = dglGet_NodeCount(graph);
  33. stack = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
  34. visited = (int *)G_calloc(nnodes + 1, sizeof(int));
  35. if (!stack || !visited) {
  36. G_fatal_error(_("Out of memory"));
  37. return -1;
  38. }
  39. dglNode_T_Initialize(&nt, graph);
  40. for (cur_node = dglNode_T_First(&nt); cur_node;
  41. cur_node = dglNode_T_Next(&nt)) {
  42. dglInt32_t node_id = dglNodeGet_Id(graph, cur_node);
  43. if (!visited[node_id]) {
  44. visited[node_id] = 1;
  45. stack[0] = node_id;
  46. stack_size = 1;
  47. component[node_id] = ++components;
  48. while (stack_size) {
  49. dglInt32_t *node, *edgeset, *edge;
  50. dglEdgesetTraverser_s et;
  51. node = dglGetNode(graph, stack[--stack_size]);
  52. edgeset = dglNodeGet_OutEdgeset(graph, node);
  53. dglEdgeset_T_Initialize(&et, graph, edgeset);
  54. for (edge = dglEdgeset_T_First(&et); edge;
  55. edge = dglEdgeset_T_Next(&et)) {
  56. dglInt32_t to;
  57. to = dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
  58. if (!visited[to]) {
  59. visited[to] = 1;
  60. component[to] = components;
  61. stack[stack_size++] = to;
  62. }
  63. }
  64. dglEdgeset_T_Release(&et);
  65. }
  66. }
  67. }
  68. dglNode_T_Release(&nt);
  69. G_free(visited);
  70. return components;
  71. }
  72. /*!
  73. \brief Computes strongly connected components
  74. \param graph input graph
  75. \param[out] component list of components
  76. \return number of components
  77. \return -1 on failure
  78. */
  79. int NetA_strongly_connected_components(dglGraph_s * graph, int *component)
  80. {
  81. int nnodes;
  82. dglInt32_t *stack, *order;
  83. int *visited, *processed;
  84. int stack_size, order_size, components;
  85. dglInt32_t *node;
  86. dglNodeTraverser_s nt;
  87. components = 0;
  88. nnodes = dglGet_NodeCount(graph);
  89. stack = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
  90. order = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
  91. visited = (int *)G_calloc(nnodes + 1, sizeof(int));
  92. processed = (int *)G_calloc(nnodes + 1, sizeof(int));
  93. if (!stack || !visited || !order || !processed) {
  94. G_fatal_error(_("Out of memory"));
  95. return -1;
  96. }
  97. order_size = 0;
  98. dglNode_T_Initialize(&nt, graph);
  99. for (node = dglNode_T_First(&nt); node; node = dglNode_T_Next(&nt)) {
  100. dglInt32_t node_id = dglNodeGet_Id(graph, node);
  101. component[node_id] = 0;
  102. if (!visited[node_id]) {
  103. visited[node_id] = 1;
  104. stack[0] = node_id;
  105. stack_size = 1;
  106. while (stack_size) {
  107. dglInt32_t *node, *edgeset, *edge;
  108. dglEdgesetTraverser_s et;
  109. dglInt32_t cur_node_id = stack[stack_size - 1];
  110. if (processed[cur_node_id]) {
  111. stack_size--;
  112. order[order_size++] = cur_node_id;
  113. continue;
  114. }
  115. processed[cur_node_id] = 1;
  116. node = dglGetNode(graph, cur_node_id);
  117. edgeset = dglNodeGet_OutEdgeset(graph, node);
  118. dglEdgeset_T_Initialize(&et, graph, edgeset);
  119. for (edge = dglEdgeset_T_First(&et); edge;
  120. edge = dglEdgeset_T_Next(&et)) {
  121. dglInt32_t to;
  122. if (dglEdgeGet_Id(graph, edge) < 0)
  123. continue; /*ignore backward edges */
  124. to = dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
  125. if (!visited[to]) {
  126. visited[to] = 1;
  127. stack[stack_size++] = to;
  128. }
  129. }
  130. dglEdgeset_T_Release(&et);
  131. }
  132. }
  133. }
  134. dglNode_T_Release(&nt);
  135. while (order_size) {
  136. dglInt32_t node_id = order[--order_size];
  137. if (component[node_id])
  138. continue;
  139. components++;
  140. component[node_id] = components;
  141. stack[0] = node_id;
  142. stack_size = 1;
  143. while (stack_size) {
  144. dglInt32_t *node, *edgeset, *edge;
  145. dglEdgesetTraverser_s et;
  146. dglInt32_t cur_node_id = stack[--stack_size];
  147. node = dglGetNode(graph, cur_node_id);
  148. edgeset = dglNodeGet_OutEdgeset(graph, node);
  149. dglEdgeset_T_Initialize(&et, graph, edgeset);
  150. for (edge = dglEdgeset_T_First(&et); edge;
  151. edge = dglEdgeset_T_Next(&et)) {
  152. dglInt32_t to;
  153. if (dglEdgeGet_Id(graph, edge) > 0)
  154. continue; /*ignore forward edges */
  155. to = dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
  156. if (!component[to]) {
  157. component[to] = components;
  158. stack[stack_size++] = to;
  159. }
  160. }
  161. dglEdgeset_T_Release(&et);
  162. }
  163. }
  164. G_free(stack);
  165. G_free(visited);
  166. G_free(order);
  167. G_free(processed);
  168. return components;
  169. }