Skip to content

Commit bd2e0aa

Browse files
wip: moving towards a heap based dijkstra
1 parent 45d905e commit bd2e0aa

File tree

3 files changed

+58
-90
lines changed

3 files changed

+58
-90
lines changed

Makefile

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
d: FORCE
2+
g++ -std=c++11 -O3 -ffast-math -g dijkstra3d.cpp -o d
3+
14
test: FORCE
2-
g++ -std=c++11 -g test.cpp -o test
5+
g++ -std=c++11 -O3 -ffast-math -g test.cpp -o test
36

47
FORCE:

dijkstra3d.cpp

+49-89
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include <queue> // probably a binomial queue
1919
#include <cstdio>
2020

21+
#include "pairing_heap.hpp"
22+
2123
#ifndef DIJKSTRA3D_HPP
2224
#define DIJKSTRA3D_HPP
2325

@@ -46,128 +48,86 @@ void print(float* dest, int x, int y, int z) {
4648
}
4749

4850

49-
50-
inline float* fill(float *arr, const size_t size, const float value) {
51+
inline float* fill(float *arr, const float value, const size_t size) {
5152
for (size_t i = 0; i < size; i++) {
5253
arr[i] = value;
5354
}
5455
return arr;
5556
}
5657

57-
float search3d(
58-
float* field, float* dist,
59-
// std::priority_queue<size_t, std::std::vector<size_t>, std::greater> &pq,
60-
const size_t sx, const size_t sxy, const size_t voxels,
61-
const size_t loc, const size_t target
62-
) {
63-
64-
if (loc == target) {
65-
return dist[loc];
66-
}
67-
68-
// Lets start with a 6-neighborhood. Move to a 26-hood when
69-
// this is working.
70-
const int neighborhood[NHOOD_SIZE] = { -1, 1, sx, -sx, sxy, -sxy };
71-
72-
float delta;
73-
size_t neighboridx;
74-
for (int i = 0; i < NHOOD_SIZE; i++) {
75-
neighboridx = loc + neighborhood[i];
76-
delta = field[neighboridx];
77-
78-
if (neighboridx < 0 || neighboridx >= voxels) {
79-
continue;
80-
}
81-
// visited nodes are marked as negative
82-
// in the distance field
83-
else if (std::signbit(delta)) {
84-
continue;
85-
}
86-
else if (dist[loc] + delta < dist[neighboridx]) {
87-
dist[neighboridx] = dist[loc] + delta;
88-
}
89-
}
90-
91-
field[loc] *= -1;
92-
93-
// O(V^2) version
94-
// replace with heap when you have it
95-
float min_val = +INFINITY;
96-
size_t next_loc = loc + 1;
97-
for (int i = 0; i < voxels; i++) {
98-
if (std::signbit(field[i])) {
99-
continue;
100-
}
101-
else if (dist[i] < min_val) {
102-
min_val = dist[i];
103-
next_loc = i;
104-
}
105-
}
106-
107-
// printf("next loc: %d\n", next_loc);
108-
109-
return search3d(field, dist, sx, sxy, voxels, next_loc, target);
110-
}
111-
11258
// works for non-negative weights
11359
// Shortest ST path
11460
// sx, sy, sz are the dimensions of the graph
11561
// s = index of source
11662
// t = index of target
11763
// field is a 3D field
11864
float dijkstra3d(
119-
float* field,
120-
const size_t sx, const size_t sy, const size_t sz,
121-
const size_t source, const size_t target) {
65+
float* field,
66+
const size_t sx, const size_t sy, const size_t sz,
67+
const size_t source, const size_t target
68+
) {
12269

12370
const size_t voxels = sx * sy * sz;
71+
const size_t sxy = sx * sy;
12472

125-
float* dist = new float[voxels]();
126-
fill(dist, voxels, +INFINITY);
127-
dist[source] = 0;
73+
float *dist = new float[voxels]();
74+
fill(dist, +INFINITY, voxels);
75+
dist[source] = -0;
12876

129-
// printf("FIELD\n");
130-
// print(field, sx, sy, sz);
77+
// Lets start with a 6-neighborhood. Move to a 26-hood when
78+
// this is working.
79+
const int neighborhood[NHOOD_SIZE] = { -1, 1, sx, -sx, sxy, -sxy };
13180

132-
// printf("DIST\n");
133-
// print(dist, sx, sy, sz);
81+
auto *heap = new MinPairingHeap();
82+
heap->insert(0.0, source);
13483

135-
// std::priority_queue<size_t, std::vector<size_t>, std::greater<size_t> priority_queue;
84+
size_t loc;
85+
float delta;
86+
size_t neighboridx;
87+
while (!heap->empty()) {
88+
loc = heap->root->value;
89+
heap->delete_min();
13690

137-
float shortest_distance = search3d(
138-
field, dist, //priority_queue,
139-
sx, sx * sy, voxels,
140-
source, target
141-
);
91+
if (loc == target) {
92+
break;
93+
}
14294

143-
// printf("FIELD\n");
144-
// print(field, sx, sy, sz);
95+
for (int i = 0; i < NHOOD_SIZE; i++) {
96+
neighboridx = loc + neighborhood[i];
97+
delta = field[neighboridx];
98+
99+
if (neighboridx < 0 || neighboridx >= voxels) {
100+
continue;
101+
}
102+
// visited nodes are marked as negative
103+
// in the distance field
104+
else if (std::signbit(dist[neighboridx])) {
105+
continue;
106+
}
107+
else if (dist[loc] + delta < dist[neighboridx]) {
108+
dist[neighboridx] = dist[loc] + delta;
109+
heap->insert(dist[neighboridx], neighboridx);
110+
}
111+
}
145112

146-
// mark all nodes unvisited
147-
// i.e. restore to previous state
148-
// so our negative number trick is invisible
149-
// lol so not threadsafe
150-
for (int i = 0; i < voxels; i++) {
151-
field[i] = fabs(field[i]);
113+
dist[loc] *= -1;
152114
}
153115

154-
// printf("DIST\n");
155-
// print(dist, sx, sy, sz);
156-
157116
delete []dist;
117+
delete heap;
158118

159-
return shortest_distance;
119+
return dist[target];
160120
}
161121

162122

163123
int main () {
164-
const size_t sx = 32;
165-
const size_t sy = 32;
166-
const size_t sz = 32;
124+
const size_t sx = 128;
125+
const size_t sy = 128;
126+
const size_t sz = 128;
167127
const size_t voxels = sx * sy * sz;
168128

169129
float* field = new float[voxels]();
170-
fill(field, voxels, 1.0);
130+
fill(field, 1.0, voxels);
171131

172132
float min = dijkstra3d(field, sx, sy, sz, 0, voxels - 1);
173133

pairing_heap.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@ class MinPairingHeap {
210210

211211
// O(1)
212212
PHNode* insert(PHNode* I) {
213+
if (!root) {
214+
root = I;
215+
return I;
216+
}
217+
213218
if (root->key <= I->key) {
214219
I->right = root->left;
215220
root->left = I;

0 commit comments

Comments
 (0)