/* This program is free software: you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package org.opentripplanner.routing.spt;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import org.opentripplanner.common.MavenVersion;
import org.opentripplanner.routing.core.RoutingRequest;
import org.opentripplanner.routing.core.State;
import org.opentripplanner.routing.graph.Vertex;
/**
* A ShortestPathTree implementation that corresponds to a basic Dijkstra search for the earliest
* arrival problem. A single optimal state is tracked per vertex: the one that minimizes
* arrival time. Optimizing for arrival time eliminates the usual need to maintain Pareto-optimal
* sets of states when working on a time-dependent graph.
*
* This approach is more coherent in Analyst when we are extracting travel times from the optimal
* paths. It should also lead to less branching and faster response times when building large
* shortest path trees.
*
* Note that for this SPT to work properly, the work queue should be ordered by time rather than weight.
*
* @author andrewbyrd
*/
public class EarliestArrivalShortestPathTree extends AbstractShortestPathTree {
private static final long serialVersionUID = MavenVersion.VERSION.getUID();
private static final int DEFAULT_CAPACITY = 500;
Map<Vertex, State> states;
/**
* Parameterless constructor that uses a default capacity for internal vertex-keyed data
* structures.
*/
public EarliestArrivalShortestPathTree (RoutingRequest options) {
this(options, DEFAULT_CAPACITY);
}
/**
* Constructor with a parameter indicating the initial capacity of the data structures holding
* vertices. This can help avoid resizing and rehashing these objects during path searches.
*
* @param n
* - the initial size of vertex-keyed maps
*/
public EarliestArrivalShortestPathTree (RoutingRequest options, int n) {
super(options);
states = new IdentityHashMap<Vertex, State>(n);
}
@Override
public Collection<State> getAllStates() {
return states.values();
}
/****
* {@link ShortestPathTree} Interface
****/
private boolean earlier (State s0, State s1) {
return s0.getActiveTime() < s1.getActiveTime();
}
@Override
public boolean add(State state) {
Vertex here = state.getVertex();
State existing = states.get(here);
if (existing == null || earlier (state, existing)) {
states.put(here, state);
return true;
} else {
// !! turn restriction code removed
return false;
}
}
@Override
public List<State> getStates(Vertex dest) {
State s = states.get(dest);
if (s == null)
return Collections.emptyList();
else
return Arrays.asList(s); // single-element array-backed list
}
@Override
public State getState(Vertex dest) {
return states.get(dest);
}
@Override
public boolean visit(State s) {
final State existing = states.get(s.getVertex());
return (s == existing);
}
@Override
public int getVertexCount() {
return states.size();
}
}