All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentripplanner.routing.algorithm.raptor.transit.mappers.TransitLayerMapper Maven / Gradle / Ivy

There is a newer version: 2.5.0
Show newest version
package org.opentripplanner.routing.algorithm.raptor.transit.mappers;

import org.opentripplanner.model.Timetable;
import org.opentripplanner.model.TripPattern;
import org.opentripplanner.model.calendar.ServiceDate;
import org.opentripplanner.routing.algorithm.raptor.transit.StopIndexForRaptor;
import org.opentripplanner.routing.algorithm.raptor.transit.Transfer;
import org.opentripplanner.routing.algorithm.raptor.transit.TransitLayer;
import org.opentripplanner.routing.algorithm.raptor.transit.TransitTuningParameters;
import org.opentripplanner.routing.algorithm.raptor.transit.TripPatternForDate;
import org.opentripplanner.routing.algorithm.raptor.transit.TripPatternWithRaptorStopIndexes;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.routing.trippattern.TripTimes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import static org.opentripplanner.routing.algorithm.raptor.transit.mappers.TransfersMapper.mapTransfers;
import static org.opentripplanner.routing.algorithm.raptor.transit.mappers.TripPatternMapper.mapOldTripPatternToRaptorTripPattern;

/**
 * Maps the TransitLayer object from the OTP Graph object. The ServiceDay hierarchy is reversed,
 * with service days at the top level, which contains TripPatternForDate objects that contain
 * only TripSchedules running on that particular date. This makes it faster to filter out
 * TripSchedules when doing Range Raptor searches.
 *
 * CONCURRENCY: This mapper run part of the mapping in parallel using parallel streams. This
 *              improve startup time on the Norwegian graph by 20 seconds; reducing the this
 *              mapper from 36 seconds to 15 seconds, and the total startup time from 80 seconds
 *              to 60 seconds. (JAN 2020, MacBook Pro, 3.1 GHz i7)
 */
public class TransitLayerMapper {

    private static final Logger LOG = LoggerFactory.getLogger(TransitLayerMapper.class);

    private final Graph graph;

    private TransitLayerMapper(Graph graph) {
        this.graph = graph;
    }

    public static TransitLayer map(TransitTuningParameters tuningParameters, Graph graph) {
        return new TransitLayerMapper(graph).map(tuningParameters);
    }

    private TransitLayer map(TransitTuningParameters tuningParameters) {
        StopIndexForRaptor stopIndex;
        HashMap> tripPatternsByStopByDate;
        List> transferByStopIndex;

        LOG.info("Mapping transitLayer from Graph...");

        stopIndex =  new StopIndexForRaptor(graph.index.getAllStops(), tuningParameters);
        tripPatternsByStopByDate = mapTripPatterns(stopIndex);
        transferByStopIndex = mapTransfers(stopIndex, graph.transfersByStop);

        LOG.info("Mapping complete.");

        return new TransitLayer(
            tripPatternsByStopByDate,
            transferByStopIndex,
            stopIndex,
            graph.getTimeZone().toZoneId()
        );
    }

    /**
     * Map pre-Raptor TripPatterns and Trips to the corresponding Raptor classes.
     * 

* Part of this method runs IN PARALLEL. *

*/ private HashMap> mapTripPatterns ( StopIndexForRaptor stopIndex ) { Collection allTripPatterns = graph.tripPatternForId.values(); final Map newTripPatternForOld = mapOldTripPatternToRaptorTripPattern(stopIndex, allTripPatterns); TripPatternForDateMapper tripPatternForDateMapper = new TripPatternForDateMapper( graph.index.getServiceCodesRunningForDate(), newTripPatternForOld ); Set allServiceDates = graph.index.getServiceCodesRunningForDate().keySet(); // The return value of this entire process. ConcurrentHashMap> result = new ConcurrentHashMap<>(); // THIS CODE RUNS IN PARALLEL allServiceDates .parallelStream() .forEach(serviceDate -> { // Create LocalDate equivalent to the OTP/GTFS ServiceDate object, serving as the key of // the return Map. LocalDate localDate = ServiceCalendarMapper.localDateFromServiceDate(serviceDate); // Create a List to hold the values for one entry in the return Map. List values = new ArrayList<>(); // This nested loop could be quite inefficient. // Maybe determine in advance which patterns are running on each service and day. for (org.opentripplanner.model.TripPattern oldTripPattern : allTripPatterns) { TripPatternForDate tripPatternForDate = tripPatternForDateMapper.map( oldTripPattern.scheduledTimetable, serviceDate ); if (tripPatternForDate != null) { values.add(tripPatternForDate); } } if (!values.isEmpty()) { result.put(localDate, values); } }); // END PARALLEL CODE return new HashMap<>(result); } // TODO We can save time by either pre-sorting these or use a sorting algorithm that is // optimized for sorting nearly sorted list static List getSortedTripTimes (Timetable timetable) { return timetable.tripTimes.stream() .sorted(Comparator.comparing(t -> t.getArrivalTime(0))) .collect(Collectors.toList()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy