network.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /****************************************************************
  2. *
  3. * MODULE: v.generalize
  4. *
  5. * AUTHOR(S): Daniel Bundala
  6. *
  7. * PURPOSE: Network generalization
  8. *
  9. * COPYRIGHT: (C) 2002-2005 by the GRASS Development Team
  10. *
  11. * This program is free software under the
  12. * GNU General Public License (>=v2).
  13. * Read the file COPYING that comes with GRASS
  14. * for details.
  15. *
  16. ****************************************************************/
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <grass/gis.h>
  21. #include <grass/vector.h>
  22. #include <grass/glocale.h>
  23. typedef struct
  24. {
  25. int **edge; /* edge for each vertex */
  26. int *degree; /* degree of vertices */
  27. int vertices;
  28. } NdglGraph_s;
  29. void graph_free(NdglGraph_s * g)
  30. {
  31. int i;
  32. return;
  33. G_free(g->degree);
  34. if (g->edge) {
  35. for (i = 0; i < g->vertices; g++)
  36. G_free(g->edge[i]);
  37. }
  38. G_free(g->edge);
  39. return;
  40. }
  41. int graph_init(NdglGraph_s * g, int vertices)
  42. {
  43. g->edge = NULL;
  44. g->degree = NULL;
  45. g->vertices = vertices;
  46. g->degree = (int *)G_calloc(vertices, sizeof(int));
  47. if (!g->degree)
  48. return 0;
  49. g->edge = (int **)G_calloc(vertices, sizeof(int *));
  50. if (!g->edge) {
  51. graph_free(g);
  52. return 0;
  53. }
  54. return 1;
  55. }
  56. /* writes the most important part of the In network to Out network
  57. * according to the thresholds, output is bigger for smaller
  58. * thresholds. Function returns the number of points written
  59. TODO: rewrite ilist by something more space and time efficient
  60. or at least, implement append which does not check whether
  61. the value is already in the list*/
  62. int graph_generalization(struct Map_info *In, struct Map_info *Out,
  63. int mask_type, double degree_thresh,
  64. double closeness_thresh, double betweeness_thresh)
  65. {
  66. int i;
  67. int output = 0;
  68. dglGraph_s *gr;
  69. NdglGraph_s g;
  70. int nnodes;
  71. struct line_pnts *Points;
  72. struct line_cats *Cats;
  73. int type;
  74. int *closeness, *queue, *internal, *paths, *comp, *dist;
  75. double *betw, *betweeness;
  76. struct ilist **prev;
  77. if (0 != Vect_net_build_graph(In, mask_type, 0, 0, NULL, NULL, NULL, 0, 0))
  78. G_fatal_error(_("Unable to build graph for vector map <%s>"), Vect_get_full_name(In));
  79. gr = Vect_net_get_graph(In);
  80. /* build own graph by edge<->vertex */
  81. /* each vertex represents undirected edge */
  82. if (!graph_init(&g, dglGet_EdgeCount(gr) / 2 + 1)) {
  83. G_fatal_error(_("Out of memory"));
  84. return 0;
  85. }
  86. nnodes = dglGet_NodeCount(gr);
  87. for (i = 0; i < nnodes; i++) {
  88. dglInt32_t *node, *edgeset, *edge;
  89. dglEdgesetTraverser_s et;
  90. node = dglGetNode(gr, (dglInt32_t) i);
  91. edgeset = dglNodeGet_OutEdgeset(gr, node);
  92. dglEdgeset_T_Initialize(&et, gr, edgeset);
  93. for (edge = dglEdgeset_T_First(&et); edge;
  94. edge = dglEdgeset_T_Next(&et)) {
  95. int id, from_degree, to_degree;
  96. dglInt32_t *to, *from, *to_edgeset, *to_edge;
  97. dglEdgesetTraverser_s to_et;
  98. from = dglEdgeGet_Head(gr, edge);
  99. to = dglEdgeGet_Tail(gr, edge);
  100. to_edgeset = dglNodeGet_OutEdgeset(gr, to);
  101. dglEdgeset_T_Initialize(&to_et, gr, to_edgeset);
  102. to_degree = dglNodeGet_OutDegree(gr, to);
  103. from_degree = dglNodeGet_OutDegree(gr, from);
  104. id = abs(dglEdgeGet_Id(gr, edge));
  105. /* allocate memory, if it has not been not allocated already */
  106. if (!g.edge[id]) {
  107. g.edge[id] =
  108. G_malloc(sizeof(int) * (to_degree + from_degree));
  109. if (!g.edge[id]) {
  110. graph_free(&g);
  111. G_fatal_error(_("Out of memory"));
  112. return 0;
  113. }
  114. }
  115. for (to_edge = dglEdgeset_T_First(&to_et); to_edge;
  116. to_edge = dglEdgeset_T_Next(&to_et)) {
  117. int id2 = abs(dglEdgeGet_Id(gr, to_edge));
  118. g.edge[id][g.degree[id]++] = id2;
  119. }
  120. dglEdgeset_T_Release(&to_et);
  121. }
  122. dglEdgeset_T_Release(&et);
  123. }
  124. closeness = (int *)G_calloc(g.vertices, sizeof(int));
  125. queue = (int *)G_calloc(g.vertices, sizeof(int));
  126. dist = (int *)G_calloc(g.vertices, sizeof(int));
  127. internal = (int *)G_calloc(g.vertices, sizeof(int));
  128. betweeness = (double *)G_calloc(g.vertices, sizeof(double));
  129. paths = (int *)G_calloc(g.vertices, sizeof(int));
  130. comp = (int *)G_calloc(g.vertices, sizeof(int));
  131. betw = (double *)G_calloc(g.vertices, sizeof(double));
  132. prev = (struct ilist **)G_calloc(g.vertices, sizeof(struct ilist *));
  133. for (i = 0; i < g.vertices; i++)
  134. prev[i] = Vect_new_list();
  135. /* run BFS from each vertex and find the sum
  136. * of the shortest paths from each vertex */
  137. G_percent_reset();
  138. G_message(_("Calculating centrality measures..."));
  139. for (i = 1; i < g.vertices; i++) {
  140. int front, back, j;
  141. G_percent(i, g.vertices - 1, 1);
  142. front = 0;
  143. back = 1;
  144. queue[front] = i;
  145. /* Is this portable? */
  146. memset(dist, 127, sizeof(int) * g.vertices);
  147. dist[i] = 0;
  148. closeness[i] = 0;
  149. comp[i] = 0;
  150. memset(paths, 0, sizeof(int) * g.vertices);
  151. paths[i] = 1;
  152. memset(internal, 0, sizeof(int) * g.vertices);
  153. for (j = 0; j < g.vertices; j++)
  154. Vect_reset_list(prev[j]);
  155. while (front != back) {
  156. int v, j;
  157. v = queue[front];
  158. comp[i]++;
  159. front = (front + 1) % g.vertices;
  160. for (j = 0; j < g.degree[v]; j++) {
  161. int to = g.edge[v][j];
  162. if (dist[to] > dist[v] + 1) {
  163. paths[to] = paths[v];
  164. internal[v] = 1;
  165. dist[to] = dist[v] + 1;
  166. closeness[i] += dist[to];
  167. queue[back] = to;
  168. Vect_reset_list(prev[to]);
  169. Vect_list_append(prev[to], v);
  170. back = (back + 1) % g.vertices;
  171. }
  172. else if (dist[to] == dist[v] + 1) {
  173. internal[v] = 1;
  174. paths[to] += paths[v];
  175. Vect_list_append(prev[to], v);
  176. }
  177. }
  178. }
  179. /* finally run another BFS from the leaves in the BFS DAG
  180. * and calculate betweeness centrality measure */
  181. front = 0;
  182. back = 0;
  183. for (j = 1; j < g.vertices; j++)
  184. if (!internal[j] && dist[j] <= g.vertices) {
  185. queue[back] = j;
  186. back = (back + 1) % g.vertices;
  187. }
  188. memset(betw, 0, sizeof(double) * g.vertices);
  189. while (front != back) {
  190. int v, j;
  191. v = queue[front];
  192. front = (front + 1) % g.vertices;
  193. betweeness[v] += betw[v];
  194. for (j = 0; j < prev[v]->n_values; j++) {
  195. int to = prev[v]->value[j];
  196. if (betw[to] == 0) {
  197. queue[back] = to;
  198. back = (back + 1) % g.vertices;
  199. }
  200. betw[to] +=
  201. (betw[v] +
  202. (double)1.0) * ((double)paths[to] / (double)paths[v]);
  203. }
  204. }
  205. }
  206. Points = Vect_new_line_struct();
  207. Cats = Vect_new_cats_struct();
  208. for (i = 1; i < g.vertices; i++) {
  209. if ((g.degree[i] >= degree_thresh &&
  210. (comp[i] - 1.0) / closeness[i] >= closeness_thresh &&
  211. betweeness[i] >= betweeness_thresh)) {
  212. type = Vect_read_line(In, Points, Cats, i);
  213. if (type & mask_type) {
  214. output += Points->n_points;
  215. Vect_write_line(Out, type, Points, Cats);
  216. }
  217. }
  218. }
  219. G_free(dist);
  220. G_free(closeness);
  221. G_free(paths);
  222. G_free(betweeness);
  223. G_free(internal);
  224. G_free(queue);
  225. G_free(comp);
  226. G_free(betw);
  227. for (i = 0; i < g.vertices; i++)
  228. Vect_destroy_list(prev[i]);
  229. G_free(prev);
  230. graph_free(&g);
  231. return output;
  232. }