shortest_path.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /* LIBDGL -- a Directed Graph Library implementation
  2. * Copyright (C) 2002 Roberto Micarelli
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. /* best view tabstop=4
  19. */
  20. #include <stdio.h>
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include <unistd.h>
  24. #include <stdlib.h>
  25. #include <fcntl.h>
  26. #include <time.h>
  27. #include <errno.h>
  28. #include "../type.h"
  29. #include "../graph.h"
  30. #include "opt.h"
  31. extern int errno;
  32. /* If the clipper function returns 1 , the node is discarded and
  33. * the traversing of the graph toward its direction is abandoned.
  34. * Try to change the return value to 1 and see that the program
  35. * will not find any more paths to destinations.
  36. * The clipper receives data relating the network segment being examined.
  37. * The pvarg is a user pointer registered to dglShortestPath() and
  38. * passed back to the clipper.
  39. * As a demo, the main uses the ClipperContext_s structure to store a nodeid
  40. * that must be discarded during the search. The clipper receives
  41. * that pointer and checks every node against the one specified there.
  42. * If the node matches return 1 , otherwise return 0.
  43. */
  44. typedef struct
  45. {
  46. dglInt32_t node_to_discard;
  47. } ClipperContext_s;
  48. static int clipper(dglGraph_s * pgraph, dglSPClipInput_s * pIn, dglSPClipOutput_s * pOut, void *pvarg /* caller's pointer */
  49. )
  50. {
  51. ClipperContext_s *pclip = (ClipperContext_s *) pvarg;
  52. #if 0
  53. dglInt32_t *pnFromXYZ =
  54. (dglInt32_t *) dglNodeGet_Attr(pgraph, pIn->pnNodeFrom);
  55. dglInt32_t *pnToXYZ =
  56. (dglInt32_t *) dglNodeGet_Attr(pgraph, pIn->pnNodeTo);
  57. printf("clipper called:\n");
  58. printf(" from node: %ld - attributes x=%ld y=%ld z=%ld\n",
  59. dglNodeGet_Id(pgraph, pIn->pnNodeFrom), pnFromXYZ[0], pnFromXYZ[1],
  60. pnFromXYZ[2]);
  61. printf(" to node: %ld - attributes x=%ld y=%ld z=%ld\n",
  62. dglNodeGet_Id(pgraph, pIn->pnNodeTo), pnToXYZ[0], pnToXYZ[1],
  63. pnToXYZ[2]);
  64. printf(" edge : %ld\n", dglEdgeGet_Id(pgraph, pIn->pnEdge));
  65. #endif
  66. if (pclip) {
  67. if (dglNodeGet_Id(pgraph, pIn->pnNodeTo) == pclip->node_to_discard) {
  68. /*
  69. printf( " discarder.\n" );
  70. */
  71. return 1;
  72. }
  73. }
  74. /*
  75. printf( " accepted.\n" );
  76. */
  77. return 0;
  78. }
  79. int main(int argc, char **argv)
  80. {
  81. dglGraph_s graph;
  82. dglInt32_t from, to;
  83. int fd, nret, version;
  84. dglSPReport_s *pReport;
  85. dglInt32_t nDistance;
  86. dglSPCache_s spCache;
  87. ClipperContext_s clipctx, *pclipctx;
  88. /* program options
  89. */
  90. char *pszFilein;
  91. char *pszFrom;
  92. char *pszTo;
  93. char *pszDiscard;
  94. char *pszVersion;
  95. Boolean fDistance;
  96. Boolean fUnflatten;
  97. GNO_BEGIN /*short long default variable help */
  98. GNO_OPTION("g", "graph", NULL, &pszFilein, "graph file to view")
  99. GNO_OPTION("v", "version", NULL, &pszVersion, "alter graph version")
  100. GNO_OPTION("f", "from", NULL, &pszFrom, "from-node id")
  101. GNO_OPTION("t", "to", NULL, &pszTo, "to-node id")
  102. GNO_OPTION("d", "discard", NULL, &pszDiscard,
  103. "node to discard in clipper")
  104. GNO_SWITCH("D", "distance", False, &fDistance,
  105. "Report shortest distance only")
  106. GNO_SWITCH("U", "unflatten", False, &fUnflatten,
  107. "Unflatten the graph before processing")
  108. GNO_END if (GNO_PARSE(argc, argv) < 0) {
  109. return 1;
  110. }
  111. /* options parsed
  112. */
  113. if (pszFilein == NULL || pszFrom == NULL || pszTo == NULL) {
  114. GNO_HELP("incomplete parameters");
  115. return 1;
  116. }
  117. if (pszDiscard) {
  118. clipctx.node_to_discard = atol(pszDiscard);
  119. pclipctx = &clipctx;
  120. }
  121. else
  122. pclipctx = NULL;
  123. if (pszVersion) {
  124. version = atoi(pszVersion);
  125. }
  126. fd = open(pszFilein, O_RDONLY);
  127. if (fd < 0) {
  128. perror("open");
  129. return 1;
  130. }
  131. nret = dglRead(&graph, fd);
  132. close(fd);
  133. if (nret < 0) {
  134. fprintf(stderr, "dglRead error: %s\n", dglStrerror(&graph));
  135. return 1;
  136. }
  137. if (fUnflatten)
  138. dglUnflatten(&graph);
  139. if (pszVersion)
  140. dglSet_Version(&graph, version);
  141. from = atol(pszFrom);
  142. to = atol(pszTo);
  143. printf("shortest path: from-node %ld - to-node %ld\n\n", from, to);
  144. dglInitializeSPCache(&graph, &spCache);
  145. if (fDistance == False) {
  146. nret =
  147. dglShortestPath(&graph, &pReport, from, to, clipper, pclipctx,
  148. &spCache);
  149. if (nret == 0) {
  150. printf("destination node is unreachable\n\n");
  151. }
  152. else if (nret < 0) {
  153. fprintf(stderr, "dglShortestPath error: %s\n",
  154. dglStrerror(&graph));
  155. }
  156. else {
  157. int i;
  158. printf
  159. ("shortest path report: total edges %ld - total distance %ld\n",
  160. pReport->cArc, pReport->nDistance);
  161. for (i = 0; i < pReport->cArc; i++) {
  162. printf("edge[%d]: from %ld to %ld - travel cost %ld - user edgeid %ld - distance from start node %ld\n", i, pReport->pArc[i].nFrom, pReport->pArc[i].nTo, dglEdgeGet_Cost(&graph, pReport->pArc[i].pnEdge), /* this is the cost from clip() */
  163. dglEdgeGet_Id(&graph, pReport->pArc[i].pnEdge),
  164. pReport->pArc[i].nDistance);
  165. }
  166. dglFreeSPReport(&graph, pReport);
  167. }
  168. }
  169. else {
  170. nret =
  171. dglShortestDistance(&graph, &nDistance, from, to, clipper,
  172. pclipctx, &spCache);
  173. if (nret == 0) {
  174. if (dglErrno(&graph) == 0) {
  175. printf("destination node is unreachable\n\n");
  176. }
  177. }
  178. else if (nret < 0) {
  179. fprintf(stderr, "dglShortestDistance error: %s\n",
  180. dglStrerror(&graph));
  181. }
  182. else {
  183. printf("shortest distance: %ld\n", nDistance);
  184. }
  185. }
  186. dglReleaseSPCache(&graph, &spCache);
  187. dglRelease(&graph);
  188. return 0;
  189. }