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