/misc/src/release/graphviz-2.18-1/src/graphviz-2.18/lib/neatogen/dijkstra.c

Go to the documentation of this file.
00001 /* $Id: dijkstra.c,v 1.4 2006/12/07 22:49:36 erg Exp $ $Revision: 1.4 $ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /**********************************************************
00005 *      This software is part of the graphviz package      *
00006 *                http://www.graphviz.org/                 *
00007 *                                                         *
00008 *            Copyright (c) 1994-2004 AT&T Corp.           *
00009 *                and is licensed under the                *
00010 *            Common Public License, Version 1.0           *
00011 *                      by AT&T Corp.                      *
00012 *                                                         *
00013 *        Information and Software Systems Research        *
00014 *              AT&T Research, Florham Park NJ             *
00015 **********************************************************/
00016 
00017 
00018 /******************************************
00019 
00020         Dijkstra algorithm
00021         Computes single-source distances for
00022         weighted graphs
00023 
00024 ******************************************/
00025 
00026 
00027 #include "bfs.h"
00028 #include "dijkstra.h"
00029 #include <limits.h>
00030 #include <stdlib.h>
00031 /* #include <math.h> */
00032 
00033 #define MAX_DIST (double)INT_MAX
00034 
00035 typedef DistType Word;
00036 
00037 #define LOOP while(TRUE)
00038 
00039 /* This heap class is suited to the Dijkstra alg.
00040    data[i]=vertexNum <==> index[vertexNum]=i
00041 */
00042 
00043 #define left(i) (2*(i))
00044 #define right(i) (2*(i)+1)
00045 #define parent(i) ((i)/2)
00046 #define insideHeap(h,i) ((i)<h->heapSize)
00047 #define greaterPriority(h,i,j,dist) (dist[h->data[i]]<dist[h->data[j]])
00048 #define assign(h,i,j,index) {h->data[i]=h->data[j]; index[h->data[i]]=i;}
00049 #define exchange(h,i,j,index) {int temp; \
00050                 temp=h->data[i]; \
00051                 h->data[i]=h->data[j]; \
00052                 h->data[j]=temp; \
00053                 index[h->data[i]]=i; \
00054                 index[h->data[j]]=j; \
00055 }
00056 
00057 typedef struct {
00058     int *data;
00059     int heapSize;
00060 } heap;
00061 
00062 static void heapify(heap * h, int i, int index[], Word dist[])
00063 {
00064     int l, r, largest;
00065     while (1) {
00066         l = left(i);
00067         r = right(i);
00068         if (insideHeap(h, l) && greaterPriority(h, l, i, dist))
00069             largest = l;
00070         else
00071             largest = i;
00072         if (insideHeap(h, r) && greaterPriority(h, r, largest, dist))
00073             largest = r;
00074 
00075         if (largest == i)
00076             break;
00077 
00078         exchange(h, largest, i, index);
00079         i = largest;
00080     }
00081 }
00082 
00083 #ifdef OBSOLETE
00084 /* originally, the code called mkHeap to allocate space, then
00085  * initHeap to realloc the space. This is silly.
00086  * Now we just call initHeap.
00087  */
00088 static void mkHeap(heap * h, int size)
00089 {
00090     h->data = N_GNEW(size, int);
00091     h->heapSize = 0;
00092 }
00093 #endif
00094 
00095 static void freeHeap(heap * h)
00096 {
00097     if (h->data) free(h->data);
00098 }
00099 
00100 static void
00101 initHeap(heap * h, int startVertex, int index[], Word dist[], int n)
00102 {
00103     int i, count;
00104     int j;    /* We cannot use an unsigned value in this loop */
00105     /* h->data=(int*) realloc(h->data, (n-1)*sizeof(int)); */
00106     if (n == 1) h->data = NULL;
00107     else h->data = N_GNEW(n - 1, int);
00108     h->heapSize = n - 1;
00109 
00110     for (count = 0, i = 0; i < n; i++)
00111         if (i != startVertex) {
00112             h->data[count] = i;
00113             index[i] = count;
00114             count++;
00115         }
00116 
00117     for (j = (n - 1) / 2; j >= 0; j--)
00118         heapify(h, j, index, dist);
00119 }
00120 
00121 static boolean extractMax(heap * h, int *max, int index[], Word dist[])
00122 {
00123     if (h->heapSize == 0)
00124         return FALSE;
00125 
00126     *max = h->data[0];
00127     h->data[0] = h->data[h->heapSize - 1];
00128     index[h->data[0]] = 0;
00129     h->heapSize--;
00130     heapify(h, 0, index, dist);
00131 
00132     return TRUE;
00133 }
00134 
00135 static void
00136 increaseKey(heap * h, int increasedVertex, Word newDist, int index[],
00137             Word dist[])
00138 {
00139     int placeInHeap;
00140     int i;
00141 
00142     if (dist[increasedVertex] <= newDist)
00143         return;
00144 
00145     placeInHeap = index[increasedVertex];
00146 
00147     dist[increasedVertex] = newDist;
00148 
00149     i = placeInHeap;
00150     while (i > 0 && dist[h->data[parent(i)]] > newDist) {       /* can write here: greaterPriority(i,parent(i),dist) */
00151         assign(h, i, parent(i), index);
00152         i = parent(i);
00153     }
00154     h->data[i] = increasedVertex;
00155     index[increasedVertex] = i;
00156 }
00157 
00158 void dijkstra(int vertex, vtx_data * graph, int n, DistType * dist)
00159 {
00160     int i;
00161     heap H;
00162     int closestVertex, neighbor;
00163     DistType closestDist, prevClosestDist = INT_MAX;
00164     static int *index;
00165 
00166 #ifdef OBSOLETE
00167     mkHeap(&H, n);
00168 #endif
00169     index = (int *) realloc(index, n * sizeof(int));
00170 
00171     /* initial distances with edge weights: */
00172     for (i = 0; i < n; i++)
00173         dist[i] = (DistType) MAX_DIST;
00174     dist[vertex] = 0;
00175     for (i = 1; i < graph[vertex].nedges; i++)
00176         dist[graph[vertex].edges[i]] = (DistType) graph[vertex].ewgts[i];
00177 
00178     initHeap(&H, vertex, index, dist, n);
00179 
00180     while (extractMax(&H, &closestVertex, index, dist)) {
00181         closestDist = dist[closestVertex];
00182         if (closestDist == MAX_DIST)
00183             break;
00184         for (i = 1; i < graph[closestVertex].nedges; i++) {
00185             neighbor = graph[closestVertex].edges[i];
00186             increaseKey(&H, neighbor,
00187                         closestDist +
00188                         (DistType) graph[closestVertex].ewgts[i], index,
00189                         dist);
00190         }
00191         prevClosestDist = closestDist;
00192     }
00193 
00194     /* For dealing with disconnected graphs: */
00195     for (i = 0; i < n; i++)
00196         if (dist[i] == MAX_DIST)        /* 'i' is not connected to 'vertex' */
00197             dist[i] = prevClosestDist + 10;
00198     freeHeap(&H);
00199 }
00200 
00201  /* Dijkstra bounded to nodes in *unweighted* radius */
00202 int
00203 dijkstra_bounded(int vertex, vtx_data * graph, int n, DistType * dist,
00204                  int bound, int *visited_nodes)
00205  /* make dijkstra, but consider only nodes whose *unweighted* distance from 'vertex'  */
00206  /* is at most 'bound' */
00207  /* MON-EFFICIENT implementation, see below. */
00208 {
00209     int num_visited_nodes;
00210     int i;
00211     static boolean *node_in_neighborhood = NULL;
00212     static int size = 0;
00213     static int *index;
00214     Queue Q;
00215     heap H;
00216     int closestVertex, neighbor;
00217     DistType closestDist;
00218     int num_found = 0;
00219 
00220     /* first, perform BFS to find the nodes in the region */
00221     mkQueue(&Q, n);
00222     /* remember that dist should be init. with -1's */
00223     for (i = 0; i < n; i++) {
00224         dist[i] = -1;           /* far, TOO COSTLY (O(n))! */
00225     }
00226     num_visited_nodes =
00227         bfs_bounded(vertex, graph, n, dist, &Q, bound, visited_nodes);
00228     if (size < n) {
00229         node_in_neighborhood =
00230             (boolean *) realloc(node_in_neighborhood, n * sizeof(boolean));
00231         for (i = size; i < n; i++) {
00232             node_in_neighborhood[i] = FALSE;
00233         }
00234         size = n;
00235     }
00236     for (i = 0; i < num_visited_nodes; i++) {
00237         node_in_neighborhood[visited_nodes[i]] = TRUE;
00238     }
00239 
00240 
00241 #ifdef OBSOLETE
00242     mkHeap(&H, n);
00243 #endif
00244     index = (int *) realloc(index, n * sizeof(int));
00245 
00246     /* initial distances with edge weights: */
00247     for (i = 0; i < n; i++)     /* far, TOO COSTLY (O(n))! */
00248         dist[i] = (DistType) MAX_DIST;
00249     dist[vertex] = 0;
00250     for (i = 1; i < graph[vertex].nedges; i++)
00251         dist[graph[vertex].edges[i]] = (DistType) graph[vertex].ewgts[i];
00252 
00253     /* again, TOO COSTLY (O(n)) to put all nodes in heap! */
00254     initHeap(&H, vertex, index, dist, n); 
00255 
00256     while (num_found < num_visited_nodes
00257            && extractMax(&H, &closestVertex, index, dist)) {
00258         if (node_in_neighborhood[closestVertex]) {
00259             num_found++;
00260         }
00261         closestDist = dist[closestVertex];
00262         if (closestDist == MAX_DIST)
00263             break;
00264         for (i = 1; i < graph[closestVertex].nedges; i++) {
00265             neighbor = graph[closestVertex].edges[i];
00266             increaseKey(&H, neighbor,
00267                         closestDist +
00268                         (DistType) graph[closestVertex].ewgts[i], index,
00269                         dist);
00270         }
00271     }
00272 
00273     /* restore initial false-status of 'node_in_neighborhood' */
00274     for (i = 0; i < num_visited_nodes; i++) {
00275         node_in_neighborhood[visited_nodes[i]] = FALSE;
00276     }
00277     freeHeap(&H);
00278     freeQueue(&Q);
00279     return num_visited_nodes;
00280 }
00281 
00282 static void heapify_f(heap * h, int i, int index[], float dist[])
00283 {
00284     int l, r, largest;
00285     while (1) {
00286         l = left(i);
00287         r = right(i);
00288         if (insideHeap(h, l) && greaterPriority(h, l, i, dist))
00289             largest = l;
00290         else
00291             largest = i;
00292         if (insideHeap(h, r) && greaterPriority(h, r, largest, dist))
00293             largest = r;
00294 
00295         if (largest == i)
00296             break;
00297 
00298         exchange(h, largest, i, index);
00299         i = largest;
00300     }
00301 }
00302 
00303 static void
00304 initHeap_f(heap * h, int startVertex, int index[], float dist[], int n)
00305 {
00306     int i, count;
00307     int j;                      /* We cannot use an unsigned value in this loop */
00308     h->data = N_GNEW(n - 1, int);
00309     h->heapSize = n - 1;
00310 
00311     for (count = 0, i = 0; i < n; i++)
00312         if (i != startVertex) {
00313             h->data[count] = i;
00314             index[i] = count;
00315             count++;
00316         }
00317 
00318     for (j = (n - 1) / 2; j >= 0; j--)
00319         heapify_f(h, j, index, dist);
00320 }
00321 
00322 static boolean extractMax_f(heap * h, int *max, int index[], float dist[])
00323 {
00324     if (h->heapSize == 0)
00325         return FALSE;
00326 
00327     *max = h->data[0];
00328     h->data[0] = h->data[h->heapSize - 1];
00329     index[h->data[0]] = 0;
00330     h->heapSize--;
00331     heapify_f(h, 0, index, dist);
00332 
00333     return TRUE;
00334 }
00335 
00336 static void
00337 increaseKey_f(heap * h, int increasedVertex, float newDist, int index[],
00338               float dist[])
00339 {
00340     int placeInHeap;
00341     int i;
00342 
00343     if (dist[increasedVertex] <= newDist)
00344         return;
00345 
00346     placeInHeap = index[increasedVertex];
00347 
00348     dist[increasedVertex] = newDist;
00349 
00350     i = placeInHeap;
00351     while (i > 0 && dist[h->data[parent(i)]] > newDist) {       /* can write here: greaterPriority(i,parent(i),dist) */
00352         assign(h, i, parent(i), index);
00353         i = parent(i);
00354     }
00355     h->data[i] = increasedVertex;
00356     index[increasedVertex] = i;
00357 }
00358 
00359 /* dijkstra_f:
00360  * Weighted shortest paths from vertex.
00361  * Assume graph is connected.
00362  */
00363 void dijkstra_f(int vertex, vtx_data * graph, int n, float *dist)
00364 {
00365     int i;
00366     heap H;
00367     int closestVertex = 0, neighbor;
00368     float closestDist;
00369     int *index;
00370 
00371 #ifdef OBSOLETE
00372     mkHeap(&H, n);
00373 #endif
00374     index = N_GNEW(n, int);
00375 
00376     /* initial distances with edge weights: */
00377     for (i = 0; i < n; i++)
00378         dist[i] = MAXFLOAT;
00379     dist[vertex] = 0;
00380     for (i = 1; i < graph[vertex].nedges; i++)
00381         dist[graph[vertex].edges[i]] = graph[vertex].ewgts[i];
00382 
00383     initHeap_f(&H, vertex, index, dist, n);
00384 
00385     while (extractMax_f(&H, &closestVertex, index, dist)) {
00386         closestDist = dist[closestVertex];
00387         if (closestDist == MAXFLOAT)
00388             break;
00389         for (i = 1; i < graph[closestVertex].nedges; i++) {
00390             neighbor = graph[closestVertex].edges[i];
00391             increaseKey_f(&H, neighbor,
00392                           closestDist + graph[closestVertex].ewgts[i],
00393                           index, dist);
00394         }
00395     }
00396 
00397     freeHeap(&H);
00398     free(index);
00399 }

Generated on Mon Mar 31 19:03:27 2008 for Graphviz by  doxygen 1.5.1