diff --git a/opentripplanner-routing/pom.xml b/opentripplanner-routing/pom.xml
index 2d200e987a3..1fbefcb85d1 100644
--- a/opentripplanner-routing/pom.xml
+++ b/opentripplanner-routing/pom.xml
@@ -43,6 +43,11 @@
org.springframework
spring-aop
+
+ edu.syr.pcpratts
+ rootbeer
+ 0.1.0
+
junit
junit
@@ -113,6 +118,59 @@
${project.basedir}/../.git
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+ jar-with-dependencies
+ package
+
+ single
+
+
+
+ jar-with-dependencies
+
+ opentripplanner-routing
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+ 1.7
+
+
+ rootbeer
+ package
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/opentripplanner-routing/src/main/java/org/opentripplanner/routing/impl/raptor/Raptor.java b/opentripplanner-routing/src/main/java/org/opentripplanner/routing/impl/raptor/Raptor.java
index 485c67f3086..b660567b1e7 100644
--- a/opentripplanner-routing/src/main/java/org/opentripplanner/routing/impl/raptor/Raptor.java
+++ b/opentripplanner-routing/src/main/java/org/opentripplanner/routing/impl/raptor/Raptor.java
@@ -100,7 +100,7 @@ public List getPaths(RoutingRequest options) {
TraverseModeSet modes = options.getModes().clone();
modes.setTransit(false);
walkOptions.setModes(modes);
- RaptorSearch search = new RaptorSearch(data, options);
+ RaptorSearch search = new RaptorSearchGPU(data, options);
if (data.maxTransitRegions != null) {
Calendar tripDate = Calendar.getInstance(graph.getTimeZone());
@@ -126,6 +126,7 @@ public List getPaths(RoutingRequest options) {
long searchBeginTime = System.currentTimeMillis();
int bestElapsedTime = Integer.MAX_VALUE;
+ options.setMaxTransfers(7);
RETRY: do {
for (int i = 0; i < options.getMaxTransfers() + 2; ++i) {
round(data, options, walkOptions, search, i);
diff --git a/opentripplanner-routing/src/main/java/org/opentripplanner/routing/impl/raptor/RaptorSearch.java b/opentripplanner-routing/src/main/java/org/opentripplanner/routing/impl/raptor/RaptorSearch.java
index 3effca5cbad..d312c0bf4b8 100644
--- a/opentripplanner-routing/src/main/java/org/opentripplanner/routing/impl/raptor/RaptorSearch.java
+++ b/opentripplanner-routing/src/main/java/org/opentripplanner/routing/impl/raptor/RaptorSearch.java
@@ -40,7 +40,7 @@ public class RaptorSearch {
List[] statesByStop;
- private List targetStates = new ArrayList();
+ protected List targetStates = new ArrayList();
Set visitedEver = new HashSet();
@@ -58,7 +58,7 @@ public class RaptorSearch {
public int maxTimeDayIndex;
- private RaptorData data;
+ protected RaptorData data;
@SuppressWarnings("unchecked")
RaptorSearch(RaptorData data, RoutingRequest options) {
diff --git a/opentripplanner-routing/src/main/java/org/opentripplanner/routing/impl/raptor/RaptorSearchGPU.java b/opentripplanner-routing/src/main/java/org/opentripplanner/routing/impl/raptor/RaptorSearchGPU.java
new file mode 100644
index 00000000000..05e38f6ffb3
--- /dev/null
+++ b/opentripplanner-routing/src/main/java/org/opentripplanner/routing/impl/raptor/RaptorSearchGPU.java
@@ -0,0 +1,271 @@
+/* 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 . */
+
+package org.opentripplanner.routing.impl.raptor;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.opentripplanner.common.pqueue.BinHeap;
+import org.opentripplanner.common.pqueue.OTPPriorityQueue;
+import org.opentripplanner.common.pqueue.OTPPriorityQueueFactory;
+import org.opentripplanner.routing.algorithm.GenericDijkstra;
+import org.opentripplanner.routing.core.RoutingRequest;
+import org.opentripplanner.routing.core.State;
+import org.opentripplanner.routing.core.StateEditor;
+import org.opentripplanner.routing.graph.Vertex;
+import org.opentripplanner.routing.spt.ShortestPathTree;
+import org.opentripplanner.routing.vertextype.TransitStop;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import edu.syr.pcpratts.rootbeer.runtime.Kernel;
+import edu.syr.pcpratts.rootbeer.runtime.Rootbeer;
+
+class LocalSearchKernel implements Kernel {
+ private GenericDijkstra search;
+
+ private RaptorSearchGPU raptor;
+
+ private State initialState;
+
+ private int nBoardings;
+
+ public LocalSearchKernel(int nBoardings, State state, GenericDijkstra search, RaptorSearchGPU raptor) {
+ this.nBoardings = nBoardings;
+ this.initialState = state;
+ this.search = search;
+ this.raptor = raptor;
+ }
+
+ @Override
+ public void gpuMethod() {
+ ShortestPathTree spt = search.getShortestPathTree(initialState);
+ SPTSTATE: for (State state : spt.getAllStates()) {
+ final Vertex vertex = state.getVertex();
+ if (!(vertex instanceof TransitStop))
+ continue;
+
+ RaptorStop stop = raptor.data.raptorStopsForStopId.get(((TransitStop) vertex).getStopId());
+ if (stop == null)
+ // we have found a stop is totally unused, so skip it
+ continue;
+
+ RaptorState parent = (RaptorState) state.getExtension("raptorParent");
+ RaptorState newState;
+ if (parent != null) {
+ newState = new RaptorState(parent);
+ } else {
+ // this only happens in round 0
+ newState = new RaptorState(state.getOptions().arriveBy);
+ }
+ newState.weight = state.getWeight();
+ newState.nBoardings = nBoardings;
+ newState.walkDistance = state.getWalkDistance();
+ newState.arrivalTime = (int) state.getTime();
+ newState.walkPath = state;
+ newState.stop = stop;
+
+ synchronized(raptor) {
+
+ List states = raptor.statesByStop[stop.index];
+ if (states == null) {
+ states = new ArrayList();
+ raptor.statesByStop[stop.index] = states;
+ }
+
+ for (RaptorState oldState : states) {
+ if (oldState.eDominates(newState)) {
+ continue SPTSTATE;
+ }
+ }
+ states.add(newState);
+ }
+ synchronized(raptor.visitedLastRound) {
+ raptor.visitedLastRound.add(stop);
+ raptor.visitedEver.add(stop);
+ }
+ }
+ }
+
+}
+
+public class RaptorSearchGPU extends RaptorSearch {
+ private static final Logger log = LoggerFactory.getLogger(RaptorSearchGPU.class);
+
+ @SuppressWarnings("unchecked")
+ RaptorSearchGPU(RaptorData data, RoutingRequest options) {
+ super(data,options);
+ }
+ public void walkPhase(RoutingRequest options, RoutingRequest walkOptions, int nBoardings,
+ List createdStates) {
+
+ final double distanceToNearestTransitStop = options.rctx.target
+ .getDistanceToNearestTransitStop();
+ ShortestPathTree spt;
+ GenericDijkstra dijkstra = new GenericDijkstra(walkOptions);
+ //dijkstra.setShortestPathTreeFactory(bounder);
+
+ if (nBoardings == 0) {
+ //TODO: retry min-time bounding with this and with maxtime
+
+ if (bounder.getTargetDistance(options.rctx.origin) < options.getMaxWalkDistance())
+ dijkstra.setHeuristic(bounder);
+
+ MaxWalkState start = new MaxWalkState(options.rctx.origin, walkOptions);
+ spt = dijkstra.getShortestPathTree(start);
+ SPTSTATE: for (State state : spt.getAllStates()) {
+ final Vertex vertex = state.getVertex();
+ if (vertex instanceof TransitStop) {
+ RaptorStop stop = data.raptorStopsForStopId.get(((TransitStop) vertex).getStopId());
+ if (stop == null) {
+ // we have found a stop is totally unused, so skip it
+ continue;
+ }
+
+ List states = statesByStop[stop.index];
+ if (states == null) {
+ states = new ArrayList();
+ statesByStop[stop.index] = states;
+ }
+
+ RaptorState newState = new RaptorState(options.arriveBy);
+ newState.weight = state.getWeight();
+ newState.nBoardings = nBoardings;
+ newState.walkDistance = state.getWalkDistance();
+ newState.arrivalTime = (int) state.getTime();
+ newState.walkPath = state;
+ newState.stop = stop;
+
+ for (RaptorState oldState : states) {
+ if (oldState.eDominates(newState)) {
+ continue SPTSTATE;
+ }
+ }
+
+ visitedLastRound.add(stop);
+ visitedEver.add(stop);
+ states.add(newState);
+ }
+ }
+
+ } else {
+
+ final List startPoints = new ArrayList();
+
+ List jobs = new ArrayList();
+ for (RaptorState state : createdStates) {
+
+ // bounding states
+ // this reduces the number of initial vertices
+ // and the state space size
+
+ Vertex stopVertex = state.stop.stopVertex;
+
+ double minWalk = distanceToNearestTransitStop;
+
+ double targetDistance = bounder.getTargetDistance(stopVertex);
+
+ if (targetDistance + state.walkDistance > options.getMaxWalkDistance()) {
+ // can't walk to destination, so we can't alight at a local vertex
+ if (state.stop.stopVertex.isLocal())
+ continue;
+ }
+
+ if (minWalk + state.walkDistance > options.getMaxWalkDistance()) {
+ continue;
+ }
+
+ StateEditor dijkstraState = new MaxWalkState.MaxWalkStateEditor(walkOptions,
+ stopVertex);
+ dijkstraState.setStartTime(options.dateTime);
+ dijkstraState.setNumBoardings(state.nBoardings);
+ dijkstraState.setWalkDistance(state.walkDistance);
+ dijkstraState.setTime(state.arrivalTime);
+ dijkstraState.setExtension("raptorParent", state);
+ dijkstraState.setOptions(walkOptions);
+ dijkstraState.incrementWeight(state.weight);
+ MaxWalkState newState = (MaxWalkState) dijkstraState.makeState();
+ jobs.add(new LocalSearchKernel(nBoardings, newState, dijkstra, this));
+
+ }
+ System.out.println("walk starts: " + startPoints.size() + " / " + visitedEver.size());
+// dijkstra.setPriorityQueueFactory(new PrefilledPriorityQueueFactory(startPoints.subList(
+// 1, startPoints.size())));
+
+// bounder.addSptStates(startPoints.subList(1, startPoints.size()));
+
+// bounder.prepareForSearch();
+
+ dijkstra.setSearchTerminationStrategy(bounder);
+ dijkstra.setSkipTraverseResultStrategy(bounder);
+
+ Rootbeer rootbeer = new Rootbeer();
+ rootbeer.runAll(jobs);
+ System.out.println("Ran " + jobs.size() + " jobs");
+ }
+
+ final List extends State> targetStates = bounder.bounders;
+ if (targetStates != null) {
+ TARGET: for (State targetState : targetStates) {
+ RaptorState parent = (RaptorState) targetState.getExtension("raptorParent");
+ RaptorState state;
+ if (parent != null) {
+ state = new RaptorState(parent);
+ state.nBoardings = parent.nBoardings;
+ } else {
+ state = new RaptorState(options.arriveBy);
+ }
+ state.weight = targetState.getWeight();
+ state.walkDistance = targetState.getWalkDistance();
+ state.arrivalTime = (int) targetState.getTime();
+ state.walkPath = targetState;
+ for (Iterator it = getTargetStates().iterator(); it.hasNext();) {
+ RaptorState oldState = it.next();
+ if (oldState.eDominates(state)) {
+ continue TARGET;
+ } else if (state.eDominates(oldState)) {
+ it.remove();
+ }
+ }
+ addTargetState(state);
+ log.debug("Found target at: " + state);
+ }
+ }
+ for (State state : bounder.removedBoundingStates) {
+ removeTargetState(state);
+ }
+ }
+
+ class PrefilledPriorityQueueFactory implements OTPPriorityQueueFactory {
+
+ private List extends State> startPoints;
+
+ public PrefilledPriorityQueueFactory(List extends State> startPoints) {
+ this.startPoints = startPoints;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public OTPPriorityQueue create(int maxSize) {
+ BinHeap heap = new BinHeap();
+ for (State state : startPoints) {
+ heap.insert(state, state.getWeight());
+ }
+ return heap;
+ }
+
+ }
+
+}
diff --git a/opentripplanner-routing/src/main/java/org/opentripplanner/routing/impl/raptor/TargetBound.java b/opentripplanner-routing/src/main/java/org/opentripplanner/routing/impl/raptor/TargetBound.java
index e45b2da1c28..02ab66af89d 100644
--- a/opentripplanner-routing/src/main/java/org/opentripplanner/routing/impl/raptor/TargetBound.java
+++ b/opentripplanner-routing/src/main/java/org/opentripplanner/routing/impl/raptor/TargetBound.java
@@ -107,11 +107,12 @@ public boolean shouldSearchContinue(Vertex origin, Vertex target, State current,
}
if (vertex == realTarget) {
addBounder(current);
+ return false;
}
return true;
}
- private void addBounder(State bounder) {
+ private synchronized void addBounder(State bounder) {
for (Iterator it = bounders.iterator(); it.hasNext(); ) {
State old = it.next();
if (bounder.dominates(old)) {
@@ -141,22 +142,8 @@ private void addBounder(State bounder) {
public boolean shouldSkipTraversalResult(Vertex origin, Vertex target, State parent,
State current, ShortestPathTree spt, RoutingRequest traverseOptions) {
final Vertex vertex = current.getVertex();
- int vertexIndex = vertex.getIndex();
- if (vertexIndex < distance.length) {
- if (distance[vertexIndex] > 0.0) {
- targetDistance = distance[vertexIndex];
- } else {
- targetDistance = distanceLibrary.fastDistance(realTargetCoordinate.y, realTargetCoordinate.x,
- vertex.getY(), vertex.getX());
- distance[vertexIndex] = targetDistance;
- if (vertex instanceof TransitStop && targetDistance < bestTargetDistance) {
- bestTargetDistance = targetDistance;
- }
- }
- } else {
- targetDistance = distanceLibrary.fastDistance(realTargetCoordinate.y, realTargetCoordinate.x,
- vertex.getY(), vertex.getX());
- }
+ targetDistance = distanceLibrary.fastDistance(realTargetCoordinate.y, realTargetCoordinate.x,
+ vertex.getY(), vertex.getX());
final double remainingWalk = traverseOptions.maxWalkDistance
- current.getWalkDistance();
@@ -316,7 +303,7 @@ public ShortestPathTree create(RoutingRequest options) {
public void addSptStates(List states) {
for (MaxWalkState state : states) {
if (state.getVertex() instanceof TransitStop) {
- transitStopsVisited.add(state);
+ //transitStopsVisited.add(state);
}
spt.add(state);
}
diff --git a/pom.xml b/pom.xml
index 0aca8f5d51a..4d67cd7827b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -268,6 +268,18 @@
+
+ lib
+ lib
+
+ true
+ ignore
+
+
+ false
+
+ file:///home/novalis/otp/opentripplanner/opentripplanner/lib
+