centrality.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*!
  2. \file lib/vector/neta/centrality.c
  3. \brief Network Analysis library - centrality
  4. Centrality measures
  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. #include <grass/neta.h>
  17. /*!
  18. \brief Computes degree centrality measure.
  19. Array degree has to be properly initialised to nnodes+1 elements
  20. \param graph input graph
  21. \param[out] degree array of degrees
  22. */
  23. void NetA_degree_centrality(dglGraph_s * graph, double *degree)
  24. {
  25. int i;
  26. double nnodes = dglGet_NodeCount(graph);
  27. for (i = 1; i <= nnodes; i++)
  28. degree[i] =
  29. dglNodeGet_OutDegree(graph,
  30. dglGetNode(graph, (dglInt32_t) i)) / nnodes;
  31. }
  32. /*!
  33. \brief Computes eigenvector centrality using edge costs as weights.
  34. \param graph input graph
  35. \param iterations number of iterations
  36. \param error ?
  37. \param[out] eigenvector eigen vector value
  38. \return 0 on success
  39. \return -1 on failure
  40. */
  41. int NetA_eigenvector_centrality(dglGraph_s * graph, int iterations,
  42. double error, double *eigenvector)
  43. {
  44. int i, iter, nnodes;
  45. double *tmp;
  46. nnodes = dglGet_NodeCount(graph);
  47. tmp = (double *)G_calloc(nnodes + 1, sizeof(double));
  48. if (!tmp) {
  49. G_fatal_error(_("Out of memory"));
  50. return -1;
  51. }
  52. error *= error;
  53. for (i = 1; i <= nnodes; i++)
  54. eigenvector[i] = 1;
  55. for (iter = 0; iter < iterations; iter++) {
  56. for (i = 1; i <= nnodes; i++)
  57. tmp[i] = 0;
  58. dglInt32_t *node;
  59. dglNodeTraverser_s nt;
  60. dglEdgesetTraverser_s et;
  61. dglNode_T_Initialize(&nt, graph);
  62. for (node = dglNode_T_First(&nt); node; node = dglNode_T_Next(&nt)) {
  63. dglInt32_t node_id = dglNodeGet_Id(graph, node);
  64. double cur_value = eigenvector[node_id];
  65. dglInt32_t *edge;
  66. dglEdgeset_T_Initialize(&et, graph,
  67. dglNodeGet_OutEdgeset(graph, node));
  68. for (edge = dglEdgeset_T_First(&et); edge;
  69. edge = dglEdgeset_T_Next(&et))
  70. tmp[dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge))] +=
  71. cur_value * dglEdgeGet_Cost(graph, edge);
  72. dglEdgeset_T_Release(&et);
  73. }
  74. dglNode_T_Release(&nt);
  75. double cum_error = 0, max_value = tmp[1];
  76. for (i = 2; i <= nnodes; i++)
  77. if (tmp[i] > max_value)
  78. max_value = tmp[i];
  79. for (i = 1; i <= nnodes; i++) {
  80. tmp[i] /= max_value;
  81. cum_error +=
  82. (tmp[i] - eigenvector[i]) * (tmp[i] - eigenvector[i]);
  83. eigenvector[i] = tmp[i];
  84. }
  85. if (cum_error < error)
  86. break;
  87. }
  88. G_free(tmp);
  89. return 0;
  90. }
  91. /*!
  92. \brief Computes betweenness and closeness centrality measure using Brandes algorithm.
  93. Edge costs must be nonnegative. If some edge costs are negative then
  94. the behaviour of this method is undefined.
  95. \param graph input graph
  96. \param[out] betweenness betweeness values
  97. \param[out] closeness cloneness values
  98. \return 0 on success
  99. \return -1 on failure
  100. */
  101. int NetA_betweenness_closeness(dglGraph_s * graph, double *betweenness,
  102. double *closeness)
  103. {
  104. int i, j, nnodes, stack_size, count;
  105. dglInt32_t *dst, *node, *stack, *cnt, *delta;
  106. dglNodeTraverser_s nt;
  107. dglEdgesetTraverser_s et;
  108. dglHeap_s heap;
  109. struct ilist **prev;
  110. nnodes = dglGet_NodeCount(graph);
  111. dst = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
  112. prev = (struct ilist **)G_calloc(nnodes + 1, sizeof(struct ilist *));
  113. stack = (dglInt32_t *) G_calloc(nnodes, sizeof(dglInt32_t));
  114. cnt = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
  115. delta = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
  116. if (!dst || !prev || !stack || !cnt || !delta) {
  117. G_fatal_error(_("Out of memory"));
  118. return -1;
  119. }
  120. for (i = 1; i <= nnodes; i++) {
  121. prev[i] = Vect_new_list();
  122. if (closeness)
  123. closeness[i] = 0;
  124. if (betweenness)
  125. betweenness[i] = 0;
  126. }
  127. count = 0;
  128. G_percent_reset();
  129. dglNode_T_Initialize(&nt, graph);
  130. for (node = dglNode_T_First(&nt); node; node = dglNode_T_Next(&nt)) {
  131. G_percent(count++, nnodes, 1);
  132. dglInt32_t s = dglNodeGet_Id(graph, node);
  133. dglHeapData_u heap_data;
  134. dglHeapNode_s heap_node;
  135. stack_size = 0;
  136. for (i = 1; i <= nnodes; i++)
  137. Vect_reset_list(prev[i]);
  138. for (i = 1; i <= nnodes; i++) {
  139. cnt[i] = 0;
  140. dst[i] = -1;
  141. }
  142. dst[s] = 0;
  143. cnt[s] = 1;
  144. dglHeapInit(&heap);
  145. heap_data.ul = s;
  146. dglHeapInsertMin(&heap, 0, ' ', heap_data);
  147. while (1) {
  148. dglInt32_t v, dist;
  149. if (!dglHeapExtractMin(&heap, &heap_node))
  150. break;
  151. v = heap_node.value.ul;
  152. dist = heap_node.key;
  153. if (dst[v] < dist)
  154. continue;
  155. stack[stack_size++] = v;
  156. dglInt32_t *edge;
  157. dglEdgeset_T_Initialize(&et, graph,
  158. dglNodeGet_OutEdgeset(graph,
  159. dglGetNode(graph,
  160. v)));
  161. for (edge = dglEdgeset_T_First(&et); edge;
  162. edge = dglEdgeset_T_Next(&et)) {
  163. dglInt32_t *to = dglEdgeGet_Tail(graph, edge);
  164. dglInt32_t to_id = dglNodeGet_Id(graph, to);
  165. dglInt32_t d = dglEdgeGet_Cost(graph, edge);
  166. if (dst[to_id] == -1 || dst[to_id] > dist + d) {
  167. dst[to_id] = dist + d;
  168. Vect_reset_list(prev[to_id]);
  169. heap_data.ul = to_id;
  170. dglHeapInsertMin(&heap, dist + d, ' ', heap_data);
  171. }
  172. if (dst[to_id] == dist + d) {
  173. cnt[to_id] += cnt[v];
  174. Vect_list_append(prev[to_id], v);
  175. }
  176. }
  177. dglEdgeset_T_Release(&et);
  178. }
  179. dglHeapFree(&heap, NULL);
  180. for (i = 1; i <= nnodes; i++)
  181. delta[i] = 0;
  182. for (i = stack_size - 1; i >= 0; i--) {
  183. dglInt32_t w = stack[i];
  184. if (closeness)
  185. closeness[s] += dst[w];
  186. for (j = 0; j < prev[w]->n_values; j++) {
  187. dglInt32_t v = prev[w]->value[j];
  188. delta[v] += (cnt[v] / (double)cnt[w]) * (1.0 + delta[w]);
  189. }
  190. if (w != s && betweenness)
  191. betweenness[w] += delta[w];
  192. }
  193. if (closeness)
  194. closeness[s] /= (double)stack_size;
  195. }
  196. dglNode_T_Release(&nt);
  197. for (i = 1; i <= nnodes; i++)
  198. Vect_destroy_list(prev[i]);
  199. G_free(delta);
  200. G_free(cnt);
  201. G_free(stack);
  202. G_free(prev);
  203. G_free(dst);
  204. return 0;
  205. };