Graphviz 12.0.1~dev.20240716.0800
Loading...
Searching...
No Matches
dijkstra.c
Go to the documentation of this file.
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
11
12/******************************************
13
14 Dijkstra algorithm
15 Computes single-source distances for
16 weighted graphs
17
18******************************************/
19
20#include <assert.h>
21#include <cgraph/alloc.h>
22#include <cgraph/bitarray.h>
23#include <float.h>
24#include <neatogen/bfs.h>
25#include <neatogen/dijkstra.h>
26#include <limits.h>
27#include <stdbool.h>
28#include <stdlib.h>
29
30typedef DistType Word;
31
32#define MAX_DIST ((DistType)INT_MAX)
33
34/* This heap class is suited to the Dijkstra alg.
35 data[i]=vertexNum <==> index[vertexNum]=i
36*/
37
38#define left(i) (2*(i))
39#define right(i) (2*(i)+1)
40#define parent(i) ((i)/2)
41#define insideHeap(h,i) ((i)<h->heapSize)
42#define greaterPriority(h,i,j,dist) (dist[h->data[i]]<dist[h->data[j]])
43#define assign(h,i,j,index) {h->data[i]=h->data[j]; index[h->data[i]]=i;}
44#define exchange(h,i,j,index) {int temp; \
45 temp=h->data[i]; \
46 h->data[i]=h->data[j]; \
47 h->data[j]=temp; \
48 index[h->data[i]]=i; \
49 index[h->data[j]]=j; \
50}
51
52typedef struct {
53 int *data;
55} heap;
56
57static void heapify(heap * h, int i, int index[], Word dist[])
58{
59 int l, r, largest;
60 while (1) {
61 l = left(i);
62 r = right(i);
63 if (insideHeap(h, l) && greaterPriority(h, l, i, dist))
64 largest = l;
65 else
66 largest = i;
67 if (insideHeap(h, r) && greaterPriority(h, r, largest, dist))
68 largest = r;
69
70 if (largest == i)
71 break;
72
73 exchange(h, largest, i, index);
74 i = largest;
75 }
76}
77
78static void freeHeap(heap * h)
79{
80 free(h->data);
81}
82
83static void
84initHeap(heap * h, int startVertex, int index[], Word dist[], int n)
85{
86 int i, count;
87 int j; /* We cannot use an unsigned value in this loop */
88 if (n == 1) h->data = NULL;
89 else h->data = gv_calloc(n - 1, sizeof(int));
90 h->heapSize = n - 1;
91
92 for (count = 0, i = 0; i < n; i++)
93 if (i != startVertex) {
94 h->data[count] = i;
95 index[i] = count;
96 count++;
97 }
98
99 for (j = (n - 1) / 2; j >= 0; j--)
100 heapify(h, j, index, dist);
101}
102
103static bool extractMax(heap * h, int *max, int index[], Word dist[])
104{
105 if (h->heapSize == 0)
106 return false;
107
108 *max = h->data[0];
109 h->data[0] = h->data[h->heapSize - 1];
110 index[h->data[0]] = 0;
111 h->heapSize--;
112 heapify(h, 0, index, dist);
113
114 return true;
115}
116
117static void
118increaseKey(heap * h, int increasedVertex, Word newDist, int index[],
119 Word dist[])
120{
121 int placeInHeap;
122 int i;
123
124 if (dist[increasedVertex] <= newDist)
125 return;
126
127 placeInHeap = index[increasedVertex];
128
129 dist[increasedVertex] = newDist;
130
131 i = placeInHeap;
132 while (i > 0 && dist[h->data[parent(i)]] > newDist) { /* can write here: greaterPriority(i,parent(i),dist) */
133 assign(h, i, parent(i), index);
134 i = parent(i);
135 }
136 h->data[i] = increasedVertex;
137 index[increasedVertex] = i;
138}
139
141{
142 heap H;
143 int closestVertex, neighbor;
144 DistType closestDist, prevClosestDist = MAX_DIST;
145
146 int *index = gv_calloc(n, sizeof(int));
147
148 /* initial distances with edge weights: */
149 for (int i = 0; i < n; i++)
150 dist[i] = MAX_DIST;
151 dist[vertex] = 0;
152 for (size_t i = 1; i < graph[vertex].nedges; i++)
153 dist[graph[vertex].edges[i]] = (DistType) graph[vertex].ewgts[i];
154
155 initHeap(&H, vertex, index, dist, n);
156
157 while (extractMax(&H, &closestVertex, index, dist)) {
158 closestDist = dist[closestVertex];
159 if (closestDist == MAX_DIST)
160 break;
161 for (size_t i = 1; i < graph[closestVertex].nedges; i++) {
162 neighbor = graph[closestVertex].edges[i];
163 increaseKey(&H, neighbor, closestDist +
164 (DistType)graph[closestVertex].ewgts[i], index, dist);
165 }
166 prevClosestDist = closestDist;
167 }
168
169 /* For dealing with disconnected graphs: */
170 for (int i = 0; i < n; i++)
171 if (dist[i] == MAX_DIST) /* 'i' is not connected to 'vertex' */
172 dist[i] = prevClosestDist + 10;
173 freeHeap(&H);
174 free(index);
175}
176
177static void heapify_f(heap * h, int i, int index[], float dist[])
178{
179 int l, r, largest;
180 while (1) {
181 l = left(i);
182 r = right(i);
183 if (insideHeap(h, l) && greaterPriority(h, l, i, dist))
184 largest = l;
185 else
186 largest = i;
187 if (insideHeap(h, r) && greaterPriority(h, r, largest, dist))
188 largest = r;
189
190 if (largest == i)
191 break;
192
193 exchange(h, largest, i, index);
194 i = largest;
195 }
196}
197
198static void
199initHeap_f(heap * h, int startVertex, int index[], float dist[], int n)
200{
201 int i, count;
202 int j; /* We cannot use an unsigned value in this loop */
203 h->data = gv_calloc(n - 1, sizeof(int));
204 h->heapSize = n - 1;
205
206 for (count = 0, i = 0; i < n; i++)
207 if (i != startVertex) {
208 h->data[count] = i;
209 index[i] = count;
210 count++;
211 }
212
213 for (j = (n - 1) / 2; j >= 0; j--)
214 heapify_f(h, j, index, dist);
215}
216
217static bool extractMax_f(heap * h, int *max, int index[], float dist[])
218{
219 if (h->heapSize == 0)
220 return false;
221
222 *max = h->data[0];
223 h->data[0] = h->data[h->heapSize - 1];
224 index[h->data[0]] = 0;
225 h->heapSize--;
226 heapify_f(h, 0, index, dist);
227
228 return true;
229}
230
231static void
232increaseKey_f(heap * h, int increasedVertex, float newDist, int index[],
233 float dist[])
234{
235 int placeInHeap;
236 int i;
237
238 if (dist[increasedVertex] <= newDist)
239 return;
240
241 placeInHeap = index[increasedVertex];
242
243 dist[increasedVertex] = newDist;
244
245 i = placeInHeap;
246 while (i > 0 && dist[h->data[parent(i)]] > newDist) { /* can write here: greaterPriority(i,parent(i),dist) */
247 assign(h, i, parent(i), index);
248 i = parent(i);
249 }
250 h->data[i] = increasedVertex;
251 index[increasedVertex] = i;
252}
253
254/* dijkstra_f:
255 * Weighted shortest paths from vertex.
256 * Assume graph is connected.
257 */
258void dijkstra_f(int vertex, vtx_data * graph, int n, float *dist)
259{
260 heap H;
261 int closestVertex = 0, neighbor;
262 float closestDist;
263 int *index = gv_calloc(n, sizeof(int));
264
265 /* initial distances with edge weights: */
266 for (int i = 0; i < n; i++)
267 dist[i] = FLT_MAX;
268 dist[vertex] = 0;
269 for (size_t i = 1; i < graph[vertex].nedges; i++)
270 dist[graph[vertex].edges[i]] = graph[vertex].ewgts[i];
271
272 initHeap_f(&H, vertex, index, dist, n);
273
274 while (extractMax_f(&H, &closestVertex, index, dist)) {
275 closestDist = dist[closestVertex];
276 if (closestDist == FLT_MAX)
277 break;
278 for (size_t i = 1; i < graph[closestVertex].nedges; i++) {
279 neighbor = graph[closestVertex].edges[i];
280 increaseKey_f(&H, neighbor, closestDist + graph[closestVertex].ewgts[i],
281 index, dist);
282 }
283 }
284
285 freeHeap(&H);
286 free(index);
287}
288
289// single source shortest paths that also builds terms as it goes
290// mostly copied from dijkstra_f above
291// returns the number of terms built
292int dijkstra_sgd(graph_sgd *graph, int source, term_sgd *terms) {
293 heap h;
294 int *indices = gv_calloc(graph->n, sizeof(int));
295 float *dists = gv_calloc(graph->n, sizeof(float));
296 for (size_t i= 0; i < graph->n; i++) {
297 dists[i] = FLT_MAX;
298 }
299 dists[source] = 0;
300 for (size_t i = graph->sources[source]; i < graph->sources[source + 1];
301 i++) {
302 size_t target = graph->targets[i];
303 dists[target] = graph->weights[i];
304 }
305 assert(graph->n <= INT_MAX);
306 initHeap_f(&h, source, indices, dists, (int)graph->n);
307
308 int closest = 0, offset = 0;
309 while (extractMax_f(&h, &closest, indices, dists)) {
310 float d = dists[closest];
311 if (d == FLT_MAX) {
312 break;
313 }
314 // if the target is fixed then always create a term as shortest paths are not calculated from there
315 // if not fixed then only create a term if the target index is lower
316 if (bitarray_get(graph->pinneds, closest) || closest<source) {
317 terms[offset].i = source;
318 terms[offset].j = closest;
319 terms[offset].d = d;
320 terms[offset].w = 1 / (d*d);
321 offset++;
322 }
323 for (size_t i = graph->sources[closest]; i < graph->sources[closest + 1];
324 i++) {
325 size_t target = graph->targets[i];
326 float weight = graph->weights[i];
327 assert(target <= (size_t)INT_MAX);
328 increaseKey_f(&h, (int)target, d+weight, indices, dists);
329 }
330 }
331 freeHeap(&h);
332 free(indices);
333 free(dists);
334 return offset;
335}
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
API for compacted arrays of booleans.
static bool bitarray_get(bitarray_t self, size_t index)
get the value of the given element
Definition bitarray.h:65
static void dijkstra(Dict_t *Q, Agraph_t *G, Agnode_t *n)
Definition dijkstra.c:188
static double dist(int dim, double *x, double *y)
void free(void *)
node NULL
Definition grammar.y:149
Agraph_t * graph(char *name)
Definition gv.cpp:31
swig_ptr_object_handlers offset
Definition gv_php.cpp:5915
#define exchange(h, i, j, index)
Definition dijkstra.c:44
DistType Word
Definition dijkstra.c:30
static bool extractMax(heap *h, int *max, int index[], Word dist[])
Definition dijkstra.c:103
static void freeHeap(heap *h)
Definition dijkstra.c:78
static void heapify(heap *h, int i, int index[], Word dist[])
Definition dijkstra.c:57
static void initHeap(heap *h, int startVertex, int index[], Word dist[], int n)
Definition dijkstra.c:84
static void increaseKey(heap *h, int increasedVertex, Word newDist, int index[], Word dist[])
Definition dijkstra.c:118
static bool extractMax_f(heap *h, int *max, int index[], float dist[])
Definition dijkstra.c:217
void dijkstra_f(int vertex, vtx_data *graph, int n, float *dist)
Definition dijkstra.c:258
static void initHeap_f(heap *h, int startVertex, int index[], float dist[], int n)
Definition dijkstra.c:199
#define left(i)
Definition dijkstra.c:38
#define assign(h, i, j, index)
Definition dijkstra.c:43
static void heapify_f(heap *h, int i, int index[], float dist[])
Definition dijkstra.c:177
#define parent(i)
Definition dijkstra.c:40
#define right(i)
Definition dijkstra.c:39
static void increaseKey_f(heap *h, int increasedVertex, float newDist, int index[], float dist[])
Definition dijkstra.c:232
int dijkstra_sgd(graph_sgd *graph, int source, term_sgd *terms)
Definition dijkstra.c:292
#define insideHeap(h, i)
Definition dijkstra.c:41
#define MAX_DIST
Definition dijkstra.c:32
#define greaterPriority(h, i, j, dist)
Definition dijkstra.c:42
#define neighbor(t, i, edim, elist)
Definition make_map.h:37
int DistType
Definition sparsegraph.h:37
int * data
Definition dijkstra.c:53
int heapSize
Definition dijkstra.c:54
Definition sgd.h:10
float d
Definition sgd.h:12
int j
Definition sgd.h:11
float w
Definition sgd.h:12
int i
Definition sgd.h:11
Definition legal.c:31