Skip to content

Commit f1e61d3

Browse files
authored
fix: revert SpeedyALTData.java to upstream/main (NodeMinHeap) for retrofit compatibility
Agent-Logs-Url: https://github.com/steffenaxer/matsim-libs/sessions/e1a1e82f-b09c-41cd-9319-42406ce7ec6d Co-authored-by: steffenaxer <26229392+steffenaxer@users.noreply.github.com>
1 parent 097d8a5 commit f1e61d3

2 files changed

Lines changed: 162 additions & 15 deletions

File tree

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
package org.matsim.core.router.speedy;
2+
3+
import java.util.NoSuchElementException;
4+
5+
/**
6+
* @author mrieser / Simunto
7+
*/
8+
class NodeMinHeap {
9+
private final int[] heap;
10+
private final int[] pos;
11+
private int size = 0;
12+
private final CostGetter costGetter;
13+
private final CostSetter costSetter;
14+
15+
public interface CostGetter {
16+
double getCost(int index);
17+
}
18+
19+
public interface CostSetter {
20+
void setCost(int index, double cost);
21+
}
22+
23+
NodeMinHeap(int nodeCount, CostGetter costGetter, CostSetter costSetter) {
24+
this.heap = new int[nodeCount]; // worst case: every node is part of the heap
25+
this.pos = new int[nodeCount];
26+
this.costGetter = costGetter;
27+
this.costSetter = costSetter;
28+
}
29+
30+
void insert(int node) {
31+
int i = this.size;
32+
this.size++;
33+
34+
double nodeCost = this.costGetter.getCost(node);
35+
// sift up
36+
int parent = parent(i);
37+
while (i > 0 && nodeCost < this.costGetter.getCost(this.heap[parent])) {
38+
this.heap[i] = this.heap[parent];
39+
this.pos[this.heap[parent]] = i;
40+
i = parent;
41+
parent = parent(parent);
42+
}
43+
this.heap[i] = node;
44+
this.pos[node] = i;
45+
}
46+
47+
void decreaseKey(int node, double cost) {
48+
int i;
49+
for (i = 0; i < this.size; i++) {
50+
if (this.heap[i] == node) {
51+
break;
52+
}
53+
}
54+
if (this.costGetter.getCost(this.heap[i]) < cost) {
55+
throw new IllegalArgumentException("existing cost is already smaller than new cost.");
56+
}
57+
58+
this.costSetter.setCost(node, cost);
59+
60+
// sift up
61+
int parent = parent(i);
62+
while (i > 0 && cost < this.costGetter.getCost(this.heap[parent])) {
63+
this.heap[i] = this.heap[parent];
64+
this.pos[this.heap[parent]] = i;
65+
i = parent;
66+
parent = parent(parent);
67+
}
68+
this.heap[i] = node;
69+
this.pos[node] = i;
70+
}
71+
72+
int poll() {
73+
if (this.size == 0) {
74+
throw new NoSuchElementException("heap is empty");
75+
}
76+
if (this.size == 1) {
77+
this.size--;
78+
return this.heap[0];
79+
}
80+
81+
int root = this.heap[0];
82+
83+
// remove the last item, set it as new root
84+
int lastNode = this.heap[this.size - 1];
85+
this.size--;
86+
this.heap[0] = lastNode;
87+
this.pos[lastNode] = 0;
88+
89+
// sift down
90+
minHeapify(0);
91+
92+
return root;
93+
}
94+
95+
int peek() {
96+
if (this.size == 0) {
97+
throw new NoSuchElementException("heap is empty");
98+
}
99+
return this.heap[0];
100+
}
101+
102+
int size() {
103+
return this.size;
104+
}
105+
106+
boolean isEmpty() {
107+
return this.size == 0;
108+
}
109+
110+
void clear() {
111+
this.size = 0;
112+
}
113+
114+
private void minHeapify(int i) {
115+
int left = left(i);
116+
int right = right(i);
117+
int smallest = i;
118+
119+
if (left <= (this.size - 1) && this.costGetter.getCost(this.heap[left]) < this.costGetter.getCost(this.heap[i])) {
120+
smallest = left;
121+
}
122+
if (right <= (this.size - 1) && this.costGetter.getCost(this.heap[right]) < this.costGetter.getCost(this.heap[smallest])) {
123+
smallest = right;
124+
}
125+
if (smallest != i) {
126+
swap(i, smallest);
127+
minHeapify(smallest);
128+
}
129+
}
130+
131+
private int right(int i) {
132+
return 2 * i + 2;
133+
}
134+
135+
private int left(int i) {
136+
return 2 * i + 1;
137+
}
138+
139+
private int parent(int i) {
140+
return (i - 1) / 2;
141+
}
142+
143+
private void swap(int i, int parent) {
144+
int tmp = this.heap[parent];
145+
this.heap[parent] = this.heap[i];
146+
this.pos[this.heap[i]] = parent;
147+
this.heap[i] = tmp;
148+
this.pos[tmp] = i;
149+
}
150+
}

matsim/src/main/java/org/matsim/core/router/speedy/SpeedyALTData.java

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ private void calcLandmarks(int threads) {
145145
Future<double[]>[] trees = new Future[this.landmarksCount * 2];
146146
ExecutorService executor = Executors.newFixedThreadPool(threads);
147147

148-
int firstLandmarkIndex = graph.getNodeIndex(firstNode);
148+
int firstLandmarkIndex = firstNode.getId().index();
149149
this.landmarksNodeIndices[0] = firstLandmarkIndex;
150150
trees[0] = executor.submit(() -> calculateTreeForward(firstLandmarkIndex));
151151
trees[1] = executor.submit(() -> calculateTreeBackward(firstLandmarkIndex));
@@ -200,9 +200,9 @@ private int calculateNextLandmark(int existingCount) {
200200
data[this.landmarksNodeIndices[i]] = 0;
201201
}
202202

203-
DAryMinHeap pq = new DAryMinHeap(this.graph.nodeCount, 6);
203+
NodeMinHeap pq = new NodeMinHeap(this.graph.nodeCount, i -> data[i], (i, c) -> data[i] = c);
204204
for (int i = 0; i < existingCount; i++) {
205-
pq.insert(this.landmarksNodeIndices[i], 0);
205+
pq.insert(this.landmarksNodeIndices[i]);
206206
}
207207

208208
int lastNodeIdx = -1;
@@ -220,12 +220,11 @@ private int calculateNextLandmark(int existingCount) {
220220
double oldCost = data[toNode];
221221
if (Double.isFinite(oldCost)) {
222222
if (newCost < oldCost) {
223-
data[toNode] = newCost;
224223
pq.decreaseKey(toNode, newCost);
225224
}
226225
} else {
227226
data[toNode] = newCost;
228-
pq.insert(toNode, newCost);
227+
pq.insert(toNode);
229228
}
230229
}
231230
}
@@ -239,8 +238,8 @@ private double[] calculateTreeForward(int node) {
239238

240239
data[node] = 0;
241240

242-
DAryMinHeap pq = new DAryMinHeap(this.graph.nodeCount, 6);
243-
pq.insert(node, 0);
241+
NodeMinHeap pq = new NodeMinHeap(this.graph.nodeCount, i -> data[i], (i, c) -> data[i] = c);
242+
pq.insert(node);
244243

245244
while (!pq.isEmpty()) {
246245
final int nodeIdx = pq.poll();
@@ -255,12 +254,11 @@ private double[] calculateTreeForward(int node) {
255254
double oldCost = data[toNode];
256255
if (Double.isFinite(oldCost)) {
257256
if (newCost < oldCost) {
258-
data[toNode] = newCost;
259257
pq.decreaseKey(toNode, newCost);
260258
}
261259
} else {
262260
data[toNode] = newCost;
263-
pq.insert(toNode, newCost);
261+
pq.insert(toNode);
264262
}
265263
}
266264
}
@@ -279,8 +277,8 @@ private double[] calculateTreeBackward(int node) {
279277

280278
data[node] = 0;
281279

282-
DAryMinHeap pq = new DAryMinHeap(this.graph.nodeCount, 6);
283-
pq.insert(node, 0);
280+
NodeMinHeap pq = new NodeMinHeap(this.graph.nodeCount, i -> data[i], (i, c) -> data[i] = c);
281+
pq.insert(node);
284282

285283
while (!pq.isEmpty()) {
286284
final int nodeIdx = pq.poll();
@@ -295,12 +293,11 @@ private double[] calculateTreeBackward(int node) {
295293
double oldCost = data[fromNode];
296294
if (Double.isFinite(oldCost)) {
297295
if (newCost < oldCost) {
298-
data[fromNode] = newCost;
299296
pq.decreaseKey(fromNode, newCost);
300297
}
301298
} else {
302299
data[fromNode] = newCost;
303-
pq.insert(fromNode, newCost);
300+
pq.insert(fromNode);
304301
}
305302
}
306303
}
@@ -319,8 +316,8 @@ private void consolidateColoredNodes(double[] data) {
319316
if (uncoloredNode != null) {
320317

321318
// the index points to a node with a different index -> colored copy
322-
if (graph.getNodeIndex(uncoloredNode) != i) {
323-
int uncoloredIndex = graph.getNodeIndex(uncoloredNode);
319+
if (uncoloredNode.getId().index() != i) {
320+
int uncoloredIndex = uncoloredNode.getId().index();
324321
double uncoloredCost = data[uncoloredIndex];
325322
double coloredCost = data[i];
326323

0 commit comments

Comments
 (0)