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