shortestpth.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. #include <pathplan/vis.h>
  11. #include <util/alloc.h>
  12. static COORD unseen = (double) INT_MAX;
  13. /* shortestPath:
  14. * Given a VxV weighted adjacency matrix, compute the shortest
  15. * path vector from root to target. The returned vector (dad) encodes the
  16. * shorted path from target to the root. That path is given by
  17. * i, dad[i], dad[dad[i]], ..., root
  18. * We have dad[root] = -1.
  19. *
  20. * Based on Dijkstra's algorithm (Sedgewick, 2nd. ed., p. 466).
  21. *
  22. * This implementation only uses the lower left triangle of the
  23. * adjacency matrix, i.e., the values a[i][j] where i >= j.
  24. */
  25. static int *shortestPath(int root, int target, int V, array2 wadj)
  26. {
  27. COORD *val;
  28. int min;
  29. int k, t;
  30. /* allocate arrays */
  31. int *dad = gv_calloc(V, sizeof(int));
  32. COORD *vl = gv_calloc(V + 1, sizeof(COORD)); // One extra for sentinel
  33. val = vl + 1;
  34. /* initialize arrays */
  35. for (k = 0; k < V; k++) {
  36. dad[k] = -1;
  37. val[k] = -unseen;
  38. }
  39. val[-1] = -(unseen + (COORD) 1); /* Set sentinel */
  40. min = root;
  41. /* use (min >= 0) to fill entire tree */
  42. while (min != target) {
  43. k = min;
  44. val[k] *= -1;
  45. min = -1;
  46. if (val[k] == unseen)
  47. val[k] = 0;
  48. for (t = 0; t < V; t++) {
  49. if (val[t] < 0) {
  50. COORD newpri;
  51. COORD wkt;
  52. /* Use lower triangle */
  53. if (k >= t)
  54. wkt = wadj[k][t];
  55. else
  56. wkt = wadj[t][k];
  57. newpri = -(val[k] + wkt);
  58. if ((wkt != 0) && (val[t] < newpri)) {
  59. val[t] = newpri;
  60. dad[t] = k;
  61. }
  62. if (val[t] > val[min])
  63. min = t;
  64. }
  65. }
  66. }
  67. free(vl);
  68. return dad;
  69. }
  70. /* makePath:
  71. * Given two points p and q in two polygons pp and qp of a vconfig_t conf,
  72. * and the visibility vectors of p and q relative to conf,
  73. * compute the shortest path from p to q.
  74. * If dad is the returned array and V is the number of polygon vertices in
  75. * conf, then the path is V(==q), dad[V], dad[dad[V]], ..., V+1(==p).
  76. * NB: This is the only path that is guaranteed to be valid.
  77. * We have dad[V+1] = -1.
  78. *
  79. */
  80. int *makePath(Ppoint_t p, int pp, COORD * pvis,
  81. Ppoint_t q, int qp, COORD * qvis, vconfig_t * conf)
  82. {
  83. int V = conf->N;
  84. if (directVis(p, pp, q, qp, conf)) {
  85. int *dad = gv_calloc(V + 2, sizeof(int));
  86. dad[V] = V + 1;
  87. dad[V + 1] = -1;
  88. return dad;
  89. } else {
  90. array2 wadj = conf->vis;
  91. wadj[V] = qvis;
  92. wadj[V + 1] = pvis;
  93. return (shortestPath(V + 1, V, V + 2, wadj));
  94. }
  95. }