package org.opentripplanner.routing.algorithm; import gnu.trove.iterator.TObjectIntIterator; import gnu.trove.map.TObjectIntMap; import gnu.trove.map.hash.TObjectIntHashMap; import org.opentripplanner.routing.vertextype.TransitStop; import java.util.Collection; @SuppressWarnings("unchecked") public class PathDiscardingRaptorStateStore implements RaptorStateStore { /** Maps from stops to arrival times by transit _or_ by transfer from another stop, one map per round. */ // suppressing warnings because generic arrays don't work in Java . . . @SuppressWarnings("rawtypes") private TObjectIntMap[] matrix; /** The best time to reach each stop in any round by transit only, not by transfer from another stop. */ public TObjectIntMap<TransitStop> bestStops; /** The maximum acceptable clock time in seconds since midnight. All arrivals after this time will be ignored. */ public int maxTime; /** Current round? TODO rename var */ int current = 0; @Override public boolean put(TransitStop t, int time, boolean transfer) { // This does not store internal algorithm state as it used to, but rather only the output. // The reasoning is that, in dynamic programming/range RAPTOR mode, bestStops is carried over between runs of // the algorithm. But you still want to propagate a non-optimal time with fewer transfers, because the // optimal time at this stop might have already used up all of the transfers. if (!transfer && time < bestStops.get(t)) bestStops.put(t, time); if (time < matrix[current].get(t)) { matrix[current].put(t, time); return true; } return false; } @Override public void proceed() { for (TObjectIntIterator<TransitStop> it = matrix[current].iterator(); it.hasNext();) { it.advance(); if (it.value() < matrix[current + 1].get(it.key())) matrix[current + 1].put(it.key(), it.value()); } current++; } public int getTime (TransitStop t) { return bestStops.get(t); } public int getPrev (TransitStop t) { return matrix[current - 1].get(t); } /** * Restart the search from the first round. Used when running repeated RAPTOR searches using the dynamic programming * algorithm. * * TODO write up the dynamic programming algorithm. */ public void restart () { current = 0; } public TObjectIntIterator<TransitStop> iterator () { return bestStops.iterator(); } /** Create a new store with the given number of rounds. Remember to include the initial walk as a "round" */ public PathDiscardingRaptorStateStore(int rounds) { this(rounds, Integer.MAX_VALUE); } public PathDiscardingRaptorStateStore(int rounds, int maxTime) { this.maxTime = maxTime; matrix = new TObjectIntMap[rounds]; for (int i = 0; i < rounds; i++) { matrix[i] = new TObjectIntHashMap<TransitStop>(1000, 0.75f, Integer.MAX_VALUE); } bestStops = new TObjectIntHashMap<TransitStop>(1000, 0.75f, Integer.MAX_VALUE); } public Collection<TransitStop> getTouchedStopsIncludingTransfers () { return matrix[current].keySet(); } }