allpairs.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*!
  2. \file vector/neta/allpairs.c
  3. \brief Network Analysis library - shortest path between all pairs
  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. /*!
  18. \brief Stores the directed distance between every pair
  19. \todo Use only O(W*W) memory where W is the number of nodes present in the graph
  20. Upon the completion, dist stores the directed distance between every pair (i,j)
  21. or -1 if the nodes are unreachable. It must be an array of dimension [nodes+1]*[nodes+1]
  22. \param graph input graph
  23. \param[out] dist list of directed distance
  24. \return -1 on error
  25. \return 0 on success
  26. */
  27. int NetA_allpairs(dglGraph_s * graph, dglInt32_t ** dist)
  28. {
  29. int nnodes, i, j, k, indices;
  30. dglEdgesetTraverser_s et;
  31. dglNodeTraverser_s nt;
  32. dglInt32_t *node;
  33. nnodes = dglGet_NodeCount(graph);
  34. dglInt32_t *node_indices;
  35. node_indices = (dglInt32_t *) G_calloc(nnodes, sizeof(dglInt32_t));
  36. if (!node_indices) {
  37. G_fatal_error(_("Out of memory"));
  38. return -1;
  39. }
  40. G_message(_("Computing all pairs shortest paths..."));
  41. G_percent_reset();
  42. for (i = 0; i <= nnodes; i++)
  43. for (j = 0; j <= nnodes; j++)
  44. dist[i][j] = -1;
  45. dglNode_T_Initialize(&nt, graph);
  46. indices = 0;
  47. for (node = dglNode_T_First(&nt); node; node = dglNode_T_Next(&nt)) {
  48. dglInt32_t node_id = dglNodeGet_Id(graph, node);
  49. node_indices[indices++] = node_id;
  50. dglInt32_t *edge;
  51. dglEdgeset_T_Initialize(&et, graph,
  52. dglNodeGet_OutEdgeset(graph, node));
  53. for (edge = dglEdgeset_T_First(&et); edge;
  54. edge = dglEdgeset_T_Next(&et))
  55. if (dglEdgeGet_Id(graph, edge) < 0) /*ignore backward edges */
  56. dist[node_id][dglNodeGet_Id
  57. (graph, dglEdgeGet_Tail(graph, edge))] =
  58. dglEdgeGet_Cost(graph, edge);
  59. dglEdgeset_T_Release(&et);
  60. }
  61. dglNode_T_Release(&nt);
  62. for (k = 0; k < indices; k++) {
  63. dglInt32_t k_index = node_indices[k];
  64. G_percent(k + 1, indices, 1);
  65. for (i = 0; i < indices; i++) {
  66. dglInt32_t i_index = node_indices[i];
  67. if (dist[i_index][k_index] == -1)
  68. continue; /*no reason to proceed along infinite path */
  69. for (j = 0; j < indices; j++) {
  70. dglInt32_t j_index = node_indices[j];
  71. if (dist[k_index][j_index] != -1 &&
  72. (dist[i_index][k_index] + dist[k_index][j_index] <
  73. dist[i_index][j_index] ||
  74. dist[i_index][j_index] == -1)) {
  75. dist[i_index][j_index] =
  76. dist[i_index][k_index] + dist[k_index][j_index];
  77. }
  78. }
  79. }
  80. }
  81. G_free(node_indices);
  82. return 0;
  83. }