1 package org.matsim.core.router.speedy;
3 import org.apache.logging.log4j.LogManager;
4 import org.apache.logging.log4j.Logger;
13 import java.util.ArrayList;
14 import java.util.Arrays;
15 import java.util.Collections;
16 import java.util.List;
38 private final static Logger
LOG = LogManager.getLogger(
SpeedyALT.class);
44 private final double[]
data;
50 private final DAryMinHeap
pq;
53 this.graph = astarData.graph;
57 this.data =
new double[this.graph.nodeCount * 3];
58 this.iterationIds =
new int[this.graph.nodeCount];
59 this.comingFrom =
new int[this.graph.nodeCount];
60 this.usedLink =
new int[this.graph.nodeCount];
61 this.pq =
new DAryMinHeap(this.graph.nodeCount, 6);
63 Arrays.fill(this.iterationIds, this.currentIteration);
67 return this.data[nodeIndex * 3];
71 return this.data[nodeIndex * 3 + 1];
75 return this.data[nodeIndex * 3 + 2];
78 private void setData(
int nodeIndex,
double cost,
double time,
double distance) {
79 int index = nodeIndex * 3;
80 this.data[index] = cost;
81 this.data[index + 1] = time;
82 this.data[index + 2] = distance;
88 this.currentIteration++;
89 if (this.currentIteration == Integer.MAX_VALUE) {
91 Arrays.fill(this.iterationIds, this.currentIteration);
92 this.currentIteration = Integer.MIN_VALUE;
95 int startNodeIndex = startNode.
getId().index();
96 int endNodeIndex = endNode.
getId().index();
98 int startDeadend = this.astarData.getNodeDeadend(startNodeIndex);
99 int endDeadend = this.astarData.getNodeDeadend(endNodeIndex);
103 this.comingFrom[startNodeIndex] = -1;
104 setData(startNodeIndex, 0, startTime, 0);
106 this.pq.insert(startNodeIndex, 0 + estimation);
107 boolean foundEndNode =
false;
109 while (!this.pq.isEmpty()) {
110 final int nodeIdx = this.pq.poll();
111 if (nodeIdx == endNodeIndex) {
116 if (hasTurnRestrictions && this.graph.getNode(nodeIdx).
getId().index() == endNodeIndex) {
118 endNodeIndex = nodeIdx;
123 int deadend = this.astarData.getNodeDeadend(nodeIdx);
124 if (deadend >= 0 && deadend != startDeadend && deadend != endDeadend) {
129 double currCost =
getCost(nodeIdx);
132 this.
outLI.reset(nodeIdx);
133 while (this.
outLI.next()) {
134 int linkIdx = this.
outLI.getLinkIndex();
135 Link link = this.graph.getLink(linkIdx);
136 int toNode = this.
outLI.getToNodeIndex();
139 double newTime = currTime + travelTime;
141 double newCost = currCost + travelCost;
143 if (this.iterationIds[toNode] == this.currentIteration) {
145 double oldCost =
getCost(toNode);
146 if (newCost < oldCost) {
148 this.pq.decreaseKey(toNode, newCost + estimation);
150 this.comingFrom[toNode] = nodeIdx;
151 this.usedLink[toNode] = linkIdx;
156 this.pq.insert(toNode, newCost + estimation);
157 this.comingFrom[toNode] = nodeIdx;
158 this.usedLink[toNode] = linkIdx;
166 LOG.warn(
"No route was found from node " + startNode.
getId() +
" to node " + endNode.
getId() +
". Some possible reasons:");
167 LOG.warn(
" * Network is not connected. Run NetworkCleaner().") ;
168 LOG.warn(
" * Network for considered mode does not even exist. Modes need to be entered for each link in network.xml.");
169 LOG.warn(
" * Network for considered mode is not connected to starting or ending point of route. Setting insertingAccessEgressWalk to true may help.");
170 LOG.warn(
"This will now return null, but it may fail later with a NullPointerException.");
185 for (
int i = 0, n = this.astarData.getLandmarksCount(); i < n; i++) {
187 if (estimate > best) {
195 double sl = this.astarData.getTravelCostToLandmark(nodeIdx, landmarkIdx);
196 double ls = this.astarData.getTravelCostFromLandmark(nodeIdx, landmarkIdx);
197 double tl = this.astarData.getTravelCostToLandmark(destinationIdx, landmarkIdx);
198 double lt = this.astarData.getTravelCostFromLandmark(destinationIdx, landmarkIdx);
199 double sltl = sl - tl;
200 double ltls = lt - ls;
201 return Math.max(sltl, ltls);
205 double travelCost =
getCost(endNodeIndex);
206 double arrivalTime =
getTimeRaw(endNodeIndex);
207 if (Double.isInfinite(arrivalTime)) {
210 double travelTime = arrivalTime - startTime;
212 List<Node> nodes =
new ArrayList<>();
213 List<Link> links =
new ArrayList<>();
215 int nodeIndex = endNodeIndex;
217 nodes.add(this.graph.getNode(nodeIndex));
219 int linkIndex = this.usedLink[nodeIndex];
220 nodeIndex = this.comingFrom[nodeIndex];
222 while (nodeIndex >= 0) {
223 nodes.add(this.graph.getNode(nodeIndex));
224 links.add(this.graph.getLink(linkIndex));
226 linkIndex = this.usedLink[nodeIndex];
227 nodeIndex = this.comingFrom[nodeIndex];
230 Collections.reverse(nodes);
231 Collections.reverse(links);
233 return new Path(nodes, links, travelTime, travelCost);
final boolean hasTurnRestrictions
Path constructPath(int endNodeIndex, double startTime)
void setData(int nodeIndex, double cost, double time, double distance)
double estimateMinTravelcostToDestinationForLandmark(int nodeIdx, int destinationIdx, int landmarkIdx)
double getLinkTravelTime(Link link, double time, Person person, Vehicle vehicle)
double getTimeRaw(int nodeIndex)
double getLinkTravelDisutility(final Link link, final double time, final Person person, final Vehicle vehicle)
final SpeedyALTData astarData
final TravelDisutility td
double getCost(int nodeIndex)
final SpeedyGraph.LinkIterator outLI
double getDistance(int nodeIndex)
double estimateMinTravelcostToDestination(int nodeIdx, int destinationIdx)
SpeedyALT(SpeedyALTData astarData, TravelTime tt, TravelDisutility td)
final int [] iterationIds
Path calcLeastCostPath(Node startNode, Node endNode, double startTime, Person person, Vehicle vehicle)
LinkIterator getOutLinkIterator()