diff --git a/.github/workflows/deploy-dtds.yaml b/.github/workflows/deploy-dtds.yaml new file mode 100644 index 00000000000..bb48f61d27b --- /dev/null +++ b/.github/workflows/deploy-dtds.yaml @@ -0,0 +1,24 @@ +name: deploy-dtds-on-website + +on: + push: + branches: + - master + paths: + - matsim/src/main/resources/dtd + +jobs: + rsync-dtds: + name: sync DTDs to website + runs-on: ubuntu-latest + + steps: + - name: rsync dtds + uses: burnett01/rsync-deployments@7.0.1 + with: + switches: -avz + path: matsim/src/main/resources/dtd/ + remote_path: ~/httpdocs/files/dtd/ + remote_host: ${{ secrets.WEBSITE_DEPLOY_HOST }} + remote_user: ${{ secrets.WEBSITE_DEPLOY_USER }} + remote_key: ${{ secrets.WEBSITE_SSH_PRIVATE_KEY }} diff --git a/contribs/application/pom.xml b/contribs/application/pom.xml index 70a548c2dc7..4035f096a83 100644 --- a/contribs/application/pom.xml +++ b/contribs/application/pom.xml @@ -22,7 +22,7 @@ - 1.11.3 + 1.12.0 diff --git a/contribs/application/src/main/java/org/matsim/application/MATSimApplication.java b/contribs/application/src/main/java/org/matsim/application/MATSimApplication.java index 7d63518e323..2425a0f1491 100644 --- a/contribs/application/src/main/java/org/matsim/application/MATSimApplication.java +++ b/contribs/application/src/main/java/org/matsim/application/MATSimApplication.java @@ -153,7 +153,14 @@ public Integer call() throws Exception { // load config if not present yet. if (config == null) { - config = loadConfig(Objects.requireNonNull( configPath, "No default scenario location given" ).getAbsoluteFile().toString() ); + String path = Objects.requireNonNull( configPath, "No default scenario location given" ).getAbsoluteFile().toString(); + List customModules = getCustomModules(); + + final Config config1 = ConfigUtils.loadConfig(path, customModules.toArray(new ConfigGroup[0] ) ); + Config prepared = prepareConfig( config1 ); + + config = prepared != null ? prepared : config1; + // (The above lines of code come from inlining so maybe it happened there: I cannot see how prepared could be null but config1 not except if user code returns null which I would consider a bug. kai, aug'24) } else { Config tmp = prepareConfig(config); config = tmp != null ? tmp : config; @@ -306,15 +313,6 @@ protected final void addRunOption(Config config, String option) { addRunOption(config, option, ""); } - private Config loadConfig(String path) { - List customModules = getCustomModules(); - - final Config config = ConfigUtils.loadConfig(path, customModules.toArray(new ConfigGroup[0])); - Config prepared = prepareConfig(config); - - return prepared != null ? prepared : config; - } - @Override public String defaultValue(CommandLine.Model.ArgSpec argSpec) throws Exception { Object obj = argSpec.userObject(); @@ -374,8 +372,39 @@ public static void run(Class clazz, String... args) } /** - * Convenience method to run a scenario from code or automatically with gui when desktop application is detected. - * This method may also be used to predefine some default arguments. + *

Convenience method to run a scenario from code or automatically with gui when desktop application is detected. + * This method may also be used to predefine some default arguments.

+ * + *

With respect to args it looks like arguments are treated in the following sequence (programmed in the run method): + *

    + *
  • ConfigUtils.loadConfig without args
  • + *
  • prepareConfig which is usually overwritten
  • + *
  • config options from some yaml file which can be provided as a command line option
  • + *
  • config options on command line
  • + *

+ * + *

defaultArgs could be used to provide defaults when calling this method here; they would go in addition to what is coming in from "upstream" which is typically the command line.

+ * + *

There are many execution paths that can be reached from this class, but a typical one for matsim-scenarios seems to be:

    + *
  • This method runs MATSimApplication.run( TheScenarioClass.class , args ).
  • + *
  • That run class will instantiate an instance of TheScenarioClass (*), then do some args consistenty checking, then call the piccoli execute method.
  • + *
  • The piccoli execute method will essentially call the "call" method of MATSimApplication.
  • + *
  • I think that in the described execution path, this.config in that call method will initially be null. (The ctor of MATSimApplication was called via reflection at (*); I think that it was called there without a config argument.)
  • + *
  • This call method then will do:
      + *
    • getCustomModules() (which is empty by default but can be overriden)
    • + *
    • ConfigUtils.loadConfig(...) _without_ passing on the args
    • + *
    • prepareConfig(...) (which is empty by default but is typically overridden, in this case in OpenBerlinScenario). In our case, this sets the typical scoring params and the typical replanning strategies. + *
    • next one can override the config from some yaml file provided as a commandline option + *
    • next args is parsed and set + *
    • then some standard CL options are detected and set + *
    • then createScenario(config) is called (which can be overwritten but is not) + *
    • then prepareScenario(scenario) is called (which can be overwritten but is not) + *
    • then a standard controler is created from scenario + *
    • then prepareControler is called which can be overwritten + *
    + *
+ *

+ * * @param clazz class of the scenario to run * @param args pass arguments from the main method * @param defaultArgs predefined default arguments that will always be present @@ -384,6 +413,8 @@ public static void runWithDefaults(Class clazz, Str if (ApplicationUtils.isRunFromDesktop() && args.length == 0) { + System.setProperty("MATSIM_GUI_DESKTOP", "true"); + if (defaultArgs.length > 0) { String value = String.join(ARGS_DELIMITER, defaultArgs); System.setProperty("MATSIM_GUI_ARGS", value); diff --git a/contribs/application/src/main/java/org/matsim/application/ShowGUI.java b/contribs/application/src/main/java/org/matsim/application/ShowGUI.java index e394bfd7b79..6400262eb95 100644 --- a/contribs/application/src/main/java/org/matsim/application/ShowGUI.java +++ b/contribs/application/src/main/java/org/matsim/application/ShowGUI.java @@ -40,6 +40,13 @@ public Integer call() throws Exception { Gui gui = f.get(); + // Set the current working directory to be used in the gui, when run from the command line + // If the gui is run from desktop, the working directory is not overwritten + + // Assumption is that starting something from command line, the user expects that the working directory remains the same + if (!System.getProperty("MATSIM_GUI_DESKTOP", "false").equals("true")) + gui.setWorkingDirectory(new File("")); + while (gui.isShowing()) Thread.sleep(250); diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/noise/MergeNoiseOutput.java b/contribs/application/src/main/java/org/matsim/application/analysis/noise/MergeNoiseOutput.java index aef1ec23d05..b5b85336c1c 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/noise/MergeNoiseOutput.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/noise/MergeNoiseOutput.java @@ -13,11 +13,14 @@ import org.apache.avro.file.DataFileWriter; import org.apache.avro.io.DatumWriter; import org.apache.avro.specific.SpecificDatumWriter; +import org.apache.commons.lang.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Coord; import org.matsim.application.avro.XYTData; +import org.matsim.core.config.Config; import org.matsim.core.utils.io.IOUtils; +import org.matsim.core.utils.misc.Time; import tech.tablesaw.api.*; import tech.tablesaw.io.csv.CsvReadOptions; @@ -29,7 +32,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.*; -import java.util.stream.Collectors; + +import static org.geotools.gml3.v3_2.GML.coordinateSystem; /** * Merges noise data from multiple files into one file. @@ -44,17 +48,16 @@ final class MergeNoiseOutput { */ private static final boolean CREATE_CSV_FILES = false; - private final String[] inputPath; private final Path outputDirectory; private final String crs; - private final String[] labels = {"immission", "emission"}; private final int minTime = 3600; private int maxTime = 24 * 3600; - MergeNoiseOutput(String[] inputPath, Path outputDirectory, String crs) { - this.inputPath = inputPath; - this.outputDirectory = outputDirectory; - this.crs = crs; + private final Map totalReceiverPointValues = new HashMap<>(); + + MergeNoiseOutput(Path path, String coordinateSystem ) { + this.outputDirectory = path; + this.crs = coordinateSystem; } /** @@ -90,25 +93,9 @@ public void setMaxTime(int maxTime) { * Merges noise data from multiple files into one file. */ public void run() { - - // Loop over all paths - for (int i = 0; i < labels.length; i++) { - - // Select the correct method based on the label - switch (labels[i]) { - case "immission" -> { - if (CREATE_CSV_FILES) { - mergeImmissionsCSV(inputPath[i], labels[i]); - } else { - mergeImissions(inputPath[i], labels[i]); - } - - } - case "emission" -> mergeEmissions(inputPath[i], labels[i]); - default -> log.warn("Unknown path: " + inputPath[i]); - } - - } + mergeReceiverPointData(outputDirectory + "/immissions/", "immission"); + mergeReceiverPointData(outputDirectory + "/damages_receiverPoint/", "damages_receiverPoint"); + mergeLinkData(outputDirectory.toString() + "/emissions/", "emission"); } /** @@ -118,6 +105,7 @@ public void run() { * @param output */ private void writeAvro(XYTData xytData, File output) { + log.info(String.format("Start writing avro file to %s", output.toString() )); DatumWriter datumWriter = new SpecificDatumWriter<>(XYTData.class); try (DataFileWriter dataFileWriter = new DataFileWriter<>(datumWriter)) { dataFileWriter.setCodec(CodecFactory.deflateCodec(9)); @@ -128,7 +116,7 @@ private void writeAvro(XYTData xytData, File output) { } } - private void mergeEmissions(String pathParameter, String label) { + private void mergeLinkData(String pathParameter, String label) { log.info("Merging emissions data for label {}", label); Object2DoubleMap mergedData = new Object2DoubleOpenHashMap<>(); Table csvOutputMerged = Table.create(TextColumn.create("Link Id"), DoubleColumn.create("value")); @@ -143,9 +131,8 @@ private void mergeEmissions(String pathParameter, String label) { .separator(';').build()); for (Row row : table) { - // index for Noise Emission xx:xx:xx -> 7 String linkId = row.getString("Link Id"); - double value = row.getDouble(7); + double value = row.getDouble(row.columnCount() - 1); mergedData.mergeDouble(linkId, value, Double::max); } @@ -165,38 +152,49 @@ private void mergeEmissions(String pathParameter, String label) { } /** - * Merges the immissions data + * Merges receiverPoint data (written by {@link org.matsim.contrib.noise.NoiseWriter} * - * @param pathParameter path to the immissions data - * @param label label for the immissions data + * @param outputDir path to the receiverPoint data + * @param label label for the receiverPoint data (which kind of data) */ - private void mergeImissions(String pathParameter, String label) { + private void mergeReceiverPointData(String outputDir, String label) { // data per time step, maps coord to value Int2ObjectMap> data = new Int2ObjectOpenHashMap<>(); // Loop over all files + //TODO could be adjusted to time bin size from noise config group + String substrToCapitalize = null; for (int time = minTime; time <= maxTime; time += 3600) { - String path = pathParameter + label + "_" + round(time, 1) + ".csv"; + String timeDataFile = outputDir + label + "_" + round(time, 1) + ".csv"; + Object2FloatOpenHashMap values = new Object2FloatOpenHashMap<>(); - if (!Files.exists(Path.of(path))) { - log.warn("File {} does not exist", path); + if (!Files.exists(Path.of(timeDataFile))) { + log.warn("File {} does not exist", timeDataFile); continue; } - // Read the file - Table table = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(path)) - .columnTypesPartial(Map.of("x", ColumnType.FLOAT, "y", ColumnType.FLOAT, "Receiver Point Id", ColumnType.INTEGER, "t", ColumnType.DOUBLE)) + //we need "damages_receiverPoint" -> "Damages 01:00:00" and "immission" -> "Immision 01:00:00" + substrToCapitalize = label.contains("_") ? label.substring(0, label.lastIndexOf("_")) : label; + String valueHeader = StringUtils.capitalize(substrToCapitalize) + " " + Time.writeTime(time, Time.TIMEFORMAT_HHMMSS); + + // Read the data file + Table dataTable = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(timeDataFile)) + .columnTypesPartial(Map.of("x", ColumnType.FLOAT, + "y", ColumnType.FLOAT, + "Receiver Point Id", ColumnType.INTEGER, + "t", ColumnType.DOUBLE, + valueHeader, ColumnType.DOUBLE)) .sample(false) .separator(';').build()); - // Loop over all rows in the file - for (Row row : table) { + // Loop over all rows in the data file + for (Row row : dataTable) { float x = row.getFloat("x"); float y = row.getFloat("y"); - float value = (float) row.getDouble(1); // 1 + float value = (float) row.getDouble(valueHeader); FloatFloatPair coord = FloatFloatPair.of(x, y); values.put(coord, value); } @@ -232,7 +230,7 @@ private void mergeImissions(String pathParameter, String label) { } } - xytHourData.setData(Map.of("imissions", raw)); + xytHourData.setData(Map.of(label, raw)); xytHourData.setCrs(crs); File out = outputDirectory.getParent().resolve(label + "_per_hour.avro").toFile(); @@ -254,15 +252,18 @@ private void mergeImissions(String pathParameter, String label) { xytDayData.setTimestamps(List.of(0)); xytDayData.setXCoords(xCoords); xytDayData.setYCoords(yCoords); - xytDayData.setData(Map.of("imissions", raw)); + xytDayData.setData(Map.of(label, raw)); xytDayData.setCrs(crs); File outDay = outputDirectory.getParent().resolve(label + "_per_day.avro").toFile(); writeAvro(xytDayData, outDay); + //cache the overall sum + this.totalReceiverPointValues.put(substrToCapitalize, raw.stream().reduce(0f, Float::sum)); } // Merges the immissions data + @Deprecated private void mergeImmissionsCSV(String pathParameter, String label) { log.info("Merging immissions data for label {}", label); @@ -278,7 +279,10 @@ private void mergeImmissionsCSV(String pathParameter, String label) { // Read the file Table table = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(path)) - .columnTypesPartial(Map.of("x", ColumnType.DOUBLE, "y", ColumnType.DOUBLE, "Receiver Point Id", ColumnType.INTEGER, "t", ColumnType.DOUBLE)) + .columnTypesPartial(Map.of("x", ColumnType.DOUBLE, + "y", ColumnType.DOUBLE, + "Receiver Point Id", ColumnType.INTEGER, + "t", ColumnType.DOUBLE)) .sample(false) .separator(';').build()); @@ -319,4 +323,7 @@ private void mergeImmissionsCSV(String pathParameter, String label) { log.info("Merged noise data written to {} ", outPerDay); } + public Map getTotalReceiverPointValues() { + return totalReceiverPointValues; + } } diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java index c5927fcdb04..1892de7fb74 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java @@ -1,5 +1,9 @@ package org.matsim.application.analysis.noise; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.locationtech.jts.geom.Envelope; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Scenario; @@ -8,6 +12,7 @@ import org.matsim.application.MATSimAppCommand; import org.matsim.application.options.InputOptions; import org.matsim.application.options.OutputOptions; +import org.matsim.application.options.SampleOptions; import org.matsim.application.options.ShpOptions; import org.matsim.contrib.noise.NoiseConfigGroup; import org.matsim.contrib.noise.NoiseOfflineCalculation; @@ -16,9 +21,15 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.geometry.CoordinateTransformation; +import org.matsim.core.utils.io.IOUtils; import picocli.CommandLine; +import java.io.IOException; import java.nio.file.Path; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.util.Locale; +import java.util.Map; import java.util.Objects; import java.util.Set; @@ -33,11 +44,16 @@ produces = { "emission_per_day.csv", "immission_per_day.%s", - "immission_per_hour.%s" + "immission_per_hour.%s", + "damages_receiverPoint_per_hour.%s", + "damages_receiverPoint_per_day.%s", + "noise_stats.csv" } ) public class NoiseAnalysis implements MATSimAppCommand { + private static final Logger log = LogManager.getLogger(NoiseAnalysis.class); + @CommandLine.Mixin private final InputOptions input = InputOptions.ofCommand(NoiseAnalysis.class); @CommandLine.Mixin @@ -46,7 +62,11 @@ public class NoiseAnalysis implements MATSimAppCommand { @CommandLine.Mixin private final ShpOptions shp = new ShpOptions(); - @CommandLine.Option(names = "--consider-activities", split = ",", description = "Considered activities for noise calculation", defaultValue = "h,w,home,work") + @CommandLine.Mixin + private final SampleOptions sampleOptions = new SampleOptions(); + + @CommandLine.Option(names = "--consider-activities", split = ",", description = "Considered activities for noise calculation." + + " Use asterisk ('*') for acttype prefixes, if all such acts shall be considered.", defaultValue = "home*,work*,educ*,leisure*") private Set considerActivities; @CommandLine.Option(names = "--noise-barrier", description = "Path to the noise barrier File", defaultValue = "") @@ -62,36 +82,72 @@ public Integer call() throws Exception { config.controller().setOutputDirectory(input.getRunDirectory().toString()); - // adjust the default noise parameters + //trying to set noise parameters more explicitly, here... + //if NoiseConfigGroup was added before. do not override (most) parameters + boolean overrideParameters = ! ConfigUtils.hasModule(config, NoiseConfigGroup.class); NoiseConfigGroup noiseParameters = ConfigUtils.addOrGetModule(config, NoiseConfigGroup.class); - noiseParameters.setConsideredActivitiesForReceiverPointGridArray(considerActivities.toArray(String[]::new)); - noiseParameters.setConsideredActivitiesForDamageCalculationArray(considerActivities.toArray(String[]::new)); - if (shp.getShapeFile() != null) { - CoordinateTransformation ct = shp.createInverseTransformation(config.global().getCoordinateSystem()); - Envelope bbox = shp.getGeometry().getEnvelopeInternal(); + if(overrideParameters){ + log.warn("no NoiseConfigGroup was configured before. Will set some standards. You should check the next lines in the log file!"); + noiseParameters.setConsideredActivitiesForReceiverPointGridArray(considerActivities.toArray(String[]::new)); + noiseParameters.setConsideredActivitiesForDamageCalculationArray(considerActivities.toArray(String[]::new)); - Coord minCoord = ct.transform(new Coord(bbox.getMinX(), bbox.getMinY())); - Coord maxCoord = ct.transform(new Coord(bbox.getMaxX(), bbox.getMaxY())); + //use actual speed and not freespeed + noiseParameters.setUseActualSpeedLevel(true); + //use the valid speed range (recommended by IK) + noiseParameters.setAllowForSpeedsOutsideTheValidRange(false); - noiseParameters.setReceiverPointsGridMinX(minCoord.getX()); - noiseParameters.setReceiverPointsGridMinY(minCoord.getY()); - noiseParameters.setReceiverPointsGridMaxX(maxCoord.getX()); - noiseParameters.setReceiverPointsGridMaxY(maxCoord.getY()); - } + if (shp.getShapeFile() != null) { + CoordinateTransformation ct = shp.createInverseTransformation(config.global().getCoordinateSystem()); + + Envelope bbox = shp.getGeometry().getEnvelopeInternal(); + + Coord minCoord = ct.transform(new Coord(bbox.getMinX(), bbox.getMinY())); + Coord maxCoord = ct.transform(new Coord(bbox.getMaxX(), bbox.getMaxY())); - noiseParameters.setNoiseComputationMethod(NoiseConfigGroup.NoiseComputationMethod.RLS19); + noiseParameters.setReceiverPointsGridMinX(minCoord.getX()); + noiseParameters.setReceiverPointsGridMinY(minCoord.getY()); + noiseParameters.setReceiverPointsGridMaxX(maxCoord.getX()); + noiseParameters.setReceiverPointsGridMaxY(maxCoord.getY()); + } - if (!Objects.equals(noiseBarrierFile, "")) { - noiseParameters.setNoiseBarriersSourceCRS(config.global().getCoordinateSystem()); - noiseParameters.setConsiderNoiseBarriers(true); - noiseParameters.setNoiseBarriersFilePath(noiseBarrierFile); + noiseParameters.setNoiseComputationMethod(NoiseConfigGroup.NoiseComputationMethod.RLS19); + + if (!Objects.equals(noiseBarrierFile, "")) { + noiseParameters.setNoiseBarriersSourceCRS(config.global().getCoordinateSystem()); + noiseParameters.setConsiderNoiseBarriers(true); + noiseParameters.setNoiseBarriersFilePath(noiseBarrierFile); + } + } else { + log.warn("will override a few settings in NoiseConfigGroup, as we are now doing postprocessing and do not want any internalization etc." + + " You should check the next lines in the log file!"); + } + + // we only mean to do postprocessing here, thus no internalization etc + noiseParameters.setInternalizeNoiseDamages(false); + noiseParameters.setComputeCausingAgents(false); + //we don't need events (for Dashboard) - spare disk space. + noiseParameters.setThrowNoiseEventsAffected(false); + noiseParameters.setThrowNoiseEventsCaused(false); + noiseParameters.setComputeNoiseDamages(true); + + if(! sampleOptions.isSet() && noiseParameters.getScaleFactor() == 1d){ + log.warn("You didn't provide the simulation sample size via command line option --sample-size! This means, noise damages are not scaled!!!"); + } else if (noiseParameters.getScaleFactor() == 1d){ + if (sampleOptions.getSample() == 1d){ + log.warn("Be aware that the noise output is not scaled. This might be unintended. If so, assure to provide the sample size via command line option --sample-size, in the SimWrapperConfigGroup," + + "or provide the scaleFactor (the inverse of the sample size) in the NoiseConfigGroup!!!"); + } + noiseParameters.setScaleFactor(sampleOptions.getUpscaleFactor()); } Scenario scenario = ScenarioUtils.loadScenario(config); String outputFilePath = output.getPath().getParent() == null ? "." : output.getPath().getParent().toString(); + log.info("starting " + NoiseOfflineCalculation.class + " with the following parameters:\n" + + noiseParameters); + NoiseOfflineCalculation noiseCalculation = new NoiseOfflineCalculation(scenario, outputFilePath); outputFilePath += "/noise-analysis"; noiseCalculation.run(); @@ -99,16 +155,25 @@ public Integer call() throws Exception { ProcessNoiseImmissions process = new ProcessNoiseImmissions(outputFilePath + "/immissions/", outputFilePath + "/receiverPoints/receiverPoints.csv", noiseParameters.getReceiverPointGap()); process.run(); - final String[] paths = {outputFilePath + "/immissions/", outputFilePath + "/emissions/"}; - MergeNoiseOutput mergeNoiseOutput = new MergeNoiseOutput(paths, Path.of(outputFilePath), config.global().getCoordinateSystem()); + MergeNoiseOutput mergeNoiseOutput = new MergeNoiseOutput(Path.of(outputFilePath), config.global().getCoordinateSystem()); mergeNoiseOutput.run(); + // Total stats + DecimalFormat df = new DecimalFormat("#.###", DecimalFormatSymbols.getInstance(Locale.US)); + try (CSVPrinter printer = new CSVPrinter(IOUtils.getBufferedWriter(output.getPath("noise_stats.csv").toString()), CSVFormat.DEFAULT)) { + printer.printRecord("Annual cost rate per pop. unit [€]:", df.format(noiseParameters.getAnnualCostRate())); + for (Map.Entry labelValueEntry : mergeNoiseOutput.getTotalReceiverPointValues().entrySet()) { + printer.printRecord("Total " + labelValueEntry.getKey() + " at receiver points", df.format(labelValueEntry.getValue())); + } + } catch (IOException ex) { + log.error(ex); + } return 0; } private Config prepareConfig() { - Config config = ConfigUtils.loadConfig(ApplicationUtils.matchInput("config.xml", input.getRunDirectory()).toAbsolutePath().toString(), new NoiseConfigGroup()); + Config config = ConfigUtils.loadConfig(ApplicationUtils.matchInput("config.xml", input.getRunDirectory()).toAbsolutePath().toString()); //it is important to match "output_vehicles.xml.gz" specifically, because otherwise dvrpVehicle files might be matched and the code crashes later config.vehicles().setVehiclesFile(ApplicationUtils.matchInput("output_vehicles.xml.gz", input.getRunDirectory()).toAbsolutePath().toString()); @@ -119,6 +184,7 @@ private Config prepareConfig() { config.facilities().setInputFile(null); config.eventsManager().setNumberOfThreads(null); config.eventsManager().setEstimatedNumberOfEvents(null); + //ts, aug '24: not sure if and why we need to set 1 thread config.global().setNumberOfThreads(1); return config; diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/population/ActivityLengthAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/population/ActivityLengthAnalysis.java new file mode 100644 index 00000000000..2e7418462fe --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/analysis/population/ActivityLengthAnalysis.java @@ -0,0 +1,82 @@ +package org.matsim.application.analysis.population; + +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.matsim.api.core.v01.population.Activity; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.PlanElement; +import org.matsim.api.core.v01.population.Population; +import org.matsim.application.MATSimAppCommand; +import org.matsim.core.population.PopulationUtils; +import picocli.CommandLine; + +import java.io.FileWriter; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +@CommandLine.Command( + name = "activity-length-analysis", + description = "Analyze the length of activity" +) +public class ActivityLengthAnalysis implements MATSimAppCommand { + @CommandLine.Option(names = "--population", description = "Path to input population", required = true) + private String populationPath; + + @CommandLine.Option(names = "--reference-population", description = "Path to reference population", defaultValue = "") + private String referencePopulationPath; + + @CommandLine.Option(names = "--output-folder", description = "Path to analysis output folder", required = true) + private Path outputFolder; + + public static void main(String[] args) { + new ActivityLengthAnalysis().execute(args); + } + + @Override + public Integer call() throws Exception { + List activityDurations = new ArrayList<>(); + List referenceActivityDurations = new ArrayList<>(); + + Population population = PopulationUtils.readPopulation(populationPath); + for (Person person : population.getPersons().values()) { + for (PlanElement planElement : person.getSelectedPlan().getPlanElements()) { + if (planElement instanceof Activity) { + double startTime = ((Activity) planElement).getStartTime().orElse(0); + double endTime = ((Activity) planElement).getEndTime().orElse(30 * 3600); + double duration = endTime - startTime; + activityDurations.add(duration); + } + } + } + + CSVPrinter csvWriter = new CSVPrinter(new FileWriter(outputFolder + "/activity-length.csv"), CSVFormat.TDF); + csvWriter.printRecord("activity_duration_in_seconds"); + for (double activityDuration : activityDurations) { + csvWriter.printRecord(Double.toString(activityDuration)); + } + csvWriter.close(); + + if (!referencePopulationPath.equals("")) { + Population referencePopulation = PopulationUtils.readPopulation(referencePopulationPath); + for (Person person : referencePopulation.getPersons().values()) { + for (PlanElement planElement : person.getSelectedPlan().getPlanElements()) { + if (planElement instanceof Activity) { + double startTime = ((Activity) planElement).getStartTime().orElse(0); + double endTime = ((Activity) planElement).getEndTime().orElse(30 * 3600); + double duration = endTime - startTime; + referenceActivityDurations.add(duration); + } + } + } + + CSVPrinter csvWriter2 = new CSVPrinter(new FileWriter(outputFolder + "/reference-activity-length.csv"), CSVFormat.TDF); + csvWriter2.printRecord("activity_duration_in_seconds"); + for (double activityDuration : referenceActivityDurations) { + csvWriter2.printRecord(Double.toString(activityDuration)); + } + csvWriter2.close(); + } + return 0; + } +} diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/population/DepartureTimeAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/population/DepartureTimeAnalysis.java new file mode 100644 index 00000000000..04e800872b9 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/analysis/population/DepartureTimeAnalysis.java @@ -0,0 +1,133 @@ +package org.matsim.application.analysis.population; + +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.lang3.mutable.MutableInt; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.Plan; +import org.matsim.api.core.v01.population.Population; +import org.matsim.application.MATSimAppCommand; +import org.matsim.core.population.PersonUtils; +import org.matsim.core.population.PopulationUtils; +import org.matsim.core.router.TripStructureUtils; +import picocli.CommandLine; + +import java.io.FileWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +@CommandLine.Command( + name = "analyze-departure-time", + description = "Analyze the departure time of the trips" +) +public class DepartureTimeAnalysis implements MATSimAppCommand { + + private static final Logger log = LogManager.getLogger(DepartureTimeAnalysis.class); + + @CommandLine.Option(names = "--plans", description = "Path to input population (plans) file", required = true) + private Path inputPlans; + + @CommandLine.Option(names = "--output-folder", description = "Path to analysis output folder", required = true) + private Path outputFolder; + + private static String[] ageGroups = new String[]{"0-17", "18-29", "30-49", "50-69", "70 or more"}; + + + public static void main(String[] args) { + new DepartureTimeAnalysis().execute(args); + } + + @Override + public Integer call() throws Exception { + Map> recordMap = initializeRecordMap(); + Population population = PopulationUtils.readPopulation(inputPlans.toString()); + + int processedPerson = 0; + int tripsDepartAfter24h = 0; + + for (Person person : population.getPersons().values()) { + //TODO potentially filter persons, e.g. by home location or by subpopulation + + processedPerson++; + int age = PersonUtils.getAge(person); + String ageGroup = determineAgeGroup(age); + Plan plan = person.getSelectedPlan(); + List trips = TripStructureUtils.getTrips(plan); + for (TripStructureUtils.Trip trip : trips) { + double departureTime = trip.getOriginActivity().getEndTime().seconds(); + // maybe the Math.floor operation is not needed? + int timeBin = (int) Math.floor(departureTime / 3600); + if (timeBin >= 24) { + tripsDepartAfter24h++; + continue; + } + // 1 time bin = 1 hour + recordMap.get(ageGroup).get(timeBin).increment(); + } + } + + // write results + if (!Files.exists(outputFolder)) { + Files.createDirectory(outputFolder); + } + CSVPrinter tsvWriter = new CSVPrinter(new FileWriter(outputFolder + "/departure_time_analysis.csv"), CSVFormat.TDF); + List titleRow = new ArrayList<>(); + titleRow.add("age_group"); + for (int i = 0; i < 24; i++) { + titleRow.add(Integer.toString(i)); + } + tsvWriter.printRecord(titleRow); + for (String ageGroup : ageGroups) { + List outputRow = new ArrayList<>(); + outputRow.add(ageGroup); + for (int i = 0; i < 24; i++) { + outputRow.add(Integer.toString(recordMap.get(ageGroup).get(i).intValue())); + } + tsvWriter.printRecord(outputRow); + } + tsvWriter.close(); + + log.info("Person processed (living within the area): {}", processedPerson); + log.info("Number of trips that depart after 24 hours is {}", tripsDepartAfter24h); + + return 0; + } + + private Map> initializeRecordMap() { + Map> recordMap = new HashMap<>(); + for (String ageGroup : ageGroups) { + recordMap.put(ageGroup, new HashMap<>()); + for (int i = 0; i < 24; i++) { + recordMap.get(ageGroup).put(i, new MutableInt(0)); + } + } + return recordMap; + } + + private String determineAgeGroup(int age) { + if (age <= 17) { + return ageGroups[0]; + } + + if (age <= 29) { + return ageGroups[1]; + } + + if (age <= 49) { + return ageGroups[2]; + } + + if (age <= 69) { + return ageGroups[3]; + } + + return ageGroups[4]; + } +} diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/traffic/traveltime/SampleValidationRoutes.java b/contribs/application/src/main/java/org/matsim/application/analysis/traffic/traveltime/SampleValidationRoutes.java index 0e6c0f2af59..aa3a1fc4ba0 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/traffic/traveltime/SampleValidationRoutes.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/traffic/traveltime/SampleValidationRoutes.java @@ -19,10 +19,7 @@ import org.matsim.api.core.v01.network.Node; import org.matsim.application.CommandSpec; import org.matsim.application.MATSimAppCommand; -import org.matsim.application.options.CrsOptions; -import org.matsim.application.options.InputOptions; -import org.matsim.application.options.OutputOptions; -import org.matsim.application.options.ShpOptions; +import org.matsim.application.options.*; import org.matsim.application.prepare.network.SampleNetwork; import org.matsim.core.network.NetworkUtils; import org.matsim.core.router.costcalculators.OnlyTimeDependentTravelDisutility; @@ -32,9 +29,11 @@ import org.matsim.core.trafficmonitoring.FreeSpeedTravelTime; import org.matsim.core.utils.geometry.CoordUtils; import org.matsim.core.utils.geometry.transformations.GeotoolsTransformation; +import org.matsim.core.utils.io.IOUtils; import picocli.CommandLine; import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; @@ -86,6 +85,8 @@ public class SampleValidationRoutes implements MATSimAppCommand { @CommandLine.Option(names = "--mode", description = "Mode to validate", defaultValue = TransportMode.car) private String mode; + @CommandLine.Option(names = "--input-od", description = "Use input fromNode,toNode instead of sampling", required = false) + private String inputOD; public static void main(String[] args) { new SampleValidationRoutes().execute(args); @@ -142,9 +143,15 @@ public Integer call() throws Exception { OnlyTimeDependentTravelDisutility util = new OnlyTimeDependentTravelDisutility(tt); LeastCostPathCalculator router = new SpeedyALTFactory().createPathCalculator(network, util, tt); - List routes = sampleRoutes(network, router, rnd); - log.info("Sampled {} routes in range {}", routes.size(), distRange); + List routes; + if (inputOD != null) { + log.info("Using input OD file {}", inputOD); + routes = queryRoutes(network, router); + } else { + routes = sampleRoutes(network, router, rnd); + log.info("Sampled {} routes in range {}", routes.size(), distRange); + } try (CSVPrinter csv = new CSVPrinter(Files.newBufferedWriter(output.getPath()), CSVFormat.DEFAULT)) { csv.printRecord("from_node", "to_node", "beeline_dist", "dist", "travel_time", "geometry"); @@ -228,6 +235,7 @@ private List sampleRoutes(Network network, LeastCostPathCalculator router ShpOptions.Index index = shp.isDefined() ? shp.createIndex(crs, "_") : null; Predicate exclude = excludeRoads != null && !excludeRoads.isBlank() ? new Predicate<>() { final Pattern p = Pattern.compile(excludeRoads, Pattern.CASE_INSENSITIVE); + @Override public boolean test(Link link) { return p.matcher(NetworkUtils.getHighwayType(link)).find(); @@ -282,6 +290,59 @@ public boolean test(Link link) { return result; } + /** + * Use given od pairs as input for validation. + */ + private List queryRoutes(Network network, LeastCostPathCalculator router) { + + List result = new ArrayList<>(); + String crs = ProjectionUtils.getCRS(network); + + if (this.crs.getInputCRS() != null) + crs = this.crs.getInputCRS(); + + if (crs == null) { + throw new IllegalArgumentException("Input CRS could not be detected. Please specify with --input-crs [EPSG:xxx]"); + } + + GeotoolsTransformation ct = new GeotoolsTransformation(crs, "EPSG:4326"); + + try (CSVParser parser = CSVParser.parse(IOUtils.getBufferedReader(inputOD), CSVFormat.DEFAULT.builder().setHeader().setSkipHeaderRecord(true). + setDelimiter(CsvOptions.detectDelimiter(inputOD)).build())) { + + List header = parser.getHeaderNames(); + if (!header.contains("from_node")) + throw new IllegalArgumentException("Missing 'from_node' column in input file"); + if (!header.contains("to_node")) + throw new IllegalArgumentException("Missing 'to_node' column in input file"); + + for (CSVRecord r : parser) { + Node fromNode = network.getNodes().get(Id.createNodeId(r.get("from_node"))); + Node toNode = network.getNodes().get(Id.createNodeId(r.get("to_node"))); + + if (fromNode == null) + throw new IllegalArgumentException("Node " + r.get("from_node") + " not found"); + if (toNode == null) + throw new IllegalArgumentException("Node " + r.get("to_node") + " not found"); + + LeastCostPathCalculator.Path path = router.calcLeastCostPath(fromNode, toNode, 0, null, null); + result.add(new Route( + fromNode.getId(), + toNode.getId(), + ct.transform(fromNode.getCoord()), + ct.transform(toNode.getCoord()), + path.travelTime, + path.links.stream().mapToDouble(Link::getLength).sum() + )); + } + + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + return result; + } + /** * Key as pair of from and to node. */ diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripExtraction/ExtractRelevantFreightTrips.java b/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripExtraction/ExtractRelevantFreightTrips.java index 12c7c03866e..84fce6b351a 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripExtraction/ExtractRelevantFreightTrips.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripExtraction/ExtractRelevantFreightTrips.java @@ -74,6 +74,9 @@ private enum TripType { @CommandLine.Option(names = "--tripType", description = "Set the tripType: OUTGOING, INCOMING, TRANSIT, INTERNAL, ALL", defaultValue = "ALL") private TripType tripType; + @CommandLine.Option(names = "--LegMode", description = "Set leg mode for long distance freight legs.", defaultValue = "freight") + private String legMode; + private final SplittableRandom rnd = new SplittableRandom(4711); private final List fromCoords = new ArrayList<>(); @@ -161,7 +164,7 @@ public Integer call() throws Exception { boolean destinationIsInside = relevantArea.contains(MGC.coord2Point(sct.transform(endCoord))); Activity act0 = populationFactory.createActivityFromCoord("freight_start", null); - Leg leg = populationFactory.createLeg("freight"); + Leg leg = populationFactory.createLeg(legMode); Activity act1 = populationFactory.createActivityFromCoord("freight_end", null); switch (tripType) { @@ -312,7 +315,7 @@ private void createActivitiesForIncomingTrips(boolean originIsInside, boolean de timeSpent += Math.floor(link.getLength() / link.getFreespeed()) + 1; } if (!isCoordSet) { - Coord originalCoord = route.links.get(0).getCoord(); + Coord originalCoord = route.links.getFirst().getCoord(); act0.setCoord(ct.transform(originalCoord)); act0.setEndTime(departureTime); } diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripGeneration/GenerateFreightPlans.java b/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripGeneration/GenerateFreightPlans.java index 0d4fa163ee1..e79d06632d6 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripGeneration/GenerateFreightPlans.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripGeneration/GenerateFreightPlans.java @@ -35,7 +35,7 @@ public class GenerateFreightPlans implements MATSimAppCommand { defaultValue = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/german-wide-freight/v2/germany-europe-network.xml.gz") private String networkPath; - @CommandLine.Option(names = "--nuts", description = "Path to desired network file", required = true) + @CommandLine.Option(names = "--nuts", description = "Path to NUTS file (available on SVN: )", required = true) // TODO Change this to URL pointing to SVN--> need to update the Location calculator private Path shpPath; @@ -48,8 +48,8 @@ public class GenerateFreightPlans implements MATSimAppCommand { @CommandLine.Option(names = "--working-days", defaultValue = "260", description = "Number of working days in a year") private int workingDays; - @CommandLine.Option(names = "--sample", defaultValue = "1", description = "Scaling factor of the freight traffic (0, 1)") - private double sample; + @CommandLine.Option(names = "--sample", defaultValue = "100", description = "Sample size of the freight plans (0, 100]") + private double pct; @CommandLine.Mixin private LanduseOptions landuse = new LanduseOptions(); @@ -60,7 +60,7 @@ public Integer call() throws Exception { log.info("Network successfully loaded!"); log.info("preparing freight agent generator..."); - FreightAgentGenerator freightAgentGenerator = new FreightAgentGenerator(network, shpPath, landuse, averageTruckLoad, workingDays, sample); + FreightAgentGenerator freightAgentGenerator = new FreightAgentGenerator(network, shpPath, landuse, averageTruckLoad, workingDays, pct / 100); log.info("Freight agent generator successfully created!"); log.info("Reading trip relations..."); @@ -84,7 +84,7 @@ public Integer call() throws Exception { Files.createDirectory(output); } - String outputPlansPath = output.toString() + "/german_freight.25pct.plans.xml.gz"; + String outputPlansPath = output.toString() + "/german_freight." + pct + "pct.plans.xml.gz"; PopulationWriter populationWriter = new PopulationWriter(outputPopulation); populationWriter.write(outputPlansPath); diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleLinkSpeedCalculatorDefaultImpl.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleLinkSpeedCalculatorDefaultImpl.java index f580b7e77f1..f6e5104fa86 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleLinkSpeedCalculatorDefaultImpl.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleLinkSpeedCalculatorDefaultImpl.java @@ -18,7 +18,10 @@ public final class BicycleLinkSpeedCalculatorDefaultImpl implements BicycleLinkS private static final Logger log = LogManager.getLogger(BicycleLinkSpeedCalculatorDefaultImpl.class ); @Inject private BicycleConfigGroup bicycleConfigGroup; @Inject private QSimConfigGroup qSimConfigGroup; - @Inject private BicycleLinkSpeedCalculatorDefaultImpl() { } + @Inject private Config config; + @Inject private BicycleLinkSpeedCalculatorDefaultImpl() { + } + /** * for unit testing */ diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java index 7bf5a766bf4..030a54935f5 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java @@ -22,8 +22,12 @@ import com.google.inject.Singleton; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.checkerframework.checker.units.qual.C; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigGroup; +import org.matsim.core.config.ConfigUtils; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.events.StartupEvent; import org.matsim.core.controler.listener.StartupListener; @@ -34,30 +38,41 @@ * @author smetzler, dziemke */ public final class BicycleModule extends AbstractModule { - private static final Logger LOG = LogManager.getLogger(BicycleModule.class); - @Inject - private BicycleConfigGroup bicycleConfigGroup; + @Inject private BicycleConfigGroup bicycleConfigGroup; + + @Override public void install() { +// BicycleConfigGroup bicycleConfigGroup = ConfigUtils.addOrGetModule( this.getConfig(), BicycleConfigGroup.class ); +// this.bind( BicycleConfigGroup.class ).toInstance( bicycleConfigGroup ); + // the above feels odd. But it seems to work. I actually have no idea where the config groups are bound, neither for the core config + // groups nor for the added config groups. In general, the original idea was that AbstractModule provides the config from + // getConfig(), not from injection. kai, jun'24 + + // It actually does not work in general. The ExplodedConfigModule injects all config groups that are materialized by then. Which + // means that it needs to be materialized "quite early", and in particular before this install method is called. For the time being, + // a run script using the contrib thus needs to materialize the config group. kai, jul'24 + - @Override - public void install() { // The idea here is the following: // * scores are just added as score events. no scoring function is replaced. // * link speeds are computed via a plugin handler to the DefaultLinkSpeedCalculator. If the plugin handler returns a speed, it is // used, otherwise the default speed is used. This has the advantage that multiple plugins can register such special link speed calculators. + // this gives the typical things to the router: addTravelTimeBinding(bicycleConfigGroup.getBicycleMode()).to(BicycleTravelTime.class).in(Singleton.class); addTravelDisutilityFactoryBinding(bicycleConfigGroup.getBicycleMode()).to(BicycleTravelDisutilityFactory.class).in(Singleton.class); + // (the BicycleTravelTime uses the BicycleLinkSpeed Calculator bound below) + // (the BicycleDisutility uses a BicycleTravelDisutility) + // compute and throw the additional score events: this.addEventHandlerBinding().to( BicycleScoreEventsCreator.class ); - // (the motorized interaction is in the BicycleScoreEventsCreator) + // (this uses the AdditionalBicycleLinkScore to compute and throw corresponding scoring events) + // (it also computes and throws the motorized interaction events, if they are switched on) this.bind( AdditionalBicycleLinkScore.class ).to( AdditionalBicycleLinkScoreDefaultImpl.class ); - - bind( BicycleLinkSpeedCalculator.class ).to( BicycleLinkSpeedCalculatorDefaultImpl.class ) ; - // this is still needed because the bicycle travel time calculator for routing needs to use the same bicycle speed as the mobsim. kai, jun'23 + // (this computes the value of the per-link scoring event. yyyy Very unfortunately, it is a re-implementation of the BicycleTravelDisutility (mentioned above).) this.installOverridingQSimModule( new AbstractQSimModule(){ @Override protected void configureQSim(){ @@ -65,6 +80,9 @@ public void install() { } } ); + bind( BicycleLinkSpeedCalculator.class ).to( BicycleLinkSpeedCalculatorDefaultImpl.class ) ; + // (both the router and the mobsim need this) + addControlerListenerBinding().to(ConsistencyCheck.class); } @@ -73,7 +91,6 @@ static class ConsistencyCheck implements StartupListener { @Inject private Scenario scenario; @Override public void notifyStartup(StartupEvent event) { - Id bicycleVehTypeId = Id.create(bicycleConfigGroup.getBicycleMode(), VehicleType.class); if (scenario.getVehicles().getVehicleTypes().get(bicycleVehTypeId) == null) { LOG.warn("There is no vehicle type '" + bicycleConfigGroup.getBicycleMode() + "' specified in the vehicle types. " diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleTravelDisutilityFactory.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleTravelDisutilityFactory.java index 135bc7e011f..ab7ffad85ad 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleTravelDisutilityFactory.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleTravelDisutilityFactory.java @@ -21,6 +21,8 @@ import com.google.inject.Inject; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.router.costcalculators.TravelDisutilityFactory; @@ -35,21 +37,20 @@ */ public final class BicycleTravelDisutilityFactory implements TravelDisutilityFactory { // public-final is ok since ctor is package-private: can only be used through injection - private static final Logger LOG = LogManager.getLogger(BicycleTravelDisutilityFactory.class); - - @Inject BicycleConfigGroup bicycleConfigGroup; - @Inject - ScoringConfigGroup cnScoringGroup; - @Inject - RoutingConfigGroup routingConfigGroup; - + private BicycleConfigGroup bicycleConfigGroup; + @Inject Config config; + @Inject ScoringConfigGroup cnScoringGroup; + @Inject RoutingConfigGroup routingConfigGroup; private static int normalisationWrnCnt = 0; - /* package-private */ BicycleTravelDisutilityFactory(){} + /* package-private */ BicycleTravelDisutilityFactory(){ + } @Override public TravelDisutility createTravelDisutility(TravelTime timeCalculator) { + this.bicycleConfigGroup = ConfigUtils.addOrGetModule( config, BicycleConfigGroup.class ); + double sigma = routingConfigGroup.getRoutingRandomness(); double normalization = 1; diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleUtils.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleUtils.java index 43bf5e63776..3af954d9c70 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleUtils.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleUtils.java @@ -127,4 +127,11 @@ private static boolean hasNoCycleway( String cyclewayType ) { } return userDefinedNetworkAttributeFactor; } + // === + public static void setSmoothness( Link link, String smoothness ){ + link.getAttributes().putAttribute( SMOOTHNESS, smoothness ); + } + public static void setBicycleInfrastructureFactor( Link link, double factor ){ + link.getAttributes().putAttribute( BICYCLE_INFRASTRUCTURE_SPEED_FACTOR, factor ); + } } diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/network/BicycleOsmNetworkReaderV2.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/network/BicycleOsmNetworkReaderV2.java index cd51b40275b..549f4c25656 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/network/BicycleOsmNetworkReaderV2.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/network/BicycleOsmNetworkReaderV2.java @@ -225,7 +225,7 @@ protected void setOrModifyLinkAttributes(Link l, OsmWay way, boolean forwardDire // Smoothness String smoothness = way.tags.get(BicycleUtils.SMOOTHNESS); if (smoothness != null) { - l.getAttributes().putAttribute(BicycleUtils.SMOOTHNESS, smoothness); + BicycleUtils.setSmoothness( l, smoothness ); this.countSmoothness++; } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java index aefdfeb5e6c..32bf96909bf 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java @@ -17,15 +17,12 @@ import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilities; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilityFinder; import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; -import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DefaultAssignShiftToVehicleLogic; -import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DefaultShiftStartLogic; -import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DrtShiftDispatcher; -import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DrtShiftDispatcherImpl; +import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.*; import org.matsim.contrib.drt.extension.operations.shifts.optimizer.ShiftVehicleDataEntryFactory; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftDrtActionCreator; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftDrtTaskFactory; import org.matsim.contrib.drt.extension.operations.shifts.scheduler.ShiftTaskScheduler; -import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShifts; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; import org.matsim.contrib.drt.optimizer.VehicleEntry; import org.matsim.contrib.drt.prebooking.PrebookingActionCreator; import org.matsim.contrib.drt.run.DrtConfigGroup; @@ -67,19 +64,22 @@ protected void configureQSim() { ).asEagerSingleton(); bindModal(DrtShiftDispatcher.class).toProvider(modalProvider( - getter -> new EDrtShiftDispatcherImpl(((EShiftTaskScheduler) getter.getModal(ShiftTaskScheduler.class)), getter.getModal(ChargingInfrastructure.class), - drtShiftParams, getter.getModal(OperationFacilities.class), new DrtShiftDispatcherImpl(getMode(), - getter.getModal(DrtShifts.class), getter.getModal(Fleet.class), - getter.get(MobsimTimer.class), getter.getModal(OperationFacilities.class), getter.getModal(OperationFacilityFinder.class), - getter.getModal(ShiftTaskScheduler.class), getter.getModal(Network.class), getter.get(EventsManager.class), - drtShiftParams, new EDrtShiftStartLogic(new DefaultShiftStartLogic()), - new EDrtAssignShiftToVehicleLogic(new DefaultAssignShiftToVehicleLogic(drtShiftParams), drtShiftParams)), - getter.getModal(Fleet.class)))).asEagerSingleton(); + getter -> new EDrtShiftDispatcherImpl(((EShiftTaskScheduler) getter.getModal(ShiftTaskScheduler.class)), + getter.getModal(ChargingInfrastructure.class), drtShiftParams, getter.getModal(OperationFacilities.class), + new DrtShiftDispatcherImpl(getMode(), getter.getModal(Fleet.class), getter.get(MobsimTimer.class), + getter.getModal(OperationFacilities.class), getter.getModal(OperationFacilityFinder.class), + getter.getModal(ShiftTaskScheduler.class), getter.getModal(Network.class), getter.get(EventsManager.class), + drtShiftParams, new EDrtShiftStartLogic(new DefaultShiftStartLogic()), + new EDrtAssignShiftToVehicleLogic(new DefaultAssignShiftToVehicleLogic(drtShiftParams), drtShiftParams), + getter.getModal(ShiftScheduler.class)), + getter.getModal(Fleet.class))) + ).asEagerSingleton(); bindModal(VehicleEntry.EntryFactory.class).toProvider(modalProvider(getter -> new ShiftVehicleDataEntryFactory(new EDrtVehicleDataEntryFactory(0), drtShiftParams.considerUpcomingShiftsForInsertion))).asEagerSingleton(); + bindModal(DrtTaskFactory.class).toProvider(modalProvider(getter -> new ShiftEDrtTaskFactoryImpl(new EDrtTaskFactoryImpl(), getter.getModal(OperationFacilities.class)))).in(Singleton.class); bindModal(ShiftDrtTaskFactory.class).toProvider(modalProvider(getter -> ((ShiftDrtTaskFactory) getter.getModal(DrtTaskFactory.class)))); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/scheduler/EShiftTaskScheduler.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/scheduler/EShiftTaskScheduler.java index a87c54a1be8..9c5a7172282 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/scheduler/EShiftTaskScheduler.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/scheduler/EShiftTaskScheduler.java @@ -62,17 +62,17 @@ public class EShiftTaskScheduler implements ShiftTaskScheduler { private final Network network; private final ChargingInfrastructure chargingInfrastructure; - public EShiftTaskScheduler(Network network, TravelTime travelTime, TravelDisutility travelDisutility, - MobsimTimer timer, ShiftDrtTaskFactory taskFactory, ShiftsParams shiftsParams, - ChargingInfrastructure chargingInfrastructure, OperationFacilities operationFacilities, Fleet fleet) { - this.travelTime = travelTime; - this.timer = timer; - this.taskFactory = taskFactory; - this.network = network; - this.shiftsParams = shiftsParams; - this.router = new SpeedyALTFactory().createPathCalculator(network, travelDisutility, travelTime); - this.chargingInfrastructure = chargingInfrastructure; - } + public EShiftTaskScheduler(Network network, TravelTime travelTime, TravelDisutility travelDisutility, + MobsimTimer timer, ShiftDrtTaskFactory taskFactory, ShiftsParams shiftsParams, + ChargingInfrastructure chargingInfrastructure, OperationFacilities operationFacilities, Fleet fleet) { + this.travelTime = travelTime; + this.timer = timer; + this.taskFactory = taskFactory; + this.network = network; + this.shiftsParams = shiftsParams; + this.router = new SpeedyALTFactory().createPathCalculator(network, travelDisutility, travelTime); + this.chargingInfrastructure = chargingInfrastructure; + } public void relocateForBreak(ShiftDvrpVehicle vehicle, OperationFacility breakFacility, DrtShift shift) { final Schedule schedule = vehicle.getSchedule(); @@ -81,7 +81,7 @@ public void relocateForBreak(ShiftDvrpVehicle vehicle, OperationFacility breakFa final Link toLink = network.getLinks().get(breakFacility.getLinkId()); if (currentTask instanceof DriveTask && currentTask.getTaskType().equals(EmptyVehicleRelocator.RELOCATE_VEHICLE_TASK_TYPE) - && currentTask.equals(schedule.getTasks().get(schedule.getTaskCount()-2))) { + && currentTask.equals(schedule.getTasks().get(schedule.getTaskCount() - 2))) { //try to divert/cancel relocation LinkTimePair start = ((OnlineDriveTaskTracker) currentTask.getTaskTracker()).getDiversionPoint(); VrpPathWithTravelData path; @@ -112,13 +112,13 @@ public void relocateForBreak(ShiftDvrpVehicle vehicle, OperationFacility breakFa } else { final Task task = schedule.getTasks().get(schedule.getTaskCount() - 1); final Link lastLink = ((StayTask) task).getLink(); - double departureTime = task.getBeginTime(); + double departureTime = task.getBeginTime(); - // @Nico Did I change something here? - if (schedule.getCurrentTask() == task) { - departureTime = Math.max(task.getBeginTime(), timer.getTimeOfDay()); - } - if (lastLink.getId() != breakFacility.getLinkId()) { + // @Nico Did I change something here? + if (schedule.getCurrentTask() == task) { + departureTime = Math.max(task.getBeginTime(), timer.getTimeOfDay()); + } + if (lastLink.getId() != breakFacility.getLinkId()) { VrpPathWithTravelData path = VrpPaths.calcAndCreatePath(lastLink, toLink, departureTime, router, @@ -154,7 +154,7 @@ public void relocateForBreak(ShiftDvrpVehicle vehicle, OperationFacility breakFa double endTime = startTime + shift.getBreak().orElseThrow().getDuration(); double latestDetourArrival = timer.getTimeOfDay(); - relocateForBreakImpl(vehicle, startTime, endTime, latestDetourArrival, toLink, shift, breakFacility); + relocateForBreakImpl(vehicle, startTime, endTime, latestDetourArrival, toLink, shift, breakFacility); } } } @@ -165,24 +165,24 @@ private void relocateForBreakImpl(ShiftDvrpVehicle vehicle, double startTime, do Schedule schedule = vehicle.getSchedule(); // append SHIFT_BREAK task - DrtShiftBreak shiftBreak = shift.getBreak().orElseThrow(); + DrtShiftBreak shiftBreak = shift.getBreak().orElseThrow(); - ShiftBreakTask dropoffStopTask; - ElectricVehicle ev = ((EvDvrpVehicle) vehicle).getElectricVehicle(); - Optional charger = charge(breakFacility, ev); - if (charger.isPresent()) { + ShiftBreakTask dropoffStopTask; + ElectricVehicle ev = ((EvDvrpVehicle) vehicle).getElectricVehicle(); + Optional charger = charge(breakFacility, ev); + if (charger.isPresent()) { final Charger chargerImpl = charger.get(); - final double waitTime = ChargingEstimations - .estimateMaxWaitTimeForNextVehicle(chargerImpl); + final double waitTime = ChargingEstimations + .estimateMaxWaitTimeForNextVehicle(chargerImpl); - if (ev.getBattery().getCharge() / ev.getBattery().getCapacity() > shiftsParams.chargeDuringBreakThreshold || - waitTime > 0) { + if (ev.getBattery().getCharge() / ev.getBattery().getCapacity() > shiftsParams.chargeDuringBreakThreshold || + waitTime > 0) { dropoffStopTask = taskFactory.createShiftBreakTask(vehicle, startTime, endTime, link, shiftBreak, breakFacility); } else { - double energyCharge = ((BatteryCharging) ev.getChargingPower()).calcEnergyCharged(chargerImpl.getSpecification(), endTime - startTime); - double totalEnergy = -energyCharge; + double energyCharge = ((BatteryCharging) ev.getChargingPower()).calcEnergyCharged(chargerImpl.getSpecification(), endTime - startTime); + double totalEnergy = -energyCharge; ((ChargingWithAssignmentLogic) chargerImpl.getLogic()).assignVehicle(ev); dropoffStopTask = ((ShiftEDrtTaskFactoryImpl) taskFactory).createChargingShiftBreakTask(vehicle, startTime, endTime, link, shiftBreak, chargerImpl, totalEnergy, breakFacility); @@ -199,32 +199,32 @@ private void relocateForBreakImpl(ShiftDvrpVehicle vehicle, double startTime, do final double latestTimeConstraintArrival = shiftBreak.getLatestBreakEndTime() - shiftBreak.getDuration(); - shiftBreak.schedule(Math.min(latestDetourArrival, latestTimeConstraintArrival)); + shiftBreak.schedule(Math.min(latestDetourArrival, latestTimeConstraintArrival)); } private Optional charge(OperationFacility breakFacility, ElectricVehicle electricVehicle) { if (chargingInfrastructure != null) { - List> chargerIds = breakFacility.getChargers(); - if(!chargerIds.isEmpty()) { - Optional selectedCharger = chargerIds - .stream() - .map(id -> chargingInfrastructure.getChargers().get(id)) - .filter(charger -> shiftsParams.breakChargerType.equals(charger.getChargerType())) - .min((c1, c2) -> { - final double waitTime = ChargingEstimations - .estimateMaxWaitTimeForNextVehicle(c1); - final double waitTime2 = ChargingEstimations - .estimateMaxWaitTimeForNextVehicle(c2); - return Double.compare(waitTime, waitTime2); - }); - if(selectedCharger.isPresent()) { - if (selectedCharger.get().getLogic().getChargingStrategy().isChargingCompleted(electricVehicle)) { - return Optional.empty(); - } - } - return selectedCharger; - } - } + List> chargerIds = breakFacility.getChargers(); + if (!chargerIds.isEmpty()) { + Optional selectedCharger = chargerIds + .stream() + .map(id -> chargingInfrastructure.getChargers().get(id)) + .filter(charger -> shiftsParams.breakChargerType.equals(charger.getChargerType())) + .min((c1, c2) -> { + final double waitTime = ChargingEstimations + .estimateMaxWaitTimeForNextVehicle(c1); + final double waitTime2 = ChargingEstimations + .estimateMaxWaitTimeForNextVehicle(c2); + return Double.compare(waitTime, waitTime2); + }); + if (selectedCharger.isPresent()) { + if (selectedCharger.get().getLogic().getChargingStrategy().isChargingCompleted(electricVehicle)) { + return Optional.empty(); + } + } + return selectedCharger; + } + } return Optional.empty(); } @@ -234,7 +234,7 @@ public void relocateForShiftChange(DvrpVehicle vehicle, Link link, DrtShift shif final Task currentTask = schedule.getCurrentTask(); if (currentTask instanceof DriveTask && currentTask.getTaskType().equals(EmptyVehicleRelocator.RELOCATE_VEHICLE_TASK_TYPE) - && currentTask.equals(schedule.getTasks().get(schedule.getTaskCount()-2))) { + && currentTask.equals(schedule.getTasks().get(schedule.getTaskCount() - 2))) { //try to divert/cancel relocation LinkTimePair start = ((OnlineDriveTaskTracker) currentTask.getTaskTracker()).getDiversionPoint(); VrpPathWithTravelData path; @@ -317,22 +317,22 @@ private void appendShiftChange(DvrpVehicle vehicle, DrtShift shift, OperationFac // append SHIFT_CHANGEOVER task - ElectricVehicle ev = ((EvDvrpVehicle) vehicle).getElectricVehicle(); - Optional charger = charge(breakFacility, ev); - if (charger.isPresent()) { - Charger chargingImpl = charger.get(); + ElectricVehicle ev = ((EvDvrpVehicle) vehicle).getElectricVehicle(); + Optional charger = charge(breakFacility, ev); + if (charger.isPresent()) { + Charger chargingImpl = charger.get(); - final double waitTime = ChargingEstimations - .estimateMaxWaitTimeForNextVehicle(chargingImpl); + final double waitTime = ChargingEstimations + .estimateMaxWaitTimeForNextVehicle(chargingImpl); - if (ev.getBattery().getCharge() / ev.getBattery().getCapacity() < shiftsParams.chargeDuringBreakThreshold + if (ev.getBattery().getCharge() / ev.getBattery().getCapacity() < shiftsParams.chargeDuringBreakThreshold || ((ChargingWithAssignmentLogic) chargingImpl.getLogic()).getAssignedVehicles().contains(ev) - || waitTime >0) { + || waitTime > 0) { dropoffStopTask = taskFactory.createShiftChangeoverTask(vehicle, startTime, endTime, link, shift, breakFacility); } else { - double energyCharge = ((BatteryCharging) ev.getChargingPower()).calcEnergyCharged(chargingImpl.getSpecification(), endTime - startTime); - double totalEnergy = -energyCharge; + double energyCharge = ((BatteryCharging) ev.getChargingPower()).calcEnergyCharged(chargingImpl.getSpecification(), endTime - startTime); + double totalEnergy = -energyCharge; ((ChargingWithAssignmentLogic) chargingImpl.getLogic()).assignVehicle(ev); dropoffStopTask = ((ShiftEDrtTaskFactoryImpl) taskFactory).createChargingShiftChangeoverTask(vehicle, startTime, endTime, link, chargingImpl, totalEnergy, shift, breakFacility); @@ -353,9 +353,11 @@ public void startShift(ShiftDvrpVehicle vehicle, double now, DrtShift shift) { if (stayTask instanceof WaitForShiftTask) { ((WaitForShiftTask) stayTask).getFacility().deregisterVehicle(vehicle.getId()); stayTask.setEndTime(now); - if(Schedules.getLastTask(schedule).equals(stayTask)) { + if (Schedules.getLastTask(schedule).equals(stayTask)) { //nothing planned yet. schedule.addTask(taskFactory.createStayTask(vehicle, now, shift.getEndTime(), stayTask.getLink())); + } else { + Schedules.getNextTask(schedule).setBeginTime(now); } } else { throw new IllegalStateException("Vehicle cannot start shift during task:" + stayTask.getTaskType().name()); @@ -370,9 +372,9 @@ public boolean updateShiftChange(ShiftDvrpVehicle vehicle, Link link, DrtShift s VrpPathWithTravelData path = VrpPaths.calcAndCreatePath(start.link, link, Math.max(start.time, timer.getTimeOfDay()), router, travelTime); //if (path.getArrivalTime() <= shift.getEndTime()) { - updateShiftChangeImpl(vehicle, path, shift, facility, lastTask); - return true; - // } + updateShiftChangeImpl(vehicle, path, shift, facility, lastTask); + return true; + // } } return false; } @@ -381,29 +383,28 @@ public boolean updateShiftChange(ShiftDvrpVehicle vehicle, Link link, DrtShift s public void planAssignedShift(ShiftDvrpVehicle vehicle, double timeStep, DrtShift shift) { Schedule schedule = vehicle.getSchedule(); StayTask stayTask = (StayTask) schedule.getCurrentTask(); - if (stayTask instanceof WaitForShiftTask waitForShiftTask) { - if(waitForShiftTask instanceof EDrtWaitForShiftTask eDrtWaitForShiftTask) { - if(eDrtWaitForShiftTask.getChargingTask() != null) { - Task nextTask = Schedules.getNextTask(vehicle.getSchedule()); - if(nextTask instanceof WaitForShiftTask) { - // set +1 to ensure this update happens after next shift start check - nextTask.setEndTime(Math.max(timeStep + 1, shift.getStartTime())); - //append stay task if required - if(Schedules.getLastTask(schedule).equals(nextTask)) { - schedule.addTask(taskFactory.createStayTask(vehicle, nextTask.getEndTime(), shift.getEndTime(), ((WaitForShiftTask) nextTask).getLink())); - } - } else { - throw new RuntimeException(); - } - } else { - stayTask.setEndTime(Math.max(timeStep +1 , shift.getStartTime())); + if (stayTask instanceof EDrtWaitForShiftTask eDrtWaitForShiftTask) { + if (eDrtWaitForShiftTask.getChargingTask() != null) { + Task nextTask = Schedules.getNextTask(vehicle.getSchedule()); + if (nextTask instanceof WaitForShiftTask) { + // set +1 to ensure this update happens after next shift start check + nextTask.setEndTime(Math.max(timeStep + 1, shift.getStartTime())); //append stay task if required - if(Schedules.getLastTask(schedule).equals(stayTask)) { - schedule.addTask(taskFactory.createStayTask(vehicle, stayTask.getEndTime(), shift.getEndTime(), stayTask.getLink())); + if (Schedules.getLastTask(schedule).equals(nextTask)) { + schedule.addTask(taskFactory.createStayTask(vehicle, nextTask.getEndTime(), shift.getEndTime(), ((WaitForShiftTask) nextTask).getLink())); } + } else { + throw new RuntimeException(); + } + } else { + stayTask.setEndTime(Math.max(timeStep + 1, shift.getStartTime())); + //append stay task if required + if (Schedules.getLastTask(schedule).equals(stayTask)) { + schedule.addTask(taskFactory.createStayTask(vehicle, stayTask.getEndTime(), shift.getEndTime(), stayTask.getLink())); } } } + } @@ -412,10 +413,10 @@ public void cancelAssignedShift(ShiftDvrpVehicle vehicle, double timeStep, DrtSh Schedule schedule = vehicle.getSchedule(); StayTask stayTask = (StayTask) schedule.getCurrentTask(); if (stayTask instanceof WaitForShiftTask waitForShiftTask) { - if(waitForShiftTask instanceof EDrtWaitForShiftTask eDrtWaitForShiftTask) { - if(eDrtWaitForShiftTask.getChargingTask() != null) { + if (waitForShiftTask instanceof EDrtWaitForShiftTask eDrtWaitForShiftTask) { + if (eDrtWaitForShiftTask.getChargingTask() != null) { Task nextTask = Schedules.getNextTask(vehicle.getSchedule()); - if(nextTask instanceof WaitForShiftTask) { + if (nextTask instanceof WaitForShiftTask) { nextTask.setEndTime(vehicle.getServiceEndTime()); } else { throw new RuntimeException(); @@ -433,15 +434,15 @@ private void updateShiftChangeImpl(DvrpVehicle vehicle, VrpPathWithTravelData vr DrtShift shift, OperationFacility facility, Task lastTask) { Schedule schedule = vehicle.getSchedule(); - Optional oldChangeOver = ShiftSchedules.getNextShiftChangeover(schedule); - if(oldChangeOver.isPresent() && oldChangeOver.get() instanceof EDrtShiftChangeoverTaskImpl) { - if(((EDrtShiftChangeoverTaskImpl) oldChangeOver.get()).getChargingTask() != null) { - ElectricVehicle ev = ((EvDvrpVehicle) vehicle).getElectricVehicle(); - ((EDrtShiftChangeoverTaskImpl) oldChangeOver.get()).getChargingTask().getChargingLogic().unassignVehicle(ev); - } - } + Optional oldChangeOver = ShiftSchedules.getNextShiftChangeover(schedule); + if (oldChangeOver.isPresent() && oldChangeOver.get() instanceof EDrtShiftChangeoverTaskImpl) { + if (((EDrtShiftChangeoverTaskImpl) oldChangeOver.get()).getChargingTask() != null) { + ElectricVehicle ev = ((EvDvrpVehicle) vehicle).getElectricVehicle(); + ((EDrtShiftChangeoverTaskImpl) oldChangeOver.get()).getChargingTask().getChargingLogic().unassignVehicle(ev); + } + } - List copy = new ArrayList<>(schedule.getTasks().subList(lastTask.getTaskIdx() + 1, schedule.getTasks().size())); + List copy = new ArrayList<>(schedule.getTasks().subList(lastTask.getTaskIdx() + 1, schedule.getTasks().size())); for (Task task : copy) { schedule.removeTask(task); } @@ -449,7 +450,7 @@ private void updateShiftChangeImpl(DvrpVehicle vehicle, VrpPathWithTravelData vr ((OnlineDriveTaskTracker) lastTask.getTaskTracker()).divertPath(vrpPath); } else { //add drive to break location - lastTask.setEndTime(vrpPath.getDepartureTime()); + lastTask.setEndTime(vrpPath.getDepartureTime()); schedule.addTask(taskFactory.createDriveTask(vehicle, vrpPath, RELOCATE_VEHICLE_SHIFT_CHANGEOVER_TASK_TYPE)); // add RELOCATE } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/DumpShiftDataAtEndImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/DumpShiftDataAtEndImpl.java index 0960125e49d..ee65d26d4fd 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/DumpShiftDataAtEndImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/DumpShiftDataAtEndImpl.java @@ -2,16 +2,14 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesSpecification; import org.matsim.contrib.drt.extension.operations.shifts.io.DrtShiftsWriter; import org.matsim.contrib.drt.extension.operations.shifts.io.OperationFacilitiesWriter; -import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesSpecification; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.core.controler.events.ShutdownEvent; import org.matsim.core.controler.listener.ShutdownListener; -import jakarta.inject.Provider; - /** * Dumps DRT shift related data at end. Based on {@link org.matsim.core.controler.corelisteners.DumpDataAtEndImpl} * @@ -20,13 +18,13 @@ final public class DumpShiftDataAtEndImpl implements ShutdownListener { private static final Logger log = LogManager.getLogger( DumpShiftDataAtEndImpl.class ); - private final Provider shifts; + private final DrtShiftsSpecification shifts; private final OperationFacilitiesSpecification operationFacilities; private final OutputDirectoryHierarchy controlerIO; - public DumpShiftDataAtEndImpl(Provider shifts, OperationFacilitiesSpecification operationFacilities, OutputDirectoryHierarchy controlerIO) { + public DumpShiftDataAtEndImpl(DrtShiftsSpecification shifts, OperationFacilitiesSpecification operationFacilities, OutputDirectoryHierarchy controlerIO) { this.shifts = shifts; this.operationFacilities = operationFacilities; this.controlerIO = controlerIO; @@ -44,7 +42,7 @@ public void notifyShutdown(ShutdownEvent event) { private void dumpShiftPans() { try { if ( this.shifts!=null){ - new DrtShiftsWriter(shifts.get()).writeFile(this.controlerIO.getOutputFilename("output_shifts.xml.gz")); + new DrtShiftsWriter(shifts).writeFile(this.controlerIO.getOutputFilename("output_shifts.xml.gz")); } } catch ( Exception ee ) { log.error("Exception writing shifts.", ee); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/RegularShiftDump.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/RegularShiftDump.java new file mode 100644 index 00000000000..908f66d0008 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/RegularShiftDump.java @@ -0,0 +1,44 @@ +package org.matsim.contrib.drt.extension.operations.shifts.analysis; + +import com.google.inject.Provider; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.contrib.drt.extension.operations.shifts.io.DrtShiftsWriter; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.controler.events.IterationEndsEvent; +import org.matsim.core.controler.listener.IterationEndsListener; + + +/** + * + * @author nkuehnel / MOIA + */ +final public class RegularShiftDump implements IterationEndsListener { + private static final Logger log = LogManager.getLogger( RegularShiftDump.class ); + + private final Provider shifts; + + private final OutputDirectoryHierarchy controlerIO; + + public RegularShiftDump(Provider shifts, OutputDirectoryHierarchy controlerIO) { + this.shifts = shifts; + this.controlerIO = controlerIO; + } + + private void dumpShiftPans(int iteration) { + try { + if ( this.shifts!=null){ + new DrtShiftsWriter(shifts.get()).writeFile(this.controlerIO.getIterationFilename(iteration, "output_shifts.xml.gz")); + } + } catch ( Exception ee ) { + log.error("Exception writing shifts.", ee); + } + } + + + @Override + public void notifyIterationEnds(IterationEndsEvent event) { + dumpShiftPans(event.getIteration()); + } +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftDurationXY.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftDurationXY.java index 809e4385323..43af5244e69 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftDurationXY.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftDurationXY.java @@ -58,22 +58,28 @@ public void handleEvent(DrtShiftBreakStartedEvent event) { @Override public void handleEvent(final DrtShiftEndedEvent event) { if (event.getMode().equals(mode)) { - final Double start = shift2StartTime.get(event.getShiftId()); - double duration = event.getTime() - start; - final DrtShiftSpecification drtShift = shifts.get().getShiftSpecifications().get(event.getShiftId()); - double plannedDuration = drtShift.getEndTime() - drtShift.getStartTime(); - shift2plannedVsActualDuration.put(event.getShiftId(), new Tuple<>(plannedDuration, duration)); + Map, DrtShiftSpecification> shiftSpecifications = shifts.get().getShiftSpecifications(); + if(shiftSpecifications.containsKey(event.getShiftId())) { + final DrtShiftSpecification drtShift = shiftSpecifications.get(event.getShiftId()); + final Double start = shift2StartTime.get(event.getShiftId()); + double duration = event.getTime() - start; + double plannedDuration = drtShift.getEndTime() - drtShift.getStartTime(); + shift2plannedVsActualDuration.put(event.getShiftId(), new Tuple<>(plannedDuration, duration)); + } } } @Override public void handleEvent(DrtShiftBreakEndedEvent event) { if (event.getMode().equals(mode)) { - final Double start = shift2BreakStartTime.get(event.getShiftId()); - double duration = event.getTime() - start; - final DrtShiftBreakSpecification drtShift = shifts.get().getShiftSpecifications().get(event.getShiftId()).getBreak().orElseThrow(); - double plannedDuration = drtShift.getDuration(); - shift2plannedVsActualBreakDuration.put(event.getShiftId(), new Tuple<>(plannedDuration, duration)); + Map, DrtShiftSpecification> shiftSpecifications = shifts.get().getShiftSpecifications(); + if(shiftSpecifications.containsKey(event.getShiftId())) { + final Double start = shift2BreakStartTime.get(event.getShiftId()); + double duration = event.getTime() - start; + final DrtShiftBreakSpecification drtShift = shifts.get().getShiftSpecifications().get(event.getShiftId()).getBreak().orElseThrow(); + double plannedDuration = drtShift.getDuration(); + shift2plannedVsActualBreakDuration.put(event.getShiftId(), new Tuple<>(plannedDuration, duration)); + } } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftHistogram.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftHistogram.java index 00dc4e85a02..b2539c40ba7 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftHistogram.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftHistogram.java @@ -1,9 +1,6 @@ package org.matsim.contrib.drt.extension.operations.shifts.analysis; -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.population.Population; import org.matsim.contrib.drt.extension.operations.shifts.events.*; -import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShift; import org.matsim.core.config.Config; import org.matsim.core.utils.io.IOUtils; import org.matsim.core.utils.misc.Time; @@ -12,35 +9,30 @@ import java.io.OutputStream; import java.io.PrintStream; import java.io.UncheckedIOException; -import java.util.Set; /** * @author nkuehnel / MOIA */ public class ShiftHistogram implements DrtShiftStartedEventHandler, DrtShiftEndedEventHandler, - DrtShiftBreakStartedEventHandler, DrtShiftBreakEndedEventHandler { + DrtShiftBreakStartedEventHandler, DrtShiftBreakEndedEventHandler { private final String mode; - public static final int DEFAULT_END_TIME = 30 * 3600; - public static final int DEFAULT_BIN_SIZE = 300; + public static final int DEFAULT_END_TIME = 30 * 3600; + public static final int DEFAULT_BIN_SIZE = 300; - private Set> shiftIds; private int iteration = 0; private final int binSize; private final int nofBins; private DataFrame data = null; - public ShiftHistogram(Population population, String mode, Config config) { - super(); + public ShiftHistogram(String mode, Config config) { + super(); this.mode = mode; this.binSize = DEFAULT_BIN_SIZE; - this.nofBins = ((int) config.qsim().getEndTime().orElse(DEFAULT_END_TIME) ) / this.binSize + 1; - reset(0); - if (population == null) { - this.shiftIds = null; - } + this.nofBins = ((int) config.qsim().getEndTime().orElse(DEFAULT_END_TIME)) / this.binSize + 1; + reset(0); } /** @@ -63,10 +55,9 @@ public ShiftHistogram(String mode, final int binSize, final int nofBins) { public void handleEvent(final DrtShiftStartedEvent event) { if (event.getMode().equals(mode)) { int index = getBinIndex(event.getTime()); - if ((this.shiftIds == null || this.shiftIds.contains(event.getShiftId()))) { - DataFrame dataFrame = getData(); - dataFrame.countsStart[index]++; - } + DataFrame dataFrame = getData(); + dataFrame.countsStart[index]++; + } } @@ -74,10 +65,9 @@ public void handleEvent(final DrtShiftStartedEvent event) { public void handleEvent(final DrtShiftEndedEvent event) { if (event.getMode().equals(mode)) { int index = getBinIndex(event.getTime()); - if ((this.shiftIds == null || this.shiftIds.contains(event.getShiftId()))) { - DataFrame dataFrame = getData(); - dataFrame.countsEnd[index]++; - } + DataFrame dataFrame = getData(); + dataFrame.countsEnd[index]++; + } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/config/ShiftsParams.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/config/ShiftsParams.java index e61e5541896..3409d13b051 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/config/ShiftsParams.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/config/ShiftsParams.java @@ -8,8 +8,10 @@ */ package org.matsim.contrib.drt.extension.operations.shifts.config; +import com.google.common.base.Verify; import org.matsim.contrib.common.util.ReflectiveConfigGroupWithConfigurableParameterSets; import org.matsim.contrib.ev.infrastructure.ChargerSpecification; +import org.matsim.core.config.Config; import org.matsim.core.config.ConfigGroup; import java.net.URL; @@ -60,7 +62,7 @@ public class ShiftsParams extends ReflectiveConfigGroupWithConfigurableParameter @Parameter @Comment("defines the battery state of charge threshold at which vehicles will start charging" + " at hubs when not in an active shift. values between [0,1)") - public double chargeAtHubThreshold = 0.5; + public double chargeAtHubThreshold = 0.6; @Parameter @Comment("defines the battery state of charge threshold at which vehicles will start charging" + @@ -97,11 +99,19 @@ public class ShiftsParams extends ReflectiveConfigGroupWithConfigurableParameter "In this case, make sure that 'shiftScheduleLookAhead' is larger than the prebboking slack.") public boolean considerUpcomingShiftsForInsertion = false; - public ShiftsParams() { + public ShiftsParams() { super(SET_NAME); } public URL getShiftInputUrl(URL context) { return shiftInputFile == null ? null : ConfigGroup.getInputFileURL(context, shiftInputFile); } + + @Override + protected void checkConsistency(Config config) { + super.checkConsistency(config); + Verify.verify(chargeAtHubThreshold >= shiftAssignmentBatteryThreshold, + "chargeAtHubThreshold must be higher than shiftAssignmentBatteryThreshold to " + + "avoid deadlocks with undercharged vehicles in hubs."); + } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DefaultShiftScheduler.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DefaultShiftScheduler.java new file mode 100644 index 00000000000..e51d7e01ec3 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DefaultShiftScheduler.java @@ -0,0 +1,52 @@ +package org.matsim.contrib.drt.extension.operations.shifts.dispatcher; + +import com.google.common.collect.ImmutableMap; +import org.matsim.api.core.v01.Id; +import org.matsim.contrib.drt.extension.operations.shifts.shift.*; +import org.matsim.contrib.dvrp.fleet.Fleet; + +import java.util.Collections; +import java.util.List; +import java.util.function.Function; + +/** + * @author nkuehnel / MOIA + */ +public final class DefaultShiftScheduler implements ShiftScheduler { + + private final DrtShiftsSpecification shiftsSpecification; + public static Function createShiftFromSpec = spec -> { + DefaultShiftBreakImpl shiftBreak = null; + DrtShiftBreakSpecification breakSpec = spec.getBreak().orElse(null); + if (breakSpec != null) { + shiftBreak = new DefaultShiftBreakImpl( + breakSpec.getEarliestBreakStartTime(), + breakSpec.getLatestBreakEndTime(), + breakSpec.getDuration()); + } + return (DrtShift) new DrtShiftImpl(spec.getId(), spec.getStartTime(), spec.getEndTime(), + spec.getOperationFacilityId().orElse(null), spec.getDesignatedVehicleId().orElse(null), + shiftBreak); + }; + + public DefaultShiftScheduler(DrtShiftsSpecification shiftsSpecification) { + this.shiftsSpecification = shiftsSpecification; + } + @Override + public List schedule(double time, Fleet fleet) { + return Collections.emptyList(); + } + + @Override + public ImmutableMap, DrtShift> initialSchedule() { + return shiftsSpecification.getShiftSpecifications().values() + .stream() + .map(createShiftFromSpec) + .collect(ImmutableMap.toImmutableMap(DrtShift::getId, s -> s)); + } + + @Override + public DrtShiftsSpecification get() { + return shiftsSpecification; + } +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java index 6e082f6f7d5..198401f4526 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java @@ -20,7 +20,6 @@ import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftSchedules; import org.matsim.contrib.drt.extension.operations.shifts.scheduler.ShiftTaskScheduler; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShift; -import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShifts; import org.matsim.contrib.drt.schedule.DrtDriveTask; import org.matsim.contrib.drt.schedule.DrtStayTask; import org.matsim.contrib.drt.schedule.DrtStopTask; @@ -51,7 +50,7 @@ public class DrtShiftDispatcherImpl implements DrtShiftDispatcher { private final String mode; - private SortedSet unscheduledShifts; + private SortedSet unAssignedShifts; private SortedSet assignedShifts; private SortedSet activeShifts; private SortedSet endingShifts; @@ -59,7 +58,6 @@ public class DrtShiftDispatcherImpl implements DrtShiftDispatcher { private Map, Queue> idleVehiclesQueues; private final Fleet fleet; - private final DrtShifts shifts; private final MobsimTimer timer; @@ -76,12 +74,14 @@ public class DrtShiftDispatcherImpl implements DrtShiftDispatcher { private final ShiftStartLogic shiftStartLogic; private final AssignShiftToVehicleLogic assignShiftToVehicleLogic; - public DrtShiftDispatcherImpl(String mode, DrtShifts shifts, Fleet fleet, MobsimTimer timer, OperationFacilities operationFacilities, + private final ShiftScheduler shiftScheduler; + + public DrtShiftDispatcherImpl(String mode, Fleet fleet, MobsimTimer timer, OperationFacilities operationFacilities, OperationFacilityFinder breakFacilityFinder, ShiftTaskScheduler shiftTaskScheduler, Network network, EventsManager eventsManager, ShiftsParams drtShiftParams, - ShiftStartLogic shiftStartLogic, AssignShiftToVehicleLogic assignShiftToVehicleLogic) { + ShiftStartLogic shiftStartLogic, AssignShiftToVehicleLogic assignShiftToVehicleLogic, + ShiftScheduler shiftScheduler) { this.mode = mode; - this.shifts = shifts; this.fleet = fleet; this.timer = timer; this.operationFacilities = operationFacilities; @@ -92,15 +92,25 @@ public DrtShiftDispatcherImpl(String mode, DrtShifts shifts, Fleet fleet, Mobsim this.drtShiftParams = drtShiftParams; this.shiftStartLogic = shiftStartLogic; this.assignShiftToVehicleLogic = assignShiftToVehicleLogic; + this.shiftScheduler = shiftScheduler; } @Override public void initialize() { - unscheduledShifts = new TreeSet<>(Comparator.comparingDouble(DrtShift::getStartTime)); - unscheduledShifts.addAll(shifts.getShifts().values()); + unAssignedShifts = new TreeSet<>(Comparator.comparingDouble(DrtShift::getStartTime).thenComparing(Comparator.naturalOrder())); + unAssignedShifts.addAll(shiftScheduler.initialSchedule().values()); + + assignedShifts = new TreeSet<>(Comparator + .comparingDouble((ShiftEntry entry) -> entry.shift().getStartTime()) + .thenComparing(ShiftEntry::shift)); - assignedShifts = new TreeSet<>(Comparator.comparingDouble(v -> v.shift().getStartTime())); + activeShifts = new TreeSet<>(Comparator + .comparingDouble((ShiftEntry entry) -> entry.shift().getEndTime()) + .thenComparing(ShiftEntry::shift)); + endingShifts = new TreeSet<>(Comparator + .comparingDouble((ShiftEntry entry) -> entry.shift().getEndTime()) + .thenComparing(ShiftEntry::shift)); idleVehiclesQueues = new LinkedHashMap<>(); for(OperationFacility facility: operationFacilities.getDrtOperationFacilities().values()) { @@ -114,15 +124,13 @@ public void initialize() { queue ); } - activeShifts = new TreeSet<>(Comparator.comparingDouble(v -> v.shift().getEndTime())); - endingShifts = new TreeSet<>(Comparator.comparingDouble(v -> v.shift().getEndTime())); } @Override public void dispatch(double timeStep) { if(timeStep % drtShiftParams.loggingInterval == 0) { logger.info(String.format("Active shifts: %s | Assigned shifts: %s | Unscheduled shifts: %s", - activeShifts.size(), assignedShifts.size(), unscheduledShifts.size())); + activeShifts.size(), assignedShifts.size(), unAssignedShifts.size())); StringJoiner print = new StringJoiner(" | "); for (Map.Entry, Queue> queueEntry : idleVehiclesQueues.entrySet()) { print.add(String.format("Idle vehicles at facility %s: %d", queueEntry.getKey().toString(), queueEntry.getValue().size())); @@ -133,6 +141,7 @@ public void dispatch(double timeStep) { if (timeStep % (drtShiftParams.updateShiftEndInterval) == 0) { updateShiftEnds(timeStep); } + scheduleShifts(timeStep, this.fleet); assignShifts(timeStep); startShifts(timeStep); checkBreaks(); @@ -162,6 +171,12 @@ private void checkBreaks() { } } + + private void scheduleShifts(double timeStep, Fleet fleet) { + List scheduled = shiftScheduler.schedule(timeStep, fleet); + unAssignedShifts.addAll(scheduled); + } + private void startShifts(double timeStep) { final Iterator iterator = this.assignedShifts.iterator(); while (iterator.hasNext()) { @@ -194,7 +209,7 @@ private void startShifts(double timeStep) { private void assignShifts(double timeStep) { // Remove elapsed shifts - unscheduledShifts.removeIf(shift -> { + unAssignedShifts.removeIf(shift -> { if (shift.getStartTime() + drtShiftParams.maxUnscheduledShiftDelay < timeStep ) { logger.warn("Shift with ID " + shift.getId() + " could not be assigned and is being removed as start time is longer in the past than defined by maxUnscheduledShiftDelay."); return true; @@ -204,7 +219,7 @@ private void assignShifts(double timeStep) { // Assign shifts Set assignableShifts = new LinkedHashSet<>(); - Iterator unscheduledShiftsIterator = unscheduledShifts.iterator(); + Iterator unscheduledShiftsIterator = unAssignedShifts.iterator(); while(unscheduledShiftsIterator.hasNext()) { DrtShift unscheduledShift = unscheduledShiftsIterator.next(); if(isSchedulable(unscheduledShift, timeStep)) { @@ -218,31 +233,46 @@ private void assignShifts(double timeStep) { for (DrtShift shift : assignableShifts) { ShiftDvrpVehicle vehicle = null; - for (ShiftEntry active : activeShifts) { - if (active.shift().getEndTime() > shift.getStartTime()) { - break; + if(shift.getDesignatedVehicleId().isPresent()) { + DvrpVehicle designatedVehicle = fleet.getVehicles().get(shift.getDesignatedVehicleId().get()); + Verify.verify(designatedVehicle.getSchedule().getStatus() == Schedule.ScheduleStatus.STARTED); + Verify.verify(designatedVehicle instanceof ShiftDvrpVehicle); + if(!((ShiftDvrpVehicle) designatedVehicle).getShifts().isEmpty()) { + continue; } if(shift.getOperationFacilityId().isPresent()) { - //we have to check that the vehicle ends the previous shift at the same facility where - //the new shift is to start. - if(active.shift().getOperationFacilityId().isPresent()) { - if(!active.shift().getOperationFacilityId().get().equals(shift.getOperationFacilityId().get())) { - continue; - } - } else { - Optional nextShiftChangeover = ShiftSchedules.getNextShiftChangeover(active.vehicle().getSchedule()); - if(nextShiftChangeover.isPresent()) { - Verify.verify(nextShiftChangeover.get().getShift().equals(active.shift())); - if(!nextShiftChangeover.get().getFacility().getId().equals(shift.getOperationFacilityId().get())) { - // there is already a shift changeover scheduled elsewhere + Verify.verify(idleVehiclesQueues.get(shift.getOperationFacilityId().get()).contains(designatedVehicle)); + } + vehicle = (ShiftDvrpVehicle) designatedVehicle; + } + + if(vehicle == null) { + for (ShiftEntry active : activeShifts) { + if (active.shift().getEndTime() > shift.getStartTime()) { + break; + } + if (shift.getOperationFacilityId().isPresent()) { + //we have to check that the vehicle ends the previous shift at the same facility where + //the new shift is to start. + if (active.shift().getOperationFacilityId().isPresent()) { + if (!active.shift().getOperationFacilityId().get().equals(shift.getOperationFacilityId().get())) { continue; } + } else { + Optional nextShiftChangeover = ShiftSchedules.getNextShiftChangeover(active.vehicle().getSchedule()); + if (nextShiftChangeover.isPresent()) { + Verify.verify(nextShiftChangeover.get().getShift().equals(active.shift())); + if (!nextShiftChangeover.get().getFacility().getId().equals(shift.getOperationFacilityId().get())) { + // there is already a shift changeover scheduled elsewhere + continue; + } + } } } - } - if (assignShiftToVehicleLogic.canAssignVehicleToShift(active.vehicle(), shift)) { - vehicle = active.vehicle(); - break; + if (assignShiftToVehicleLogic.canAssignVehicleToShift(active.vehicle(), shift)) { + vehicle = active.vehicle(); + break; + } } } @@ -277,7 +307,7 @@ private void assignShifts(double timeStep) { } else { // logger.warn("Could not assign shift " + shift.getId().toString() + " to a // vehicle. Will retry next time step."); - this.unscheduledShifts.add(shift); + this.unAssignedShifts.add(shift); } } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/ShiftScheduler.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/ShiftScheduler.java new file mode 100644 index 00000000000..e5f74f8b75e --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/ShiftScheduler.java @@ -0,0 +1,21 @@ +package org.matsim.contrib.drt.extension.operations.shifts.dispatcher; + +import com.google.common.collect.ImmutableMap; +import org.matsim.api.core.v01.Id; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShift; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; + +import jakarta.inject.Provider; +import org.matsim.contrib.dvrp.fleet.Fleet; + +import java.util.List; + +/** + * @author nkuehnel / MOIA + */ +public interface ShiftScheduler extends Provider { + + List schedule(double time, Fleet fleet); + ImmutableMap, DrtShift> initialSchedule(); + +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/io/DrtShiftsReader.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/io/DrtShiftsReader.java index f707a8c8108..928fd2360cd 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/io/DrtShiftsReader.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/io/DrtShiftsReader.java @@ -8,6 +8,7 @@ import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftBreakSpecificationImpl; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftSpecificationImpl; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.core.utils.io.MatsimXmlParser; import org.xml.sax.Attributes; @@ -27,6 +28,7 @@ public class DrtShiftsReader extends MatsimXmlParser { public static final String START_TIME = "start"; public static final String END_TIME = "end"; public static final String OPERATION_FACILITY_ID = "operationFacilityId"; + public static final String DESIGNATED_VEHICLE_ID = "designatedVehicleId"; public static final String EARLIEST_BREAK_START_TIME = "earliestStart"; public static final String LATEST_BREAK_END_TIME = "latestEnd"; @@ -55,8 +57,12 @@ public void startTag(final String name, final Attributes atts, final Stack, DrtShiftSpecification> shifts) throws atts.add(createTuple(END_TIME, shift.getEndTime())); shift.getOperationFacilityId().ifPresent(operationFacilityId -> atts.add(createTuple(OPERATION_FACILITY_ID, operationFacilityId.toString()))); + shift.getDesignatedVehicleId().ifPresent(designatedVehicleId -> + atts.add(createTuple(DESIGNATED_VEHICLE_ID, designatedVehicleId.toString()))); this.writeStartTag(SHIFT_NAME, atts); //Write break, if present diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java index 8b52ca88951..fd4756bb2ab 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java @@ -5,12 +5,14 @@ import com.google.inject.Provider; import com.google.inject.Singleton; import com.google.inject.TypeLiteral; -import org.matsim.api.core.v01.population.Population; +import org.matsim.contrib.common.timeprofile.ProfileWriter; import org.matsim.contrib.drt.extension.DrtWithExtensionsConfigGroup; import org.matsim.contrib.drt.extension.operations.DrtOperationsParams; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesSpecification; import org.matsim.contrib.drt.extension.operations.shifts.analysis.*; import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; +import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.ShiftScheduler; +import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DefaultShiftScheduler; import org.matsim.contrib.drt.extension.operations.shifts.io.DrtShiftsReader; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftBreakTaskImpl; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftChangeoverTaskImpl; @@ -24,14 +26,13 @@ import org.matsim.contrib.drt.schedule.DrtStayTask; import org.matsim.contrib.drt.schedule.DrtTaskBaseType; import org.matsim.contrib.drt.scheduler.EmptyVehicleRelocator; -import org.matsim.contrib.dvrp.fleet.FleetSpecification; -import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; -import org.matsim.contrib.dvrp.schedule.Task; -import org.matsim.contrib.common.timeprofile.ProfileWriter; import org.matsim.contrib.dvrp.analysis.VehicleOccupancyProfileCalculator; import org.matsim.contrib.dvrp.analysis.VehicleOccupancyProfileView; import org.matsim.contrib.dvrp.analysis.VehicleTaskProfileCalculator; import org.matsim.contrib.dvrp.analysis.VehicleTaskProfileView; +import org.matsim.contrib.dvrp.fleet.FleetSpecification; +import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; +import org.matsim.contrib.dvrp.schedule.Task; import org.matsim.core.config.Config; import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.controler.MatsimServices; @@ -82,14 +83,15 @@ public ShiftDrtModeModule(DrtConfigGroup drtCfg) { @Override public void install() { ShiftsParams shiftsParams = drtOperationsParams.getShiftsParams().orElseThrow(); + + DrtShiftsSpecification drtShiftsSpecification = new DrtShiftsSpecificationImpl(); if (shiftsParams.shiftInputFile != null) { - bindModal(DrtShiftsSpecification.class).toProvider(() -> { - DrtShiftsSpecification drtShiftsSpecification = new DrtShiftsSpecificationImpl(); - new DrtShiftsReader(drtShiftsSpecification).readURL(shiftsParams.getShiftInputUrl(getConfig().getContext())); - return drtShiftsSpecification; - }).asEagerSingleton(); + new DrtShiftsReader(drtShiftsSpecification).readURL(shiftsParams.getShiftInputUrl(getConfig().getContext())); } + bindModal(ShiftScheduler.class).toProvider(modalProvider(getter -> new DefaultShiftScheduler(drtShiftsSpecification))); + bindModal(DrtShiftsSpecification.class).toProvider(modalKey(ShiftScheduler.class)); + bindModal(ShiftDurationXY.class).toProvider(modalProvider( getter -> new ShiftDurationXY(getter.getModal(new TypeLiteral>(){}), getMode()) )).asEagerSingleton(); @@ -99,7 +101,7 @@ public void install() { )).asEagerSingleton(); bindModal(ShiftHistogram.class).toProvider(modalProvider( - getter -> new ShiftHistogram(getter.get(Population.class), getMode(), getter.get(Config.class)))).asEagerSingleton(); + getter -> new ShiftHistogram(getMode(), getter.get(Config.class)))).asEagerSingleton(); addEventHandlerBinding().to(modalKey(ShiftDurationXY.class)); addEventHandlerBinding().to(modalKey(BreakCorridorXY.class)); @@ -115,7 +117,7 @@ public void install() { bindModal(DumpShiftDataAtEndImpl.class).toProvider(modalProvider( getter -> new DumpShiftDataAtEndImpl( - getter.getModal(new TypeLiteral>(){}), + getter.getModal(DrtShiftsSpecification.class), getter.getModal(OperationFacilitiesSpecification.class), getter.get(OutputDirectoryHierarchy.class) )) @@ -137,5 +139,16 @@ public void install() { addControlerListenerBinding().toProvider(modalProvider(getter -> new ProfileWriter(getter.get(MatsimServices.class), drtConfigGroup.getMode(), new VehicleTaskProfileView(getter.getModal(VehicleTaskProfileCalculator.class), taskTypeComparator, taskTypePaints), "shift_task_time_profiles"))).in(Singleton.class); + + bindModal(RegularShiftDump.class).toProvider(modalProvider( + getter -> new RegularShiftDump( + getter.getModal(new TypeLiteral>(){}), + getter.get(OutputDirectoryHierarchy.class) + )) + ).asEagerSingleton(); + + addControlerListenerBinding().toProvider(modalProvider( + getter -> getter.getModal(RegularShiftDump.class) + )); } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java index a65de06b2c4..70423f2e59e 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java @@ -1,18 +1,13 @@ package org.matsim.contrib.drt.extension.operations.shifts.run; -import com.google.common.collect.ImmutableMap; import com.google.inject.Singleton; -import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Network; import org.matsim.contrib.drt.extension.DrtWithExtensionsConfigGroup; import org.matsim.contrib.drt.extension.operations.DrtOperationsParams; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilities; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilityFinder; import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; -import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DefaultAssignShiftToVehicleLogic; -import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DefaultShiftStartLogic; -import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DrtShiftDispatcher; -import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DrtShiftDispatcherImpl; +import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.*; import org.matsim.contrib.drt.extension.operations.shifts.fleet.DefaultShiftDvrpVehicle; import org.matsim.contrib.drt.extension.operations.shifts.optimizer.ShiftDrtOptimizer; import org.matsim.contrib.drt.extension.operations.shifts.optimizer.ShiftVehicleDataEntryFactory; @@ -24,7 +19,6 @@ import org.matsim.contrib.drt.extension.operations.shifts.scheduler.ShiftDrtScheduleInquiry; import org.matsim.contrib.drt.extension.operations.shifts.scheduler.ShiftTaskScheduler; import org.matsim.contrib.drt.extension.operations.shifts.scheduler.ShiftTaskSchedulerImpl; -import org.matsim.contrib.drt.extension.operations.shifts.shift.*; import org.matsim.contrib.drt.optimizer.*; import org.matsim.contrib.drt.optimizer.depot.DepotFinder; import org.matsim.contrib.drt.optimizer.insertion.CostCalculationStrategy; @@ -77,27 +71,6 @@ public ShiftDrtModeOptimizerQSimModule(DrtConfigGroup drtCfg) { protected void configureQSim() { ShiftsParams shiftsParams = drtOperationsParams.getShiftsParams().orElseThrow(); - bindModal(DrtShifts.class).toProvider(new ModalProviders.AbstractProvider<>(getMode(), DvrpModes::mode) { - @Override - public DrtShifts get() { - DrtShiftsSpecification shiftsSpecification = getModalInstance(DrtShiftsSpecification.class); - ImmutableMap, DrtShiftImpl> shifts = shiftsSpecification.getShiftSpecifications().values() - .stream() - .map(spec -> { - DefaultShiftBreakImpl shiftBreak = null; - DrtShiftBreakSpecification breakSpec = spec.getBreak().orElse(null); - if(breakSpec != null) { - shiftBreak = new DefaultShiftBreakImpl( - breakSpec.getEarliestBreakStartTime(), - breakSpec.getLatestBreakEndTime(), - breakSpec.getDuration()); - } - return new DrtShiftImpl(spec.getId(), spec.getStartTime(), spec.getEndTime(), spec.getOperationFacilityId().orElse(null), shiftBreak); - }) - .collect(ImmutableMap.toImmutableMap(DrtShift::getId, s -> s)); - return () -> shifts; - } - }).asEagerSingleton(); addModalComponent(DrtOptimizer.class, modalProvider( getter -> { @@ -112,11 +85,12 @@ public DrtShifts get() { getter.getModal(ScheduleTimingUpdater.class)); })); - bindModal(DrtShiftDispatcher.class).toProvider(modalProvider( - getter -> new DrtShiftDispatcherImpl(getMode(), getter.getModal(DrtShifts.class), getter.getModal(Fleet.class), - getter.get(MobsimTimer.class), getter.getModal(OperationFacilities.class), getter.getModal(OperationFacilityFinder.class), + bindModal(DrtShiftDispatcher.class).toProvider(modalProvider( + getter -> new DrtShiftDispatcherImpl(getMode(), getter.getModal(Fleet.class), getter.get(MobsimTimer.class), + getter.getModal(OperationFacilities.class), getter.getModal(OperationFacilityFinder.class), getter.getModal(ShiftTaskScheduler.class), getter.getModal(Network.class), getter.get(EventsManager.class), - shiftsParams, new DefaultShiftStartLogic(), new DefaultAssignShiftToVehicleLogic(shiftsParams))) + shiftsParams, new DefaultShiftStartLogic(), new DefaultAssignShiftToVehicleLogic(shiftsParams), + getter.getModal(ShiftScheduler.class))) ).asEagerSingleton(); bindModal(InsertionCostCalculator.class).toProvider(modalProvider( diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskSchedulerImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskSchedulerImpl.java index 94b5c3d0fed..c2fcc1ac4ee 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskSchedulerImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskSchedulerImpl.java @@ -269,6 +269,8 @@ public void startShift(ShiftDvrpVehicle vehicle, double now, DrtShift shift) { if(Schedules.getLastTask(schedule).equals(stayTask)) { //nothing planned yet. schedule.addTask(taskFactory.createStayTask(vehicle, now, shift.getEndTime(), stayTask.getLink())); + } else { + Schedules.getNextTask(schedule).setBeginTime(now); } } else { throw new IllegalStateException("Vehicle cannot start shift during task:" + stayTask.getTaskType().name()); @@ -296,7 +298,8 @@ public void planAssignedShift(ShiftDvrpVehicle vehicle, double timeStep, DrtShif Schedule schedule = vehicle.getSchedule(); StayTask stayTask = (StayTask) schedule.getCurrentTask(); if (stayTask instanceof WaitForShiftTask) { - stayTask.setEndTime(Math.max(timeStep, shift.getStartTime())); + // set +1 to ensure this update happens after next shift start check + stayTask.setEndTime(Math.max(timeStep + 1, shift.getStartTime())); } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShift.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShift.java index d641677cd38..5682dbeaf55 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShift.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShift.java @@ -3,20 +3,19 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Identifiable; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import java.util.Optional; /** * @author nkuehnel, fzwick / MOIA */ -public interface DrtShift extends Identifiable { +public interface DrtShift extends Identifiable, Comparable { double getStartTime(); double getEndTime(); - Optional getBreak(); - boolean isStarted(); boolean isEnded(); @@ -26,4 +25,8 @@ public interface DrtShift extends Identifiable { void end(); Optional> getOperationFacilityId(); + + Optional getBreak(); + + Optional> getDesignatedVehicleId(); } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftImpl.java index 79373816104..676e0fc6cc3 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftImpl.java @@ -2,6 +2,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import java.util.Optional; @@ -15,6 +16,7 @@ public class DrtShiftImpl implements DrtShift { private final double start; private final double end; private final Id operationFacilityId; + private final Id designatedVehicleId; private final DrtShiftBreak shiftBreak; @@ -22,12 +24,13 @@ public class DrtShiftImpl implements DrtShift { private boolean ended = false; public DrtShiftImpl(Id id, double start, double end, Id operationFacilityId, - DrtShiftBreak shiftBreak) { + Id designatedVehicleId, DrtShiftBreak shiftBreak) { this.id = id; this.start = start; this.end = end; this.operationFacilityId = operationFacilityId; - this.shiftBreak = shiftBreak; + this.designatedVehicleId = designatedVehicleId; + this.shiftBreak = shiftBreak; } @Override @@ -45,6 +48,11 @@ public Optional getBreak() { return Optional.ofNullable(shiftBreak); } + @Override + public Optional> getDesignatedVehicleId() { + return Optional.ofNullable(designatedVehicleId); + } + @Override public boolean isStarted() { return started; @@ -87,4 +95,9 @@ public Id getId() { public String toString() { return "Shift " + id.toString() + " ["+start+"-"+end+"]"; } + + @Override + public int compareTo(DrtShift shift) { + return this.id.compareTo(shift.getId()); + } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftSpecification.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftSpecification.java index 18f877c45e3..e32ad8a8416 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftSpecification.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftSpecification.java @@ -3,6 +3,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Identifiable; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import java.util.Optional; @@ -18,4 +19,6 @@ public interface DrtShiftSpecification extends Identifiable { Optional getBreak(); Optional> getOperationFacilityId(); + + Optional> getDesignatedVehicleId(); } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftSpecificationImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftSpecificationImpl.java index fd5a36f2501..6e0bc88b0dc 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftSpecificationImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftSpecificationImpl.java @@ -2,6 +2,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import java.util.Optional; @@ -15,6 +16,7 @@ public class DrtShiftSpecificationImpl implements DrtShiftSpecification { private final double end; private final DrtShiftBreakSpecification shiftBreak; private final Id operationFacilityId; + private final Id designatedVehicleId; private DrtShiftSpecificationImpl(Builder builder) { this.id = builder.id; @@ -22,6 +24,7 @@ private DrtShiftSpecificationImpl(Builder builder) { this.end = builder.end; this.shiftBreak = builder.shiftBreak; this.operationFacilityId = builder.operationFacilityId; + this.designatedVehicleId = builder.designatedVehicleId; } @Override @@ -44,6 +47,11 @@ public Optional> getOperationFacilityId() { return Optional.ofNullable(operationFacilityId); } + @Override + public Optional> getDesignatedVehicleId() { + return Optional.ofNullable(designatedVehicleId); + } + @Override public Id getId() { return id; @@ -69,6 +77,7 @@ public static final class Builder { private double end; private DrtShiftBreakSpecification shiftBreak; private Id operationFacilityId; + public Id designatedVehicleId; private Builder() { } @@ -97,6 +106,10 @@ public Builder operationFacility(Id operationFacilityId) { this.operationFacilityId = operationFacilityId; return this; } + public Builder designatedVehicle(Id designatedVehicleId) { + this.designatedVehicleId = designatedVehicleId; + return this; + } public DrtShiftSpecificationImpl build() { return new DrtShiftSpecificationImpl(this); diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenarioIT.java index 1d23eb2a1c4..8aaa6a7af7f 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenarioIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenarioIT.java @@ -103,7 +103,9 @@ void testWithPrebooking() { new OTFVisConfigGroup(), new EvConfigGroup()); DrtConfigGroup drtConfig = DrtConfigGroup.getSingleModeDrtConfig(config); - drtConfig.addParameterSet(new PrebookingParams()); + PrebookingParams prebookingParams = new PrebookingParams(); + prebookingParams.abortRejectedPrebookings = false; + drtConfig.addParameterSet(prebookingParams); Controler controller = RunEDrtScenario.createControler(config, false); ProbabilityBasedPrebookingLogic.install(controller, drtConfig, 0.5, 4.0 * 3600.0); diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimatorTest.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimatorTest.java index f925ed604dd..d5e606ed980 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimatorTest.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimatorTest.java @@ -5,7 +5,7 @@ import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.application.MATSimApplication; import org.matsim.contrib.drt.estimator.DrtEstimatorModule; -import org.matsim.contrib.drt.estimator.impl.ConstantDrtEstimator; +import org.matsim.contrib.drt.estimator.impl.ExampleDrtEstimator; import org.matsim.contrib.drt.extension.DrtTestScenario; import org.matsim.contrib.drt.extension.modechoice.MultiModalDrtLegEstimator; import org.matsim.contrib.drt.run.DrtConfigGroup; @@ -51,7 +51,7 @@ public void install() { for (DrtConfigGroup el : drtConfig.getModalElements()) { install(new DrtEstimatorModule(el.mode, el, el.getDrtEstimatorParams().get())); - DrtEstimatorModule.bindEstimator(binder(), el.mode).toInstance(new ConstantDrtEstimator(1.05, 300)); + DrtEstimatorModule.bindEstimator(binder(), el.mode).toInstance(new ExampleDrtEstimator(1.05, 300)); } } }); diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/ShiftsIOTest.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/ShiftsIOTest.java index ff5eb57ecdc..ae00d55bd16 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/ShiftsIOTest.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/ShiftsIOTest.java @@ -15,6 +15,7 @@ import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftSpecification; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecificationImpl; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.testcases.MatsimTestUtils; /** @@ -35,6 +36,9 @@ public class ShiftsIOTest { private final Id oid1 = Id.create("op1", OperationFacility.class); private final Id oid2 = Id.create("op2", OperationFacility.class); + private final Id vehId1 = Id.create("drt1", DvrpVehicle.class); + private final Id vehId2 = Id.create("drt2", DvrpVehicle.class); + @Test void testBasicReaderWriter() { @@ -69,6 +73,7 @@ private void checkContent(DrtShiftsSpecification shiftsSpecification) { assertEquals(45000., shiftSpecification1.getEndTime(), 0); assertTrue(shiftSpecification1.getOperationFacilityId().isPresent()); assertEquals(oid1, shiftSpecification1.getOperationFacilityId().get()); + assertEquals(vehId1, shiftSpecification1.getDesignatedVehicleId().get()); assertEquals(1800., shiftSpecification1.getBreak().orElseThrow().getDuration(), 0); assertEquals(28800., shiftSpecification1.getBreak().orElseThrow().getEarliestBreakStartTime(), 0); assertEquals(32400., shiftSpecification1.getBreak().orElseThrow().getLatestBreakEndTime(), 0); @@ -80,6 +85,7 @@ private void checkContent(DrtShiftsSpecification shiftsSpecification) { assertEquals(49000., shiftSpecification2.getEndTime(), 0); assertTrue(shiftSpecification2.getOperationFacilityId().isPresent()); assertEquals(oid2, shiftSpecification2.getOperationFacilityId().get()); + assertEquals(vehId2, shiftSpecification2.getDesignatedVehicleId().get()); assertEquals(3600., shiftSpecification2.getBreak().orElseThrow().getDuration(), 0); assertEquals(29200., shiftSpecification2.getBreak().orElseThrow().getEarliestBreakStartTime(), 0); assertEquals(32800., shiftSpecification2.getBreak().orElseThrow().getLatestBreakEndTime(), 0); @@ -91,6 +97,7 @@ private void checkContent(DrtShiftsSpecification shiftsSpecification) { assertEquals(53000., shiftSpecification3.getEndTime(), 0); assertFalse(shiftSpecification3.getOperationFacilityId().isPresent()); assertEquals(Optional.empty(), shiftSpecification3.getOperationFacilityId()); + assertEquals(Optional.empty(), shiftSpecification3.getDesignatedVehicleId()); assertTrue(shiftSpecification3.getBreak().isEmpty()); } } diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunOnTheFlyShiftDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunOnTheFlyShiftDrtScenarioIT.java new file mode 100644 index 00000000000..07c9a0b793b --- /dev/null +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunOnTheFlyShiftDrtScenarioIT.java @@ -0,0 +1,211 @@ +package org.matsim.contrib.drt.extension.operations.shifts.run; + +import com.google.common.collect.ImmutableMap; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.contrib.common.zones.systems.grid.square.SquareGridZoneSystemParams; +import org.matsim.contrib.drt.analysis.zonal.DrtZoneSystemParams; +import org.matsim.contrib.drt.extension.DrtWithExtensionsConfigGroup; +import org.matsim.contrib.drt.extension.operations.DrtOperationsControlerCreator; +import org.matsim.contrib.drt.extension.operations.DrtOperationsParams; +import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesParams; +import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; +import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DefaultShiftScheduler; +import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.ShiftScheduler; +import org.matsim.contrib.drt.extension.operations.shifts.shift.*; +import org.matsim.contrib.drt.fare.DrtFareParams; +import org.matsim.contrib.drt.optimizer.constraints.DefaultDrtOptimizationConstraintsSet; +import org.matsim.contrib.drt.optimizer.insertion.extensive.ExtensiveInsertionSearchParams; +import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams; +import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.MinCostFlowRebalancingStrategyParams; +import org.matsim.contrib.drt.run.DrtConfigGroup; +import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; +import org.matsim.contrib.dvrp.fleet.Fleet; +import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; +import org.matsim.contrib.dvrp.run.DvrpConfigGroup; +import org.matsim.contrib.zone.skims.DvrpTravelTimeMatrixParams; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigGroup; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.ReplanningConfigGroup; +import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.controler.Controler; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.controler.events.IterationStartsEvent; +import org.matsim.core.controler.listener.IterationStartsListener; +import org.matsim.examples.ExamplesUtils; + +import java.util.*; + +public class RunOnTheFlyShiftDrtScenarioIT { + + @Test + void test() { + + MultiModeDrtConfigGroup multiModeDrtConfigGroup = new MultiModeDrtConfigGroup(DrtWithExtensionsConfigGroup::new); + + String fleetFile = "holzkirchenFleet.xml"; + String plansFile = "holzkirchenPlans.xml.gz"; + String networkFile = "holzkirchenNetwork.xml.gz"; + String opFacilitiesFile = "holzkirchenOperationFacilities.xml"; + + DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup = (DrtWithExtensionsConfigGroup) multiModeDrtConfigGroup.createParameterSet("drt"); + + drtWithShiftsConfigGroup.mode = TransportMode.drt; + DefaultDrtOptimizationConstraintsSet defaultConstraintsSet = + (DefaultDrtOptimizationConstraintsSet) drtWithShiftsConfigGroup.addOrGetDrtOptimizationConstraintsParams() + .addOrGetDefaultDrtOptimizationConstraintsSet(); + drtWithShiftsConfigGroup.stopDuration = 30.; + defaultConstraintsSet.maxTravelTimeAlpha = 1.5; + defaultConstraintsSet.maxTravelTimeBeta = 10. * 60.; + defaultConstraintsSet.maxWaitTime = 600.; + defaultConstraintsSet.rejectRequestIfMaxWaitOrTravelTimeViolated = true; + defaultConstraintsSet.maxWalkDistance = 1000.; + drtWithShiftsConfigGroup.useModeFilteredSubnetwork = false; + drtWithShiftsConfigGroup.vehiclesFile = fleetFile; + drtWithShiftsConfigGroup.operationalScheme = DrtConfigGroup.OperationalScheme.door2door; + drtWithShiftsConfigGroup.plotDetailedCustomerStats = true; + drtWithShiftsConfigGroup.idleVehiclesReturnToDepots = false; + + drtWithShiftsConfigGroup.addParameterSet(new ExtensiveInsertionSearchParams()); + + ConfigGroup rebalancing = drtWithShiftsConfigGroup.createParameterSet("rebalancing"); + drtWithShiftsConfigGroup.addParameterSet(rebalancing); + ((RebalancingParams) rebalancing).interval = 600; + + MinCostFlowRebalancingStrategyParams strategyParams = new MinCostFlowRebalancingStrategyParams(); + strategyParams.targetAlpha = 0.3; + strategyParams.targetBeta = 0.3; + + drtWithShiftsConfigGroup.getRebalancingParams().get().addParameterSet(strategyParams); + + DrtZoneSystemParams drtZoneSystemParams = new DrtZoneSystemParams(); + SquareGridZoneSystemParams zoneParams = (SquareGridZoneSystemParams) drtZoneSystemParams.createParameterSet(SquareGridZoneSystemParams.SET_NAME); + zoneParams.cellSize = 500.; + drtZoneSystemParams.addParameterSet(zoneParams); + drtZoneSystemParams.targetLinkSelection = DrtZoneSystemParams.TargetLinkSelection.mostCentral; + drtWithShiftsConfigGroup.addParameterSet(drtZoneSystemParams); + + multiModeDrtConfigGroup.addParameterSet(drtWithShiftsConfigGroup); + + DvrpConfigGroup dvrpConfigGroup = new DvrpConfigGroup(); + DvrpTravelTimeMatrixParams matrixParams = dvrpConfigGroup.getTravelTimeMatrixParams(); + matrixParams.addParameterSet(matrixParams.createParameterSet(SquareGridZoneSystemParams.SET_NAME)); + + final Config config = ConfigUtils.createConfig(multiModeDrtConfigGroup, + dvrpConfigGroup); + config.setContext(ExamplesUtils.getTestScenarioURL("holzkirchen")); + + Set modes = new HashSet<>(); + modes.add("drt"); + config.travelTimeCalculator().setAnalyzedModes(modes); + + ScoringConfigGroup.ModeParams scoreParams = new ScoringConfigGroup.ModeParams("drt"); + config.scoring().addModeParams(scoreParams); + ScoringConfigGroup.ModeParams scoreParams2 = new ScoringConfigGroup.ModeParams("walk"); + config.scoring().addModeParams(scoreParams2); + + config.plans().setInputFile(plansFile); + config.network().setInputFile(networkFile); + + config.qsim().setSimStarttimeInterpretation(QSimConfigGroup.StarttimeInterpretation.onlyUseStarttime); + config.qsim().setSimEndtimeInterpretation(QSimConfigGroup.EndtimeInterpretation.minOfEndtimeAndMobsimFinished); + + final ScoringConfigGroup.ActivityParams home = new ScoringConfigGroup.ActivityParams("home"); + home.setTypicalDuration(8 * 3600); + final ScoringConfigGroup.ActivityParams other = new ScoringConfigGroup.ActivityParams("other"); + other.setTypicalDuration(4 * 3600); + final ScoringConfigGroup.ActivityParams education = new ScoringConfigGroup.ActivityParams("education"); + education.setTypicalDuration(6 * 3600); + final ScoringConfigGroup.ActivityParams shopping = new ScoringConfigGroup.ActivityParams("shopping"); + shopping.setTypicalDuration(2 * 3600); + final ScoringConfigGroup.ActivityParams work = new ScoringConfigGroup.ActivityParams("work"); + work.setTypicalDuration(2 * 3600); + + config.scoring().addActivityParams(home); + config.scoring().addActivityParams(other); + config.scoring().addActivityParams(education); + config.scoring().addActivityParams(shopping); + config.scoring().addActivityParams(work); + + final ReplanningConfigGroup.StrategySettings stratSets = new ReplanningConfigGroup.StrategySettings(); + stratSets.setWeight(1); + stratSets.setStrategyName("ChangeExpBeta"); + config.replanning().addStrategySettings(stratSets); + + config.controller().setLastIteration(1); + config.controller().setWriteEventsInterval(1); + + config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory("test/output/holzkirchen_shifts"); + + DrtOperationsParams operationsParams = (DrtOperationsParams) drtWithShiftsConfigGroup.createParameterSet(DrtOperationsParams.SET_NAME); + ShiftsParams shiftsParams = (ShiftsParams) operationsParams.createParameterSet(ShiftsParams.SET_NAME); + OperationFacilitiesParams operationFacilitiesParams = (OperationFacilitiesParams) operationsParams.createParameterSet(OperationFacilitiesParams.SET_NAME); + operationsParams.addParameterSet(shiftsParams); + operationsParams.addParameterSet(operationFacilitiesParams); + + operationFacilitiesParams.operationFacilityInputFile = opFacilitiesFile; + shiftsParams.allowInFieldChangeover = true; + drtWithShiftsConfigGroup.addParameterSet(operationsParams); + + DrtFareParams drtFareParams = new DrtFareParams(); + drtFareParams.baseFare = 1.; + drtFareParams.distanceFare_m = 1. / 1000; + drtWithShiftsConfigGroup.addParameterSet(drtFareParams); + + final Controler run = DrtOperationsControlerCreator.createControler(config, false); + + run.addOverridingModule(new AbstractDvrpModeModule(drtWithShiftsConfigGroup.getMode()) { + @Override + public void install() { + this.bindModal(OnTheFlyScheduler.class).toProvider(modalProvider(getter -> + new OnTheFlyScheduler())).asEagerSingleton(); + this.bindModal(ShiftScheduler.class).toProvider(modalProvider( getter -> getter.getModal(OnTheFlyScheduler.class))); + this.addControlerListenerBinding().toProvider(modalProvider( getter -> getter.getModal(OnTheFlyScheduler.class))); + } + }); + + run.run(); + } + + private static class OnTheFlyScheduler implements ShiftScheduler, IterationStartsListener { + + + private DefaultShiftScheduler delegate = new DefaultShiftScheduler(new DrtShiftsSpecificationImpl()); + private int iteration; + + @Override + public DrtShiftsSpecification get() { + return delegate.get(); + } + + @Override + public List schedule(double time, Fleet fleet) { + List shifts = new ArrayList<>(); + if (time > 4 * 3600 && time < 15 * 3600 && time % 3600 == 0) { + for (int i = 0; i < iteration + 1 ; i++) { + DrtShiftSpecificationImpl shift = DrtShiftSpecificationImpl.newBuilder() + .id(Id.create(time + "_" + i, DrtShift.class)) + .start(time + 3600).end(time + 9 * 3600).build(); + shifts.add(shift); + delegate.get().addShiftSpecification(shift); + } + } + return shifts.stream().map(DefaultShiftScheduler.createShiftFromSpec).toList(); + } + + @Override + public ImmutableMap, DrtShift> initialSchedule() { + delegate = new DefaultShiftScheduler(new DrtShiftsSpecificationImpl()); + return delegate.initialSchedule(); + } + + @Override + public void notifyIterationStarts(IterationStartsEvent event) { + iteration = event.getIteration(); + } + } +} diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java index 5babef611b3..01f5e27b837 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java @@ -1,5 +1,8 @@ package org.matsim.contrib.drt.extension.operations.shifts.run; +import com.google.common.collect.HashMultiset; +import com.google.common.collect.Multiset; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.matsim.api.core.v01.Coord; @@ -16,6 +19,8 @@ import org.matsim.contrib.drt.extension.operations.DrtOperationsParams; import org.matsim.contrib.drt.extension.operations.operationFacilities.*; import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; +import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DefaultShiftScheduler; +import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.ShiftScheduler; import org.matsim.contrib.drt.extension.operations.shifts.shift.*; import org.matsim.contrib.drt.optimizer.constraints.DefaultDrtOptimizationConstraintsSet; import org.matsim.contrib.drt.optimizer.insertion.extensive.ExtensiveInsertionSearchParams; @@ -32,6 +37,8 @@ import org.matsim.contrib.dvrp.fleet.FleetSpecificationImpl; import org.matsim.contrib.dvrp.fleet.ImmutableDvrpVehicleSpecification; import org.matsim.contrib.dvrp.passenger.PassengerRequestRejectedEventHandler; +import org.matsim.contrib.dvrp.passenger.PassengerRequestScheduledEventHandler; +import org.matsim.contrib.dvrp.passenger.PassengerRequestSubmittedEventHandler; import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; import org.matsim.contrib.dvrp.run.DvrpConfigGroup; import org.matsim.contrib.zone.skims.DvrpTravelTimeMatrixParams; @@ -60,11 +67,115 @@ public class RunPrebookingShiftDrtScenarioIT { @Test - void test() { + void testWithReattempts() { MultiModeDrtConfigGroup multiModeDrtConfigGroup = new MultiModeDrtConfigGroup(DrtWithExtensionsConfigGroup::new); + DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup = (DrtWithExtensionsConfigGroup) multiModeDrtConfigGroup.createParameterSet("drt"); + final Controler run = prepare(drtWithShiftsConfigGroup, multiModeDrtConfigGroup); + + Multiset> submittedPersons = HashMultiset.create(); + Multiset> scheduledPersons = HashMultiset.create(); + Multiset> rejectedPersons = HashMultiset.create(); + + run.addOverridingModule(new AbstractModule() { + @Override + public void install() { + addEventHandlerBinding().toInstance((PassengerRequestSubmittedEventHandler) event -> submittedPersons.addAll(event.getPersonIds())); + addEventHandlerBinding().toInstance((PassengerRequestScheduledEventHandler) event -> scheduledPersons.addAll(event.getPersonIds())); + addEventHandlerBinding().toInstance((PassengerRequestRejectedEventHandler) event -> rejectedPersons.addAll(event.getPersonIds())); + } + }); + + PrebookingParams prebookingParams = new PrebookingParams(); + prebookingParams.maximumPassengerDelay = 600; + prebookingParams.unschedulingMode = PrebookingParams.UnschedulingMode.Routing; + prebookingParams.scheduleWaitBeforeDrive = true; + prebookingParams.abortRejectedPrebookings = false; + drtWithShiftsConfigGroup.addParameterSet(prebookingParams); + + run.addOverridingQSimModule(new PrebookingModeQSimModule(drtWithShiftsConfigGroup.getMode(), + prebookingParams)); + + run.run(); + + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(1))); + Assertions.assertEquals(2, submittedPersons.count(Id.createPersonId(2))); + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(3))); + Assertions.assertEquals(2, submittedPersons.count(Id.createPersonId(4))); + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(5))); + Assertions.assertEquals(2, submittedPersons.count(Id.createPersonId(6))); + + Assertions.assertEquals(1, scheduledPersons.count(Id.createPersonId(1))); + Assertions.assertEquals(1, scheduledPersons.count(Id.createPersonId(2))); + Assertions.assertEquals(1, scheduledPersons.count(Id.createPersonId(3))); + Assertions.assertEquals(1, scheduledPersons.count(Id.createPersonId(4))); + Assertions.assertEquals(1, scheduledPersons.count(Id.createPersonId(5))); + Assertions.assertEquals(0, scheduledPersons.count(Id.createPersonId(6))); + + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(1))); + Assertions.assertEquals(1, rejectedPersons.count(Id.createPersonId(2))); + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(3))); + Assertions.assertEquals(1, rejectedPersons.count(Id.createPersonId(4))); + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(5))); + Assertions.assertEquals(2, rejectedPersons.count(Id.createPersonId(6))); + } + @Test + void testWithoutReattempts() { + + MultiModeDrtConfigGroup multiModeDrtConfigGroup = new MultiModeDrtConfigGroup(DrtWithExtensionsConfigGroup::new); DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup = (DrtWithExtensionsConfigGroup) multiModeDrtConfigGroup.createParameterSet("drt"); + final Controler run = prepare(drtWithShiftsConfigGroup, multiModeDrtConfigGroup); + + Multiset> submittedPersons = HashMultiset.create(); + Multiset> scheduledPersons = HashMultiset.create(); + Multiset> rejectedPersons = HashMultiset.create(); + + run.addOverridingModule(new AbstractModule() { + @Override + public void install() { + addEventHandlerBinding().toInstance((PassengerRequestSubmittedEventHandler) event -> submittedPersons.addAll(event.getPersonIds())); + addEventHandlerBinding().toInstance((PassengerRequestScheduledEventHandler) event -> scheduledPersons.addAll(event.getPersonIds())); + addEventHandlerBinding().toInstance((PassengerRequestRejectedEventHandler) event -> rejectedPersons.addAll(event.getPersonIds())); + } + }); + + PrebookingParams prebookingParams = new PrebookingParams(); + prebookingParams.maximumPassengerDelay = 600; + prebookingParams.unschedulingMode = PrebookingParams.UnschedulingMode.Routing; + prebookingParams.scheduleWaitBeforeDrive = true; + prebookingParams.abortRejectedPrebookings = true; + drtWithShiftsConfigGroup.addParameterSet(prebookingParams); + + run.addOverridingQSimModule(new PrebookingModeQSimModule(drtWithShiftsConfigGroup.getMode(), + prebookingParams)); + + run.run(); + + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(1))); + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(2))); + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(3))); + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(4))); + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(5))); + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(6))); + + Assertions.assertEquals(1, scheduledPersons.count(Id.createPersonId(1))); + Assertions.assertEquals(0, scheduledPersons.count(Id.createPersonId(2))); + Assertions.assertEquals(1, scheduledPersons.count(Id.createPersonId(3))); + Assertions.assertEquals(0, scheduledPersons.count(Id.createPersonId(4))); + Assertions.assertEquals(1, scheduledPersons.count(Id.createPersonId(5))); + Assertions.assertEquals(0, scheduledPersons.count(Id.createPersonId(6))); + + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(1))); + Assertions.assertEquals(1, rejectedPersons.count(Id.createPersonId(2))); + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(3))); + Assertions.assertEquals(1, rejectedPersons.count(Id.createPersonId(4))); + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(5))); + Assertions.assertEquals(1, rejectedPersons.count(Id.createPersonId(6))); + } + + @NotNull + private Controler prepare(DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup, MultiModeDrtConfigGroup multiModeDrtConfigGroup) { drtWithShiftsConfigGroup.mode = TransportMode.drt; DefaultDrtOptimizationConstraintsSet defaultConstraintsSet = (DefaultDrtOptimizationConstraintsSet) drtWithShiftsConfigGroup.addOrGetDrtOptimizationConstraintsParams() @@ -146,11 +257,6 @@ void test() { shiftsParams.shiftEndLookAhead = 900.; drtWithShiftsConfigGroup.addParameterSet(operationsParams); - PrebookingParams prebookingParams = new PrebookingParams(); - prebookingParams.maximumPassengerDelay = 600; - prebookingParams.unschedulingMode = PrebookingParams.UnschedulingMode.Routing; - prebookingParams.scheduleWaitBeforeDrive = true; - drtWithShiftsConfigGroup.addParameterSet(prebookingParams); Scenario scenario = DrtControlerCreator.createScenarioWithDrtRouteFactory(config); prepareNetwork(scenario); @@ -159,27 +265,9 @@ void test() { final Controler run = DrtOperationsControlerCreator.createControler(config, scenario, false); prepareOperations(run, drtWithShiftsConfigGroup); - run.addOverridingQSimModule(new PrebookingModeQSimModule(drtWithShiftsConfigGroup.getMode(), - prebookingParams)); - AttributeBasedPrebookingLogic.install(run, drtWithShiftsConfigGroup); - - Set> rejectedPersons = new HashSet<>(); - run.addOverridingModule(new AbstractModule() { - @Override - public void install() { - addEventHandlerBinding().toInstance((PassengerRequestRejectedEventHandler) event -> rejectedPersons.addAll(event.getPersonIds())); - } - }); - - run.run(); - - Assertions.assertFalse(rejectedPersons.contains(Id.createPersonId(1))); - Assertions.assertTrue(rejectedPersons.contains(Id.createPersonId(2))); - Assertions.assertFalse(rejectedPersons.contains(Id.createPersonId(3))); - Assertions.assertTrue(rejectedPersons.contains(Id.createPersonId(4))); - Assertions.assertFalse(rejectedPersons.contains(Id.createPersonId(5))); - Assertions.assertTrue(rejectedPersons.contains(Id.createPersonId(6))); + AttributeBasedPrebookingLogic.install(run, drtWithShiftsConfigGroup); + return run; } private void preparePopulation(Scenario scenario) { @@ -208,7 +296,7 @@ private void preparePopulation(Scenario scenario) { Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1)); start.setEndTime(5000); start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 900.); - start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 5000.); + start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 5005.); plan.addActivity(start); plan.addLeg(factory.createLeg("drt")); plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2))); @@ -311,7 +399,7 @@ private static void prepareOperations(Controler run, DrtWithExtensionsConfigGrou public void install() { bindModal(FleetSpecification.class).toInstance(fleetSpecification); bindModal(OperationFacilitiesSpecification.class).toInstance(opFasSpecification); - bindModal(DrtShiftsSpecification.class).toInstance(shiftsSpecification); + bindModal(ShiftScheduler.class).toProvider(modalProvider(getter -> new DefaultShiftScheduler(shiftsSpecification))); } }); diff --git a/contribs/drt-extensions/test/input/org/matsim/contrib/drt/extension/operations/shifts/testShifts.xml b/contribs/drt-extensions/test/input/org/matsim/contrib/drt/extension/operations/shifts/testShifts.xml index 2cb87bd3c9f..972a28788af 100644 --- a/contribs/drt-extensions/test/input/org/matsim/contrib/drt/extension/operations/shifts/testShifts.xml +++ b/contribs/drt-extensions/test/input/org/matsim/contrib/drt/extension/operations/shifts/testShifts.xml @@ -1,8 +1,8 @@ - + - + diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/DrtEventSequenceCollector.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/DrtEventSequenceCollector.java index b8b095cd1dc..90836e785cc 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/DrtEventSequenceCollector.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/DrtEventSequenceCollector.java @@ -159,7 +159,7 @@ public List getDrtFares() { } public boolean isCompleted() { - return personEvents.values().stream().allMatch(pe -> pe.droppedOff != null); + return submitted.getPersonIds().stream().allMatch(personId -> personEvents.get(personId).droppedOff != null); } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/DetourBasedDrtEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/DetourBasedDrtEstimator.java deleted file mode 100644 index e85e5595930..00000000000 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/DetourBasedDrtEstimator.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.matsim.contrib.drt.estimator.impl; - -import org.matsim.contrib.drt.estimator.DrtEstimator; -import org.matsim.contrib.drt.routing.DrtRoute; -import org.matsim.core.utils.misc.OptionalTime; - -import java.util.Random; - -/** - * A simple DRT estimator that uses normal distributions to estimate the ride time, wait time, ride distance and acceptance. - */ -public final class DetourBasedDrtEstimator implements DrtEstimator { - - private final NormalDistributionGenerator distributionGenerator; - - private DetourBasedDrtEstimator(double estRideTimeAlpha, double estRideTimeBeta, double rideTimeStd, double estMeanWaitTime, - double waitTimeStd) { - this.distributionGenerator = new NormalDistributionGenerator(estRideTimeAlpha, estRideTimeBeta, rideTimeStd, estMeanWaitTime, waitTimeStd); - } - - public static DetourBasedDrtEstimator normalDistributed(double estRideTimeAlpha, double estRideTimeBeta, double rideTimeStd, double estMeanWaitTime, - double waitTimeStd) { - return new DetourBasedDrtEstimator(estRideTimeAlpha, estRideTimeBeta, rideTimeStd, estMeanWaitTime, waitTimeStd); - } - - @Override - public Estimate estimate(DrtRoute route, OptionalTime departureTime) { - double directRideTIme = route.getDirectRideTime(); - double directDistance = route.getDistance(); - double waitTime = distributionGenerator.generateWaitTime(); - double rideTime = distributionGenerator.generateRideTime(directRideTIme); - double rideDistance = distributionGenerator.generateRideDistance(rideTime, directRideTIme, directDistance); - double acceptanceRate = distributionGenerator.generateAcceptanceRate(); - - return new Estimate(rideDistance, waitTime + rideTime, waitTime, acceptanceRate); - } - - private static class NormalDistributionGenerator { - private final Random random = new Random(4711); - private final double estRideTimeAlpha; - private final double estRideTimeBeta; - private final double rideTimeStd; - private final double estMeanWaitTime; - private final double waitTimeStd; - - public NormalDistributionGenerator(double estRideTimeAlpha, double estRideTimeBeta, double rideTimeStd, double estMeanWaitTime, - double waitTimeStd) { - this.estRideTimeAlpha = estRideTimeAlpha; - this.estRideTimeBeta = estRideTimeBeta; - this.rideTimeStd = rideTimeStd; - this.estMeanWaitTime = estMeanWaitTime; - this.waitTimeStd = waitTimeStd; - } - - public double generateRideTime(double directRideTime) { - // TODO improve this distribution - double estMeanRideTime = estRideTimeAlpha * directRideTime + estRideTimeBeta; - return Math.max(directRideTime, estMeanRideTime * (1 + random.nextGaussian() * rideTimeStd)); - } - - public double generateRideDistance(double estRideTime, double directRideTime, double directRideDistance) { - // TODO Currently, same ratio is used as in the ride time estimation; improve this distribution - double ratio = estRideTime / directRideTime; - return ratio * directRideDistance; - } - - public double generateWaitTime() { - // TODO improve this distribution - return Math.max(estMeanWaitTime * (1 + random.nextGaussian() * waitTimeStd), 0); - } - - public double generateAcceptanceRate() { - return 1; - } - } -} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/DirectTripBasedDrtEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/DirectTripBasedDrtEstimator.java new file mode 100644 index 00000000000..08ae52d5a0a --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/DirectTripBasedDrtEstimator.java @@ -0,0 +1,130 @@ +package org.matsim.contrib.drt.estimator.impl; + +import org.checkerframework.checker.units.qual.C; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.drt.estimator.DrtEstimator; +import org.matsim.contrib.drt.estimator.impl.distribution.DistributionGenerator; +import org.matsim.contrib.drt.estimator.impl.distribution.LogNormalDistributionGenerator; +import org.matsim.contrib.drt.estimator.impl.distribution.NoDistribution; +import org.matsim.contrib.drt.estimator.impl.distribution.NormalDistributionGenerator; +import org.matsim.contrib.drt.estimator.impl.trip_estimation.ConstantRideDurationEstimator; +import org.matsim.contrib.drt.estimator.impl.trip_estimation.RideDurationEstimator; +import org.matsim.contrib.drt.estimator.impl.waiting_time_estimation.ConstantWaitingTimeEstimator; +import org.matsim.contrib.drt.estimator.impl.waiting_time_estimation.WaitingTimeEstimator; +import org.matsim.contrib.drt.routing.DrtRoute; +import org.matsim.core.utils.misc.OptionalTime; + +/** + * DRT estimator that uses available data (e.g., real-world operational data, simulation-based data) to provide estimated data for DRT trips. + */ +public final class DirectTripBasedDrtEstimator implements DrtEstimator { + private final RideDurationEstimator rideDurationEstimator; + private final WaitingTimeEstimator waitingTimeEstimator; + private final DistributionGenerator waitingTimeDistributionGenerator; + private final DistributionGenerator rideTimeDistributionGenerator; + + public static class Builder { + // Initialize with default estimation + private RideDurationEstimator rideDurationEstimator = new ConstantRideDurationEstimator(1.25, 300); + private WaitingTimeEstimator waitingTimeEstimator = new ConstantWaitingTimeEstimator(300); + private DistributionGenerator waitingTimeDistributionGenerator = new NoDistribution(); + private DistributionGenerator rideTimeDistributionGenerator = new NoDistribution(); + + public Builder setRideDurationEstimator(RideDurationEstimator rideDurationEstimator) { + this.rideDurationEstimator = rideDurationEstimator; + return this; + } + + public Builder setWaitingTimeEstimator(WaitingTimeEstimator waitingTimeEstimator) { + this.waitingTimeEstimator = waitingTimeEstimator; + return this; + } + + public Builder setRideDurationDistributionGenerator(DistributionGenerator rideTimeDistributionGenerator) { + this.rideTimeDistributionGenerator = rideTimeDistributionGenerator; + return this; + } + + public Builder setWaitingTimeDistributionGenerator(DistributionGenerator waitingTimeDistributionGenerator) { + this.waitingTimeDistributionGenerator = waitingTimeDistributionGenerator; + return this; + } + + public DirectTripBasedDrtEstimator build() { + return new DirectTripBasedDrtEstimator(rideDurationEstimator, waitingTimeEstimator, rideTimeDistributionGenerator, waitingTimeDistributionGenerator); + } + + } + + public DirectTripBasedDrtEstimator(RideDurationEstimator rideDurationEstimator, WaitingTimeEstimator waitingTimeEstimator, + DistributionGenerator rideTimeDistribution, DistributionGenerator waitTimeDistribution) { + this.rideDurationEstimator = rideDurationEstimator; + this.waitingTimeEstimator = waitingTimeEstimator; + this.rideTimeDistributionGenerator = rideTimeDistribution; + this.waitingTimeDistributionGenerator = waitTimeDistribution; + } + + /** + * Example DRT estimator based on the normal distributed ride time and waiting time + * @param estRideTimeAlpha typical ride duration = alpha * direct ride time + beta, alpha is specified here + * @param estRideTimeBeta typical ride duration = alpha * direct ride time + beta, beta is specified here + * @param rideTimeStd standard deviation of ride duration (normalized to 1) + * @param estMeanWaitTime estimated waiting time (i.e., mean wait time) + * @param waitTimeStd standard deviation of waiting time (normalized to 1) + * @return NetworkBasedDrtEstimator + */ + public static DirectTripBasedDrtEstimator normalDistributedNetworkBasedDrtEstimator(double estRideTimeAlpha, double estRideTimeBeta, + double rideTimeStd, double estMeanWaitTime, + double waitTimeStd) { + return new Builder() + .setWaitingTimeEstimator(new ConstantWaitingTimeEstimator(estMeanWaitTime)) + .setRideDurationEstimator(new ConstantRideDurationEstimator(estRideTimeAlpha, estRideTimeBeta)) + .setWaitingTimeDistributionGenerator(new NormalDistributionGenerator(1, waitTimeStd)) + .setRideDurationDistributionGenerator(new NormalDistributionGenerator(2, rideTimeStd)) + .build(); + } + + /** + * Example DRT estimator based on the log-normal distributed ride time and normal distributed waiting time + * @param estRideTimeAlpha typical ride duration = alpha * direct ride time + beta, alpha is specified here + * @param estRideTimeBeta typical ride duration = alpha * direct ride time + beta, beta is specified here + * @param mu log-normal distribution parameter for ride duration (normalized to typical ride duration) + * @param sigma log-normal distribution parameter for ride duration (normalized to typical ride duration) + * @param estMeanWaitTime estimated waiting time (i.e., mean wait time) + * @param waitTimeStd standard deviation of waiting time (normalized to 1) + * @return NetworkBasedDrtEstimator + */ + public static DirectTripBasedDrtEstimator mixDistributedNetworkBasedDrtEstimator(double estRideTimeAlpha, double estRideTimeBeta, + double mu, double sigma, double estMeanWaitTime, + double waitTimeStd) { + return new Builder() + .setWaitingTimeEstimator(new ConstantWaitingTimeEstimator(estMeanWaitTime)) + .setRideDurationEstimator(new ConstantRideDurationEstimator(estRideTimeAlpha, estRideTimeBeta)) + .setWaitingTimeDistributionGenerator(new NormalDistributionGenerator(1, waitTimeStd)) + .setRideDurationDistributionGenerator(new LogNormalDistributionGenerator(2, mu, sigma)) + .build(); + } + + @Override + public Estimate estimate(DrtRoute route, OptionalTime departureTime) { + double directRideTIme = route.getDirectRideTime(); + double directDistance = route.getDistance(); + Id fromLinkId = route.getStartLinkId(); + Id toLinkId = route.getEndLinkId(); + double typicalRideDuration = rideDurationEstimator.getEstimatedRideDuration(fromLinkId, toLinkId, departureTime, directRideTIme); + double typicalRideDistance = (typicalRideDuration / directRideTIme) * directDistance; + double typicalWaitingTime = waitingTimeEstimator.estimateWaitTime(fromLinkId, toLinkId, departureTime); + + double estimatedWaitingTime = typicalWaitingTime * waitingTimeDistributionGenerator.generateRandomValue(); + + double detourRandomFactor = rideTimeDistributionGenerator.generateRandomValue(); + double estimatedRideDuration = detourRandomFactor * typicalRideDuration; + double estimatedRideDistance = detourRandomFactor * typicalRideDistance; + + double acceptanceRate = 1.0; + + return new Estimate(estimatedRideDistance, estimatedRideDuration, estimatedWaitingTime, acceptanceRate); + } + +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/EuclideanDistanceBasedDrtEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/EuclideanDistanceBasedDrtEstimator.java index dd3a2492ce9..8b617888084 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/EuclideanDistanceBasedDrtEstimator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/EuclideanDistanceBasedDrtEstimator.java @@ -3,12 +3,18 @@ import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.network.Network; import org.matsim.contrib.drt.estimator.DrtEstimator; +import org.matsim.contrib.drt.estimator.impl.distribution.DistributionGenerator; +import org.matsim.contrib.drt.estimator.impl.distribution.LogNormalDistributionGenerator; +import org.matsim.contrib.drt.estimator.impl.distribution.NormalDistributionGenerator; +import org.matsim.contrib.drt.estimator.impl.trip_estimation.ConstantRideDurationEstimator; +import org.matsim.contrib.drt.estimator.impl.trip_estimation.RideDurationEstimator; +import org.matsim.contrib.drt.estimator.impl.waiting_time_estimation.ConstantWaitingTimeEstimator; +import org.matsim.contrib.drt.estimator.impl.waiting_time_estimation.WaitingTimeEstimator; import org.matsim.contrib.drt.routing.DrtRoute; +import org.matsim.core.utils.collections.Tuple; import org.matsim.core.utils.geometry.CoordUtils; import org.matsim.core.utils.misc.OptionalTime; -import java.util.Random; - public class EuclideanDistanceBasedDrtEstimator implements DrtEstimator { private final Network network; /** @@ -16,26 +22,16 @@ public class EuclideanDistanceBasedDrtEstimator implements DrtEstimator { * Estimated network distance = Euclidean distance * network distance factor */ private final double networkDistanceFactor; - /** - * Slope of the linear regression - */ - private final double slope; - /** - * Intercept of the linear regression - */ - private final double intercept; - - private final double estimatedMeanWaitTime; - - private final double waitTimeStd; + private final RideDurationEstimator rideDurationEstimator; + private final WaitingTimeEstimator waitingTimeEstimator; + private final DistributionGenerator rideDurationDistributionGenerator; + private final DistributionGenerator waitingTimeDistributionGenerator; - private final double mu; - private final double sigma; - private final Random random = new Random(1234); /** * We use log normal distribution to estimate the ride duration of each individual trip. The distribution * is based on the linear regression. + * * @params networkDistanceFactor: Estimated network distance = Euclidean distance * network distance factor * @params slope: slope for the linear regression * @params intercept: intercept for linear regression @@ -47,12 +43,21 @@ public EuclideanDistanceBasedDrtEstimator(Network network, double networkDistanc double mu, double sigma) { this.network = network; this.networkDistanceFactor = networkDistanceFactor; - this.slope = slope; - this.intercept = intercept; - this.estimatedMeanWaitTime = estimatedMeanWaitTime; - this.waitTimeStd = waitTimeStd; - this.mu = mu; - this.sigma = sigma; + this.rideDurationEstimator = new ConstantRideDurationEstimator(slope, intercept); + this.waitingTimeEstimator = new ConstantWaitingTimeEstimator(estimatedMeanWaitTime); + this.rideDurationDistributionGenerator = new LogNormalDistributionGenerator(1, mu, sigma); + this.waitingTimeDistributionGenerator = new NormalDistributionGenerator(2, waitTimeStd); + } + + public EuclideanDistanceBasedDrtEstimator(Network network, double networkDistanceFactor, RideDurationEstimator rideDurationEstimator, + WaitingTimeEstimator waitingTimeEstimator, DistributionGenerator rideDurationDistributionGenerator, + DistributionGenerator waitingTimeDistributionGenerator) { + this.network = network; + this.networkDistanceFactor = networkDistanceFactor; + this.rideDurationEstimator = rideDurationEstimator; + this.waitingTimeEstimator = waitingTimeEstimator; + this.rideDurationDistributionGenerator = rideDurationDistributionGenerator; + this.waitingTimeDistributionGenerator = waitingTimeDistributionGenerator; } @Override @@ -60,19 +65,15 @@ public Estimate estimate(DrtRoute route, OptionalTime departureTime) { Coord fromCoord = network.getLinks().get(route.getStartLinkId()).getToNode().getCoord(); Coord toCoord = network.getLinks().get(route.getEndLinkId()).getToNode().getCoord(); double euclideanDistance = CoordUtils.calcEuclideanDistance(fromCoord, toCoord); - double typicalRideDuration = euclideanDistance * slope + intercept; + + double typicalRideDuration = rideDurationEstimator.getEstimatedRideDuration(route.getStartLinkId(), route.getEndLinkId(), departureTime, euclideanDistance); double typicalRideDistance = networkDistanceFactor * euclideanDistance; - double randomFactor = nextLogNormal(mu, sigma); - double waitTime = Math.max(estimatedMeanWaitTime * (1 + random.nextGaussian() * waitTimeStd), 0); + double typicalWaitingTime = waitingTimeEstimator.estimateWaitTime(route.getStartLinkId(), route.getEndLinkId(), departureTime); + double randomFactor = rideDurationDistributionGenerator.generateRandomValue(); + double waitTime = Math.max(typicalWaitingTime * waitingTimeDistributionGenerator.generateRandomValue(), 0); return new Estimate(typicalRideDistance * randomFactor, typicalRideDuration * randomFactor, waitTime, 0); } - public double nextLogNormal(double mu, double sigma) { - if (sigma == 0) - return Math.exp(mu); - - return Math.exp(sigma * random.nextGaussian() + mu); - } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/ConstantDrtEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/ExampleDrtEstimator.java similarity index 82% rename from contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/ConstantDrtEstimator.java rename to contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/ExampleDrtEstimator.java index 20ea18ee120..b49b3b988f0 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/ConstantDrtEstimator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/ExampleDrtEstimator.java @@ -2,13 +2,13 @@ import org.matsim.contrib.drt.estimator.DrtEstimator; import org.matsim.contrib.drt.routing.DrtRoute; -import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.core.utils.misc.OptionalTime; /** * Estimates using a constant detour factor and waiting time. */ -public class ConstantDrtEstimator implements DrtEstimator { +@Deprecated +public class ExampleDrtEstimator implements DrtEstimator { /** * Detour factor for the estimate. 1.0 means no detour, 2.0 means twice the distance. @@ -20,7 +20,7 @@ public class ConstantDrtEstimator implements DrtEstimator { */ private final double waitingTime; - public ConstantDrtEstimator(double detourFactor, double waitingTime) { + public ExampleDrtEstimator(double detourFactor, double waitingTime) { this.detourFactor = detourFactor; this.waitingTime = waitingTime; } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/BasicDrtEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/OnlineSimulationBasedDrtEstimator.java similarity index 90% rename from contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/BasicDrtEstimator.java rename to contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/OnlineSimulationBasedDrtEstimator.java index f02c4ee59b2..db1f3e83ccd 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/BasicDrtEstimator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/OnlineSimulationBasedDrtEstimator.java @@ -1,7 +1,6 @@ package org.matsim.contrib.drt.estimator.impl; import org.apache.commons.math3.stat.descriptive.SummaryStatistics; -import org.apache.commons.math3.stat.regression.RegressionResults; import org.apache.commons.math3.stat.regression.SimpleRegression; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -23,12 +22,14 @@ import java.util.SplittableRandom; /** + * When this estimator is used, explicit simulations of DRT will be carried out intermittently. During the iterations where no + * DRT is simulated, estimated DRT will be used. This estimator will replace the original DRT speed-up module * Estimates drt trips based only daily averages. No spatial or temporal differentiation is taken into account for the estimate. * This estimator is suited for small scenarios with few vehicles and trips and consequently few data points. */ -public class BasicDrtEstimator implements DrtOnlineEstimator, IterationEndsListener { +public class OnlineSimulationBasedDrtEstimator implements DrtOnlineEstimator, IterationEndsListener { - private static final Logger log = LogManager.getLogger(BasicDrtEstimator.class); + private static final Logger log = LogManager.getLogger(OnlineSimulationBasedDrtEstimator.class); private final DrtEventSequenceCollector collector; private final DrtEstimatorParams config; @@ -41,8 +42,8 @@ public class BasicDrtEstimator implements DrtOnlineEstimator, IterationEndsListe */ private GlobalEstimate currentEst; - public BasicDrtEstimator(DrtEventSequenceCollector collector, DrtEstimator initial, - DrtEstimatorParams config, DrtConfigGroup drtConfig) { + public OnlineSimulationBasedDrtEstimator(DrtEventSequenceCollector collector, DrtEstimator initial, + DrtEstimatorParams config, DrtConfigGroup drtConfig) { //zones = injector.getModal(DrtZonalSystem.class); this.collector = collector; this.initial = initial; diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/DistributionGenerator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/DistributionGenerator.java new file mode 100644 index 00000000000..d5e6e890729 --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/DistributionGenerator.java @@ -0,0 +1,10 @@ +package org.matsim.contrib.drt.estimator.impl.distribution; + +public interface DistributionGenerator { + /** + * @return relative value to the typical ride duration (i.e., generate a distribution around 1.0) + */ + double generateRandomValue(); + + enum DistributionType {NO_DISTRIBUTION, NORMAL, LOG_NORMAL, CUSTOM} +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/LogNormalDistributionGenerator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/LogNormalDistributionGenerator.java new file mode 100644 index 00000000000..1be1250a870 --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/LogNormalDistributionGenerator.java @@ -0,0 +1,35 @@ +package org.matsim.contrib.drt.estimator.impl.distribution; + +import java.util.Random; + +public class LogNormalDistributionGenerator implements DistributionGenerator { + private final Random random; + private final double mu; + private final double sigma; + private final double minValue; + + private final double maxValue; + + public LogNormalDistributionGenerator(long seed, double mu, double sigma) { + this.random = new Random(seed); + this.mu = mu; + this.sigma = sigma; + this.minValue = 0.5; + this.maxValue = 3; + } + + public LogNormalDistributionGenerator(long seed, double mu, double sigma, double minValue, double maxValue) { + this.random = new Random(seed); + this.mu = mu; + this.sigma = sigma; + this.minValue = minValue; + this.maxValue = maxValue; + } + + @Override + public double generateRandomValue() { + if (sigma == 0) + return Math.exp(mu); + return Math.max(Math.min(Math.exp(sigma * random.nextGaussian() + mu), maxValue), minValue); + } +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/NoDistribution.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/NoDistribution.java new file mode 100644 index 00000000000..0643c45ba53 --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/NoDistribution.java @@ -0,0 +1,8 @@ +package org.matsim.contrib.drt.estimator.impl.distribution; + +public class NoDistribution implements DistributionGenerator{ + @Override + public double generateRandomValue() { + return 1.0; + } +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/NormalDistributionGenerator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/NormalDistributionGenerator.java new file mode 100644 index 00000000000..5b6a23fc31a --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/NormalDistributionGenerator.java @@ -0,0 +1,34 @@ +package org.matsim.contrib.drt.estimator.impl.distribution; + +import java.util.Random; + +public class NormalDistributionGenerator implements DistributionGenerator{ + private final Random random; + private final double std; + + private final double minValue; + + private final double maxValue; + + public NormalDistributionGenerator(long seed, double std) { + this.random = new Random(seed); + this.std = std; + this.minValue = 0.5; + this.maxValue = 3.0; + } + + public NormalDistributionGenerator(long seed, double std, double minValue, double maxValue) { + this.random = new Random(seed); + this.std = std; + this.minValue = minValue; + this.maxValue = maxValue; + } + + @Override + public double generateRandomValue() { + double randomValue = 1 + random.nextGaussian() * std; + randomValue = Math.min(maxValue, randomValue); + randomValue = Math.max(minValue, randomValue); + return randomValue; + } +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/trip_estimation/ConstantRideDurationEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/trip_estimation/ConstantRideDurationEstimator.java new file mode 100644 index 00000000000..7c431fb39ba --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/trip_estimation/ConstantRideDurationEstimator.java @@ -0,0 +1,20 @@ +package org.matsim.contrib.drt.estimator.impl.trip_estimation; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.utils.misc.OptionalTime; + +public class ConstantRideDurationEstimator implements RideDurationEstimator { + private final double alpha; + private final double beta; + + public ConstantRideDurationEstimator(double alpha, double beta) { + this.alpha = alpha; + this.beta = beta; + } + + @Override + public double getEstimatedRideDuration(Id fromLinkId, Id toLinkId, OptionalTime departureTime, double directRideDuration) { + return alpha * directRideDuration + beta; + } +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/trip_estimation/RideDurationEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/trip_estimation/RideDurationEstimator.java new file mode 100644 index 00000000000..d19a4e9fa6c --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/trip_estimation/RideDurationEstimator.java @@ -0,0 +1,11 @@ +package org.matsim.contrib.drt.estimator.impl.trip_estimation; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.utils.collections.Tuple; +import org.matsim.core.utils.misc.OptionalTime; + +public interface RideDurationEstimator { + double getEstimatedRideDuration(Id fromLinkId, Id toLinkId, OptionalTime departureTime, double directTripDuration); + +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/ConstantWaitingTimeEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/ConstantWaitingTimeEstimator.java new file mode 100644 index 00000000000..1b2d18288d5 --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/ConstantWaitingTimeEstimator.java @@ -0,0 +1,18 @@ +package org.matsim.contrib.drt.estimator.impl.waiting_time_estimation; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.utils.misc.OptionalTime; + +public class ConstantWaitingTimeEstimator implements WaitingTimeEstimator { + private final double typicalWaitingTime; + + public ConstantWaitingTimeEstimator(double typicalWaitingTime) { + this.typicalWaitingTime = typicalWaitingTime; + } + + @Override + public double estimateWaitTime(Id fromLinkId, Id toLinkId, OptionalTime departureTime) { + return typicalWaitingTime; + } +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/ShapeFileBasedWaitingTimeEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/ShapeFileBasedWaitingTimeEstimator.java new file mode 100644 index 00000000000..32bcb03c8cd --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/ShapeFileBasedWaitingTimeEstimator.java @@ -0,0 +1,63 @@ +package org.matsim.contrib.drt.estimator.impl.waiting_time_estimation; + +import org.geotools.api.feature.simple.SimpleFeature; +import org.locationtech.jts.geom.Geometry; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.utils.geometry.geotools.MGC; +import org.matsim.core.utils.misc.OptionalTime; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ShapeFileBasedWaitingTimeEstimator implements WaitingTimeEstimator { + /** + * Typical waiting time. Due to the length limit of the attribute name, we have to use some abbreviate + */ + private final static String TYPICAL_WAITING_TIME_NAME = "typ_wt"; + private final Map, Double> typicalWaitingTimeForEachLink = new HashMap<>(); + /** + * The default typical waiting time. This value will be used for links that are not covered by any + * waiting time zone. The baseTypicalWaitingTime is usually larger than the typical waiting time + * in any waiting time zone. + */ + private final double baseTypicalWaitingTime; + + public ShapeFileBasedWaitingTimeEstimator(Network network, List features) { + baseTypicalWaitingTime = 1800; + initializeWaitingTimeMap(network, features); + } + + public ShapeFileBasedWaitingTimeEstimator(Network network, List features, double baseTypicalWaitingTime) { + this.baseTypicalWaitingTime = baseTypicalWaitingTime; + initializeWaitingTimeMap(network, features); + } + + private void initializeWaitingTimeMap(Network network, List features) { + for (Link link : network.getLinks().values()) { + if (!link.getAllowedModes().contains(TransportMode.car) && !link.getAllowedModes().contains(TransportMode.drt)) { + continue; + } + double minTypicalWaitingTime = baseTypicalWaitingTime; + for (SimpleFeature feature : features) { + Geometry geometry = (Geometry) feature.getDefaultGeometry(); + if (geometry.contains(MGC.coord2Point(link.getToNode().getCoord()))) { + // The link is located within the zone -> reduce typical waiting time if necessary + double typicalWaitingTimeForCurrentZone = (long) feature.getAttribute(TYPICAL_WAITING_TIME_NAME); + if (typicalWaitingTimeForCurrentZone < minTypicalWaitingTime) { + minTypicalWaitingTime = typicalWaitingTimeForCurrentZone; + } + } + } + typicalWaitingTimeForEachLink.put(link.getId(), minTypicalWaitingTime); + } + } + + @Override + public double estimateWaitTime(Id fromLinkId, Id toLinkId, OptionalTime departureTime) { + return typicalWaitingTimeForEachLink.get(fromLinkId); + } +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/WaitingTimeEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/WaitingTimeEstimator.java new file mode 100644 index 00000000000..8649cd88a2c --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/WaitingTimeEstimator.java @@ -0,0 +1,9 @@ +package org.matsim.contrib.drt.estimator.impl.waiting_time_estimation; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.utils.misc.OptionalTime; + +public interface WaitingTimeEstimator { + double estimateWaitTime(Id fromLinkId, Id toLinkId, OptionalTime departureTime); +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/DefaultUnplannedRequestInserter.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/DefaultUnplannedRequestInserter.java index 0f8443f0141..1854e93ffd1 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/DefaultUnplannedRequestInserter.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/DefaultUnplannedRequestInserter.java @@ -54,6 +54,7 @@ public class DefaultUnplannedRequestInserter implements UnplannedRequestInserter { private static final Logger log = LogManager.getLogger(DefaultUnplannedRequestInserter.class); public static final String NO_INSERTION_FOUND_CAUSE = "no_insertion_found"; + public static final String OFFER_REJECTED_CAUSE = "offer_rejected"; private final String mode; private final Fleet fleet; @@ -125,17 +126,7 @@ private void scheduleUnplannedRequest(DrtRequest req, Map, Vehic Optional best = insertionSearch.findBestInsertion(req, Collections.unmodifiableCollection(vehicleEntries.values())); if (best.isEmpty()) { - if (!insertionRetryQueue.tryAddFailedRequest(req, now)) { - eventsManager.processEvent( - new PassengerRequestRejectedEvent(now, mode, req.getId(), req.getPassengerIds(), - NO_INSERTION_FOUND_CAUSE)); - log.debug("No insertion found for drt request " - + req - + " with passenger ids=" - + req.getPassengerIds().stream().map(Object::toString).collect(Collectors.joining(",")) - + " fromLinkId=" - + req.getFromLink().getId()); - } + retryOrReject(req, now, NO_INSERTION_FOUND_CAUSE); } else { InsertionWithDetourData insertion = best.get(); @@ -144,26 +135,44 @@ private void scheduleUnplannedRequest(DrtRequest req, Map, Vehic insertion.detourTimeInfo.pickupDetourInfo.departureTime, insertion.detourTimeInfo.dropoffDetourInfo.arrivalTime); - var vehicle = insertion.insertion.vehicleEntry.vehicle; - var pickupDropoffTaskPair = insertionScheduler.scheduleRequest(acceptedRequest.get(), insertion); + if(acceptedRequest.isPresent()) { + var vehicle = insertion.insertion.vehicleEntry.vehicle; + var pickupDropoffTaskPair = insertionScheduler.scheduleRequest(acceptedRequest.get(), insertion); - VehicleEntry newVehicleEntry = vehicleEntryFactory.create(vehicle, now); - if (newVehicleEntry != null) { - vehicleEntries.put(vehicle.getId(), newVehicleEntry); - } else { - vehicleEntries.remove(vehicle.getId()); - } + VehicleEntry newVehicleEntry = vehicleEntryFactory.create(vehicle, now); + if (newVehicleEntry != null) { + vehicleEntries.put(vehicle.getId(), newVehicleEntry); + } else { + vehicleEntries.remove(vehicle.getId()); + } + + double expectedPickupTime = pickupDropoffTaskPair.pickupTask.getBeginTime(); + expectedPickupTime = Math.max(expectedPickupTime, acceptedRequest.get().getEarliestStartTime()); + expectedPickupTime += stopDurationProvider.calcPickupDuration(vehicle, req); - double expectedPickupTime = pickupDropoffTaskPair.pickupTask.getBeginTime(); - expectedPickupTime = Math.max(expectedPickupTime, acceptedRequest.get().getEarliestStartTime()); - expectedPickupTime += stopDurationProvider.calcPickupDuration(vehicle, req); + double expectedDropoffTime = pickupDropoffTaskPair.dropoffTask.getBeginTime(); + expectedDropoffTime += stopDurationProvider.calcDropoffDuration(vehicle, req); - double expectedDropoffTime = pickupDropoffTaskPair.dropoffTask.getBeginTime(); - expectedDropoffTime += stopDurationProvider.calcDropoffDuration(vehicle, req); + eventsManager.processEvent( + new PassengerRequestScheduledEvent(now, mode, req.getId(), req.getPassengerIds(), vehicle.getId(), + expectedPickupTime, expectedDropoffTime)); + } else { + retryOrReject(req, now, OFFER_REJECTED_CAUSE); + } + } + } + private void retryOrReject(DrtRequest req, double now, String cause) { + if (!insertionRetryQueue.tryAddFailedRequest(req, now)) { eventsManager.processEvent( - new PassengerRequestScheduledEvent(now, mode, req.getId(), req.getPassengerIds(), vehicle.getId(), - expectedPickupTime, expectedDropoffTime)); + new PassengerRequestRejectedEvent(now, mode, req.getId(), req.getPassengerIds(), + cause)); + log.debug("No insertion found for drt request " + + req + + " with passenger ids=" + + req.getPassengerIds().stream().map(Object::toString).collect(Collectors.joining(",")) + + " fromLinkId=" + + req.getFromLink().getId()); } } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java index ed79cd0bf9f..04d8df45161 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java @@ -9,9 +9,7 @@ import org.matsim.api.core.v01.events.handler.PersonStuckEventHandler; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; -import org.matsim.api.core.v01.population.Leg; -import org.matsim.api.core.v01.population.Person; -import org.matsim.api.core.v01.population.Plan; +import org.matsim.api.core.v01.population.*; import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; import org.matsim.contrib.drt.prebooking.unscheduler.RequestUnscheduler; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; @@ -21,10 +19,12 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.mobsim.framework.MobsimAgent; import org.matsim.core.mobsim.framework.MobsimAgent.State; +import org.matsim.core.mobsim.framework.MobsimPassengerAgent; import org.matsim.core.mobsim.framework.MobsimTimer; import org.matsim.core.mobsim.framework.events.MobsimAfterSimStepEvent; import org.matsim.core.mobsim.framework.listeners.MobsimAfterSimStepListener; import org.matsim.core.mobsim.qsim.InternalInterface; +import org.matsim.core.mobsim.qsim.agents.HasModifiablePlan; import org.matsim.core.mobsim.qsim.agents.WithinDayAgentUtils; import org.matsim.core.mobsim.qsim.interfaces.MobsimEngine; @@ -59,12 +59,16 @@ public class PrebookingManager implements MobsimEngine, MobsimAfterSimStepListen private final VrpOptimizer optimizer; private final RequestUnscheduler unscheduler; + private final boolean abortRejectedPrebookings; private final MobsimTimer mobsimTimer; + private InternalInterface internalInterface; + + public PrebookingManager(String mode, Network network, PassengerRequestCreator requestCreator, - VrpOptimizer optimizer, MobsimTimer mobsimTimer, PassengerRequestValidator requestValidator, - EventsManager eventsManager, RequestUnscheduler unscheduler) { + VrpOptimizer optimizer, MobsimTimer mobsimTimer, PassengerRequestValidator requestValidator, + EventsManager eventsManager, RequestUnscheduler unscheduler, boolean abortRejectedPrebookings) { this.network = network; this.mode = mode; this.requestCreator = requestCreator; @@ -74,6 +78,7 @@ public PrebookingManager(String mode, Network network, PassengerRequestCreator r this.mobsimTimer = mobsimTimer; this.eventsManager = eventsManager; this.unscheduler = unscheduler; + this.abortRejectedPrebookings = abortRejectedPrebookings; } // Functionality for ID management @@ -386,6 +391,22 @@ private void processRejections(double now) { } else { unscheduleUponVehicleAssignment.add(requestId); } + + if(abortRejectedPrebookings) { + for (Id passengerId : item.request.getPassengerIds()) { + MobsimAgent agent = internalInterface.getMobsim().getAgents().get(passengerId); + PlanElement planElement = WithinDayAgentUtils.getCurrentPlanElement(agent); + if(planElement instanceof Activity activity) { + activity.setEndTime(Double.POSITIVE_INFINITY); + activity.setMaximumDurationUndefined(); + ((HasModifiablePlan) agent).resetCaches(); + internalInterface.getMobsim().rescheduleActivityEnd(agent); + } + eventsManager.processEvent(new PersonStuckEvent(now, agent.getId(), agent.getCurrentLinkId(), + this.mode)); + internalInterface.getMobsim().getAgentCounter().incLost(); + } + } } } @@ -454,5 +475,6 @@ public void afterSim() { @Override public void setInternalInterface(InternalInterface internalInterface) { + this.internalInterface = internalInterface; } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingModeQSimModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingModeQSimModule.java index 19274c3fd8b..4ae7e1201a3 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingModeQSimModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingModeQSimModule.java @@ -59,7 +59,7 @@ protected void configureQSim() { MobsimTimer mobsimTimer = getter.get(MobsimTimer.class); return new PrebookingManager(getMode(), network, requestCreator, optimizer, mobsimTimer, requestValidator, - eventsManager, requestUnscheduler); + eventsManager, requestUnscheduler, prebookingParams.abortRejectedPrebookings); })).in(Singleton.class); addModalQSimComponentBinding().to(modalKey(PrebookingManager.class)); diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingParams.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingParams.java index fdf678bb272..4f1cdcb58e2 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingParams.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingParams.java @@ -38,4 +38,10 @@ public enum UnschedulingMode { @NotNull public UnschedulingMode unschedulingMode = UnschedulingMode.StopBased; + @Parameter + @Comment("Defines whether agents are set to stuck and abort when a prebooked request is rejected." + + "If false, prebooked agents will re-attempt to ride at their initially planned departure time." + + "Note that additional passenger events for submission, scheduling etc. will occur for re-attempts.") + public boolean abortRejectedPrebookings = true; + } \ No newline at end of file diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingStopActivity.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingStopActivity.java index fd81c1745f3..e55af9e76a5 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingStopActivity.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingStopActivity.java @@ -1,15 +1,15 @@ package org.matsim.contrib.drt.prebooking; -import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.PriorityQueue; import java.util.Queue; -import java.util.Set; import java.util.function.Supplier; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.IdMap; +import org.matsim.api.core.v01.IdSet; import org.matsim.api.core.v01.Identifiable; import org.matsim.api.core.v01.population.Person; import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; @@ -39,9 +39,13 @@ public class PrebookingStopActivity extends FirstLastSimStepDynActivity implemen private final Map, ? extends AcceptedDrtRequest> pickupRequests; private final Map, ? extends AcceptedDrtRequest> dropoffRequests; - private final IdMap enterTimes = new IdMap<>(Request.class); + private final Queue enterTimes = new PriorityQueue<>(); private final Queue leaveTimes = new PriorityQueue<>(); - private final Set> enteredRequests = new HashSet<>(); + + private final IdSet enteredRequests = new IdSet<>(Request.class); + + private final IdSet registeredPickups = new IdSet<>(Request.class); + private final IdMap expectedPickups = new IdMap<>(Request.class); private final PrebookingManager prebookingManager; private final PassengerHandler passengerHandler; @@ -93,7 +97,6 @@ private void initDropoffRequests(double now) { } private boolean updateDropoffRequests(double now) { - while (!leaveTimes.isEmpty() && leaveTimes.peek().time <= now) { Id requestId = leaveTimes.poll().id; passengerHandler.dropOffPassengers(driver, requestId, now); @@ -105,60 +108,94 @@ private boolean updateDropoffRequests(double now) { } private record QueuedRequest(Id id, double time) implements Comparable { - @Override public int compareTo(QueuedRequest o) { return Double.compare(this.time, o.time); } } + private int cachedPickupRequestsHash = -1; + private boolean updatePickupRequests(double now, boolean isFirstStep) { - var pickupIterator = pickupRequests.values().iterator(); - - while (pickupIterator.hasNext()) { - var request = pickupIterator.next(); - - if (!enteredRequests.contains(request.getId()) && !enterTimes.containsKey(request.getId())) { - // this is a new request that has been added after the activity has been created - // or that had not arrived yet - - if (passengerHandler.notifyWaitForPassengers(this, this.driver, request.getId())) { - // agent starts to enter - queuePickup(request, now); - } else if (now > request.getEarliestStartTime() && !isFirstStep) { - if (abandonVoter.abandonRequest(now, vehicle, request)) { - prebookingManager.abandon(request.getId()); - } + int pickupRequestsHash = pickupRequests.hashCode(); + + // part 1: check if the pickup list has been updated dynamically + + if (isFirstStep || pickupRequestsHash != cachedPickupRequestsHash) { + cachedPickupRequestsHash = pickupRequestsHash; + + // added requests + for (AcceptedDrtRequest request : pickupRequests.values()) { + if (!registeredPickups.contains(request.getId())) { + // in the first step, this is a standard pickup request, later this is a request that has been added after the activity has been created + expectedPickups.put(request.getId(), request); + registeredPickups.add(request.getId()); + } + } + + // removed requests (for instance via cancellation) + var expectedIterator = expectedPickups.iterator(); + while (expectedIterator.hasNext()) { + if (!pickupRequests.containsKey(expectedIterator.next().getId())) { + // a request has been removed from the list of expected pickups + expectedIterator.remove(); } } } + + // part 2: handle the requests that we expect but which have not arrived yet + + var expectedIterator = expectedPickups.values().iterator(); + while (expectedIterator.hasNext()) { + AcceptedDrtRequest request = expectedIterator.next(); + + if (passengerHandler.notifyWaitForPassengers(this, this.driver, request.getId())) { + // agent starts to enter + queuePickup(request, now); + expectedIterator.remove(); + } else if (now > request.getEarliestStartTime() && !isFirstStep) { + if (abandonVoter.abandonRequest(now, vehicle, request)) { + // abandon the request, but not in the first time step for the sake of event timing + prebookingManager.abandon(request.getId()); + expectedIterator.remove(); + } + } + } + + // part 3: handle the requests that are currently entering the vehicle - var enterIterator = enterTimes.entrySet().iterator(); + var enterIterator = enterTimes.iterator(); + + // logic is as follows: + // - let people enter in the order at which they arrived + their interaction time + // - but in case there is no capacity (others still disembarking) they need to wait while (enterIterator.hasNext()) { var entry = enterIterator.next(); int availableCapacity = vehicle.getCapacity() - onboard; - if (entry.getValue() <= now) { - int requiredCapacity = pickupRequests.get(entry.getKey()).getPassengerCount(); + if (entry.time <= now) { + int requiredCapacity = pickupRequests.get(entry.id).getPassengerCount(); if (requiredCapacity <= availableCapacity) { // let agent enter now - Verify.verify(passengerHandler.tryPickUpPassengers(this, driver, entry.getKey(), now)); - enteredRequests.add(entry.getKey()); + Verify.verify(passengerHandler.tryPickUpPassengers(this, driver, entry.id, now)); + enteredRequests.add(entry.id); onboard += requiredCapacity; enterIterator.remove(); } + } else { + break; } } - return enterTimes.size() == 0 && pickupRequests.size() == enteredRequests.size(); + return expectedPickups.size() == 0 && pickupRequests.size() == enteredRequests.size(); } private void queuePickup(AcceptedDrtRequest request, double now) { prebookingManager.notifyPickup(now, request); double enterTime = now + stopDurationProvider.calcPickupDuration(vehicle, request.getRequest()); - enterTimes.put(request.getId(), enterTime); + enterTimes.add(new QueuedRequest(request.getId(), enterTime)); } @Override @@ -169,7 +206,10 @@ protected void simStep(double now) { @Override public void notifyPassengersAreReadyForDeparture(List passengers, double now) { var request = getRequestForPassengers(passengers.stream().map(Identifiable::getId).toList()); - queuePickup(request, now); + if(expectedPickups.containsKey(request.getId())) { + queuePickup(request, now); + expectedPickups.remove(request.getId()); + } } private AcceptedDrtRequest getRequestForPassengers(List> passengerIds) { diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java index 8b3755ba082..5ef8ea8f31a 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java @@ -24,6 +24,7 @@ import java.util.List; +import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.contrib.drt.optimizer.VehicleEntry; import org.matsim.contrib.drt.optimizer.Waypoint; @@ -37,6 +38,7 @@ import org.matsim.contrib.drt.stops.StopTimeCalculator; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.Fleet; +import org.matsim.contrib.dvrp.path.DivertedVrpPath; import org.matsim.contrib.dvrp.path.VrpPathWithTravelData; import org.matsim.contrib.dvrp.path.VrpPaths; import org.matsim.contrib.dvrp.schedule.DriveTask; @@ -65,9 +67,9 @@ public class DefaultRequestInsertionScheduler implements RequestInsertionSchedul private final StopTimeCalculator stopTimeCalculator; private final boolean scheduleWaitBeforeDrive; - public DefaultRequestInsertionScheduler(Fleet fleet, MobsimTimer timer, - TravelTime travelTime, ScheduleTimingUpdater scheduleTimingUpdater, DrtTaskFactory taskFactory, - StopTimeCalculator stopTimeCalculator, boolean scheduleWaitBeforeDrive) { + public DefaultRequestInsertionScheduler(Fleet fleet, MobsimTimer timer, TravelTime travelTime, + ScheduleTimingUpdater scheduleTimingUpdater, DrtTaskFactory taskFactory, + StopTimeCalculator stopTimeCalculator, boolean scheduleWaitBeforeDrive) { this.timer = timer; this.travelTime = travelTime; this.scheduleTimingUpdater = scheduleTimingUpdater; @@ -128,8 +130,7 @@ private void verifyConstraints(InsertionWithDetourData insertion) { Schedule schedule = insertion.insertion.vehicleEntry.vehicle.getSchedule(); for (Task task : schedule.getTasks()) { - if (task instanceof DrtStopTask) { - DrtStopTask stopTask = (DrtStopTask) task; + if (task instanceof DrtStopTask stopTask) { for (AcceptedDrtRequest request : stopTask.getPickupRequests().values()) { Verify.verify(stopTask.getEndTime() <= request.getLatestStartTime()); @@ -144,7 +145,7 @@ private void verifyConstraints(InsertionWithDetourData insertion) { } private void verifyStructure(Schedule schedule) { - boolean previousDrive = false; + DriveTask previousDrive = null; int startIndex = schedule.getStatus().equals(ScheduleStatus.STARTED) ? schedule.getCurrentTask().getTaskIdx() : 0; @@ -152,11 +153,18 @@ private void verifyStructure(Schedule schedule) { for (int index = startIndex; index < schedule.getTaskCount(); index++) { Task task = schedule.getTasks().get(index); - if (task instanceof DriveTask) { - Verify.verify(!previousDrive); - previousDrive = true; + if (task instanceof DriveTask driveTask) { + if(previousDrive != null) { + Verify.verify(previousDrive.getPath() instanceof DivertedVrpPath, + "The first of two subsequent drive tasks has to be a diverted path."); + Id firstEnd = previousDrive.getPath().getToLink().getId(); + Id secondStart = driveTask.getPath().getFromLink().getId(); + Verify.verify(firstEnd.equals(secondStart), + String.format("Subsequent drive tasks are not connected link %s !=> %s", firstEnd.toString(), secondStart.toString())); + } + previousDrive = driveTask; } else { - previousDrive = false; + previousDrive = null; } } } @@ -211,12 +219,16 @@ private DrtStopTask insertPickup(AcceptedDrtRequest request, InsertionWithDetour beforePickupTask = insertWait(vehicleEntry.vehicle, currentTask, dropoffIdx); } } + if(!stops.isEmpty() && stops.size() + 1 > pickupIdx) { + //there is an existing stop which was scheduled earlier and was not the destination of the already diverted drive task + removeBetween(schedule, beforePickupTask, stops.get(pickupIdx).task); + } } else { // insert pickup after an existing stop/stay task StayTask stayTask = null; DrtStopTask stopTask = null; if (pickupIdx == 0) { if (scheduleStatus == ScheduleStatus.PLANNED) {// PLANNED schedule - stayTask = (StayTask)schedule.getTasks().get(0); + stayTask = (StayTask)schedule.getTasks().getFirst(); stayTask.setEndTime(stayTask.getBeginTime());// could get later removed with ScheduleTimingUpdater } else if (STAY.isBaseTypeOf(currentTask)) { stayTask = (StayTask)currentTask; // ongoing stay task @@ -307,7 +319,11 @@ private DrtStopTask insertPickup(AcceptedDrtRequest request, InsertionWithDetour double nextBeginTime = pickupIdx == dropoffIdx ? // pickupStopTask.getEndTime() : // asap - stops.get(pickupIdx).task.getBeginTime(); // as planned + stops.get(pickupIdx).task.getPickupRequests().values() + .stream() + .mapToDouble(AcceptedDrtRequest::getEarliestStartTime) + .min() + .orElse(pickupStopTask.getEndTime()); if (request.getFromLink() == toLink) { // prebooking case when we are already at the stop location, but next stop task happens in the future @@ -340,7 +356,7 @@ private DrtStopTask insertPickup(AcceptedDrtRequest request, InsertionWithDetour } private DrtStopTask insertDropoff(AcceptedDrtRequest request, InsertionWithDetourData insertionWithDetourData, - DrtStopTask pickupTask) { + DrtStopTask pickupTask) { final double now = timer.getTimeOfDay(); var insertion = insertionWithDetourData.insertion; VehicleEntry vehicleEntry = insertion.vehicleEntry; @@ -422,8 +438,13 @@ private DrtStopTask insertDropoff(AcceptedDrtRequest request, InsertionWithDetou afterDropoffTask.getTaskIdx() + 1, afterDropoffTask.getEndTime()); } else { // may want to wait here or after driving before starting next stop + double earliestArrivalTime = stops.get(dropoffIdx).task.getPickupRequests().values() + .stream() + .mapToDouble(AcceptedDrtRequest::getEarliestStartTime) + .min() + .orElse(dropoffStopTask.getEndTime()); Task afterDropoffTask = insertDriveWithWait(vehicleEntry.vehicle, dropoffStopTask, vrpPath, - stops.get(dropoffIdx).task.getBeginTime()); + earliestArrivalTime); scheduleTimingUpdater.updateTimingsStartingFromTaskIdx(vehicleEntry.vehicle, afterDropoffTask.getTaskIdx() + 1, afterDropoffTask.getEndTime()); @@ -506,7 +527,7 @@ private Task insertDriveWithWait(DvrpVehicle vehicle, Task departureTask, VrpPat Task driveTask = taskFactory.createDriveTask(vehicle, path, DrtDriveTask.TYPE); schedule.addTask(leadingTask.getTaskIdx() + 1, driveTask); - if (driveTask.getEndTime() < latestArrivalTime) { + if (driveTask.getEndTime() < latestArrivalTime && !scheduleWaitBeforeDrive) { DrtStayTask waitTask = taskFactory.createStayTask(vehicle, driveTask.getEndTime(), latestArrivalTime, path.getToLink()); schedule.addTask(driveTask.getTaskIdx() + 1, waitTask); diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/estimator/DrtEstimateAndTeleportTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/estimator/DrtEstimateAndTeleportTest.java new file mode 100644 index 00000000000..cafd39170b3 --- /dev/null +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/estimator/DrtEstimateAndTeleportTest.java @@ -0,0 +1,59 @@ +package org.matsim.contrib.drt.estimator; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.contrib.common.zones.systems.grid.square.SquareGridZoneSystemParams; +import org.matsim.contrib.drt.estimator.impl.DirectTripBasedDrtEstimator; +import org.matsim.contrib.drt.estimator.impl.distribution.NormalDistributionGenerator; +import org.matsim.contrib.drt.estimator.impl.trip_estimation.ConstantRideDurationEstimator; +import org.matsim.contrib.drt.estimator.impl.waiting_time_estimation.ConstantWaitingTimeEstimator; +import org.matsim.contrib.drt.run.DrtConfigGroup; +import org.matsim.contrib.drt.run.DrtControlerCreator; +import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; +import org.matsim.contrib.dvrp.run.DvrpConfigGroup; +import org.matsim.contrib.zone.skims.DvrpTravelTimeMatrixParams; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controler; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vis.otfvis.OTFVisConfigGroup; + +import java.net.URL; + +public class DrtEstimateAndTeleportTest { + @RegisterExtension + public MatsimTestUtils utils = new MatsimTestUtils(); + + @Test + public void testDrtEstimateAndTeleport() { + URL configUrl = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("mielec"), "mielec_drt_config.xml"); + + DvrpConfigGroup dvrpConfig = new DvrpConfigGroup(); + DvrpTravelTimeMatrixParams matrixParams = dvrpConfig.getTravelTimeMatrixParams(); + matrixParams.addParameterSet(matrixParams.createParameterSet(SquareGridZoneSystemParams.SET_NAME)); + + Config config = ConfigUtils.loadConfig(configUrl, new MultiModeDrtConfigGroup(), dvrpConfig, + new OTFVisConfigGroup()); + DrtConfigGroup drtConfigGroup = DrtConfigGroup.getSingleModeDrtConfig(config); + drtConfigGroup.simulationType = DrtConfigGroup.SimulationType.estimateAndTeleport; + + Controler controler = DrtControlerCreator.createControler(config, false); + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + DrtEstimatorModule.bindEstimator(binder(), drtConfigGroup.mode).toInstance( + new DirectTripBasedDrtEstimator.Builder() + .setWaitingTimeEstimator(new ConstantWaitingTimeEstimator(300)) + .setWaitingTimeDistributionGenerator(new NormalDistributionGenerator(1, 0.4)) + .setRideDurationEstimator(new ConstantRideDurationEstimator(1.25, 300)) + .setRideDurationDistributionGenerator(new NormalDistributionGenerator(2, 0.3)) + .build() + ); + } + }); + controler.run(); + } +} diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java index 0b2adb16db2..0291899bc1d 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java @@ -26,9 +26,7 @@ import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -37,6 +35,10 @@ import org.matsim.contrib.drt.optimizer.DrtRequestInsertionRetryParams; import org.matsim.contrib.drt.optimizer.insertion.repeatedselective.RepeatedSelectiveInsertionSearchParams; import org.matsim.contrib.drt.optimizer.insertion.selective.SelectiveInsertionSearchParams; +import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; +import org.matsim.contrib.drt.passenger.DefaultOfferAcceptor; +import org.matsim.contrib.drt.passenger.DrtOfferAcceptor; +import org.matsim.contrib.drt.passenger.DrtRequest; import org.matsim.contrib.drt.prebooking.PrebookingParams; import org.matsim.contrib.drt.prebooking.logic.ProbabilityBasedPrebookingLogic; import org.matsim.contrib.drt.run.DrtConfigGroup; @@ -53,6 +55,7 @@ import org.matsim.contrib.dvrp.passenger.PassengerRequestScheduledEvent; import org.matsim.contrib.dvrp.passenger.PassengerRequestScheduledEventHandler; import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; +import org.matsim.contrib.dvrp.run.AbstractDvrpModeQSimModule; import org.matsim.contrib.dvrp.run.DvrpConfigGroup; import org.matsim.contrib.zone.skims.DvrpTravelTimeMatrixParams; import org.matsim.core.config.Config; @@ -60,6 +63,7 @@ import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; @@ -366,7 +370,9 @@ void testRunDrtWithPrebooking() { config.controller().setOutputDirectory(utils.getOutputDirectory()); DrtConfigGroup drtConfig = DrtConfigGroup.getSingleModeDrtConfig(config); - drtConfig.addParameterSet(new PrebookingParams()); + PrebookingParams prebookingParams = new PrebookingParams(); + prebookingParams.abortRejectedPrebookings = false; + drtConfig.addParameterSet(prebookingParams); Controler controller = DrtControlerCreator.createControler(config, false); ProbabilityBasedPrebookingLogic.install(controller, drtConfig, 0.5, 4.0 * 3600.0); @@ -384,7 +390,7 @@ void testRunDrtWithPrebooking() { var expectedStats = Stats.newBuilder() .rejectionRate(0.04) .rejections(14) - .waitAverage(232.47) + .waitAverage(232.48) .inVehicleTravelTimeMean(389.16) .totalTravelTimeMean(621.63) .build(); @@ -392,6 +398,39 @@ void testRunDrtWithPrebooking() { verifyDrtCustomerStatsCloseToExpectedStats(utils.getOutputDirectory(), expectedStats); } + + @Test + void testRunDrtOfferRejectionExample() { + Id.resetCaches(); + URL configUrl = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("mielec"), + "mielec_stop_based_drt_config.xml"); + Config config = ConfigUtils.loadConfig(configUrl, new MultiModeDrtConfigGroup(), new DvrpConfigGroup(), + new OTFVisConfigGroup()); + + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + + Controler controller = DrtControlerCreator.createControler(config, false); + controller.addOverridingQSimModule(new AbstractDvrpModeQSimModule("drt") { + @Override + protected void configureQSim() { + bindModal(DrtOfferAcceptor.class).toProvider(modalProvider(getter -> new ProbabilisticOfferAcceptor())); + } + }); + controller.run(); + + + var expectedStats = Stats.newBuilder() + .rejectionRate(0.46) + .rejections(174.0) + .waitAverage(222.66) + .inVehicleTravelTimeMean(369.74) + .totalTravelTimeMean(592.4) + .build(); + + verifyDrtCustomerStatsCloseToExpectedStats(utils.getOutputDirectory(), expectedStats); + } + /** * Early warning system: if customer stats vary more than the defined percentage above or below the expected values * then the following unit tests will fail. This is meant to serve as a red flag. @@ -536,4 +575,20 @@ public void install() { }); } } + + private static class ProbabilisticOfferAcceptor implements DrtOfferAcceptor { + + private final DefaultOfferAcceptor delegate = new DefaultOfferAcceptor(); + + private final Random random = new Random(123); + + @Override + public Optional acceptDrtOffer(DrtRequest request, double departureTime, double arrivalTime) { + if (random.nextBoolean()) { + return Optional.empty(); + } else { + return delegate.acceptDrtOffer(request, departureTime, arrivalTime); + } + } + } } diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionSchedulerTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionSchedulerTest.java new file mode 100644 index 00000000000..b1924ad36b4 --- /dev/null +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionSchedulerTest.java @@ -0,0 +1,288 @@ +package org.matsim.contrib.drt.scheduler; + +import com.google.common.base.Verify; +import com.google.common.collect.ImmutableList; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.drt.optimizer.VehicleEntry; +import org.matsim.contrib.drt.optimizer.Waypoint; +import org.matsim.contrib.drt.optimizer.insertion.InsertionDetourTimeCalculator; +import org.matsim.contrib.drt.optimizer.insertion.InsertionGenerator; +import org.matsim.contrib.drt.optimizer.insertion.InsertionWithDetourData; +import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; +import org.matsim.contrib.drt.passenger.DrtRequest; +import org.matsim.contrib.drt.run.examples.RunDrtExampleIT; +import org.matsim.contrib.drt.schedule.*; +import org.matsim.contrib.drt.stops.MinimumStopDurationAdapter; +import org.matsim.contrib.drt.stops.PrebookingStopTimeCalculator; +import org.matsim.contrib.drt.stops.StaticPassengerStopDurationProvider; +import org.matsim.contrib.dvrp.fleet.*; +import org.matsim.contrib.dvrp.optimizer.Request; +import org.matsim.contrib.dvrp.path.OneToManyPathSearch; +import org.matsim.contrib.dvrp.path.VrpPathWithTravelData; +import org.matsim.contrib.dvrp.path.VrpPaths; +import org.matsim.contrib.dvrp.schedule.*; +import org.matsim.core.mobsim.framework.MobsimTimer; +import org.matsim.core.router.util.LeastCostPathCalculator; +import org.matsim.core.router.util.TravelTime; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.testcases.fakes.FakeLink; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.matsim.contrib.dvrp.path.VrpPaths.NODE_TRANSITION_TIME; + +/** + * @author nkuehnel / MOIA + */ +public class DefaultRequestInsertionSchedulerTest { + + @RegisterExtension + public MatsimTestUtils utils = new MatsimTestUtils(); + + public static final TravelTime TRAVEL_TIME = (link, time, person, vehicle) -> 10 - NODE_TRANSITION_TIME; + public static final double STOP_DURATION = 60.; + + private final static double DRIVE_TIME = 10.; + + public static final double CURRENT_TIME = 10; + public static final double R1_PU_TIME = CURRENT_TIME + DRIVE_TIME + STOP_DURATION; + public static final double R1_DO_TIME = R1_PU_TIME + DRIVE_TIME; + + //existing on-board request + public static final double R2_PU_TIME = 0.; + public static final double R2_DO_TIME = R1_DO_TIME + STOP_DURATION + DRIVE_TIME ; + + public static final int R3_PU_TIME = 20; + public static final int R3_DO_TIME = 30; + + public static final double ALLOWED_DETOUR = STOP_DURATION + 2 * DRIVE_TIME; + + public static final Id V_1_ID = Id.create("v1", DvrpVehicle.class); + + private final Link from1 = link("from1"); + private final Link to1 = link("to1"); + + private final Link from2 = link("from2"); + private final Link to2 = link("to2"); + private final Link from3 = from1; + private final Link to3 = link("to3"); + private final DrtRequest existingRequest1 = request("r1", from1, to1, 0., R1_DO_TIME + ALLOWED_DETOUR, R1_PU_TIME, R1_PU_TIME); + private final DrtRequest existingRequest2 = request("r2", from2, to2, 0., R2_DO_TIME + ALLOWED_DETOUR, R2_PU_TIME, R2_PU_TIME); + private final DrtRequest newRequest = request("r3", from3, to3, CURRENT_TIME, R3_DO_TIME + ALLOWED_DETOUR, R3_PU_TIME, R3_PU_TIME); + + private static final String mode = "DRT_MODE"; + + + @Test + public void testInsertion() { + Link startLink = link("start"); + FleetSpecificationImpl fleetSpecification = new FleetSpecificationImpl(); + fleetSpecification.addVehicleSpecification(ImmutableDvrpVehicleSpecification.newBuilder() + .id(V_1_ID) + .startLinkId(startLink.getId()) + .capacity(6) + .serviceBeginTime(0) + .serviceEndTime(1000) + .build() + ); + + Fleet fleet = Fleets.createDefaultFleet(fleetSpecification, dvrpVehicleSpecification -> startLink); + MobsimTimer timer = new MobsimTimer(1); + timer.setTime(CURRENT_TIME); + DefaultRequestInsertionScheduler insertionScheduler = getDefaultRequestInsertionScheduler(fleet, timer); + + + DvrpVehicle vehicle = fleet.getVehicles().get(V_1_ID); + + // vehicle schedule + Task task = vehicle.getSchedule().nextTask(); + + vehicle.getSchedule().getCurrentTask().setEndTime(CURRENT_TIME); + LeastCostPathCalculator.Path path = new LeastCostPathCalculator.Path(null, List.of(), 0., 0); + VrpPathWithTravelData vrpPath = VrpPaths.createPath(startLink, existingRequest1.getFromLink(), CURRENT_TIME, path, TRAVEL_TIME); + vehicle.getSchedule().addTask(new DrtDriveTask(vrpPath, DrtDriveTask.TYPE)); + + DefaultDrtStopTask stopTask0 = new DefaultDrtStopTask(R1_PU_TIME - STOP_DURATION, R1_PU_TIME, from1); + AcceptedDrtRequest acceptedExistingRequest = AcceptedDrtRequest.createFromOriginalRequest(existingRequest1); + stopTask0.addPickupRequest(acceptedExistingRequest); + vehicle.getSchedule().addTask(stopTask0); + + VrpPathWithTravelData vrpPath2 = VrpPaths.createPath(existingRequest1.getFromLink(), existingRequest1.getToLink(), stopTask0.getEndTime(), path, TRAVEL_TIME); + vehicle.getSchedule().addTask(new DrtDriveTask(vrpPath2, DrtDriveTask.TYPE)); + + DefaultDrtStopTask stopTask1 = new DefaultDrtStopTask(R1_DO_TIME, R1_DO_TIME + STOP_DURATION, to1); + stopTask1.addDropoffRequest(acceptedExistingRequest); + vehicle.getSchedule().addTask(stopTask1); + + LeastCostPathCalculator.Path longPath = new LeastCostPathCalculator.Path(null, List.of(), 200, 0); + VrpPathWithTravelData vrpPath3 = VrpPaths.createPath(existingRequest1.getToLink(), existingRequest2.getToLink(), stopTask1.getEndTime(), longPath, TRAVEL_TIME); + vehicle.getSchedule().addTask(new DrtDriveTask(vrpPath3, DrtDriveTask.TYPE)); + + DefaultDrtStopTask stopTask2 = new DefaultDrtStopTask(stopTask1.getEndTime() + longPath.travelTime + 10., stopTask1.getEndTime() + longPath.travelTime + STOP_DURATION, to2); + AcceptedDrtRequest acceptedExistingRequest2 = AcceptedDrtRequest.createFromOriginalRequest(existingRequest2); + stopTask2.addDropoffRequest(acceptedExistingRequest2); + vehicle.getSchedule().addTask(stopTask2); + + + // vehicle entry + Waypoint.Start start = start(null, CURRENT_TIME, startLink, 1);//not a STOP -> pickup cannot be appended + Waypoint.Stop stop0 = stop(stopTask0, 2); + Waypoint.Stop stop1 = stop(stopTask1, 1); + Waypoint.Stop stop2 = stop(stopTask2, 0); + var vehicleEntry = entry(vehicle, start, stop0, stop1, stop2); + + InsertionWithDetourData.InsertionDetourData detour = detourData(0, 10, 10, 10.); + InsertionDetourTimeCalculator.DetourTimeInfo detourTimeInfo = detourTimeInfo(); + InsertionWithDetourData insertion = insertion(vehicleEntry, 1, 2, detour, newRequest, + detourTimeInfo); + + RequestInsertionScheduler.PickupDropoffTaskPair pickupDropoffTaskPair = + insertionScheduler.scheduleRequest(AcceptedDrtRequest.createFromOriginalRequest(newRequest), insertion); + + ScheduleInfo actualScheduleInfo = getScheduleInfo(vehicle.getSchedule()); + ScheduleInfo expectedScheduleInfo = ScheduleInfo.newBuilder() + .addTask(new ScheduleBuilder.TaskInfo(0, 0, 10, Task.TaskStatus.STARTED, + DrtStayTask.TYPE, Set.of(), Set.of())) + .addTask(new ScheduleBuilder.TaskInfo(1, 10, 20, Task.TaskStatus.PLANNED, + DrtDriveTask.TYPE, Set.of(), Set.of())) + .addTask(new ScheduleBuilder.TaskInfo(2, 20, 80, Task.TaskStatus.PLANNED, + DefaultDrtStopTask.TYPE, Set.of(existingRequest1.getId(), newRequest.getId()), Set.of())) + .addTask(new ScheduleBuilder.TaskInfo(3, 80, 90, Task.TaskStatus.PLANNED, + DrtDriveTask.TYPE, Set.of(), Set.of())) + .addTask(new ScheduleBuilder.TaskInfo(4, 90, 150, Task.TaskStatus.PLANNED, + DefaultDrtStopTask.TYPE, Set.of(), Set.of(existingRequest1.getId()))) + .addTask(new ScheduleBuilder.TaskInfo(5, 150, 170, Task.TaskStatus.PLANNED, + DrtDriveTask.TYPE, Set.of(), Set.of())) + .addTask(new ScheduleBuilder.TaskInfo(6, 170, 230, Task.TaskStatus.PLANNED, + DefaultDrtStopTask.TYPE, Set.of(), Set.of(newRequest.getId()))) + .addTask(new ScheduleBuilder.TaskInfo(7, 230, 250, Task.TaskStatus.PLANNED, + DrtDriveTask.TYPE, Set.of(), Set.of())) + .addTask(new ScheduleBuilder.TaskInfo(8, 250, 310, Task.TaskStatus.PLANNED, + DefaultDrtStopTask.TYPE, Set.of(), Set.of(existingRequest2.getId()))) + .build(); + + compareTwoSchedules(actualScheduleInfo, expectedScheduleInfo); + + + } + + private InsertionDetourTimeCalculator.DetourTimeInfo detourTimeInfo() { + return new InsertionDetourTimeCalculator.DetourTimeInfo( + new InsertionDetourTimeCalculator.PickupDetourInfo(R1_PU_TIME + STOP_DURATION, 0.), + new InsertionDetourTimeCalculator.DropoffDetourInfo(R1_PU_TIME + STOP_DURATION + DRIVE_TIME, 20.) + ); + } + + private static DefaultRequestInsertionScheduler getDefaultRequestInsertionScheduler(Fleet fleet, MobsimTimer timer) { + MinimumStopDurationAdapter stopDuration = new MinimumStopDurationAdapter(new PrebookingStopTimeCalculator(StaticPassengerStopDurationProvider.of(STOP_DURATION, 0.0)), 60.); + ScheduleTimingUpdater scheduleTimingUpdater = new ScheduleTimingUpdater(timer, new DrtStayTaskEndTimeCalculator(stopDuration)); + DefaultRequestInsertionScheduler insertionScheduler = new DefaultRequestInsertionScheduler(fleet, timer, TRAVEL_TIME, scheduleTimingUpdater, + new DrtTaskFactoryImpl(), stopDuration, true); + return insertionScheduler; + } + + private InsertionWithDetourData.InsertionDetourData detourData(double toPickupTT, double fromPickupTT, double toDropoffTT, + double fromDropoffTT) { + var toPickupDetour = new OneToManyPathSearch.PathData(new LeastCostPathCalculator.Path(null, List.of(), toPickupTT, 0), 0); + var fromPickupDetour = new OneToManyPathSearch.PathData(new LeastCostPathCalculator.Path(null, List.of(), fromPickupTT, 0), 0); + var toDropoffDetour = new OneToManyPathSearch.PathData(new LeastCostPathCalculator.Path(null, List.of(), toDropoffTT, 0), 0); + var fromDropoffDetour = new OneToManyPathSearch.PathData(new LeastCostPathCalculator.Path(null, List.of(), fromDropoffTT, 0), 0); + return new InsertionWithDetourData.InsertionDetourData(toPickupDetour, fromPickupDetour, toDropoffDetour, fromDropoffDetour); + } + + private InsertionWithDetourData insertion(VehicleEntry entry, int pickupIdx, int dropoffIdx, + InsertionWithDetourData.InsertionDetourData detour, + DrtRequest drtRequest, InsertionDetourTimeCalculator.DetourTimeInfo detourTimeInfo) { + return new InsertionWithDetourData( + new InsertionGenerator.Insertion(drtRequest, entry, pickupIdx, dropoffIdx), + detour, + detourTimeInfo + ); + } + + + private VehicleEntry entry(DvrpVehicle vehicle, Waypoint.Start start, Waypoint.Stop... stops) { + List precedingStayTimes = Collections.nCopies(stops.length, 0.0); + return new VehicleEntry(vehicle, start, ImmutableList.copyOf(stops), null, precedingStayTimes, 0); + } + + private Waypoint.Start start(Task task, double time, Link link, int occupancy) { + return new Waypoint.Start(task, link, time, occupancy); + } + + private Waypoint.Stop stop(DefaultDrtStopTask stopTask, int outgoingOccupancy) { + return new Waypoint.Stop(stopTask, outgoingOccupancy); + } + + + private DrtRequest request(String id, Link fromLink, Link toLink, double submissionTime, + double latestArrivalTime, double earliestStartTime, double latestStartTime) { + return DrtRequest.newBuilder() + .id(Id.create(id, Request.class)) + .passengerIds(List.of(Id.createPersonId(id))) + .submissionTime(submissionTime) + .latestArrivalTime(latestArrivalTime) + .latestStartTime(latestStartTime) + .earliestStartTime(earliestStartTime) + .fromLink(fromLink) + .toLink(toLink) + .mode(mode) + .build(); + } + + private Link link(String id) { + return new FakeLink(Id.createLinkId(id)); + } + + + + private record ScheduleInfo(List taskInfos) { + public static ScheduleBuilder newBuilder() { + return new ScheduleBuilder(); + } + } + + private static ScheduleInfo getScheduleInfo(Schedule schedule) { + ScheduleBuilder scheduleBuilder = ScheduleInfo.newBuilder(); + for (Task task : schedule.getTasks()) { + scheduleBuilder.addTask(new ScheduleBuilder.TaskInfo(task.getTaskIdx(), task.getBeginTime(), + task.getEndTime(), task.getStatus(), task.getTaskType(), + task instanceof DrtStopTask ? ((DrtStopTask) task).getPickupRequests().keySet(): Set.of(), + task instanceof DrtStopTask ? ((DrtStopTask) task).getDropoffRequests().keySet(): Set.of() + )); + } + return scheduleBuilder.build(); + } + + + private static class ScheduleBuilder { + + private record TaskInfo(int taskIdx, double beginTime, double endTime, Task.TaskStatus status, + Task.TaskType taskType, Set> puRequests, Set> doRequests) {} + + private ScheduleBuilder(){} + + + private final List taskInfos = new ArrayList<>(); + + public ScheduleBuilder addTask(TaskInfo taskInfo) { + taskInfos.add(taskInfo.taskIdx, taskInfo); + return this; + } + + public ScheduleInfo build() { + return new ScheduleInfo(taskInfos); + } + } + + private static void compareTwoSchedules(ScheduleInfo actualScheduleInfo, ScheduleInfo expectedScheduleInfo) { + assertThat(actualScheduleInfo).usingRecursiveComparison().isEqualTo(expectedScheduleInfo); + } +} \ No newline at end of file diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/teleportation/DrtTeleportationWithModeChoiceTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/teleportation/DrtTeleportationWithModeChoiceTest.java index effd09b64ac..0e035acb518 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/teleportation/DrtTeleportationWithModeChoiceTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/teleportation/DrtTeleportationWithModeChoiceTest.java @@ -6,7 +6,6 @@ import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.network.Network; import org.matsim.contrib.drt.estimator.DrtEstimator; -import org.matsim.contrib.drt.estimator.impl.DetourBasedDrtEstimator; import org.matsim.contrib.drt.estimator.impl.EuclideanDistanceBasedDrtEstimator; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.run.DrtControlerCreator; @@ -72,8 +71,6 @@ void testModeChoice() { controler.addOverridingModule(new AbstractDvrpModeModule(drtConfigGroup.mode) { @Override public void install() { -// bindModal(DrtEstimator.class).toInstance(DetourBasedDrtEstimator.normalDistributed(1.2, 32, -// 0.3, 300, 0.4)); bindModal(DrtEstimator.class).toProvider(modalProvider(getter -> new EuclideanDistanceBasedDrtEstimator(getter.getModal(Network.class), 2.0, 0.1577493, 103.0972273, 120, 0.3, -0.1, 0.28))); diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/passenger/DefaultPassengerEngine.java b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/passenger/DefaultPassengerEngine.java index 7406ceaa359..96571f584da 100644 --- a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/passenger/DefaultPassengerEngine.java +++ b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/passenger/DefaultPassengerEngine.java @@ -153,7 +153,7 @@ private void handleGroupDepartures(double now) { private void handleDepartureImpl(double now, List group) { List> groupIds = group.stream().map(Identifiable::getId).toList(); - MobsimPassengerAgent representative = group.get(0); + MobsimPassengerAgent representative = group.getFirst(); Id fromLinkId = representative.getCurrentLinkId(); Id toLinkId = representative.getDestinationLinkId(); diff --git a/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/router/DiversionTest.java b/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/router/DiversionTest.java index ed2c0c27587..16e1f5be09f 100644 --- a/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/router/DiversionTest.java +++ b/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/router/DiversionTest.java @@ -51,6 +51,7 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.config.groups.QSimConfigGroup.StarttimeInterpretation; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.Controler; import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; import org.matsim.core.mobsim.framework.MobsimTimer; @@ -124,7 +125,7 @@ void testRepeatedSameDestinationDiversions() { { /* Create some necessary configuration for the test */ - + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setLastIteration(0); @@ -454,6 +455,7 @@ void testRepeatedDiversionToDifferentDestinationRightBeforeLastLink() { config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setLastIteration(0); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setStartTime(0.0); config.qsim().setSimStarttimeInterpretation(StarttimeInterpretation.onlyUseStarttime); diff --git a/contribs/emissions/src/test/java/org/matsim/contrib/emissions/TestPositionEmissionModule.java b/contribs/emissions/src/test/java/org/matsim/contrib/emissions/TestPositionEmissionModule.java index f1824def7cd..a3059795499 100644 --- a/contribs/emissions/src/test/java/org/matsim/contrib/emissions/TestPositionEmissionModule.java +++ b/contribs/emissions/src/test/java/org/matsim/contrib/emissions/TestPositionEmissionModule.java @@ -18,11 +18,7 @@ import org.matsim.contrib.emissions.utils.EmissionsConfigGroup; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.ConfigUtils; -import org.matsim.core.config.groups.ControllerConfigGroup; -import org.matsim.core.config.groups.NetworkConfigGroup; -import org.matsim.core.config.groups.ReplanningConfigGroup; -import org.matsim.core.config.groups.ScoringConfigGroup; -import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.*; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; import org.matsim.core.controler.OutputDirectoryHierarchy; @@ -91,6 +87,7 @@ void compareToOtherModule_singleVehicleSingleLink() { var config = ConfigUtils.loadConfig(configFile, emissionConfig); config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setOutputDirectory(testUtils.getOutputDirectory()); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); emissionConfig.setAverageColdEmissionFactorsFile("../sample_41_EFA_ColdStart_vehcat_2020average.csv"); emissionConfig.setAverageWarmEmissionFactorsFile( "../sample_41_EFA_HOT_vehcat_2020average.csv" ); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java index 00233bbbf18..c7f030f3457 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java @@ -97,6 +97,10 @@ void handleAnEvent(Event event){ case LinkEnterEvent linkEnterEvent -> handleEvent(linkEnterEvent); case ActivityEndEvent activityEndEvent -> handleEvent(activityEndEvent); case ActivityStartEvent activityStartEvent -> handleEvent(activityStartEvent); + case VehicleEntersTrafficEvent vehicleEntersTrafficEvent -> handleEvent(vehicleEntersTrafficEvent); + case VehicleLeavesTrafficEvent vehicleLeavesTrafficEvent -> handleEvent(vehicleLeavesTrafficEvent); + case PersonMoneyEvent personMoneyEvent -> handleEvent( personMoneyEvent ); + case PersonScoreEvent personScoreEvent -> handleEvent( personScoreEvent ); case null, default -> createAdditionalEvents(event, null, scheduledTour, driverId, planElementCounter); } } @@ -145,6 +149,33 @@ private void handleEvent( LinkEnterEvent event ){ createAdditionalEvents( event, null, scheduledTour, driverId, planElementCounter ); } + private void handleEvent( PersonScoreEvent event ){ + if( scoringFunction != null ){ + scoringFunction.handleEvent( event ); + } + } + + private void handleEvent( PersonMoneyEvent event ){ + if( scoringFunction != null ){ + scoringFunction.handleEvent( event ); + } + } + + private void handleEvent( VehicleEntersTrafficEvent event ){ + if( scoringFunction != null ){ + scoringFunction.handleEvent( event ); + } + if ((Event) event instanceof VehicleEntersTrafficEvent vehicleEntersTrafficEvent) { + driver2EventHandler.handleEvent(vehicleEntersTrafficEvent); + } + } + + private void handleEvent( VehicleLeavesTrafficEvent event ){ + if( scoringFunction != null ){ + scoringFunction.handleEvent( event ); + } + } + private void handleEvent( ActivityEndEvent event ){ if( currentActivity == null ){ Activity firstActivity = PopulationUtils.createActivityFromLinkId( event.getActType(), event.getLinkId() ); @@ -196,7 +227,6 @@ private void createAdditionalEvents( Event event, Activity activity, ScheduledTo // if( scoringFunction == null ){ // (means "called from LSP". kai, jul'22) - driver2EventHandler.handleAnEvent(event); Id vehicleId = driver2EventHandler.getVehicleOfDriver(driverId); // Reason why this here is needed is that the more informative objects such as ScheduledTour cannot be @@ -271,15 +301,6 @@ public Id getVehicleOfDriver(Id personId){ return driversVehicles.get(personId); } - public void handleAnEvent(Event event){ - if (event instanceof VehicleEntersTrafficEvent vehicleEntersTrafficEvent) { - driver2EventHandler.handleEvent(vehicleEntersTrafficEvent); - } - if (event instanceof VehicleEntersTrafficEvent vehicleEntersTrafficEvent) { - driver2EventHandler.handleEvent(vehicleEntersTrafficEvent); - } - } - } } diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierVehicleReRouter.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierVehicleReRouter.java index 4a75e5c607d..cd03cb5fd94 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierVehicleReRouter.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierVehicleReRouter.java @@ -36,6 +36,7 @@ import com.graphhopper.jsprit.io.algorithm.AlgorithmConfigXmlReader; import com.graphhopper.jsprit.io.algorithm.VehicleRoutingAlgorithms; import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.roadpricing.RoadPricingScheme; import org.matsim.core.replanning.ReplanningContext; import org.matsim.core.replanning.modules.GenericPlanStrategyModule; import org.matsim.core.router.util.TravelTime; @@ -58,7 +59,7 @@ class CarrierVehicleReRouter implements GenericPlanStrategyModule{ private final VehicleRoutingActivityCosts vehicleRoutingActivityCosts; - public CarrierVehicleReRouter( Network network, CarrierVehicleTypes vehicleTypes, TravelTime travelTimes, String vrpAlgoConfigFile, VehicleTypeDependentRoadPricingCalculator roadPricing ) { + public CarrierVehicleReRouter( Network network, CarrierVehicleTypes vehicleTypes, TravelTime travelTimes, String vrpAlgoConfigFile, RoadPricingScheme roadPricing ) { this.network = network; vehicleRoutingTransportCosts = getNetworkBasedTransportCosts(network,vehicleTypes,travelTimes,roadPricing); vehicleRoutingActivityCosts = new VehicleRoutingActivityCosts() { @@ -146,7 +147,7 @@ public void handlePlan(CarrierPlan carrierPlan) { } - private NetworkBasedTransportCosts getNetworkBasedTransportCosts(Network network, CarrierVehicleTypes vehicleTypes, TravelTime travelTimes, VehicleTypeDependentRoadPricingCalculator roadPricing) { + private NetworkBasedTransportCosts getNetworkBasedTransportCosts(Network network, CarrierVehicleTypes vehicleTypes, TravelTime travelTimes, RoadPricingScheme roadPricing ) { //****** //Define transport-costs //****** @@ -157,7 +158,7 @@ private NetworkBasedTransportCosts getNetworkBasedTransportCosts(Network network //sets time-dependent travelTimes tpcostsBuilder.setTravelTime(travelTimes); - if(roadPricing != null) tpcostsBuilder.setRoadPricingCalculator(roadPricing); + if(roadPricing != null) tpcostsBuilder.setRoadPricingScheme(roadPricing ); //sets time-slice to build time-dependent tpcosts and travelTime matrices tpcostsBuilder.setTimeSliceWidth(900); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCosts.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCosts.java index f332b84cb0b..e6d8e1a0e45 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCosts.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCosts.java @@ -30,6 +30,8 @@ import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; import org.matsim.api.core.v01.population.Person; +import org.matsim.contrib.roadpricing.RoadPricingScheme; +import org.matsim.contrib.roadpricing.RoadPricingSchemeImpl; import org.matsim.core.router.speedy.SpeedyALTFactory; import org.matsim.core.router.util.LeastCostPathCalculator; import org.matsim.core.router.util.LeastCostPathCalculator.Path; @@ -83,6 +85,8 @@ */ public class NetworkBasedTransportCosts implements VRPTransportCosts { + private final RoadPricingScheme roadPricingScheme; + public interface InternalLeastCostPathCalculatorListener { void startCalculation(long routerId); @@ -316,27 +320,34 @@ private static class VehicleTypeVarCosts { */ static class VehicleTransportCostsIncludingToll implements TravelDisutility { -// private static Logger logger = LogManager.getLogger(VehicleTransportCostsIncludingToll.class); private final TravelDisutility baseTransportDisutility; - private final VehicleTypeDependentRoadPricingCalculator vehicleTypeDependentPricingCalculator; + private final RoadPricingScheme roadPricingScheme; - public VehicleTransportCostsIncludingToll(TravelDisutility baseTransportDisutility, - VehicleTypeDependentRoadPricingCalculator vehicleTypeDependentPricingCalculator) { + public VehicleTransportCostsIncludingToll( TravelDisutility baseTransportDisutility, + RoadPricingScheme roadPricingScheme ) { super(); this.baseTransportDisutility = baseTransportDisutility; - this.vehicleTypeDependentPricingCalculator = vehicleTypeDependentPricingCalculator; -// System.out.println("huuuuuuuuuuuuuuuuuuuu - initialize transport costs with toll"); + this.roadPricingScheme = roadPricingScheme; } @Override public double getLinkTravelDisutility(Link link, double time, Person person, org.matsim.vehicles.Vehicle vehicle) { double costs = baseTransportDisutility.getLinkTravelDisutility(link, time, person, vehicle); - Id typeId = vehicle.getType().getId(); - double toll = vehicleTypeDependentPricingCalculator.getTollAmount(typeId, link, time); -// System.out.println("huuuuuuuuuuuuuuuuuuuu - paid toll"); + + RoadPricingSchemeImpl.Cost costInfo; + if (person == null) { + costInfo = roadPricingScheme.getLinkCostInfo( link.getId(), time, null, vehicle.getId() ); + } else { + costInfo = roadPricingScheme.getLinkCostInfo( link.getId(), time, person.getId(), vehicle.getId() ); + } + + double toll = 0.; + if ( costInfo != null ){ + toll = costInfo.amount; + } return costs + toll; } @@ -377,7 +388,8 @@ public static Builder newInstance(Network network) { private LeastCostPathCalculatorFactory leastCostPathCalculatorFactory = (network, travelCosts, travelTimes) -> new SpeedyALTFactory().createPathCalculator(network, travelCosts, travelTime); - private VehicleTypeDependentRoadPricingCalculator roadPricingCalculator = new VehicleTypeDependentRoadPricingCalculator(); +// private VehicleTypeDependentRoadPricingCalculator roadPricingScheme = new VehicleTypeDependentRoadPricingCalculator(); + private RoadPricingScheme roadPricingScheme; private boolean withToll = false; @@ -393,7 +405,7 @@ public static Builder newInstance(Network network) { * Creates the builder requiring {@link Network} and a collection of * {@link VehicleType}. * - * @param network + * @param network the MATSim network * @param vehicleTypes must be all vehicleTypes and their assigned * costInformation in the system. */ @@ -414,7 +426,7 @@ private void retrieveTypeSpecificCosts(Collection vehicleTypes) { * Sets the travelTime. By default, travelTime is based on * link.getFreespeed();. * - * @param travelTime + * @param travelTime the travelTime to set * @return this builder */ public Builder setTravelTime(TravelTime travelTime) { @@ -463,7 +475,7 @@ public Builder setFIFO(boolean isFIFO) { *

* By default, it use {@link SpeedyALTFactory} * - * @param {@link {@link LeastCostPathCalculatorFactory} + * @param leastCostPathCalcFactory {@link LeastCostPathCalculatorFactory} * @return this builder */ public Builder setThreadSafeLeastCostPathCalculatorFactory( @@ -472,9 +484,9 @@ public Builder setThreadSafeLeastCostPathCalculatorFactory( return this; } - public Builder setRoadPricingCalculator(VehicleTypeDependentRoadPricingCalculator calculator) { + public Builder setRoadPricingScheme( RoadPricingScheme roadPricingScheme) { withToll = true; - this.roadPricingCalculator = calculator; + this.roadPricingScheme = roadPricingScheme; return this; } @@ -501,7 +513,7 @@ public NetworkBasedTransportCosts build() { baseDisutility = new BaseVehicleTransportCosts(typeSpecificCosts, travelTime); } if (withToll) { - finalDisutility = new VehicleTransportCostsIncludingToll(baseDisutility, roadPricingCalculator); + finalDisutility = new VehicleTransportCostsIncludingToll(baseDisutility, roadPricingScheme ); } else finalDisutility = baseDisutility; return new NetworkBasedTransportCosts(this); @@ -511,10 +523,10 @@ public NetworkBasedTransportCosts build() { * Adds type-specific costs. If typeId already exists, existing entry is * overwritten. * - * @param typeId - * @param fix - * @param perSecond - * @param perMeter + * @param typeId the vehicleType-id as String + * @param fix fix costs for the vehicle + * @param perSecond variable costs per second + * @param perMeter variable costs per meter */ public void addVehicleTypeSpecificCosts(String typeId, double fix, double perSecond, double perMeter) { typeSpecificCosts.put(typeId, new VehicleTypeVarCosts(perMeter, perSecond)); @@ -551,8 +563,6 @@ public void addVehicleTypeSpecificCosts(String typeId, double fix, double perSec private final Map matsimVehicles = new HashMap<>(); - private final VehicleTypeDependentRoadPricingCalculator roadPricingCalc; - /** * by default sets the {@link SpeedyALTFactory} */ @@ -568,7 +578,7 @@ private NetworkBasedTransportCosts(Builder builder) { this.travelTime = builder.travelTime; this.network = builder.network; this.leastCostPathCalculatorFactory = builder.leastCostPathCalculatorFactory; - this.roadPricingCalc = builder.roadPricingCalculator; + this.roadPricingScheme = builder.roadPricingScheme; this.timeSliceWidth = builder.timeSliceWidth; this.defaultTypeId = builder.defaultTypeId; this.ttMemorizedCounter = new Counter("#TransportCostValues cached "); @@ -585,7 +595,7 @@ private NetworkBasedTransportCosts(Builder builder) { * cached travel-time. If not, it computes and caches new values with the * leastCostPathCalc defined in here. * - * @Throws {@link IllegalStateException} if vehicle is null + * @exception IllegalStateException if vehicle is null */ @Override public double getTransportTime(Location fromId, Location toId, double departureTime, Driver driver, @@ -666,7 +676,7 @@ private void informStartCalc() { * cached travel-cost value. If not, it computes and caches new values with the * leastCostPathCalc defined in here. * - * @Throws {@link IllegalStateException} if vehicle is null + * @exception IllegalStateException if vehicle is null */ @Override public double getTransportCost(Location fromId, Location toId, double departureTime, Driver driver, @@ -734,7 +744,7 @@ public double getTransportCost(Location fromId, Location toId, double departureT * cached distance. If not, it computes and caches new values with the * leastCostPathCalc defined in here. * - * @Throws {@link IllegalStateException} if vehicle is null + * @exception IllegalStateException if vehicle is null */ @Override public double getDistance(Location fromId, Location toId, double departureTime, Vehicle vehicle) { @@ -799,7 +809,7 @@ public Collection getInternalListeners( * This is a rather bad approximation. If you require this, you should implement * another {@link VehicleRoutingTransportCosts} * - * @Throws {@link IllegalStateException} if vehicle is null + * @exception IllegalStateException if vehicle is null */ @Override public double getBackwardTransportCost(Location fromId, Location toId, double arrivalTime, Driver driver, @@ -815,7 +825,7 @@ public double getBackwardTransportCost(Location fromId, Location toId, double ar * This is a rather bad approximation. If you require this, you should implement * another {@link VehicleRoutingTransportCosts}. * - * @Throws {@link IllegalStateException} if vehicle is null + * @exception IllegalStateException if vehicle is null */ @Override public double getBackwardTransportTime(Location fromId, Location toId, double arrivalTime, Driver driver, @@ -862,7 +872,7 @@ private int getTimeSlice(double time) { /** * Gets the network the calculation is based on. * - * @return + * @return the network */ public Network getNetwork() { return network; @@ -877,13 +887,4 @@ public TravelTime getTravelTime() { return travelTime; } - /** - * Gets the {@link VehicleTypeDependentRoadPricingCalculator} - * - * @return {@link VehicleTypeDependentRoadPricingCalculator} - */ - public VehicleTypeDependentRoadPricingCalculator getRoadPricingCalculator() { - return roadPricingCalc; - } - } diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/VehicleTypeDependentRoadPricingCalculator.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/VehicleTypeDependentRoadPricingCalculator.java index ed5d3694720..6175780ab9a 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/VehicleTypeDependentRoadPricingCalculator.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/VehicleTypeDependentRoadPricingCalculator.java @@ -35,6 +35,7 @@ * @author stefan schröder * */ +@Deprecated // use RoadPricingScheme public class VehicleTypeDependentRoadPricingCalculator { interface TollCalculator { diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierModuleTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierModuleTest.java index b0d4922fcf9..49dc173dd05 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierModuleTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierModuleTest.java @@ -27,6 +27,7 @@ import org.matsim.api.core.v01.Scenario; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; @@ -53,6 +54,7 @@ public class CarrierModuleTest { @BeforeEach public void setUp(){ Config config = ConfigUtils.createConfig() ; + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ScoringConfigGroup.ActivityParams workParams = new ScoringConfigGroup.ActivityParams("w"); workParams.setTypicalDuration(60 * 60 * 8); config.scoring().addActivityParams(workParams); diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT.java index acfb8eab226..75800bfd34d 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT.java @@ -30,6 +30,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.ReplanningConfigGroup.StrategySettings; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; @@ -57,6 +58,8 @@ static Config commonConfig( MatsimTestUtils testUtils ) { config.controller().setOutputDirectory(testUtils.getOutputDirectory()); config.network().setInputFile( testUtils.getClassInputDirectory() + "network.xml" ); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + return config; } diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT.java index 83f1dd9e021..70b01111b10 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT.java @@ -30,6 +30,7 @@ import org.matsim.api.core.v01.Scenario; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; import org.matsim.freight.carriers.FreightCarriersConfigGroup; @@ -50,6 +51,7 @@ public class EquilWithCarrierWithoutPersonsIT { public void setUp() { Config config = EquilWithCarrierWithPersonsIT.commonConfig( testUtils ); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = EquilWithCarrierWithPersonsIT.commonScenario( config, testUtils ); controler = new Controler(scenario); } diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsTest.java index ccdb7095162..64e7eeba641 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsTest.java @@ -27,16 +27,21 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.roadpricing.*; import org.matsim.core.config.Config; import org.matsim.core.network.io.MatsimNetworkReader; import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.misc.Time; +import org.matsim.freight.carriers.CarrierVehicle; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.CostInformation; import org.matsim.vehicles.VehicleType; import org.matsim.vehicles.VehicleUtils; +import org.matsim.vehicles.VehiclesFactory; import java.util.Arrays; @@ -47,6 +52,8 @@ public class NetworkBasedTransportCostsTest { + private static final String TYPE_1 = "type1"; + private static final String TYPE_2 = "type2"; @RegisterExtension public final MatsimTestUtils utils = new MatsimTestUtils(); @@ -60,21 +67,21 @@ void test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem(){ Network network = scenario.getNetwork(); NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(network); - builder.addVehicleTypeSpecificCosts("type1", 10.0, 0.0, 2.0); - builder.addVehicleTypeSpecificCosts("type2", 20.0, 0.0, 4.0); + builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); + builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); NetworkBasedTransportCosts c = builder.build(); Vehicle vehicle1 = mock(Vehicle.class); com.graphhopper.jsprit.core.problem.vehicle.VehicleType type1 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); when(type1.getMaxVelocity()).thenReturn(5.0); - when(type1.getTypeId()).thenReturn("type1"); + when(type1.getTypeId()).thenReturn(TYPE_1); when(vehicle1.getType()).thenReturn(type1); when(vehicle1.getId()).thenReturn("vehicle1"); Vehicle vehicle2 = mock(Vehicle.class); com.graphhopper.jsprit.core.problem.vehicle.VehicleType type2 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); when(type2.getMaxVelocity()).thenReturn(5.0); - when(type2.getTypeId()).thenReturn("type2"); + when(type2.getTypeId()).thenReturn(TYPE_2); when(vehicle2.getType()).thenReturn(type2); when(vehicle2.getId()).thenReturn("vehicle2"); @@ -94,8 +101,8 @@ void test_whenVehicleTypeNotKnow_throwException(){ Network network = scenario.getNetwork(); NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(network); - builder.addVehicleTypeSpecificCosts("type1", 10.0, 0.0, 2.0); - builder.addVehicleTypeSpecificCosts("type2", 20.0, 0.0, 4.0); + builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); + builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); NetworkBasedTransportCosts c = builder.build(); Vehicle vehicle2 = mock(Vehicle.class); @@ -120,14 +127,14 @@ void test_whenAddingTwoVehicleTypesViaConstructor_itMustAccountForThat(){ String NETWORK_FILENAME = utils.getClassInputDirectory() + "network.xml"; new MatsimNetworkReader(scenario.getNetwork()).readFile(NETWORK_FILENAME); - VehicleType vehType1 = VehicleUtils.getFactory().createVehicleType(Id.create( "type1", VehicleType.class )); + VehicleType vehType1 = VehicleUtils.getFactory().createVehicleType(Id.create(TYPE_1, VehicleType.class )); CostInformation costInformation1 = vehType1.getCostInformation() ; costInformation1.setFixedCost( 0.0 ); costInformation1.setCostsPerMeter( 2.0 ); costInformation1.setCostsPerSecond( 0.0 ); - VehicleType vehType2 = VehicleUtils.getFactory().createVehicleType(Id.create( "type2", VehicleType.class )); + VehicleType vehType2 = VehicleUtils.getFactory().createVehicleType(Id.create(TYPE_2, VehicleType.class )); CostInformation costInformation = vehType2.getCostInformation() ; costInformation.setFixedCost( 0.0 ); @@ -136,20 +143,20 @@ void test_whenAddingTwoVehicleTypesViaConstructor_itMustAccountForThat(){ Network network = scenario.getNetwork(); NetworkBasedTransportCosts.Builder builder = - NetworkBasedTransportCosts.Builder.newInstance(network,Arrays.asList(vehType1,vehType2)); + NetworkBasedTransportCosts.Builder.newInstance(network,Arrays.asList(vehType1,vehType2)); NetworkBasedTransportCosts networkBasedTransportCosts = builder.build(); Vehicle vehicle1 = mock(Vehicle.class); com.graphhopper.jsprit.core.problem.vehicle.VehicleType type1 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); when(type1.getMaxVelocity()).thenReturn(5.0); - when(type1.getTypeId()).thenReturn("type1"); + when(type1.getTypeId()).thenReturn(TYPE_1); when(vehicle1.getType()).thenReturn(type1); when(vehicle1.getId()).thenReturn("vehicle1"); Vehicle vehicle2 = mock(Vehicle.class); com.graphhopper.jsprit.core.problem.vehicle.VehicleType type2 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); when(type2.getMaxVelocity()).thenReturn(5.0); - when(type2.getTypeId()).thenReturn("type2"); + when(type2.getTypeId()).thenReturn(TYPE_2); when(vehicle2.getType()).thenReturn(type2); when(vehicle2.getId()).thenReturn("vehicle2"); @@ -159,4 +166,211 @@ void test_whenAddingTwoVehicleTypesViaConstructor_itMustAccountForThat(){ Assertions.assertEquals(20000.0, networkBasedTransportCosts.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); } + + /** + * This test is a modified version of {@link #test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem} + * In addition, there is added a road pricing scheme to toll all vehicles + */ + @Test + void test_whenAddingTwoDifferentVehicleTypes_tollAllTypes(){ + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile(utils.getClassInputDirectory() + "network.xml"); + + //Create Rp Scheme from code. + RoadPricingSchemeImpl scheme = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); + /* Configure roadpricing scheme. */ + RoadPricingUtils.setName(scheme, "DemoToll4Test"); + RoadPricingUtils.setType(scheme, RoadPricingScheme.TOLL_TYPE_LINK); + RoadPricingUtils.setDescription(scheme, "Tolling scheme for test."); + + /* Add general link based toll for one link */ + RoadPricingUtils.addLink(scheme, Id.createLinkId("21")); + RoadPricingUtils.createAndAddGeneralCost(scheme, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 99.99); + + NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(scenario.getNetwork()); + builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); + builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); + builder.setRoadPricingScheme(scheme); + NetworkBasedTransportCosts c = builder.build(); + + Vehicle vehicle1 = mock(Vehicle.class); + com.graphhopper.jsprit.core.problem.vehicle.VehicleType type1 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); + when(type1.getMaxVelocity()).thenReturn(5.0); + when(type1.getTypeId()).thenReturn(TYPE_1); + when(vehicle1.getType()).thenReturn(type1); + when(vehicle1.getId()).thenReturn("vehicle1"); + + Vehicle vehicle2 = mock(Vehicle.class); + com.graphhopper.jsprit.core.problem.vehicle.VehicleType type2 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); + when(type2.getMaxVelocity()).thenReturn(5.0); + when(type2.getTypeId()).thenReturn(TYPE_2); + when(vehicle2.getType()).thenReturn(type2); + when(vehicle2.getId()).thenReturn("vehicle2"); + + //vehicle1: includes toll + Assertions.assertEquals(20099.99, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle1), 0.01); + Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle1), 0.01); + + //vehicle 2: no toll + Assertions.assertEquals(40099.99, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle2), 0.01); + Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); + } + + /** + * This test is a modified version of {@link #test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem} + * In addition, there is added a road pricing scheme. + * The scheme is only set for one vehicle type: type1. + * So, only the vehicle using that type (vehicle1) should be tolled, the other (vehicle2) not. + * This test is build, in a way, that it uses the MATSim infrastructure for filtering the vehicles in the toll factor. + * To see it just on jsprit setting, please refer to {@link #test_whenAddingTwoDifferentVehicleTypes_tollBasedOnVehicleId} + */ + @Test + void test_whenAddingTwoDifferentVehicleTypes_tollOneTypeTollFactor(){ + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile(utils.getClassInputDirectory() + "network.xml"); + + //Create RoadPricing Scheme from code. + RoadPricingSchemeImpl scheme = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); + /* Configure roadpricing scheme. */ + RoadPricingUtils.setName(scheme, "DemoToll4Test"); + RoadPricingUtils.setType(scheme, RoadPricingScheme.TOLL_TYPE_LINK); + RoadPricingUtils.setDescription(scheme, "Tolling scheme for test."); + + /* Add general link based toll for one link */ + RoadPricingUtils.addLink(scheme, Id.createLinkId("21")); + RoadPricingUtils.createAndAddGeneralCost(scheme, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 99.99); + + //Use toll factor to only toll vehicles of type1. + TollFactor tollFactor = (personId, vehicleId, linkId, time) -> { + double tollFactor1 = 0.; + var vehTypeIdString = VehicleUtils.findVehicle(vehicleId, scenario).getType().getId().toString(); //This needs, the vehicles registered in the scenario. + if (TYPE_1.equals(vehTypeIdString)) { + tollFactor1 = 1.; + } + return tollFactor1; + }; + RoadPricingScheme rpSchemeWTollFactor = new RoadPricingSchemeUsingTollFactor( scheme , tollFactor ); + + /// End creating roadPricing scheme from Code + + //Build MATSim vehicles and convert them to jsprit Vehicles ... just to see, that this works across the whole chain and + //that we can filter/search by (MATSim) vehicle types in TollFactor usage + VehiclesFactory vf = scenario.getVehicles().getFactory(); + final Vehicle vehicle1; + { + VehicleType vehType1 = vf.createVehicleType( Id.create( TYPE_1, VehicleType.class ) ); + vehType1.getCostInformation().setFixedCost(10.0); + vehType1.getCostInformation().setCostsPerSecond(0.0); + vehType1.getCostInformation().setCostsPerMeter(2.0); + scenario.getVehicles().addVehicleType( vehType1 ); + CarrierVehicle matsimVehicle1 = CarrierVehicle.newInstance( Id.createVehicleId( "vehicle1" ), Id.createLinkId("20"), vehType1 ); + scenario.getVehicles().addVehicle( matsimVehicle1 ); + vehicle1 = MatsimJspritFactory.createJspritVehicle( matsimVehicle1, new Coord() ); + } + + final Vehicle vehicle2; + { + VehicleType vehType2 = vf.createVehicleType(Id.create(TYPE_2, VehicleType.class)); + vehType2.getCostInformation().setFixedCost(20.0); + vehType2.getCostInformation().setCostsPerSecond(0.0); + vehType2.getCostInformation().setCostsPerMeter(4.0); + scenario.getVehicles().addVehicleType(vehType2); + + CarrierVehicle matsimVehicle2 = CarrierVehicle.newInstance(Id.createVehicleId("vehicle2"), Id.createLinkId("20"), vehType2); + scenario.getVehicles().addVehicle(matsimVehicle2); + vehicle2 = MatsimJspritFactory.createJspritVehicle(matsimVehicle2, new Coord()); + } + + //Build the NetbasedTransportCosts object with the roadpricing scheme. + NetworkBasedTransportCosts c = NetworkBasedTransportCosts.Builder.newInstance( + scenario.getNetwork(), + scenario.getVehicles().getVehicleTypes().values() ) + .setRoadPricingScheme(rpSchemeWTollFactor) + .build() ; + + //vehicle1: includes toll + Assertions.assertEquals(20099.99, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle1), 0.01); + Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle1), 0.01); + + //vehicle 2: no toll + Assertions.assertEquals(40000.0, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle2), 0.01); + Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); + } + + + /** + * This test is a modified version of {@link #test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem} + * In addition, there is added a road pricing scheme. + * With using a toll factor, the tolling can be set differently for the two vehicles. + * This test is build, in a way, that it uses the JSPRIT vehicle directly. + * To see it with the MATSim settings, please refer to {@link #test_whenAddingTwoDifferentVehicleTypes_tollOneTypeTollFactor()} + */ + @Test + void test_whenAddingTwoDifferentVehicleTypes_tollBasedOnVehicleId(){ + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile(utils.getClassInputDirectory() + "network.xml"); + + //Create Rp Scheme from code. + RoadPricingSchemeImpl scheme = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); + /* Configure roadpricing scheme. */ + RoadPricingUtils.setName(scheme, "DemoToll4TestType1"); + RoadPricingUtils.setType(scheme, RoadPricingScheme.TOLL_TYPE_LINK); + RoadPricingUtils.setDescription(scheme, "Tolling scheme for test."); + + /* Add general link based toll for one link */ + RoadPricingUtils.addLink(scheme, Id.createLinkId("21")); + RoadPricingUtils.createAndAddGeneralCost(scheme, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 99.99); + + //Use a factor to take into account the different types. type2 gehts tolled with 50% of the toll of type1 + TollFactor tollFactor = (personId, vehicleId, linkId, time) -> { + //No information about the vehicleType available anywhere, because it is not registered centrally. + // -> Use the vehicleId to distinguish the types. + var vehTypeIdString = vehicleId.toString(); + if (vehTypeIdString.equals("vehicle1")) { + return 1; + } else if (vehTypeIdString.equals("vehicle2")) { + return 0.5; + } else { + return 0; + } + }; + RoadPricingSchemeUsingTollFactor rpSchemeWTollFactor = new RoadPricingSchemeUsingTollFactor( scheme , tollFactor ); + + ///___ End creating toll scheme from code + + NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(scenario.getNetwork()); + builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); + builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); + builder.setRoadPricingScheme(rpSchemeWTollFactor); //add the rpCalculator to activate the tolling. + NetworkBasedTransportCosts c = builder.build(); + + Vehicle vehicle1 = mock(Vehicle.class); + com.graphhopper.jsprit.core.problem.vehicle.VehicleType type1 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); + when(type1.getMaxVelocity()).thenReturn(5.0); + when(type1.getTypeId()).thenReturn(TYPE_1); + when(vehicle1.getType()).thenReturn(type1); + when(vehicle1.getId()).thenReturn("vehicle1"); + + Vehicle vehicle2 = mock(Vehicle.class); + com.graphhopper.jsprit.core.problem.vehicle.VehicleType type2 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); + when(type2.getMaxVelocity()).thenReturn(5.0); + when(type2.getTypeId()).thenReturn(TYPE_2); + when(vehicle2.getType()).thenReturn(type2); + when(vehicle2.getId()).thenReturn("vehicle2"); + + //vehicle1: includes toll of 99.99 for entering the final link + Assertions.assertEquals(20099.99, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle1), 0.01); + Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle1), 0.01); + + //vehicle 2: includes toll of 49.995 (50% of 99.99) for entering the final link + Assertions.assertEquals(40049.995, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle2), 0.01); + Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); + } + } diff --git a/contribs/hybridsim/pom.xml b/contribs/hybridsim/pom.xml index 5917f032e3e..b480aa197dd 100644 --- a/contribs/hybridsim/pom.xml +++ b/contribs/hybridsim/pom.xml @@ -10,8 +10,8 @@ hybridsim - 4.27.2 - 1.65.0 + 4.28.0 + 1.65.1 diff --git a/contribs/locationchoice/src/test/java/org/matsim/contrib/locationchoice/LocationChoiceIT.java b/contribs/locationchoice/src/test/java/org/matsim/contrib/locationchoice/LocationChoiceIT.java index 4f39e4a0b72..1a045c7c8f6 100644 --- a/contribs/locationchoice/src/test/java/org/matsim/contrib/locationchoice/LocationChoiceIT.java +++ b/contribs/locationchoice/src/test/java/org/matsim/contrib/locationchoice/LocationChoiceIT.java @@ -84,6 +84,7 @@ public class LocationChoiceIT { void testLocationChoice() { final Config config = localCreateConfig( utils.getPackageInputDirectory() + "config2.xml"); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); final MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); diff --git a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/MultiModalControlerListenerTest.java b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/MultiModalControlerListenerTest.java index cb24c3d8849..fa7c3b2f767 100644 --- a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/MultiModalControlerListenerTest.java +++ b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/MultiModalControlerListenerTest.java @@ -89,7 +89,7 @@ void testSimpleScenario() { static void runSimpleScenario(int numberOfThreads) { Config config = ConfigUtils.createConfig(); - + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setEndTime(24 * 3600); config.controller().setLastIteration(0); diff --git a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/MultiModalTripRouterTest.java b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/MultiModalTripRouterTest.java index a939cb76327..ea6ba8549c3 100644 --- a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/MultiModalTripRouterTest.java +++ b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/MultiModalTripRouterTest.java @@ -39,6 +39,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Injector; @@ -73,6 +74,7 @@ void testRouteLeg() { config.routing().addParam("teleportedModeSpeed_ride", "15.0"); config.routing().addParam("teleportedModeSpeed_undefined", "13.88888888888889"); config.routing().addParam("teleportedModeSpeed_walk", "1.34"); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.scoring().addModeParams( new ScoringConfigGroup.ModeParams( TransportMode.ride ) ); final Scenario scenario = ScenarioUtils.createScenario(config); diff --git a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/RunMultimodalExampleTest.java b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/RunMultimodalExampleTest.java index 3a3c2101c9a..4cad691e8b5 100644 --- a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/RunMultimodalExampleTest.java +++ b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/RunMultimodalExampleTest.java @@ -20,8 +20,9 @@ void main(){ URL url = IOUtils.extendUrl( ExamplesUtils.getTestScenarioURL( "berlin" ), "config_multimodal.xml" );; String [] args = { url.toString(), - "--config:controler.outputDirectory" , utils.getOutputDirectory() - } ; + "--config:controler.outputDirectory" , utils.getOutputDirectory(), + "--config:routing.networkRouteConsistencyCheck", "disable" + } ;; try{ RunMultimodalExample.main( args ); diff --git a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/pt/MultiModalPTCombinationTest.java b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/pt/MultiModalPTCombinationTest.java index ca3a78fce35..78231bd1790 100644 --- a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/pt/MultiModalPTCombinationTest.java +++ b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/pt/MultiModalPTCombinationTest.java @@ -85,6 +85,7 @@ void testMultiModalPtCombination() { Scenario scenario = f.scenario; Config config = scenario.getConfig(); config.controller().setOutputDirectory(utils.getOutputDirectory()); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MultiModalConfigGroup mmcg = new MultiModalConfigGroup(); mmcg.setMultiModalSimulationEnabled(true); diff --git a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/simengine/StuckAgentTest.java b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/simengine/StuckAgentTest.java index 790922dd590..d0776605026 100644 --- a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/simengine/StuckAgentTest.java +++ b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/simengine/StuckAgentTest.java @@ -46,6 +46,7 @@ import org.matsim.contrib.multimodal.config.MultiModalConfigGroup; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.controler.Controler; import org.matsim.core.events.handler.BasicEventHandler; @@ -69,7 +70,7 @@ public class StuckAgentTest { void testStuckEvents() { Config config = ConfigUtils.createConfig(); config.controller().setOutputDirectory(utils.getOutputDirectory()); - + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setEndTime(24*3600); config.controller().setLastIteration(0); diff --git a/contribs/noise/src/main/java/org/matsim/contrib/noise/MergeNoiseCSVFile.java b/contribs/noise/src/main/java/org/matsim/contrib/noise/MergeNoiseCSVFile.java index d052f341cfe..7abae434d94 100644 --- a/contribs/noise/src/main/java/org/matsim/contrib/noise/MergeNoiseCSVFile.java +++ b/contribs/noise/src/main/java/org/matsim/contrib/noise/MergeNoiseCSVFile.java @@ -392,6 +392,7 @@ private void readReceiverPoints() { } } + //TODO this should be updated to use CSVReader or something as robust private void readValues() { for (int ll = 0; ll < this.labels.length; ll++) { diff --git a/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseConfigGroup.java b/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseConfigGroup.java index cd7b2a500ab..06e793c85d9 100644 --- a/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseConfigGroup.java +++ b/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseConfigGroup.java @@ -95,8 +95,8 @@ public NoiseConfigGroup() { private double receiverPointGap = 250.; - private String[] consideredActivitiesForReceiverPointGrid = {"home", "work"}; - private String[] consideredActivitiesForDamageCalculation = {"home", "work"}; + private String[] consideredActivitiesForReceiverPointGrid = {"home*", "work*"}; + private String[] consideredActivitiesForDamageCalculation = {"home*", "work*"}; private double receiverPointsGridMinX = 0.; private double receiverPointsGridMinY = 0.; diff --git a/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseWriter.java b/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseWriter.java index de465940c1a..6187e0b2f06 100644 --- a/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseWriter.java +++ b/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseWriter.java @@ -78,17 +78,17 @@ public static void writeReceiverPoints(NoiseContext noiseContext, String outputP // .addAttribute("Id", String.class) // .create(); // Collection features = new ArrayList(); -// +// // for (ReceiverPoint rp : noiseContext.getReceiverPoints().values()) { -// +// // SimpleFeature feature = factory.createPoint(MGC.coord2Coordinate(rp.getCoord()), new Object[] {rp.getId().toString()}, null); // features.add(feature); // } -// +// // String filePath = outputPath; // File file = new File(filePath); // file.mkdirs(); -// +// // log.info("Writing receiver points to shapefile... "); // ShapeFileWriter.writeGeometries(features, filePath + "receiverPoints.shp"); // log.info("Writing receiver points to shapefile... Done. "); @@ -318,13 +318,11 @@ public static void writeDamageInfoPerHour(NoiseContext noiseContext, String outp try { BufferedWriter bw = new BufferedWriter(new FileWriter(file)); - - bw.write("Receiver Point Id;Damages " + Time.writeTime(timeInterval, Time.TIMEFORMAT_HHMMSS)); + bw.write("Receiver Point Id;Damages " + Time.writeTime(timeInterval, Time.TIMEFORMAT_HHMMSS) + ";x;y;t"); bw.newLine(); for (NoiseReceiverPoint rp : noiseContext.getReceiverPoints().values()) { - - bw.write(rp.getId() + ";" + rp.getDamageCosts()); + bw.write(rp.getId() + ";" + rp.getDamageCosts() + ";" + rp.getCoord().getX() + ";" + rp.getCoord().getY() + ";" + timeInterval ); bw.newLine(); } diff --git a/contribs/noise/src/test/java/org/matsim/contrib/noise/NoiseConfigGroupIT.java b/contribs/noise/src/test/java/org/matsim/contrib/noise/NoiseConfigGroupIT.java index d5b61b0b590..1b5e2db9ccd 100644 --- a/contribs/noise/src/test/java/org/matsim/contrib/noise/NoiseConfigGroupIT.java +++ b/contribs/noise/src/test/java/org/matsim/contrib/noise/NoiseConfigGroupIT.java @@ -22,17 +22,18 @@ */ package org.matsim.contrib.noise; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Scenario; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.Controler; import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.core.scenario.ScenarioUtils; -import org.matsim.testcases.MatsimTestUtils; - +import org.matsim.testcases.MatsimTestUtils; + /** * @author ikaddoura * @@ -41,9 +42,9 @@ public class NoiseConfigGroupIT { @RegisterExtension - private MatsimTestUtils testUtils = new MatsimTestUtils(); - - @Test + private MatsimTestUtils testUtils = new MatsimTestUtils(); + + @Test final void test0(){ String configFile = testUtils.getPackageInputDirectory() + "NoiseConfigGroupTest/config0.xml"; @@ -69,14 +70,15 @@ final void test0(){ String tunnelLinkIds = noiseParameters.getTunnelLinkIDsSet().toArray()[0] + "," + noiseParameters.getTunnelLinkIDsSet().toArray()[1]; Assertions.assertEquals("link1,link2", tunnelLinkIds, "wrong config parameter"); - } - - @Test + } + + @Test final void test1(){ String configFile = testUtils.getPackageInputDirectory() + "NoiseConfigGroupTest/config1.xml"; Config config = ConfigUtils.loadConfig(configFile, new NoiseConfigGroup()); config.controller().setOutputDirectory(testUtils.getOutputDirectory()); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); NoiseConfigGroup noiseParameters = (NoiseConfigGroup) config.getModule("noise"); diff --git a/contribs/noise/src/test/java/org/matsim/contrib/noise/NoiseIT.java b/contribs/noise/src/test/java/org/matsim/contrib/noise/NoiseIT.java index e8aa97a3ab3..542580dcb44 100644 --- a/contribs/noise/src/test/java/org/matsim/contrib/noise/NoiseIT.java +++ b/contribs/noise/src/test/java/org/matsim/contrib/noise/NoiseIT.java @@ -93,6 +93,7 @@ final void test1(){ String[] consideredActivities = {"home", "work"}; noiseParameters.setConsideredActivitiesForDamageCalculationArray(consideredActivities); + noiseParameters.setConsideredActivitiesForReceiverPointGridArray(consideredActivities); com.google.inject.Injector injector = Injector.createInjector( scenario.getConfig() , new AbstractModule(){ @Override public void install(){ @@ -197,6 +198,7 @@ private static void runTest2a( Config runConfig ) { String[] consideredActivities = {"home", "work"}; noiseParameters.setConsideredActivitiesForDamageCalculationArray(consideredActivities); + noiseParameters.setConsideredActivitiesForReceiverPointGridArray(consideredActivities); noiseParameters.setScaleFactor(1.); noiseParameters.setUseActualSpeedLevel(false); @@ -984,6 +986,7 @@ final void test2b(){ String[] consideredActivities = {"home", "work"}; noiseParameters.setConsideredActivitiesForDamageCalculationArray(consideredActivities); + noiseParameters.setConsideredActivitiesForReceiverPointGridArray(consideredActivities); noiseParameters.setScaleFactor(1.); noiseParameters.setNoiseAllocationApproach(NoiseConfigGroup.NoiseAllocationApproach.MarginalCost); @@ -1073,6 +1076,7 @@ final void test2c(){ String[] consideredActivities = {"home", "work"}; noiseParameters.setConsideredActivitiesForDamageCalculationArray(consideredActivities); + noiseParameters.setConsideredActivitiesForReceiverPointGridArray(consideredActivities); noiseParameters.setScaleFactor(1.); noiseParameters.setUseActualSpeedLevel(true); diff --git a/contribs/noise/test/input/org/matsim/contrib/noise/NoiseConfigGroupTest/config1.xml b/contribs/noise/test/input/org/matsim/contrib/noise/NoiseConfigGroupTest/config1.xml index e2d42df47cf..f4830014284 100644 --- a/contribs/noise/test/input/org/matsim/contrib/noise/NoiseConfigGroupTest/config1.xml +++ b/contribs/noise/test/input/org/matsim/contrib/noise/NoiseConfigGroupTest/config1.xml @@ -1,24 +1,25 @@ - + - + + - + - + - + @@ -34,20 +35,20 @@ - - + + - + - + - + - + @@ -66,26 +67,26 @@ - + - + - + - + - + - + @@ -171,20 +172,20 @@ - + - + - + - + - + @@ -199,5 +200,5 @@ - + diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/CarEgressWalkChanger.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/CarEgressWalkChanger.java index ee231f716ed..20c0b113bed 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/CarEgressWalkChanger.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/CarEgressWalkChanger.java @@ -33,7 +33,7 @@ *

* This class allows to implicitly apply penalties to plans by changing the duration of the egress walk after car interactions. * By construction this only works for plans involving car trips and can not be used if you want to penalize all plans that - * fulfill a certain condition. + * fulfill a certain condition. Note that if you bind this, you should also bind the return value of {@link #getBackChanger()}! *

*

* More precisely, the class will...
@@ -49,13 +49,14 @@ * @author tkohl / Senozon * */ -class CarEgressWalkChanger implements BeforeMobsimListener, AfterMobsimListener { +class CarEgressWalkChanger implements BeforeMobsimListener { public static final String PENALTY_ATTRIBUTE = "parkingPenalty"; private final CarEgressWalkObserver observer; private final AccessEgressFinder egressFinder = new AccessEgressFinder(TransportMode.car); private final Iter0Method iter0Method; + private final CarEgressWalkBackChanger backChanger; /** * Sets the class up with the specified {@linkplain PenaltyGenerator} and {@linkplain PenaltyFunction}. @@ -66,6 +67,21 @@ class CarEgressWalkChanger implements BeforeMobsimListener, AfterMobsimListener public CarEgressWalkChanger(PenaltyGenerator penaltyGenerator, PenaltyFunction penaltyFunction, CarEgressWalkObserver observer, Iter0Method iter0Method) { this.observer = observer; this.iter0Method = iter0Method; + this.backChanger = new CarEgressWalkBackChanger(this); + } + + @Override + public double priority() { //we want this to happen very late, because it should only affect the mobsim, not other listeners + return -1001; + } + + /** + * Returns the class that changes the egress walks bag in AfterMobsim. Note that you need to bind this separately! + * + * @return the {@linkplain CarEgressWalkBackChanger} to this class + */ + public CarEgressWalkBackChanger getBackChanger() { + return this.backChanger; } /** @@ -93,33 +109,6 @@ public void notifyBeforeMobsim(BeforeMobsimEvent event) { this.changeEgressTimesByGridcell(event.getServices().getScenario().getPopulation().getPersons().values(), false); } } - - /** - * resets egress times before scoring / replanning - */ - @Override - public void notifyAfterMobsim(AfterMobsimEvent event) { - // we need to roll back the changes we made before the mobsim, otherwise we can't apply - // a different penalty next iteration. - if (event.getIteration() == 0) { - switch (this.iter0Method) { - case noPenalty: - case hourPenalty: - case estimateFromPlans: - this.changeEgressTimesByGridcell(event.getServices().getScenario().getPopulation().getPersons().values(), true); - break; - case takeFromAttributes: - this.changeEgressTimesByAttribute(event.getServices().getScenario().getPopulation().getPersons().values(), true); - break; - default: - throw new RuntimeException("Unknown iter0 mode"); - } - } else { - this.changeEgressTimesByGridcell(event.getServices().getScenario().getPopulation().getPersons().values(), true); - } - // yyyy this is something we do not like: to just "fake" something and take it back afterwards. Would be good to find some other design - // eventually. Not so obvious, though ... kai, mar'20 - } /** * Changes the egress times of all agents using cars according to the penalty for the corresponding space-time-gridcell and writes the penalty @@ -130,12 +119,13 @@ public void notifyAfterMobsim(AfterMobsimEvent event) { * by that time (calling this method twice, first with {@code false}, then with {@code true} should yield the original plans) */ private void changeEgressTimesByGridcell(Collection population, boolean reverse) { - int sign = reverse ? -1 : 1; for (Person p : population) { for (LegActPair walkActPair : this.egressFinder.findEgressWalks(p.getSelectedPlan())) { - double penalty = sign * this.observer.getPenaltyCalculator().getPenalty(walkActPair.leg.getDepartureTime().seconds(), walkActPair.act.getCoord()); - setTimes(walkActPair, penalty); - if (!reverse) { + double penalty = Math.round(this.observer.getPenaltyCalculator().getPenalty(walkActPair.leg.getDepartureTime().seconds(), walkActPair.act.getCoord())); + if (reverse) { + setTimes(walkActPair, -penalty); + } else { + setTimes(walkActPair, penalty); walkActPair.leg.getAttributes().putAttribute(PENALTY_ATTRIBUTE, penalty); } } @@ -171,4 +161,50 @@ private static void setTimes(LegActPair walkActPair, double penalty) { walkActPair.leg.getRoute().setTravelTime(walkActPair.leg.getRoute().getTravelTime().seconds() + penalty); walkActPair.act.setStartTime(walkActPair.act.getStartTime().seconds() + penalty); } + + /** + * The reverse to {@linkplain CarEgressWalkChanger} + * + * @author tkohl + * + */ + static class CarEgressWalkBackChanger implements AfterMobsimListener { + private final CarEgressWalkChanger forwardChanger; + + CarEgressWalkBackChanger(CarEgressWalkChanger forwardChanger) { + this.forwardChanger = forwardChanger; + } + + @Override + public double priority() { //we want this to happen very early to undo what we did before the mobsim before other listeners can pick it up + return 1001; + } + + /** + * resets egress times before scoring / replanning + */ + @Override + public void notifyAfterMobsim(AfterMobsimEvent event) { + // we need to roll back the changes we made before the mobsim, otherwise we can't apply + // a different penalty next iteration. + if (event.getIteration() == 0) { + switch (forwardChanger.iter0Method) { + case noPenalty: + case hourPenalty: + case estimateFromPlans: + forwardChanger.changeEgressTimesByGridcell(event.getServices().getScenario().getPopulation().getPersons().values(), true); + break; + case takeFromAttributes: + forwardChanger.changeEgressTimesByAttribute(event.getServices().getScenario().getPopulation().getPersons().values(), true); + break; + default: + throw new RuntimeException("Unknown iter0 mode"); + } + } else { + forwardChanger.changeEgressTimesByGridcell(event.getServices().getScenario().getPopulation().getPersons().values(), true); + } + // yyyy this is something we do not like: to just "fake" something and take it back afterwards. Would be good to find some other design + // eventually. Not so obvious, though ... kai, mar'20 + } + } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/ParkingProxyModule.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/ParkingProxyModule.java index f356f0911e8..41f179d4977 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/ParkingProxyModule.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/ParkingProxyModule.java @@ -92,7 +92,9 @@ public void install() { if (parkingConfig.getObserveOnly()) { super.addControlerListenerBinding().toInstance(walkObserver); } else { - super.addControlerListenerBinding().toInstance(new CarEgressWalkChanger(parkingHandler, penaltyFunction, walkObserver, parkingConfig.getIter0Method())); + CarEgressWalkChanger walkChanger = new CarEgressWalkChanger(parkingHandler, penaltyFunction, walkObserver, parkingConfig.getIter0Method()); + super.addControlerListenerBinding().toInstance(walkChanger); + super.addControlerListenerBinding().toInstance(walkChanger.getBackChanger()); } } diff --git a/contribs/protobuf/pom.xml b/contribs/protobuf/pom.xml index a2c8a4ef62b..a08c2d527c8 100644 --- a/contribs/protobuf/pom.xml +++ b/contribs/protobuf/pom.xml @@ -11,7 +11,7 @@ protobuf - 4.27.2 + 4.28.0 diff --git a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/CalcPaidTollTest.java b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/CalcPaidTollTest.java index 85c90cb3e79..9cfbfca06ed 100644 --- a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/CalcPaidTollTest.java +++ b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/CalcPaidTollTest.java @@ -34,6 +34,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -58,6 +59,7 @@ public class CalcPaidTollTest { @Test void testDistanceToll() { Config config = ConfigUtils.loadConfig(utils.getClassInputDirectory() + "config.xml"); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); final String tollFile = utils.getClassInputDirectory() + "/roadpricing1.xml"; Id id1 = Id.create("1", Person.class); @@ -94,6 +96,7 @@ void testDistanceToll() { @Test void testAreaToll() { Config config = ConfigUtils.loadConfig(utils.getClassInputDirectory() + "config.xml"); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); final String tollFile = utils.getClassInputDirectory() + "/roadpricing2.xml"; Id id1 = Id.create("1", Person.class); @@ -145,6 +148,7 @@ void testAreaToll() { @Test void testCordonToll() { Config config = ConfigUtils.loadConfig(utils.getClassInputDirectory() + "config.xml"); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); final String tollFile = utils.getClassInputDirectory() + "/roadpricing3.xml"; Id id1 = Id.create("1", Person.class); diff --git a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/PlansCalcRouteWithTollOrNotTest.java b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/PlansCalcRouteWithTollOrNotTest.java index e75ed598afa..e5651f02648 100644 --- a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/PlansCalcRouteWithTollOrNotTest.java +++ b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/PlansCalcRouteWithTollOrNotTest.java @@ -36,6 +36,7 @@ import org.matsim.api.core.v01.population.PlanElement; import org.matsim.api.core.v01.population.Population; import org.matsim.core.config.Config; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.RoutingConfigGroup.AccessEgressType; import org.matsim.core.controler.Injector; import org.matsim.core.controler.NewControlerModule; @@ -74,6 +75,7 @@ public class PlansCalcRouteWithTollOrNotTest { @Test void testBestAlternatives() { Config config = matsimTestUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.overwriteExistingFiles); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); RoadPricingTestUtils.createNetwork2(scenario); @@ -180,6 +182,7 @@ private PlansCalcRouteWithTollOrNot testee(final Scenario scenario, final RoadPr @Test void testTolledActLink() { Config config = matsimTestUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); RoadPricingTestUtils.createNetwork2(scenario); @@ -206,6 +209,7 @@ void testTolledActLink() { @Test void testAllAlternativesTolled() { Config config = matsimTestUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); RoadPricingTestUtils.createNetwork2(scenario); @@ -245,6 +249,7 @@ private static Leg getLeg3(Config config, Population population, Id id1) @Test void testOutsideTollTime() { Config config = matsimTestUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); RoadPricingTestUtils.createNetwork2(scenario); diff --git a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/TollTravelCostCalculatorTest.java b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/TollTravelCostCalculatorTest.java index 84052e33d8c..4eecbfef4df 100644 --- a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/TollTravelCostCalculatorTest.java +++ b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/TollTravelCostCalculatorTest.java @@ -24,6 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertNull; import java.util.List; +import java.util.Map; import jakarta.inject.Provider; import org.junit.jupiter.api.Test; @@ -74,6 +75,7 @@ public class TollTravelCostCalculatorTest { @Test void testDisutilityResults() { Config config = ConfigUtils.createConfig() ; + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = ScenarioUtils.createScenario(config) ; RoadPricingTestUtils.createNetwork2((MutableScenario)scenario); @@ -124,11 +126,12 @@ void testDisutilityResults() { @Test void testDistanceTollRouter() { Config config = utils.createConfig(); - MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); RoadPricingTestUtils.createNetwork2(scenario); Network network = scenario.getNetwork(); // a basic toll where only the morning hours are tolled - RoadPricingSchemeImpl toll = RoadPricingUtils.addOrGetMutableRoadPricingScheme(ScenarioUtils.createScenario( ConfigUtils.createConfig() ) ); + RoadPricingSchemeImpl toll = RoadPricingUtils.addOrGetMutableRoadPricingScheme(ScenarioUtils.createScenario( config ) ); toll.setType(RoadPricingScheme.TOLL_TYPE_DISTANCE); toll.addLink(Id.create("5", Link.class)); toll.addLink(Id.create("11", Link.class)); @@ -209,11 +212,12 @@ void testDistanceTollRouter() { @Test void testLinkTollRouter() { Config config = utils.createConfig(); - MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); RoadPricingTestUtils.createNetwork2(scenario); Network network = scenario.getNetwork(); // a basic toll where only the morning hours are tolled - RoadPricingSchemeImpl toll = RoadPricingUtils.addOrGetMutableRoadPricingScheme(ScenarioUtils.createScenario( ConfigUtils.createConfig() ) ); + RoadPricingSchemeImpl toll = RoadPricingUtils.addOrGetMutableRoadPricingScheme(ScenarioUtils.createScenario( config ) ); toll.setType(RoadPricingScheme.TOLL_TYPE_LINK); toll.addLink(Id.create("5", Link.class)); toll.addLink(Id.create("11", Link.class)); @@ -304,11 +308,11 @@ void testLinkTollRouter() { @Test void testCordonTollRouter() { Config config = utils.createConfig(); - MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); RoadPricingTestUtils.createNetwork2(scenario); - Network network = scenario.getNetwork(); // a basic toll where only the morning hours are tolled - RoadPricingSchemeImpl toll = RoadPricingUtils.addOrGetMutableRoadPricingScheme(ScenarioUtils.createScenario( ConfigUtils.createConfig() ) ); + RoadPricingSchemeImpl toll = RoadPricingUtils.addOrGetMutableRoadPricingScheme(ScenarioUtils.createScenario( config ) ); // toll.setType(RoadPricingScheme.TOLL_TYPE_CORDON); toll.setType(RoadPricingScheme.TOLL_TYPE_LINK); toll.addLink(Id.create("5", Link.class)); diff --git a/contribs/signals/src/test/java/org/matsim/contrib/signals/analysis/DelayAnalysisToolTest.java b/contribs/signals/src/test/java/org/matsim/contrib/signals/analysis/DelayAnalysisToolTest.java index 22c34ad8ddc..c7b0852857e 100644 --- a/contribs/signals/src/test/java/org/matsim/contrib/signals/analysis/DelayAnalysisToolTest.java +++ b/contribs/signals/src/test/java/org/matsim/contrib/signals/analysis/DelayAnalysisToolTest.java @@ -25,6 +25,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.events.algorithms.EventWriterXML; @@ -140,6 +141,7 @@ private void generateOutput(Scenario scenario, final List eventslist) { private Scenario prepareTest(int numberOfPersons) { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = ScenarioUtils.createScenario(config); createNetwork(scenario); createPopulation(scenario, numberOfPersons); diff --git a/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/Fixture.java b/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/Fixture.java index 63f18a921a9..d51e4727e4b 100644 --- a/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/Fixture.java +++ b/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/Fixture.java @@ -45,6 +45,7 @@ import org.matsim.contrib.signals.model.SignalSystem; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.config.groups.ReplanningConfigGroup.StrategySettings; import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; @@ -87,6 +88,7 @@ private Config createConfigOneSignal(Boolean useIntergreens) { } Config conf = ConfigUtils.createConfig(testUtils.classInputResourcePath()); conf.controller().setOverwriteFileSetting(OverwriteFileSetting.overwriteExistingFiles); + conf.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ActivityParams params = new ActivityParams("h"); params.setTypicalDuration(24.0 * 3600.0); conf.scoring().addActivityParams(params); diff --git a/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/TravelTimeFourWaysTest.java b/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/TravelTimeFourWaysTest.java index ba97489f89e..ff0080324d1 100644 --- a/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/TravelTimeFourWaysTest.java +++ b/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/TravelTimeFourWaysTest.java @@ -30,6 +30,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.*; import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; import org.matsim.core.events.EventsUtils; @@ -77,6 +78,8 @@ private Scenario createTestScenario(){ conf.network().setLaneDefinitionsFile("testLaneDefinitions_v2.0.xml"); conf.qsim().setUseLanes(true); conf.qsim().setUsingFastCapacityUpdate(false); + conf.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + SignalSystemsConfigGroup signalsConfig = ConfigUtils.addOrGetModule(conf, SignalSystemsConfigGroup.GROUP_NAME, SignalSystemsConfigGroup.class ); signalsConfig.setUseSignalSystems(true); diff --git a/contribs/signals/src/test/java/org/matsim/contrib/signals/controller/fixedTime/DefaultPlanbasedSignalSystemControllerIT.java b/contribs/signals/src/test/java/org/matsim/contrib/signals/controller/fixedTime/DefaultPlanbasedSignalSystemControllerIT.java index e5f7d325967..91323bda153 100644 --- a/contribs/signals/src/test/java/org/matsim/contrib/signals/controller/fixedTime/DefaultPlanbasedSignalSystemControllerIT.java +++ b/contribs/signals/src/test/java/org/matsim/contrib/signals/controller/fixedTime/DefaultPlanbasedSignalSystemControllerIT.java @@ -61,6 +61,7 @@ import org.matsim.contrib.signals.utils.SignalUtils; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.config.groups.ReplanningConfigGroup.StrategySettings; import org.matsim.core.controler.AbstractModule; @@ -719,6 +720,7 @@ private void createSignals() { private Config defineConfig() { Config config = ConfigUtils.createConfig(); config.controller().setOutputDirectory(testUtils.getOutputDirectory()); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); // set number of iterations config.controller().setLastIteration(0); diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/CreateSingleSimWrapperDashboard.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/CreateSingleSimWrapperDashboard.java new file mode 100644 index 00000000000..fce848736a6 --- /dev/null +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/CreateSingleSimWrapperDashboard.java @@ -0,0 +1,148 @@ +/* *********************************************************************** * + * project: org.matsim.* + * Controler.java + * * + * *********************************************************************** * + * * + * copyright : (C) 2007 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ + +package org.matsim.simwrapper; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.application.ApplicationUtils; +import org.matsim.application.MATSimAppCommand; +import org.matsim.application.options.ShpOptions; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.simwrapper.dashboard.*; +import picocli.CommandLine; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; + +@CommandLine.Command( + name = "dashboard", + description = "Run analysis and create SimWrapper dashboard for existing run output." +) + +/** + * This class creates single SimWrapper dashboards for multiple output directories. It is meant to be run as a post-process, + * e.g. when a specific dashboard was missing after the initial run (for whatever reason). + * It will create the dashboard with all standard settings. + * Depending on the dashboard type, it might be required to provide ShpOptions for data filtering. + * TODO: test whether this works for the non-noise DashboardTypes. + */ +final class CreateSingleSimWrapperDashboard implements MATSimAppCommand { + + private static final Logger log = LogManager.getLogger(CreateSingleSimWrapperDashboard.class); + + @CommandLine.Option(names = "--type", required = true, description = "Provide the dashboard type to be generated. See DashboardType enum within this class.") + private DashboardType dashboardType; + + @CommandLine.Parameters(arity = "1..*", description = "Path to run output directories for which the dashboards is to be generated.") + private List inputPaths; + + @CommandLine.Mixin + private final ShpOptions shp = new ShpOptions(); + + enum DashboardType{ + noise, + emissions, + traffic, + overview, + stuckAgent, + populationAttribute, + ODTrip, + trip, + publicTransit + } + + private CreateSingleSimWrapperDashboard(){ + } + + @Override + public Integer call() throws Exception { + + for (Path runDirectory : inputPaths) { + log.info("Creating " + dashboardType + " for {}", runDirectory); + + Path configPath = ApplicationUtils.matchInput("config.xml", runDirectory); + Config config = ConfigUtils.loadConfig(configPath.toString()); + SimWrapper sw = SimWrapper.create(config); + + SimWrapperConfigGroup simwrapperCfg = ConfigUtils.addOrGetModule(config, SimWrapperConfigGroup.class); + + if (shp.isDefined()){ + //not sure if this is the best way to go, might be that the shape file would be automatically read by providing the --shp command line option + simwrapperCfg.defaultParams().shp = shp.getShapeFile().toString(); + } + + //skip default dashboards + simwrapperCfg.defaultDashboards = SimWrapperConfigGroup.Mode.disabled; + + //add dashboard + switch (dashboardType) { + case noise -> { + sw.addDashboard(new NoiseDashboard()); + } + case emissions -> { + sw.addDashboard(new EmissionsDashboard()); + } + case traffic -> { + sw.addDashboard(new TrafficDashboard()); + } + case overview -> { + sw.addDashboard(new OverviewDashboard()); + } + case stuckAgent -> { + sw.addDashboard(new StuckAgentDashboard()); + } + case populationAttribute -> { + sw.addDashboard(new PopulationAttributeDashboard()); + } + case ODTrip -> { + throw new RuntimeException("ODTripDashboard needs additional information. Single creation is currently not implemented"); +// sw.addDashboard(new ODTripDashboard()); + } + case trip -> { + sw.addDashboard(new TripDashboard()); + } + case publicTransit -> { + sw.addDashboard(new PublicTransitDashboard()); + } + default -> throw new IllegalArgumentException("unkown dashboard type: " + dashboardType); + } + + try { + //append dashboard to existing ones + boolean append = true; + sw.generate(runDirectory, append); + sw.run(runDirectory); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + return 0; + } + + public static void main(String[] args) { + new CreateSingleSimWrapperDashboard().execute(args); + } + +} + diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java index dc934e6c2e2..48f173a8adb 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java @@ -1,6 +1,7 @@ package org.matsim.simwrapper.dashboard; import org.matsim.application.analysis.noise.NoiseAnalysis; +import org.matsim.application.analysis.population.StuckAgentAnalysis; import org.matsim.application.prepare.network.CreateAvroNetwork; import org.matsim.simwrapper.Dashboard; import org.matsim.simwrapper.Header; @@ -8,6 +9,7 @@ import org.matsim.simwrapper.viz.ColorScheme; import org.matsim.simwrapper.viz.GridMap; import org.matsim.simwrapper.viz.MapPlot; +import org.matsim.simwrapper.viz.Tile; /** * Shows emission in the scenario. @@ -32,22 +34,15 @@ public void configure(Header header, Layout layout) { header.title = "Noise"; header.description = "Shows the noise footprint and spatial distribution."; - layout.row("aggregate noise") - .el(GridMap.class, (viz, data) -> { - viz.title = "Noise Immissions (Grid)"; - viz.description = "Aggregate Noise Immissions per day"; - viz.height = 12.0; - viz.cellSize = 250; - viz.opacity = 0.2; - viz.maxHeight = 20; - viz.center = data.context().getCenter(); - viz.zoom = data.context().mapZoomLevel; - viz.setColorRamp(new double[]{40, 50, 60}, new String[]{"#1175b3", "#95c7df", "#f4a986", "#cc0c27"}); - viz.file = data.computeWithPlaceholder(NoiseAnalysis.class, "immission_per_day.%s", "avro"); - }) + layout.row("stats") + .el(Tile.class, (viz, data) -> { + viz.dataset = data.compute(NoiseAnalysis.class, "noise_stats.csv"); + viz.height = 0.1; + }); + layout.row("emissions") .el(MapPlot.class, (viz, data) -> { viz.title = "Noise Emissions (Link)"; - viz.description = "Aggregate Noise Emissions per day"; + viz.description = "Maximum Noise Level per day [dB]"; viz.height = 12.0; viz.center = data.context().getCenter(); viz.zoom = data.context().mapZoomLevel; @@ -58,25 +53,63 @@ public void configure(Header header, Layout layout) { viz.display.lineColor.dataset = "noise"; viz.display.lineColor.columnName = "value"; viz.display.lineColor.join = "Link Id"; - viz.display.lineColor.fixedColors = new String[]{"#1175b3", "#95c7df", "#f4a986", "#cc0c27"}; - viz.display.lineColor.setColorRamp(ColorScheme.RdYlBu, 4, true, "45, 55, 65"); + //viz.display.lineColor.fixedColors = new String[]{"#1175b3", "#95c7df", "#f4a986", "#cc0c27"}; + viz.display.lineColor.setColorRamp(ColorScheme.Oranges, 8, false, "35, 45, 55, 65, 75, 85, 95"); viz.display.lineWidth.dataset = "noise"; viz.display.lineWidth.columnName = "value"; viz.display.lineWidth.scaleFactor = 8d; viz.display.lineWidth.join = "Link Id"; }); - layout.row("hourly noise") + layout.row("imissions") + .el(GridMap.class, (viz, data) -> { + viz.title = "Noise Immissions (Grid)"; + viz.description = "Total Noise Immissions per day"; + viz.height = 12.0; + viz.cellSize = 250; + viz.opacity = 0.1; + viz.maxHeight = 40; + viz.center = data.context().getCenter(); + viz.zoom = data.context().mapZoomLevel; + viz.setColorRamp(new double[]{30, 40, 50, 60, 70}, new String[]{"#1175b3", "#95c7df", "#dfdb95", "#dfb095", "#f4a986", "#cc0c27"}); + viz.file = data.computeWithPlaceholder(NoiseAnalysis.class, "immission_per_day.%s", "avro"); + }) .el(GridMap.class, (viz, data) -> { viz.title = "Hourly Noise Immissions (Grid)"; viz.description = "Noise Immissions per hour"; viz.height = 12.0; viz.cellSize = 250; - viz.opacity = 0.2; - viz.maxHeight = 20; + viz.opacity = 0.1; + viz.maxHeight = 40; viz.center = data.context().getCenter(); viz.zoom = data.context().mapZoomLevel; - viz.setColorRamp(new double[]{40, 50, 60}, new String[]{"#1175b3", "#95c7df", "#f4a986", "#cc0c27"}); + viz.setColorRamp(new double[]{30, 40, 50, 60, 70}, new String[]{"#1175b3", "#95c7df", "#dfdb95", "#dfb095", "#f4a986", "#cc0c27"}); viz.file = data.computeWithPlaceholder(NoiseAnalysis.class, "immission_per_hour.%s", "avro"); }); + layout.row("damages") + .el(GridMap.class, (viz, data) -> { + viz.title = "Daily Noise Damages (Grid)"; + viz.description = "Total Noise Damages per day [€]"; + viz.height = 12.0; + viz.cellSize = 250; + viz.opacity = 0.1; + viz.maxHeight = 40; + viz.center = data.context().getCenter(); + viz.zoom = data.context().mapZoomLevel; + viz.setColorRamp(ColorScheme.Oranges); + viz.file = data.computeWithPlaceholder(NoiseAnalysis.class, "damages_receiverPoint_per_day.%s", "avro"); + }) + .el(GridMap.class, (viz, data) -> { + viz.title = "Hourly Noise Damages (Grid)"; + viz.description = "Noise Damages per hour [€]"; + viz.height = 12.0; + viz.cellSize = 250; + viz.opacity = 0.2; + viz.maxHeight = 40; + viz.center = data.context().getCenter(); + viz.zoom = data.context().mapZoomLevel; +// viz.setColorRamp(new double[]{30, 40, 50, 60, 70}, new String[]{"#1175b3", "#95c7df", "#dfdb95", "#dfb095", "#f4a986", "#cc0c27"}); + viz.setColorRamp(ColorScheme.Oranges); + viz.file = data.computeWithPlaceholder(NoiseAnalysis.class, "damages_receiverPoint_per_hour.%s", "avro"); + }); } } diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/viz/ColorScheme.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/viz/ColorScheme.java index 37e31cc97ca..df8f6410679 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/viz/ColorScheme.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/viz/ColorScheme.java @@ -27,6 +27,7 @@ public final class ColorScheme { public static final String Inferne = "Inferne"; public static final String Cividis = "Cividis"; public static final String Rainbow = "Rainbow"; + public static final String Oranges = "Oranges"; private ColorScheme() { diff --git a/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/NoiseDashboardTests.java b/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/NoiseDashboardTests.java index 6ca2a08cee3..fdc846cdff5 100644 --- a/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/NoiseDashboardTests.java +++ b/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/NoiseDashboardTests.java @@ -46,6 +46,11 @@ void generate() { Assertions.assertThat(out) .isDirectoryContaining("glob:**emission_per_day.csv") .isDirectoryContaining("glob:**immission_per_day.avro") - .isDirectoryContaining("glob:**immission_per_hour.avro"); + .isDirectoryContaining("glob:**immission_per_hour.avro") + .isDirectoryContaining("glob:**damages_receiverPoint_per_hour.avro") + .isDirectoryContaining("glob:**damages_receiverPoint_per_day.avro") + .isDirectoryContaining("glob:**noise_stats.csv"); + + //TODO check content / values of the files } } diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java index 1b8a0b260e8..af8fbacf479 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java @@ -25,7 +25,6 @@ import org.apache.commons.math3.distribution.EnumeratedDistribution; import org.apache.commons.math3.random.MersenneTwister; import org.apache.commons.math3.random.RandomGenerator; -import org.apache.commons.math3.util.Pair; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -72,6 +71,8 @@ import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; import org.matsim.freight.carriers.controler.*; import org.matsim.freight.carriers.usecases.chessboard.CarrierTravelDisutilities; +import org.matsim.smallScaleCommercialTrafficGeneration.data.DefaultTourSpecificationsByUsingKID2002; +import org.matsim.smallScaleCommercialTrafficGeneration.data.GetCommercialTourSpecifications; import org.matsim.vehicles.CostInformation; import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.VehicleType; @@ -106,7 +107,8 @@ public class GenerateSmallScaleCommercialTrafficDemand implements MATSimAppComma // Option 3: Leerkamp (nur in RVR Modell). private static final Logger log = LogManager.getLogger(GenerateSmallScaleCommercialTrafficDemand.class); - private static IntegrateExistingTrafficToSmallScaleCommercial integrateExistingTrafficToSmallScaleCommercial; + private final IntegrateExistingTrafficToSmallScaleCommercial integrateExistingTrafficToSmallScaleCommercial; + private final GetCommercialTourSpecifications getCommercialTourSpecifications; private enum CreationOption { useExistingCarrierFileWithSolution, createNewCarrierFile, useExistingCarrierFileWithoutSolution @@ -174,12 +176,26 @@ public enum SmallScaleCommercialTrafficType { private Index indexZones; public GenerateSmallScaleCommercialTrafficDemand() { - integrateExistingTrafficToSmallScaleCommercial = new DefaultIntegrateExistingTrafficToSmallScaleCommercialImpl(); + this.integrateExistingTrafficToSmallScaleCommercial = new DefaultIntegrateExistingTrafficToSmallScaleCommercialImpl(); log.info("Using default {} if existing models are integrated!", DefaultIntegrateExistingTrafficToSmallScaleCommercialImpl.class.getSimpleName()); + this.getCommercialTourSpecifications = new DefaultTourSpecificationsByUsingKID2002(); + log.info("Using default {} for tour specifications!", DefaultTourSpecificationsByUsingKID2002.class.getSimpleName()); } - public GenerateSmallScaleCommercialTrafficDemand(IntegrateExistingTrafficToSmallScaleCommercial integrateExistingTrafficToSmallScaleCommercial) { - GenerateSmallScaleCommercialTrafficDemand.integrateExistingTrafficToSmallScaleCommercial = integrateExistingTrafficToSmallScaleCommercial; - log.info("Using {} if existing models are integrated!", integrateExistingTrafficToSmallScaleCommercial.getClass().getSimpleName()); + public GenerateSmallScaleCommercialTrafficDemand(IntegrateExistingTrafficToSmallScaleCommercial integrateExistingTrafficToSmallScaleCommercial, GetCommercialTourSpecifications getCommercialTourSpecifications) { + if (integrateExistingTrafficToSmallScaleCommercial == null){ + this.integrateExistingTrafficToSmallScaleCommercial = new DefaultIntegrateExistingTrafficToSmallScaleCommercialImpl(); + log.info("Using default {} if existing models are integrated!", DefaultIntegrateExistingTrafficToSmallScaleCommercialImpl.class.getSimpleName()); + } else { + this.integrateExistingTrafficToSmallScaleCommercial = integrateExistingTrafficToSmallScaleCommercial; + log.info("Using {} if existing models are integrated!", integrateExistingTrafficToSmallScaleCommercial.getClass().getSimpleName()); + } + if (getCommercialTourSpecifications == null){ + this.getCommercialTourSpecifications = new DefaultTourSpecificationsByUsingKID2002(); + log.info("Using default {} for tour specifications!", DefaultTourSpecificationsByUsingKID2002.class.getSimpleName()); + } else { + this.getCommercialTourSpecifications = getCommercialTourSpecifications; + log.info("Using {} for tour specifications!", getCommercialTourSpecifications.getClass().getSimpleName()); + } } public static void main(String[] args) { @@ -289,8 +305,8 @@ public Integer call() throws Exception { } /** Creates a map with the different facility types per building. - * @param scenario - * @param facilitiesPerZone + * @param scenario complete Scenario + * @param facilitiesPerZone Map with facilities per zone */ private void filterFacilitiesForZones(Scenario scenario, Map>> facilitiesPerZone) { scenario.getActivityFacilities().getFacilities().values().forEach((activityFacility -> { @@ -552,15 +568,14 @@ private void createCarriers(Scenario scenario, TripDistributionMatrix odMatrix, int createdCarrier = 0; int fixedNumberOfVehiclePerTypeAndLocation = 1; //TODO possible improvement, perhaps check KiD - EnumeratedDistribution tourDistribution = createTourDistribution(smallScaleCommercialTrafficType); + EnumeratedDistribution tourDistribution = getCommercialTourSpecifications.createTourDistribution(smallScaleCommercialTrafficType, rng); - Map stopDurationTimeSelector = createStopDurationTimeDistributionPerCategory( - smallScaleCommercialTrafficType); + Map> stopDurationTimeSelector = getCommercialTourSpecifications.createStopDurationDistributionPerCategory(smallScaleCommercialTrafficType, rng); CarrierVehicleTypes carrierVehicleTypes = CarriersUtils.getCarrierVehicleTypes(scenario); Map, VehicleType> additionalCarrierVehicleTypes = scenario.getVehicles().getVehicleTypes(); - // Only vehicle with cost information will work properly + // Only a vehicle with cost information will work properly additionalCarrierVehicleTypes.values().stream() .filter(vehicleType -> vehicleType.getCostInformation().getCostsPerSecond() != null) .forEach(vehicleType -> carrierVehicleTypes.getVehicleTypes().putIfAbsent(vehicleType.getId(), vehicleType)); @@ -586,6 +601,7 @@ private void createCarriers(Scenario scenario, TripDistributionMatrix odMatrix, } } } + //TODO make vehcile selection configurable if (isStartingLocation) { double occupancyRate = 0; String[] possibleVehicleTypes = null; @@ -698,7 +714,7 @@ private void createCarriers(Scenario scenario, TripDistributionMatrix odMatrix, String[] serviceArea = new String[]{stopZone}; int serviceTimePerStop; if (selectedStartCategory.equals("Inhabitants")) - serviceTimePerStop = getServiceTimePerStop(stopDurationTimeSelector, startCategory.get(0), modeORvehType, smallScaleCommercialTrafficType); + serviceTimePerStop = getServiceTimePerStop(stopDurationTimeSelector, startCategory.getFirst(), modeORvehType, smallScaleCommercialTrafficType); else serviceTimePerStop = getServiceTimePerStop(stopDurationTimeSelector, selectedStartCategory, modeORvehType, smallScaleCommercialTrafficType); @@ -718,10 +734,10 @@ private void createCarriers(Scenario scenario, TripDistributionMatrix odMatrix, // System.out.println("Final results for the tour duration distribution"); // tourDurationTimeSelector.writeResults(); - for (StopDurationGoodTrafficKey sector : stopDurationTimeSelector.keySet()) { - System.out.println("Final results for the stop duration distribution in sector " + sector); - stopDurationTimeSelector.get(sector).writeResults(); - } +// for (StopDurationGoodTrafficKey sector : stopDurationTimeSelector.keySet()) { +// System.out.println("Final results for the stop duration distribution in sector " + sector); +// stopDurationTimeSelector.get(sector); +// } log.warn("The jspritIterations are now set to {} in this simulation!", jspritIterations); log.info("Finished creating {} carriers including related services.", createdCarrier); @@ -834,13 +850,13 @@ private int getVehicleStartTime(TourStartAndDuration t) { /** * Give a service duration based on the purpose and the trafficType under a given probability * - * @param serviceDurationTimeSelector - * @param employeeCategory - * @param modeORvehType - * @param smallScaleCommercialTrafficType - * @return + * @param serviceDurationTimeSelector the selector for the service duration + * @param employeeCategory the category of the employee + * @param modeORvehType the mode or vehicle type + * @param smallScaleCommercialTrafficType the traffic type + * @return the service duration */ - private Integer getServiceTimePerStop(Map serviceDurationTimeSelector, + private Integer getServiceTimePerStop(Map> serviceDurationTimeSelector, String employeeCategory, String modeORvehType, String smallScaleCommercialTrafficType) { StopDurationGoodTrafficKey key = null; @@ -849,10 +865,9 @@ private Integer getServiceTimePerStop(Map tourStartProbabilityDistribution = new ArrayList<>(); - if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "1", 0.002)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("1", "2", 0.001)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("2", "3", 0.001)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("3", "4", 0.002)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("4", "5", 0.008)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("5", "6", 0.031)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("6", "7", 0.144)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("7", "8", 0.335)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("8", "9", 0.182)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("9", "10", 0.108)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "11", 0.057)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("11", "12", 0.032)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("12", "13", 0.021)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("13", "14", 0.021)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("14", "15", 0.019)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("15", "16", 0.012)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("16", "17", 0.009)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("17", "18", 0.006)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("18", "19", 0.004)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("19", "20", 0.003)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "21", 0.001)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("22", "23", 0.001)); - } else if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.goodsTraffic.toString())) { - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "1", 0.008)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("1", "2", 0.003)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("2", "3", 0.008)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("3", "4", 0.012)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("4", "5", 0.028)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("5", "6", 0.052)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("6", "7", 0.115)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("7", "8", 0.222)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("8", "9", 0.197)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("9", "10", 0.14)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "11", 0.076)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("11", "12", 0.035)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("12", "13", 0.022)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("13", "14", 0.022)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("14", "15", 0.021)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("15", "16", 0.014)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("16", "17", 0.008)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("17", "18", 0.005)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("18", "19", 0.004)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("19", "20", 0.002)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "21", 0.001)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("21", "22", 0.001)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("22", "23", 0.002)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("23", "24", 0.001)); - - } - return new ValueSelectorUnderGivenProbability(tourStartProbabilityDistribution, rnd); - } - - /** - * Creates the probability distribution for the tour duration for the day. - * The values are given in [h] and have an upperBound. - * Data source: KiD 2002 - * - * @return - */ - private ValueSelectorUnderGivenProbability createTourDurationTimeDistribution(String smallScaleCommercialTrafficType) { - List tourDurationProbabilityDistribution = new ArrayList<>(); - if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "1", 0.14)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("1", "2", 0.066)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("2", "3", 0.056)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("3", "4", 0.052)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("4", "5", 0.061)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("5", "6", 0.063)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("6", "7", 0.07)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("7", "8", 0.086)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("8", "9", 0.14)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("9", "10", 0.122)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "11", 0.068)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("11", "12", 0.031)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("12", "13", 0.018)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("13", "14", 0.01)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("14", "15", 0.006)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("15", "16", 0.003)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("16", "17", 0.002)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("17", "18", 0.001)); - } else if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.goodsTraffic.toString())) { - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "1", 0.096)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("1", "2", 0.074)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("2", "3", 0.065)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("3", "4", 0.071)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("4", "5", 0.086)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("5", "6", 0.084)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("6", "7", 0.084)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("7", "8", 0.101)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("8", "9", 0.118)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("9", "10", 0.092)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "11", 0.048)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("11", "12", 0.027)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("12", "13", 0.015)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("13", "14", 0.011)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("14", "15", 0.006)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("15", "16", 0.004)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("16", "17", 0.002)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("17", "18", 0.001)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("18", "19", 0.001)); - } - - return new ValueSelectorUnderGivenProbability(tourDurationProbabilityDistribution, rnd); - } - - private EnumeratedDistribution createTourDistribution(String smallScaleCommercialTrafficType) { - List> tourDurationProbabilityDistribution = new ArrayList<>(); - - if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { - - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 0.0, 30.0), 0.0005917893035900173)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 30.0, 60.0), 0.00021859484237437887)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 90.0, 120.0), 0.00037490287407786324)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 120.0, 180.0), 0.0004337321926125666)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 180.0, 240.0), 0.0005834182239827621)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 240.0, 300.0), 0.0005116938323661723)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 300.0, 360.0), 0.0005027065159573272)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 360.0, 420.0), 0.0006719740164147071)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 420.0, 480.0), 0.00022375027665644004)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 480.0, 540.0), 0.00022103749529549306)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 540.0, 600.0), 0.00022119440831885122)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 600.0, 660.0), 0.0002732185104003396)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 660.0, 720.0), 7.287567629774946e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 720.0, 780.0), 0.0005090670761685264)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 780.0, 840.0), 0.0002169454122557984)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 840.0, 1080.0), 0.0016947794402011696)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 0.0, 30.0), 0.00033050926084770643)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 30.0, 60.0), 0.0004963985976117265)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 60.0, 90.0), 0.0009458837608304906)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 90.0, 120.0), 0.0006507941771038976)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 120.0, 180.0), 0.0002949035696660126)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 180.0, 240.0), 0.0005812406149568905)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 240.0, 300.0), 0.00072666224822023)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 300.0, 360.0), 0.0006017750128936798)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 360.0, 420.0), 0.0007696491628020603)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 420.0, 480.0), 0.0006951014583380694)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 480.0, 540.0), 0.0006675367479652174)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 540.0, 600.0), 0.0009951412624367468)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 600.0, 660.0), 0.0006193958232902363)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 660.0, 720.0), 0.0005496335422364244)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 720.0, 780.0), 0.000963763774344583)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 780.0, 840.0), 0.001585152586657775)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 840.0, 1080.0), 0.0022779973751500433)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 0.0, 30.0), 0.003678291745870938)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 30.0, 60.0), 0.0037749680865755936)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 60.0, 90.0), 0.0021464058981758467)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 90.0, 120.0), 0.0010105726369455444)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 120.0, 180.0), 0.0017166729332290624)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 180.0, 240.0), 0.001218657902054598)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 240.0, 300.0), 0.0019212859349972463)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 300.0, 360.0), 0.0018498349748915703)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 360.0, 420.0), 0.0020820722844894844)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 420.0, 480.0), 0.0033255032578691536)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 480.0, 540.0), 0.004499580798913233)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 540.0, 600.0), 0.004508722079694882)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 600.0, 660.0), 0.009460453046374911)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 660.0, 720.0), 0.008632039128635343)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 720.0, 780.0), 0.005173130409039029)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 780.0, 840.0), 0.0021287189901771954)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 840.0, 1080.0), 0.002735246591728173)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 0.0, 30.0), 0.015534599731489868)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 30.0, 60.0), 0.009424737666749776)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 60.0, 90.0), 0.003979757502241877)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 90.0, 120.0), 0.0026219034509082214)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 120.0, 180.0), 0.004373894821911171)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 180.0, 240.0), 0.005349695968407728)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 240.0, 300.0), 0.008398668008895199)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 300.0, 360.0), 0.013017576110359298)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 360.0, 420.0), 0.013178466937493282)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 420.0, 480.0), 0.015799261066253244)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 480.0, 540.0), 0.031932993774084484)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 540.0, 600.0), 0.056976770375347194)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 600.0, 660.0), 0.03411514635058722)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 660.0, 720.0), 0.010952547256934878)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 720.0, 780.0), 0.005071677294689363)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 780.0, 840.0), 0.002758017802376135)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 840.0, 1080.0), 0.003182481371327368)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 0.0, 30.0), 0.018010507239762663)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 30.0, 60.0), 0.009246211080247332)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 60.0, 90.0), 0.006297103845359016)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 90.0, 120.0), 0.003415561088528113)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 120.0, 180.0), 0.010918022744746231)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 180.0, 240.0), 0.011371721163141522)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 240.0, 300.0), 0.01861910064916215)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 300.0, 360.0), 0.015443374909900384)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 360.0, 420.0), 0.020470726990450452)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 420.0, 480.0), 0.030727618880727087)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 480.0, 540.0), 0.07364088624635841)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 540.0, 600.0), 0.04082061588575034)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 600.0, 660.0), 0.012935881167590665)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 660.0, 720.0), 0.005469250367916343)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 720.0, 780.0), 0.0030030673084490513)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 780.0, 840.0), 0.0011042643367551329)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 840.0, 1080.0), 0.0011327583672022575)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 0.0, 30.0), 0.015589932735904798)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 30.0, 60.0), 0.007157798082590814)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 60.0, 90.0), 0.006563655710107534)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 90.0, 120.0), 0.004888423230467872)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 120.0, 180.0), 0.01261126944262904)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 180.0, 240.0), 0.013275311108363174)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 240.0, 300.0), 0.011059737216827653)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 300.0, 360.0), 0.00980644443311104)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 360.0, 420.0), 0.013476523854959467)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 420.0, 480.0), 0.01766932338862498)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 480.0, 540.0), 0.013855266610087914)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 540.0, 600.0), 0.006090238569895901)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 600.0, 660.0), 0.00326688741194661)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 660.0, 720.0), 0.0009742217966822537)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 720.0, 780.0), 0.0008462163162537791)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 780.0, 840.0), 0.0009357453082055104)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 840.0, 1080.0), 0.0006867783494497427)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 0.0, 30.0), 0.011836581569331607)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 30.0, 60.0), 0.0060475163532472224)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 60.0, 90.0), 0.006091033719221284)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 90.0, 120.0), 0.004870323217391879)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 120.0, 180.0), 0.009852214102720915)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 180.0, 240.0), 0.006649077724867284)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 240.0, 300.0), 0.006549809619698136)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 300.0, 360.0), 0.00743649188225418)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 360.0, 420.0), 0.008370330719772223)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 420.0, 480.0), 0.006055410372169952)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 480.0, 540.0), 0.003221026290023441)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 540.0, 600.0), 0.00270804359225063)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 600.0, 660.0), 0.0011328763880567346)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 660.0, 720.0), 0.0005295062815147344)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 720.0, 780.0), 0.0005244739409173669)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 780.0, 840.0), 0.00022261373811852168)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 840.0, 1080.0), 0.0002976820307410009)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 0.0, 30.0), 0.0072347359578799255)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 30.0, 60.0), 0.005528762818372258)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 60.0, 90.0), 0.004301874597910846)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 90.0, 120.0), 0.002706271535768685)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 120.0, 180.0), 0.004461225555303183)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 180.0, 240.0), 0.003289266637558867)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 240.0, 300.0), 0.004773112389257731)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 300.0, 360.0), 0.004153307715767419)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 360.0, 420.0), 0.0023002274828502435)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 420.0, 480.0), 0.002295722460734858)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 480.0, 540.0), 0.0008008191218782178)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 540.0, 600.0), 0.0005302938593833011)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 600.0, 660.0), 0.00012017333498779025)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 660.0, 720.0), 0.00029497120761336085)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 720.0, 780.0), 7.442207741095891e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 780.0, 840.0), 7.491510042413546e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 0.0, 30.0), 0.005979044848708125)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 30.0, 60.0), 0.0030727725862362003)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 60.0, 90.0), 0.0018328582061095421)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 90.0, 120.0), 0.0015730248216810105)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 120.0, 180.0), 0.0025909176745678485)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 180.0, 240.0), 0.0023584284876344117)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 240.0, 300.0), 0.002888683132930499)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 300.0, 360.0), 0.0026723295114103734)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 360.0, 420.0), 0.001368034507711622)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 420.0, 480.0), 0.001322142609646873)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 480.0, 540.0), 0.00014896322977011863)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 540.0, 600.0), 0.00036793050573151096)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 600.0, 660.0), 0.0003024749417379503)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 660.0, 720.0), 7.263766179594998e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 720.0, 780.0), 7.737798495114381e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 840.0, 1080.0), 7.360037219024495e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 0.0, 30.0), 0.005442934607459622)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 30.0, 60.0), 0.0023099603288455053)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 60.0, 90.0), 0.0015476125810207045)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 90.0, 120.0), 0.0015690710859882222)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 120.0, 180.0), 0.003155552178314994)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 180.0, 240.0), 0.0024715148201473933)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 240.0, 300.0), 0.00214638868043489)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 300.0, 360.0), 0.0017134793037846727)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 360.0, 420.0), 0.0009684921868733149)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 420.0, 480.0), 0.0005519992558366529)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 480.0, 540.0), 0.0004441672064981391)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 540.0, 600.0), 0.00022332686365997108)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 600.0, 660.0), 0.00023780343565208111)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 660.0, 720.0), 0.00014898555439278127)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 0.0, 30.0), 0.0065652971880044205)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 30.0, 60.0), 0.0033645458423904226)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 60.0, 90.0), 0.002247264924524252)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 90.0, 120.0), 0.0021755851670695867)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 120.0, 180.0), 0.00292250684836152)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 180.0, 240.0), 0.0029939610328467135)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 240.0, 300.0), 0.0013771262994841458)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 300.0, 360.0), 0.0005929387919824101)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 360.0, 420.0), 0.0007299574379337656)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 420.0, 480.0), 0.00015161310680499916)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 480.0, 540.0), 0.00022326623210165028)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 540.0, 600.0), 0.00021908720500178134)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 0.0, 30.0), 0.004700575755513116)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 30.0, 60.0), 0.002876930233578738)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 60.0, 90.0), 0.0012326059557891803)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 90.0, 120.0), 0.001688513011030605)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 120.0, 180.0), 0.0024148215923521744)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 180.0, 240.0), 0.0009664823712470381)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 240.0, 300.0), 0.0008158516384741175)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 300.0, 360.0), 0.0005326476409500361)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 360.0, 420.0), 0.00037447250704764534)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 420.0, 480.0), 7.278074100962308e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 480.0, 540.0), 0.00015460621875651884)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 540.0, 600.0), 0.00022625636961834557)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 840.0, 1080.0), 7.369704340227916e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 0.0, 30.0), 0.005421542133242069)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 30.0, 60.0), 0.0028543297205245563)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 60.0, 90.0), 0.001320449445343739)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 90.0, 120.0), 0.0011372744623221703)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 120.0, 180.0), 0.0011175546229352943)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 180.0, 240.0), 0.0005212091408906178)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 240.0, 300.0), 0.00025063117439263165)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 300.0, 360.0), 0.0002906557976189996)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 360.0, 420.0), 6.934683987097806e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 420.0, 480.0), 7.198332684426051e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 0.0, 30.0), 0.005997678933359281)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 30.0, 60.0), 0.0014450238860978966)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 60.0, 90.0), 0.0008909835110546583)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 90.0, 120.0), 0.0008692603958852261)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 120.0, 180.0), 0.0004645626068627116)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 180.0, 240.0), 0.0005161866418057845)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 240.0, 300.0), 0.00047492492382272117)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 300.0, 360.0), 7.348989097075777e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 360.0, 420.0), 0.0003000342936128893)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 0.0, 30.0), 0.004621906661329853)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 30.0, 60.0), 0.0015152391398060199)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 60.0, 90.0), 0.0006769045119123614)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 90.0, 120.0), 0.00044820275277284946)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 120.0, 180.0), 0.0007140653752077821)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 180.0, 240.0), 0.0001502672132808765)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 240.0, 300.0), 0.0003842231300012746)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 300.0, 360.0), 0.00021634404805889257)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 0.0, 30.0), 0.0034023082743939916)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 30.0, 60.0), 0.0006251774232962365)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 60.0, 90.0), 0.00022163965781205308)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 90.0, 120.0), 7.360037219024495e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 120.0, 180.0), 0.00045934601255169126)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 180.0, 240.0), 7.511874968194916e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 240.0, 300.0), 0.0001486019187134722)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 300.0, 360.0), 7.505084488366769e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 420.0, 480.0), 7.594714627228585e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 0.0, 30.0), 0.005137034953520923)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 30.0, 60.0), 0.0010774703023578233)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 60.0, 90.0), 0.00048539418673270443)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 90.0, 120.0), 0.0002988049182984063)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 120.0, 180.0), 0.00032644209078127245)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 180.0, 240.0), 0.0005357497395368892)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 240.0, 300.0), 0.0002944914928100358)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 300.0, 360.0), 0.00022851651374757815)); - } - else if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.goodsTraffic.toString())) { - - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 0.0, 30.0), 0.0002666800577200411)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 30.0, 60.0), 0.0006395055678719748)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 60.0, 90.0), 0.0007110769046958423)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 90.0, 120.0), 0.0006665961628449491)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 120.0, 180.0), 0.0023195866923785575)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 180.0, 240.0), 0.00261751319938476)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 240.0, 300.0), 0.0021430032453503087)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 300.0, 360.0), 0.0029303876579925905)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 360.0, 420.0), 0.00283576618143643)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 420.0, 480.0), 0.0027188265347502893)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 480.0, 540.0), 0.002597768116531099)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 540.0, 600.0), 0.002659151494701916)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 600.0, 660.0), 0.0021738406044924437)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 660.0, 720.0), 0.0021949848461843176)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 720.0, 780.0), 0.0021801193011023083)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 780.0, 840.0), 0.001746033717539671)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 840.0, 1080.0), 0.00350888397405923)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 0.0, 30.0), 0.0006845643884312735)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 30.0, 60.0), 0.0004003126952082357)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 60.0, 90.0), 0.0008155012585632697)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 90.0, 120.0), 0.0010930534970200114)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 120.0, 180.0), 0.0011760353713952051)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 180.0, 240.0), 0.0019364061980548415)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 240.0, 300.0), 0.002953452881036028)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 300.0, 360.0), 0.002589370165068672)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 360.0, 420.0), 0.0025604405819583055)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 420.0, 480.0), 0.0034319041631081476)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 480.0, 540.0), 0.0033480025727905907)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 540.0, 600.0), 0.002175717502193024)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 600.0, 660.0), 0.0028036478238686957)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 660.0, 720.0), 0.0028759635193342887)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 720.0, 780.0), 0.0017584406503249872)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 780.0, 840.0), 0.0016742001219093045)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 840.0, 1080.0), 0.0020658205220468245)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 0.0, 30.0), 0.0017247403950228777)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 30.0, 60.0), 0.003090998236080484)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 60.0, 90.0), 0.0015209554995803177)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 90.0, 120.0), 0.0016533392810110293)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 120.0, 180.0), 0.003732306124403562)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 180.0, 240.0), 0.004106247357091271)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 240.0, 300.0), 0.003188442431357427)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 300.0, 360.0), 0.005929370570550301)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 360.0, 420.0), 0.005992695595693005)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 420.0, 480.0), 0.006390572360276255)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 480.0, 540.0), 0.00993732232424166)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 540.0, 600.0), 0.007917613781985494)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 600.0, 660.0), 0.00753055040114282)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 660.0, 720.0), 0.004839531706746983)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 720.0, 780.0), 0.003571294178536547)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 780.0, 840.0), 0.0022261075091276465)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 840.0, 1080.0), 0.0020123396391017526)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 0.0, 30.0), 0.00553085745500388)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 30.0, 60.0), 0.005164301035284355)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 60.0, 90.0), 0.0034287284279468384)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 90.0, 120.0), 0.003359657704287739)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 120.0, 180.0), 0.005963896679549981)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 180.0, 240.0), 0.006376396116305889)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 240.0, 300.0), 0.011553162434249647)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 300.0, 360.0), 0.01216390369869719)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 360.0, 420.0), 0.015303642980241483)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 420.0, 480.0), 0.01894502604909179)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 480.0, 540.0), 0.026995818384739457)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 540.0, 600.0), 0.03735238580259259)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 600.0, 660.0), 0.02007351137947408)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 660.0, 720.0), 0.007579189226621267)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 720.0, 780.0), 0.003806896198418994)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 780.0, 840.0), 0.0020371212990837376)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 840.0, 1080.0), 0.00246729057836831)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 0.0, 30.0), 0.007834929725170775)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 30.0, 60.0), 0.007875284751511802)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 60.0, 90.0), 0.0056369706407995695)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 90.0, 120.0), 0.007252792818630801)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 120.0, 180.0), 0.011595289158181222)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 180.0, 240.0), 0.01584695155572567)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 240.0, 300.0), 0.019385993489144607)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 300.0, 360.0), 0.01804569113072999)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 360.0, 420.0), 0.020338168968415053)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 420.0, 480.0), 0.03244941203821404)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 480.0, 540.0), 0.046986423884473)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 540.0, 600.0), 0.026127574804977814)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 600.0, 660.0), 0.006859707180170414)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 660.0, 720.0), 0.004053368732850601)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 720.0, 780.0), 0.0017728320836715625)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 780.0, 840.0), 0.0008117046283836942)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 840.0, 1080.0), 0.0014889766393137468)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 0.0, 30.0), 0.008702611915372131)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 30.0, 60.0), 0.009703391735884857)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 60.0, 90.0), 0.00833249802530372)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 90.0, 120.0), 0.008160824294542027)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 120.0, 180.0), 0.014522058792957903)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 180.0, 240.0), 0.019189639247661674)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 240.0, 300.0), 0.022628081955363144)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 300.0, 360.0), 0.018168175275565253)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 360.0, 420.0), 0.01830766579908246)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 420.0, 480.0), 0.022414786327228577)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 480.0, 540.0), 0.015454698179801149)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 540.0, 600.0), 0.00743339793333549)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 600.0, 660.0), 0.0028959167218627997)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 660.0, 720.0), 0.0011608823477359163)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 720.0, 780.0), 0.0006126324367099846)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 780.0, 840.0), 0.0007090395380022889)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 840.0, 1080.0), 0.0009650931773638335)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 0.0, 30.0), 0.010532384705529854)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 30.0, 60.0), 0.010106787618396446)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 60.0, 90.0), 0.007305519187631069)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 90.0, 120.0), 0.0065298278976416635)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 120.0, 180.0), 0.012991661099288086)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 180.0, 240.0), 0.011082392048301831)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 240.0, 300.0), 0.013735041027849332)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 300.0, 360.0), 0.012921165569106639)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 360.0, 420.0), 0.010187951930469277)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 420.0, 480.0), 0.0070071162811467125)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 480.0, 540.0), 0.003478434072337058)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 540.0, 600.0), 0.002487434148850001)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 600.0, 660.0), 0.0007617139935295275)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 660.0, 720.0), 0.0004794259473854554)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 720.0, 780.0), 0.00011828408353297643)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 780.0, 840.0), 0.0009221448817170415)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 0.0, 30.0), 0.0053803765038808364)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 30.0, 60.0), 0.00748440387556175)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 60.0, 90.0), 0.003817044622559703)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 90.0, 120.0), 0.0042559767658946045)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 120.0, 180.0), 0.004633517730561146)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 180.0, 240.0), 0.0040156278424527785)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 240.0, 300.0), 0.004097425621422603)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 300.0, 360.0), 0.00534407493573042)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 360.0, 420.0), 0.002849425985304954)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 420.0, 480.0), 0.0024443772372422234)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 480.0, 540.0), 0.0011258612568464076)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 540.0, 600.0), 0.0005966047093584399)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 600.0, 660.0), 0.0005779388889435179)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 660.0, 720.0), 0.0004527621290439082)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 720.0, 780.0), 0.00011727646428602624)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 780.0, 840.0), 0.00011130198744577025)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 0.0, 30.0), 0.0025301846046864363)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 30.0, 60.0), 0.002932856090944951)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 60.0, 90.0), 0.0015297442159744696)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 90.0, 120.0), 0.0016816440829740813)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 120.0, 180.0), 0.0023140070407952395)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 180.0, 240.0), 0.0013768767086426792)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 240.0, 300.0), 0.0019019317686819275)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 300.0, 360.0), 0.0015577691125463963)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 360.0, 420.0), 0.001499121306916632)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 420.0, 480.0), 0.0007361366421130972)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 480.0, 540.0), 0.0007423049940853575)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 540.0, 600.0), 0.00011130198744577025)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 660.0, 720.0), 0.00024243947114654707)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 720.0, 780.0), 0.000261579996858755)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 0.0, 30.0), 0.0021669594044717543)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 30.0, 60.0), 0.0033993161916113994)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 60.0, 90.0), 0.001870484877697732)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 90.0, 120.0), 0.0008448185262884799)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 120.0, 180.0), 0.002024573233571085)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 180.0, 240.0), 0.0021888099857994042)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 240.0, 300.0), 0.0021657834323017752)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 300.0, 360.0), 0.0010623089332746248)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 360.0, 420.0), 0.0006268095760401356)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 420.0, 480.0), 0.0005094532977538987)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 480.0, 540.0), 0.0004744090926784203)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 540.0, 600.0), 0.00016487328572417658)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 660.0, 720.0), 0.0001162996982120756)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 0.0, 30.0), 0.0033401411497772818)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 30.0, 60.0), 0.002492685695459365)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 60.0, 90.0), 0.0027064477589805068)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 90.0, 120.0), 0.0018052297053924354)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 120.0, 180.0), 0.0027984509294891498)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 180.0, 240.0), 0.0022758505657711914)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 240.0, 300.0), 0.0003535503655144059)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 300.0, 360.0), 0.0005890430396050117)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 360.0, 420.0), 0.0002319134363595028)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 420.0, 480.0), 0.00011617748025141993)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 480.0, 540.0), 0.0003690064941818713)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 540.0, 600.0), 0.0001650495071007077)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 600.0, 660.0), 0.00023113252306835525)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 840.0, 1080.0), 0.00017239206443126303)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 0.0, 30.0), 0.003543871129770451)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 30.0, 60.0), 0.0018407982276338393)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 60.0, 90.0), 0.0010649270862293423)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 90.0, 120.0), 0.0009538696044712171)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 120.0, 180.0), 0.0021318639289119572)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 180.0, 240.0), 0.0019740243143620277)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 240.0, 300.0), 0.0006157677659961421)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 300.0, 360.0), 0.0004035374922773149)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 360.0, 420.0), 0.00011607019237524387)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 420.0, 480.0), 0.0003938282727195195)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 480.0, 540.0), 0.00011130198744577025)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 600.0, 660.0), 0.00011942109323430472)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 0.0, 30.0), 0.00254340964132742)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 30.0, 60.0), 0.0017847751078888892)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 60.0, 90.0), 0.000841891386995212)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 90.0, 120.0), 0.0003543852337006742)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 120.0, 180.0), 0.0013974221085794884)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 180.0, 240.0), 0.0006229273683665316)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 240.0, 300.0), 0.00020579571489011056)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 300.0, 360.0), 0.0004809214516599411)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 360.0, 420.0), 0.00022514291890117063)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 420.0, 480.0), 0.00014748146383900364)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 720.0, 780.0), 0.00011605559293173729)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 0.0, 30.0), 0.0019634787835054656)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 30.0, 60.0), 0.000860670737476427)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 60.0, 90.0), 0.0003550148096943092)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 90.0, 120.0), 0.000855728546868917)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 120.0, 180.0), 0.0009283998993093458)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 180.0, 240.0), 0.00022795178106384156)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 240.0, 300.0), 0.00024119874825349313)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 420.0, 480.0), 0.00023429279224671318)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 480.0, 540.0), 0.00011727269965059726)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 660.0, 720.0), 0.00011130198744577025)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 0.0, 30.0), 0.0017099830161073832)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 30.0, 60.0), 0.0006015092064895483)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 60.0, 90.0), 0.00011819436012345105)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 90.0, 120.0), 0.0002279569151752547)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 120.0, 180.0), 0.0006440525787748041)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 180.0, 240.0), 0.0003142746964600832)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 300.0, 360.0), 0.00022788575876606104)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 360.0, 420.0), 0.0004761806298753505)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 480.0, 540.0), 0.00011727269965059726)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 0.0, 30.0), 0.0020011795184968267)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 30.0, 60.0), 0.00023620950461199452)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 60.0, 90.0), 0.00011935825257957617)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 90.0, 120.0), 0.00011130198744577025)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 120.0, 180.0), 0.00012222981614916706)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 180.0, 240.0), 0.0002377005397786721)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 240.0, 300.0), 0.00026373526728965034)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 300.0, 360.0), 0.000256086036315955)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 360.0, 420.0), 0.00011394287938236544)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 0.0, 30.0), 0.0021116872169622083)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 30.0, 60.0), 0.0003681765715703113)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 60.0, 90.0), 0.0004137833254678062)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 90.0, 120.0), 0.00025108497234833097)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 120.0, 180.0), 0.0007576827338029722)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 180.0, 240.0), 0.0005180490039062906)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 240.0, 300.0), 0.0004944106124208977)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 300.0, 360.0), 0.0002278857587658224)); - } else - throw new IllegalArgumentException("Unknown small scale commercial traffic type: " + smallScaleCommercialTrafficType); - - return new EnumeratedDistribution<>(rng, tourDurationProbabilityDistribution); - } - - /** - * Creates the probability distribution for the duration of the services. - * The values are given in [min] and have an upperBound. - * Data source: KiD 2002 - * - * @param smallScaleCommercialTrafficType - * @return - */ - private Map createStopDurationTimeDistributionPerCategory(String smallScaleCommercialTrafficType) { - - Map stopDurationProbabilityDistribution = new HashMap<>(); - if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { - List singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "30", 0.098)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "60", 0.17)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "90", 0.127)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.11)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "180", 0.17)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.076)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.057)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "360", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("360", "420", 0.026)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "480", 0.045)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("480", "540", 0.064)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "600", 0.034)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("600", "720", 0.012)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("720", "840", 0.002)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", null), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "30", 0.054)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "60", 0.164)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "90", 0.153)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.087)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "180", 0.12)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.055)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.044)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "360", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("360", "420", 0.025)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "480", 0.069)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("480", "540", 0.132)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "600", 0.058)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("600", "720", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("720", "840", 0.002)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", null), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "30", 0.13)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "60", 0.324)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "90", 0.178)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.108)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "180", 0.097)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.034)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "360", 0.018)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("360", "420", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "480", 0.027)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("480", "540", 0.029)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "600", 0.008)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("600", "720", 0.006)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("720", "840", 0.001)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest",null), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "30", 0.178)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "60", 0.301)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "90", 0.192)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.104)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "180", 0.092)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.043)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.013)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "360", 0.017)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("360", "420", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "480", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("480", "540", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "600", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("600", "720", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("720", "840", 0.001)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail",null), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "30", 0.144)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "60", 0.372)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "90", 0.203)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.069)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "180", 0.112)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.038)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "360", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("360", "420", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "480", 0.012)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("480", "540", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "600", 0.005)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("600", "720", 0.005)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels",null), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "30", 0.196)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "60", 0.292)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "90", 0.19)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.101)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "180", 0.105)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.034)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.017)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "360", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("360", "420", 0.013)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "480", 0.019)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("480", "540", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "600", 0.006)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("600", "720", 0.004)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("720", "840", 0.001)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest",null), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - } else if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.goodsTraffic.toString())) { - List singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.038)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.049)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.052)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.094)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.125)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.094)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.167)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.094)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.113)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.056)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.04)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.026)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.002)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp1"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.025)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.025)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.05)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.043)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.112)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.168)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.149)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.081)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.168)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.068)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.068)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.025)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.019)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp2"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.036)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.098)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.036)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.042)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.124)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.085)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.144)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.105)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.052)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.072)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.052)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.023)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.033)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.062)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("660", "780", 0.003)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp3"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.071)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.143)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.429)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.179)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.107)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.071)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp4"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.026)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.395)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.158)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.132)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.026)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.105)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.079)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.026)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.053)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp5"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.033)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.064)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.109)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.088)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.095)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.112)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.105)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.114)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.053)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.088)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.038)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.012)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.051)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.015)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp1"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.027)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.061)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.045)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.068)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.083)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.112)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.114)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.146)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.058)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.114)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.036)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.022)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.065)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.023)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp2"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.04)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.074)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.09)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.086)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.069)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.113)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.135)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.071)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.008)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.044)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.041)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.03)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.021)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.075)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.022)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp3"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.036)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.055)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.018)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.236)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.073)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.018)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.164)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.091)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.109)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.055)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.018)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.055)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.055)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.018)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp4"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.163)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.21)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.165)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.125)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.095)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.101)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.04)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.03)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.006)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.008)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.002)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.004)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.008)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.004)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp5"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.072)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.093)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.123)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.113)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.137)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.081)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.102)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.087)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.079)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.032)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.021)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.018)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "780", 0.002)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp1"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.062)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.14)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.093)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.115)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.133)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.102)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.098)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.071)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.067)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.038)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.027)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.011)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp2"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.051)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.214)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.146)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.129)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.10)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.072)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.083)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.063)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.054)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.022)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.008)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "900", 0.003)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp3"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.163)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.224)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.153)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.061)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.173)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.082)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.122)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.01)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp4"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.003)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.195)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.225)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.16)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.143)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.089)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.075)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.031)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.048)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.003)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "660", 0.009)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp5"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.057)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.108)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.093)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.133)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.133)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.11)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.102)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.064)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.104)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.049)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.015)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.015)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.003)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.005)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.006)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.003)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp1"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.084)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.119)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.183)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.076)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.085)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.101)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.124)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.069)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.057)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.041)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.002)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.025)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.004)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("780", "900", 0.002)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp2"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.103)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.23)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.193)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.08)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.065)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.071)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.072)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.044)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.054)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.035)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.013)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.003)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.003)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp3"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.094)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.179)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.094)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.245)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.123)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.075)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.094)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.038)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.019)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.019)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp4"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.066)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.063)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.142)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.165)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.135)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.102)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.122)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.033)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.086)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.043)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.023)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.017)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.003)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp5"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.159)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.173)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.173)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.088)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.115)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.071)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.051)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.041)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.031)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.017)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.007)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp1"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.292)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.135)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.062)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.197)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.051)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.079)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.022)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.045)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.056)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.034)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.006)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.022)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp2"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.092)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.111)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.224)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.173)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.09)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.103)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.045)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.028)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.056)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.017)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.019)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.025)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.006)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.006)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp3"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.146)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.098)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.146)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.195)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.268)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.012)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.037)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.012)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.012)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp4"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.026)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.042)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.062)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.121)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.133)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.144)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.144)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.104)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.121)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.046)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.026)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.005)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "900", 0.008)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp5"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.061)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.093)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.101)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.125)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.125)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.101)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.124)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.08)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.093)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.046)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.013)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.017)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.004)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.005)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp1"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.081)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.101)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.101)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.109)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.124)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.065)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.109)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.124)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.097)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.032)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.022)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.017)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.003)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.008)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp2"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.052)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.114)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.155)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.111)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.151)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.112)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.125)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.043)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.051)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.026)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("660", "780", 0.003)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp3"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.082)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.102)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.449)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.061)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.163)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.102)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.02)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp4"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.151)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.296)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.156)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.065)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.121)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.05)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.075)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.015)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.005)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.005)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp5"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - - - // because no data für private persons; use average numbers of all employee categories - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.056)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.084)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.095)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.118)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.12)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.096)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.112)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.083)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.095)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.045)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.033)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.022)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.018)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.004)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp1"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.077)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.093)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.103)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.092)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.098)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.091)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.108)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.092)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.095)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.043)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.035)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.021)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.007)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp2"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.06)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.141)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.152)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.107)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.094)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.087)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.089)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.067)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.06)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.037)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.023)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.025)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.015)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.012)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.006)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("660", "780", 0.001)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp3"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.062)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.11)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.12)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.144)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.151)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.129)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.062)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.079)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.041)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.031)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.019)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.002)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp4"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.099)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.147)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.17)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.133)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.108)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.116)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.058)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.075)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.03)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.005)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.004)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "660", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("660", "900", 0.002)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp5"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - } - return stopDurationProbabilityDistribution; - } - - private record StopDurationGoodTrafficKey(String employeeCategory, String vehicleType) { + public record StopDurationGoodTrafficKey(String employeeCategory, String vehicleType) { @Override public boolean equals(Object obj) { @@ -2573,10 +1224,12 @@ public boolean equals(Object obj) { } else return vehicleType.equals(other.vehicleType); } } - private StopDurationGoodTrafficKey makeStopDurationGoodTrafficKey(String employeeCategory, String vehicleType) { + public static StopDurationGoodTrafficKey makeStopDurationGoodTrafficKey(String employeeCategory, String vehicleType) { return new StopDurationGoodTrafficKey(employeeCategory, vehicleType); } - private record TourStartAndDuration(int hourLower, int hourUpper, double minDuration, double maxDuration) {} + public record TourStartAndDuration(int hourLower, int hourUpper, double minDuration, double maxDuration) {} + + public record DurationsBounds(int minDuration, int maxDuration) {} } diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java index 3af4dc1fa7f..e0b3a8b23ea 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java @@ -43,6 +43,7 @@ import org.matsim.core.network.NetworkUtils; import org.matsim.core.population.PopulationUtils; import org.matsim.core.utils.io.IOUtils; +import org.matsim.core.utils.misc.OptionalTime; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.CarriersUtils; import org.matsim.vehicles.Vehicle; @@ -116,7 +117,7 @@ public static Index getIndexBuildings(Path shapeFileBuildingsPath, String shapeC } /** - * Creates and return the Index of the regions shape. + * Creates and return the Index of the regions shapes. * * @param shapeFileRegionsPath Path to the shape file of the regions * @param shapeCRS CRS of the shape file @@ -131,13 +132,13 @@ public static Index getIndexRegions(Path shapeFileRegionsPath, String shapeCRS, } /** Finds the nearest possible link for the building polygon. - * @param zone - * @param noPossibleLinks - * @param linksPerZone - * @param newLink - * @param centroidPointOfBuildingPolygon - * @param numberOfPossibleLinks - * @return + * @param zone zone of the building + * @param noPossibleLinks list of links that are not possible + * @param linksPerZone map of links per zone + * @param newLink new link + * @param centroidPointOfBuildingPolygon centroid point of the building polygon + * @param numberOfPossibleLinks number of possible links + * @return new possible Link */ static Id findNearestPossibleLink(String zone, List noPossibleLinks, Map, Link>> linksPerZone, Id newLink, Coord centroidPointOfBuildingPolygon, int numberOfPossibleLinks) { @@ -199,21 +200,19 @@ static void createPlansBasedOnCarrierPlans(Scenario scenario, String smallScaleC String mode = allVehicles.getVehicles().get(vehicleId).getType().getNetworkMode(); List tourElements = person.getSelectedPlan().getPlanElements(); - double tourStartTime = 0; for (PlanElement tourElement : tourElements) { if (tourElement instanceof Activity activity) { Activity newActivity = PopulationUtils.createActivityFromCoord(activity.getType(), scenario.getNetwork().getLinks().get(activity.getLinkId()).getFromNode().getCoord()); + if (activity.getMaximumDuration() != OptionalTime.undefined()) + newActivity.setMaximumDuration(activity.getMaximumDuration().seconds()); if (activity.getType().equals("start")) { newActivity.setEndTime(activity.getEndTime().seconds()); newActivity.setType("commercial_start"); - } else - newActivity.setEndTimeUndefined(); - if (activity.getType().equals("end")) { - newActivity.setStartTime(tourStartTime + 8 * 3600); - newActivity.setType("commercial_end"); } + if (activity.getType().equals("end")) + newActivity.setType("commercial_end"); plan.addActivity(newActivity); } if (tourElement instanceof Leg) { @@ -284,9 +283,9 @@ static String findZoneOfLink(Id linkId, Map, Link>> l /** Reads the data distribution of the zones. - * @param pathToDataDistributionToZones - * @return - * @throws IOException + * @param pathToDataDistributionToZones Path to the data distribution of the zones + * @return resultingDataPerZone + * @throws IOException if the file is not found */ static Map> readDataDistribution(Path pathToDataDistributionToZones) throws IOException { if (!Files.exists(pathToDataDistributionToZones)) { diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/ValueSelectorUnderGivenProbability.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/ValueSelectorUnderGivenProbability.java deleted file mode 100644 index 8a2d7ef9407..00000000000 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/ValueSelectorUnderGivenProbability.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.matsim.smallScaleCommercialTrafficGeneration; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -/** This class creates a distribution under given probabilities for the possible values. - * - * @author: Ricardo Ewert - */ -public class ValueSelectorUnderGivenProbability { - - private int anIntAsSum; - private final List ProbabilityDistribution; - private final Random rnd; - - public ValueSelectorUnderGivenProbability(List ProbabilityDistribution, Random rnd) { - this.anIntAsSum = 0; - this.ProbabilityDistribution = ProbabilityDistribution; - this.rnd = rnd; - } - - - public ProbabilityForValue getNextValueUnderGivenProbability() { - anIntAsSum++; - weightedProbability(); - ProbabilityForValue selectedValue = null; - while (selectedValue == null) { - ProbabilityForValue probabilityForValue = ProbabilityDistribution.get(rnd.nextInt(ProbabilityDistribution.size())); - if (probabilityForValue.getRealizedValues() < probabilityForValue.getExpectedCount()) { - selectedValue = probabilityForValue; - selectedValue.increaseRealizedValue(1); - } - } - return selectedValue; - } - - private void weightedProbability() { - - //List to hold the cumulative probabilities of each value - List cumulativeProbabilities = new ArrayList<>(); - double sum = 0; - //Calculate cumulative probabilities for each value - for (ProbabilityForValue l : ProbabilityDistribution) { - sum += l.getProbability(); - cumulativeProbabilities.add(sum); - } - //Generate a random number between 0 and sum - double r = rnd.nextDouble(0.0, sum); - //Select a value based on the cumulative probabilities - String selectedLetter = ProbabilityDistribution.stream() - //Find the first value whose cumulative probability is greater than the random number - .filter(l -> r < cumulativeProbabilities.get(ProbabilityDistribution.indexOf(l))) - .findFirst().get().getValue(); - - //Increment the expectedCount for the selected value - ProbabilityDistribution.stream() - .filter(a -> a.getValue().equals(selectedLetter)) - .findFirst() - .ifPresent(l -> l.setExpectedCount(l.getExpectedCount() + 1)); - } - public void writeResults(){ - for (ProbabilityForValue probabilityForValue : ProbabilityDistribution) { - System.out.println(probabilityForValue.getValue() - + " -> expected: " + probabilityForValue.getExpectedCount() - + "(" + String.format("%.2f", (probabilityForValue.getExpectedCount() * Math.pow(anIntAsSum, - -1)) * 100) + " %); prob: " + ((double) Math.round(probabilityForValue.getProbability() * 1000) / 10) + "%"); - } - } - - public static class ProbabilityForValue { - - private String value; - private String upperBound; - private int expectedCount; - private double probability; - private int realizedValues; - - public ProbabilityForValue(String value, double probability) { - this.value = value; - this.probability = probability; - this.expectedCount = 0; - this.realizedValues = 0; - } - - - public ProbabilityForValue(String lowerBound, String upperBound, double probability) { - this.value = lowerBound; - this.upperBound = upperBound; - this.probability = probability; - this.expectedCount = 0; - this.realizedValues = 0; - } - - public double getProbability() { - return probability; - } - - public void setProbability(double probability) { - this.probability = probability; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public int getExpectedCount() { - return expectedCount; - } - - public void setExpectedCount(int expectedCount) { - this.expectedCount = expectedCount; - } - - public int getRealizedValues() { - return realizedValues; - } - - public void setRealizedValues(int realizedValues) { - this.realizedValues = realizedValues; - } - - public void increaseRealizedValue(int i) { - setRealizedValues(this.getRealizedValues() + i); - } - - public String getUpperBound() { - return upperBound; - } - - public void setUpperBound(String upperBound) { - this.upperBound = upperBound; - } - } -} diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/DefaultTourSpecificationsByUsingKID2002.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/DefaultTourSpecificationsByUsingKID2002.java new file mode 100644 index 00000000000..ec4bd9640ab --- /dev/null +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/DefaultTourSpecificationsByUsingKID2002.java @@ -0,0 +1,1390 @@ +package org.matsim.smallScaleCommercialTrafficGeneration.data; + +import org.apache.commons.math3.distribution.EnumeratedDistribution; +import org.apache.commons.math3.random.RandomGenerator; +import org.apache.commons.math3.util.Pair; +import org.matsim.smallScaleCommercialTrafficGeneration.GenerateSmallScaleCommercialTrafficDemand; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.matsim.smallScaleCommercialTrafficGeneration.GenerateSmallScaleCommercialTrafficDemand.makeStopDurationGoodTrafficKey; + +public class DefaultTourSpecificationsByUsingKID2002 implements GetCommercialTourSpecifications { + + @Override + public Map> createStopDurationDistributionPerCategory(String smallScaleCommercialTrafficType, RandomGenerator rng) { + Map> stopDurationProbabilityDistribution = new HashMap<>(); + + if (smallScaleCommercialTrafficType.equals(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { + List> thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 30), 0.098)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 60), 0.17)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 90), 0.127)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.11)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 180), 0.17)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.076)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.057)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 360), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(360, 420), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 480), 0.045)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(480, 540), 0.064)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 600), 0.034)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(600, 720), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(720, 840), 0.002)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector",null), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 30), 0.054)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 60), 0.164)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 90), 0.153)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.087)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 180), 0.12)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.055)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.044)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 360), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(360, 420), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 480), 0.069)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(480, 540), 0.132)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 600), 0.058)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(600, 720), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(720, 840), 0.002)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction",null), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 30), 0.13)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 60), 0.324)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 90), 0.178)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.108)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 180), 0.097)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.034)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 360), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(360, 420), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 480), 0.027)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(480, 540), 0.029)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 600), 0.008)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(600, 720), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(720, 840), 0.001)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest",null), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 30), 0.178)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 60), 0.301)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 90), 0.192)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.104)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 180), 0.092)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.043)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.013)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 360), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(360, 420), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 480), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(480, 540), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 600), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(600, 720), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(720, 840), 0.001)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail",null), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 30), 0.144)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 60), 0.372)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 90), 0.203)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.069)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 180), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.038)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 360), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(360, 420), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 480), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(480, 540), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 600), 0.005)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(600, 720), 0.005)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels",null), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 30), 0.196)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 60), 0.292)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 90), 0.19)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 180), 0.105)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.034)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 360), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(360, 420), 0.013)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 480), 0.019)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(480, 540), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 600), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(600, 720), 0.004)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(720, 840), 0.001)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest",null), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + + } else if (smallScaleCommercialTrafficType.equals(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString())) { + List> thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.038)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.049)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.052)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.125)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.167)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.113)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.056)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.04)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.002)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp1"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.05)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.043)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.168)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.149)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.081)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.168)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.068)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.068)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.019)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp2"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.036)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.098)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.036)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.042)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.124)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.085)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.144)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.105)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.052)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.072)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.052)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.023)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.033)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(660, 780), 0.003)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp3"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.071)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.143)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.429)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.179)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.107)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.071)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp4"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.395)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.158)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.132)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.105)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.079)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.053)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp5"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.033)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.064)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.109)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.088)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.095)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.105)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.114)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.053)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.088)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.038)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.051)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.015)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp1"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.027)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.061)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.045)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.068)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.083)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.114)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.146)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.058)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.114)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.036)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.022)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.065)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.023)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp2"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.04)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.074)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.09)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.086)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.069)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.113)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.135)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.071)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.008)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.044)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.041)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.03)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.021)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.075)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.022)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp3"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.036)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.055)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.236)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.073)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.164)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.091)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.109)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.055)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.055)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.055)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.018)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp4"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.163)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.21)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.165)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.125)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.095)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.04)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.03)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.008)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.002)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.004)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.008)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.004)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp5"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.072)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.123)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.113)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.137)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.081)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.087)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.079)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.032)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.021)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 780), 0.002)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp1"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.14)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.115)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.133)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.098)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.071)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.067)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.038)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.027)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.011)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp2"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.051)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.214)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.146)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.129)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.10)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.072)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.083)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.063)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.054)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.022)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.008)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 900), 0.003)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp3"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.163)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.224)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.153)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.061)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.173)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.082)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.122)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.01)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp4"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.003)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.195)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.225)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.16)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.143)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.089)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.075)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.031)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.048)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.003)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 660), 0.009)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp5"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.057)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.108)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.133)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.133)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.11)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.064)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.104)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.049)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.015)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.015)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.003)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.005)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.003)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp1"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.084)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.119)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.183)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.076)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.085)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.124)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.069)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.057)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.041)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.002)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.004)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(780, 900), 0.002)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp2"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.103)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.23)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.193)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.08)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.065)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.071)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.072)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.044)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.054)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.035)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.013)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.003)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.003)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp3"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.179)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.245)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.123)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.075)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.038)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.019)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.019)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp4"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.066)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.063)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.142)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.165)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.135)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.122)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.033)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.086)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.043)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.023)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.003)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp5"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.159)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.173)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.173)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.088)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.115)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.071)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.051)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.041)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.031)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.007)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp1"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.292)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.135)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.197)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.051)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.079)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.022)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.045)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.056)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.034)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.022)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp2"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.092)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.111)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.224)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.173)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.09)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.103)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.045)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.028)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.056)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.019)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.006)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp3"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.146)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.098)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.146)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.195)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.268)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.037)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.012)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp4"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.042)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.121)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.133)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.144)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.144)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.104)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.121)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.046)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.005)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 900), 0.008)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp5"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.061)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.125)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.125)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.124)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.08)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.046)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.013)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.004)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.005)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp1"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.081)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.109)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.124)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.065)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.109)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.124)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.097)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.032)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.022)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.003)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.008)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp2"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.052)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.114)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.155)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.111)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.151)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.125)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.043)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.051)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(660, 780), 0.003)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp3"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.082)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.449)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.061)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.163)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.02)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp4"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.151)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.296)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.156)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.065)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.121)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.05)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.075)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.015)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.005)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.005)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp5"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + // because no data für private persons; use average numbers of all employee categories + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.056)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.084)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.095)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.118)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.12)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.096)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.083)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.095)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.045)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.033)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.022)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.004)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp1"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.077)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.103)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.092)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.098)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.091)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.108)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.092)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.095)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.043)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.035)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.021)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.007)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp2"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.06)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.141)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.152)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.107)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.087)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.089)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.067)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.06)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.037)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.023)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.015)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(660, 780), 0.001)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp3"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.11)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.12)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.144)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.151)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.129)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.079)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.041)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.031)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.019)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.002)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp4"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.099)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.147)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.17)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.133)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.108)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.116)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.058)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.075)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.03)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.005)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.004)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 660), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(660, 900), 0.002)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp5"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + } + return stopDurationProbabilityDistribution; + } + + @Override + public EnumeratedDistribution createTourDistribution( + String smallScaleCommercialTrafficType, RandomGenerator rng) { + List> tourDurationProbabilityDistribution = new ArrayList<>(); + + if (smallScaleCommercialTrafficType.equals(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { + + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 0.0, 30.0), 0.0005917893035900173)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 30.0, 60.0), 0.00021859484237437887)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 90.0, 120.0), 0.00037490287407786324)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 120.0, 180.0), 0.0004337321926125666)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 180.0, 240.0), 0.0005834182239827621)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 240.0, 300.0), 0.0005116938323661723)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 300.0, 360.0), 0.0005027065159573272)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 360.0, 420.0), 0.0006719740164147071)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 420.0, 480.0), 0.00022375027665644004)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 480.0, 540.0), 0.00022103749529549306)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 540.0, 600.0), 0.00022119440831885122)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 600.0, 660.0), 0.0002732185104003396)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 660.0, 720.0), 7.287567629774946e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 720.0, 780.0), 0.0005090670761685264)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 780.0, 840.0), 0.0002169454122557984)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 840.0, 1080.0), 0.0016947794402011696)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 0.0, 30.0), 0.00033050926084770643)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 30.0, 60.0), 0.0004963985976117265)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 60.0, 90.0), 0.0009458837608304906)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 90.0, 120.0), 0.0006507941771038976)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 120.0, 180.0), 0.0002949035696660126)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 180.0, 240.0), 0.0005812406149568905)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 240.0, 300.0), 0.00072666224822023)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 300.0, 360.0), 0.0006017750128936798)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 360.0, 420.0), 0.0007696491628020603)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 420.0, 480.0), 0.0006951014583380694)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 480.0, 540.0), 0.0006675367479652174)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 540.0, 600.0), 0.0009951412624367468)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 600.0, 660.0), 0.0006193958232902363)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 660.0, 720.0), 0.0005496335422364244)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 720.0, 780.0), 0.000963763774344583)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 780.0, 840.0), 0.001585152586657775)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 840.0, 1080.0), 0.0022779973751500433)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 0.0, 30.0), 0.003678291745870938)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 30.0, 60.0), 0.0037749680865755936)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 60.0, 90.0), 0.0021464058981758467)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 90.0, 120.0), 0.0010105726369455444)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 120.0, 180.0), 0.0017166729332290624)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 180.0, 240.0), 0.001218657902054598)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 240.0, 300.0), 0.0019212859349972463)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 300.0, 360.0), 0.0018498349748915703)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 360.0, 420.0), 0.0020820722844894844)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 420.0, 480.0), 0.0033255032578691536)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 480.0, 540.0), 0.004499580798913233)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 540.0, 600.0), 0.004508722079694882)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 600.0, 660.0), 0.009460453046374911)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 660.0, 720.0), 0.008632039128635343)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 720.0, 780.0), 0.005173130409039029)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 780.0, 840.0), 0.0021287189901771954)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 840.0, 1080.0), 0.002735246591728173)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 0.0, 30.0), 0.015534599731489868)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 30.0, 60.0), 0.009424737666749776)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 60.0, 90.0), 0.003979757502241877)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 90.0, 120.0), 0.0026219034509082214)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 120.0, 180.0), 0.004373894821911171)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 180.0, 240.0), 0.005349695968407728)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 240.0, 300.0), 0.008398668008895199)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 300.0, 360.0), 0.013017576110359298)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 360.0, 420.0), 0.013178466937493282)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 420.0, 480.0), 0.015799261066253244)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 480.0, 540.0), 0.031932993774084484)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 540.0, 600.0), 0.056976770375347194)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 600.0, 660.0), 0.03411514635058722)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 660.0, 720.0), 0.010952547256934878)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 720.0, 780.0), 0.005071677294689363)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 780.0, 840.0), 0.002758017802376135)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 840.0, 1080.0), 0.003182481371327368)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 0.0, 30.0), 0.018010507239762663)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 30.0, 60.0), 0.009246211080247332)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 60.0, 90.0), 0.006297103845359016)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 90.0, 120.0), 0.003415561088528113)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 120.0, 180.0), 0.010918022744746231)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 180.0, 240.0), 0.011371721163141522)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 240.0, 300.0), 0.01861910064916215)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 300.0, 360.0), 0.015443374909900384)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 360.0, 420.0), 0.020470726990450452)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 420.0, 480.0), 0.030727618880727087)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 480.0, 540.0), 0.07364088624635841)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 540.0, 600.0), 0.04082061588575034)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 600.0, 660.0), 0.012935881167590665)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 660.0, 720.0), 0.005469250367916343)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 720.0, 780.0), 0.0030030673084490513)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 780.0, 840.0), 0.0011042643367551329)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 840.0, 1080.0), 0.0011327583672022575)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 0.0, 30.0), 0.015589932735904798)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 30.0, 60.0), 0.007157798082590814)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 60.0, 90.0), 0.006563655710107534)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 90.0, 120.0), 0.004888423230467872)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 120.0, 180.0), 0.01261126944262904)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 180.0, 240.0), 0.013275311108363174)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 240.0, 300.0), 0.011059737216827653)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 300.0, 360.0), 0.00980644443311104)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 360.0, 420.0), 0.013476523854959467)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 420.0, 480.0), 0.01766932338862498)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 480.0, 540.0), 0.013855266610087914)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 540.0, 600.0), 0.006090238569895901)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 600.0, 660.0), 0.00326688741194661)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 660.0, 720.0), 0.0009742217966822537)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 720.0, 780.0), 0.0008462163162537791)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 780.0, 840.0), 0.0009357453082055104)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 840.0, 1080.0), 0.0006867783494497427)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 0.0, 30.0), 0.011836581569331607)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 30.0, 60.0), 0.0060475163532472224)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 60.0, 90.0), 0.006091033719221284)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 90.0, 120.0), 0.004870323217391879)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 120.0, 180.0), 0.009852214102720915)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 180.0, 240.0), 0.006649077724867284)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 240.0, 300.0), 0.006549809619698136)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 300.0, 360.0), 0.00743649188225418)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 360.0, 420.0), 0.008370330719772223)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 420.0, 480.0), 0.006055410372169952)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 480.0, 540.0), 0.003221026290023441)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 540.0, 600.0), 0.00270804359225063)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 600.0, 660.0), 0.0011328763880567346)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 660.0, 720.0), 0.0005295062815147344)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 720.0, 780.0), 0.0005244739409173669)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 780.0, 840.0), 0.00022261373811852168)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 840.0, 1080.0), 0.0002976820307410009)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 0.0, 30.0), 0.0072347359578799255)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 30.0, 60.0), 0.005528762818372258)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 60.0, 90.0), 0.004301874597910846)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 90.0, 120.0), 0.002706271535768685)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 120.0, 180.0), 0.004461225555303183)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 180.0, 240.0), 0.003289266637558867)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 240.0, 300.0), 0.004773112389257731)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 300.0, 360.0), 0.004153307715767419)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 360.0, 420.0), 0.0023002274828502435)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 420.0, 480.0), 0.002295722460734858)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 480.0, 540.0), 0.0008008191218782178)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 540.0, 600.0), 0.0005302938593833011)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 600.0, 660.0), 0.00012017333498779025)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 660.0, 720.0), 0.00029497120761336085)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 720.0, 780.0), 7.442207741095891e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 780.0, 840.0), 7.491510042413546e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 0.0, 30.0), 0.005979044848708125)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 30.0, 60.0), 0.0030727725862362003)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 60.0, 90.0), 0.0018328582061095421)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 90.0, 120.0), 0.0015730248216810105)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 120.0, 180.0), 0.0025909176745678485)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 180.0, 240.0), 0.0023584284876344117)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 240.0, 300.0), 0.002888683132930499)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 300.0, 360.0), 0.0026723295114103734)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 360.0, 420.0), 0.001368034507711622)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 420.0, 480.0), 0.001322142609646873)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 480.0, 540.0), 0.00014896322977011863)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 540.0, 600.0), 0.00036793050573151096)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 600.0, 660.0), 0.0003024749417379503)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 660.0, 720.0), 7.263766179594998e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 720.0, 780.0), 7.737798495114381e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 840.0, 1080.0), 7.360037219024495e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 0.0, 30.0), 0.005442934607459622)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 30.0, 60.0), 0.0023099603288455053)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 60.0, 90.0), 0.0015476125810207045)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 90.0, 120.0), 0.0015690710859882222)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 120.0, 180.0), 0.003155552178314994)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 180.0, 240.0), 0.0024715148201473933)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 240.0, 300.0), 0.00214638868043489)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 300.0, 360.0), 0.0017134793037846727)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 360.0, 420.0), 0.0009684921868733149)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 420.0, 480.0), 0.0005519992558366529)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 480.0, 540.0), 0.0004441672064981391)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 540.0, 600.0), 0.00022332686365997108)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 600.0, 660.0), 0.00023780343565208111)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 660.0, 720.0), 0.00014898555439278127)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 0.0, 30.0), 0.0065652971880044205)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 30.0, 60.0), 0.0033645458423904226)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 60.0, 90.0), 0.002247264924524252)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 90.0, 120.0), 0.0021755851670695867)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 120.0, 180.0), 0.00292250684836152)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 180.0, 240.0), 0.0029939610328467135)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 240.0, 300.0), 0.0013771262994841458)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 300.0, 360.0), 0.0005929387919824101)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 360.0, 420.0), 0.0007299574379337656)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 420.0, 480.0), 0.00015161310680499916)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 480.0, 540.0), 0.00022326623210165028)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 540.0, 600.0), 0.00021908720500178134)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 0.0, 30.0), 0.004700575755513116)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 30.0, 60.0), 0.002876930233578738)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 60.0, 90.0), 0.0012326059557891803)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 90.0, 120.0), 0.001688513011030605)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 120.0, 180.0), 0.0024148215923521744)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 180.0, 240.0), 0.0009664823712470381)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 240.0, 300.0), 0.0008158516384741175)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 300.0, 360.0), 0.0005326476409500361)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 360.0, 420.0), 0.00037447250704764534)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 420.0, 480.0), 7.278074100962308e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 480.0, 540.0), 0.00015460621875651884)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 540.0, 600.0), 0.00022625636961834557)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 840.0, 1080.0), 7.369704340227916e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 0.0, 30.0), 0.005421542133242069)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 30.0, 60.0), 0.0028543297205245563)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 60.0, 90.0), 0.001320449445343739)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 90.0, 120.0), 0.0011372744623221703)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 120.0, 180.0), 0.0011175546229352943)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 180.0, 240.0), 0.0005212091408906178)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 240.0, 300.0), 0.00025063117439263165)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 300.0, 360.0), 0.0002906557976189996)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 360.0, 420.0), 6.934683987097806e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 420.0, 480.0), 7.198332684426051e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 0.0, 30.0), 0.005997678933359281)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 30.0, 60.0), 0.0014450238860978966)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 60.0, 90.0), 0.0008909835110546583)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 90.0, 120.0), 0.0008692603958852261)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 120.0, 180.0), 0.0004645626068627116)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 180.0, 240.0), 0.0005161866418057845)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 240.0, 300.0), 0.00047492492382272117)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 300.0, 360.0), 7.348989097075777e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 360.0, 420.0), 0.0003000342936128893)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 0.0, 30.0), 0.004621906661329853)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 30.0, 60.0), 0.0015152391398060199)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 60.0, 90.0), 0.0006769045119123614)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 90.0, 120.0), 0.00044820275277284946)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 120.0, 180.0), 0.0007140653752077821)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 180.0, 240.0), 0.0001502672132808765)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 240.0, 300.0), 0.0003842231300012746)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 300.0, 360.0), 0.00021634404805889257)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 0.0, 30.0), 0.0034023082743939916)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 30.0, 60.0), 0.0006251774232962365)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 60.0, 90.0), 0.00022163965781205308)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 90.0, 120.0), 7.360037219024495e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 120.0, 180.0), 0.00045934601255169126)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 180.0, 240.0), 7.511874968194916e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 240.0, 300.0), 0.0001486019187134722)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 300.0, 360.0), 7.505084488366769e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 420.0, 480.0), 7.594714627228585e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 0.0, 30.0), 0.005137034953520923)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 30.0, 60.0), 0.0010774703023578233)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 60.0, 90.0), 0.00048539418673270443)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 90.0, 120.0), 0.0002988049182984063)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 120.0, 180.0), 0.00032644209078127245)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 180.0, 240.0), 0.0005357497395368892)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 240.0, 300.0), 0.0002944914928100358)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 300.0, 360.0), 0.00022851651374757815)); + } + else if (smallScaleCommercialTrafficType.equals(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString())) { + + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 0.0, 30.0), 0.0002666800577200411)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 30.0, 60.0), 0.0006395055678719748)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 60.0, 90.0), 0.0007110769046958423)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 90.0, 120.0), 0.0006665961628449491)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 120.0, 180.0), 0.0023195866923785575)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 180.0, 240.0), 0.00261751319938476)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 240.0, 300.0), 0.0021430032453503087)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 300.0, 360.0), 0.0029303876579925905)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 360.0, 420.0), 0.00283576618143643)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 420.0, 480.0), 0.0027188265347502893)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 480.0, 540.0), 0.002597768116531099)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 540.0, 600.0), 0.002659151494701916)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 600.0, 660.0), 0.0021738406044924437)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 660.0, 720.0), 0.0021949848461843176)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 720.0, 780.0), 0.0021801193011023083)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 780.0, 840.0), 0.001746033717539671)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 840.0, 1080.0), 0.00350888397405923)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 0.0, 30.0), 0.0006845643884312735)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 30.0, 60.0), 0.0004003126952082357)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 60.0, 90.0), 0.0008155012585632697)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 90.0, 120.0), 0.0010930534970200114)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 120.0, 180.0), 0.0011760353713952051)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 180.0, 240.0), 0.0019364061980548415)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 240.0, 300.0), 0.002953452881036028)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 300.0, 360.0), 0.002589370165068672)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 360.0, 420.0), 0.0025604405819583055)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 420.0, 480.0), 0.0034319041631081476)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 480.0, 540.0), 0.0033480025727905907)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 540.0, 600.0), 0.002175717502193024)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 600.0, 660.0), 0.0028036478238686957)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 660.0, 720.0), 0.0028759635193342887)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 720.0, 780.0), 0.0017584406503249872)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 780.0, 840.0), 0.0016742001219093045)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 840.0, 1080.0), 0.0020658205220468245)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 0.0, 30.0), 0.0017247403950228777)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 30.0, 60.0), 0.003090998236080484)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 60.0, 90.0), 0.0015209554995803177)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 90.0, 120.0), 0.0016533392810110293)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 120.0, 180.0), 0.003732306124403562)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 180.0, 240.0), 0.004106247357091271)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 240.0, 300.0), 0.003188442431357427)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 300.0, 360.0), 0.005929370570550301)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 360.0, 420.0), 0.005992695595693005)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 420.0, 480.0), 0.006390572360276255)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 480.0, 540.0), 0.00993732232424166)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 540.0, 600.0), 0.007917613781985494)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 600.0, 660.0), 0.00753055040114282)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 660.0, 720.0), 0.004839531706746983)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 720.0, 780.0), 0.003571294178536547)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 780.0, 840.0), 0.0022261075091276465)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 840.0, 1080.0), 0.0020123396391017526)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 0.0, 30.0), 0.00553085745500388)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 30.0, 60.0), 0.005164301035284355)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 60.0, 90.0), 0.0034287284279468384)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 90.0, 120.0), 0.003359657704287739)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 120.0, 180.0), 0.005963896679549981)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 180.0, 240.0), 0.006376396116305889)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 240.0, 300.0), 0.011553162434249647)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 300.0, 360.0), 0.01216390369869719)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 360.0, 420.0), 0.015303642980241483)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 420.0, 480.0), 0.01894502604909179)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 480.0, 540.0), 0.026995818384739457)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 540.0, 600.0), 0.03735238580259259)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 600.0, 660.0), 0.02007351137947408)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 660.0, 720.0), 0.007579189226621267)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 720.0, 780.0), 0.003806896198418994)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 780.0, 840.0), 0.0020371212990837376)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 840.0, 1080.0), 0.00246729057836831)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 0.0, 30.0), 0.007834929725170775)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 30.0, 60.0), 0.007875284751511802)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 60.0, 90.0), 0.0056369706407995695)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 90.0, 120.0), 0.007252792818630801)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 120.0, 180.0), 0.011595289158181222)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 180.0, 240.0), 0.01584695155572567)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 240.0, 300.0), 0.019385993489144607)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 300.0, 360.0), 0.01804569113072999)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 360.0, 420.0), 0.020338168968415053)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 420.0, 480.0), 0.03244941203821404)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 480.0, 540.0), 0.046986423884473)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 540.0, 600.0), 0.026127574804977814)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 600.0, 660.0), 0.006859707180170414)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 660.0, 720.0), 0.004053368732850601)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 720.0, 780.0), 0.0017728320836715625)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 780.0, 840.0), 0.0008117046283836942)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 840.0, 1080.0), 0.0014889766393137468)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 0.0, 30.0), 0.008702611915372131)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 30.0, 60.0), 0.009703391735884857)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 60.0, 90.0), 0.00833249802530372)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 90.0, 120.0), 0.008160824294542027)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 120.0, 180.0), 0.014522058792957903)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 180.0, 240.0), 0.019189639247661674)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 240.0, 300.0), 0.022628081955363144)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 300.0, 360.0), 0.018168175275565253)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 360.0, 420.0), 0.01830766579908246)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 420.0, 480.0), 0.022414786327228577)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 480.0, 540.0), 0.015454698179801149)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 540.0, 600.0), 0.00743339793333549)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 600.0, 660.0), 0.0028959167218627997)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 660.0, 720.0), 0.0011608823477359163)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 720.0, 780.0), 0.0006126324367099846)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 780.0, 840.0), 0.0007090395380022889)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 840.0, 1080.0), 0.0009650931773638335)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 0.0, 30.0), 0.010532384705529854)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 30.0, 60.0), 0.010106787618396446)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 60.0, 90.0), 0.007305519187631069)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 90.0, 120.0), 0.0065298278976416635)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 120.0, 180.0), 0.012991661099288086)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 180.0, 240.0), 0.011082392048301831)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 240.0, 300.0), 0.013735041027849332)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 300.0, 360.0), 0.012921165569106639)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 360.0, 420.0), 0.010187951930469277)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 420.0, 480.0), 0.0070071162811467125)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 480.0, 540.0), 0.003478434072337058)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 540.0, 600.0), 0.002487434148850001)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 600.0, 660.0), 0.0007617139935295275)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 660.0, 720.0), 0.0004794259473854554)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 720.0, 780.0), 0.00011828408353297643)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 780.0, 840.0), 0.0009221448817170415)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 0.0, 30.0), 0.0053803765038808364)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 30.0, 60.0), 0.00748440387556175)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 60.0, 90.0), 0.003817044622559703)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 90.0, 120.0), 0.0042559767658946045)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 120.0, 180.0), 0.004633517730561146)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 180.0, 240.0), 0.0040156278424527785)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 240.0, 300.0), 0.004097425621422603)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 300.0, 360.0), 0.00534407493573042)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 360.0, 420.0), 0.002849425985304954)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 420.0, 480.0), 0.0024443772372422234)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 480.0, 540.0), 0.0011258612568464076)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 540.0, 600.0), 0.0005966047093584399)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 600.0, 660.0), 0.0005779388889435179)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 660.0, 720.0), 0.0004527621290439082)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 720.0, 780.0), 0.00011727646428602624)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 780.0, 840.0), 0.00011130198744577025)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 0.0, 30.0), 0.0025301846046864363)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 30.0, 60.0), 0.002932856090944951)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 60.0, 90.0), 0.0015297442159744696)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 90.0, 120.0), 0.0016816440829740813)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 120.0, 180.0), 0.0023140070407952395)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 180.0, 240.0), 0.0013768767086426792)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 240.0, 300.0), 0.0019019317686819275)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 300.0, 360.0), 0.0015577691125463963)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 360.0, 420.0), 0.001499121306916632)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 420.0, 480.0), 0.0007361366421130972)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 480.0, 540.0), 0.0007423049940853575)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 540.0, 600.0), 0.00011130198744577025)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 660.0, 720.0), 0.00024243947114654707)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 720.0, 780.0), 0.000261579996858755)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 0.0, 30.0), 0.0021669594044717543)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 30.0, 60.0), 0.0033993161916113994)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 60.0, 90.0), 0.001870484877697732)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 90.0, 120.0), 0.0008448185262884799)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 120.0, 180.0), 0.002024573233571085)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 180.0, 240.0), 0.0021888099857994042)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 240.0, 300.0), 0.0021657834323017752)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 300.0, 360.0), 0.0010623089332746248)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 360.0, 420.0), 0.0006268095760401356)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 420.0, 480.0), 0.0005094532977538987)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 480.0, 540.0), 0.0004744090926784203)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 540.0, 600.0), 0.00016487328572417658)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 660.0, 720.0), 0.0001162996982120756)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 0.0, 30.0), 0.0033401411497772818)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 30.0, 60.0), 0.002492685695459365)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 60.0, 90.0), 0.0027064477589805068)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 90.0, 120.0), 0.0018052297053924354)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 120.0, 180.0), 0.0027984509294891498)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 180.0, 240.0), 0.0022758505657711914)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 240.0, 300.0), 0.0003535503655144059)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 300.0, 360.0), 0.0005890430396050117)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 360.0, 420.0), 0.0002319134363595028)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 420.0, 480.0), 0.00011617748025141993)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 480.0, 540.0), 0.0003690064941818713)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 540.0, 600.0), 0.0001650495071007077)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 600.0, 660.0), 0.00023113252306835525)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 840.0, 1080.0), 0.00017239206443126303)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 0.0, 30.0), 0.003543871129770451)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 30.0, 60.0), 0.0018407982276338393)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 60.0, 90.0), 0.0010649270862293423)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 90.0, 120.0), 0.0009538696044712171)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 120.0, 180.0), 0.0021318639289119572)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 180.0, 240.0), 0.0019740243143620277)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 240.0, 300.0), 0.0006157677659961421)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 300.0, 360.0), 0.0004035374922773149)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 360.0, 420.0), 0.00011607019237524387)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 420.0, 480.0), 0.0003938282727195195)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 480.0, 540.0), 0.00011130198744577025)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 600.0, 660.0), 0.00011942109323430472)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 0.0, 30.0), 0.00254340964132742)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 30.0, 60.0), 0.0017847751078888892)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 60.0, 90.0), 0.000841891386995212)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 90.0, 120.0), 0.0003543852337006742)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 120.0, 180.0), 0.0013974221085794884)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 180.0, 240.0), 0.0006229273683665316)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 240.0, 300.0), 0.00020579571489011056)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 300.0, 360.0), 0.0004809214516599411)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 360.0, 420.0), 0.00022514291890117063)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 420.0, 480.0), 0.00014748146383900364)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 720.0, 780.0), 0.00011605559293173729)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 0.0, 30.0), 0.0019634787835054656)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 30.0, 60.0), 0.000860670737476427)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 60.0, 90.0), 0.0003550148096943092)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 90.0, 120.0), 0.000855728546868917)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 120.0, 180.0), 0.0009283998993093458)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 180.0, 240.0), 0.00022795178106384156)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 240.0, 300.0), 0.00024119874825349313)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 420.0, 480.0), 0.00023429279224671318)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 480.0, 540.0), 0.00011727269965059726)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 660.0, 720.0), 0.00011130198744577025)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 0.0, 30.0), 0.0017099830161073832)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 30.0, 60.0), 0.0006015092064895483)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 60.0, 90.0), 0.00011819436012345105)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 90.0, 120.0), 0.0002279569151752547)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 120.0, 180.0), 0.0006440525787748041)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 180.0, 240.0), 0.0003142746964600832)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 300.0, 360.0), 0.00022788575876606104)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 360.0, 420.0), 0.0004761806298753505)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 480.0, 540.0), 0.00011727269965059726)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 0.0, 30.0), 0.0020011795184968267)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 30.0, 60.0), 0.00023620950461199452)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 60.0, 90.0), 0.00011935825257957617)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 90.0, 120.0), 0.00011130198744577025)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 120.0, 180.0), 0.00012222981614916706)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 180.0, 240.0), 0.0002377005397786721)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 240.0, 300.0), 0.00026373526728965034)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 300.0, 360.0), 0.000256086036315955)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 360.0, 420.0), 0.00011394287938236544)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 0.0, 30.0), 0.0021116872169622083)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 30.0, 60.0), 0.0003681765715703113)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 60.0, 90.0), 0.0004137833254678062)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 90.0, 120.0), 0.00025108497234833097)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 120.0, 180.0), 0.0007576827338029722)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 180.0, 240.0), 0.0005180490039062906)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 240.0, 300.0), 0.0004944106124208977)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 300.0, 360.0), 0.0002278857587658224)); + } else + throw new IllegalArgumentException("Unknown small scale commercial traffic type: " + smallScaleCommercialTrafficType); + + return new EnumeratedDistribution<>(rng, tourDurationProbabilityDistribution); + } + + @Override + public EnumeratedDistribution createTourStartTimeDistribution( + String smallScaleCommercialTrafficType, RandomGenerator rng) { + List> tourStartProbabilityDistribution = new ArrayList<>(); + if (smallScaleCommercialTrafficType.equals(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 1), 0.002)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(1, 2), 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(2, 3), 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(3, 4), 0.002)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(4, 5), 0.008)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(5, 6), 0.031)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(6, 7), 0.144)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(7, 8), 0.335)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(8, 9), 0.182)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(9, 10), 0.108)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 11), 0.057)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(11, 12), 0.032)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(12, 13), 0.021)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(13, 14), 0.021)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(14, 15), 0.019)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(15, 16), 0.012)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(16, 17), 0.009)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(17, 18), 0.006)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(18, 19), 0.004)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(19, 20), 0.003)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 21), 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(22, 23), 0.001)); + } else if (smallScaleCommercialTrafficType.equals(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString())) { + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 1), 0.008)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(1, 2), 0.003)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(2, 3), 0.008)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(3, 4), 0.012)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(4, 5), 0.028)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(5, 6), 0.052)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(6, 7), 0.115)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(7, 8), 0.222)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(8, 9), 0.197)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(9, 10), 0.14)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 11), 0.076)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(11, 12), 0.035)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(12, 13), 0.022)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(13, 14), 0.022)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(14, 15), 0.021)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(15, 16), 0.014)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(16, 17), 0.008)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(17, 18), 0.005)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(18, 19), 0.004)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(19, 20), 0.002)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 21), 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(21, 22), 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(22, 23), 0.002)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(23, 24), 0.001)); + } + return new EnumeratedDistribution<>(rng, tourStartProbabilityDistribution); + } + + @Override + public EnumeratedDistribution createTourDurationTimeDistribution( + String smallScaleCommercialTrafficType, RandomGenerator rng) { + List> tourDurationProbabilityDistribution = new ArrayList<>(); + if (smallScaleCommercialTrafficType.equals(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 1), 0.14)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(1, 2), 0.066)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(2, 3), 0.056)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(3, 4), 0.052)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(4, 5), 0.061)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(5, 6), 0.063)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(6, 7), 0.07)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(7, 8), 0.086)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(8, 9), 0.14)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(9, 10), 0.122)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 11), 0.068)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(11, 12), 0.031)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(12, 13), 0.018)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(13, 14), 0.01)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(14, 15), 0.006)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(15, 16), 0.003)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(16, 17), 0.002)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(17, 18), 0.001)); + } else if (smallScaleCommercialTrafficType.equals(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString())) { + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 1), 0.096)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(1, 2), 0.074)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(2, 3), 0.065)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(3, 4), 0.071)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(4, 5), 0.086)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(5, 6), 0.084)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(6, 7), 0.084)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(7, 8), 0.101)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(8, 9), 0.118)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(9, 10), 0.092)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 11), 0.048)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(11, 12), 0.027)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(12, 13), 0.015)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(13, 14), 0.011)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(14, 15), 0.006)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(15, 16), 0.004)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(16, 17), 0.002)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(17, 18), 0.001)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(18, 19), 0.001)); + } + return new EnumeratedDistribution<>(rng, tourDurationProbabilityDistribution); + } +} diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/GetCommercialTourSpecifications.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/GetCommercialTourSpecifications.java new file mode 100644 index 00000000000..ce6bce3c04c --- /dev/null +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/GetCommercialTourSpecifications.java @@ -0,0 +1,47 @@ +package org.matsim.smallScaleCommercialTrafficGeneration.data; + +import org.apache.commons.math3.distribution.EnumeratedDistribution; +import org.apache.commons.math3.random.RandomGenerator; +import org.matsim.smallScaleCommercialTrafficGeneration.GenerateSmallScaleCommercialTrafficDemand; + +import java.util.Map; + +public interface GetCommercialTourSpecifications { + + /** + * Creates the probability distribution for the duration of the services. + * The values are given in [min] and have an upperBound. + * + * @param smallScaleCommercialTrafficType the type of small scale commercial traffic + * @return the probability distribution for the duration of the services + */ + Map> createStopDurationDistributionPerCategory( + String smallScaleCommercialTrafficType, RandomGenerator rng); + + /** + * Creates the distribution of the tour start and the related duration. + * + * @param smallScaleCommercialTrafficType the type of the small scale commercial traffic + * @return the distribution of the tour start and the related duration + */ + EnumeratedDistribution createTourDistribution(String smallScaleCommercialTrafficType, RandomGenerator rng); + + /** + * Creates the probability distribution for the tour start times for the day. + * The values are given in [h] and have an upperBound. + * + * @return the probability distribution for the tour start times + */ + + @Deprecated //use createTourDistribution(String smallScaleCommercialTrafficType) instead + EnumeratedDistribution createTourStartTimeDistribution(String smallScaleCommercialTrafficType, RandomGenerator rng); + + /** + * Creates the probability distribution for the tour duration for the day. + * The values are given in [h] and have an upperBound. + * + * @return the probability distribution for the tour duration + */ + @Deprecated //use createTourDistribution(String smallScaleCommercialTrafficType) instead + EnumeratedDistribution createTourDurationTimeDistribution(String smallScaleCommercialTrafficType, RandomGenerator rng); +} diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/prepare/CreateDataDistributionOfStructureData.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/prepare/CreateDataDistributionOfStructureData.java index 477231505c1..dcd4c3732d9 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/prepare/CreateDataDistributionOfStructureData.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/prepare/CreateDataDistributionOfStructureData.java @@ -29,7 +29,7 @@ public class CreateDataDistributionOfStructureData implements MATSimAppCommand { private static final Logger log = LogManager.getLogger(CreateDataDistributionOfStructureData.class); - private static LanduseDataConnectionCreator landuseDataConnectionCreator; + private final LanduseDataConnectionCreator landuseDataConnectionCreator; private enum LanduseConfiguration { useOnlyOSMLanduse, useOSMBuildingsAndLanduse @@ -78,16 +78,16 @@ private enum LanduseConfiguration { private final Map>> buildingsPerZone = new HashMap<>(); public CreateDataDistributionOfStructureData(LanduseDataConnectionCreator landuseDataConnectionCreator) { - CreateDataDistributionOfStructureData.landuseDataConnectionCreator = landuseDataConnectionCreator; + this.landuseDataConnectionCreator = landuseDataConnectionCreator; log.info("Using LanduseDataConnectionCreator {} to connect the types of the landuse data to the categories of the small scale commercial traffic generation", landuseDataConnectionCreator.getClass().getSimpleName()); } public CreateDataDistributionOfStructureData() { - landuseDataConnectionCreator = new LanduseDataConnectionCreatorForOSM_Data(); + this.landuseDataConnectionCreator = new LanduseDataConnectionCreatorForOSM_Data(); log.info("Using default LanduseDataConnectionCreatorForOSM_Data to connect the types of the landuse data to the categories of the small scale commercial traffic generation"); } public static void main(String[] args) { - System.exit(new CommandLine(new CreateDataDistributionOfStructureData(landuseDataConnectionCreator)).execute(args)); + System.exit(new CommandLine(new CreateDataDistributionOfStructureData()).execute(args)); } @Override diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java index 1e20839af41..7aeefbf5925 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java @@ -28,14 +28,18 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.population.Activity; import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.Population; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.population.PopulationUtils; +import org.matsim.core.router.TripStructureUtils; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.io.IOUtils; +import org.matsim.core.utils.misc.OptionalTime; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.CarriersUtils; import org.matsim.freight.carriers.FreightCarriersConfigGroup; @@ -47,6 +51,7 @@ import java.io.IOException; import java.nio.file.Path; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Objects; @@ -68,20 +73,12 @@ void testMainRunAndResults() { String sample = "0.1"; String jspritIterations = "2"; String creationOption = "createNewCarrierFile"; - String landuseConfiguration = "useExistingDataDistribution"; String smallScaleCommercialTrafficType = "commercialPersonTraffic"; - String regionsShapeFileName = utils.getPackageInputDirectory() + "/shp/testRegions.shp"; - String regionsShapeRegionColumn = "region"; String zoneShapeFileName = utils.getPackageInputDirectory() + "/shp/testZones.shp"; String zoneShapeFileNameColumn = "name"; - String buildingsShapeFileName = utils.getPackageInputDirectory() + "/shp/testBuildings.shp"; - String shapeFileBuildingTypeColumn = "type"; - String landuseShapeFileName = utils.getPackageInputDirectory() + "/shp/testLanduse.shp"; - String shapeFileLanduseTypeColumn = "fclass"; String shapeCRS = "EPSG:4326"; String resultPopulation = "testPopulation.xml.gz"; - new GenerateSmallScaleCommercialTrafficDemand().execute( pathToConfig, "--pathToDataDistributionToZones", pathToDataDistributionToZones.toString(), @@ -118,6 +115,18 @@ void testMainRunAndResults() { Assertions.assertTrue(person.getAttributes().getAsMap().containsKey("vehicles")); Assertions.assertTrue(person.getAttributes().getAsMap().containsKey("subpopulation")); Assertions.assertTrue(person.getAttributes().getAsMap().containsKey("purpose")); + + for (Plan plan : person.getPlans()) { + List activities = TripStructureUtils.getActivities(plan, TripStructureUtils.StageActivityHandling.ExcludeStageActivities); + Assertions.assertEquals("commercial_start", activities.getFirst().getType()); + Assertions.assertEquals("commercial_end", activities.getLast().getType()); + activities.forEach(activity -> { + Assertions.assertNotNull(activity.getCoord()); + if (!activity.getType().equals("commercial_start") && !activity.getType().equals("commercial_end")) { + Assertions.assertNotEquals(OptionalTime.undefined(), activity.getMaximumDuration()); + } + }); + } } Assertions.assertEquals(CarriersUtils.addOrGetCarriers(scenarioWSolution).getCarriers().size(), @@ -144,10 +153,10 @@ void testMainRunAndResults() { } /** - * Reads a CSV file and creates a map with the first column as key and the rest as a map with the header as key and the value as value + * Reads a CSV file and creates a map with the first column as a key and the rest as a map with the header as key and the value as value * * @param calculatedFile the file to read - * @return + * @return the map with the data distribution */ private static Map> readCSVInputAndCreateMap(String calculatedFile) { Map> dataDistribution = new HashMap<>(); diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/test.output_events.xml.gz b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/test.output_events.xml.gz index b402920a875..6934ebcecc0 100644 Binary files a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/test.output_events.xml.gz and b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/test.output_events.xml.gz differ diff --git a/contribs/socnetsim/src/test/java/org/matsim/contrib/socnetsim/jointtrips/router/JointTripRouterFactoryTest.java b/contribs/socnetsim/src/test/java/org/matsim/contrib/socnetsim/jointtrips/router/JointTripRouterFactoryTest.java index 993cfdb52bb..71b3dbf77b9 100644 --- a/contribs/socnetsim/src/test/java/org/matsim/contrib/socnetsim/jointtrips/router/JointTripRouterFactoryTest.java +++ b/contribs/socnetsim/src/test/java/org/matsim/contrib/socnetsim/jointtrips/router/JointTripRouterFactoryTest.java @@ -48,6 +48,7 @@ import org.matsim.contrib.socnetsim.jointtrips.population.PassengerRoute; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Injector; import org.matsim.core.events.EventsUtils; @@ -95,6 +96,8 @@ private static Scenario createScenario() { Scenario sc = ScenarioUtils.createScenario( ConfigUtils.createConfig() ); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + Network net = (Network) sc.getNetwork(); final Id id5 = node1; Node node1inst = NetworkUtils.createAndAddNode(net, id5, new Coord((double) 0, (double) 1)); diff --git a/contribs/vsp/pom.xml b/contribs/vsp/pom.xml index b2bf9fb3a41..8f4e01bec37 100644 --- a/contribs/vsp/pom.xml +++ b/contribs/vsp/pom.xml @@ -184,7 +184,7 @@ org.openjfx javafx-graphics - 22.0.1 + 22.0.2 com.graphhopper diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareCalculator.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareCalculator.java new file mode 100644 index 00000000000..1e95a8b909f --- /dev/null +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareCalculator.java @@ -0,0 +1,28 @@ +package org.matsim.contrib.vsp.pt.fare; + +import com.google.inject.Inject; +import org.matsim.api.core.v01.Coord; + +import java.util.Optional; +import java.util.Set; + +/** + * This class is a {@link PtFareCalculator} that chains multiple {@link PtFareCalculator}s together. As soon as one of the chained calculators + * returns a fare, this calculator returns that fare. In {@link PtFareModule} all available {@link PtFareCalculator}s are bound to this class. The + * order in which the calculators are bound is determined by the priority of the {@link PtFareParams} they are created from. + */ +public class ChainedPtFareCalculator implements PtFareCalculator { + @Inject + private Set fareCalculators; + + @Override + public Optional calculateFare(Coord from, Coord to) { + for (PtFareCalculator fareCalculator : fareCalculators) { + Optional fareResult = fareCalculator.calculateFare(from, to); + if (fareResult.isPresent()) { + return fareResult; + } + } + return Optional.empty(); + } +} diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareHandler.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareHandler.java new file mode 100644 index 00000000000..fef87f65ba3 --- /dev/null +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareHandler.java @@ -0,0 +1,68 @@ +package org.matsim.contrib.vsp.pt.fare; + +import com.google.inject.Inject; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.events.ActivityStartEvent; +import org.matsim.api.core.v01.events.PersonMoneyEvent; +import org.matsim.api.core.v01.population.Person; +import org.matsim.core.api.experimental.events.AgentWaitingForPtEvent; +import org.matsim.core.api.experimental.events.EventsManager; +import org.matsim.core.router.StageActivityTypeIdentifier; +import org.matsim.pt.PtConstants; + +import java.util.HashMap; +import java.util.Map; + +public class ChainedPtFareHandler implements PtFareHandler { + @Inject + private EventsManager events; + + private final Map, Coord> personDepartureCoordMap = new HashMap<>(); + private final Map, Coord> personArrivalCoordMap = new HashMap<>(); + + @Inject + private ChainedPtFareCalculator fareCalculator; + + @Override + public void handleEvent(ActivityStartEvent event) { + if (event.getActType().equals(PtConstants.TRANSIT_ACTIVITY_TYPE)) { + personDepartureCoordMap.computeIfAbsent(event.getPersonId(), c -> event.getCoord()); // The departure place is fixed to the place of + // first pt interaction an agent has in the whole leg + personArrivalCoordMap.put(event.getPersonId(), event.getCoord()); // The arrival stop will keep updating until the agent start a real + // activity (i.e. finish the leg) + } + + if (StageActivityTypeIdentifier.isStageActivity(event.getActType())) { + return; + } + + Id personId = event.getPersonId(); + if (!personDepartureCoordMap.containsKey(personId)) { + return; + } + + Coord from = personDepartureCoordMap.get(personId); + Coord to = personArrivalCoordMap.get(personId); + + PtFareCalculator.FareResult fare = fareCalculator.calculateFare(from, to).orElseThrow(); + + // charge fare to the person + events.processEvent(new PersonMoneyEvent(event.getTime(), event.getPersonId(), -fare.fare(), PtFareConfigGroup.PT_FARE, + fare.transactionPartner(), event.getPersonId().toString())); + + personDepartureCoordMap.remove(personId); + personArrivalCoordMap.remove(personId); + } + + @Override + public void handleEvent(AgentWaitingForPtEvent event) { + //TODO + } + + @Override + public void reset(int iteration) { + personArrivalCoordMap.clear(); + personDepartureCoordMap.clear(); + } +} diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculator.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculator.java new file mode 100644 index 00000000000..90e8d0079dc --- /dev/null +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculator.java @@ -0,0 +1,82 @@ +package org.matsim.contrib.vsp.pt.fare; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.locationtech.jts.geom.Geometry; +import org.matsim.api.core.v01.Coord; +import org.matsim.application.options.ShpOptions; +import org.matsim.core.utils.geometry.CoordUtils; +import org.matsim.core.utils.geometry.geotools.MGC; +import org.matsim.core.utils.io.IOUtils; + +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.SortedMap; + +/** + * This class calculates the fare for a public transport trip based on the distance between the origin and destination. If a shape file is + * provided, the + * fare will be calculated only if the trip is within the shape. + */ +public class DistanceBasedPtFareCalculator implements PtFareCalculator { + private static final Logger log = LogManager.getLogger(DistanceBasedPtFareCalculator.class); + + private final double minFare; + private final SortedMap distanceClassFareParams; + private ShpOptions shp = null; + private final String transactionPartner; + + private final Map inShapeCache = new HashMap<>(); + + public DistanceBasedPtFareCalculator(DistanceBasedPtFareParams params, URL context) { + this.minFare = params.getMinFare(); + this.distanceClassFareParams = params.getDistanceClassFareParams(); + this.transactionPartner = params.getTransactionPartner(); + + if (params.getFareZoneShp() != null) { + log.info("For DistanceBasedPtFareCalculator '{}' a fare zone shape file was provided. During the computation, the fare will be " + + "calculated only if the trip is within the shape.", params.getDescription()); + this.shp = new ShpOptions(IOUtils.extendUrl(context, params.getFareZoneShp()).toString(), null, null); + } else { + log.info("For DistanceBasedPtFareCalculator '{}' no fare zone shape file was provided. The fare will be calculated for all trips.", + params.getDescription()); + } + } + + @Override + public Optional calculateFare(Coord from, Coord to) { + if (!shapeCheck(from, to)) { + return Optional.empty(); + } + + double distance = CoordUtils.calcEuclideanDistance(from, to); + + double fare = computeFare(distance, minFare, distanceClassFareParams); + return Optional.of(new FareResult(fare, transactionPartner)); + } + + private boolean shapeCheck(Coord from, Coord to) { + if (shp == null) { + return true; + } + return inShapeCache.computeIfAbsent(from, this::inShape) && inShapeCache.computeIfAbsent(to, this::inShape); + } + + private boolean inShape(Coord coord) { + return shp.readFeatures().stream().anyMatch(f -> MGC.coord2Point(coord).within((Geometry) f.getDefaultGeometry())); + } + + public static double computeFare(double distance, double minFare, + SortedMap distanceClassFareParams) { + try { + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClassFareParam = distanceClassFareParams.tailMap(distance).firstEntry().getValue(); + return Math.max(minFare, distance * distanceClassFareParam.getFareSlope() + distanceClassFareParam.getFareIntercept()); + } catch (IllegalArgumentException e) { + log.error("No fare found for distance of " + distance + " meters."); + log.error(e.getMessage()); + throw new RuntimeException("No fare found for distance of " + distance + " meters."); + } + } +} diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java new file mode 100644 index 00000000000..363306b30df --- /dev/null +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java @@ -0,0 +1,240 @@ +package org.matsim.contrib.vsp.pt.fare; + +import jakarta.validation.constraints.PositiveOrZero; +import org.apache.commons.math.stat.regression.SimpleRegression; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigGroup; +import org.matsim.core.config.ReflectiveConfigGroup; + +import java.util.*; + +/** + * @author Chengqi Lu (luchengqi7) + * The parameters for the distance-based PT trip fare calculation. + * The default values are set based on the fitting results of the trip and fare data collected on September 2021 + * The values are based on the standard unit of meter (m) and Euro (EUR) + */ +public class DistanceBasedPtFareParams extends PtFareParams { + public static final DistanceBasedPtFareParams GERMAN_WIDE_FARE_2024 = germanWideFare2024(); + + public static final String SET_TYPE = "ptFareCalculationDistanceBased"; + public static final String MIN_FARE = "minFare"; + + private static final Logger log = LogManager.getLogger(DistanceBasedPtFareParams.class); + + @PositiveOrZero + private double minFare = 0.0; + + public DistanceBasedPtFareParams() { + super(SET_TYPE); + } + + @Override + public Map getComments() { + Map map = super.getComments(); + map.put(MIN_FARE, "Minimum fare for a PT trip (e.g. Kurzstrecke/short distance ticket in cities, ticket for 1 zone in rural areas). " + + "Default is 2.0EUR."); + return map; + } + + @StringGetter(MIN_FARE) + public double getMinFare() { + return minFare; + } + + @StringSetter(MIN_FARE) + public void setMinFare(double minFare) { + this.minFare = minFare; + } + + // in Deutschlandtarif, the linear function for the prices above 100km seem to have a different steepness + // hence the following difference in data points + // prices taken from https://deutschlandtarifverbund.de/wp-content/uploads/2024/07/20231201_TBDT_J_10_Preisliste_V07.pdf + // TODO: This fare will change. We might need a way to select the fare of a specific year + private static DistanceBasedPtFareParams germanWideFare2024() { + final double MIN_FARE = 1.70; + + SimpleRegression under100kmTrip = new SimpleRegression(); + under100kmTrip.addData(1, MIN_FARE); + under100kmTrip.addData(2, 1.90); + under100kmTrip.addData(3, 2.00); + under100kmTrip.addData(4, 2.10); + under100kmTrip.addData(5, 2.20); + under100kmTrip.addData(6, 3.20); + under100kmTrip.addData(7, 3.70); + under100kmTrip.addData(8, 3.80); + under100kmTrip.addData(9, 3.90); + under100kmTrip.addData(10, 4.10); + under100kmTrip.addData(11, 5.00); + under100kmTrip.addData(12, 5.40); + under100kmTrip.addData(13, 5.60); + under100kmTrip.addData(14, 5.80); + under100kmTrip.addData(15, 5.90); + under100kmTrip.addData(16, 6.40); + under100kmTrip.addData(17, 6.50); + under100kmTrip.addData(18, 6.60); + under100kmTrip.addData(19, 6.70); + under100kmTrip.addData(20, 6.90); + under100kmTrip.addData(30, 9.90); + under100kmTrip.addData(40, 13.70); + under100kmTrip.addData(50, 16.30); + under100kmTrip.addData(60, 18.10); + under100kmTrip.addData(70, 20.10); + under100kmTrip.addData(80, 23.20); + under100kmTrip.addData(90, 26.20); + under100kmTrip.addData(100, 28.10); + + SimpleRegression longDistanceTrip = new SimpleRegression(); + longDistanceTrip.addData(100, 28.10); + longDistanceTrip.addData(200, 47.20); + longDistanceTrip.addData(300, 59.70); + longDistanceTrip.addData(400, 71.70); + longDistanceTrip.addData(500, 83.00); + longDistanceTrip.addData(600, 94.60); + longDistanceTrip.addData(700, 106.30); + longDistanceTrip.addData(800, 118.20); + longDistanceTrip.addData(900, 130.10); + longDistanceTrip.addData(1000, 141.00); + longDistanceTrip.addData(1100, 148.60); + longDistanceTrip.addData(1200, 158.10); + longDistanceTrip.addData(1300, 169.20); + longDistanceTrip.addData(1400, 179.80); + longDistanceTrip.addData(1500, 190.10); + longDistanceTrip.addData(1600, 201.50); + longDistanceTrip.addData(1700, 212.80); + longDistanceTrip.addData(1800, 223.30); + longDistanceTrip.addData(1900, 233.90); + longDistanceTrip.addData(2000, 244.00); + + var params = new DistanceBasedPtFareParams(); + + DistanceClassLinearFareFunctionParams distanceClass100kmFareParams = params.getOrCreateDistanceClassFareParams(100_000.); + // above values are per km, fare deduction is based on meter instead + distanceClass100kmFareParams.setFareSlope(under100kmTrip.getSlope() / 1000.0); + distanceClass100kmFareParams.setFareIntercept(under100kmTrip.getIntercept()); + + DistanceClassLinearFareFunctionParams distanceClassLongFareParams = params.getOrCreateDistanceClassFareParams(Double.POSITIVE_INFINITY); + distanceClassLongFareParams.setFareSlope(longDistanceTrip.getSlope() / 1000.0); + distanceClassLongFareParams.setFareIntercept(longDistanceTrip.getIntercept()); + + params.setTransactionPartner("Deutschlandtarif"); + params.setMinFare(MIN_FARE); + + return params; + } + + @Override + public ConfigGroup createParameterSet(final String type) { + switch (type) { + case DistanceClassLinearFareFunctionParams.SET_TYPE: + return new DistanceClassLinearFareFunctionParams(); + default: + throw new IllegalArgumentException(type); + } + } + + @Override + protected final void checkConsistency(final Config config) { + super.checkConsistency(config); + getDistanceClassFareParams(); + } + + public SortedMap getDistanceClassFareParams() { + @SuppressWarnings("unchecked") + final Collection distanceClassFareParams = + (Collection) getParameterSets(DistanceClassLinearFareFunctionParams.SET_TYPE); + final SortedMap map = new TreeMap<>(); + + for (DistanceClassLinearFareFunctionParams pars : distanceClassFareParams) { + if (this.isLocked()) { + pars.setLocked(); + } + if (map.containsKey(pars.getMaxDistance())) { + log.error("Multiple " + DistanceClassLinearFareFunctionParams.class + + " with same max distance in same DistanceBasedPtFareParams. Max distance must be unique."); + throw new RuntimeException("Multiple " + DistanceClassLinearFareFunctionParams.class); + } + map.put(pars.getMaxDistance(), pars); + } + if (this.isLocked()) { + return Collections.unmodifiableSortedMap(map); + } else { + return map; + } + } + + public DistanceClassLinearFareFunctionParams getOrCreateDistanceClassFareParams(double maxDistance) { + DistanceClassLinearFareFunctionParams distanceClassFareParams = this.getDistanceClassFareParams().get(maxDistance); + if (distanceClassFareParams == null) { + distanceClassFareParams = new DistanceClassLinearFareFunctionParams(); + distanceClassFareParams.setMaxDistance(maxDistance); + addParameterSet(distanceClassFareParams); + } + return distanceClassFareParams; + } + + public static class DistanceClassLinearFareFunctionParams extends ReflectiveConfigGroup { + + public static final String SET_TYPE = "distanceClassLinearFare"; + public static final String FARE_SLOPE = "fareSlope"; + public static final String FARE_INTERCEPT = "fareIntercept"; + public static final String MAX_DISTANCE = "maxDistance"; + + @PositiveOrZero + private double fareSlope; + @PositiveOrZero + private double fareIntercept; + @PositiveOrZero + private double maxDistance; + + public DistanceClassLinearFareFunctionParams() { + super(SET_TYPE); + } + + @StringGetter(FARE_SLOPE) + public double getFareSlope() { + return fareSlope; + } + + @StringSetter(FARE_SLOPE) + public void setFareSlope(double fareSlope) { + this.fareSlope = fareSlope; + } + + @StringGetter(FARE_INTERCEPT) + public double getFareIntercept() { + return fareIntercept; + } + + + @StringSetter(FARE_INTERCEPT) + public void setFareIntercept(double fareIntercept) { + this.fareIntercept = fareIntercept; + } + + @StringGetter(MAX_DISTANCE) + public double getMaxDistance() { + return maxDistance; + } + + @StringSetter(MAX_DISTANCE) + public void setMaxDistance(double maxDistance) { + this.maxDistance = maxDistance; + } + + @Override + public Map getComments() { + Map map = super.getComments(); + map.put(FARE_SLOPE, "Linear function fare = slope * distance + intercept: the value of the slope factor in currency units / m" + + "(not km!)."); + map.put(FARE_INTERCEPT, "Linear function fare = slope * distance + intercept: the value of the intercept in currency units."); + map.put(MAX_DISTANCE, "The given linear function is applied to trips up to this distance threshold in meters. If set to a finite value" + + ", the linear function for the next distance class will be tried out. If no fare is defined with " + MAX_DISTANCE + " greater than" + + "pt trip length, an error is thrown. If multiple distance classes have the same max distance it is unclear which applies, therefore " + + "an error is thrown."); + return map; + } + } +} diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculator.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculator.java new file mode 100644 index 00000000000..adf9971f914 --- /dev/null +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculator.java @@ -0,0 +1,54 @@ +package org.matsim.contrib.vsp.pt.fare; + +import com.google.common.base.Verify; +import org.geotools.api.feature.simple.SimpleFeature; +import org.locationtech.jts.geom.Geometry; +import org.matsim.api.core.v01.Coord; +import org.matsim.application.options.ShpOptions; +import org.matsim.core.utils.geometry.geotools.MGC; +import org.matsim.core.utils.io.IOUtils; + +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +/** + * This class calculates the fare for a public transport trip based on the fare zone the origin and destination are in. + */ +public class FareZoneBasedPtFareCalculator implements PtFareCalculator { + private final ShpOptions shp; + private final String transactionPartner; + private final Map> zoneByCoordCache = new HashMap<>(); + + public static final String FARE = "fare"; + + public FareZoneBasedPtFareCalculator(FareZoneBasedPtFareParams params, URL context) { + this.shp = new ShpOptions(IOUtils.extendUrl(context, params.getFareZoneShp()).toString(), null, null); + transactionPartner = params.getTransactionPartner(); + } + + @Override + public Optional calculateFare(Coord from, Coord to) { + Optional departureZone = zoneByCoordCache.computeIfAbsent(from, this::determineFareZone); + Optional arrivalZone = zoneByCoordCache.computeIfAbsent(to, this::determineFareZone); + + //if one of the zones is empty, it is not included in the shape file, so this calculator cannot compute the fare + if (departureZone.isEmpty() || arrivalZone.isEmpty()) { + return Optional.empty(); + } + + if (!departureZone.get().getID().equals(arrivalZone.get().getID())) { + return Optional.empty(); + } + + Double fare = (Double) departureZone.get().getAttribute(FARE); + Verify.verifyNotNull(fare, "Fare zone without attribute " + FARE + " in " + shp.getShapeFile() + + " found. Terminating."); + return Optional.of(new FareResult(fare, transactionPartner)); + } + + Optional determineFareZone(Coord coord) { + return shp.readFeatures().stream().filter(f -> MGC.coord2Point(coord).within((Geometry) f.getDefaultGeometry())).findFirst(); + } +} diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareParams.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareParams.java new file mode 100644 index 00000000000..4944ad13d78 --- /dev/null +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareParams.java @@ -0,0 +1,9 @@ +package org.matsim.contrib.vsp.pt.fare; + +public class FareZoneBasedPtFareParams extends PtFareParams { + public static final String SET_TYPE = "ptFareCalculationFareZoneBased"; + + public FareZoneBasedPtFareParams() { + super(SET_TYPE); + } +} diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareCalculator.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareCalculator.java new file mode 100644 index 00000000000..597f105c0dc --- /dev/null +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareCalculator.java @@ -0,0 +1,12 @@ +package org.matsim.contrib.vsp.pt.fare; + +import org.matsim.api.core.v01.Coord; + +import java.util.Optional; + +public interface PtFareCalculator { + Optional calculateFare(Coord from, Coord to); + + record FareResult(Double fare, String transactionPartner) { + } +} diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareConfigGroup.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareConfigGroup.java new file mode 100644 index 00000000000..ca1ce2fdb65 --- /dev/null +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareConfigGroup.java @@ -0,0 +1,93 @@ +package org.matsim.contrib.vsp.pt.fare; + +import jakarta.validation.constraints.PositiveOrZero; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigGroup; +import org.matsim.core.config.ReflectiveConfigGroup; + +import java.util.Map; +import java.util.stream.Stream; + +public class PtFareConfigGroup extends ReflectiveConfigGroup { + public static final String PT_FARE = "pt fare"; + public static final String MODULE_NAME = "ptFare"; + public static final String APPLY_UPPER_BOUND = "applyUpperBound"; + public static final String UPPER_BOUND_FACTOR = "upperBoundFactor"; + + public static final String UPPER_BOUND_FACTOR_CMT = "When upper bound is applied, upperBound = upperBoundFactor * max Fare of the day. " + + "This value is decided by the ratio between average daily cost of a ticket subscription and the single " + + "trip ticket of the same trip. Usually this value should be somewhere between 1.0 and 2.0"; + public static final String APPLY_UPPER_BOUND_CMT = "Enable the upper bound for daily PT fare to count for ticket subscription. Input value: " + + "true" + + " or false"; + + private boolean applyUpperBound = true; + @PositiveOrZero + private double upperBoundFactor = 1.5; + + public PtFareConfigGroup() { + super(MODULE_NAME); + } + + @Override + public Map getComments() { + Map map = super.getComments(); + map.put(APPLY_UPPER_BOUND, APPLY_UPPER_BOUND_CMT); + map.put(UPPER_BOUND_FACTOR, UPPER_BOUND_FACTOR_CMT); + return map; + } + + @StringGetter(APPLY_UPPER_BOUND) + public boolean getApplyUpperBound() { + return applyUpperBound; + } + + @StringSetter(APPLY_UPPER_BOUND) + public void setApplyUpperBound(boolean applyUpperBound) { + this.applyUpperBound = applyUpperBound; + } + + + @StringGetter(UPPER_BOUND_FACTOR) + public double getUpperBoundFactor() { + return upperBoundFactor; + } + + @StringSetter(UPPER_BOUND_FACTOR) + public void setUpperBoundFactor(double upperBoundFactor) { + this.upperBoundFactor = upperBoundFactor; + } + + @Override + public ConfigGroup createParameterSet(final String type) { + switch (type) { + case DistanceBasedPtFareParams.SET_TYPE: + return new DistanceBasedPtFareParams(); + case FareZoneBasedPtFareParams.SET_TYPE: + return new FareZoneBasedPtFareParams(); + default: + throw new IllegalArgumentException(type); + } + } + + @Override + protected void checkConsistency(Config config) { + super.checkConsistency(config); + + var distanceBasedParameterSets = getParameterSets(DistanceBasedPtFareParams.SET_TYPE); + var fareZoneBasedParameterSets = getParameterSets(FareZoneBasedPtFareParams.SET_TYPE); + + if (distanceBasedParameterSets.isEmpty() && fareZoneBasedParameterSets.isEmpty()) { + throw new IllegalArgumentException("No parameter sets found for pt fare calculation. Please add at least one parameter set."); + } + + long distinctOrders = Stream.concat(distanceBasedParameterSets.stream(), fareZoneBasedParameterSets.stream()) + .map(PtFareParams.class::cast) + .map(PtFareParams::getOrder) + .distinct().count(); + + if (distinctOrders != distanceBasedParameterSets.size() + fareZoneBasedParameterSets.size()) { + throw new IllegalArgumentException("Duplicate order values found in parameter sets. Please make sure that order values are unique."); + } + } +} diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareHandler.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareHandler.java new file mode 100644 index 00000000000..0bd169e0b60 --- /dev/null +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareHandler.java @@ -0,0 +1,8 @@ +package org.matsim.contrib.vsp.pt.fare; + +import org.matsim.api.core.v01.events.handler.ActivityStartEventHandler; +import org.matsim.core.api.experimental.events.handler.AgentWaitingForPtEventHandler; + +public interface PtFareHandler extends ActivityStartEventHandler, AgentWaitingForPtEventHandler { + //other methods for informed mode choice +} diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareModule.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareModule.java new file mode 100644 index 00000000000..8bb27ba59b4 --- /dev/null +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareModule.java @@ -0,0 +1,51 @@ +package org.matsim.contrib.vsp.pt.fare; + +import com.google.inject.multibindings.Multibinder; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.core.config.ConfigGroup; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.controler.AbstractModule; + +import java.net.URL; +import java.util.Collection; +import java.util.Comparator; +import java.util.stream.Stream; + +public class PtFareModule extends AbstractModule { + + @Override + public void install() { + getConfig().scoring().getModes().get(TransportMode.pt).setDailyMonetaryConstant(0); + getConfig().scoring().getModes().get(TransportMode.pt).setMarginalUtilityOfDistance(0); + Multibinder ptFareCalculator = Multibinder.newSetBinder(binder(), PtFareCalculator.class); + + PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(this.getConfig(), PtFareConfigGroup.class); + Collection fareZoneBased = ptFareConfigGroup.getParameterSets(FareZoneBasedPtFareParams.SET_TYPE); + Collection distanceBased = ptFareConfigGroup.getParameterSets(DistanceBasedPtFareParams.SET_TYPE); + + URL context = getConfig().getContext(); + + Stream.concat(fareZoneBased.stream(), distanceBased.stream()) + .map(c -> (PtFareParams) c) + .sorted(Comparator.comparing(PtFareParams::getOrder)) + .forEach(p -> { + if (p instanceof FareZoneBasedPtFareParams fareZoneBasedPtFareParams) { + ptFareCalculator.addBinding().toInstance(new FareZoneBasedPtFareCalculator(fareZoneBasedPtFareParams, context)); + } else if (p instanceof DistanceBasedPtFareParams distanceBasedPtFareParams) { + ptFareCalculator.addBinding().toInstance(new DistanceBasedPtFareCalculator(distanceBasedPtFareParams, context)); + } else { + throw new RuntimeException("Unknown PtFareParams: " + p.getClass()); + } + }); + + bind(ChainedPtFareCalculator.class); + bind(PtFareHandler.class).to(ChainedPtFareHandler.class); + addEventHandlerBinding().to(PtFareHandler.class); + + if (ptFareConfigGroup.getApplyUpperBound()) { + PtFareUpperBoundHandler ptFareUpperBoundHandler = new PtFareUpperBoundHandler(ptFareConfigGroup.getUpperBoundFactor()); + addEventHandlerBinding().toInstance(ptFareUpperBoundHandler); + addControlerListenerBinding().toInstance(ptFareUpperBoundHandler); + } + } +} diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareParams.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareParams.java new file mode 100644 index 00000000000..2ab1c501d4f --- /dev/null +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareParams.java @@ -0,0 +1,71 @@ +package org.matsim.contrib.vsp.pt.fare; + +import org.matsim.core.config.ReflectiveConfigGroup; + +import java.util.Map; + +public abstract class PtFareParams extends ReflectiveConfigGroup { + public static final String FARE_ZONE_SHP = "fareZoneShp"; + public static final String ORDER = "order"; + public static final String TRANSACTION_PARTNER = "transactionPartner"; + public static final String DESCRIPTION = "description"; + + private int order; + private String fareZoneShp; + private String transactionPartner; + private String description; + + public PtFareParams(String name) { + super(name); + } + + @Override + public Map getComments() { + var map = super.getComments(); + map.put(FARE_ZONE_SHP, "Shp file with fare zone(s). This parameter is only used for PtFareCalculationModel 'fareZoneBased'."); + map.put(ORDER, "Order of this fare calculation in the list of fare calculations. Lower values mean to be evaluated first."); + map.put(TRANSACTION_PARTNER, "The transaction partner for the fare calculation. This is used in the PersonMoneyEvent."); + map.put(DESCRIPTION, "Description of the fare zone."); + return map; + } + + @StringGetter(FARE_ZONE_SHP) + public String getFareZoneShp() { + return fareZoneShp; + } + + @StringSetter(FARE_ZONE_SHP) + public void setFareZoneShp(String fareZoneShp) { + this.fareZoneShp = fareZoneShp; + } + + @StringGetter(ORDER) + public int getOrder() { + return order; + } + + @StringSetter(ORDER) + public void setOrder(int order) { + this.order = order; + } + + @StringGetter(TRANSACTION_PARTNER) + public String getTransactionPartner() { + return transactionPartner; + } + + @StringSetter(TRANSACTION_PARTNER) + public void setTransactionPartner(String transactionPartner) { + this.transactionPartner = transactionPartner; + } + + @StringGetter(DESCRIPTION) + public String getDescription() { + return description; + } + + @StringSetter(DESCRIPTION) + public void setDescription(String description) { + this.description = description; + } +} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareUpperBoundHandler.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareUpperBoundHandler.java similarity index 96% rename from contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareUpperBoundHandler.java rename to contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareUpperBoundHandler.java index 6638c12e7f3..8d9accc9759 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareUpperBoundHandler.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareUpperBoundHandler.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import com.google.inject.Inject; import org.matsim.api.core.v01.Id; @@ -10,7 +10,6 @@ import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.controler.events.AfterMobsimEvent; import org.matsim.core.controler.listener.AfterMobsimListener; -import org.matsim.pt.PtConstants; import java.util.ArrayList; import java.util.HashMap; @@ -62,7 +61,7 @@ public void notifyAfterMobsim(AfterMobsimEvent event) { // Issue refund to person events.processEvent( new PersonMoneyEvent(getOrCalcCompensationTime(), personId, refund, - PT_REFUND, TransportMode.pt, "Refund for person" + personId.toString())); + PT_REFUND, TransportMode.pt, "Refund for person " + personId.toString())); } } } diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java similarity index 86% rename from contribs/vsp/src/main/java/playground/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java rename to contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java index 5af45c407fe..b1d05244534 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import com.google.inject.Inject; import it.unimi.dsi.fastutil.doubles.DoubleArrayList; @@ -29,13 +29,22 @@ public class PtTripWithDistanceBasedFareEstimator extends PtTripEstimator { private final Map, TransitStopFacility> facilities; @Inject - public PtTripWithDistanceBasedFareEstimator(TransitSchedule transitSchedule, PtFareConfigGroup config, DistanceBasedPtFareParams ptFare, Scenario scenario) { + public PtTripWithDistanceBasedFareEstimator(TransitSchedule transitSchedule, PtFareConfigGroup config, + Scenario scenario) { super(transitSchedule); this.config = config; - this.ptFare = ptFare; + this.ptFare = extractPtFare(config); this.facilities = scenario.getTransitSchedule().getFacilities(); } + private static DistanceBasedPtFareParams extractPtFare(PtFareConfigGroup config) { + //TODO + return config.getParameterSets(DistanceBasedPtFareParams.SET_TYPE).stream() + .map(DistanceBasedPtFareParams.class::cast) + .findFirst() + .orElseThrow(() -> new IllegalStateException("No distance based fare parameters found")); + } + @Override public MinMaxEstimate estimate(EstimatorContext context, String mode, PlanModel plan, List trip, ModeAvailability option) { @@ -55,8 +64,9 @@ public MinMaxEstimate estimate(EstimatorContext context, String mode, PlanModel maxFareUtility = Math.max(fareUtility, maxFareUtility); max = estimate + maxFareUtility; - } else + } else { max = estimate + fareUtility; + } // Distance fareUtility is the highest possible price, therefore the minimum utility return MinMaxEstimate.of(estimate + fareUtility, max); @@ -78,8 +88,9 @@ public double estimate(EstimatorContext context, String mode, String[] modes, Pl List legs = plan.getLegs(mode, i); // Legs can be null if there is a predefined pt trip - if (legs == null) + if (legs == null) { continue; + } //assert legs != null : "Legs must be not null at this point"; @@ -121,8 +132,9 @@ private DoubleDoublePair estimateTrip(EstimatorContext context, List trip) TransitPassengerRoute route = (TransitPassengerRoute) leg.getRoute(); - if (access == null) + if (access == null) { access = facilities.get(route.getAccessStopId()); + } egress = facilities.get(route.getEgressStopId()); @@ -139,9 +151,8 @@ private DoubleDoublePair estimateTrip(EstimatorContext context, List trip) double dist = CoordUtils.calcEuclideanDistance(access.getCoord(), egress.getCoord()); - double fareUtility = -context.scoring.marginalUtilityOfMoney * DistanceBasedPtFareHandler.computeFare(dist, ptFare.getLongDistanceTripThreshold(), ptFare.getMinFare(), - ptFare.getNormalTripIntercept(), ptFare.getNormalTripSlope(), ptFare.getLongDistanceTripIntercept(), ptFare.getLongDistanceTripSlope()); - + double fareUtility = -context.scoring.marginalUtilityOfMoney * DistanceBasedPtFareCalculator.computeFare(dist, + ptFare.getMinFare(), ptFare.getDistanceClassFareParams()); estimate += context.scoring.marginalUtilityOfWaitingPt_s * totalWaitingTime; @@ -165,8 +176,9 @@ private double calcMinimumFare(PlanModel plan) { List legs = plan.getLegs(TransportMode.pt, i); - if (legs == null) + if (legs == null) { continue; + } // first access and last egress TransitStopFacility access = null; @@ -183,8 +195,9 @@ private double calcMinimumFare(PlanModel plan) { TransitPassengerRoute route = (TransitPassengerRoute) leg.getRoute(); hasPT = true; - if (access == null) + if (access == null) { access = facilities.get(route.getAccessStopId()); + } egress = facilities.get(route.getEgressStopId()); } @@ -206,15 +219,14 @@ private double calcMinimumFare(PlanModel plan) { // a single pt trip could never benefit from the upper bound if (n == 1) { - return DistanceBasedPtFareHandler.computeFare(minDist, ptFare.getLongDistanceTripThreshold(), ptFare.getMinFare(), - ptFare.getNormalTripIntercept(), ptFare.getNormalTripSlope(), ptFare.getLongDistanceTripIntercept(), ptFare.getLongDistanceTripSlope()); + return DistanceBasedPtFareCalculator.computeFare(minDist, ptFare.getMinFare(), ptFare.getDistanceClassFareParams()); } // the upper bound is the maximum single trip times a factor // therefore the minimum upper bound is the fare for the second-longest trip // the max costs are then assumed to be evenly distributed over all pt trips - return 1d / n * config.getUpperBoundFactor() * DistanceBasedPtFareHandler.computeFare(secondMinDist, ptFare.getLongDistanceTripThreshold(), ptFare.getMinFare(), - ptFare.getNormalTripIntercept(), ptFare.getNormalTripSlope(), ptFare.getLongDistanceTripIntercept(), ptFare.getLongDistanceTripSlope()); + return 1d / n * config.getUpperBoundFactor() * DistanceBasedPtFareCalculator.computeFare(secondMinDist, + ptFare.getMinFare(), ptFare.getDistanceClassFareParams()); } @Override diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/scoring/RideScoringParamsFromCarParams.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/scoring/RideScoringParamsFromCarParams.java new file mode 100644 index 00000000000..2286692e4d6 --- /dev/null +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/scoring/RideScoringParamsFromCarParams.java @@ -0,0 +1,37 @@ +package org.matsim.contrib.vsp.scoring; + +import org.matsim.api.core.v01.TransportMode; +import org.matsim.core.config.groups.ScoringConfigGroup; + +public class RideScoringParamsFromCarParams { + + /** + * Sets ride scoring params based on car scoring params (including prices). This assumes that the ride passenger somehow has + * to compensate the driver for the additional driving effort to provide the ride. + * + * @param scoringConfigGroup config.scoring() + * @param alpha represents the share of an average ride trip that the car driver has to drive additionally to the car + * trip to provide the ride. Typical values are between 1 (i.e. driver drives additional 10km to provide a 10 km + * ride) and 2 (i.e. driver drives additional 20km to provide a 10 km ride). Alpha can be calibrated and must + * be alpha >= 0. + */ + public static void setRideScoringParamsBasedOnCarParams (ScoringConfigGroup scoringConfigGroup, double alpha) { + ScoringConfigGroup.ModeParams carParams = scoringConfigGroup.getOrCreateModeParams(TransportMode.car); + ScoringConfigGroup.ModeParams rideParams = scoringConfigGroup.getOrCreateModeParams(TransportMode.ride); + + // constant is a calibration parameter and should not be changed + + // ride has no fixed cost + rideParams.setDailyMonetaryConstant(0.0); + + // account for the driver's monetary distance rate. + rideParams.setMonetaryDistanceRate(alpha * carParams.getMonetaryDistanceRate()); + + // rider and driver have marginalUtilityOfDistance + rideParams.setMarginalUtilityOfDistance((alpha + 1.0) * carParams.getMarginalUtilityOfDistance()); + + // rider and driver have marginalUtilityOfTravelling, the driver additionally loses the opportunity to perform an activity + rideParams.setMarginalUtilityOfTraveling((alpha + 1.0) * carParams.getMarginalUtilityOfTraveling() + + alpha * -scoringConfigGroup.getPerforming_utils_hr()); + } +} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareHandler.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareHandler.java deleted file mode 100644 index 79741e54919..00000000000 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareHandler.java +++ /dev/null @@ -1,81 +0,0 @@ -package playground.vsp.pt.fare; - -import com.google.inject.Inject; -import org.matsim.api.core.v01.Coord; -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.events.ActivityStartEvent; -import org.matsim.api.core.v01.events.PersonMoneyEvent; -import org.matsim.api.core.v01.events.handler.ActivityStartEventHandler; -import org.matsim.api.core.v01.population.Person; -import org.matsim.core.api.experimental.events.EventsManager; -import org.matsim.core.router.StageActivityTypeIdentifier; -import org.matsim.core.utils.geometry.CoordUtils; -import org.matsim.pt.PtConstants; - -import java.util.HashMap; -import java.util.Map; - -public class DistanceBasedPtFareHandler implements ActivityStartEventHandler { - @Inject - private EventsManager events; - - private final double minFare; - private final double shortTripIntercept; - private final double shortTripSlope; - private final double longTripIntercept; - private final double longTripSlope; - private final double longTripThreshold; - - private final Map, Coord> personDepartureCoordMap = new HashMap<>(); - private final Map, Coord> personArrivalCoordMap = new HashMap<>(); - - public DistanceBasedPtFareHandler(DistanceBasedPtFareParams params) { - this.minFare = params.getMinFare(); - this.shortTripIntercept = params.getNormalTripIntercept(); - this.shortTripSlope = params.getNormalTripSlope(); - this.longTripIntercept = params.getLongDistanceTripIntercept(); - this.longTripSlope = params.getLongDistanceTripSlope(); - this.longTripThreshold = params.getLongDistanceTripThreshold(); - } - - @Override - public void handleEvent(ActivityStartEvent event) { - if (event.getActType().equals(PtConstants.TRANSIT_ACTIVITY_TYPE)) { - personDepartureCoordMap.computeIfAbsent(event.getPersonId(), c -> event.getCoord()); // The departure place is fixed to the place of first pt interaction an agent has in the whole leg - personArrivalCoordMap.put(event.getPersonId(), event.getCoord()); // The arrival stop will keep updating until the agent start a real activity (i.e. finish the leg) - } - - if (!StageActivityTypeIdentifier.isStageActivity(event.getActType())) { - Id personId = event.getPersonId(); - if (personDepartureCoordMap.containsKey(personId)) { - double distance = CoordUtils.calcEuclideanDistance - (personDepartureCoordMap.get(personId), personArrivalCoordMap.get(personId)); - - double fare = computeFare(distance, longTripThreshold, minFare, shortTripIntercept, shortTripSlope, longTripIntercept, longTripSlope); - // charge fare to the person - events.processEvent( - new PersonMoneyEvent(event.getTime(), event.getPersonId(), -fare, - PtFareConfigGroup.PT_FARE, DistanceBasedPtFareParams.PT_FARE_DISTANCE_BASED, event.getPersonId().toString())); - - personDepartureCoordMap.remove(personId); - personArrivalCoordMap.remove(personId); - } - } - } - - public static double computeFare(double distance, double longTripThreshold, double minFare, - double shortTripIntercept, double shortTripSlope, - double longTripIntercept, double longTripSlope) { - if (distance <= longTripThreshold) { - return Math.max(minFare, shortTripIntercept + shortTripSlope * distance); - } else { - return Math.max(minFare, longTripIntercept + longTripSlope * distance); - } - } - - @Override - public void reset(int iteration) { - personArrivalCoordMap.clear(); - personDepartureCoordMap.clear(); - } -} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java deleted file mode 100644 index a86cd173c14..00000000000 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java +++ /dev/null @@ -1,117 +0,0 @@ -package playground.vsp.pt.fare; - -import org.matsim.core.config.ReflectiveConfigGroup; - -import jakarta.validation.constraints.PositiveOrZero; - -import java.util.Map; - -/** - * @author Chengqi Lu (luchengqi7) - * The parameters for the distance-based PT trip fare calculation. - * The default values are set based on the fitting results of the trip and fare data collected on September 2021 - * The values are based on the standard unit of meter (m) and Euro (EUR) - */ -public class DistanceBasedPtFareParams extends ReflectiveConfigGroup { - public static final String PT_FARE_DISTANCE_BASED = "distance based pt fare"; - - public static final String SET_NAME = "ptFareCalculationDistanceBased"; - public static final String MIN_FARE = "minFare"; - public static final String NORMAL_TRIP_SLOPE = "normalTripSlope"; - public static final String NORMAL_TRIP_INTERCEPT = "normalTripIntercept"; - public static final String LONG_DISTANCE_TRIP_THRESHOLD = "longDistanceTripThreshold"; - public static final String LONG_DISTANCE_TRIP_SLOPE = "longDistanceTripSlope"; - public static final String LONG_DISTANCE_TRIP_INTERCEPT = "longDistanceTripIntercept"; - - @PositiveOrZero - private double minFare = 2.0; - @PositiveOrZero - private double normalTripIntercept = 1.6; - @PositiveOrZero - private double normalTripSlope = 0.00017; - @PositiveOrZero - private double longDistanceTripThreshold = 50000.0; - @PositiveOrZero - private double longDistanceTripIntercept = 30.0; - @PositiveOrZero - private double longDistanceTripSlope = 0.00025; - - public DistanceBasedPtFareParams() { - super(SET_NAME); - } - - @Override - public Map getComments() { - Map map = super.getComments(); - map.put(MIN_FARE, "Minimum fare for a PT trip " + - "(e.g. Kurzstrecke/short distance ticket in cities, ticket for 1 zone in rural areas)"); - map.put(NORMAL_TRIP_SLOPE, "Linear model y = ax + b: the value of a, for normal trips (e.g. within the city or region)"); - map.put(NORMAL_TRIP_INTERCEPT, "Linear model y = ax + b: the value of b, for normal trips"); - map.put(LONG_DISTANCE_TRIP_SLOPE, "Linear model y = ax + b: the value of a, for long distance trips (e.g. intercity trips)"); - map.put(LONG_DISTANCE_TRIP_INTERCEPT, "Linear model y = ax + b: the value of b, for long trips"); - map.put(LONG_DISTANCE_TRIP_THRESHOLD, "Threshold of the long trips in meters. Below this value, " + - "the trips are considered as normal trips. Above this value, the trips are considered as " + - "inter-city trips"); - return map; - } - - @StringGetter(MIN_FARE) - public double getMinFare() { - return minFare; - } - - @StringSetter(MIN_FARE) - public void setMinFare(double minFare) { - this.minFare = minFare; - } - - @StringGetter(NORMAL_TRIP_SLOPE) - public double getNormalTripSlope() { - return normalTripSlope; - } - - @StringSetter(NORMAL_TRIP_SLOPE) - public void setNormalTripSlope(double normalTripSlope) { - this.normalTripSlope = normalTripSlope; - } - - @StringGetter(NORMAL_TRIP_INTERCEPT) - public double getNormalTripIntercept() { - return normalTripIntercept; - } - - @StringSetter(NORMAL_TRIP_INTERCEPT) - public void setNormalTripIntercept(double normalTripIntercept) { - this.normalTripIntercept = normalTripIntercept; - } - - @StringGetter(LONG_DISTANCE_TRIP_SLOPE) - public double getLongDistanceTripSlope() { - return longDistanceTripSlope; - } - - @StringSetter(LONG_DISTANCE_TRIP_SLOPE) - public void setLongDistanceTripSlope(double longDistanceTripSlope) { - this.longDistanceTripSlope = longDistanceTripSlope; - } - - @StringGetter(LONG_DISTANCE_TRIP_INTERCEPT) - public double getLongDistanceTripIntercept() { - return longDistanceTripIntercept; - } - - @StringSetter(LONG_DISTANCE_TRIP_INTERCEPT) - public void setLongDistanceTripIntercept(double longDistanceTripIntercept) { - this.longDistanceTripIntercept = longDistanceTripIntercept; - } - - @StringGetter(LONG_DISTANCE_TRIP_THRESHOLD) - public double getLongDistanceTripThreshold() { - return longDistanceTripThreshold; - } - - @StringSetter(LONG_DISTANCE_TRIP_THRESHOLD) - public void setLongDistanceTripThreshold(double longDistanceTripThreshold) { - this.longDistanceTripThreshold = longDistanceTripThreshold; - } -} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java deleted file mode 100644 index 20c9291dc1b..00000000000 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java +++ /dev/null @@ -1,75 +0,0 @@ -package playground.vsp.pt.fare; - -import org.matsim.core.config.ReflectiveConfigGroup; - -import jakarta.validation.constraints.PositiveOrZero; - -import java.util.Map; - -public class PtFareConfigGroup extends ReflectiveConfigGroup { - public static final String PT_FARE = "pt fare"; - public static final String MODULE_NAME = "ptFare"; - public static final String PT_FARE_CALCULATION = "ptFareCalculation"; - public static final String APPLY_UPPER_BOUND = "applyUpperBound"; - public static final String UPPER_BOUND_FACTOR = "upperBoundFactor"; - - public enum PtFareCalculationModels {distanceBased} // More to come (e.g. zone based, hybrid...) - - private static final String PT_FARE_CALCULATION_CMT = "PT fare calculation scheme. Current implementation: distanceBased (more to come...)"; - public static final String UPPER_BOUND_FACTOR_CMT = "When upper bound is applied, upperBound = upperBoundFactor * max Fare of the day. " + - "This value is decided by the ratio between average daily cost of a ticket subscription and the single " + - "trip ticket of the same trip. Usually this value should be somewhere between 1.0 and 2.0"; - public static final String APPLY_UPPER_BOUND_CMT = "Enable the upper bound for daily PT fare to count for ticket subscription. Input value: true or false"; - - private PtFareCalculationModels ptFareCalculation = PtFareCalculationModels.distanceBased; // Use distance based calculation by default - private boolean applyUpperBound = true; - @PositiveOrZero - private double upperBoundFactor = 1.5; - - public PtFareConfigGroup() { - super(MODULE_NAME); - } - - @Override - public Map getComments() { - Map map = super.getComments(); - map.put(PT_FARE_CALCULATION, PT_FARE_CALCULATION_CMT ); - map.put(APPLY_UPPER_BOUND, APPLY_UPPER_BOUND_CMT ); - map.put(UPPER_BOUND_FACTOR, UPPER_BOUND_FACTOR_CMT ); - return map; - } - - @StringGetter(PT_FARE_CALCULATION) - public PtFareCalculationModels getPtFareCalculation() { - return ptFareCalculation; - } - - @StringSetter(PT_FARE_CALCULATION) - public void setPtFareCalculationModel(PtFareCalculationModels ptFareCalculation) { - this.ptFareCalculation = ptFareCalculation; - } - - @StringGetter(APPLY_UPPER_BOUND) - public boolean getApplyUpperBound() { - return applyUpperBound; - } - - @StringSetter(APPLY_UPPER_BOUND) - public void setApplyUpperBound(boolean applyUpperBound) { - this.applyUpperBound = applyUpperBound; - } - - - @StringGetter(UPPER_BOUND_FACTOR) - public double getUpperBoundFactor() { - return upperBoundFactor; - } - - /** - * @param upperBoundFactor -- {@value #UPPER_BOUND_FACTOR_CMT} - */ - @StringSetter(UPPER_BOUND_FACTOR) - public void setUpperBoundFactor(double upperBoundFactor) { - this.upperBoundFactor = upperBoundFactor; - } -} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java deleted file mode 100644 index 9bd25cc81f4..00000000000 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java +++ /dev/null @@ -1,28 +0,0 @@ -package playground.vsp.pt.fare; - -import org.matsim.api.core.v01.TransportMode; -import org.matsim.core.config.ConfigUtils; -import org.matsim.core.controler.AbstractModule; - -public class PtFareModule extends AbstractModule { - - @Override - public void install() { - getConfig().scoring().getModes().get(TransportMode.pt).setDailyMonetaryConstant(0); - getConfig().scoring().getModes().get(TransportMode.pt).setMarginalUtilityOfDistance(0); - PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(this.getConfig(), PtFareConfigGroup.class); - if (ptFareConfigGroup.getPtFareCalculation() == PtFareConfigGroup.PtFareCalculationModels.distanceBased) { - DistanceBasedPtFareParams distanceBasedPtFareParams = ConfigUtils.addOrGetModule(this.getConfig(), DistanceBasedPtFareParams.class); - addEventHandlerBinding().toInstance(new DistanceBasedPtFareHandler(distanceBasedPtFareParams)); - } else { - throw new RuntimeException("Please choose from the following fare Calculation method: [" + - PtFareConfigGroup.PtFareCalculationModels.distanceBased + "]"); - } - - if (ptFareConfigGroup.getApplyUpperBound()) { - PtFareUpperBoundHandler ptFareUpperBoundHandler = new PtFareUpperBoundHandler(ptFareConfigGroup.getUpperBoundFactor()); - addEventHandlerBinding().toInstance(ptFareUpperBoundHandler); - addControlerListenerBinding().toInstance(ptFareUpperBoundHandler); - } - } -} diff --git a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareHandlerTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareHandlerTest.java new file mode 100644 index 00000000000..5fb7ea83355 --- /dev/null +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareHandlerTest.java @@ -0,0 +1,200 @@ +package org.matsim.contrib.vsp.pt.fare; + +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.events.PersonMoneyEvent; +import org.matsim.api.core.v01.events.handler.PersonMoneyEventHandler; +import org.matsim.api.core.v01.population.*; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controler; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.scenario.MutableScenario; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; +import org.matsim.testcases.MatsimTestUtils; + +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +public class ChainedPtFareHandlerTest { + + private final static String FARE_ZONE_TRANSACTION_PARTNER = "fare zone transaction partner"; + private final static String DISTANCE_BASED_TRANSACTION_PARTNER = "distance based transaction partner"; + + @RegisterExtension + private MatsimTestUtils utils = new MatsimTestUtils(); + + @Test + void testChainedPtFareHandler() { + //Prepare + Config config = getConfig(); + + //adapt pt fare + PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(config, PtFareConfigGroup.class); + + FareZoneBasedPtFareParams fareZoneBased = new FareZoneBasedPtFareParams(); + fareZoneBased.setDescription("simple fare zone based"); + // smallest area (Kelheim and villages) + fareZoneBased.setFareZoneShp(IOUtils.extendUrl(config.getContext(), "ptTestArea/pt-area.shp").toString()); + fareZoneBased.setOrder(1); + fareZoneBased.setTransactionPartner(FARE_ZONE_TRANSACTION_PARTNER); + + DistanceBasedPtFareParams distanceBased = new DistanceBasedPtFareParams(); + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClassFareParams = + distanceBased.getOrCreateDistanceClassFareParams(Double.POSITIVE_INFINITY); + distanceClassFareParams.setFareSlope(0.00017); + distanceClassFareParams.setFareIntercept(1.6); + distanceBased.setOrder(2); + distanceBased.setTransactionPartner(DISTANCE_BASED_TRANSACTION_PARTNER); + // larger area Kelheim - Regensburg + distanceBased.setFareZoneShp(IOUtils.extendUrl(config.getContext(), "pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.shp").toString()); + distanceBased.setMinFare(2.0); + + // second DistanceBasedPtFareParams, e.g. applicable in a different shape file + DistanceBasedPtFareParams distanceBased2 = new DistanceBasedPtFareParams(); + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClassFareParams2 = + distanceBased2.getOrCreateDistanceClassFareParams(Double.POSITIVE_INFINITY); + distanceClassFareParams2.setFareSlope(0.0003); + distanceClassFareParams2.setFareIntercept(2.0); + distanceBased2.setOrder(3); + distanceBased2.setTransactionPartner(DISTANCE_BASED_TRANSACTION_PARTNER); + distanceBased2.setMinFare(7.0); + + ptFareConfigGroup.addParameterSet(fareZoneBased); + ptFareConfigGroup.addParameterSet(distanceBased); + ptFareConfigGroup.addParameterSet(distanceBased2); + + ptFareConfigGroup.setUpperBoundFactor(2.0); + + // write config to file and read in again to check config reading and writing + ConfigUtils.writeConfig(config, utils.getOutputDirectory() + "configFromCode.xml"); + Config configFromFile = ConfigUtils.loadConfig(utils.getOutputDirectory() + "configFromCode.xml"); + // re-direct to correct input directory + URL context = ExamplesUtils.getTestScenarioURL("kelheim"); + configFromFile.setContext(context); + + MutableScenario scenario = setUpScenario(configFromFile); + + //Run + var fareAnalysis = new FareAnalysis(); + + Controler controler = new Controler(scenario); + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new PtFareModule()); + addEventHandlerBinding().toInstance(fareAnalysis); + } + }); + controler.run(); + + //Check + List events = fareAnalysis.getEvents(); + // 1 event per leg plus 1 event fare capping at upper bound factor + Assertions.assertEquals(5, events.size()); + + final String FARE_TEST_PERSON = "fareTestPerson"; + + //first event is the fare zone based event + Assertions.assertEquals(new PersonMoneyEvent(33264, Id.createPersonId(FARE_TEST_PERSON), -1.5, "pt fare", FARE_ZONE_TRANSACTION_PARTNER, + FARE_TEST_PERSON), events.get(0)); + + //second event is the distance based fare of the first DistanceBasedPtFareParams (in area.shp) + Assertions.assertEquals(new PersonMoneyEvent(51062, Id.createPersonId(FARE_TEST_PERSON), -2.788776056323089, "pt fare", + DISTANCE_BASED_TRANSACTION_PARTNER, FARE_TEST_PERSON), events.get(1)); + + //third event is the distance based fare of the second DistanceBasedPtFareParams (outside area.shp), ca. 5.069 < min fare 7.0 + Assertions.assertEquals(new PersonMoneyEvent(61622, Id.createPersonId(FARE_TEST_PERSON), -7.0, "pt fare", + DISTANCE_BASED_TRANSACTION_PARTNER, FARE_TEST_PERSON), events.get(2)); + + //fourth event is the distance based fare of the second DistanceBasedPtFareParams (outside area.shp) + Assertions.assertEquals(new PersonMoneyEvent(70354, Id.createPersonId(FARE_TEST_PERSON), -7.961415135189197, "pt fare", + DISTANCE_BASED_TRANSACTION_PARTNER, FARE_TEST_PERSON), events.get(3)); + + //fifth event is the upper bound fare capping compensation + Assertions.assertEquals(new PersonMoneyEvent(129600, Id.createPersonId(FARE_TEST_PERSON), 3.3273609211338915, "pt fare refund", + "pt", "Refund for person fareTestPerson"), events.get(4)); + } + + private @NotNull MutableScenario setUpScenario(Config config) { + MutableScenario scenario = (MutableScenario) ScenarioUtils.loadScenario(config); + + Population population = ScenarioUtils.createScenario(ConfigUtils.createConfig()).getPopulation(); + PopulationFactory fac = population.getFactory(); + + Person person = fac.createPerson(Id.createPersonId("fareTestPerson")); + Plan plan = fac.createPlan(); + + Activity home = fac.createActivityFromCoord("home", new Coord(710300.624, 5422165.737)); + // bus to Saal (Donau) work location departs at 09:14 + home.setEndTime(9 * 3600.); + Activity work = fac.createActivityFromCoord("work", new Coord(714940.65, 5420707.78)); + // rb17 to Gundelshausen 2nd work location departs at 13:59 (in distance fare 1 zone, 6992.797m) + work.setEndTime(13 * 3600. + 45 * 60); + Activity work2 = fac.createActivityFromCoord("work", new Coord(719916.02, 5425676.91)); + // rb17 to Regensburg 2nd home location departs at 16:52 (beyond distance fare 1 zone, distance fare 2 applies, 10230.93m) + work2.setEndTime(16 * 3600. + 40 * 60); + Activity work3 = fac.createActivityFromCoord("work", new Coord(726645.48, 5433383.16)); + // rb17 to Kelheim home location departs at 18:46, then transfer to bus 6022 (beyond distance fare 1 zone, distance fare 2 applies, 19871.38m) + work3.setEndTime(18 * 3600. + 40 * 60); + Activity home2 = fac.createActivityFromCoord("home", new Coord(710300.624, 5422165.737)); + + Leg leg = fac.createLeg(TransportMode.pt); + + plan.addActivity(home); + plan.addLeg(leg); + plan.addActivity(work); + plan.addLeg(leg); + plan.addActivity(work2); + plan.addLeg(leg); + plan.addActivity(work3); + plan.addLeg(leg); + plan.addActivity(home2); + + person.addPlan(plan); + population.addPerson(person); + scenario.setPopulation(population); + return scenario; + } + + private @NotNull Config getConfig() { + URL context = ExamplesUtils.getTestScenarioURL("kelheim"); + Config config = ConfigUtils.loadConfig(IOUtils.extendUrl(context, "config.xml")); + config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + config.controller().setLastIteration(0); + + ScoringConfigGroup scoring = ConfigUtils.addOrGetModule(config, ScoringConfigGroup.class); + + ScoringConfigGroup.ActivityParams homeParams = new ScoringConfigGroup.ActivityParams("home"); + ScoringConfigGroup.ActivityParams workParams = new ScoringConfigGroup.ActivityParams("work"); + homeParams.setTypicalDuration(8 * 3600.); + workParams.setTypicalDuration(8 * 3600.); + scoring.addActivityParams(homeParams); + scoring.addActivityParams(workParams); + return config; + } + + private static class FareAnalysis implements PersonMoneyEventHandler { + private final List events = new ArrayList<>(); + + @Override + public void handleEvent(PersonMoneyEvent event) { + events.add(event); + } + + public List getEvents() { + return events; + } + } +} diff --git a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java new file mode 100644 index 00000000000..71e5a803859 --- /dev/null +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java @@ -0,0 +1,133 @@ +package org.matsim.contrib.vsp.pt.fare; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Coord; +import org.matsim.core.utils.geometry.CoordUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; + +import java.net.URL; +import java.util.Optional; + +class DistanceBasedPtFareCalculatorTest { + private static final String TRANSACTION_PARTNER = "TP"; + + private static final URL context = ExamplesUtils.getTestScenarioURL("kelheim"); + + @Test + void testNormalDistance() { + //100m -> 1.1 EUR + calculateAndCheck(null, new Coord(0, 0), new Coord(0, 100), 1.1); + } + + @Test + void testLongDistance() { + //3000m -> 4.5 EUR + calculateAndCheck(null, new Coord(0, 0), new Coord(0, 3000), 4.5); + } + + @Test + void testThreshold() { + //2000m -> 3.0 EUR + calculateAndCheck(null, new Coord(0, 0), new Coord(0, 2000), 3.0); + } + + @Test + void testNotInShapeFile() { + String shape = IOUtils.extendUrl(context, "ptTestArea/pt-area.shp").toString(); + Coord a = new Coord(726634.40, 5433508.07); + Coord b = new Coord(736634.40, 5533508.07); + DistanceBasedPtFareCalculator calculator = getCalculator(shape); + Assertions.assertEquals(Optional.empty(), calculator.calculateFare(a, b)); + } + + @Test + void testInShapeFile() { + String shape = IOUtils.extendUrl(context, "ptTestArea/pt-area.shp").toString(); + Coord a = new Coord(710300.624, 5422165.737); + Coord b = new Coord(714940.65, 5420707.78); + double distance = CoordUtils.calcEuclideanDistance(a, b); + calculateAndCheck(shape, a, b, distance * 0.0005 + 3.); + } + + private void calculateAndCheck(String shape, Coord a, Coord b, double fare) { + DistanceBasedPtFareCalculator distanceBasedPtFareCalculator = getCalculator(shape); + PtFareCalculator.FareResult fareResult = distanceBasedPtFareCalculator.calculateFare(a, b).orElseThrow(); + Assertions.assertEquals(new PtFareCalculator.FareResult(fare, TRANSACTION_PARTNER), fareResult); + } + + private DistanceBasedPtFareCalculator getCalculator(String shapeFile) { + var params = new DistanceBasedPtFareParams(); + params.setTransactionPartner(TRANSACTION_PARTNER); + //0-2000m: 1EUR + 1EUR/km + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClass2kmFareParams = + params.getOrCreateDistanceClassFareParams(2000.0); + distanceClass2kmFareParams.setFareIntercept(1.0); + distanceClass2kmFareParams.setFareSlope(0.001); + + //2000m+: 3EUR + 0.5EUR/km + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClassLongFareParams = + params.getOrCreateDistanceClassFareParams(Double.POSITIVE_INFINITY); + distanceClassLongFareParams.setFareIntercept(3.0); + distanceClassLongFareParams.setFareSlope(0.0005); + + params.setMinFare(1.0); + params.setFareZoneShp(shapeFile); + return new DistanceBasedPtFareCalculator(params, context); + } + + @Test + void testModifyParams() { + var params = new DistanceBasedPtFareParams(); + params.setTransactionPartner(TRANSACTION_PARTNER); + + //2000m+: 3EUR + 0.5EUR/km + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClassLongFareParams = + params.getOrCreateDistanceClassFareParams(Double.POSITIVE_INFINITY); + distanceClassLongFareParams.setFareIntercept(3.0); + distanceClassLongFareParams.setFareSlope(0.0005); + + //0-2000m: 1EUR + 1EUR/km + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClass2kmFareParams = + params.getOrCreateDistanceClassFareParams(2000.0); + distanceClass2kmFareParams.setFareIntercept(1.0); + distanceClass2kmFareParams.setFareSlope(0.001); + + // get params for max distance 2km and modify + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClass2kmDuplicateFareParams = + params.getOrCreateDistanceClassFareParams(2000.0); + distanceClass2kmDuplicateFareParams.setFareIntercept(2.0); + distanceClass2kmDuplicateFareParams.setFareSlope(0.002); + + params.setMinFare(1.0); + + DistanceBasedPtFareCalculator distanceBasedPtFareCalculator = new DistanceBasedPtFareCalculator(params, context); + PtFareCalculator.FareResult fareResult = distanceBasedPtFareCalculator.calculateFare(new Coord(0, 0), new Coord(0, 100)).orElseThrow(); + Assertions.assertEquals(new PtFareCalculator.FareResult(2.2, TRANSACTION_PARTNER), fareResult); + } + + @Test + void testMultipleParamsWithSameMaxDistance() { + var params = new DistanceBasedPtFareParams(); + params.setTransactionPartner(TRANSACTION_PARTNER); + //0-2000m: 1EUR + 1EUR/km + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClass2kmFareParams = + params.getOrCreateDistanceClassFareParams(2000.0); + distanceClass2kmFareParams.setFareIntercept(1.0); + distanceClass2kmFareParams.setFareSlope(0.001); + + // add second distance class with same max distance + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClass2kmDuplicateFareParams = + new DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams(); + distanceClass2kmDuplicateFareParams.setMaxDistance(2000.0); + distanceClass2kmDuplicateFareParams.setFareIntercept(2.0); + distanceClass2kmDuplicateFareParams.setFareSlope(0.002); + // add in a different way so no automatic overwrite + params.addParameterSet(distanceClass2kmDuplicateFareParams); + + Assertions.assertThrows(RuntimeException.class, () -> new DistanceBasedPtFareCalculator(params, context), + "DistanceBasedPtFareCalculator should crash if multiple DistanceClassLinearFareFunctionParams with the same max distance " + + " are present, because it is unclear which of them should be applied at that distance."); + } +} diff --git a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java new file mode 100644 index 00000000000..e9e9080952e --- /dev/null +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java @@ -0,0 +1,55 @@ +package org.matsim.contrib.vsp.pt.fare; + +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Coord; +import org.matsim.examples.ExamplesUtils; + +import java.net.URL; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class FareZoneBasedPtFareCalculatorTest { + private static final double COST_IN_SHP_FILE = 1.5; + private static final String TRANSACTION_PARTNER = "TP"; + private static final URL context = ExamplesUtils.getTestScenarioURL("kelheim"); + + @Test + void testCalculateFareInShape() { + FareZoneBasedPtFareCalculator fareZoneBasedPtFareCalculator = new FareZoneBasedPtFareCalculator(getParams(), context); + + Coord inShape = new Coord(710300.624, 5422165.737); + Coord inShape2 = new Coord(714940.65, 5420707.78); + + assertEquals(Optional.of(new PtFareCalculator.FareResult(COST_IN_SHP_FILE, TRANSACTION_PARTNER)), + fareZoneBasedPtFareCalculator.calculateFare(inShape, + inShape2)); + assertEquals(Optional.of(new PtFareCalculator.FareResult(COST_IN_SHP_FILE, TRANSACTION_PARTNER)), + fareZoneBasedPtFareCalculator.calculateFare(inShape2, + inShape)); + } + + @Test + void testCalculateFareOutShape() { + FareZoneBasedPtFareCalculator fareZoneBasedPtFareCalculator = new FareZoneBasedPtFareCalculator(getParams(), context); + + Coord inShape = new Coord(710300.624, 5422165.737); + Coord inShape2 = new Coord(714940.65, 5420707.78); + Coord outShape = new Coord(726634.40, 5433508.07); + Coord outShape2 = new Coord(736634.40, 5533508.07); + + assertEquals(Optional.empty(), fareZoneBasedPtFareCalculator.calculateFare(inShape, outShape)); + assertEquals(Optional.empty(), fareZoneBasedPtFareCalculator.calculateFare(inShape, outShape2)); + assertEquals(Optional.empty(), fareZoneBasedPtFareCalculator.calculateFare(inShape2, outShape)); + assertEquals(Optional.empty(), fareZoneBasedPtFareCalculator.calculateFare(inShape2, outShape)); + assertEquals(Optional.empty(), fareZoneBasedPtFareCalculator.calculateFare(outShape, outShape2)); + } + + private FareZoneBasedPtFareParams getParams() { + FareZoneBasedPtFareParams fareZoneBasedPtFareParams = new FareZoneBasedPtFareParams(); + fareZoneBasedPtFareParams.setFareZoneShp("ptTestArea/pt-area.shp"); + fareZoneBasedPtFareParams.setTransactionPartner(TRANSACTION_PARTNER); + return fareZoneBasedPtFareParams; + } + +} diff --git a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/PtFareConfigGroupTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/PtFareConfigGroupTest.java new file mode 100644 index 00000000000..ed32e9ac859 --- /dev/null +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/PtFareConfigGroupTest.java @@ -0,0 +1,45 @@ +package org.matsim.contrib.vsp.pt.fare; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; + +class PtFareConfigGroupTest { + @Test + void testNoFareParams_throws() { + Config config = ConfigUtils.createConfig(); + PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(config, PtFareConfigGroup.class); + Assertions.assertThrows(IllegalArgumentException.class, () -> ptFareConfigGroup.checkConsistency(config)); + } + + @Test + void testSamePriority_throws() { + Config config = ConfigUtils.createConfig(); + PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(config, PtFareConfigGroup.class); + FareZoneBasedPtFareParams fareZoneBased = new FareZoneBasedPtFareParams(); + fareZoneBased.setOrder(5); + ptFareConfigGroup.addParameterSet(fareZoneBased); + + DistanceBasedPtFareParams distanceBased = new DistanceBasedPtFareParams(); + distanceBased.setOrder(5); + ptFareConfigGroup.addParameterSet(distanceBased); + + Assertions.assertThrows(IllegalArgumentException.class, () -> ptFareConfigGroup.checkConsistency(config)); + } + + @Test + void test_ok() { + Config config = ConfigUtils.createConfig(); + PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(config, PtFareConfigGroup.class); + FareZoneBasedPtFareParams fareZoneBased = new FareZoneBasedPtFareParams(); + fareZoneBased.setOrder(5); + ptFareConfigGroup.addParameterSet(fareZoneBased); + + DistanceBasedPtFareParams distanceBased = new DistanceBasedPtFareParams(); + distanceBased.setOrder(10); + ptFareConfigGroup.addParameterSet(distanceBased); + + ptFareConfigGroup.checkConsistency(config); + } +} diff --git a/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtTripFareEstimatorTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/PtTripFareEstimatorTest.java similarity index 79% rename from contribs/vsp/src/test/java/playground/vsp/pt/fare/PtTripFareEstimatorTest.java rename to contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/PtTripFareEstimatorTest.java index 6ddfef69d44..791931b89a2 100644 --- a/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtTripFareEstimatorTest.java +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/PtTripFareEstimatorTest.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import com.google.inject.Inject; import com.google.inject.Injector; @@ -60,18 +60,23 @@ public void setUp() throws Exception { group = ConfigUtils.addOrGetModule(config, InformedModeChoiceConfigGroup.class); PtFareConfigGroup fare = ConfigUtils.addOrGetModule(config, PtFareConfigGroup.class); - DistanceBasedPtFareParams distanceFare = ConfigUtils.addOrGetModule(config, DistanceBasedPtFareParams.class); + DistanceBasedPtFareParams distanceFare = new DistanceBasedPtFareParams(); fare.setApplyUpperBound(true); fare.setUpperBoundFactor(1.5); distanceFare.setMinFare(0.1); - distanceFare.setNormalTripIntercept(0.5); - distanceFare.setNormalTripSlope(0.1); + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClass20kmFareParams = + distanceFare.getOrCreateDistanceClassFareParams(20000.0); + distanceClass20kmFareParams.setFareIntercept(0.5); + distanceClass20kmFareParams.setFareSlope(0.1); - distanceFare.setLongDistanceTripThreshold(20000); - distanceFare.setLongDistanceTripIntercept(1); - distanceFare.setLongDistanceTripSlope(0.01); + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClassLongFareParams = + distanceFare.getOrCreateDistanceClassFareParams(Double.POSITIVE_INFINITY); + distanceClassLongFareParams.setFareIntercept(1.0); + distanceClassLongFareParams.setFareSlope(0.01); + + fare.addParameterSet(distanceFare); controler = MATSimApplication.prepare(TestScenario.class, config); injector = controler.getInjector(); @@ -98,8 +103,9 @@ private List estimateAgent(Id personId) { List trip = model.getLegs(TransportMode.pt, i); - if (trip == null) + if (trip == null) { continue; + } MinMaxEstimate est = estimator.estimate(context, TransportMode.pt, model, trip, ModeAvailability.YES); @@ -116,9 +122,9 @@ void fare() { System.out.println(est); assertThat(est) - .allMatch(e -> e.getMin() < e.getMax(), "Min smaller max") - .first().extracting(MinMaxEstimate::getMin, InstanceOfAssertFactories.DOUBLE) - .isCloseTo(-379.4, Offset.offset(0.1)); + .allMatch(e -> e.getMin() < e.getMax(), "Min smaller max") + .first().extracting(MinMaxEstimate::getMin, InstanceOfAssertFactories.DOUBLE) + .isCloseTo(-379.4, Offset.offset(0.1)); } @@ -129,7 +135,7 @@ void all() { List est = estimateAgent(agent); assertThat(est) - .allMatch(e -> e.getMin() <= e.getMax(), "Min smaller max"); + .allMatch(e -> e.getMin() <= e.getMax(), "Min smaller max"); } } @@ -157,22 +163,22 @@ void planEstimate() { double estimate = estimator.estimate(context, TransportMode.pt, new String[]{"pt", "car", "pt", "pt", "pt"}, model, ModeAvailability.YES); assertThat(estimate) - .isLessThanOrEqualTo(maxSum) - .isGreaterThanOrEqualTo(minSum) - .isCloseTo(-2738.72, Offset.offset(0.1)); + .isLessThanOrEqualTo(maxSum) + .isGreaterThanOrEqualTo(minSum) + .isCloseTo(-2738.72, Offset.offset(0.1)); estimate = estimator.estimate(context, TransportMode.pt, new String[]{"pt", "car", "car", "car", "pt"}, model, ModeAvailability.YES); assertThat(estimate) - .isLessThanOrEqualTo(maxSum) - .isGreaterThanOrEqualTo(minSum) - .isCloseTo(-1222.91, Offset.offset(0.1)); + .isLessThanOrEqualTo(maxSum) + .isGreaterThanOrEqualTo(minSum) + .isCloseTo(-1222.91, Offset.offset(0.1)); // Essentially single trip estimate = estimator.estimate(context, TransportMode.pt, new String[]{"pt", "car", "car", "car", "car"}, model, ModeAvailability.YES); assertThat(estimate) - .isCloseTo(singleTrips.get(0).getMin(), Offset.offset(0.1)); + .isCloseTo(singleTrips.get(0).getMin(), Offset.offset(0.1)); } } diff --git a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/scoring/RideScoringParamsFromCarParamsTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/scoring/RideScoringParamsFromCarParamsTest.java new file mode 100644 index 00000000000..2703f23443a --- /dev/null +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/scoring/RideScoringParamsFromCarParamsTest.java @@ -0,0 +1,34 @@ +package org.matsim.contrib.vsp.scoring; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.ScoringConfigGroup; + +public class RideScoringParamsFromCarParamsTest { + + @Test + void testSetRideScoringParamsBasedOnCarParams() { + Config config = ConfigUtils.createConfig(); + ScoringConfigGroup scoringConfigGroup = config.scoring(); + + scoringConfigGroup.setPerforming_utils_hr(6.0); + ScoringConfigGroup.ModeParams carParams = scoringConfigGroup.getOrCreateModeParams(TransportMode.car); + carParams.setDailyMonetaryConstant(-10.0); + carParams.setMarginalUtilityOfDistance(-2.0); + carParams.setMarginalUtilityOfTraveling(-1.0); + carParams.setMonetaryDistanceRate(-0.3); + + double alpha = 2.0; + + RideScoringParamsFromCarParams.setRideScoringParamsBasedOnCarParams(scoringConfigGroup, alpha); + + ScoringConfigGroup.ModeParams rideParams = scoringConfigGroup.getOrCreateModeParams(TransportMode.ride); + Assertions.assertEquals(0.0, rideParams.getDailyMonetaryConstant()); + Assertions.assertEquals(-0.6, rideParams.getMonetaryDistanceRate()); + Assertions.assertEquals(-6.0, rideParams.getMarginalUtilityOfDistance()); + Assertions.assertEquals(alpha * -6.0 + (alpha + 1) * -1.0, rideParams.getMarginalUtilityOfTraveling()); + } +} diff --git a/contribs/vsp/src/test/java/org/matsim/integration/drtAndPt/PtAlongALine2Test.java b/contribs/vsp/src/test/java/org/matsim/integration/drtAndPt/PtAlongALine2Test.java index d298b4ad003..f90f6112f3a 100644 --- a/contribs/vsp/src/test/java/org/matsim/integration/drtAndPt/PtAlongALine2Test.java +++ b/contribs/vsp/src/test/java/org/matsim/integration/drtAndPt/PtAlongALine2Test.java @@ -111,7 +111,7 @@ void testPtAlongALineWithRaptorAndDrtServiceArea() { // === ROUTER: === config.routing().setAccessEgressType(AccessEgressType.accessEgressModeToLink); - + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.modeVehicleTypesFromVehiclesData); // (as of today, will also influence router. kai, jun'19) diff --git a/contribs/vsp/src/test/java/playground/vsp/TestScenario.java b/contribs/vsp/src/test/java/playground/vsp/TestScenario.java index 24fde8c688a..973c9362786 100644 --- a/contribs/vsp/src/test/java/playground/vsp/TestScenario.java +++ b/contribs/vsp/src/test/java/playground/vsp/TestScenario.java @@ -14,7 +14,7 @@ import org.matsim.modechoice.estimators.DefaultLegScoreEstimator; import org.matsim.modechoice.estimators.FixedCostsEstimator; import org.matsim.testcases.MatsimTestUtils; -import playground.vsp.pt.fare.PtTripWithDistanceBasedFareEstimator; +import org.matsim.contrib.vsp.pt.fare.PtTripWithDistanceBasedFareEstimator; import javax.annotation.Nullable; import java.net.URL; diff --git a/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceAndCountsCadytsIT.java b/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceAndCountsCadytsIT.java index 0173d5e8552..dbdb804cb9b 100644 --- a/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceAndCountsCadytsIT.java +++ b/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceAndCountsCadytsIT.java @@ -68,6 +68,7 @@ private Config createConfig() { Config config = ConfigUtils.createConfig(); String[] modes = new String[]{TransportMode.car, TransportMode.bike}; + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setOutputDirectory(this.utils.getOutputDirectory()); config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setLastIteration(40); diff --git a/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceCadytsMultipleDistancesIT.java b/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceCadytsMultipleDistancesIT.java index 796380440ad..add356bc92e 100644 --- a/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceCadytsMultipleDistancesIT.java +++ b/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceCadytsMultipleDistancesIT.java @@ -14,11 +14,8 @@ import org.matsim.contrib.cadyts.general.CadytsScoring; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; -import org.matsim.core.config.groups.ChangeModeConfigGroup; -import org.matsim.core.config.groups.ReplanningConfigGroup; -import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.config.groups.*; import org.matsim.core.config.groups.RoutingConfigGroup.AccessEgressType; -import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; import org.matsim.core.controler.OutputDirectoryHierarchy; @@ -134,6 +131,8 @@ public ScoringFunction createNewScoringFunction(Person person) { private Config createConfig() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + String[] modes = new String[]{TransportMode.car, TransportMode.bike}; config.controller().setOutputDirectory(this.utils.getOutputDirectory()); diff --git a/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceCadytsSingleDistanceIT.java b/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceCadytsSingleDistanceIT.java index 2a7f0fdc897..133a4a48d83 100644 --- a/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceCadytsSingleDistanceIT.java +++ b/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceCadytsSingleDistanceIT.java @@ -139,7 +139,7 @@ private Config createConfig() { Config config = ConfigUtils.createConfig(); String[] modes = new String[]{TransportMode.car, TransportMode.bike}; - + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setOutputDirectory(this.utils.getOutputDirectory()); config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setLastIteration(20); diff --git a/contribs/vsp/src/test/java/playground/vsp/congestion/CombinedFlowAndStorageDelayTest.java b/contribs/vsp/src/test/java/playground/vsp/congestion/CombinedFlowAndStorageDelayTest.java index 755df67d97d..b8b5dfa08b2 100644 --- a/contribs/vsp/src/test/java/playground/vsp/congestion/CombinedFlowAndStorageDelayTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/congestion/CombinedFlowAndStorageDelayTest.java @@ -40,6 +40,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -163,6 +164,7 @@ private class createPseudoInputs { public createPseudoInputs(){ config=ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); this.scenario = ScenarioUtils.loadScenario(config); network = (Network) this.scenario.getNetwork(); population = this.scenario.getPopulation(); diff --git a/contribs/vsp/src/test/java/playground/vsp/congestion/CorridorNetworkTest.java b/contribs/vsp/src/test/java/playground/vsp/congestion/CorridorNetworkTest.java index ae8f04f18a4..be42f9e8a5a 100644 --- a/contribs/vsp/src/test/java/playground/vsp/congestion/CorridorNetworkTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/congestion/CorridorNetworkTest.java @@ -42,6 +42,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.events.handler.BasicEventHandler; @@ -68,7 +69,7 @@ public class CorridorNetworkTest { void v3Test(){ CorridorNetworkAndPlans inputs = new CorridorNetworkAndPlans(); Scenario sc = inputs.getDesiredScenario(); - + List v3_events = getCongestionEvents("v3", sc); Assertions.assertEquals(6, v3_events.size(), MatsimTestUtils.EPSILON, "wrong number of congestion events"); @@ -83,27 +84,27 @@ void v3Test(){ } else if ( event.getAffectedAgentId().equals(Id.createPersonId(3)) ) { // agent 3 is delayed on link 2 due to agent 2, 1 if(event.getCausingAgentId().equals(Id.createPersonId(2))) { - + Assertions.assertEquals(4, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - + } else { - + Assertions.assertEquals(2, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - + } - } else if(event.getAffectedAgentId().equals(Id.createPersonId(4))){ // agent 4 is first delayed due to spill back on link 1 (3 sec) and then on link 2 (6sec) + } else if(event.getAffectedAgentId().equals(Id.createPersonId(4))){ // agent 4 is first delayed due to spill back on link 1 (3 sec) and then on link 2 (6sec) if(event.getCausingAgentId().equals(Id.createPersonId(3))){ - + Assertions.assertEquals(4, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - + } else if (event.getCausingAgentId().equals(Id.createPersonId(2))){ - + Assertions.assertEquals(4, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - + } else { - + Assertions.assertEquals("1", event.getCausingAgentId().toString(), "wrong causing agent"); Assertions.assertEquals(1, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); } @@ -130,35 +131,35 @@ void v4Test(){ } else if ( event.getAffectedAgentId().equals(Id.createPersonId(3)) ) { // agent 3 is delayed on link 2 due to agent 2, 1 if(event.getCausingAgentId().equals(Id.createPersonId(2))) { - + Assertions.assertEquals(4, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - + } else { - + Assertions.assertEquals(2, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - + } - } else if(event.getAffectedAgentId().equals(Id.createPersonId(4))){ // agent 4 is first delayed due to spill back on link 1 (3 sec) and then on link 2 (6sec) + } else if(event.getAffectedAgentId().equals(Id.createPersonId(4))){ // agent 4 is first delayed due to spill back on link 1 (3 sec) and then on link 2 (6sec) if(event.getCausingAgentId().equals(Id.createPersonId(3)) ){ if ( event.getTime() == 10.0 ) { - + Assertions.assertEquals(3, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - + } else { - + Assertions.assertEquals(18.0, event.getTime(), MatsimTestUtils.EPSILON, "wrong congestion event time"); Assertions.assertEquals(4, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - + } - + } else { - + Assertions.assertEquals("2", event.getCausingAgentId().toString(), "wrong causing agent"); Assertions.assertEquals(2, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - - } + + } } } } @@ -173,7 +174,7 @@ private List getCongestionEvents (String congestionPricingImpl, events.addHandler( new CongestionEventHandler() { @Override - public void reset(int iteration) { + public void reset(int iteration) { } @Override @@ -188,7 +189,7 @@ public void handleEvent(CongestionEvent event) { LogManager.getLogger( CorridorNetworkTest.class ).warn( event ); } }); - + if(congestionPricingImpl.equalsIgnoreCase("v3")) { events.addHandler(new CongestionHandlerImplV3(events, (MutableScenario)sc)); } @@ -204,10 +205,10 @@ public void handleEvent(CongestionEvent event) { private class CorridorNetworkAndPlans { /** - * generates network with 3 links. - *

+ * generates network with 3 links. + *

*

o--0---o---1---o---2---o---3---o - *

+ *

*/ Scenario scenario; Config config; @@ -221,6 +222,7 @@ private class CorridorNetworkAndPlans { CorridorNetworkAndPlans(){ config=ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); this.scenario = ScenarioUtils.loadScenario(config); network = (Network) this.scenario.getNetwork(); population = this.scenario.getPopulation(); diff --git a/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerFlowQueueQsimTest.java b/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerFlowQueueQsimTest.java index 94c1f09f388..576d33e53ed 100644 --- a/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerFlowQueueQsimTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerFlowQueueQsimTest.java @@ -45,6 +45,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSim; @@ -301,6 +302,7 @@ private Scenario loadScenario1() { // -----link1---- ----link2---- ----link3---- ----link4---- ----link5---- Config config = testUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); QSimConfigGroup qSimConfigGroup = config.qsim(); qSimConfigGroup.setFlowCapFactor(1.0); qSimConfigGroup.setStorageCapFactor(1.0); diff --git a/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerFlowSpillbackQueueQsimTest.java b/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerFlowSpillbackQueueQsimTest.java index 1d0f93eb272..a3952fcf727 100644 --- a/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerFlowSpillbackQueueQsimTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerFlowSpillbackQueueQsimTest.java @@ -136,6 +136,7 @@ public class MarginalCongestionHandlerFlowSpillbackQueueQsimTest { final void testFlowAndStorageCongestion_3agents(){ Scenario sc = loadScenario1(); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); setPopulation1(sc); final List congestionEvents = new ArrayList(); @@ -181,6 +182,7 @@ public void handleEvent(CongestionEvent event) { final void testFlowAndStorageCongestion_3agents_V9() { Scenario sc = loadScenario1(); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); setPopulation1(sc); final List congestionEvents = new ArrayList(); @@ -222,6 +224,7 @@ public void handleEvent(CongestionEvent event) { final void testFlowAndStorageCongestion_3agents_V8() { Scenario sc = loadScenario1(); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); setPopulation1(sc); final List congestionEvents = new ArrayList(); @@ -264,6 +267,7 @@ public void handleEvent(CongestionEvent event) { final void testFlowAndStorageCongestion_3agents_V10() { Scenario sc = loadScenario1(); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); setPopulation1(sc); final List congestionEvents = new ArrayList(); @@ -318,6 +322,7 @@ final void testRouting(){ Config config = ConfigUtils.loadConfig( configFile ) ; config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.none); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); final Scenario scenario = ScenarioUtils.loadScenario( config ); Controler controler = new Controler( scenario ); @@ -454,6 +459,7 @@ else if(((event.getServices().getConfig().controller().getLastIteration())-(even final void testInsertingWaitingVehicles_01(){ Scenario sc = loadScenario4(); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); setPopulation4(sc); final List congestionEvents = new ArrayList(); @@ -513,6 +519,7 @@ public void handleEvent(LinkLeaveEvent event) { final void testInsertingWaitingVehicles_02(){ Scenario sc = loadScenario5(); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); setPopulation5(sc); final List congestionEvents = new ArrayList(); @@ -574,6 +581,7 @@ public void handleEvent(LinkLeaveEvent event) { final void testInsertingWaitingVehicles_03(){ Scenario sc = loadScenario4(); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); setPopulation6(sc); final List congestionEvents = new ArrayList(); diff --git a/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerV3Test.java b/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerV3Test.java index 1f70380e3de..a9ca7a13c8e 100644 --- a/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerV3Test.java +++ b/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerV3Test.java @@ -70,7 +70,7 @@ final void testCongestionExample(){ Config config = ConfigUtils.loadConfig( configFile ) ; config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.none); - + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); final Controler controler = new Controler(config); controler.addOverridingModule(new AbstractModule() { @Override diff --git a/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionPricingTest.java b/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionPricingTest.java index a398d462e77..4ef9873280a 100644 --- a/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionPricingTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionPricingTest.java @@ -42,6 +42,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -81,6 +82,7 @@ final void implV4Test(){ sc.getVehicles().addVehicleType(car); sc.getConfig().qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.modeVehicleTypesFromVehiclesData); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); EventsManager events = EventsUtils.createEventsManager(); diff --git a/contribs/vsp/src/test/java/playground/vsp/congestion/TestForEmergenceTime.java b/contribs/vsp/src/test/java/playground/vsp/congestion/TestForEmergenceTime.java index 9cdfa5b37b1..835ef5a9c9a 100644 --- a/contribs/vsp/src/test/java/playground/vsp/congestion/TestForEmergenceTime.java +++ b/contribs/vsp/src/test/java/playground/vsp/congestion/TestForEmergenceTime.java @@ -40,6 +40,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -109,6 +110,7 @@ private List getAffectedPersonId2Delays(String congestionPricin sc.getVehicles().addVehicleType(car); sc.getConfig().qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.modeVehicleTypesFromVehiclesData); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); EventsManager events = EventsUtils.createEventsManager(); diff --git a/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.cpg b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.cpg new file mode 100644 index 00000000000..3ad133c048f --- /dev/null +++ b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.cpg @@ -0,0 +1 @@ +UTF-8 \ No newline at end of file diff --git a/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.dbf b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.dbf new file mode 100644 index 00000000000..3193e4ca986 Binary files /dev/null and b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.dbf differ diff --git a/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.prj b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.prj new file mode 100644 index 00000000000..bd846aeb220 --- /dev/null +++ b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.prj @@ -0,0 +1 @@ +PROJCS["ETRS_1989_UTM_Zone_32N",GEOGCS["GCS_ETRS_1989",DATUM["D_ETRS_1989",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",9.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.shp b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.shp new file mode 100644 index 00000000000..1fded033e5a Binary files /dev/null and b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.shp differ diff --git a/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.shx b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.shx new file mode 100644 index 00000000000..233d288c485 Binary files /dev/null and b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.shx differ diff --git a/examples/scenarios/kelheim/ptTestArea/pt-area.cpg b/examples/scenarios/kelheim/ptTestArea/pt-area.cpg new file mode 100644 index 00000000000..3ad133c048f --- /dev/null +++ b/examples/scenarios/kelheim/ptTestArea/pt-area.cpg @@ -0,0 +1 @@ +UTF-8 \ No newline at end of file diff --git a/examples/scenarios/kelheim/ptTestArea/pt-area.dbf b/examples/scenarios/kelheim/ptTestArea/pt-area.dbf new file mode 100644 index 00000000000..e17541dab99 Binary files /dev/null and b/examples/scenarios/kelheim/ptTestArea/pt-area.dbf differ diff --git a/examples/scenarios/kelheim/ptTestArea/pt-area.prj b/examples/scenarios/kelheim/ptTestArea/pt-area.prj new file mode 100644 index 00000000000..bd846aeb220 --- /dev/null +++ b/examples/scenarios/kelheim/ptTestArea/pt-area.prj @@ -0,0 +1 @@ +PROJCS["ETRS_1989_UTM_Zone_32N",GEOGCS["GCS_ETRS_1989",DATUM["D_ETRS_1989",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",9.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/examples/scenarios/kelheim/ptTestArea/pt-area.shp b/examples/scenarios/kelheim/ptTestArea/pt-area.shp new file mode 100644 index 00000000000..a798ec1b8bf Binary files /dev/null and b/examples/scenarios/kelheim/ptTestArea/pt-area.shp differ diff --git a/examples/scenarios/kelheim/ptTestArea/pt-area.shx b/examples/scenarios/kelheim/ptTestArea/pt-area.shx new file mode 100644 index 00000000000..534dab6a968 Binary files /dev/null and b/examples/scenarios/kelheim/ptTestArea/pt-area.shx differ diff --git a/matsim/pom.xml b/matsim/pom.xml index 17556c8ac08..7f768fffe76 100644 --- a/matsim/pom.xml +++ b/matsim/pom.xml @@ -118,7 +118,7 @@ org.apache.maven.plugins maven-surefire-report-plugin - 3.3.0 + 3.3.1 @@ -127,7 +127,7 @@ it.unimi.dsi fastutil-core - 8.5.13 + 8.5.14 org.geotools diff --git a/matsim/src/main/java/org/matsim/core/config/groups/RoutingConfigGroup.java b/matsim/src/main/java/org/matsim/core/config/groups/RoutingConfigGroup.java index a693d0c0297..c38fba94eec 100644 --- a/matsim/src/main/java/org/matsim/core/config/groups/RoutingConfigGroup.java +++ b/matsim/src/main/java/org/matsim/core/config/groups/RoutingConfigGroup.java @@ -104,6 +104,13 @@ public enum AccessEgressType { "settings for helper modes such as for " + TransportMode.non_network_walk; private boolean clearingDefaultModeRoutingParams = false ; + private static final String NETWORK_ROUTE_CONSISTENCY_CHECK = "networkRouteConsistencyCheck"; + private NetworkRouteConsistencyCheck networkRouteConsistencyCheck = NetworkRouteConsistencyCheck.abortOnInconsistency; + + public enum NetworkRouteConsistencyCheck { + disable, abortOnInconsistency + } + /** * @deprecated -- use {@link TeleportedModeParams} to be consistent with xml config. kai, jun'23 */ @@ -519,6 +526,8 @@ public void addParam(final String key, final String value) { } else if (ACCESSEGRESSTYPE.equals( key ) ) { this.setAccessEgressType(AccessEgressType.valueOf(value)); + } else if (NETWORK_ROUTE_CONSISTENCY_CHECK.equals(key)){ + this.setNetworkRouteConsistencyCheck(NetworkRouteConsistencyCheck.valueOf(value)); } else { throw new IllegalArgumentException(key); @@ -532,6 +541,7 @@ public final Map getParams() { map.put( CLEAR_MODE_ROUTING_PARAMS, Boolean.toString( this.clearingDefaultModeRoutingParams ) ) ; map.put( RANDOMNESS, Double.toString( this.routingRandomness ) ) ; map.put( ACCESSEGRESSTYPE, getAccessEgressType().toString()) ; + map.put(NETWORK_ROUTE_CONSISTENCY_CHECK, NetworkRouteConsistencyCheck.abortOnInconsistency.toString()); return map; } @@ -547,6 +557,7 @@ public final Map getComments() { + "Technically the width parameter of a log-normal distribution. 3.0 seems to be a good value. " ) ; map.put( CLEAR_MODE_ROUTING_PARAMS, CLEAR_MODE_ROUTING_PARAMS_CMT ) ; map.put(ACCESSEGRESSTYPE, ACCESSEGRESSTYPE_CMT); + map.put(NETWORK_ROUTE_CONSISTENCY_CHECK, "Defines whether the network consistency should be checked."); return map; } @@ -650,6 +661,16 @@ public void setRoutingRandomness(double routingRandomness) { this.routingRandomness = routingRandomness; } + @StringGetter(NETWORK_ROUTE_CONSISTENCY_CHECK) + public NetworkRouteConsistencyCheck getNetworkRouteConsistencyCheck() { + return networkRouteConsistencyCheck; + } + + @StringSetter(NETWORK_ROUTE_CONSISTENCY_CHECK) + public void setNetworkRouteConsistencyCheck(NetworkRouteConsistencyCheck networkRouteConsistencyCheck) { + this.networkRouteConsistencyCheck = networkRouteConsistencyCheck; + } + @Override protected void checkConsistency(Config config) { super.checkConsistency(config); Set modesRoutedAsTeleportation = this.getModeRoutingParams().keySet(); diff --git a/matsim/src/main/java/org/matsim/core/controler/ControlerDefaultsModule.java b/matsim/src/main/java/org/matsim/core/controler/ControlerDefaultsModule.java index fc5c43da358..293ac9ed415 100755 --- a/matsim/src/main/java/org/matsim/core/controler/ControlerDefaultsModule.java +++ b/matsim/src/main/java/org/matsim/core/controler/ControlerDefaultsModule.java @@ -85,8 +85,7 @@ public void install() { // Maybe not the best place to but this but since ChartUtils is used by many modules, including default ones, // the cache needs to be always set correctly. addControlerListenerBinding().toInstance(new StartupListener() { - @Inject - private OutputDirectoryHierarchy outputDirectoryHierarchy; + @Inject private OutputDirectoryHierarchy outputDirectoryHierarchy; @Override public void notifyStartup(StartupEvent event) { ImageIO.setCacheDirectory(new File(outputDirectoryHierarchy.getTempPath())); } diff --git a/matsim/src/main/java/org/matsim/core/controler/PrepareForSimImpl.java b/matsim/src/main/java/org/matsim/core/controler/PrepareForSimImpl.java index 359a812887a..fc9be952cc3 100644 --- a/matsim/src/main/java/org/matsim/core/controler/PrepareForSimImpl.java +++ b/matsim/src/main/java/org/matsim/core/controler/PrepareForSimImpl.java @@ -34,11 +34,8 @@ import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.Population; -import org.matsim.core.config.groups.FacilitiesConfigGroup; -import org.matsim.core.config.groups.GlobalConfigGroup; -import org.matsim.core.config.groups.PlansConfigGroup; +import org.matsim.core.config.groups.*; import org.matsim.core.config.groups.PlansConfigGroup.HandlingOfPlansWithoutRoutingMode; -import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.gbl.Gbl; import org.matsim.core.network.NetworkUtils; import org.matsim.core.network.algorithms.TransportModeNetworkFilter; @@ -331,6 +328,11 @@ private void createAndAddVehicleIfNecessary(Id vehicleId, VehicleType v private static boolean insistingOnPlansWithoutRoutingModeLogWarnNotShownYet = true; + /** + * Make sure that each leg has a routing mode. + * Legs with outdated fallback modes will be treated in a special way. + * Legs with no routing mode will have their network mode as routing mode. + */ private void adaptOutdatedPlansForRoutingMode() { for (Person person : population.getPersons().values()) { for (Plan plan : person.getPlans()) { @@ -369,8 +371,7 @@ private void adaptOutdatedPlansForRoutingMode() { // there is only a single leg (e.g. after Trips2Legs and a mode choice replanning // module) - String oldMainMode = replaceOutdatedFallbackModesAndReturnOldMainMode(legs.get(0), - null); + String oldMainMode = replaceOutdatedFallbackModesAndReturnOldMainMode(legs.get(0), null); if (oldMainMode != null) { routingMode = oldMainMode; TripStructureUtils.setRoutingMode(legs.get(0), routingMode); diff --git a/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/AbstractAgentSnapshotInfoBuilder.java b/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/AbstractAgentSnapshotInfoBuilder.java index 78d2b0afe5d..c6bf2e47d49 100644 --- a/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/AbstractAgentSnapshotInfoBuilder.java +++ b/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/AbstractAgentSnapshotInfoBuilder.java @@ -139,12 +139,13 @@ public final void positionAgentGivenDistanceFromFNode(final Collection positionVehiclesAlongLine(Collection positions, - double now, Collection vehs, double curvedLength, double storageCapacity, - Coord upstreamCoord, Coord downstreamCoord, double inverseFlowCapPerTS, double freeSpeed, - int numberOfLanesAsInt, Queue holes) + public final Collection positionVehiclesAlongLine( Collection positions, + double now, Collection vehs, double curvedLength, double storageCapacity, + Coord upstreamCoord, Coord downstreamCoord, double inverseFlowCapPerTS, double freeSpeed, + int numberOfLanesAsInt, Queue holes, AbstractQLink.QLinkInternalInterface qLinkInternalInterface ) { double spacingOfOnePCE = this.calculateVehicleSpacing( curvedLength, storageCapacity, vehs ); + // ("vehs" is needed since the link may be more than full because of squeezing. In this case, spacingOfOnePCE is smaller than one "cell".) double ttimeOfHoles = curvedLength / (QueueWithBuffer.HOLE_SPEED_KM_H*1000./3600.); @@ -211,8 +212,16 @@ public final Collection positionVehiclesAlongLine(Collection< // (starts off relatively small (rightmost vehicle)) final double vehicleSpacing = mveh.getSizeInEquivalents() * spacingOfOnePCE; + + double speed = min( freeSpeed, veh.getMaximumVelocity() ); + if ( qLinkInternalInterface!=null ){ + speed = qLinkInternalInterface.getMaximumVelocityFromLinkSpeedCalculator( veh, now ); + } + distanceFromFromNode = this.calculateOdometerDistanceFromFromNode( - now, curvedLength, min( freeSpeed, veh.getMaximumVelocity()), vehicleSpacing, distanceFromFromNode, remainingTravelTime + now, curvedLength, + speed, // min( freeSpeed, veh.getMaximumVelocity()), + vehicleSpacing, distanceFromFromNode, remainingTravelTime ); // yyyy if the LinkSpeedCalculator says something that is not free speed, we are out of luck here. kai, jan'23 diff --git a/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueWithBuffer.java b/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueWithBuffer.java index 868e9813c65..741763e4c87 100644 --- a/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueWithBuffer.java +++ b/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueWithBuffer.java @@ -162,7 +162,7 @@ private void addValue(double value1, double now) { * pointer, and give access only to reduced number of methods (in particular not the full Link information). kai, feb'18 * This is now done with the {@link AbstractQLink.QLinkInternalInterface}. kai, feb'18 */ - private final AbstractQLink.QLinkInternalInterface qLink; + private final AbstractQLink.QLinkInternalInterface qLinkInternalInterface; private final Id id; private static int spaceCapWarningCount = 0; final static double HOLE_SPEED_KM_H = 15.0; @@ -202,7 +202,7 @@ private QueueWithBuffer(AbstractQLink.QLinkInternalInterface qlink, final Vehicl // log.setLevel(Level.DEBUG); this.flowEfficiencyCalculator = flowEfficiencyCalculator; - this.qLink = qlink; + this.qLinkInternalInterface = qlink; this.id = laneId ; this.context = context ; this.vehQueue = vehicleQueue ; @@ -239,7 +239,7 @@ private void addToBuffer(final QVehicle veh) { // need to reset the lastMovedTime. If, in contrast, there was already a vehicle in the buffer before, we can // use the lastMovedTime that was (somehow) computed for that vehicle.) } - final QNodeI toNode = qLink.getToNodeQ(); + final QNodeI toNode = qLinkInternalInterface.getToNodeQ(); if ( toNode instanceof AbstractQNode ) { ((AbstractQNode) toNode).activateNode(); // yy for an "upstream" QLane, this activates the toNode too early. Yet I think I founds this @@ -266,9 +266,9 @@ private void moveQueueToBuffer() { MobsimDriverAgent driver = veh.getDriver(); if (driver instanceof TransitDriverAgent) { - HandleTransitStopResult handleTransitStop = qLink.handleTransitStop( - now, veh, (TransitDriverAgent) driver, this.qLink.getId() - ); + HandleTransitStopResult handleTransitStop = qLinkInternalInterface.handleTransitStop( + now, veh, (TransitDriverAgent) driver, this.qLinkInternalInterface.getId() + ); if (handleTransitStop == HandleTransitStopResult.accepted) { // vehicle has been accepted into the transit vehicle queue of the link. removeVehicleFromQueue(veh); @@ -285,7 +285,7 @@ private void moveQueueToBuffer() { // Check if veh has reached destination: if (driver.isWantingToArriveOnCurrentLink()) { - if (qLink.letVehicleArrive(veh)) { + if ( qLinkInternalInterface.letVehicleArrive(veh )) { // remove _after_ processing the arrival to keep link active: removeVehicleFromQueue(veh); continue; @@ -395,8 +395,8 @@ private void calculateFlowCapacity() { // yyyyyy this should possibly be getFreespeed(now). But if that's the case, then maxFlowFromFdiag would // also have to be re-computed with each freespeed change. kai, feb'18 - final double maxFlowFromFdiag = (this.effectiveNumberOfLanes/context.effectiveCellSize) / ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLink.getFreespeed() ) ; - final double minimumNumberOfLanesFromFdiag = this.flowCapacityPerTimeStep * context.effectiveCellSize * ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLink.getFreespeed() ); + final double maxFlowFromFdiag = (this.effectiveNumberOfLanes/context.effectiveCellSize) / ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLinkInternalInterface.getFreespeed() ) ; + final double minimumNumberOfLanesFromFdiag = this.flowCapacityPerTimeStep * context.effectiveCellSize * ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLinkInternalInterface.getFreespeed() ); QSimConfigGroup.InflowCapacitySetting inflowCapacitySetting = context.qsimConfig.getInflowCapacitySetting(); @@ -411,19 +411,19 @@ private void calculateFlowCapacity() { log.warn( Gbl.FUTURE_SUPPRESSED ) ; } - this.maxInflowUsedInQsim = (1/context.effectiveCellSize) / ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLink.getFreespeed() ) ; + this.maxInflowUsedInQsim = (1/context.effectiveCellSize) / ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLinkInternalInterface.getFreespeed() ) ; // write out the modified qsim behavior as link attribute - qLink.getLink().getAttributes().putAttribute("maxInflowUsedInQsim", 3600* maxInflowUsedInQsim /context.qsimConfig.getTimeStepSize()); + qLinkInternalInterface.getLink().getAttributes().putAttribute("maxInflowUsedInQsim", 3600* maxInflowUsedInQsim /context.qsimConfig.getTimeStepSize() ); } else { if ( maxFlowFromFdiag < flowCapacityPerTimeStep ){ //warnings if (wrnCnt<10) { wrnCnt++ ; - log.warn( "max flow from fdiag < flow cap in network file; linkId=" + qLink.getId() + + log.warn( "max flow from fdiag < flow cap in network file; linkId=" + qLinkInternalInterface.getId() + "; network file flow cap/h=" + 3600.*flowCapacityPerTimeStep/context.qsimConfig.getTimeStepSize() + "; max flow from fdiag/h=" + 3600*maxFlowFromFdiag/context.qsimConfig.getTimeStepSize() ) ; - log.warn( "number of lanes from fdiag > number of lanes in network file; linkId=" + qLink.getId() + + log.warn( "number of lanes from fdiag > number of lanes in network file; linkId=" + qLinkInternalInterface.getId() + "; number of lanes in network file=" + this.effectiveNumberOfLanes + "; number of lanes from fdiag=" + minimumNumberOfLanesFromFdiag ) ; @@ -445,11 +445,11 @@ private void calculateFlowCapacity() { if (inflowCapacitySetting == QSimConfigGroup.InflowCapacitySetting.INFLOW_FROM_FDIAG) { this.maxInflowUsedInQsim = maxFlowFromFdiag; // write out the modified qsim behavior as link attribute - qLink.getLink().getAttributes().putAttribute("maxInflowUsedInQsim", 3600* maxInflowUsedInQsim /context.qsimConfig.getTimeStepSize()); + qLinkInternalInterface.getLink().getAttributes().putAttribute("maxInflowUsedInQsim", 3600* maxInflowUsedInQsim /context.qsimConfig.getTimeStepSize() ); } else if (inflowCapacitySetting == QSimConfigGroup.InflowCapacitySetting.NR_OF_LANES_FROM_FDIAG) { this.effectiveNumberOfLanesUsedInQsim = minimumNumberOfLanesFromFdiag; // write out the modified qsim behavior as link attribute - qLink.getLink().getAttributes().putAttribute("effectiveNumberOfLanesUsedInQsim", effectiveNumberOfLanesUsedInQsim); + qLinkInternalInterface.getLink().getAttributes().putAttribute("effectiveNumberOfLanesUsedInQsim", effectiveNumberOfLanesUsedInQsim ); } else { throw new RuntimeException("The approach "+ inflowCapacitySetting.toString()+" is not implemented yet."); } @@ -483,7 +483,7 @@ private void calculateStorageCapacity() { * Will base these computations (for the time being) on the standard free speed; i.e. reductions in free speed * will also reduce the maximum flow. */ - double freespeedTravelTime = this.length / qLink.getFreespeed(); + double freespeedTravelTime = this.length / qLinkInternalInterface.getFreespeed(); // yyyyyy this should possibly be getFreespeed(now). But if that's the case, then storageCap would // also have to be re-computed with each freespeed change. kai, feb'18 if (Double.isNaN(freespeedTravelTime)) { @@ -507,7 +507,7 @@ private void calculateStorageCapacity() { storageCapacity = tempStorageCapacity; // write out the modified qsim behavior as link attribute - qLink.getLink().getAttributes().putAttribute("storageCapacityUsedInQsim", storageCapacity); + qLinkInternalInterface.getLink().getAttributes().putAttribute("storageCapacityUsedInQsim", storageCapacity ); } /* About minStorCapForHoles: @@ -527,7 +527,7 @@ private void calculateStorageCapacity() { case withHoles: case kinematicWaves: // final double minStorCapForHoles = 2. * flowCapacityPerTimeStep * context.getSimTimer().getSimTimestepSize(); - final double freeSpeed = qLink.getFreespeed() ; // yyyyyy not clear why this is not time-dep. kai, feb'18 + final double freeSpeed = qLinkInternalInterface.getFreespeed() ; // yyyyyy not clear why this is not time-dep. kai, feb'18 final double holeSpeed = HOLE_SPEED_KM_H/3.6; final double minStorCapForHoles = length * flowCapacityPerTimeStep * (freeSpeed + holeSpeed) / freeSpeed / holeSpeed ; // final double minStorCapForHoles = 2.* length * flowCapacityPerTimeStep * (freeSpeed + holeSpeed) / freeSpeed / holeSpeed ; @@ -541,7 +541,7 @@ private void calculateStorageCapacity() { } storageCapacity = minStorCapForHoles ; // write out the modified qsim behavior as link attribute - qLink.getLink().getAttributes().putAttribute("storageCapacityUsedInQsim", storageCapacity); + qLinkInternalInterface.getLink().getAttributes().putAttribute("storageCapacityUsedInQsim", storageCapacity ); } remainingHolesStorageCapacity = this.storageCapacity; @@ -589,12 +589,12 @@ public final void addFromUpstream(final QVehicle veh) { if (this.context.qsimConfig.isUseLanes()) { if (hasMoreThanOneLane()) { - this.context.getEventsManager().processEvent(new LaneEnterEvent(now, veh.getId(), this.qLink.getId(), this.getId())); + this.context.getEventsManager().processEvent(new LaneEnterEvent(now, veh.getId(), this.qLinkInternalInterface.getId(), this.getId()) ); } } // activate link since there is now action on it: - qLink.activateLink(); + qLinkInternalInterface.activateLink(); if (context.qsimConfig.isSeepModeStorageFree() && context.qsimConfig.getSeepModes().contains(veh.getVehicle().getType().getId().toString())) { // do nothing @@ -604,7 +604,7 @@ public final void addFromUpstream(final QVehicle veh) { // compute and set earliest link exit time: // double linkTravelTime = this.length / this.linkSpeedCalculator.getMaximumVelocity(veh, qLink.getLink(), now); - double linkTravelTime = this.length / this.qLink.getMaximumVelocityFromLinkSpeedCalculator(veh, now); + double linkTravelTime = this.length / this.qLinkInternalInterface.getMaximumVelocityFromLinkSpeedCalculator(veh, now ); linkTravelTime = context.qsimConfig.getTimeStepSize() * Math.floor(linkTravelTime / context.qsimConfig.getTimeStepSize()); veh.setEarliestLinkExitTime(now + linkTravelTime); @@ -619,7 +619,7 @@ public final void addFromUpstream(final QVehicle veh) { // inserted and thus end up after vehicles with a later link exit time. theresa & kai, jun'14 // veh.setCurrentLink(qLink.getLink()); - this.qLink.setCurrentLinkToVehicle(veh); + this.qLinkInternalInterface.setCurrentLinkToVehicle(veh ); vehQueue.add(veh); switch (context.qsimConfig.getTrafficDynamics()) { @@ -795,7 +795,7 @@ public final QVehicle popFirstVehicle() { QVehicle veh = removeFirstVehicle(); if (this.context.qsimConfig.isUseLanes() ) { if ( hasMoreThanOneLane() ) { - this.context.getEventsManager().processEvent(new LaneLeaveEvent( now, veh.getId(), this.qLink.getId(), this.getId() )); + this.context.getEventsManager().processEvent(new LaneLeaveEvent( now, veh.getId(), this.qLinkInternalInterface.getId(), this.getId() ) ); } } return veh; @@ -813,7 +813,7 @@ private final QVehicle removeFirstVehicle(){ @Override public final void setSignalStateForTurningMove( final SignalGroupState state, final Id toLinkId) { - if (!qLink.getToNode().getOutLinks().containsKey(toLinkId)){ + if (!qLinkInternalInterface.getToNode().getOutLinks().containsKey(toLinkId )){ throw new IllegalArgumentException("ToLink " + toLinkId + " is not reachable from QLink Id " + this.id ); } qSignalizedItem.setSignalStateForTurningMove(state, toLinkId); @@ -879,12 +879,12 @@ public final void clearVehicles() { } private double getFlowCapacityConsumptionInEquivalents(QVehicle vehicle, QVehicle prevVehicle, Double timeDiff) { - double flowEfficiency = flowEfficiencyCalculator.calculateFlowEfficiency(vehicle, prevVehicle, timeDiff, qLink.getLink(), id); + double flowEfficiency = flowEfficiencyCalculator.calculateFlowEfficiency(vehicle, prevVehicle, timeDiff, qLinkInternalInterface.getLink(), id ); return vehicle.getSizeInEquivalents() / flowEfficiency; } private boolean hasMoreThanOneLane() { - return this.qLink.getAcceptingQLane() != this.qLink.getOfferingQLanes().get(0); + return this.qLinkInternalInterface.getAcceptingQLane() != this.qLinkInternalInterface.getOfferingQLanes().get(0 ); // this works independent from sorting since if there is only one lane, then it has to be the one to be returned by // getOfferingQLanes().get(0), and it is also the same as the accepting QLane. If, however, "lanes" is used, // there are at least two lanes in sequence, so the accepting lane is never the same as any of the offering lanes, and @@ -919,7 +919,7 @@ public final void addTransitSlightlyUpstreamOfStop( final QVehicle veh) { @Override public final void setSignalized( final boolean isSignalized) { - qSignalizedItem = new DefaultSignalizeableItem(qLink.getToNode().getOutLinks().keySet()); + qSignalizedItem = new DefaultSignalizeableItem( qLinkInternalInterface.getToNode().getOutLinks().keySet()); } @Override @@ -989,10 +989,10 @@ public final Collection addAgentSnapshotInfo(Collection addAgentSnapshotInfo(Collection modes = new HashSet<>(link.getAllowedModes()); + modes.add(mode); + link.setAllowedModes(modes); + } + + public static void removeAllowedMode(Link link, String mode) { + Set modes = new HashSet<>(link.getAllowedModes()); + modes.remove(mode); + link.setAllowedModes(modes); + } + + /** + * Removes the given modes from the links and runs the network cleaner afterwards. Thus, some more links may be restricted to keep the network consistent. + * That means, each link can be reached from each other link. + * @param network the network + * @param modesToRemoveByLinkId map of modes that should be removed from the links + */ + public static void restrictModesAndCleanNetwork(Network network, Function, Set> modesToRemoveByLinkId) { + new NetworkModeRestriction(modesToRemoveByLinkId).run(network); + } } diff --git a/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkCleaner.java b/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkCleaner.java index 89965f05f2e..9df6cd6d896 100644 --- a/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkCleaner.java +++ b/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkCleaner.java @@ -75,7 +75,7 @@ private Map, Node> findCluster(final Node startNode, final Network netw pendingBackward.add(startNode); // step through the network in forward mode - while (pendingForward.size() > 0) { + while (!pendingForward.isEmpty()) { int idx = pendingForward.size() - 1; Node currNode = pendingForward.remove(idx); // get the last element to prevent object shifting in the array for (Link link : currNode.getOutLinks().values()) { @@ -89,7 +89,7 @@ private Map, Node> findCluster(final Node startNode, final Network netw } // now step through the network in backward mode - while (pendingBackward.size() > 0) { + while (!pendingBackward.isEmpty()) { int idx = pendingBackward.size()-1; Node currNode = pendingBackward.remove(idx); // get the last element to prevent object shifting in the array for (Link link : currNode.getInLinks().values()) { @@ -112,7 +112,7 @@ private Map, Node> findCluster(final Node startNode, final Network netw /** * Searches the biggest cluster in the given Network. The Network is not modified. */ - public Map, Node> searchBiggestCluster(Network network) { + private Map, Node> searchBiggestCluster(Network network) { final Map, Node> visitedNodes = new TreeMap<>(); Map, Node> biggestCluster = new TreeMap<>(); @@ -142,11 +142,11 @@ public Map, Node> searchBiggestCluster(Network network) { return biggestCluster; } - /** + /** * Reducing the network so it only contains nodes included in the biggest Cluster. * Loop over all nodes and check if they are in the cluster, if not, remove them from the network */ - public static void reduceToBiggestCluster(Network network, Map, Node> biggestCluster) { + private static void reduceToBiggestCluster(Network network, Map, Node> biggestCluster) { List allNodes2 = new ArrayList<>(network.getNodes().values()); for (Node node : allNodes2) { if (!biggestCluster.containsKey(node.getId())) { @@ -157,7 +157,7 @@ public static void reduceToBiggestCluster(Network network, Map, Node> b network.getLinks().size() + " links."); log.info("done."); } - + @Override public void run(final Network network) { Map, Node> biggestCluster = this.searchBiggestCluster(network); diff --git a/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeRestriction.java b/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeRestriction.java new file mode 100644 index 00000000000..c2457da636c --- /dev/null +++ b/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeRestriction.java @@ -0,0 +1,88 @@ +package org.matsim.core.network.algorithms; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.network.Node; +import org.matsim.core.api.internal.NetworkRunnable; +import org.matsim.core.network.NetworkUtils; + +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * This class changes the allowed modes of links in a network and cleans the network afterward. + * I.e. for each mode, it removes by running the {@link NetworkCleaner} that mode for links, that are not reachable from all other links + * or from which all other links are not reachable. + */ +public class NetworkModeRestriction implements NetworkRunnable { + private static final Logger log = LogManager.getLogger(NetworkModeRestriction.class); + + private final Function, Set> modesToRemoveByLinkId; + + public NetworkModeRestriction(Function, Set> modesToRemoveByLinkId) { + this.modesToRemoveByLinkId = modesToRemoveByLinkId; + } + + public NetworkModeRestriction(Map, Set> modesToRemoveByLinkId) { + this.modesToRemoveByLinkId = l -> modesToRemoveByLinkId.getOrDefault(l, Set.of()); + } + + @Override + public void run(Network network) { + Map modeCountBefore = countModes(network); + + applyModeChanges(network); + cleanNetworkPerMode(network); + removeLinksWithNoModes(network); + removeNodesWithNoLinks(network); + + Map modeCountAfter = countModes(network); + logModeCountDifference(modeCountBefore, modeCountAfter); + } + + private void applyModeChanges(Network network) { + for (Map.Entry, ? extends Link> link : network.getLinks().entrySet()) { + this.modesToRemoveByLinkId.apply(link.getKey()).forEach(m -> NetworkUtils.removeAllowedMode(link.getValue(), m)); + } + } + + private void cleanNetworkPerMode(Network network) { + Set modes = network.getLinks().values().stream().flatMap(l -> l.getAllowedModes().stream()).collect(Collectors.toSet()); + for (String mode : modes) { + MultimodalNetworkCleaner multimodalNetworkCleaner = new MultimodalNetworkCleaner(network); + multimodalNetworkCleaner.run(Set.of(mode)); + } + } + + private void removeLinksWithNoModes(Network network) { + network.getLinks().values().stream() + .filter(l -> l.getAllowedModes().isEmpty()) + .map(Link::getId) + .forEach(network::removeLink); + } + + private void removeNodesWithNoLinks(Network network) { + network.getNodes().values().stream() + .filter(n -> n.getInLinks().isEmpty() && n.getOutLinks().isEmpty()) + .map(Node::getId) + .forEach(network::removeNode); + } + + private void logModeCountDifference(Map modeCountBefore, Map modeCountAfter) { + modeCountBefore.forEach((mode, countBefore) -> { + long countAfter = modeCountAfter.getOrDefault(mode, 0L); + log.info("Removed mode {} from {} links.", mode, countBefore - countAfter); + }); + } + + private static Map countModes(Network network) { + return network.getLinks().values().stream() + .flatMap(l -> l.getAllowedModes().stream()) + .collect(Collectors.groupingBy(m -> m, Collectors.counting())); + } +} diff --git a/matsim/src/main/java/org/matsim/core/population/PopulationUtils.java b/matsim/src/main/java/org/matsim/core/population/PopulationUtils.java index 5755982b6ed..5b62242de72 100644 --- a/matsim/src/main/java/org/matsim/core/population/PopulationUtils.java +++ b/matsim/src/main/java/org/matsim/core/population/PopulationUtils.java @@ -57,6 +57,7 @@ import org.matsim.core.config.groups.PlansConfigGroup; import org.matsim.core.gbl.Gbl; import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.population.algorithms.PersonRouteCheck; import org.matsim.core.population.io.PopulationReader; import org.matsim.core.population.io.PopulationWriter; import org.matsim.core.population.io.StreamingPopulationReader; @@ -1295,4 +1296,16 @@ public static void insertVehicleIdsIntoPersonAttributes(Person person, Map modes = new HashSet(); - modes.add(TransportMode.car); - filter.filter(net, modes); + filter.filter(net, Set.of(TransportMode.car)); } this.xy2links = new XY2Links(net, scenario.getActivityFacilities()); @@ -110,121 +106,32 @@ public void run(final Person person) { log.warn("Person " + person.getId() + " has no plans!"); return; } - + // yyyyyy need to find out somewhere here if the access/egress legs of the incoming plans // are consistent with the config setting. Otherwise need to re-route all of them. kai, jul'18 - // make sure all the plans have valid act-locations and valid routes for (Plan plan : person.getPlans()) { boolean needsXY2Links = false; boolean needsReRoute = false; - - // for backward compatibility: add routingMode to legs if not present - for (Trip trip : TripStructureUtils.getTrips(plan.getPlanElements())) { - List legs = trip.getLegsOnly(); - if (legs.size() >= 1) { - String routingMode = TripStructureUtils.getRoutingMode(legs.get(0)); - - for (Leg leg : legs) { - // check all legs either have the same routing mode or all have routingMode==null - String existingRoutingMode = TripStructureUtils.getRoutingMode(leg); - if (existingRoutingMode == null) { - if (routingMode == null) { - // outdated initial plan without routingMode - } else { - String errorMessage = "Found a mixed trip, some legs with routingMode and others without. " - + "This is inconsistent. Agent id: " + person.getId().toString(); - log.error(errorMessage); - throw new RuntimeException(errorMessage); - } - } else { - if (!routingMode.equals(existingRoutingMode)) { - String errorMessage = "Found a trip whose legs have different routingModes. " - + "This is inconsistent. Agent id: " + person.getId().toString(); - log.error(errorMessage); - throw new RuntimeException(errorMessage); - } - } - } - // add routing mode - if (routingMode == null) { - if (legs.size() == 1) { - // there is only a single leg (e.g. after Trips2Legs and a mode choice replanning module) - routingMode = legs.get(0).getMode(); - if (routingMode.equals(TransportMode.transit_walk)) { - String errorMessage = "Found a trip of only one leg of mode transit_walk. " - + "This should not happen during simulation since transit_walk was replaced by walk and " - + "routingMode. Agent id: " + person.getId().toString(); - log.error(errorMessage); - throw new RuntimeException(errorMessage); - } - TripStructureUtils.setRoutingMode(legs.get(0), routingMode); - } else { - String errorMessage = "Found a trip whose legs have no routingMode. " - + "This is only allowed for (outdated) input plans, not during simulation (after PrepareForSim). Agent id: " - + person.getId().toString(); - log.error(errorMessage); - throw new RuntimeException(errorMessage); - } - } - } - } - - for (PlanElement pe : plan.getPlanElements()) { - if (pe instanceof Activity) { - Activity act = (Activity) pe; - if ( act.getLinkId() == null // neither activity nor facility has a link - && - //this check is necessary here, else, XY2Links will put the link/coord back to activity which is clear violation of facilitiesConfigGroup.removingLinksAndCoordinates =true. Amit July'18 - ( act.getFacilityId() == null - || this.activityFacilities.getFacilities().isEmpty() - || this.activityFacilities.getFacilities().get(act.getFacilityId()) == null - || this.activityFacilities.getFacilities().get(act.getFacilityId()).getLinkId() == null) - ) { - needsXY2Links = true; + // for backward compatibility: add routingMode to legs if not present + checkAndAddRoutingMode(plan); + + // make sure all the plans have valid act-locations and valid routes + planLoop: for (PlanElement pe : plan.getPlanElements()) { + switch (pe) { + case Activity act -> { + boolean needsReComputation = needsReComputation(act); + if (needsReComputation) { + needsXY2Links = true; needsReRoute = true; - break; - } - } else if (pe instanceof Leg) { - Leg leg = (Leg) pe; - - if (TripStructureUtils.getRoutingMode(leg) == null) { - String errorMessage = "Routing mode not set for leg :" + leg.toString() + " of agent id " + person.getId().toString(); - log.error( errorMessage ); - throw new RuntimeException( errorMessage ); - } - - if (leg.getRoute() == null) { - needsReRoute = true; - } else if (Double.isNaN(leg.getRoute().getDistance())){ - Double dist = null; - if (leg.getRoute() instanceof NetworkRoute){ - /* So far, 1.0 is always used as relative position on start and end link. - * This means that the end link is considered in route distance and the start link not. - * tt feb'16 - */ - double relativePositionStartLink = scenario.getConfig().global().getRelativePositionOfEntryExitOnLink() ; - double relativePositionEndLink = scenario.getConfig().global().getRelativePositionOfEntryExitOnLink() ; -// dist = RouteUtils.calcDistance((NetworkRoute) leg.getRoute(), relativePositionStartLink, relativePositionEndLink, this.network); - dist = RouteUtils.calcDistance((NetworkRoute) leg.getRoute(), relativePositionStartLink, relativePositionEndLink, scenario.getNetwork() ); - // using the full network for the distance calculation. kai, jul'18 - } else if (leg.getRoute() instanceof ExperimentalTransitRoute) { - // replace deprecated ExperimentalTransitRoute with DefaultTransitPassengerRoute - ExperimentalTransitRoute oldRoute = (ExperimentalTransitRoute) leg.getRoute(); - DefaultTransitPassengerRoute newRoute = new DefaultTransitPassengerRoute( - oldRoute.getStartLinkId(), - oldRoute.getEndLinkId(), - oldRoute.getAccessStopId(), - oldRoute.getEgressStopId(), - oldRoute.getLineId(), - oldRoute.getRouteId()); - leg.setRoute(newRoute); - } - if (dist != null){ - leg.getRoute().setDistance(dist); + break planLoop; } } + case Leg leg -> { + needsReRoute |= needsReRoute(person, leg); + } + default -> throw new IllegalStateException("Unexpected PlanElement: " + pe); } } if (needsXY2Links) { @@ -237,4 +144,135 @@ public void run(final Person person) { } + private boolean needsReRoute(Person person, Leg leg) { + if (TripStructureUtils.getRoutingMode(leg) == null) { + String errorMessage = "Routing mode not set for leg :" + leg + " of agent id " + person.getId().toString(); + log.error( errorMessage ); + throw new RuntimeException( errorMessage ); + } + + if (leg.getRoute() == null) { + return true; + } + + checkModeConsistent(person, leg); + + if(!Double.isNaN(leg.getRoute().getDistance())){ + return false; + } + + adaptRoute(leg); + + return false; + } + + private void adaptRoute(Leg leg) { + if (leg.getRoute() instanceof NetworkRoute){ + /* So far, 1.0 is always used as relative position on start and end link. + * This means that the end link is considered in route distance and the start link not. + * tt feb'16 + */ + double relativePositionStartLink = scenario.getConfig().global().getRelativePositionOfEntryExitOnLink() ; + double relativePositionEndLink = scenario.getConfig().global().getRelativePositionOfEntryExitOnLink() ; +// dist = RouteUtils.calcDistance((NetworkRoute) leg.getRoute(), relativePositionStartLink, relativePositionEndLink, this.network); + double dist = RouteUtils.calcDistance((NetworkRoute) leg.getRoute(), relativePositionStartLink, relativePositionEndLink, scenario.getNetwork() ); + leg.getRoute().setDistance(dist); + // using the full network for the distance calculation. kai, jul'18 + } else if (leg.getRoute() instanceof ExperimentalTransitRoute) { + // replace deprecated ExperimentalTransitRoute with DefaultTransitPassengerRoute + ExperimentalTransitRoute oldRoute = (ExperimentalTransitRoute) leg.getRoute(); + DefaultTransitPassengerRoute newRoute = new DefaultTransitPassengerRoute( + oldRoute.getStartLinkId(), + oldRoute.getEndLinkId(), + oldRoute.getAccessStopId(), + oldRoute.getEgressStopId(), + oldRoute.getLineId(), + oldRoute.getRouteId()); + leg.setRoute(newRoute); + } + } + + private void checkModeConsistent(Person person, Leg leg) { + if(this.scenario.getConfig().routing().getNetworkRouteConsistencyCheck() == RoutingConfigGroup.NetworkRouteConsistencyCheck.disable) { + return; + } + + if(!(leg.getRoute() instanceof NetworkRoute networkRoute)) { + return; + } + + boolean linkModesConsistent = networkRoute.getLinkIds().stream() + .map(l -> scenario.getNetwork().getLinks().get(l)) + .allMatch(l -> l.getAllowedModes().contains(leg.getMode())); + + if(!linkModesConsistent){ + String errorMessage = "Route inconsistent with link modes for: Person " + person.getId() + "; Leg '" + leg + "'"; + log.error(errorMessage + "\n Consider cleaning inconsistent routes by using PopulationUtils.checkRouteModeAndReset()." + + "\n If this is intended, set the routing config parameter 'networkRouteConsistencyCheck' to 'disable'."); + throw new RuntimeException(errorMessage); + } + } + + private boolean needsReComputation(Activity act) { + return act.getLinkId() == null // neither activity nor facility has a link + && + //this check is necessary here, else, XY2Links will put the link/coord back to activity which is clear violation of facilitiesConfigGroup.removingLinksAndCoordinates =true. Amit July'18 + (act.getFacilityId() == null + || this.activityFacilities.getFacilities().isEmpty() + || this.activityFacilities.getFacilities().get(act.getFacilityId()) == null + || this.activityFacilities.getFacilities().get(act.getFacilityId()).getLinkId() == null); + } + + private void checkAndAddRoutingMode(Plan plan) { + for (Trip trip : TripStructureUtils.getTrips(plan.getPlanElements())) { + List legs = trip.getLegsOnly(); + if (!legs.isEmpty()) { + String routingMode = TripStructureUtils.getRoutingMode(legs.get(0)); + + for (Leg leg : legs) { + // check all legs either have the same routing mode or all have routingMode==null + String existingRoutingMode = TripStructureUtils.getRoutingMode(leg); + if (existingRoutingMode == null) { + if (routingMode == null) { + // outdated initial plan without routingMode + } else { + String errorMessage = "Found a mixed trip, some legs with routingMode and others without. " + + "This is inconsistent. Agent id: " + plan.getPerson().getId().toString(); + log.error(errorMessage); + throw new RuntimeException(errorMessage); + } + } else { + if (!routingMode.equals(existingRoutingMode)) { + String errorMessage = "Found a trip whose legs have different routingModes. " + + "This is inconsistent. Agent id: " + plan.getPerson().getId().toString(); + log.error(errorMessage); + throw new RuntimeException(errorMessage); + } + } + } + + // add routing mode + if (routingMode == null) { + if (legs.size() == 1) { + // there is only a single leg (e.g. after Trips2Legs and a mode choice replanning module) + routingMode = legs.get(0).getMode(); + if (routingMode.equals(TransportMode.transit_walk)) { + String errorMessage = "Found a trip of only one leg of mode transit_walk. " + + "This should not happen during simulation since transit_walk was replaced by walk and " + + "routingMode. Agent id: " + plan.getPerson().getId().toString(); + log.error(errorMessage); + throw new RuntimeException(errorMessage); + } + TripStructureUtils.setRoutingMode(legs.get(0), routingMode); + } else { + String errorMessage = "Found a trip whose legs have no routingMode. " + + "This is only allowed for (outdated) input plans, not during simulation (after PrepareForSim). Agent id: " + + plan.getPerson().getId().toString(); + log.error(errorMessage); + throw new RuntimeException(errorMessage); + } + } + } + } + } } diff --git a/matsim/src/main/java/org/matsim/core/population/algorithms/PersonRouteCheck.java b/matsim/src/main/java/org/matsim/core/population/algorithms/PersonRouteCheck.java new file mode 100644 index 00000000000..aca5f9bb976 --- /dev/null +++ b/matsim/src/main/java/org/matsim/core/population/algorithms/PersonRouteCheck.java @@ -0,0 +1,43 @@ +package org.matsim.core.population.algorithms; + +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.population.Leg; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.Route; +import org.matsim.core.population.routes.NetworkRoute; + +public class PersonRouteCheck implements PersonAlgorithm{ + private final Network network; + + public PersonRouteCheck(Network network) { + this.network = network; + } + + @Override + public void run(Person person) { + person.getPlans().stream() + .flatMap(p -> p.getPlanElements().stream()) + .filter(pe -> pe instanceof Leg) + .map(pe -> (Leg) pe) + .forEach(this::resetRouteIfInconsistentModes); + } + + private void resetRouteIfInconsistentModes(Leg leg) { + Route route = leg.getRoute(); + if (route == null) { + return; + } + + if (!(route instanceof NetworkRoute netRoute)) { + return; + } + + boolean allLinksHaveLegMode = netRoute.getLinkIds().stream() + .map(id -> network.getLinks().get(id)) + .allMatch(link -> link.getAllowedModes().contains(leg.getMode())); + + if (!allLinksHaveLegMode) { + leg.setRoute(null); + } + } +} diff --git a/matsim/src/main/java/org/matsim/core/population/io/PopulationReaderMatsimV6.java b/matsim/src/main/java/org/matsim/core/population/io/PopulationReaderMatsimV6.java index 725ffb83654..54447776f4d 100644 --- a/matsim/src/main/java/org/matsim/core/population/io/PopulationReaderMatsimV6.java +++ b/matsim/src/main/java/org/matsim/core/population/io/PopulationReaderMatsimV6.java @@ -461,6 +461,7 @@ private void startRoute(final Attributes atts) { if ("pt".equals(legMode)) { routeType = "experimentalPt1"; } else if ("car".equals(legMode)) { + //yyyy couldn't we check against all network modes of config here? paul, jul '24 routeType = "links"; } else { routeType = "generic"; diff --git a/matsim/src/main/java/org/matsim/core/router/DefaultRoutingModules.java b/matsim/src/main/java/org/matsim/core/router/DefaultRoutingModules.java index 8e26e960a76..88e99ba95ce 100644 --- a/matsim/src/main/java/org/matsim/core/router/DefaultRoutingModules.java +++ b/matsim/src/main/java/org/matsim/core/router/DefaultRoutingModules.java @@ -60,6 +60,7 @@ public static RoutingModule createTeleportationRouter( String mode, Scenario sce /** * Creates network router without access/egress. */ + @Deprecated // use AccessEgressNetworkRouter instead public static RoutingModule createPureNetworkRouter( String mode, PopulationFactory popFact, Network net, final LeastCostPathCalculator routeAlgo ) { return new NetworkRoutingModule( mode, diff --git a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingModule.java b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingModule.java index 5380f45d47d..82e9b04928f 100644 --- a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingModule.java +++ b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingModule.java @@ -42,6 +42,7 @@ * * @author thibautd */ +@Deprecated // use NetworkRoutingInclAccessEgressModule instead public final class NetworkRoutingModule implements RoutingModule { // I think it makes sense to NOT add the bushwhacking mode directly into here ... // ... since it makes sense be able to to route from facility.getLinkId() to facility.getLinkId(). kai, dec'15 @@ -81,11 +82,13 @@ public List calcRoute(RoutingRequest request) { Link fromLink = this.network.getLinks().get(fromFacility.getLinkId()); if ( fromLink==null ) { + //if an activity takes place on a link which is not part of the modal network, use coord as fallback Gbl.assertNotNull( fromFacility.getCoord() ) ; fromLink = NetworkUtils.getNearestLink( network, fromFacility.getCoord()) ; } Link toLink = this.network.getLinks().get(toFacility.getLinkId()); if ( toLink==null ) { + //if an activity takes place on a link which is not part of the modal network, use coord as fallback Gbl.assertNotNull( toFacility.getCoord() ) ; toLink = NetworkUtils.getNearestLink(network, toFacility.getCoord()); } diff --git a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java index 667764861ca..7b874593fa1 100644 --- a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java +++ b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java @@ -29,10 +29,9 @@ import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.network.Network; import org.matsim.api.core.v01.population.PopulationFactory; -import org.matsim.core.config.groups.NetworkConfigGroup; +import org.matsim.core.config.groups.ControllerConfigGroup; import org.matsim.core.config.groups.RoutingConfigGroup; -import org.matsim.core.network.NetworkUtils; -import org.matsim.core.network.algorithms.TransportModeNetworkFilter; +import org.matsim.core.network.algorithms.NetworkCleaner; import org.matsim.core.router.costcalculators.TravelDisutilityFactory; import org.matsim.core.router.util.LeastCostPathCalculator; import org.matsim.core.router.util.LeastCostPathCalculatorFactory; @@ -41,22 +40,19 @@ import com.google.inject.name.Named; -import java.util.HashSet; import java.util.Map; -import java.util.Set; public class NetworkRoutingProvider implements Provider{ private static final Logger log = LogManager.getLogger( NetworkRoutingProvider.class ) ; private final String routingMode; + private boolean alreadyCheckedConsistency = false; @Inject Map travelTimes; @Inject Map travelDisutilityFactories; @Inject SingleModeNetworksCache singleModeNetworksCache; @Inject RoutingConfigGroup routingConfigGroup; - @Inject Network network; - @Inject NetworkConfigGroup networkConfigGroup; @Inject PopulationFactory populationFactory; @Inject LeastCostPathCalculatorFactory leastCostPathCalculatorFactory; @Inject Scenario scenario ; @@ -101,6 +97,8 @@ public RoutingModule get() { // the network refers to the (transport)mode: Network filteredNetwork = singleModeNetworksCache.getOrCreateSingleModeNetwork(mode); + checkNetwork(filteredNetwork); + // the travel time & disutility refer to the routing mode: TravelDisutilityFactory travelDisutilityFactory = this.travelDisutilityFactories.get(routingMode); if (travelDisutilityFactory == null) { @@ -135,7 +133,34 @@ public RoutingModule get() { } } else { + log.warn("[mode: {}; routingMode: {}] Using deprecated routing module without access/egress. Consider using AccessEgressNetworkRouter instead.", mode, routingMode); return DefaultRoutingModules.createPureNetworkRouter(mode, populationFactory, filteredNetwork, routeAlgo); } } + + private void checkNetwork(Network filteredNetwork) { + if(routingConfigGroup.getNetworkRouteConsistencyCheck() == RoutingConfigGroup.NetworkRouteConsistencyCheck.disable) { + return; + } + + if(alreadyCheckedConsistency){ + return; + } + + log.info("Checking network for mode '{}' for consistency...", mode); + + int nLinks = filteredNetwork.getLinks().size(); + int nNodes = filteredNetwork.getNodes().size(); + new NetworkCleaner().run(filteredNetwork); + boolean changed = nLinks != filteredNetwork.getLinks().size() || nNodes != filteredNetwork.getNodes().size(); + + if(changed) { + String errorMessage = "Network for mode '" + mode + "' has unreachable links and nodes. This may be caused by mode restrictions on certain links. Aborting."; + log.error(errorMessage + "\n If you restricted modes on some links, consider doing that with NetworkUtils.restrictModesAndCleanNetwork(). This makes sure, that the network is consistent for each mode." + + "\n If this network topology is intended, set the routing config parameter 'networkRouteConsistencyCheck' to 'disable'."); + throw new RuntimeException(errorMessage); + } + + alreadyCheckedConsistency = true; + } } diff --git a/matsim/src/main/java/org/matsim/core/router/PlanRouter.java b/matsim/src/main/java/org/matsim/core/router/PlanRouter.java index 2e96a046a94..f52b9a85169 100644 --- a/matsim/src/main/java/org/matsim/core/router/PlanRouter.java +++ b/matsim/src/main/java/org/matsim/core/router/PlanRouter.java @@ -71,17 +71,6 @@ public PlanRouter( final TripRouter routingHandler, final TimeInterpretation tim this( routingHandler , null, timeInterpretation ); } -// /** -// * Gives access to the {@link TripRouter} used -// * to compute routes. -// * -// * @return the internal TripRouter instance. -// */ -// @Deprecated // get TripRouter out of injection instead. kai, feb'16 -// public TripRouter getTripRouter() { -// return tripRouter; -// } - @Override public void run(final Plan plan) { final List trips = TripStructureUtils.getTrips( plan ); diff --git a/matsim/src/main/java/org/matsim/core/router/TripRouter.java b/matsim/src/main/java/org/matsim/core/router/TripRouter.java index ac39295ebe8..84769313c86 100644 --- a/matsim/src/main/java/org/matsim/core/router/TripRouter.java +++ b/matsim/src/main/java/org/matsim/core/router/TripRouter.java @@ -169,26 +169,25 @@ public synchronized List calcRoute( RoutingModule module = routingModules.get( mainMode ); - if (module != null) { - RoutingRequest request = DefaultRoutingRequest.of( - fromFacility, - toFacility, - departureTime, - person, - routingAttributes); - - List trip = module.calcRoute(request); - - if ( trip == null ) { - trip = fallbackRoutingModule.calcRoute(request) ; - } - for (Leg leg: TripStructureUtils.getLegs(trip)) { - TripStructureUtils.setRoutingMode(leg, mainMode); - } - return trip; + if (module == null) { + throw new UnknownModeException( "unregistered main mode |"+mainMode+"|: does not pertain to "+routingModules.keySet() ); } + RoutingRequest request = DefaultRoutingRequest.of( + fromFacility, + toFacility, + departureTime, + person, + routingAttributes); + + List trip = module.calcRoute(request); - throw new UnknownModeException( "unregistered main mode |"+mainMode+"|: does not pertain to "+routingModules.keySet() ); + if ( trip == null ) { + trip = fallbackRoutingModule.calcRoute(request) ; + } + for (Leg leg: TripStructureUtils.getLegs(trip)) { + TripStructureUtils.setRoutingMode(leg, mainMode); + } + return trip; } public static class UnknownModeException extends RuntimeException { diff --git a/matsim/src/main/java/org/matsim/core/scoring/PlansScoringImpl.java b/matsim/src/main/java/org/matsim/core/scoring/PlansScoringImpl.java index bc774cc2c1d..a5671b0c673 100644 --- a/matsim/src/main/java/org/matsim/core/scoring/PlansScoringImpl.java +++ b/matsim/src/main/java/org/matsim/core/scoring/PlansScoringImpl.java @@ -52,11 +52,11 @@ final class PlansScoringImpl implements PlansScoring, ScoringListener, Iteration @Inject private OutputDirectoryHierarchy controlerIO; @Inject private ScoringFunctionsForPopulation scoringFunctionsForPopulation; @Inject private ExperiencedPlansService experiencedPlansService; + @Inject private NewScoreAssigner newScoreAssigner; @Override public void notifyScoring(final ScoringEvent event) { scoringFunctionsForPopulation.finishScoringFunctions(); - NewScoreAssignerImpl newScoreAssigner = new NewScoreAssignerImpl(this.scoringConfigGroup, this.controllerConfigGroup); newScoreAssigner.assignNewScores(event.getIteration(), this.scoringFunctionsForPopulation, this.population); } diff --git a/matsim/src/main/java/org/matsim/core/scoring/PlansScoringModule.java b/matsim/src/main/java/org/matsim/core/scoring/PlansScoringModule.java index 1e5f29c1114..2048613ebd5 100644 --- a/matsim/src/main/java/org/matsim/core/scoring/PlansScoringModule.java +++ b/matsim/src/main/java/org/matsim/core/scoring/PlansScoringModule.java @@ -32,5 +32,6 @@ public void install() { bind(ScoringFunctionsForPopulation.class).asEagerSingleton(); bind(PlansScoring.class).to(PlansScoringImpl.class); bind(ExperiencedPlansService.class).to(ExperiencedPlansServiceImpl.class).asEagerSingleton(); + bind(NewScoreAssigner.class).to(NewScoreAssignerImpl.class).asEagerSingleton(); } } diff --git a/matsim/src/main/java/org/matsim/run/gui/Gui.java b/matsim/src/main/java/org/matsim/run/gui/Gui.java index 4b826b14842..1ca4a9afc8d 100644 --- a/matsim/src/main/java/org/matsim/run/gui/Gui.java +++ b/matsim/src/main/java/org/matsim/run/gui/Gui.java @@ -91,6 +91,11 @@ public class Gui extends JFrame { private File configFile; private File lastUsedDirectory; + + /** + * This is the working directory for the simulation. If it is null, the working directory is the directory of the config file. + */ + private File workingDirectory = null; private ConfigEditor editor = null; private ScheduleValidatorWindow transitValidator = null; @@ -439,6 +444,8 @@ private void startMATSim() { textStdOut.setText(""); textErrOut.setText(""); + String cwd = workingDirectory == null ? new File(txtConfigfilename.getText()).getParent() : workingDirectory.getAbsolutePath(); + new Thread(() -> { String classpath = System.getProperty("java.class.path"); String[] cpParts = classpath.split(File.pathSeparator); @@ -457,8 +464,7 @@ private void startMATSim() { "--add-exports", "java.desktop/sun.java2d=ALL-UNNAMED", mainClass, txtConfigfilename.getText() }; // see https://jogamp.org/bugzilla/show_bug.cgi?id=1317#c21 and/or https://github.com/matsim-org/matsim-libs/pull/2940 - exeRunner = ExeRunner.run(cmdArgs, textStdOut, textErrOut, - new File(txtConfigfilename.getText()).getParent()); + exeRunner = ExeRunner.run(cmdArgs, textStdOut, textErrOut, cwd); int exitcode = exeRunner.waitForFinish(); exeRunner = null; @@ -575,6 +581,10 @@ public static void main(String[] args) { Gui.show("MATSim", RunMatsim.class, args.length == 1 ? new File(args[0]) : null); } + public void setWorkingDirectory(File cwd) { + this.workingDirectory = cwd; + } + // Is it a problem to make the following available to the outside? If so, why? Would it // be better to rather copy/paste the above code and start from there? kai, jun/aug'18 diff --git a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/Fixture.java b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/Fixture.java index 97bdc02747a..f842302b4d6 100644 --- a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/Fixture.java +++ b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/Fixture.java @@ -30,6 +30,7 @@ import org.matsim.api.core.v01.network.Node; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.population.routes.NetworkRoute; import org.matsim.core.population.routes.RouteUtils; import org.matsim.core.scenario.MutableScenario; @@ -100,6 +101,7 @@ public Fixture() { this.config = ConfigUtils.createConfig(); this.config.transit().setUseTransit(true); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ScenarioBuilder scBuilder = new ScenarioBuilder(config) ; this.scenario = (MutableScenario) scBuilder.build() ; diff --git a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/IntermodalFixture.java b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/IntermodalFixture.java index 495868e6991..a29767b6a48 100644 --- a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/IntermodalFixture.java +++ b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/IntermodalFixture.java @@ -30,6 +30,7 @@ import org.matsim.api.core.v01.population.Person; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.population.routes.NetworkRoute; import org.matsim.core.population.routes.RouteUtils; import org.matsim.core.scenario.ScenarioUtils; @@ -96,6 +97,7 @@ class IntermodalFixture { IntermodalFixture() { this.srrConfig = new SwissRailRaptorConfigGroup(); this.config = ConfigUtils.createConfig(this.srrConfig); + this.config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); this.scenario = ScenarioUtils.createScenario(this.config); TransitSchedule schedule = this.scenario.getTransitSchedule(); diff --git a/matsim/src/test/java/org/matsim/analysis/LinkStatsControlerListenerTest.java b/matsim/src/test/java/org/matsim/analysis/LinkStatsControlerListenerTest.java index 8ec2fb9f37d..0a47e4b929f 100644 --- a/matsim/src/test/java/org/matsim/analysis/LinkStatsControlerListenerTest.java +++ b/matsim/src/test/java/org/matsim/analysis/LinkStatsControlerListenerTest.java @@ -33,6 +33,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.LinkStatsConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.*; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Injector; @@ -352,6 +353,7 @@ void testReset_CorrectlyExecuted() throws IOException { config.controller().setFirstIteration(0); config.controller().setLastIteration(7); config.controller().setWritePlansInterval(0); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); LinkStatsConfigGroup lsConfig = config.linkStats(); lsConfig.setWriteLinkStatsInterval(3); diff --git a/matsim/src/test/java/org/matsim/core/controler/ControlerIT.java b/matsim/src/test/java/org/matsim/core/controler/ControlerIT.java index 2a735f508af..703ea500d06 100644 --- a/matsim/src/test/java/org/matsim/core/controler/ControlerIT.java +++ b/matsim/src/test/java/org/matsim/core/controler/ControlerIT.java @@ -1018,6 +1018,7 @@ private static class Fixture { Link link3 = null; protected Fixture(final Config config) { + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); this.scenario = ScenarioUtils.createScenario(config); this.network = this.scenario.getNetwork(); diff --git a/matsim/src/test/java/org/matsim/core/controler/PrepareForSimImplTest.java b/matsim/src/test/java/org/matsim/core/controler/PrepareForSimImplTest.java index af9ec71a41b..5f0e60dd990 100644 --- a/matsim/src/test/java/org/matsim/core/controler/PrepareForSimImplTest.java +++ b/matsim/src/test/java/org/matsim/core/controler/PrepareForSimImplTest.java @@ -829,7 +829,7 @@ public List calcRoute(RoutingRequest request) { } } - private Link createAndAddNetwork(Scenario sc) { + private void createAndAddNetwork(Scenario sc) { Network net = sc.getNetwork(); Link link1; { @@ -851,6 +851,5 @@ private Link createAndAddNetwork(Scenario sc) { net.addLink(link1); net.addLink(l2); } - return link1; } } diff --git a/matsim/src/test/java/org/matsim/core/controler/TransitControlerIntegrationTest.java b/matsim/src/test/java/org/matsim/core/controler/TransitControlerIntegrationTest.java index 10d912cfe9d..20699888afa 100644 --- a/matsim/src/test/java/org/matsim/core/controler/TransitControlerIntegrationTest.java +++ b/matsim/src/test/java/org/matsim/core/controler/TransitControlerIntegrationTest.java @@ -41,6 +41,7 @@ import org.matsim.api.core.v01.population.Population; import org.matsim.api.core.v01.population.PopulationFactory; import org.matsim.core.config.Config; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.config.groups.ReplanningConfigGroup.StrategySettings; import org.matsim.core.population.routes.NetworkRoute; @@ -68,6 +69,7 @@ public class TransitControlerIntegrationTest { @Test void testTransitRouteCopy() { Config config = utils.loadConfig((String)null); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.transit().setUseTransit(true); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/hermes/HermesTest.java b/matsim/src/test/java/org/matsim/core/mobsim/hermes/HermesTest.java index 09cb1763746..426a984aa8a 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/hermes/HermesTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/hermes/HermesTest.java @@ -59,6 +59,7 @@ import org.matsim.core.api.experimental.events.TeleportationArrivalEvent; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.events.handler.BasicEventHandler; @@ -808,6 +809,7 @@ private LogCounter runConsistentRoutesTestSim(final String startLinkId, final St void testStartAndEndTime() { final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); // --- @@ -864,6 +866,7 @@ void testStartAndEndTime() { void testCleanupSim_EarlyEnd() { MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); Config config = scenario.getConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); double simEndTime = 8.0*3600; @@ -990,6 +993,7 @@ public static final class Fixture { public Fixture() { this.scenario = ScenarioUtils.createScenario(ConfigUtils.createConfig()); this.config = scenario.getConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); /* build network */ diff --git a/matsim/src/test/java/org/matsim/core/mobsim/hermes/StorageCapacityTest.java b/matsim/src/test/java/org/matsim/core/mobsim/hermes/StorageCapacityTest.java index fd7958999fb..290d4632d45 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/hermes/StorageCapacityTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/hermes/StorageCapacityTest.java @@ -44,6 +44,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.events.EventsUtils; import org.matsim.core.network.NetworkUtils; import org.matsim.core.population.PersonUtils; @@ -68,6 +69,7 @@ public class StorageCapacityTest { void testStorageCapacity() { ScenarioImporter.flush(); Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.hermes().setStuckTime(Integer.MAX_VALUE); Scenario scenario = ScenarioUtils.createScenario(config); var links = generateNetwork(scenario.getNetwork()); @@ -120,6 +122,7 @@ void testStorageCapacityDownscaling() { config.hermes().setStuckTime(Integer.MAX_VALUE); config.hermes().setFlowCapacityFactor(0.1); config.hermes().setStorageCapacityFactor(0.1); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = ScenarioUtils.createScenario(config); var links = generateNetwork(scenario.getNetwork()); @@ -169,6 +172,7 @@ void testStorageCapacityDownscaling() { void testStorageCapacityWithDifferentPCUs() { ScenarioImporter.flush(); Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.hermes().setStuckTime(Integer.MAX_VALUE); Scenario scenario = ScenarioUtils.createScenario(config); var links = generateNetwork(scenario.getNetwork()); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/FlowStorageSpillbackTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/FlowStorageSpillbackTest.java index dbf47866033..311831b6bad 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/FlowStorageSpillbackTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/FlowStorageSpillbackTest.java @@ -38,6 +38,7 @@ import org.matsim.api.core.v01.population.*; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.population.PopulationUtils; @@ -230,6 +231,7 @@ private Scenario loadScenario() { // (0)-----link1-----(1)-----link2-----(2)-----link3-----(3)-----link4-----(4) Config config = testUtils.loadConfig((String) null); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = (ScenarioUtils.createScenario(config)); Network network = (Network) scenario.getNetwork(); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/NetsimRoutingConsistencyTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/NetsimRoutingConsistencyTest.java index 6899e6c95f1..e8693333c25 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/NetsimRoutingConsistencyTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/NetsimRoutingConsistencyTest.java @@ -46,6 +46,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; @@ -213,7 +214,7 @@ void testRoutingVsSimulation() { @Test void testRoutingVsSimulationFullStack() { Config config = ConfigUtils.createConfig(); - + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setLastIteration(0); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/NodeTransitionTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/NodeTransitionTest.java index b37c5f2a32d..40403107cb9 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/NodeTransitionTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/NodeTransitionTest.java @@ -43,6 +43,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.config.groups.QSimConfigGroup.NodeTransition; import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; @@ -292,6 +293,7 @@ void testBlockedNodeSituationWithEmptyBufferAfterBufferRandomDistribution(boolea Scenario scenario = Fixture.createBlockedNodeScenario(); scenario.getConfig().qsim().setNodeTransitionLogic(NodeTransition.emptyBufferAfterBufferRandomDistribution_nodeBlockedWhenSingleOutlinkFull); scenario.getConfig().qsim().setUsingFastCapacityUpdate(useFastCapUpdate); + scenario.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); EventsManager events = EventsUtils.createEventsManager(); List> linksOfInterest = new LinkedList<>(); @@ -374,6 +376,7 @@ void testBlockedNodeSituationWithMoveVehByVehRandomDistribution(boolean useFastC Scenario scenario = Fixture.createBlockedNodeScenario(); scenario.getConfig().qsim().setNodeTransitionLogic(NodeTransition.moveVehByVehRandomDistribution_nodeBlockedWhenSingleOutlinkFull); scenario.getConfig().qsim().setUsingFastCapacityUpdate(useFastCapUpdate); + scenario.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); EventsManager events = EventsUtils.createEventsManager(); List> linksOfInterest = new LinkedList<>(); @@ -457,6 +460,7 @@ void testBlockedNodeSituationWithMoveVehByVehDeterministicPriorities(boolean use Scenario scenario = Fixture.createBlockedNodeScenario(); scenario.getConfig().qsim().setNodeTransitionLogic(NodeTransition.moveVehByVehDeterministicPriorities_nodeBlockedWhenSingleOutlinkFull); scenario.getConfig().qsim().setUsingFastCapacityUpdate(useFastCapUpdate); + scenario.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); EventsManager events = EventsUtils.createEventsManager(); List> linksOfInterest = new LinkedList<>(); @@ -548,6 +552,7 @@ void testNodeTransitionWithTimeStepSizeSmallerOne(boolean useFastCapUpdate) { scenario.getConfig().qsim().setNodeTransitionLogic(NodeTransition.emptyBufferAfterBufferRandomDistribution_dontBlockNode); scenario.getConfig().qsim().setTimeStepSize(0.5); scenario.getConfig().qsim().setUsingFastCapacityUpdate(useFastCapUpdate); + scenario.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); EventsManager events = EventsUtils.createEventsManager(); List> linksOfInterest = new LinkedList<>(); @@ -633,9 +638,11 @@ static Scenario createMergeScenario() { config.controller().setLastIteration(0); config.qsim().setStuckTime(24*3600); config.qsim().setRemoveStuckVehicles(false); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ScoringConfigGroup.ActivityParams dummyAct = new ScoringConfigGroup.ActivityParams("dummy"); dummyAct.setTypicalDuration(12 * 3600); config.scoring().addActivityParams(dummyAct); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = ScenarioUtils.createScenario(config); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/QSimTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/QSimTest.java index e33947ee22f..96c12d442be 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/QSimTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/QSimTest.java @@ -66,6 +66,7 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.config.groups.QSimConfigGroup.TrafficDynamics; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.events.ParallelEventsManager; @@ -1393,6 +1394,7 @@ private LogCounter runConsistentRoutesTestSim(final String startLinkId, final St void testStartAndEndTime(boolean isUsingFastCapacityUpdate, int numberOfThreads) { final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setUsingFastCapacityUpdate(isUsingFastCapacityUpdate); // --- @@ -1461,6 +1463,7 @@ void testCleanupSim_EarlyEnd(boolean isUsingFastCapacityUpdate, int numberOfThre MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); Config config = scenario.getConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setUsingFastCapacityUpdate(isUsingFastCapacityUpdate); config.qsim().setNumberOfThreads(numberOfThreads); @@ -1806,6 +1809,8 @@ public Fixture(boolean isUsingFastCapacityUpdate, int numberOfThreads) { this.config.qsim().setUsingFastCapacityUpdate(isUsingFastCapacityUpdate); this.config.qsim().setNumberOfThreads(numberOfThreads); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + /* build network */ this.network = this.scenario.getNetwork(); this.network.setCapacityPeriod(Time.parseTime("1:00:00")); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/TeleportationEngineWDistanceCheckTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/TeleportationEngineWDistanceCheckTest.java index 8f0286cf9cd..5fa782435f3 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/TeleportationEngineWDistanceCheckTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/TeleportationEngineWDistanceCheckTest.java @@ -39,6 +39,7 @@ import org.matsim.api.core.v01.population.PopulationFactory; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.config.groups.ReplanningConfigGroup.StrategySettings; import org.matsim.core.controler.AbstractModule; @@ -64,6 +65,7 @@ final void test() { config.controller().setOutputDirectory( utils.getOutputDirectory() ); config.controller().setOverwriteFileSetting( OverwriteFileSetting.deleteDirectoryIfExists ); config.controller().setLastIteration(0); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ActivityParams params = new ActivityParams("dummy" ) ; config.scoring().addActivityParams(params); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/VehicleSourceTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/VehicleSourceTest.java index 9460bd95d03..367eb5d10db 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/VehicleSourceTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/VehicleSourceTest.java @@ -36,6 +36,7 @@ import org.matsim.api.core.v01.population.*; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.config.groups.QSimConfigGroup.VehiclesSource; @@ -94,6 +95,7 @@ void main(VehiclesSource vehiclesSource, boolean usingPersonIdForMissingVehicleI createPlans(vehiclesSource, providingVehiclesInPerson); Config config = scenario.getConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setFlowCapFactor(1.0); config.qsim().setStorageCapFactor(1.0); config.qsim().setMainModes(Arrays.asList(transportModes)); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/QSimIntegrationTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/QSimIntegrationTest.java index 25234b89cd0..078d2355b42 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/QSimIntegrationTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/QSimIntegrationTest.java @@ -44,6 +44,7 @@ import org.matsim.core.api.experimental.events.VehicleDepartsAtFacilityEvent; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -425,7 +426,8 @@ private static class Fixture { public Fixture() throws SAXException, ParserConfigurationException, IOException { // setup: config final Config config = ConfigUtils.createConfig(); - config.transit().setUseTransit(true); + config.transit().setUseTransit(true); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setEndTime(8.0*3600); this.scenario = (MutableScenario) ScenarioUtils.createScenario(config); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/TransitAgentTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/TransitAgentTest.java index 59c7341e27e..7b73108a13f 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/TransitAgentTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/TransitAgentTest.java @@ -39,7 +39,9 @@ import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.PopulationFactory; import org.matsim.core.api.experimental.events.EventsManager; +import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSim; @@ -65,7 +67,9 @@ public class TransitAgentTest { @Test void testAcceptLineRoute() { - MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); + Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); Network network = (Network) scenario.getNetwork(); Node node1 = NetworkUtils.createAndAddNode(network, Id.create("1", Node.class), new Coord((double) 0, (double) 0)); @@ -117,7 +121,9 @@ void testAcceptLineRoute() { @Test void testArriveAtStop() { - MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); + Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); Network network = (Network) scenario.getNetwork(); Node node1 = NetworkUtils.createAndAddNode(network, Id.create("1", Node.class), new Coord((double) 0, (double) 0)); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/TransitQueueSimulationTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/TransitQueueSimulationTest.java index 914190b0228..c635f01df74 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/TransitQueueSimulationTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/TransitQueueSimulationTest.java @@ -63,6 +63,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.ExternalMobimConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.events.handler.BasicEventHandler; @@ -108,6 +109,7 @@ public class TransitQueueSimulationTest { void testCreateAgents() { // setup: config final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.transit().setUseTransit(true); config.qsim().setEndTime(8.0*3600); @@ -310,6 +312,7 @@ void testAddAgentToStopWrongLink() { assertThrows(TransitAgentTriesToTeleportException.class, () -> { // setup: config final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.transit().setUseTransit(true); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); @@ -381,6 +384,7 @@ void testAddAgentToStopWrongLink() { void testHandleStop() { // setup: config final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.transit().setUseTransit(true); config.qsim().setEndTime(8.0*3600); @@ -631,6 +635,7 @@ protected SpyHandleStopData(final TransitStopFacility stopFacility, final double @Test void testStartAndEndTime() { final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.transit().setUseTransit(true); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); @@ -728,6 +733,7 @@ public void reset(final int iteration) { @Test void testEvents() { final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.transit().setUseTransit(true); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/DeparturesOnSameLinkSameTimeTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/DeparturesOnSameLinkSameTimeTest.java index bc69576a7f2..f603260e3ce 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/DeparturesOnSameLinkSameTimeTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/DeparturesOnSameLinkSameTimeTest.java @@ -34,6 +34,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup.VehiclesSource; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -147,6 +148,7 @@ public PseudoInputs(String travelMode) { config=ConfigUtils.createConfig(); this.scenario = ScenarioUtils.loadScenario(config); config.qsim().setMainModes(Arrays.asList(travelMode)); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); //following is necessary for mixed traffic, providing a route was obstructing // the requirement of these which might be all right in some cases. Amit Jan'18 diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/EquiDistAgentSnapshotInfoBuilderTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/EquiDistAgentSnapshotInfoBuilderTest.java index 5af56c62d44..3047d361ee0 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/EquiDistAgentSnapshotInfoBuilderTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/EquiDistAgentSnapshotInfoBuilderTest.java @@ -53,8 +53,8 @@ void positionVehiclesAlongLine_singleVehicleFreeFlow(){ 1 / setUp.linkCapacity, // this would mean the flow capacity is 100 setUp.freespeed, 1, - new LinkedList<>() - ); + new LinkedList<>(), + null ); // assert assertEquals(1, outCollection.size()); @@ -85,8 +85,8 @@ void positionVehiclesAlongLine_congestedAboveCapacityLimit() { 1 / setUp.linkCapacity, // this would mean the flow capacity is 100 setUp.freespeed, 1, - new LinkedList<>() - ); + new LinkedList<>(), + null ); // assert assertEquals(vehicles.size(), outCollection.size()); @@ -337,4 +337,4 @@ private static Collection createAgents(int size) { return result; } -} \ No newline at end of file +} diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/FlowCapacityVariationTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/FlowCapacityVariationTest.java index d94ce42724a..2507353faa1 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/FlowCapacityVariationTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/FlowCapacityVariationTest.java @@ -37,6 +37,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup.VehiclesSource; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -130,7 +131,7 @@ public PseudoInputs(String travelMode){ config = scenario.getConfig(); config.qsim().setMainModes(Arrays.asList(travelMode)); config.qsim().setUsingFastCapacityUpdate(true); - + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); population = scenario.getPopulation(); } diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/FlowEfficiencyCalculatorTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/FlowEfficiencyCalculatorTest.java index 2d373a8e2b1..89594e75077 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/FlowEfficiencyCalculatorTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/FlowEfficiencyCalculatorTest.java @@ -37,6 +37,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; @@ -132,6 +133,7 @@ private Scenario createScenario() { Config config = ConfigUtils.createConfig(); config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setLastIteration(0); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ActivityParams genericParams = new ActivityParams("generic"); genericParams.setTypicalDuration(1.0); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/JavaRoundingErrorInQsimTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/JavaRoundingErrorInQsimTest.java index ca771b4156c..bf41bf3241c 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/JavaRoundingErrorInQsimTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/JavaRoundingErrorInQsimTest.java @@ -39,6 +39,7 @@ import org.matsim.api.core.v01.population.*; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -142,6 +143,7 @@ private static final class PseudoInputs{ public PseudoInputs(){ scenario = ScenarioUtils.createScenario(ConfigUtils.createConfig()); scenario.getConfig().qsim().setUsingFastCapacityUpdate(true); + scenario.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); population = scenario.getPopulation(); } diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/LinkSpeedCalculatorIntegrationTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/LinkSpeedCalculatorIntegrationTest.java index 2a6554df93d..c84fa35e061 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/LinkSpeedCalculatorIntegrationTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/LinkSpeedCalculatorIntegrationTest.java @@ -39,6 +39,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.Injector; import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; import org.matsim.core.controler.PrepareForSimUtils; @@ -222,7 +223,9 @@ static class Fixture { Scenario scenario; public Fixture() { - this.scenario = ScenarioUtils.createScenario(ConfigUtils.createConfig()); + Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + this.scenario = ScenarioUtils.createScenario(config); Id[] nodeIds = new Id[5]; for (int i = 0; i < nodeIds.length; i++) { diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/PassingTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/PassingTest.java index a145ecf6c39..2db8d64118c 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/PassingTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/PassingTest.java @@ -38,6 +38,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.controler.events.IterationEndsEvent; import org.matsim.core.controler.events.StartupEvent; @@ -182,6 +183,7 @@ public SimpleNetwork(){ config.qsim().setStorageCapFactor(1.0); config.qsim().setMainModes(Arrays.asList("car","bike")); config.qsim().setLinkDynamics(QSimConfigGroup.LinkDynamics.PassingQ); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); network = (Network) scenario.getNetwork(); this.network.setCapacityPeriod(Time.parseTime("1:00:00")); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QLinkLanesTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QLinkLanesTest.java index 53794c1f44a..ba289374fe9 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QLinkLanesTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QLinkLanesTest.java @@ -33,6 +33,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSim; @@ -137,6 +138,7 @@ private static void createThreeLanes(Scenario scenario) { @Test void testCapacityWoLanes() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); initNetwork(scenario.getNetwork()); @@ -155,6 +157,7 @@ void testCapacityWoLanes() { @Test void testCapacityWithOneLaneOneLane() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); initNetwork(scenario.getNetwork()); createOneLane(scenario, 1); @@ -191,6 +194,7 @@ void testCapacityWithOneLaneOneLane() { @Test void testCapacityWithOneLaneTwoLanes() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); initNetwork(scenario.getNetwork()); createOneLane(scenario, 2); @@ -228,6 +232,7 @@ void testCapacityWithOneLaneTwoLanes() { @Test void testCapacityWithLanes() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); initNetwork(scenario.getNetwork()); createThreeLanes(scenario); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QLinkTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QLinkTest.java index 394ef272b28..93e9ed84e07 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QLinkTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QLinkTest.java @@ -46,6 +46,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.gbl.MatsimRandom; @@ -313,6 +314,7 @@ void testGetVehicle_Departing(boolean isUsingFastCapacityUpdate) { @ValueSource(booleans = {true, false}) void testBuffer(boolean isUsingFastCapacityUpdate) { Config conf = utils.loadConfig((String)null); + conf.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); conf.qsim().setUsingFastCapacityUpdate(isUsingFastCapacityUpdate); @@ -543,6 +545,7 @@ void testStuckEvents(boolean isUsingFastCapacityUpdate) { Scenario scenario = ScenarioUtils.createScenario(ConfigUtils.createConfig()); scenario.getConfig().qsim().setStuckTime(100); scenario.getConfig().qsim().setRemoveStuckVehicles(true); + scenario.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MatsimRandom.reset(4711); // yyyyyy !!!!!! Network network = (Network) scenario.getNetwork(); network.setCapacityPeriod(3600.0); @@ -622,6 +625,7 @@ private static final class Fixture { this.scenario.getConfig().qsim().setStuckTime(100); this.scenario.getConfig().qsim().setRemoveStuckVehicles(true); this.scenario.getConfig().qsim().setUsingFastCapacityUpdate(usingFastCapacityUpdate); + this.scenario.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Network network = (Network) this.scenario.getNetwork(); network.setCapacityPeriod(3600.0); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueAgentSnapshotInfoBuilderTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueAgentSnapshotInfoBuilderTest.java index b81a8fb91a0..b815ced0819 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueAgentSnapshotInfoBuilderTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueAgentSnapshotInfoBuilderTest.java @@ -53,8 +53,8 @@ void positionVehiclesAlongLine_singleVehicleFreeFlow() { 1 / setUp.linkCapacity, // this would mean the flow capacity is 100 setUp.freespeed, 1, - new LinkedList<>() - ); + new LinkedList<>(), + null ); // assert assertEquals(1, outCollection.size()); @@ -94,8 +94,8 @@ void positionVehiclesAlongLine_congestedAboveCapacityLimit() { 1 / setUp.linkCapacity, // this would mean the flow capacity is 100 setUp.freespeed, 1, - new LinkedList<>() - ); + new LinkedList<>(), + null ); // assert assertEquals(vehicles.size(), outCollection.size()); @@ -132,8 +132,8 @@ void positionVehiclesAlongLine_queueAtEnd() { 1 / setUp.linkCapacity, setUp.freespeed, 1, - new LinkedList<>() - ); + new LinkedList<>(), + null ); // assert assertEquals(5, outCollection.size()); @@ -473,4 +473,4 @@ private static Collection createAgents(int size) { } return result; } -} \ No newline at end of file +} diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SeepageTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SeepageTest.java index c562b59987b..081028398b1 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SeepageTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SeepageTest.java @@ -40,6 +40,7 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup.LinkDynamics; import org.matsim.core.config.groups.QSimConfigGroup.VehiclesSource; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -170,6 +171,7 @@ public SimpleNetwork(){ config.qsim().setStorageCapFactor(1.0); config.qsim().setMainModes(Arrays.asList(TransportMode.car,TransportMode.walk)); config.qsim().setLinkDynamics(LinkDynamics.SeepageQ); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setSeepModes(Arrays.asList(TransportMode.walk) ); config.qsim().setSeepModeStorageFree(false); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SimulatedLaneFlowCapacityTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SimulatedLaneFlowCapacityTest.java index 018ef7c995f..36d56ad9d2c 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SimulatedLaneFlowCapacityTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SimulatedLaneFlowCapacityTest.java @@ -48,6 +48,7 @@ import org.matsim.core.api.experimental.events.handler.LaneLeaveEventHandler; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; @@ -210,6 +211,7 @@ private static void initPopulation(Population population) { @Test void testCapacityWoLanes() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ActivityParams dummyAct = new ActivityParams("dummy"); dummyAct.setTypicalDuration(12 * 3600); config.scoring().addActivityParams(dummyAct); @@ -238,6 +240,7 @@ void testCapacityWoLanes() { @Test void testCapacityWithOneLaneOneLane() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ActivityParams dummyAct = new ActivityParams("dummy"); dummyAct.setTypicalDuration(12 * 3600); config.scoring().addActivityParams(dummyAct); @@ -270,6 +273,7 @@ void testCapacityWithOneLaneOneLane() { @Test void testCapacityWithOneLaneTwoLanes() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ActivityParams dummyAct = new ActivityParams("dummy"); dummyAct.setTypicalDuration(12 * 3600); config.scoring().addActivityParams(dummyAct); @@ -303,6 +307,7 @@ void testCapacityWithOneLaneTwoLanes() { @Test void testCapacityWithThreeLanes() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ActivityParams dummyAct = new ActivityParams("dummy"); dummyAct.setTypicalDuration(12 * 3600); config.scoring().addActivityParams(dummyAct); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/VehVsLinkSpeedTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/VehVsLinkSpeedTest.java index 820914fc323..51d9f80872f 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/VehVsLinkSpeedTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/VehVsLinkSpeedTest.java @@ -39,6 +39,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -128,6 +129,7 @@ public SimpleNetwork(){ config.qsim().setMainModes(Arrays.asList("car")); config.qsim().setLinkDynamics(QSimConfigGroup.LinkDynamics.PassingQ); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.modeVehicleTypesFromVehiclesData); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); network = (Network) scenario.getNetwork(); this.network.setCapacityPeriod(Time.parseTime("1:00:00")); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/VehicleHandlerTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/VehicleHandlerTest.java index 292ae461e58..bfaac4a4eaa 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/VehicleHandlerTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/VehicleHandlerTest.java @@ -43,6 +43,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; @@ -184,6 +185,7 @@ public void handleEvent(PersonArrivalEvent event) { private Scenario createScenario() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setLastIteration(0); config.controller().setOutputDirectory(utils.getOutputDirectory()); diff --git a/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkCleanerTest.java b/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkCleanerTest.java index db870267bcc..b60c8052c73 100644 --- a/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkCleanerTest.java +++ b/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkCleanerTest.java @@ -22,13 +22,18 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; import org.matsim.api.core.v01.network.Node; import org.matsim.core.network.NetworkUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; /** * A very simple test for the NetworkCleaner, it doesn't test by far all possible cases. @@ -189,4 +194,23 @@ void testDoubleSource() { assertEquals(4, network.getLinks().size(), "# links"); } + /** + * This test essentially does the same by modifying the equil scenario. + * Visualization: + * /... ...\ + * ------o------------o------------o----------- + * l1 (n2) l6 (n7) l15 (n12) l20 + */ + @ParameterizedTest + @CsvSource({"6,15", "15,6"}) + void testNetworkCleaner(String removedBefore, String expectedRemovedAfter){ + Network net = NetworkUtils.readNetwork(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("equil"), "network.xml").toString()); + net.removeLink(Id.createLinkId(removedBefore)); + int size = net.getLinks().size(); + + NetworkUtils.runNetworkCleaner(net); + Assertions.assertFalse(net.getLinks().containsKey(Id.createLinkId(expectedRemovedAfter))); + assertEquals(net.getLinks().size(), size - 1); + } + } diff --git a/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkModeRestrictionTest.java b/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkModeRestrictionTest.java new file mode 100644 index 00000000000..92f3bef546f --- /dev/null +++ b/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkModeRestrictionTest.java @@ -0,0 +1,144 @@ +package org.matsim.core.network.algorithms; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +// @formatter:off +/** + * In this test, we restrict the allowed modes of a link. The base case is the equil scenario. + *

+ * /... ...\ + * ------o------------o------------o----------- + * l1 (n2) l6 (n7) l15 (n12) l20 + */ +// @formatter:on +class NetworkModeRestrictionTest { + + /** + * Test that all links and nodes are removed if the network is not connected any more for every mode. + */ + @Test + void testRemoveWholeNetwork() { + Network network = getNetwork(); + + Map, Set> changes = new HashMap<>(); + changes.put(Id.createLinkId(1), Set.of("car","bike")); + + new NetworkModeRestriction(changes).run(network); + + assertTrue(network.getLinks().isEmpty()); + assertTrue(network.getNodes().isEmpty()); + } + + /** + * Test that mode is removed from each node if there is not connected any more for this mode. + */ + @ParameterizedTest + @ValueSource(strings = {"car", "bike"}) + void testRemoveWholeMode(String modeToRemove) { + Network network = getNetwork(); + + int linksBefore = network.getLinks().size(); + int nodesBefore = network.getNodes().size(); + + Map, Set> changes = new HashMap<>(); + changes.put(Id.createLinkId(1), Set.of(modeToRemove)); + + new NetworkModeRestriction(changes).run(network); + + assertEquals(linksBefore, network.getLinks().size()); + assertEquals(nodesBefore, network.getNodes().size()); + + Assertions.assertTrue(network.getLinks().values().stream() + .allMatch(l -> l.getAllowedModes().size() == 1 && l.getAllowedModes().contains(getOtherMode(modeToRemove)))); + } + + /** + * Test that removing a mode from link 6 or 15 also removes it from the other link. + */ + @ParameterizedTest + @CsvSource({"6,car", "6,bike", "15,car", "15,bike"}) + void testRemoveModePartially(int link, String modeToRemove) { + Network network = getNetwork(); + + int linksBefore = network.getLinks().size(); + int nodesBefore = network.getNodes().size(); + + //prepare removal + Map, Set> changes = new HashMap<>(); + changes.put(Id.createLinkId(link), Set.of(modeToRemove)); + + //remove + new NetworkModeRestriction(changes).run(network); + + //links and nodes should all still be there + assertEquals(linksBefore, network.getLinks().size()); + assertEquals(nodesBefore, network.getNodes().size()); + + Set link6Modes = network.getLinks().get(Id.createLinkId(6)).getAllowedModes(); + Set link15Modes = network.getLinks().get(Id.createLinkId(15)).getAllowedModes(); + + //link 6 and 15 should have the mode removed + Assertions.assertEquals(1, link6Modes.size()); + Assertions.assertEquals(1, link15Modes.size()); + Assertions.assertTrue(link6Modes.contains(getOtherMode(modeToRemove))); + Assertions.assertTrue(link15Modes.contains(getOtherMode(modeToRemove))); + } + + /** + * Test that removing each mode from link 6 or 15 also removes both links at all. + */ + @ParameterizedTest + @ValueSource(ints = {6, 15}) + void testRemovePartialNetwork(int link) { + Network network = getNetwork(); + + int linksBefore = network.getLinks().size(); + int nodesBefore = network.getNodes().size(); + + //prepare removal + Map, Set> changes = new HashMap<>(); + changes.put(Id.createLinkId(link), Set.of("car", "bike")); + + //remove + new NetworkModeRestriction(changes).run(network); + + //both links and the node in between should be removed + assertEquals(linksBefore - 2, network.getLinks().size()); + assertEquals(nodesBefore - 1, network.getNodes().size()); + + //check node + Assertions.assertNull(network.getNodes().get(Id.createNodeId(7))); + + //check links + Assertions.assertNull(network.getLinks().get(Id.createLinkId(6))); + Assertions.assertNull(network.getLinks().get(Id.createLinkId(15))); + } + + + private static Network getNetwork() { + Network network = NetworkUtils.readNetwork(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("equil"), "network.xml").toString()); + network.getLinks().values().forEach(l -> l.setAllowedModes(Set.of("car", "bike"))); + return network; + } + + private String getOtherMode(String mode) { + return mode.equals("car") ? "bike" : "car"; + } +} diff --git a/matsim/src/test/java/org/matsim/core/network/io/NetworkReprojectionIOTest.java b/matsim/src/test/java/org/matsim/core/network/io/NetworkReprojectionIOTest.java index 8398f1a7db1..3e0170943e9 100644 --- a/matsim/src/test/java/org/matsim/core/network/io/NetworkReprojectionIOTest.java +++ b/matsim/src/test/java/org/matsim/core/network/io/NetworkReprojectionIOTest.java @@ -32,6 +32,7 @@ import org.matsim.api.core.v01.network.Node; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.Controler; import org.matsim.core.network.NetworkUtils; import org.matsim.core.scenario.ProjectionUtils; @@ -119,6 +120,7 @@ void testWithControlerAndAttributes() { new NetworkWriter( initialNetwork ).write( networkFile ); final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.network().setInputFile( networkFile ); // web mercator. This would be a pretty silly choice for simulation, @@ -171,6 +173,7 @@ void testWithControlerAndConfigParameters() { new NetworkWriter( initialNetwork ).write( networkFile ); final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.network().setInputFile( networkFile ); config.network().setInputCRS( INITIAL_CRS ); diff --git a/matsim/src/test/java/org/matsim/population/algorithms/PersonPrepareForSimTest.java b/matsim/src/test/java/org/matsim/core/population/algorithms/PersonPrepareForSimTest.java similarity index 86% rename from matsim/src/test/java/org/matsim/population/algorithms/PersonPrepareForSimTest.java rename to matsim/src/test/java/org/matsim/core/population/algorithms/PersonPrepareForSimTest.java index baec9afc911..4a5cf91dd6a 100644 --- a/matsim/src/test/java/org/matsim/population/algorithms/PersonPrepareForSimTest.java +++ b/matsim/src/test/java/org/matsim/core/population/algorithms/PersonPrepareForSimTest.java @@ -17,9 +17,10 @@ * * * *********************************************************************** */ -package org.matsim.population.algorithms; +package org.matsim.core.population.algorithms; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.junit.jupiter.api.Assertions; @@ -38,11 +39,13 @@ import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.Population; import org.matsim.api.core.v01.population.PopulationFactory; +import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimImpl; import org.matsim.core.population.PopulationUtils; -import org.matsim.core.population.algorithms.PersonPrepareForSim; -import org.matsim.core.population.algorithms.PlanAlgorithm; +import org.matsim.core.population.routes.NetworkRoute; +import org.matsim.core.population.routes.RouteUtils; import org.matsim.core.router.TripStructureUtils; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.pt.routes.DefaultTransitPassengerRoute; @@ -144,9 +147,7 @@ void testSingleLegTripRoutingMode() { new PersonPrepareForSim(new DummyRouter(), sc).run(person); - Assertions.assertEquals(TransportMode.pt, - TripStructureUtils.getRoutingMode(leg), - "wrong routing mode!"); + Assertions.assertEquals(TransportMode.pt, TripStructureUtils.getRoutingMode(leg),"wrong routing mode!"); } // test routing mode set @@ -167,9 +168,7 @@ void testSingleLegTripRoutingMode() { new PersonPrepareForSim(new DummyRouter(), sc).run(person); - Assertions.assertEquals(TransportMode.pt, - TripStructureUtils.getRoutingMode(leg), - "wrong routing mode!"); + Assertions.assertEquals(TransportMode.pt, TripStructureUtils.getRoutingMode(leg),"wrong routing mode!"); } } @@ -203,10 +202,7 @@ void testSingleFallbackModeLegTrip() { person.addPlan(plan); pop.addPerson(person); - try { - new PersonPrepareForSim(new DummyRouter(), sc).run(person); - Assertions.fail("expected Exception, got none."); - } catch (RuntimeException expected) {} + Assertions.assertThrows(RuntimeException.class, () -> new PersonPrepareForSim(new DummyRouter(), sc).run(person)); } // test outdated fallback mode single leg trip (arbitrary drt mode) @@ -228,9 +224,7 @@ void testSingleFallbackModeLegTrip() { new PersonPrepareForSim(new DummyRouter(), sc).run(person); Assertions.assertEquals("drt67_fallback", leg.getMode(), "wrong leg mode replacement"); - Assertions.assertEquals("drt67_fallback", - TripStructureUtils.getRoutingMode(leg), - "wrong routing mode set"); + Assertions.assertEquals("drt67_fallback", TripStructureUtils.getRoutingMode(leg),"wrong routing mode set"); } } @@ -368,6 +362,9 @@ void testRoutingModeConsistency() { Population pop = sc.getPopulation(); // test trip with inconsistent routing modes causes exception + // modes: walk - drt - walk + // routing modes: pt - drt - drt + // expected behaviour: throws RuntimeException, because routing modes are inconsistent { PopulationFactory pf = pop.getFactory(); Person person = pf.createPerson(Id.create("3", Person.class)); @@ -392,13 +389,13 @@ void testRoutingModeConsistency() { person.addPlan(plan); pop.addPerson(person); - try { - new PersonPrepareForSim(new DummyRouter(), sc).run(person); - Assertions.fail("expected Exception, got none."); - } catch (RuntimeException expected) {} + Assertions.assertThrows(RuntimeException.class, () -> new PersonPrepareForSim(new DummyRouter(), sc).run(person)); } // test trip with legs with and others without routing modes causes exception + // modes: walk - drt - walk + // routing modes: null - drt - drt + // expected behaviour: throws RuntimeException, because routing modes are inconsistent { PopulationFactory pf = pop.getFactory(); Person person = pf.createPerson(Id.create("4", Person.class)); @@ -423,10 +420,7 @@ void testRoutingModeConsistency() { person.addPlan(plan); pop.addPerson(person); - try { - new PersonPrepareForSim(new DummyRouter(), sc).run(person); - Assertions.fail("expected Exception, got none."); - } catch (RuntimeException expected) {} + Assertions.assertThrows(RuntimeException.class, () -> new PersonPrepareForSim(new DummyRouter(), sc).run(person)); } } @@ -478,13 +472,76 @@ void testReplaceExperimentalTransitRoute() { Assertions.assertEquals(route, ((DefaultTransitPassengerRoute) leg.getRoute()).getRouteId()); } + @Test + void testLegRouteModeConsistency_throws() { + // set config, such that exception is thrown due to inconsistency + Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.abortOnInconsistency); + Scenario scenario = ScenarioUtils.createScenario(config); + Person person = createInconsistentPersonForModeConsistencyCheck(scenario); + + // check exception + Assertions.assertThrows(RuntimeException.class, () -> new PersonPrepareForSim(new DummyRouter(), scenario).run(person)); + } + + @Test + void testLegRouteModeConsistency_ignored() { + // set config, such that inconsistency is ignored + Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + Scenario scenario = ScenarioUtils.createScenario(config); + Person person = createInconsistentPersonForModeConsistencyCheck(scenario); + + DummyRouter router = new DummyRouter(); + new PersonPrepareForSim(router, scenario).run(person); + // check no router call + Assertions.assertEquals(0, router.getCounter()); + } + + /** + * Creates a person with one leg, that has mode pt, but route goes over link with only mode car. + */ + private Person createInconsistentPersonForModeConsistencyCheck(Scenario scenario) { + createAndAddNetwork(scenario); + + Population pop = scenario.getPopulation(); + PopulationFactory pf = pop.getFactory(); + Person person = pf.createPerson(Id.create("1", Person.class)); + Plan plan = pf.createPlan(); + + Id l1Id = Id.createLinkId("1"); + Activity act1 = pf.createActivityFromLinkId("home", l1Id); + // Leg mode is pt, but route goes over links with car mode + Leg leg = pf.createLeg(TransportMode.pt); + NetworkRoute route = RouteUtils.createLinkNetworkRouteImpl(l1Id, List.of(l1Id), l1Id); + leg.setRoute(route); + Activity act2 = pf.createActivityFromLinkId("home", l1Id); + plan.addActivity(act1); + plan.addLeg(leg); + plan.addActivity(act2); + person.addPlan(plan); + return person; + } + private static class DummyRouter implements PlanAlgorithm { + private int counter = 0; @Override public void run(final Plan plan) { + counter++; + } + + public int getCounter() { + return counter; } } - private Link createAndAddNetwork(Scenario sc) { + /** + * Creates Network: + * (n1)---l1---(n2)---l2---(n3) + * l1 modes: car + * l2 modes: pt + */ + private void createAndAddNetwork(Scenario sc) { Network net = sc.getNetwork(); Link link1; { @@ -506,6 +563,5 @@ private Link createAndAddNetwork(Scenario sc) { net.addLink(link1); net.addLink(l2); } - return link1; } } diff --git a/matsim/src/test/java/org/matsim/core/router/FallbackRoutingModuleTest.java b/matsim/src/test/java/org/matsim/core/router/FallbackRoutingModuleTest.java index b2654bc7734..ecfb14eefe0 100644 --- a/matsim/src/test/java/org/matsim/core/router/FallbackRoutingModuleTest.java +++ b/matsim/src/test/java/org/matsim/core/router/FallbackRoutingModuleTest.java @@ -20,6 +20,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.ReplanningConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; import org.matsim.core.replanning.strategies.DefaultPlanStrategiesModule; @@ -33,6 +34,7 @@ public class FallbackRoutingModuleTest{ void calcRoute(){ Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setOutputDirectory( utils.getOutputDirectory() ); config.controller().setLastIteration( 1 ); diff --git a/matsim/src/test/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModuleTest.java b/matsim/src/test/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModuleTest.java index 392a301d1c4..6781d0872d2 100644 --- a/matsim/src/test/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModuleTest.java +++ b/matsim/src/test/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModuleTest.java @@ -181,6 +181,7 @@ private static List> getNetworkRoute(List elements) { void calcRoute_modeVehiclesFromVehiclesData_differentTypesTakeDifferentRoutes() { Config config = createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); // set test specific things Collection modes = Arrays.asList(SLOW_MODE, FAST_MODE); @@ -234,6 +235,7 @@ void calcRoute_modeVehiclesFromVehiclesData_differentTypesTakeDifferentRoutes() void calcRoute_defaultVehicle_defaultVehicleIsAssigned() { Config config = createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.defaultVehicle); Scenario scenario = createScenario(config); @@ -266,7 +268,8 @@ void useAccessEgressTimeFromLinkAttributes() { Config config = createConfig(); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.defaultVehicle); config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.walkConstantTimeToLink); - Scenario scenario = createScenario(config); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + Scenario scenario = createScenario(config); NetworkUtils.setLinkAccessTime(scenario.getNetwork().getLinks().get(Id.createLinkId(START_LINK)),TransportMode.car,75); NetworkUtils.setLinkEgressTime(scenario.getNetwork().getLinks().get(Id.createLinkId(END_LINK)),TransportMode.car,180); // add persons @@ -285,6 +288,7 @@ void useAccessEgressTimeFromLinkAttributes() { void useAccessEgressTimeFromConstantAndWalkTime() { Config config = createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.defaultVehicle); config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.accessEgressModeToLinkPlusTimeConstant); Scenario scenario = createScenario(config); @@ -308,6 +312,7 @@ void useAccessEgressTimeFromConstantAndWalkTime() { void routingModeInEvents() { Config config = createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.defaultVehicle); config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.accessEgressModeToLinkPlusTimeConstant); Scenario scenario = createScenario(config); @@ -352,6 +357,7 @@ void failifNoAccessTimeSet() { Config config = createConfig(); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.defaultVehicle); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.walkConstantTimeToLink); Scenario scenario = createScenario(config); NetworkUtils.setLinkAccessTime(scenario.getNetwork().getLinks().get(Id.createLinkId(START_LINK)), TransportMode.car, 75); @@ -385,6 +391,7 @@ void calcAccessTimeFromDistanceToLink() { Config config = createConfig(); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.defaultVehicle); config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.accessEgressModeToLink); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = createScenario(config); NetworkUtils.setLinkAccessTime(scenario.getNetwork().getLinks().get(Id.createLinkId(START_LINK)),TransportMode.car,75); NetworkUtils.setLinkAccessTime(scenario.getNetwork().getLinks().get(Id.createLinkId(END_LINK)),TransportMode.car,180); @@ -410,6 +417,7 @@ void noBushwackingLegs() { Config config = createConfig(); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.defaultVehicle); config.routing().setAccessEgressType(AccessEgressType.none); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = createScenario(config); NetworkUtils.setLinkAccessTime(scenario.getNetwork().getLinks().get(Id.createLinkId(START_LINK)),TransportMode.car,75); NetworkUtils.setLinkAccessTime(scenario.getNetwork().getLinks().get(Id.createLinkId(END_LINK)),TransportMode.car,180); diff --git a/matsim/src/test/java/org/matsim/core/router/PseudoTransitRoutingModuleTest.java b/matsim/src/test/java/org/matsim/core/router/PseudoTransitRoutingModuleTest.java index 74f366f4864..60a48326aeb 100644 --- a/matsim/src/test/java/org/matsim/core/router/PseudoTransitRoutingModuleTest.java +++ b/matsim/src/test/java/org/matsim/core/router/PseudoTransitRoutingModuleTest.java @@ -37,6 +37,7 @@ import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.PlanElement; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.RoutingConfigGroup.TeleportedModeParams; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.ControlerDefaultsModule; @@ -135,6 +136,7 @@ private static class Fixture { public Fixture() { s.getConfig().controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + s.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); TeleportedModeParams walk = new TeleportedModeParams(TransportMode.walk); walk.setBeelineDistanceFactor(1.3); walk.setTeleportedModeSpeed(3.0 / 3.6); diff --git a/matsim/src/test/java/org/matsim/core/router/TripRouterFactoryImplTest.java b/matsim/src/test/java/org/matsim/core/router/TripRouterFactoryImplTest.java index d2a23b546a1..bd671737a31 100644 --- a/matsim/src/test/java/org/matsim/core/router/TripRouterFactoryImplTest.java +++ b/matsim/src/test/java/org/matsim/core/router/TripRouterFactoryImplTest.java @@ -66,6 +66,7 @@ public class TripRouterFactoryImplTest { void testRestrictedNetworkNoPt() throws Exception { Config config = ConfigUtils.createConfig(); config.transit().setUseTransit( false ); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); testRestrictedNetwork( config ); } @@ -153,6 +154,7 @@ public void install() { @Test void testMonomodalNetwork() throws Exception { final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); final Scenario scenario = ScenarioUtils.createScenario( config ); Network net = scenario.getNetwork(); diff --git a/matsim/src/test/java/org/matsim/core/scoring/EventsToScoreTest.java b/matsim/src/test/java/org/matsim/core/scoring/EventsToScoreTest.java index d7390a8bf70..8462f81ed19 100644 --- a/matsim/src/test/java/org/matsim/core/scoring/EventsToScoreTest.java +++ b/matsim/src/test/java/org/matsim/core/scoring/EventsToScoreTest.java @@ -23,17 +23,39 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.events.PersonDepartureEvent; import org.matsim.api.core.v01.events.PersonMoneyEvent; +import org.matsim.api.core.v01.events.handler.PersonDepartureEventHandler; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.network.Node; import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.Population; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.ReplanningConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; +import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controler; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.controler.events.IterationEndsEvent; +import org.matsim.core.controler.events.IterationStartsEvent; +import org.matsim.core.controler.listener.IterationEndsListener; +import org.matsim.core.controler.listener.IterationStartsListener; import org.matsim.core.events.EventsUtils; +import org.matsim.core.mobsim.framework.events.MobsimBeforeCleanupEvent; +import org.matsim.core.mobsim.framework.events.MobsimInitializedEvent; +import org.matsim.core.mobsim.framework.listeners.MobsimBeforeCleanupListener; +import org.matsim.core.mobsim.framework.listeners.MobsimInitializedListener; +import org.matsim.core.mobsim.qsim.AbstractQSimModule; import org.matsim.core.population.PopulationUtils; +import org.matsim.core.replanning.strategies.DefaultPlanStrategiesModule; import org.matsim.core.scenario.MutableScenario; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.scoring.functions.CharyparNagelScoringFunctionFactory; @@ -158,6 +180,119 @@ void testMsaAveraging() { } } + @Test + void testMsaAveragingWithController() { + Config config = ConfigUtils.createConfig() ; + config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.overwriteExistingFiles); + + config.controller().setFirstIteration(10); + config.controller().setLastIteration(110); + + config.scoring().setMarginalUtilityOfMoney(1.); + config.scoring().setFractionOfIterationsToStartScoreMSA(0.9); + + ReplanningConfigGroup.StrategySettings strat = new ReplanningConfigGroup.StrategySettings(); + strat.setStrategyName(DefaultPlanStrategiesModule.DefaultSelector.KeepLastSelected); + strat.setWeight(1.); + config.replanning().addStrategySettings(strat); + + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + + Scenario scenario = ScenarioUtils.createScenario(config); + + Network network = scenario.getNetwork(); + Node node0 = network.getFactory().createNode(Id.createNodeId(0), new Coord(0, 0)); + Node node1 = network.getFactory().createNode(Id.createNodeId(1), new Coord(1, 0)); + network.addNode(node0); + network.addNode(node1); + Link link01 = network.getFactory().createLink(Id.createLinkId("0_1"), node0, node1); + network.addLink(link01); + + Population population = scenario.getPopulation(); + Person person = PopulationUtils.getFactory().createPerson(Id.create(1, Person.class)); + population.addPerson(person); + Plan plan = PopulationUtils.createPlan() ; + plan.addActivity(population.getFactory().createActivityFromLinkId("dummy", link01.getId())); + person.addPlan(plan); + + ScoringConfigGroup.ActivityParams dummyAct = new ScoringConfigGroup.ActivityParams("dummy"); + dummyAct.setScoringThisActivityAtAll(false); + config.scoring().addActivityParams(dummyAct); + + Controler controler = new Controler(scenario); + EventsManager events = controler.getEvents(); + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + final int[] iteration = new int[1]; + this.addControlerListenerBinding().toInstance(new IterationStartsListener() { + @Override + public void notifyIterationStarts(IterationStartsEvent event) { + iteration[0] = event.getIteration(); + } + }); + this.addMobsimListenerBinding().toInstance(new MobsimInitializedListener() { + @Override + public void notifyMobsimInitialized(MobsimInitializedEvent e) { + events.processEvent(new PersonMoneyEvent(3600.0, person.getId(), iteration[0] -98, "bribe", "contractor" )); + } + }); + } + }); + controler.addControlerListener(new IterationEndsListener() { + @Override + public void notifyIterationEnds(IterationEndsEvent event) { + System.out.println( "score: " + person.getSelectedPlan().getScore() ) ; + + switch(event.getIteration()){ + case 99: + Assertions.assertEquals(1.0, person.getSelectedPlan().getScore(), 0); + break ; + case 100: + // first MSA iteration; plain score should be ok: + Assertions.assertEquals(2.0, person.getSelectedPlan().getScore(), 0); + break ; + case 101: + // second MSA iteration + // (2+3)/2 = 2.5 + Assertions.assertEquals(2.5, person.getSelectedPlan().getScore(), 0); + break ; + case 102: + // 3rd MSA iteration + // (2+3+4)/3 = 3 + Assertions.assertEquals(3.0, person.getSelectedPlan().getScore(), 0); + break ; + case 103: + // (2+3+4+5)/4 = 3.5 + Assertions.assertEquals(3.5, person.getSelectedPlan().getScore(), 0); + break ; + case 104: + Assertions.assertEquals(4.0, person.getSelectedPlan().getScore(), 0); + break ; + case 105: + Assertions.assertEquals(4.5, person.getSelectedPlan().getScore(), 0); + break ; + case 106: + Assertions.assertEquals(5.0, person.getSelectedPlan().getScore(), 0); + break ; + case 107: + Assertions.assertEquals(5.5, person.getSelectedPlan().getScore(), 0); + break ; + case 108: + Assertions.assertEquals(6.0, person.getSelectedPlan().getScore(), 0); + break ; + case 109: + Assertions.assertEquals(6.5, person.getSelectedPlan().getScore(), 0); + break ; + case 110: + Assertions.assertEquals(7.0, person.getSelectedPlan().getScore(), 0); + break ; + } + } + }); + controler.run(); + } + private static class MockScoringFunctionFactory implements ScoringFunctionFactory { @Override diff --git a/matsim/src/test/java/org/matsim/core/utils/timing/TimeInterpretationTest.java b/matsim/src/test/java/org/matsim/core/utils/timing/TimeInterpretationTest.java index d771d585de9..497f1233891 100644 --- a/matsim/src/test/java/org/matsim/core/utils/timing/TimeInterpretationTest.java +++ b/matsim/src/test/java/org/matsim/core/utils/timing/TimeInterpretationTest.java @@ -39,6 +39,7 @@ import org.matsim.api.core.v01.population.PopulationFactory; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.config.groups.PlansConfigGroup.TripDurationHandling; import org.matsim.core.controler.Controler; @@ -55,6 +56,7 @@ public class TimeInterpretationTest { @Test void testIgnoreDelays() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.plans().setTripDurationHandling(TripDurationHandling.ignoreDelays); Controler controller = prepareController(config); @@ -76,6 +78,7 @@ void testIgnoreDelays() { @Test void testShiftActivityEndTime() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.plans().setTripDurationHandling(TripDurationHandling.shiftActivityEndTimes); Controler controller = prepareController(config); diff --git a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java new file mode 100644 index 00000000000..dee40f8f38d --- /dev/null +++ b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java @@ -0,0 +1,392 @@ +package org.matsim.examples; + +import com.google.common.collect.Lists; +import com.google.inject.ProvisionException; +import com.google.inject.spi.Message; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.events.LinkEnterEvent; +import org.matsim.api.core.v01.events.LinkLeaveEvent; +import org.matsim.api.core.v01.events.PersonEntersVehicleEvent; +import org.matsim.api.core.v01.events.PersonLeavesVehicleEvent; +import org.matsim.api.core.v01.events.handler.LinkEnterEventHandler; +import org.matsim.api.core.v01.events.handler.LinkLeaveEventHandler; +import org.matsim.api.core.v01.events.handler.PersonEntersVehicleEventHandler; +import org.matsim.api.core.v01.events.handler.PersonLeavesVehicleEventHandler; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.population.Activity; +import org.matsim.api.core.v01.population.Leg; +import org.matsim.api.core.v01.population.Person; +import org.matsim.core.config.Config; +import org.matsim.core.config.groups.RoutingConfigGroup; +import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controler; +import org.matsim.core.events.EventsUtils; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.population.PopulationUtils; +import org.matsim.core.router.util.TravelTime; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; +import org.matsim.vehicles.Vehicle; + +import java.util.*; +import java.util.stream.Stream; + +// @formatter:off +/** + * In this test, we restrict the allowed modes of a link. The base case is the equil scenario. + *

+ * /... ...\ + * ------o------------o------------o----------- + * l1 (n2) l6 (n7) l15 (n12) l20 + */ +// @formatter:on +public class ModeRestrictionTest { + @RegisterExtension + private MatsimTestUtils utils = new MatsimTestUtils(); + + static Stream intersectLinkAndMode() { + List links = List.of("6", "15", "20"); + List restrictedModes = List.of("car", "bike"); + + return links.stream() + .flatMap(link -> restrictedModes.stream().map(restrictedMode -> Arguments.of(link, restrictedMode))); + } + + /** + * Setting: The agents (both car & bike) have a route from the plan. Link before and at the activity is restricted respectively. Consistency check is turned off. + * Expected behaviour: Since it is not checked, if the route contains link, which are not allowed to use anymore, it can still use the restricted link. + */ + @ParameterizedTest + @MethodSource("intersectLinkAndMode") + void testNoRouteChange_noConsistencyCheck_ok(String link, String restrictedMode) { + final Config config = prepareConfig("plans_act_link20.xml", RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + + Id linkId = Id.createLinkId(link); + Scenario scenario = ScenarioUtils.loadScenario(config); + Link networkLink = scenario.getNetwork().getLinks().get(linkId); + removeModeFromLink(networkLink, restrictedMode); + + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck( + Map.of(Id.createPersonId("car"), List.of(linkId), Id.createPersonId("bike"), List.of(linkId))); + runController(scenario, firstLegRouteCheck); + firstLegRouteCheck.assertActualContainsExpected(); + assertEventFilesSame(); + } + + /** + * Setting: The agents (both car & bike) have a route from the plan. Link before and at the activity is restricted respectively. Consistency check is turned on. + * Expected behaviour: An exception is thrown because the route is inconsistent and this is checked. + */ + @ParameterizedTest + @MethodSource("intersectLinkAndMode") + void testNoRouteChange_withConsistencyCheck_throws(String link, String restrictedMode) { + final Config config = prepareConfig("plans_act_link20.xml", RoutingConfigGroup.NetworkRouteConsistencyCheck.abortOnInconsistency); + + Id linkId = Id.createLinkId(link); + Scenario scenario = ScenarioUtils.loadScenario(config); + Link networkLink = scenario.getNetwork().getLinks().get(linkId); + removeModeFromLink(networkLink, restrictedMode); + + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(); + RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runController(scenario, firstLegRouteCheck)); + Assertions.assertInstanceOf(ProvisionException.class, exception); + Assertions.assertTrue(((ProvisionException) exception).getErrorMessages().stream() + .map(Message::getMessage) + .anyMatch(m -> m.equals("java.lang.RuntimeException: Network for mode '" + restrictedMode + "' has unreachable links and nodes. This may be caused by mode restrictions on certain links. Aborting."))); + } + + /** + * Setting: The agents (both car & bike) have no route. The mode of the link in front of the activity is restricted. Consistency check is turned off. + * Expected behaviour: By default, the network is not cleaned. The router throws an exception since there is no route from home to the activity. + */ + @ParameterizedTest + @ValueSource(strings = {"car", "bike"}) + void testRerouteBeforeSim_toActNotPossible_throws(String restrictedMode) { + final Config config = prepareConfig("plans_act_link15.xml", RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + + Id link = Id.createLinkId("6"); + + Scenario scenario = restrictLinkAndResetRoutes(config, link, restrictedMode); + + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(); + RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runController(scenario, firstLegRouteCheck)); + + //we can't check the root exception because the check is done in another thread. So we check for the more general exception. + Assertions.assertTrue( + exception.getMessage().contains("Exception while processing persons. Cannot guarantee that all persons have been fully processed.")); + } + + /** + * Setting: The agents (both car & bike) have no route. The mode of the link behind the activity is restricted. Consistency check is turned off. + * Expected behaviour: By default, the network is not cleaned. The router throws an exception since there is no route from the activity to home. + */ + @ParameterizedTest + @ValueSource(strings = {"car", "bike"}) + void testRerouteBeforeSim_fromActNotPossible_throws(String restrictedMode) { + final Config config = prepareConfig("plans_act_link6.xml", RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + + Id link = Id.createLinkId("15"); + + Scenario scenario = restrictLinkAndResetRoutes(config, link, restrictedMode); + + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(); + RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runController(scenario, firstLegRouteCheck)); + + //we can't check the root exception because the check is done in another thread. So we check for the more general exception. + Assertions.assertTrue( + exception.getMessage().contains("Exception while processing persons. Cannot guarantee that all persons have been fully processed.")); + } + + /** + * Setting: Network and routes are cleaned before simulation. Link before the activity is restricted. Consistency check is turned off. + * Expected behaviour: The agent using the restricted are mode is rerouted. The new link of the activity for this agent is the one which is closest to the activity. + */ + @ParameterizedTest + @ValueSource(strings = {"car", "bike"}) + void testCleanNetworkAndRerouteBeforeSim_toActNotPossible_withConsistencyCheck_ok(String restrictedMode){ + final Config config = prepareConfig("plans_act_link15.xml", RoutingConfigGroup.NetworkRouteConsistencyCheck.abortOnInconsistency); + + Id link = Id.createLinkId("6"); + + Scenario scenario = ScenarioUtils.loadScenario(config); + NetworkUtils.restrictModesAndCleanNetwork(scenario.getNetwork(), l -> Map.of(link, Set.of(restrictedMode)).getOrDefault(l, Set.of())); + PopulationUtils.checkRouteModeAndReset(scenario.getPopulation(), scenario.getNetwork()); + + // New route. Note that the end link is 20, but the activity's link in the input was 15. + // But since we restricted the mode for link 6 AND 15, 20 is used as fallback. + List> newRoute = List.of(Id.createLinkId("1"), Id.createLinkId("2"), Id.createLinkId("11"), Id.createLinkId("20")); + List> oldRoute = List.of(Id.createLinkId("1"), Id.createLinkId("6"), Id.createLinkId("15")); + + String other = restrictedMode.equals("car") ? "bike" : "car"; + + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(Map.of(Id.createPersonId(restrictedMode), newRoute, Id.createPersonId(other), oldRoute)); + runController(scenario, firstLegRouteCheck); + firstLegRouteCheck.assertActualEqualsExpected(); + assertEventFilesSame(); + } + + /** + * Setting: Network and routes are cleaned before simulation. Link from the activity is restricted. Consistency check is turned off. + * Expected behaviour: The agent using the restricted are mode is rerouted. The new link of the activity for this agent is the one which is closest to the activity. + */ + @ParameterizedTest + @ValueSource(strings = {"car", "bike"}) + void testCleanNetworkAndRerouteBeforeSim_fromActNotPossible_withConsistencyCheck_ok(String restrictedMode){ + final Config config = prepareConfig("plans_act_link6.xml", RoutingConfigGroup.NetworkRouteConsistencyCheck.abortOnInconsistency); + + Id link = Id.createLinkId("15"); + + Scenario scenario = ScenarioUtils.loadScenario(config); + NetworkUtils.restrictModesAndCleanNetwork(scenario.getNetwork(), l -> Map.of(link, Set.of(restrictedMode)).getOrDefault(l, Set.of())); + PopulationUtils.checkRouteModeAndReset(scenario.getPopulation(), scenario.getNetwork()); + + // New route. Note that the end link is 20, but the activity's link in the input was 6. + // But since we restricted the mode for link 6 AND 15, 20 is used as fallback. + List> newRoute = List.of(Id.createLinkId("1"), Id.createLinkId("2"), Id.createLinkId("11"), Id.createLinkId("20")); + List> oldRoute = List.of(Id.createLinkId("1"), Id.createLinkId("6")); + + String other = restrictedMode.equals("car") ? "bike" : "car"; + + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(Map.of(Id.createPersonId(restrictedMode), newRoute, Id.createPersonId(other), oldRoute)); + runController(scenario, firstLegRouteCheck); + firstLegRouteCheck.assertActualEqualsExpected(); + assertEventFilesSame(); + } + + /** + * Setting: The agents (both car & bike) have no route. The mode of the activity's link is restricted. Activity has x-y-coordinate. Consistency check is turned off. + * Expected behaviour: The agents (both car & bike) are rerouted to the nearest link to the activity's coordinate. + */ + @ParameterizedTest + @ValueSource(strings = {"car", "bike"}) + void testRerouteBeforeSim_actOnRestrictedLinkWithCoords_ok(String restrictedMode) { + final Config config = prepareConfig("plans_act_link15.xml", RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + + Scenario scenario = restrictLinkAndResetRoutes(config, Id.createLinkId("15"), restrictedMode); + + // New route. Note that the end link is 20, but the activity's link in the input was 15. + // But since we restricted the mode for link 15, 20 is used as fallback. + List> newRoute = List.of(Id.createLinkId("1"), Id.createLinkId("2"), Id.createLinkId("11"), Id.createLinkId("20")); + List> oldRoute = List.of(Id.createLinkId("1"), Id.createLinkId("6"), Id.createLinkId("15")); + + String other = restrictedMode.equals("car") ? "bike" : "car"; + + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(Map.of(Id.createPersonId(restrictedMode), newRoute, Id.createPersonId(other), oldRoute)); + runController(scenario, firstLegRouteCheck); + firstLegRouteCheck.assertActualEqualsExpected(); + assertEventFilesSame(); + } + + /** + * Setting: The agents (both car & bike) have no route. The mode of the activity's link is restricted. Activity has no x-y-coordinate. Consistency check is turned off. + * Expected behaviour: The router throws an exception since there is no fallback x-y-coordinate. + */ + @ParameterizedTest + @ValueSource(strings = {"car", "bike"}) + void testRerouteBeforeSim_actOnRestrictedLinkWithoutCoord_throws(String restrictedMode){ + final Config config = prepareConfig("plans_act_link15.xml", RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + + Id person = Id.createPersonId(restrictedMode); + Scenario scenario = restrictLinkAndResetRoutes(config, Id.createLinkId("15"), restrictedMode); + Activity act = (Activity) scenario.getPopulation().getPersons().get(person).getPlans().getFirst().getPlanElements().get(2); + act.setCoord(null); + + RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runController(scenario, new FirstLegVisitedLinksCheck())); + + //we can't check the root exception because the check is done in another thread. So we check for the more general exception. + Assertions.assertTrue( + exception.getMessage().contains("Exception while processing persons. Cannot guarantee that all persons have been fully processed.")); + } + + private Config prepareConfig(String plansFile, RoutingConfigGroup.NetworkRouteConsistencyCheck consistencyCheck) { + final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml", MatsimTestUtils.TestMethodType.Parameterized); + config.routing().setNetworkRouteConsistencyCheck(consistencyCheck); + config.plans().setInputFile(plansFile); + + ScoringConfigGroup.ModeParams params = new ScoringConfigGroup.ModeParams("bike") ; + config.scoring().addModeParams(params); + + config.qsim().setMainModes( new HashSet<>( Arrays.asList( TransportMode.car, TransportMode.bike ) ) ) ; + config.routing().setNetworkModes( Arrays.asList( TransportMode.car, TransportMode.bike ) ); + config.routing().removeTeleportedModeParams("bike"); + config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.accessEgressModeToLink); + + config.controller().setLastIteration(0); + return config; + } + + private static Scenario restrictLinkAndResetRoutes(Config config, Id link, String restrictedMode) { + Scenario scenario = ScenarioUtils.loadScenario(config); + removeModeFromLink(scenario.getNetwork().getLinks().get(link), restrictedMode); + for (Person person : scenario.getPopulation().getPersons().values()) { + Leg leg = (Leg) person.getSelectedPlan().getPlanElements().get(1); + leg.setRoute(null); + } + return scenario; + } + + private static void runController(Scenario scenario, FirstLegVisitedLinksCheck firstLegRouteCheck) { + Controler controler = new Controler(scenario); + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + this.addEventHandlerBinding().toInstance(firstLegRouteCheck); + this.addTravelTimeBinding(TransportMode.bike).to(BikeTravelTime.class); + } + }); + controler.run(); + } + + private static void removeModeFromLink(Link networkLink, String restrictedMode) { + Set allowedModes = new HashSet<>(networkLink.getAllowedModes()); + allowedModes.remove(restrictedMode); + networkLink.setAllowedModes(allowedModes); + } + + /** + * Event handler that checks the visited Links of a person on the first leg. + */ + private static class FirstLegVisitedLinksCheck implements LinkEnterEventHandler, LinkLeaveEventHandler, PersonEntersVehicleEventHandler, + PersonLeavesVehicleEventHandler { + private final Map, List>> expected = new HashMap<>(); + private final Map, List>> actual = new HashMap<>(); + private final Map, Id> currentPersonByVehicle = new HashMap<>(); + private final Map, Boolean> onFirstLeg = new HashMap<>(); + + public FirstLegVisitedLinksCheck() { + } + + public FirstLegVisitedLinksCheck(Map, List>> expected) { + this.expected.putAll(expected); + } + + public FirstLegVisitedLinksCheck(Id personId, List> expected) { + this.expected.put(personId, expected); + } + + public FirstLegVisitedLinksCheck(Id personId, Id expected) { + this.expected.put(personId, Collections.singletonList(expected)); + } + + @Override + public void handleEvent(LinkLeaveEvent event) { + addLinkIdToActual(this.currentPersonByVehicle.get(event.getVehicleId()), event.getLinkId()); + } + + @Override + public void handleEvent(LinkEnterEvent event) { + addLinkIdToActual(this.currentPersonByVehicle.get(event.getVehicleId()), event.getLinkId()); + } + + @Override + public void handleEvent(PersonLeavesVehicleEvent event) { + this.currentPersonByVehicle.remove(event.getVehicleId()); + this.onFirstLeg.put(event.getPersonId(), false); + } + + @Override + public void handleEvent(PersonEntersVehicleEvent event) { + this.currentPersonByVehicle.put(event.getVehicleId(), event.getPersonId()); + this.onFirstLeg.putIfAbsent(event.getPersonId(), true); + } + + private void addLinkIdToActual(Id personId, Id linkId) { + if (!this.onFirstLeg.get(personId)) { + return; + } + actual.putIfAbsent(personId, Lists.newArrayList(linkId)); + List> linkIds = actual.get(personId); + if (linkIds.getLast() == null || linkIds.getLast() == linkId) { + return; + } + linkIds.add(linkId); + } + + public void assertActualEqualsExpected() { + Assertions.assertEquals(expected, actual); + } + + public void assertActualContainsExpected() { + for (Map.Entry, List>> entry : expected.entrySet()) { + Id personId = entry.getKey(); + List> expected = entry.getValue(); + List> actual = this.actual.get(personId); + Assertions.assertNotNull(actual); + Assertions.assertTrue(actual.containsAll(expected)); + } + } + } + + + private static class BikeTravelTime implements TravelTime { + @Override public double getLinkTravelTime( Link link, double time, Person person, Vehicle vehicle ){ + return 1. ; + } + } + + /** + * Note that this method alone would be sufficient to check the simulation behaviour. But since I have already written the eventHandler, I will use it as well. + * If at some point it is too nervig, to maintain both test methodologies here, the eventHandler can be removed. + * But, I think it makes clearer what is the relevant thing to check. paul aug '24 + */ + private void assertEventFilesSame() { + String fileName = "output_events.xml.gz"; + + String inputFile = utils.getInputDirectory() + utils.getParameterizedTestInputString() + "/" + fileName; + String outputFile = utils.getOutputDirectory() + "/" + fileName; + + ComparisonResult comparisonResult = EventsUtils.compareEventsFiles(inputFile, outputFile); + if (comparisonResult != ComparisonResult.FILES_ARE_EQUAL) + Assertions.fail("Event files are not equal: " + comparisonResult); + } +} diff --git a/matsim/src/test/java/org/matsim/integration/SimulateAndScoreTest.java b/matsim/src/test/java/org/matsim/integration/SimulateAndScoreTest.java index 9bd875631c0..6c57b14d3ca 100644 --- a/matsim/src/test/java/org/matsim/integration/SimulateAndScoreTest.java +++ b/matsim/src/test/java/org/matsim/integration/SimulateAndScoreTest.java @@ -43,6 +43,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Injector; @@ -89,6 +90,7 @@ public class SimulateAndScoreTest { @Test void testRealPtScore() { final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.transit().setUseTransit(true); ScoringConfigGroup.ActivityParams h = new ScoringConfigGroup.ActivityParams("h"); @@ -240,7 +242,9 @@ public void install() { @Test void testTeleportationScore() { - Scenario scenario = ScenarioUtils.createScenario(ConfigUtils.createConfig()); + Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + Scenario scenario = ScenarioUtils.createScenario(config); Network network = scenario.getNetwork(); Node node1 = network.getFactory().createNode(Id.create("1", Node.class), new Coord(0, 0)); Node node2 = network.getFactory().createNode(Id.create("2", Node.class), new Coord(100, 0)); diff --git a/matsim/src/test/java/org/matsim/integration/invertednetworks/InvertedNetworkRoutingTestFixture.java b/matsim/src/test/java/org/matsim/integration/invertednetworks/InvertedNetworkRoutingTestFixture.java index e63fb5115fa..4a0a6ef92bd 100644 --- a/matsim/src/test/java/org/matsim/integration/invertednetworks/InvertedNetworkRoutingTestFixture.java +++ b/matsim/src/test/java/org/matsim/integration/invertednetworks/InvertedNetworkRoutingTestFixture.java @@ -38,6 +38,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.config.groups.ReplanningConfigGroup.StrategySettings; import org.matsim.core.replanning.strategies.DefaultPlanStrategiesModule; @@ -78,6 +79,7 @@ public class InvertedNetworkRoutingTestFixture { public InvertedNetworkRoutingTestFixture(boolean doCreateModes, boolean doCreateLanes, boolean doCreateSignals) { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setLastIteration(0); config.controller().setLinkToLinkRoutingEnabled(true); config.travelTimeCalculator().setCalculateLinkToLinkTravelTimes(true); diff --git a/matsim/src/test/java/org/matsim/integration/population/NonAlternatingPlanElementsIT.java b/matsim/src/test/java/org/matsim/integration/population/NonAlternatingPlanElementsIT.java index 033857c8a4c..d4caf530dc0 100644 --- a/matsim/src/test/java/org/matsim/integration/population/NonAlternatingPlanElementsIT.java +++ b/matsim/src/test/java/org/matsim/integration/population/NonAlternatingPlanElementsIT.java @@ -37,6 +37,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.groups.FacilitiesConfigGroup; import org.matsim.core.config.groups.PlansConfigGroup.HandlingOfPlansWithoutRoutingMode; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.Controler; import org.matsim.core.network.io.MatsimNetworkReader; import org.matsim.core.population.routes.NetworkRoute; @@ -97,6 +98,7 @@ void test_Controler_QSim_Routechoice_acts() { @Test void test_Controler_QSim_Routechoice_legs() { Config config = this.utils.loadConfig("test/scenarios/equil/config.xml"); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setMobsim("qsim"); config.controller().setLastIteration(10); config.plans().setHandlingOfPlansWithoutRoutingMode(HandlingOfPlansWithoutRoutingMode.useMainModeIdentifier); diff --git a/matsim/src/test/java/org/matsim/integration/replanning/ChangeTripModeIntegrationTest.java b/matsim/src/test/java/org/matsim/integration/replanning/ChangeTripModeIntegrationTest.java index e3d4651b7e0..950434f316d 100644 --- a/matsim/src/test/java/org/matsim/integration/replanning/ChangeTripModeIntegrationTest.java +++ b/matsim/src/test/java/org/matsim/integration/replanning/ChangeTripModeIntegrationTest.java @@ -38,6 +38,7 @@ import org.matsim.api.core.v01.population.Population; import org.matsim.core.config.Config; import org.matsim.core.config.groups.ReplanningConfigGroup.StrategySettings; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Injector; import org.matsim.core.controler.NewControlerModule; @@ -78,6 +79,7 @@ public class ChangeTripModeIntegrationTest { void testStrategyManagerConfigLoaderIntegration() { // setup config final Config config = utils.loadConfig((String)null); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); final MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); final StrategySettings strategySettings = new StrategySettings(Id.create("1", StrategySettings.class)); strategySettings.setStrategyName("ChangeTripMode"); diff --git a/matsim/src/test/java/org/matsim/integration/timevariantnetworks/QSimIntegrationTest.java b/matsim/src/test/java/org/matsim/integration/timevariantnetworks/QSimIntegrationTest.java index 609737eb135..7c0b8b6eac7 100644 --- a/matsim/src/test/java/org/matsim/integration/timevariantnetworks/QSimIntegrationTest.java +++ b/matsim/src/test/java/org/matsim/integration/timevariantnetworks/QSimIntegrationTest.java @@ -50,6 +50,7 @@ import org.matsim.api.core.v01.population.Population; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -82,6 +83,7 @@ public class QSimIntegrationTest { @Test void testFreespeed() { Config config = utils.loadConfig((String)null); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.network().setTimeVariantNetwork(true); Scenario scenario = ScenarioUtils.createScenario(config); @@ -132,6 +134,7 @@ void testCapacity() { final double capacityFactor = 0.5; Config config = utils.loadConfig((String)null); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.network().setTimeVariantNetwork(true); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); @@ -203,6 +206,7 @@ void testZeroCapacity() { final double capacityFactor = 0.0; Config config = utils.loadConfig((String)null); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.network().setTimeVariantNetwork(true); config.qsim().setStartTime(0.0); final double simEndTime = 7200.0; diff --git a/matsim/src/test/java/org/matsim/testcases/MatsimTestUtils.java b/matsim/src/test/java/org/matsim/testcases/MatsimTestUtils.java index 112bcaaddaf..287858329cb 100644 --- a/matsim/src/test/java/org/matsim/testcases/MatsimTestUtils.java +++ b/matsim/src/test/java/org/matsim/testcases/MatsimTestUtils.java @@ -51,6 +51,10 @@ public final class MatsimTestUtils implements BeforeEachCallback, AfterEachCallback { private static final Logger log = LogManager.getLogger(MatsimTestUtils.class); + public enum TestMethodType { + Normal, Parameterized + } + /** * A constant for the exactness when comparing doubles. */ @@ -79,6 +83,7 @@ public final class MatsimTestUtils implements BeforeEachCallback, AfterEachCallb private Class testClass = null; private String testMethodName = null; + private String testDisplayName = null; public MatsimTestUtils() { MatsimRandom.reset(); @@ -88,6 +93,7 @@ public MatsimTestUtils() { public void beforeEach(ExtensionContext extensionContext) { this.testClass = extensionContext.getTestClass().orElseThrow(); this.testMethodName = extensionContext.getRequiredTestMethod().getName(); + this.testDisplayName = extensionContext.getDisplayName(); } @Override @@ -163,37 +169,62 @@ public Config createConfig(URL context) { return config; } - /** - * Loads a configuration from file (or the default config if configfile is null). + * Loads a configuration from file (or the default config if configfile is null) + * and sets the output directory to {classPath}/{methodName}/. For parameterized tests, the output directory is {classPath}/{methodName}/{parameters}/. * * @param configfile The path/filename of a configuration file, or null to load the default configuration. * @return The loaded configuration. */ - public Config loadConfig(final String configfile, final ConfigGroup... customGroups) { + public Config loadConfig(final String configfile, TestMethodType testMethodType, final ConfigGroup... customGroups) { Config config; if (configfile != null) { config = ConfigUtils.loadConfig(configfile, customGroups); } else { config = ConfigUtils.createConfig( customGroups ); } - this.outputDirectory = getOutputDirectory(); - config.controller().setOutputDirectory(this.outputDirectory); - return config; + return setOutputDirectory(config, testMethodType); } - public Config loadConfig(final URL configfile, final ConfigGroup... customGroups) { + public Config loadConfig(final String configfile, final ConfigGroup... customGroups) { + return loadConfig(configfile, TestMethodType.Normal, customGroups); + } + + public Config loadConfig(final URL configfile, TestMethodType testMethodType, final ConfigGroup... customGroups) { Config config; if (configfile != null) { config = ConfigUtils.loadConfig(configfile, customGroups); } else { config = ConfigUtils.createConfig( customGroups ); } - this.outputDirectory = getOutputDirectory(); + return setOutputDirectory(config, testMethodType); + } + + public Config loadConfig(final URL configfile, final ConfigGroup... customGroups) { + return loadConfig(configfile, TestMethodType.Normal, customGroups); + } + + /** + * Sets the output directory to {classPath}/{methodName}/{subDir}. For normal tests, there is no {subDir}. + * For parameterized tests, {subDir} is a slightly adapted test input parameter string (aka display name of JUnit 5). + * E.g.: "[1] car, 6" will be transformed to "car_6". + */ + private Config setOutputDirectory(Config config, TestMethodType testMethodType) { + String subDirectory = switch (testMethodType) { + case Normal -> ""; + case Parameterized -> getParameterizedTestInputString(); + }; + this.outputDirectory = getOutputDirectory(subDirectory); config.controller().setOutputDirectory(this.outputDirectory); return config; } + public String getParameterizedTestInputString() { + String parameters = this.testDisplayName.replaceFirst("^.*?\\]", "").trim(); + parameters = parameters.replaceAll(" ", "").replaceAll("[^a-zA-Z0-9]", "_"); + return parameters; + } + public Config createConfig(final ConfigGroup... customGroups) { Config config = ConfigUtils.createConfig( customGroups ); this.outputDirectory = getOutputDirectory(); diff --git a/matsim/src/test/java/org/matsim/withinday/controller/ExperiencedPlansWriterTest.java b/matsim/src/test/java/org/matsim/withinday/controller/ExperiencedPlansWriterTest.java index bad57d42cc7..e6cc6ff0c15 100644 --- a/matsim/src/test/java/org/matsim/withinday/controller/ExperiencedPlansWriterTest.java +++ b/matsim/src/test/java/org/matsim/withinday/controller/ExperiencedPlansWriterTest.java @@ -38,6 +38,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.ControllerConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; @@ -82,6 +83,7 @@ void testWriteFile() { Config config = ConfigUtils.createConfig(); config.controller().setOutputDirectory(this.utils.getOutputDirectory()); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setEndTime(24 * 3600); diff --git a/matsim/src/test/java/org/matsim/withinday/trafficmonitoring/WithinDayTravelTimeWithNetworkChangeEventsTest.java b/matsim/src/test/java/org/matsim/withinday/trafficmonitoring/WithinDayTravelTimeWithNetworkChangeEventsTest.java index 2b63bbb9f0d..1de5fb1096d 100644 --- a/matsim/src/test/java/org/matsim/withinday/trafficmonitoring/WithinDayTravelTimeWithNetworkChangeEventsTest.java +++ b/matsim/src/test/java/org/matsim/withinday/trafficmonitoring/WithinDayTravelTimeWithNetworkChangeEventsTest.java @@ -43,6 +43,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.ControllerConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; @@ -77,6 +78,7 @@ final void testTTviaMobSimAfterSimStepListener() { String outputDirectory = testUtils.getOutputDirectory() + "output_TTviaMobsimAfterSimStepListener/"; final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setFirstIteration(0); config.controller().setLastIteration(0); diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/config.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/config.xml new file mode 100755 index 00000000000..b61e26d25d8 --- /dev/null +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/config.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/network.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/network.xml new file mode 100644 index 00000000000..e62e521bf50 --- /dev/null +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/network.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link15.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link15.xml new file mode 100644 index 00000000000..72ac9cf223b --- /dev/null +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link15.xml @@ -0,0 +1,37 @@ + + + + + + + + + 1 6 15 + + + + 15 20 21 22 23 1 + + + + + + + + + + bike + + 1 6 15 + + + + + bike + + 15 20 21 22 23 1 + + + + + diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link20.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link20.xml new file mode 100644 index 00000000000..6209ab27a8f --- /dev/null +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link20.xml @@ -0,0 +1,37 @@ + + + + + + + + + 1 6 15 20 + + + + 20 21 22 23 1 + + + + + + + + + + bike + + 1 6 15 20 + + + + + bike + + 20 21 22 23 1 + + + + + diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link6.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link6.xml new file mode 100644 index 00000000000..d8bdcd6ec12 --- /dev/null +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link6.xml @@ -0,0 +1,37 @@ + + + + + + + + + 1 6 + + + + 6 15 20 21 22 23 1 + + + + + + + + + + bike + + 1 6 + + + + + bike + + 6 15 20 21 22 23 1 + + + + + diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_fromActNotPossible_withConsistencyCheck_ok/bike/output_events.xml.gz b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_fromActNotPossible_withConsistencyCheck_ok/bike/output_events.xml.gz new file mode 100644 index 00000000000..b310d236f60 Binary files /dev/null and b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_fromActNotPossible_withConsistencyCheck_ok/bike/output_events.xml.gz differ diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_fromActNotPossible_withConsistencyCheck_ok/car/output_events.xml.gz b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_fromActNotPossible_withConsistencyCheck_ok/car/output_events.xml.gz new file mode 100644 index 00000000000..1bd8331382e Binary files /dev/null and b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_fromActNotPossible_withConsistencyCheck_ok/car/output_events.xml.gz differ diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_toActNotPossible_withConsistencyCheck_ok/bike/output_events.xml.gz b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_toActNotPossible_withConsistencyCheck_ok/bike/output_events.xml.gz new file mode 100644 index 00000000000..42ba2aa5fe1 Binary files /dev/null and b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_toActNotPossible_withConsistencyCheck_ok/bike/output_events.xml.gz differ diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_toActNotPossible_withConsistencyCheck_ok/car/output_events.xml.gz b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_toActNotPossible_withConsistencyCheck_ok/car/output_events.xml.gz new file mode 100644 index 00000000000..02749b188d5 Binary files /dev/null and b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_toActNotPossible_withConsistencyCheck_ok/car/output_events.xml.gz differ diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/15_bike/output_events.xml.gz b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/15_bike/output_events.xml.gz new file mode 100644 index 00000000000..c6c664e79df Binary files /dev/null and b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/15_bike/output_events.xml.gz differ diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/15_car/output_events.xml.gz b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/15_car/output_events.xml.gz new file mode 100644 index 00000000000..c6c664e79df Binary files /dev/null and b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/15_car/output_events.xml.gz differ diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/20_bike/output_events.xml.gz b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/20_bike/output_events.xml.gz new file mode 100644 index 00000000000..c6c664e79df Binary files /dev/null and b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/20_bike/output_events.xml.gz differ diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/20_car/output_events.xml.gz b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/20_car/output_events.xml.gz new file mode 100644 index 00000000000..c6c664e79df Binary files /dev/null and b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/20_car/output_events.xml.gz differ diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/6_bike/output_events.xml.gz b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/6_bike/output_events.xml.gz new file mode 100644 index 00000000000..c6c664e79df Binary files /dev/null and b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/6_bike/output_events.xml.gz differ diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/6_car/output_events.xml.gz b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/6_car/output_events.xml.gz new file mode 100644 index 00000000000..c6c664e79df Binary files /dev/null and b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/6_car/output_events.xml.gz differ diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testRerouteBeforeSim_actOnRestrictedLinkWithCoords_ok/bike/output_events.xml.gz b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testRerouteBeforeSim_actOnRestrictedLinkWithCoords_ok/bike/output_events.xml.gz new file mode 100644 index 00000000000..6db5a801ac3 Binary files /dev/null and b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testRerouteBeforeSim_actOnRestrictedLinkWithCoords_ok/bike/output_events.xml.gz differ diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testRerouteBeforeSim_actOnRestrictedLinkWithCoords_ok/car/output_events.xml.gz b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testRerouteBeforeSim_actOnRestrictedLinkWithCoords_ok/car/output_events.xml.gz new file mode 100644 index 00000000000..b86ec8cdd7e Binary files /dev/null and b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testRerouteBeforeSim_actOnRestrictedLinkWithCoords_ok/car/output_events.xml.gz differ diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/vehicles.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/vehicles.xml new file mode 100644 index 00000000000..f38bea12f30 --- /dev/null +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/vehicles.xml @@ -0,0 +1,35 @@ + + + + + + + bike + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 3f97fb8c5d3..f7866d67c0a 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 2.23.1 - 31.2 + 31.3 0.49.2 1.19.0 7.0.0 @@ -128,7 +128,7 @@ commons-codec commons-codec - 1.17.0 + 1.17.1 org.apache.commons @@ -205,7 +205,7 @@ com.google.errorprone error_prone_annotations - 2.28.0 + 2.29.2 @@ -308,7 +308,7 @@ it.unimi.dsi fastutil - 8.5.13 + 8.5.14 @@ -333,7 +333,7 @@ org.hamcrest hamcrest - 2.2 + 3.0 test @@ -420,7 +420,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.3.0 + 3.3.1 org.apache.maven.plugins