Search in sources :

Example 1 with RepeatedRaptorProfileRouter

use of org.opentripplanner.profile.RepeatedRaptorProfileRouter in project OpenTripPlanner by opentripplanner.

the class ConvertToFrequencyTest method testBidirectional.

/**
 * Test bidirectional conversion
 */
@Test
public void testBidirectional() throws Exception {
    Graph gg = buildGraphNoTransit();
    addTransitBidirectional(gg);
    link(gg);
    gg.index(new DefaultStreetVertexIndexFactory());
    ProfileRequest pr2 = new ProfileRequest();
    pr2.date = new LocalDate(2015, 6, 10);
    pr2.fromTime = 7 * 3600;
    pr2.toTime = 9 * 3600;
    pr2.fromLat = pr2.toLat = 39.9621;
    pr2.fromLon = pr2.toLon = -83.0007;
    pr2.accessModes = pr2.egressModes = pr2.directModes = new QualifiedModeSet("WALK");
    pr2.transitModes = new TraverseModeSet("TRANSIT");
    ConvertToFrequency ctf = new ConvertToFrequency();
    ctf.groupBy = ConvertToFrequency.ConversionGroup.ROUTE_DIRECTION;
    ctf.routeId = new String[] { "route" };
    ctf.windowStart = 5 * 3600;
    ctf.windowEnd = 10 * 3600;
    pr2.scenario = new Scenario(0);
    pr2.scenario.modifications = Arrays.asList(ctf);
    RepeatedRaptorProfileRouter rrpr2 = new RepeatedRaptorProfileRouter(gg, pr2);
    rrpr2.route();
    assertTrue(rrpr2.raptorWorkerData.hasFrequencies);
    assertEquals(2, rrpr2.raptorWorkerData.timetablesForPattern.size());
    // make sure we got trips in both directions
    RaptorWorkerTimetable tt = rrpr2.raptorWorkerData.timetablesForPattern.get(0);
    RaptorWorkerTimetable tt2 = rrpr2.raptorWorkerData.timetablesForPattern.get(1);
    assertEquals(2, tt2.stopIndices.length);
    assertEquals(2, tt.stopIndices.length);
    assertEquals(tt.stopIndices[0], tt2.stopIndices[1]);
    assertEquals(tt.stopIndices[1], tt2.stopIndices[0]);
}
Also used : RepeatedRaptorProfileRouter(org.opentripplanner.profile.RepeatedRaptorProfileRouter) FakeGraph(org.opentripplanner.graph_builder.module.FakeGraph) Graph(org.opentripplanner.routing.graph.Graph) ConvertToFrequency(org.opentripplanner.analyst.scenario.ConvertToFrequency) QualifiedModeSet(org.opentripplanner.api.parameter.QualifiedModeSet) TraverseModeSet(org.opentripplanner.routing.core.TraverseModeSet) DefaultStreetVertexIndexFactory(org.opentripplanner.routing.impl.DefaultStreetVertexIndexFactory) RaptorWorkerTimetable(org.opentripplanner.profile.RaptorWorkerTimetable) ProfileRequest(org.opentripplanner.profile.ProfileRequest) LocalDate(org.joda.time.LocalDate) Scenario(org.opentripplanner.analyst.scenario.Scenario) Test(org.junit.Test)

Example 2 with RepeatedRaptorProfileRouter

use of org.opentripplanner.profile.RepeatedRaptorProfileRouter in project OpenTripPlanner by opentripplanner.

the class InitialStopsTest method testInitialStopWalkSpeedIncrease.

/**
 * Test that increasing the walk speed on a walk-to-transit search
 * a) decreases or leaves unchanged all access times.
 * b) allows access to a superset of the originally accessible stops.
 * c) decreases at least some access times.
 *
 * There was once a bug where bike speed was not correctly applied because we used the distance not the speed.
 */
@Test
public void testInitialStopWalkSpeedIncrease() throws Exception {
    Graph g = buildGraphNoTransit();
    addRegularStopGrid(g);
    addTransitMultipleLines(g);
    link(g);
    g.index(new DefaultStreetVertexIndexFactory());
    ProfileRequest req = new ProfileRequest();
    req.fromLon = req.toLon = -83.0118;
    req.fromLat = req.toLat = 39.9908;
    req.date = new LocalDate(2015, 9, 17);
    req.bikeSpeed = 4.1f;
    req.walkSpeed = 1.3f;
    req.fromTime = 7 * 3600;
    req.toTime = 9 * 3600;
    req.maxBikeTime = 20;
    req.maxWalkTime = 20;
    req.transitModes = new TraverseModeSet("TRANSIT");
    req.accessModes = req.egressModes = req.directModes = new QualifiedModeSet("WALK");
    RaptorWorkerData data = RepeatedRaptorProfileRouter.getRaptorWorkerData(req, g, null, new TaskStatistics());
    assertNotNull(data);
    RepeatedRaptorProfileRouter rrpr = new RepeatedRaptorProfileRouter(g, req);
    TIntIntMap initialStops1 = rrpr.findInitialStops(false, data);
    assertFalse(initialStops1.isEmpty());
    // let's get crazy, set walk speed really high.
    req.walkSpeed = 25f;
    data = RepeatedRaptorProfileRouter.getRaptorWorkerData(req, g, null, new TaskStatistics());
    assertNotNull(data);
    rrpr = new RepeatedRaptorProfileRouter(g, req);
    TIntIntMap initialStops2 = rrpr.findInitialStops(false, data);
    // we should find decreases to at least some stops
    boolean foundDecreases = false;
    for (TIntIntIterator it = initialStops1.iterator(); it.hasNext(); ) {
        it.advance();
        // the reached stops from the faster search should be a superset of the reached stops from the slower search
        assertTrue(initialStops2.containsKey(it.key()));
        assertTrue("Found increase in travel time to stop", initialStops2.get(it.key()) <= it.value());
        foundDecreases = foundDecreases || initialStops2.get(it.key()) < it.value() - EPSILON;
    }
    assertTrue("No decreases were found due to increased walk speed", foundDecreases);
}
Also used : RepeatedRaptorProfileRouter(org.opentripplanner.profile.RepeatedRaptorProfileRouter) FakeGraph(org.opentripplanner.graph_builder.module.FakeGraph) Graph(org.opentripplanner.routing.graph.Graph) TIntIntIterator(gnu.trove.iterator.TIntIntIterator) TaskStatistics(org.opentripplanner.analyst.cluster.TaskStatistics) TraverseModeSet(org.opentripplanner.routing.core.TraverseModeSet) QualifiedModeSet(org.opentripplanner.api.parameter.QualifiedModeSet) RaptorWorkerData(org.opentripplanner.profile.RaptorWorkerData) DefaultStreetVertexIndexFactory(org.opentripplanner.routing.impl.DefaultStreetVertexIndexFactory) ProfileRequest(org.opentripplanner.profile.ProfileRequest) LocalDate(org.joda.time.LocalDate) TIntIntMap(gnu.trove.map.TIntIntMap) Test(org.junit.Test)

Example 3 with RepeatedRaptorProfileRouter

use of org.opentripplanner.profile.RepeatedRaptorProfileRouter in project OpenTripPlanner by opentripplanner.

the class InitialStopsTest method testInitialStopBikeSpeedIncrease.

/**
 * Test that increasing the bike speed on a bike-to-transit search
 * a) decreases or leaves unchanged all access times.
 * b) allows access to a superset of the originally accessible stops.
 *
 * There was once a bug where bike speed was not correctly applied because we used the distance not the speed.
 */
@Test
public void testInitialStopBikeSpeedIncrease() throws Exception {
    Graph g = buildGraphNoTransit();
    addRegularStopGrid(g);
    addTransitMultipleLines(g);
    link(g);
    g.index(new DefaultStreetVertexIndexFactory());
    ProfileRequest req = new ProfileRequest();
    req.fromLon = req.toLon = -83.0118;
    req.fromLat = req.toLat = 39.9908;
    req.date = new LocalDate(2015, 9, 17);
    req.bikeSpeed = 4.1f;
    req.walkSpeed = 1.3f;
    req.fromTime = 7 * 3600;
    req.toTime = 9 * 3600;
    req.maxBikeTime = 20;
    req.transitModes = new TraverseModeSet("TRANSIT");
    req.accessModes = req.egressModes = req.directModes = new QualifiedModeSet("BICYCLE");
    RaptorWorkerData data = RepeatedRaptorProfileRouter.getRaptorWorkerData(req, g, null, new TaskStatistics());
    assertNotNull(data);
    RepeatedRaptorProfileRouter rrpr = new RepeatedRaptorProfileRouter(g, req);
    TIntIntMap initialStops1 = rrpr.findInitialStops(false, data);
    assertFalse(initialStops1.isEmpty());
    // let's get crazy, set bike speed really high.
    req.bikeSpeed = 25f;
    data = RepeatedRaptorProfileRouter.getRaptorWorkerData(req, g, null, new TaskStatistics());
    assertNotNull(data);
    rrpr = new RepeatedRaptorProfileRouter(g, req);
    TIntIntMap initialStops2 = rrpr.findInitialStops(false, data);
    // we should find decreases to at least some stops
    boolean foundDecreases = false;
    for (TIntIntIterator it = initialStops1.iterator(); it.hasNext(); ) {
        it.advance();
        // the reached stops from the faster search should be a superset of the reached stops from the slower search
        assertTrue(initialStops2.containsKey(it.key()));
        assertTrue("Found increase in travel time to stop", initialStops2.get(it.key()) <= it.value());
        foundDecreases = foundDecreases || initialStops2.get(it.key()) < it.value() - EPSILON;
    }
    assertTrue(foundDecreases);
}
Also used : RepeatedRaptorProfileRouter(org.opentripplanner.profile.RepeatedRaptorProfileRouter) FakeGraph(org.opentripplanner.graph_builder.module.FakeGraph) Graph(org.opentripplanner.routing.graph.Graph) TIntIntIterator(gnu.trove.iterator.TIntIntIterator) TaskStatistics(org.opentripplanner.analyst.cluster.TaskStatistics) TraverseModeSet(org.opentripplanner.routing.core.TraverseModeSet) QualifiedModeSet(org.opentripplanner.api.parameter.QualifiedModeSet) RaptorWorkerData(org.opentripplanner.profile.RaptorWorkerData) DefaultStreetVertexIndexFactory(org.opentripplanner.routing.impl.DefaultStreetVertexIndexFactory) ProfileRequest(org.opentripplanner.profile.ProfileRequest) LocalDate(org.joda.time.LocalDate) TIntIntMap(gnu.trove.map.TIntIntMap) Test(org.junit.Test)

Example 4 with RepeatedRaptorProfileRouter

use of org.opentripplanner.profile.RepeatedRaptorProfileRouter in project OpenTripPlanner by opentripplanner.

the class RepeatedRaptorTestResource method oneOrigin.

private void oneOrigin(double lat, double lon, String banAgency) {
    ProfileRequest req = new ProfileRequest();
    req.fromLat = lat;
    req.fromLon = lon;
    req.fromTime = 60 * 60 * 8;
    req.toTime = 60 * 60 * 9;
    req.walkSpeed = 2;
    req.bikeSpeed = 4;
    req.carSpeed = 8;
    req.date = new LocalDate(2015, 04, 20);
    // minutes
    req.maxWalkTime = 20;
    req.accessModes = new QualifiedModeSet("WALK");
    req.egressModes = new QualifiedModeSet("WALK");
    req.transitModes = new TraverseModeSet("TRANSIT");
    req.analyst = true;
    if (surfaceCache == null) {
        LOG.error("You must run OTP with the --analyst option to enable spatial analysis features.");
    }
    final RepeatedRaptorProfileRouter router_a = new RepeatedRaptorProfileRouter(graph, req);
    final RepeatedRaptorProfileRouter router_b = new RepeatedRaptorProfileRouter(graph, req);
    router_b.banAgency = banAgency;
    try {
        router_a.route();
        router_b.route();
    } catch (VertexNotFoundException ex) {
        LOG.error("vertex not found");
        return;
    }
    System.out.printf("stop, min_a, min_b, min_diff, max_a, max_b, max_diff\n");
    boolean decreased = false;
    // Compare the propagated results
    decreased = false;
    TimeSurface.RangeSet timeSurfaces_a = router_a.timeSurfaceRangeSet;
    TimeSurface.RangeSet timeSurfaces_b = router_b.timeSurfaceRangeSet;
    for (Vertex destVertex : timeSurfaces_a.min.times.keySet()) {
        int min_a = timeSurfaces_a.min.getTime(destVertex);
        int max_a = timeSurfaces_a.max.getTime(destVertex);
        int avg_a = timeSurfaces_a.avg.getTime(destVertex);
        int min_b = timeSurfaces_b.min.getTime(destVertex);
        int max_b = timeSurfaces_b.max.getTime(destVertex);
        int avg_b = timeSurfaces_b.avg.getTime(destVertex);
        long min_diff = (long) min_b - min_a;
        long max_diff = (long) max_b - max_a;
        long avg_diff = (long) avg_b - avg_a;
        if (min_b == TimeSurface.UNREACHABLE) {
            min_diff = Integer.MAX_VALUE;
            max_diff = Integer.MAX_VALUE;
            avg_diff = Integer.MAX_VALUE;
        }
        n_total += 1;
        if (min_diff < 0 || max_diff < 0 || avg_diff < 0) {
            n_decrease += 1;
            sum_decrease += max_diff;
            // Time decreased due to banning a route. This is bad, print it out.
            System.out.printf("\"%s\",%d,%d,%d,%d,%d,%d\n", destVertex.getName(), min_a, min_b, min_diff, max_a, max_b, max_diff);
            decreased = true;
        } else if (avg_diff > 0) {
            n_increase += 1;
        }
    }
    if (decreased) {
        LOG.error("Decreases happened at propagated street vertices for this origin!");
    }
    LOG.info("Street Vertices: {} increased, {} decreased out of {} destinations total", n_increase, n_decrease, n_total);
}
Also used : RepeatedRaptorProfileRouter(org.opentripplanner.profile.RepeatedRaptorProfileRouter) Vertex(org.opentripplanner.routing.graph.Vertex) TimeSurface(org.opentripplanner.analyst.TimeSurface) QualifiedModeSet(org.opentripplanner.api.parameter.QualifiedModeSet) TraverseModeSet(org.opentripplanner.routing.core.TraverseModeSet) ProfileRequest(org.opentripplanner.profile.ProfileRequest) LocalDate(org.joda.time.LocalDate) VertexNotFoundException(org.opentripplanner.routing.error.VertexNotFoundException)

Example 5 with RepeatedRaptorProfileRouter

use of org.opentripplanner.profile.RepeatedRaptorProfileRouter in project OpenTripPlanner by opentripplanner.

the class AnalystWorker method handleOneRequest.

/**
 * This is the callback that processes a single task and returns the results upon completion.
 * It may be called several times simultaneously on different executor threads.
 */
private void handleOneRequest(AnalystClusterRequest clusterRequest) {
    if (dryRunFailureRate >= 0) {
        // but will fail a certain percentage of the time.
        if (random.nextInt(100) >= dryRunFailureRate) {
            // Pretend to succeed.
            deleteRequest(clusterRequest);
        } else {
            LOG.info("Intentionally failing on task {}", clusterRequest.taskId);
        }
        return;
    }
    try {
        long startTime = System.currentTimeMillis();
        LOG.info("Handling message {}", clusterRequest.toString());
        // We need to distinguish between and handle four different types of requests here:
        // Either vector isochrones or accessibility to a pointset,
        // as either a single-origin priority request (where the result is returned immediately)
        // or a job task (where the result is saved to output location on S3).
        boolean isochrone = (clusterRequest.destinationPointsetId == null);
        boolean singlePoint = (clusterRequest.outputLocation == null);
        boolean transit = (clusterRequest.profileRequest.transitModes != null && clusterRequest.profileRequest.transitModes.isTransit());
        if (singlePoint) {
            lastHighPriorityRequestProcessed = startTime;
            if (!sideChannelOpen) {
                openSideChannel();
            }
        }
        TaskStatistics ts = new TaskStatistics();
        ts.pointsetId = clusterRequest.destinationPointsetId;
        ts.graphId = clusterRequest.graphId;
        ts.awsInstanceType = instanceType;
        ts.jobId = clusterRequest.jobId;
        ts.workerId = machineId;
        ts.single = singlePoint;
        // Get the graph object for the ID given in the request, fetching inputs and building as needed.
        // All requests handled together are for the same graph, and this call is synchronized so the graph will
        // only be built once.
        long graphStartTime = System.currentTimeMillis();
        Graph graph = clusterGraphBuilder.getGraph(clusterRequest.graphId);
        // Record graphId so we "stick" to this same graph on subsequent polls
        graphId = clusterRequest.graphId;
        ts.graphBuild = (int) (System.currentTimeMillis() - graphStartTime);
        ts.graphTripCount = graph.index.patternForTrip.size();
        ts.graphStopCount = graph.index.stopForId.size();
        ts.lon = clusterRequest.profileRequest.fromLon;
        ts.lat = clusterRequest.profileRequest.fromLat;
        final SampleSet sampleSet;
        // fetch the set of points we will use as destinations.
        if (isochrone) {
            // This is an isochrone request, tell the RepeatedRaptorProfileRouter there are no targets.
            sampleSet = null;
        } else {
            // This is not an isochrone request. There is necessarily a destination point set supplied.
            PointSet pointSet = pointSetDatastore.get(clusterRequest.destinationPointsetId);
            // TODO this breaks if graph has been rebuilt
            sampleSet = pointSet.getOrCreateSampleSet(graph);
        }
        // Note that all parameters to create the Raptor worker data are passed in the constructor except ts.
        // Why not pass in ts as well since this is a throwaway calculator?
        RepeatedRaptorProfileRouter router = new RepeatedRaptorProfileRouter(graph, clusterRequest.profileRequest, sampleSet);
        router.ts = ts;
        // But then we'd need to pass in both the cache and the key, which is weird.
        if (transit && !singlePoint) {
            long dataStart = System.currentTimeMillis();
            router.raptorWorkerData = workerDataCache.get(clusterRequest.jobId, () -> RepeatedRaptorProfileRouter.getRaptorWorkerData(clusterRequest.profileRequest, graph, sampleSet, ts));
            ts.raptorData = (int) (System.currentTimeMillis() - dataStart);
        } else {
            // The worker will generate a one-time throw-away table.
            router.raptorWorkerData = null;
        }
        // Run the core repeated-raptor analysis.
        // This result envelope will contain the results of the one-to-many profile or single-departure-time search.
        ResultEnvelope envelope = new ResultEnvelope();
        try {
            // TODO when router runs, if there are no transit modes defined it should just skip the transit work.
            router.includeTimes = clusterRequest.includeTimes;
            envelope = router.route();
            envelope.id = clusterRequest.id;
            ts.success = true;
        } catch (Exception ex) {
            // An error occurred. Leave the envelope empty and TODO include error information.
            LOG.error("Error occurred in profile request", ex);
            ts.success = false;
        }
        // Send the ResultEnvelope back to the user.
        // The results are either stored on S3 (for multi-origin jobs) or sent back through the broker (for
        // immediate interactive display of isochrones).
        envelope.id = clusterRequest.id;
        envelope.jobId = clusterRequest.jobId;
        envelope.destinationPointsetId = clusterRequest.destinationPointsetId;
        if (clusterRequest.outputLocation != null) {
            // Convert the result envelope and its contents to JSON and gzip it in this thread.
            // Transfer the results to Amazon S3 in another thread, piping between the two.
            String s3key = String.join("/", clusterRequest.jobId, clusterRequest.id + ".json.gz");
            PipedInputStream inPipe = new PipedInputStream();
            PipedOutputStream outPipe = new PipedOutputStream(inPipe);
            new Thread(() -> {
                s3.putObject(clusterRequest.outputLocation, s3key, inPipe, null);
            }).start();
            OutputStream gzipOutputStream = new GZIPOutputStream(outPipe);
            // We could do the writeValue() in a thread instead, in which case both the DELETE and S3 options
            // could consume it in the same way.
            objectMapper.writeValue(gzipOutputStream, envelope);
            gzipOutputStream.close();
            // Tell the broker the task has been handled and should not be re-delivered to another worker.
            deleteRequest(clusterRequest);
        } else {
            // No output location was provided. Instead of saving the result on S3,
            // return the result immediately via a connection held open by the broker and mark the task completed.
            finishPriorityTask(clusterRequest, envelope);
        }
        // Record information about the current task so we can analyze usage and efficiency over time.
        ts.total = (int) (System.currentTimeMillis() - startTime);
        statsStore.store(ts);
    } catch (Exception ex) {
        LOG.error("An error occurred while routing", ex);
    }
}
Also used : GZIPOutputStream(java.util.zip.GZIPOutputStream) OutputStream(java.io.OutputStream) PipedOutputStream(java.io.PipedOutputStream) PipedOutputStream(java.io.PipedOutputStream) PipedInputStream(java.io.PipedInputStream) HttpHostConnectException(org.apache.http.conn.HttpHostConnectException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) SocketTimeoutException(java.net.SocketTimeoutException) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) IOException(java.io.IOException) PointSet(org.opentripplanner.analyst.PointSet) SampleSet(org.opentripplanner.analyst.SampleSet) RepeatedRaptorProfileRouter(org.opentripplanner.profile.RepeatedRaptorProfileRouter) Graph(org.opentripplanner.routing.graph.Graph) GZIPOutputStream(java.util.zip.GZIPOutputStream)

Aggregations

RepeatedRaptorProfileRouter (org.opentripplanner.profile.RepeatedRaptorProfileRouter)9 ProfileRequest (org.opentripplanner.profile.ProfileRequest)8 LocalDate (org.joda.time.LocalDate)7 QualifiedModeSet (org.opentripplanner.api.parameter.QualifiedModeSet)7 TraverseModeSet (org.opentripplanner.routing.core.TraverseModeSet)7 Graph (org.opentripplanner.routing.graph.Graph)7 Test (org.junit.Test)5 FakeGraph (org.opentripplanner.graph_builder.module.FakeGraph)5 DefaultStreetVertexIndexFactory (org.opentripplanner.routing.impl.DefaultStreetVertexIndexFactory)5 TaskStatistics (org.opentripplanner.analyst.cluster.TaskStatistics)3 ConvertToFrequency (org.opentripplanner.analyst.scenario.ConvertToFrequency)3 Scenario (org.opentripplanner.analyst.scenario.Scenario)3 RaptorWorkerData (org.opentripplanner.profile.RaptorWorkerData)3 RaptorWorkerTimetable (org.opentripplanner.profile.RaptorWorkerTimetable)3 TIntIntIterator (gnu.trove.iterator.TIntIntIterator)2 TIntIntMap (gnu.trove.map.TIntIntMap)2 TimeSurface (org.opentripplanner.analyst.TimeSurface)2 Vertex (org.opentripplanner.routing.graph.Vertex)2 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)1 Coordinate (com.vividsolutions.jts.geom.Coordinate)1