sgraph.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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 "config.h"
  11. #include <limits.h>
  12. #include <ortho/sgraph.h>
  13. #include <ortho/fPQ.h>
  14. #include <util/alloc.h>
  15. void
  16. gsave (sgraph* G)
  17. {
  18. int i;
  19. G->save_nnodes = G->nnodes;
  20. G->save_nedges = G->nedges;
  21. for (i = 0; i < G->nnodes; i++)
  22. G->nodes[i].save_n_adj = G->nodes[i].n_adj;
  23. }
  24. void
  25. reset(sgraph* G)
  26. {
  27. int i;
  28. G->nnodes = G->save_nnodes;
  29. G->nedges = G->save_nedges;
  30. for (i = 0; i < G->nnodes; i++)
  31. G->nodes[i].n_adj = G->nodes[i].save_n_adj;
  32. for (; i < G->nnodes+2; i++)
  33. G->nodes[i].n_adj = 0;
  34. }
  35. void
  36. initSEdges (sgraph* g, int maxdeg)
  37. {
  38. int i;
  39. int* adj = gv_calloc(6 * g->nnodes + 2 * maxdeg, sizeof(int));
  40. g->edges = gv_calloc(3 * g->nnodes + maxdeg, sizeof(sedge));
  41. for (i = 0; i < g->nnodes; i++) {
  42. g->nodes[i].adj_edge_list = adj;
  43. adj += 6;
  44. }
  45. for (; i < g->nnodes+2; i++) {
  46. g->nodes[i].adj_edge_list = adj;
  47. adj += maxdeg;
  48. }
  49. }
  50. sgraph*
  51. createSGraph (int nnodes)
  52. {
  53. sgraph* g = gv_alloc(sizeof(sgraph));
  54. /* create the nodes vector in the search graph */
  55. g->nnodes = 0;
  56. g->nodes = gv_calloc(nnodes, sizeof(snode));
  57. return g;
  58. }
  59. snode*
  60. createSNode (sgraph* g)
  61. {
  62. snode* np = g->nodes+g->nnodes;
  63. np->index = g->nnodes;
  64. g->nnodes++;
  65. return np;
  66. }
  67. static void
  68. addEdgeToNode (snode* np, int idx)
  69. {
  70. np->adj_edge_list[np->n_adj] = idx;
  71. np->n_adj++;
  72. }
  73. sedge*
  74. createSEdge (sgraph* g, snode* v1, snode* v2, double wt)
  75. {
  76. sedge* e;
  77. int idx = g->nedges++;
  78. e = g->edges + idx;
  79. e->v1 = v1->index;
  80. e->v2 = v2->index;
  81. e->weight = wt;
  82. e->cnt = 0;
  83. addEdgeToNode (v1, idx);
  84. addEdgeToNode (v2, idx);
  85. return e;
  86. }
  87. void
  88. freeSGraph (sgraph* g)
  89. {
  90. free (g->nodes[0].adj_edge_list);
  91. free (g->nodes);
  92. free (g->edges);
  93. free (g);
  94. }
  95. #include <ortho/fPQ.h>
  96. /* shortest path:
  97. * Constructs the path of least weight between from and to.
  98. *
  99. * Assumes graph, node and edge type, and that nodes
  100. * have associated values N_VAL, N_IDX, and N_DAD, the first two
  101. * being ints, the last being a node*. Edges have a E_WT function
  102. * to specify the edge length or weight.
  103. *
  104. * Assumes there are functions:
  105. * agnnodes: graph -> int number of nodes in the graph
  106. * agfstnode, agnxtnode : iterators over the nodes in the graph
  107. * agfstedge, agnxtedge : iterators over the edges attached to a node
  108. * adjacentNode : given an edge e and an endpoint n of e, returns the
  109. * other endpoint.
  110. *
  111. * The path is given by
  112. * to, N_DAD(to), N_DAD(N_DAD(to)), ..., from
  113. */
  114. #define UNSEEN INT_MIN
  115. static snode*
  116. adjacentNode(sgraph* g, sedge* e, snode* n)
  117. {
  118. if (e->v1==n->index)
  119. return &g->nodes[e->v2];
  120. else
  121. return &g->nodes[e->v1];
  122. }
  123. int
  124. shortPath (sgraph* g, snode* from, snode* to)
  125. {
  126. snode* n;
  127. sedge* e;
  128. snode* adjn;
  129. int d;
  130. int x, y;
  131. for (x = 0; x<g->nnodes; x++) {
  132. snode* temp = &g->nodes[x];
  133. N_VAL(temp) = UNSEEN;
  134. }
  135. PQinit();
  136. if (PQ_insert (from)) return 1;
  137. N_DAD(from) = NULL;
  138. N_VAL(from) = 0;
  139. while ((n = PQremove())) {
  140. #ifdef DEBUG
  141. fprintf (stderr, "process %d\n", n->index);
  142. #endif
  143. N_VAL(n) *= -1;
  144. if (n == to) break;
  145. for (y=0; y<n->n_adj; y++) {
  146. e = &g->edges[n->adj_edge_list[y]];
  147. adjn = adjacentNode(g, e, n);
  148. if (N_VAL(adjn) < 0) {
  149. d = -(N_VAL(n) + E_WT(e));
  150. if (N_VAL(adjn) == UNSEEN) {
  151. #ifdef DEBUG
  152. fprintf (stderr, "new %d (%d)\n", adjn->index, -d);
  153. #endif
  154. N_VAL(adjn) = d;
  155. if (PQ_insert(adjn)) return 1;
  156. N_DAD(adjn) = n;
  157. N_EDGE(adjn) = e;
  158. }
  159. else {
  160. if (N_VAL(adjn) < d) {
  161. #ifdef DEBUG
  162. fprintf (stderr, "adjust %d (%d)\n", adjn->index, -d);
  163. #endif
  164. PQupdate(adjn, d);
  165. N_DAD(adjn) = n;
  166. N_EDGE(adjn) = e;
  167. }
  168. }
  169. }
  170. }
  171. }
  172. return 0;
  173. }