MATSIM
Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
org.matsim.core.router.speedy.SpeedyALT Class Reference
Inheritance diagram for org.matsim.core.router.speedy.SpeedyALT:
Inheritance graph
[legend]

Public Member Functions

 SpeedyALT (SpeedyALTData astarData, TravelTime tt, TravelDisutility td)
 
double getCost (int nodeIndex)
 
Path calcLeastCostPath (Node startNode, Node endNode, double startTime, Person person, Vehicle vehicle)
 

Private Member Functions

double getTimeRaw (int nodeIndex)
 
double getDistance (int nodeIndex)
 
void setData (int nodeIndex, double cost, double time, double distance)
 
double estimateMinTravelcostToDestination (int nodeIdx, int destinationIdx)
 
double estimateMinTravelcostToDestinationForLandmark (int nodeIdx, int destinationIdx, int landmarkIdx)
 
Path constructPath (int endNodeIndex, double startTime)
 

Private Attributes

final SpeedyGraph graph
 
final SpeedyALTData astarData
 
final TravelTime tt
 
final TravelDisutility td
 
final double [] data
 
int currentIteration = Integer.MIN_VALUE
 
final int [] iterationIds
 
final int [] comingFrom
 
final int [] usedLink
 
final SpeedyGraph.LinkIterator outLI
 
final DAryMinHeap pq
 

Static Private Attributes

static final Logger LOG = LogManager.getLogger(SpeedyALT.class)
 

Detailed Description

A very fast implementation of the ALT algorithm (A*-search with Landmarks and Triangle Inequality).

Based on "Computing the Shortest Path: A* Search Meets Graph Theory" by Andrew V. Goldberg and Chris Harrelson, 2005.

This implementation always looks at all landmarks and does not filter them, as performance measurements suggest that selecting and re-selecting landmarks regularly actually results in an overhead compared to just calculate the values for each landmark in each step (using a typical value of 16 landmarks). This might be due to the fact that all values for each landmark are just next to each other in the memory, so when accessing the travelcosts to/from one landmark basically already loads the values of all landmarks in the CPU cache, making the calculation for the remaining landmarks very fast.

This implementation is not thread-safe. In the case of multi-threading, every thread should use a separate instance. (But the used SpeedyALTData is thread-safe and can be shared by multiple instances).

Author
mrieser / Simunto, sponsored by SBB Swiss Federal Railways

Definition at line 36 of file SpeedyALT.java.

Constructor & Destructor Documentation

◆ SpeedyALT()

org.matsim.core.router.speedy.SpeedyALT.SpeedyALT ( SpeedyALTData  astarData,
TravelTime  tt,
TravelDisutility  td 
)

Definition at line 52 of file SpeedyALT.java.

References org.matsim.core.router.speedy.SpeedyALT.astarData, org.matsim.core.router.speedy.SpeedyGraph.getOutLinkIterator(), org.matsim.core.router.speedy.SpeedyALT.outLI, org.matsim.core.router.speedy.SpeedyALT.td, and org.matsim.core.router.speedy.SpeedyALT.tt.

52  {
53  this.graph = astarData.graph;
54  this.astarData = astarData;
55  this.tt = tt;
56  this.td = td;
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);
62  this.outLI = this.graph.getOutLinkIterator();
63  Arrays.fill(this.iterationIds, this.currentIteration);
64  }
final SpeedyGraph.LinkIterator outLI
Definition: SpeedyALT.java:49
Here is the call graph for this function:

Member Function Documentation

◆ getCost()

double org.matsim.core.router.speedy.SpeedyALT.getCost ( int  nodeIndex)

Definition at line 66 of file SpeedyALT.java.

Referenced by org.matsim.core.router.speedy.SpeedyALT.calcLeastCostPath(), and org.matsim.core.router.speedy.SpeedyALT.constructPath().

66  {
67  return this.data[nodeIndex * 3];
68  }

◆ getTimeRaw()

double org.matsim.core.router.speedy.SpeedyALT.getTimeRaw ( int  nodeIndex)
private

Definition at line 70 of file SpeedyALT.java.

Referenced by org.matsim.core.router.speedy.SpeedyALT.calcLeastCostPath(), and org.matsim.core.router.speedy.SpeedyALT.constructPath().

70  {
71  return this.data[nodeIndex * 3 + 1];
72  }

◆ getDistance()

double org.matsim.core.router.speedy.SpeedyALT.getDistance ( int  nodeIndex)
private

Definition at line 74 of file SpeedyALT.java.

Referenced by org.matsim.core.router.speedy.SpeedyALT.calcLeastCostPath().

74  {
75  return this.data[nodeIndex * 3 + 2];
76  }

◆ setData()

void org.matsim.core.router.speedy.SpeedyALT.setData ( int  nodeIndex,
double  cost,
double  time,
double  distance 
)
private

Definition at line 78 of file SpeedyALT.java.

References org.matsim.core.router.speedy.SpeedyALT.currentIteration.

Referenced by org.matsim.core.router.speedy.SpeedyALT.calcLeastCostPath().

78  {
79  int index = nodeIndex * 3;
80  this.data[index] = cost;
81  this.data[index + 1] = time;
82  this.data[index + 2] = distance;
83  this.iterationIds[nodeIndex] = this.currentIteration;
84  }

◆ calcLeastCostPath()

Path org.matsim.core.router.speedy.SpeedyALT.calcLeastCostPath ( Node  startNode,
Node  endNode,
double  startTime,
Person  person,
Vehicle  vehicle 
)

Implements org.matsim.core.router.util.LeastCostPathCalculator.

Definition at line 87 of file SpeedyALT.java.

References org.matsim.core.router.speedy.SpeedyALT.constructPath(), org.matsim.core.router.speedy.SpeedyALT.estimateMinTravelcostToDestination(), org.matsim.core.router.speedy.SpeedyALT.getCost(), org.matsim.core.router.speedy.SpeedyALT.getDistance(), org.matsim.api.core.v01.Identifiable< T >.getId(), org.matsim.api.core.v01.network.Link.getLength(), org.matsim.core.router.util.TravelDisutility.getLinkTravelDisutility(), org.matsim.core.router.util.TravelTime.getLinkTravelTime(), org.matsim.core.router.speedy.SpeedyALT.getTimeRaw(), org.matsim.core.router.speedy.SpeedyGraph.hasTurnRestrictions, org.matsim.core.router.speedy.SpeedyALT.outLI, and org.matsim.core.router.speedy.SpeedyALT.setData().

87  {
88  this.currentIteration++;
89  if (this.currentIteration == Integer.MAX_VALUE) {
90  // reset iteration as we overflow
91  Arrays.fill(this.iterationIds, this.currentIteration);
92  this.currentIteration = Integer.MIN_VALUE;
93  }
94  boolean hasTurnRestrictions = this.graph.hasTurnRestrictions();
95  int startNodeIndex = startNode.getId().index();
96  int endNodeIndex = endNode.getId().index();
97 
98  int startDeadend = this.astarData.getNodeDeadend(startNodeIndex);
99  int endDeadend = this.astarData.getNodeDeadend(endNodeIndex);
100 
101  double estimation = estimateMinTravelcostToDestination(startNodeIndex, endNodeIndex);
102 
103  this.comingFrom[startNodeIndex] = -1;
104  setData(startNodeIndex, 0, startTime, 0);
105  this.pq.clear();
106  this.pq.insert(startNodeIndex, 0 + estimation);
107  boolean foundEndNode = false;
108 
109  while (!this.pq.isEmpty()) {
110  final int nodeIdx = this.pq.poll();
111  if (nodeIdx == endNodeIndex) {
112  foundEndNode = true;
113  break;
114  }
115  // if turn restrictions are used, we might be on a colored node, so check for the original node
116  if (hasTurnRestrictions && this.graph.getNode(nodeIdx).getId().index() == endNodeIndex) {
117  foundEndNode = true;
118  endNodeIndex = nodeIdx;
119  break;
120  }
121 
122  // ignore dead-ends
123  int deadend = this.astarData.getNodeDeadend(nodeIdx);
124  if (deadend >= 0 && deadend != startDeadend && deadend != endDeadend) {
125  continue; // it's a dead-end we're not interested in
126  }
127 
128  double currTime = getTimeRaw(nodeIdx);
129  double currCost = getCost(nodeIdx);
130  double currDistance = getDistance(nodeIdx);
131 
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();
137 
138  double travelTime = this.tt.getLinkTravelTime(link, currTime, person, vehicle);
139  double newTime = currTime + travelTime;
140  double travelCost = this.td.getLinkTravelDisutility(link, currTime, person, vehicle);
141  double newCost = currCost + travelCost;
142 
143  if (this.iterationIds[toNode] == this.currentIteration) {
144  // this node was already visited in this route-query
145  double oldCost = getCost(toNode);
146  if (newCost < oldCost) {
147  estimation = estimateMinTravelcostToDestination(toNode, endNodeIndex);
148  this.pq.decreaseKey(toNode, newCost + estimation);
149  setData(toNode, newCost, newTime, currDistance + link.getLength());
150  this.comingFrom[toNode] = nodeIdx;
151  this.usedLink[toNode] = linkIdx;
152  }
153  } else {
154  estimation = estimateMinTravelcostToDestination(toNode, endNodeIndex);
155  setData(toNode, newCost, newTime, currDistance + link.getLength());
156  this.pq.insert(toNode, newCost + estimation);
157  this.comingFrom[toNode] = nodeIdx;
158  this.usedLink[toNode] = linkIdx;
159  }
160  }
161  }
162 
163  if (foundEndNode) {
164  return constructPath(endNodeIndex, startTime);
165  }
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.");
171  return null;
172  }
Path constructPath(int endNodeIndex, double startTime)
Definition: SpeedyALT.java:204
void setData(int nodeIndex, double cost, double time, double distance)
Definition: SpeedyALT.java:78
double getLinkTravelTime(Link link, double time, Person person, Vehicle vehicle)
double getLinkTravelDisutility(final Link link, final double time, final Person person, final Vehicle vehicle)
final SpeedyGraph.LinkIterator outLI
Definition: SpeedyALT.java:49
double estimateMinTravelcostToDestination(int nodeIdx, int destinationIdx)
Definition: SpeedyALT.java:174
Here is the call graph for this function:

◆ estimateMinTravelcostToDestination()

double org.matsim.core.router.speedy.SpeedyALT.estimateMinTravelcostToDestination ( int  nodeIdx,
int  destinationIdx 
)
private

Definition at line 174 of file SpeedyALT.java.

References org.matsim.core.router.speedy.SpeedyALT.estimateMinTravelcostToDestinationForLandmark().

Referenced by org.matsim.core.router.speedy.SpeedyALT.calcLeastCostPath().

174  {
175  /* The ALT algorithm uses two lower bounds for each Landmark:
176  * given: source node S, target node T, landmark L
177  * then, due to the triangle inequality:
178  * 1) ST + TL >= SL --> ST >= SL - TL
179  * 2) LS + ST >= LT --> ST >= LT - LS
180  * The algorithm is interested in the largest possible value of (SL-TL) and (LT-LS),
181  * as this gives the closest approximation for the minimal travel time required to
182  * go from S to T.
183  */
184  double best = 0;
185  for (int i = 0, n = this.astarData.getLandmarksCount(); i < n; i++) {
186  double estimate = estimateMinTravelcostToDestinationForLandmark(nodeIdx, destinationIdx, i);
187  if (estimate > best) {
188  best = estimate;
189  }
190  }
191  return best;
192  }
double estimateMinTravelcostToDestinationForLandmark(int nodeIdx, int destinationIdx, int landmarkIdx)
Definition: SpeedyALT.java:194
Here is the call graph for this function:

◆ estimateMinTravelcostToDestinationForLandmark()

double org.matsim.core.router.speedy.SpeedyALT.estimateMinTravelcostToDestinationForLandmark ( int  nodeIdx,
int  destinationIdx,
int  landmarkIdx 
)
private

Definition at line 194 of file SpeedyALT.java.

Referenced by org.matsim.core.router.speedy.SpeedyALT.estimateMinTravelcostToDestination().

194  {
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);
202  }

◆ constructPath()

Path org.matsim.core.router.speedy.SpeedyALT.constructPath ( int  endNodeIndex,
double  startTime 
)
private

Definition at line 204 of file SpeedyALT.java.

References org.matsim.core.router.speedy.SpeedyALT.getCost(), and org.matsim.core.router.speedy.SpeedyALT.getTimeRaw().

Referenced by org.matsim.core.router.speedy.SpeedyALT.calcLeastCostPath().

204  {
205  double travelCost = getCost(endNodeIndex);
206  double arrivalTime = getTimeRaw(endNodeIndex);
207  if (Double.isInfinite(arrivalTime)) {
208  throw new RuntimeException("Undefined time on end node");
209  }
210  double travelTime = arrivalTime - startTime;
211 
212  List<Node> nodes = new ArrayList<>();
213  List<Link> links = new ArrayList<>();
214 
215  int nodeIndex = endNodeIndex;
216 
217  nodes.add(this.graph.getNode(nodeIndex));
218 
219  int linkIndex = this.usedLink[nodeIndex];
220  nodeIndex = this.comingFrom[nodeIndex];
221 
222  while (nodeIndex >= 0) {
223  nodes.add(this.graph.getNode(nodeIndex));
224  links.add(this.graph.getLink(linkIndex));
225 
226  linkIndex = this.usedLink[nodeIndex];
227  nodeIndex = this.comingFrom[nodeIndex];
228  }
229 
230  Collections.reverse(nodes);
231  Collections.reverse(links);
232 
233  return new Path(nodes, links, travelTime, travelCost);
234  }
Here is the call graph for this function:

Member Data Documentation

◆ LOG

final Logger org.matsim.core.router.speedy.SpeedyALT.LOG = LogManager.getLogger(SpeedyALT.class)
staticprivate

Definition at line 38 of file SpeedyALT.java.

◆ graph

final SpeedyGraph org.matsim.core.router.speedy.SpeedyALT.graph
private

Definition at line 40 of file SpeedyALT.java.

◆ astarData

final SpeedyALTData org.matsim.core.router.speedy.SpeedyALT.astarData
private

Definition at line 41 of file SpeedyALT.java.

Referenced by org.matsim.core.router.speedy.SpeedyALT.SpeedyALT().

◆ tt

final TravelTime org.matsim.core.router.speedy.SpeedyALT.tt
private

Definition at line 42 of file SpeedyALT.java.

Referenced by org.matsim.core.router.speedy.SpeedyALT.SpeedyALT().

◆ td

final TravelDisutility org.matsim.core.router.speedy.SpeedyALT.td
private

Definition at line 43 of file SpeedyALT.java.

Referenced by org.matsim.core.router.speedy.SpeedyALT.SpeedyALT().

◆ data

final double [] org.matsim.core.router.speedy.SpeedyALT.data
private

Definition at line 44 of file SpeedyALT.java.

◆ currentIteration

int org.matsim.core.router.speedy.SpeedyALT.currentIteration = Integer.MIN_VALUE
private

Definition at line 45 of file SpeedyALT.java.

Referenced by org.matsim.core.router.speedy.SpeedyALT.setData().

◆ iterationIds

final int [] org.matsim.core.router.speedy.SpeedyALT.iterationIds
private

Definition at line 46 of file SpeedyALT.java.

◆ comingFrom

final int [] org.matsim.core.router.speedy.SpeedyALT.comingFrom
private

Definition at line 47 of file SpeedyALT.java.

◆ usedLink

final int [] org.matsim.core.router.speedy.SpeedyALT.usedLink
private

Definition at line 48 of file SpeedyALT.java.

◆ outLI

final SpeedyGraph.LinkIterator org.matsim.core.router.speedy.SpeedyALT.outLI
private

◆ pq

final DAryMinHeap org.matsim.core.router.speedy.SpeedyALT.pq
private

Definition at line 50 of file SpeedyALT.java.


The documentation for this class was generated from the following file: