diff --git a/.github/workflows/deploy-dtds.yaml b/.github/workflows/deploy-dtds.yaml index bb48f61d27b..09d94069d76 100644 --- a/.github/workflows/deploy-dtds.yaml +++ b/.github/workflows/deploy-dtds.yaml @@ -1,18 +1,20 @@ name: deploy-dtds-on-website on: - push: - branches: - - master + pull_request: + types: + - closed paths: - - matsim/src/main/resources/dtd + - 'matsim/src/main/resources/dtd/**' jobs: rsync-dtds: + if: github.event.pull_request.merged == true # only if PR closed by merging name: sync DTDs to website runs-on: ubuntu-latest steps: + - uses: actions/checkout@v4 - name: rsync dtds uses: burnett01/rsync-deployments@7.0.1 with: diff --git a/.github/workflows/full-integration.yaml b/.github/workflows/full-integration.yaml index a75ea5767da..2c20cb48d31 100644 --- a/.github/workflows/full-integration.yaml +++ b/.github/workflows/full-integration.yaml @@ -14,7 +14,8 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + os: [ubuntu-latest, windows-latest] + #os: [ubuntu-latest, windows-latest, macos-latest] steps: - name: Prepare git diff --git a/contribs/accessibility/pom.xml b/contribs/accessibility/pom.xml index 73058cefd24..973dc3c5177 100644 --- a/contribs/accessibility/pom.xml +++ b/contribs/accessibility/pom.xml @@ -37,12 +37,12 @@ org.matsim.contrib matrixbasedptrouter - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib roadpricing - 2025.0-SNAPSHOT + ${project.parent.version} net.sf.trove4j @@ -70,7 +70,7 @@ org.matsim.contrib analysis - 2025.0-SNAPSHOT + ${project.parent.version} diff --git a/contribs/analysis/pom.xml b/contribs/analysis/pom.xml index 74a32b64c03..eea01c79ffb 100644 --- a/contribs/analysis/pom.xml +++ b/contribs/analysis/pom.xml @@ -13,7 +13,7 @@ org.matsim.contrib roadpricing - 2025.0-SNAPSHOT + ${project.parent.version} org.osgeo diff --git a/contribs/application/pom.xml b/contribs/application/pom.xml index 88bd8e9606c..c2cfee1e0bf 100644 --- a/contribs/application/pom.xml +++ b/contribs/application/pom.xml @@ -40,37 +40,37 @@ org.matsim.contrib otfvis - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib osm - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib sumo - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib analysis - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib emissions - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib noise - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib freight - 2025.0-SNAPSHOT + ${project.parent.version} @@ -87,7 +87,7 @@ com.github.matsim-org gtfs2matsim - fc8b13954d + 47b0802a29 @@ -151,7 +151,7 @@ org.matsim.contrib dvrp - 2025.0-SNAPSHOT + ${project.parent.version} compile diff --git a/contribs/application/src/main/java/org/matsim/application/ApplicationUtils.java b/contribs/application/src/main/java/org/matsim/application/ApplicationUtils.java index 083a315ecb5..0a13fbe9311 100644 --- a/contribs/application/src/main/java/org/matsim/application/ApplicationUtils.java +++ b/contribs/application/src/main/java/org/matsim/application/ApplicationUtils.java @@ -440,12 +440,17 @@ public static Path matchInput(String name, Path dir) { if (path.isPresent()) return path.get(); - // Match more general pattern at last - path = matchPattern(".+\\.[a-zA-Z0-9]*_" + name + "\\..+", dir); + // Match more general pattern + path = matchPattern(".+\\.[a-zA-Z0-9\\-]*_" + name + "\\..+", dir); if (path.isPresent()) return path.get(); - throw new IllegalArgumentException("Could not match input file: " + name); + // Even more permissive pattern + path = matchPattern(".+[a-zA-Z0-9_.\\-]*(_|\\.)" + name + ".+", dir); + if (path.isPresent()) + return path.get(); + + throw new IllegalArgumentException("Could not match input file: %s (in %s)".formatted(name, dir)); } private static Optional matchSuffix(String suffix, Path dir) { 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 3976a35c21b..bac5eaadd7c 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 @@ -7,6 +7,7 @@ import org.locationtech.jts.geom.Envelope; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.TransportMode; import org.matsim.application.ApplicationUtils; import org.matsim.application.CommandSpec; import org.matsim.application.MATSimAppCommand; @@ -20,6 +21,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.collections.CollectionUtils; import org.matsim.core.utils.geometry.CoordinateTransformation; import org.matsim.core.utils.io.IOUtils; import picocli.CommandLine; @@ -28,10 +30,7 @@ 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; +import java.util.*; @CommandLine.Command( name = "noise-analysis", @@ -67,7 +66,7 @@ public class NoiseAnalysis implements MATSimAppCommand { @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; + private Set consideredActivities; @CommandLine.Option(names = "--noise-barrier", description = "Path to the noise barrier File", defaultValue = "") private String noiseBarrierFile; @@ -87,10 +86,19 @@ public Integer call() throws Exception { boolean overrideParameters = ! ConfigUtils.hasModule(config, NoiseConfigGroup.class); NoiseConfigGroup noiseParameters = ConfigUtils.addOrGetModule(config, NoiseConfigGroup.class); - 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)); + if (overrideParameters){ + log.warn("no NoiseConfigGroup was configured before. Will set some standards. You should check the next lines in the log file and the output_config.xml!"); + noiseParameters.setConsideredActivitiesForReceiverPointGridArray(consideredActivities.toArray(String[]::new)); + noiseParameters.setConsideredActivitiesForDamageCalculationArray(consideredActivities.toArray(String[]::new)); + + { + //the default settings are now actually the same as what we 'override' here, but let's leave it here for clarity. + Set ignoredNetworkModes = CollectionUtils.stringArrayToSet( new String[]{TransportMode.bike, TransportMode.walk, TransportMode.transit_walk, TransportMode.non_network_walk} ); + noiseParameters.setNetworkModesToIgnoreSet( ignoredNetworkModes ); + + String[] hgvIdPrefixes = {"lkw", "truck", "freight"}; + noiseParameters.setHgvIdPrefixesArray( hgvIdPrefixes ); + } //use actual speed and not freespeed noiseParameters.setUseActualSpeedLevel(true); diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/population/TripAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/population/TripAnalysis.java index 11c75f21b1a..2365ed8a189 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/population/TripAnalysis.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/population/TripAnalysis.java @@ -4,10 +4,7 @@ import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; -import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2LongMap; -import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; +import it.unimi.dsi.fastutil.objects.*; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; import org.apache.commons.math3.analysis.interpolation.LoessInterpolator; @@ -17,6 +14,7 @@ import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.Point; +import org.matsim.application.ApplicationUtils; import org.matsim.application.CommandSpec; import org.matsim.application.MATSimAppCommand; import org.matsim.application.options.CsvOptions; @@ -26,6 +24,7 @@ import org.matsim.core.utils.io.IOUtils; import picocli.CommandLine; import tech.tablesaw.api.*; +import tech.tablesaw.columns.strings.AbstractStringColumn; import tech.tablesaw.io.csv.CsvReadOptions; import tech.tablesaw.joining.DataFrameJoiner; import tech.tablesaw.selection.Selection; @@ -34,7 +33,9 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.nio.file.Files; +import java.nio.file.Path; import java.util.*; +import java.util.stream.Collectors; import java.util.stream.IntStream; import static tech.tablesaw.aggregate.AggregateFunctions.count; @@ -44,16 +45,15 @@ requires = {"trips.csv", "persons.csv"}, produces = { "mode_share.csv", "mode_share_per_dist.csv", "mode_users.csv", "trip_stats.csv", - "mode_share_per_%s.csv", "population_trip_stats.csv", "trip_purposes_by_hour.csv", - "mode_share_distance_distribution.csv", + "mode_share_per_purpose.csv", "mode_share_per_%s.csv", + "population_trip_stats.csv", "trip_purposes_by_hour.csv", + "mode_share_distance_distribution.csv", "mode_shift.csv", "mode_chains.csv", "mode_choices.csv", "mode_choice_evaluation.csv", "mode_choice_evaluation_per_mode.csv", "mode_confusion_matrix.csv", "mode_prediction_error.csv" } ) public class TripAnalysis implements MATSimAppCommand { - private static final Logger log = LogManager.getLogger(TripAnalysis.class); - /** * Attributes which relates this person to a reference person. */ @@ -66,31 +66,24 @@ public class TripAnalysis implements MATSimAppCommand { * Person attribute containing its weight for analysis purposes. */ public static final String ATTR_REF_WEIGHT = "ref_weight"; - + private static final Logger log = LogManager.getLogger(TripAnalysis.class); + @CommandLine.Option(names = "--person-filter", description = "Define which persons should be included into trip analysis. Map like: Attribute name (key), attribute value (value). " + + "The attribute needs to be contained by output_persons.csv. Persons who do not match all filters are filtered out.", split = ",") + private final Map personFilters = new HashMap<>(); @CommandLine.Mixin private InputOptions input = InputOptions.ofCommand(TripAnalysis.class); @CommandLine.Mixin private OutputOptions output = OutputOptions.ofCommand(TripAnalysis.class); - @CommandLine.Option(names = "--input-ref-data", description = "Optional path to reference data", required = false) private String refData; - @CommandLine.Option(names = "--match-id", description = "Pattern to filter agents by id") private String matchId; - @CommandLine.Option(names = "--dist-groups", split = ",", description = "List of distances for binning", defaultValue = "0,1000,2000,5000,10000,20000") private List distGroups; - @CommandLine.Option(names = "--modes", split = ",", description = "List of considered modes, if not set all will be used") private List modeOrder; - @CommandLine.Option(names = "--shp-filter", description = "Define how the shp file filtering should work", defaultValue = "home") private LocationFilter filter; - - @CommandLine.Option(names = "--person-filter", description = "Define which persons should be included into trip analysis. Map like: Attribute name (key), attribute value (value). " + - "The attribute needs to be contained by output_persons.csv. Persons who do not match all filters are filtered out.", split = ",") - private final Map personFilters = new HashMap<>(); - @CommandLine.Mixin private ShpOptions shp; @@ -137,6 +130,20 @@ private static double[] calcHistogram(double[] data, double[] bins) { return hist; } + private static Map getColumnTypes() { + Map columnTypes = new HashMap<>(Map.of("person", ColumnType.TEXT, + "trav_time", ColumnType.STRING, "wait_time", ColumnType.STRING, "dep_time", ColumnType.STRING, + "longest_distance_mode", ColumnType.STRING, "main_mode", ColumnType.STRING, + "start_activity_type", ColumnType.TEXT, "end_activity_type", ColumnType.TEXT, + "first_pt_boarding_stop", ColumnType.TEXT, "last_pt_egress_stop", ColumnType.TEXT)); + + // Map.of only has 10 argument max + columnTypes.put("traveled_distance", ColumnType.LONG); + columnTypes.put("euclidean_distance", ColumnType.LONG); + + return columnTypes; + } + @Override public Integer call() throws Exception { @@ -209,18 +216,8 @@ public Integer call() throws Exception { log.info("Filtered {} out of {} persons", persons.rowCount(), total); - Map columnTypes = new HashMap<>(Map.of("person", ColumnType.TEXT, - "trav_time", ColumnType.STRING, "wait_time", ColumnType.STRING, "dep_time", ColumnType.STRING, - "longest_distance_mode", ColumnType.STRING, "main_mode", ColumnType.STRING, - "start_activity_type", ColumnType.TEXT, "end_activity_type", ColumnType.TEXT, - "first_pt_boarding_stop", ColumnType.TEXT, "last_pt_egress_stop", ColumnType.TEXT)); - - // Map.of only has 10 argument max - columnTypes.put("traveled_distance", ColumnType.LONG); - columnTypes.put("euclidean_distance", ColumnType.LONG); - Table trips = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(input.getPath("trips.csv"))) - .columnTypesPartial(columnTypes) + .columnTypesPartial(getColumnTypes()) .sample(false) .separator(CsvOptions.detectDelimiter(input.getPath("trips.csv"))).build()); @@ -286,10 +283,15 @@ public Integer call() throws Exception { joined.addColumns(dist_group); + TextColumn purpose = joined.textColumn("end_activity_type"); + + // Remove suffix durations like _345 + purpose.set(Selection.withRange(0, purpose.size()), purpose.replaceAll("_[0-9]{2,}$", "")); + writeModeShare(joined, labels); if (groups != null) { - groups.analyzeModeShare(joined, labels, modeOrder, (g) -> output.getPath("mode_share_per_%s.csv", g)); + groups.writeModeShare(joined, labels, modeOrder, (g) -> output.getPath("mode_share_per_%s.csv", g)); } if (persons.containsColumn(ATTR_REF_MODES)) { @@ -308,15 +310,24 @@ public Integer call() throws Exception { writePopulationStats(persons, joined); - writeTripStats(joined); - - writeTripPurposes(joined); - - writeTripDistribution(joined); + tryRun(this::writeTripStats, joined); + tryRun(this::writeTripPurposes, joined); + tryRun(this::writeTripDistribution, joined); + tryRun(this::writeModeShift, joined); + tryRun(this::writeModeChains, joined); + tryRun(this::writeModeStatsPerPurpose, joined); return 0; } + private void tryRun(ThrowingConsumer f, Table df) { + try { + f.accept(df); + } catch (IOException e) { + log.error("Error while running method", e); + } + } + private void writeModeShare(Table trips, List labels) { Table aggr = trips.summarize("trip_id", count).by("dist_group", "main_mode"); @@ -503,11 +514,6 @@ private void writeTripPurposes(Table trips) { IntColumn.create("arrival_h", arrival.intStream().toArray()) ); - TextColumn purpose = trips.textColumn("end_activity_type"); - - // Remove suffix durations like _345 - purpose.set(Selection.withRange(0, purpose.size()), purpose.replaceAll("_[0-9]{2,}$", "")); - Table tArrival = trips.summarize("trip_id", count).by("end_activity_type", "arrival_h"); tArrival.column(0).setName("purpose"); @@ -583,6 +589,117 @@ private void writeTripDistribution(Table trips) throws IOException { } } + private void writeModeShift(Table trips) throws IOException { + Path path; + try { + Path dir = Path.of(input.getPath("trips.csv")).getParent().resolve("ITERS").resolve("it.0"); + path = ApplicationUtils.matchInput("trips.csv", dir); + } catch (Exception e) { + log.error("Could not find trips from 0th iteration.", e); + return; + } + + Table originalTrips = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(path.toString())) + .columnTypesPartial(getColumnTypes()) + .sample(false) + .separator(CsvOptions.detectDelimiter(path.toString())).build()); + + // Use longest_distance_mode where main_mode is not present + originalTrips.stringColumn("main_mode") + .set(originalTrips.stringColumn("main_mode").isMissing(), + originalTrips.stringColumn("longest_distance_mode")); + + originalTrips.column("main_mode").setName("original_mode"); + + Table joined = new DataFrameJoiner(trips, "trip_id").inner(true, originalTrips); + Table aggr = joined.summarize("trip_id", count).by("original_mode", "main_mode"); + + aggr.write().csv(output.getPath("mode_shift.csv").toFile()); + } + + /** + * Collects information about all modes used during one day. + */ + private void writeModeChains(Table trips) throws IOException { + + Map> modesPerPerson = new LinkedHashMap<>(); + + for (Row trip : trips) { + String id = trip.getString("person"); + String mode = trip.getString("main_mode"); + modesPerPerson.computeIfAbsent(id, s -> new LinkedList<>()).add(mode); + } + + // Store other values explicitly + ObjectDoubleMutablePair other = ObjectDoubleMutablePair.of("other", 0); + Object2DoubleMap chains = new Object2DoubleOpenHashMap<>(); + for (List modes : modesPerPerson.values()) { + String key; + if (modes.size() == 1) + key = modes.getFirst(); + else if (modes.size() > 6) { + other.right(other.rightDouble() + 1); + continue; + } else + key = String.join("-", modes); + + chains.mergeDouble(key, 1, Double::sum); + } + + + List> counts = chains.object2DoubleEntrySet().stream() + .map(e -> ObjectDoubleMutablePair.of(e.getKey(), (int) e.getDoubleValue())) + .sorted(Comparator.comparingDouble(p -> -p.rightDouble())) + .collect(Collectors.toList()); + + // Aggregate entries to prevent file from getting too large + for (int i = 250; i < counts.size(); i++) { + other.right(other.rightDouble() + counts.get(i).rightDouble()); + } + counts = counts.subList(0, Math.min(counts.size(), 250)); + counts.add(other); + + counts.sort(Comparator.comparingDouble(p -> -p.rightDouble())); + + + try (CSVPrinter printer = new CSVPrinter(Files.newBufferedWriter(output.getPath("mode_chains.csv")), CSVFormat.DEFAULT)) { + + printer.printRecord("modes", "count", "share"); + + double total = counts.stream().mapToDouble(ObjectDoubleMutablePair::rightDouble).sum(); + for (ObjectDoubleMutablePair p : counts) { + printer.printRecord(p.left(), (int) p.rightDouble(), p.rightDouble() / total); + } + } + } + + @SuppressWarnings("unchecked") + private void writeModeStatsPerPurpose(Table trips) { + + Table aggr = trips.summarize("trip_id", count).by("end_activity_type", "main_mode"); + + Comparator cmp = Comparator.comparing(row -> row.getString("end_activity_type")); + aggr = aggr.sortOn(cmp.thenComparing(row -> row.getString("main_mode"))); + + aggr.doubleColumn(aggr.columnCount() - 1).setName("share"); + aggr.column("end_activity_type").setName("purpose"); + + Set purposes = (Set) aggr.column("purpose").asSet(); + + // Norm each purpose to 1 + // It was not clear if the purpose is a string or text colum, therefor this code uses the abstract version + for (String label : purposes) { + DoubleColumn all = aggr.doubleColumn("share"); + Selection sel = ((AbstractStringColumn) aggr.column("purpose")).isEqualTo(label); + + double total = all.where(sel).sum(); + if (total > 0) + all.set(sel, all.divide(total)); + } + + aggr.write().csv(output.getPath("mode_share_per_purpose.csv").toFile()); + } + /** * How shape file filtering should be applied. */ @@ -592,4 +709,9 @@ enum LocationFilter { home, none } + + @FunctionalInterface + private interface ThrowingConsumer { + void accept(T t) throws IOException; + } } diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/population/TripByGroupAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/population/TripByGroupAnalysis.java index b63a58f5ed8..5f7e8894500 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/population/TripByGroupAnalysis.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/population/TripByGroupAnalysis.java @@ -100,7 +100,7 @@ final class TripByGroupAnalysis { } } - void analyzeModeShare(Table trips, List dists, List modeOrder, Function output) { + void writeModeShare(Table trips, List dists, List modeOrder, Function output) { for (Group group : groups) { diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/pt/PublicTransitAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/pt/PublicTransitAnalysis.java new file mode 100644 index 00000000000..e8785b30cda --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/analysis/pt/PublicTransitAnalysis.java @@ -0,0 +1,105 @@ +/* *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.application.analysis.pt; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.analysis.pt.stop2stop.PtStop2StopAnalysis; +import org.matsim.api.core.v01.Scenario; +import org.matsim.application.ApplicationUtils; +import org.matsim.application.CommandSpec; +import org.matsim.application.MATSimAppCommand; +import org.matsim.application.analysis.emissions.AirPollutionAnalysis; +import org.matsim.application.options.InputOptions; +import org.matsim.application.options.OutputOptions; +import org.matsim.application.options.SampleOptions; +import org.matsim.core.api.experimental.events.EventsManager; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.events.EventsUtils; +import org.matsim.core.events.MatsimEventsReader; +import org.matsim.core.scenario.ScenarioUtils; +import picocli.CommandLine; + +@CommandLine.Command( + name = "transit", description = "General public transit analysis.", + mixinStandardHelpOptions = true, showDefaultValues = true +) +@CommandSpec(requireRunDirectory = true, + produces = { + "pt_pax_volumes.csv.gz", + } +) +public class PublicTransitAnalysis implements MATSimAppCommand { + + private static final Logger log = LogManager.getLogger(PublicTransitAnalysis.class); + + @CommandLine.Mixin + private final InputOptions input = InputOptions.ofCommand(PublicTransitAnalysis.class); + @CommandLine.Mixin + private final OutputOptions output = OutputOptions.ofCommand(PublicTransitAnalysis.class); + @CommandLine.Mixin + private SampleOptions sample; + + public static void main(String[] args) { + new PublicTransitAnalysis().execute(args); + } + + @Override + public Integer call() throws Exception { + + Config config = prepareConfig(); + Scenario scenario = ScenarioUtils.loadScenario(config); + EventsManager eventsManager = EventsUtils.createEventsManager(); + + String eventsFile = ApplicationUtils.matchInput("events", input.getRunDirectory()).toString(); + + PtStop2StopAnalysis ptStop2StopEventHandler = new PtStop2StopAnalysis(scenario.getTransitVehicles(), sample.getUpscaleFactor()); + eventsManager.addHandler(ptStop2StopEventHandler); + eventsManager.initProcessing(); + MatsimEventsReader matsimEventsReader = new MatsimEventsReader(eventsManager); + matsimEventsReader.readFile(eventsFile); + + log.info("Done reading the events file."); + log.info("Finish processing..."); + eventsManager.finishProcessing(); + + ptStop2StopEventHandler.writeStop2StopEntriesByDepartureCsv(output.getPath("pt_pax_volumes.csv.gz"), + ",", ";"); + + return 0; + } + + private Config prepareConfig() { + Config config = ConfigUtils.loadConfig(ApplicationUtils.matchInput("config.xml", input.getRunDirectory()).toAbsolutePath().toString()); + + config.vehicles().setVehiclesFile(ApplicationUtils.matchInput("vehicles", input.getRunDirectory()).toAbsolutePath().toString()); + config.network().setInputFile(ApplicationUtils.matchInput("network", input.getRunDirectory()).toAbsolutePath().toString()); + config.transit().setTransitScheduleFile(ApplicationUtils.matchInput("transitSchedule", input.getRunDirectory()).toAbsolutePath().toString()); + config.transit().setVehiclesFile(ApplicationUtils.matchInput("transitVehicles", input.getRunDirectory()).toAbsolutePath().toString()); + config.plans().setInputFile(null); + config.facilities().setInputFile(null); + config.eventsManager().setNumberOfThreads(null); + config.eventsManager().setEstimatedNumberOfEvents(null); + config.global().setNumberOfThreads(1); + + return config; + } +} diff --git a/contribs/application/src/main/java/org/matsim/application/options/ShpOptions.java b/contribs/application/src/main/java/org/matsim/application/options/ShpOptions.java index 985db84bba7..5d9f8ccec99 100644 --- a/contribs/application/src/main/java/org/matsim/application/options/ShpOptions.java +++ b/contribs/application/src/main/java/org/matsim/application/options/ShpOptions.java @@ -8,9 +8,12 @@ import org.geotools.api.feature.simple.SimpleFeatureType; import org.geotools.api.referencing.FactoryException; import org.geotools.api.referencing.crs.CoordinateReferenceSystem; -import org.geotools.data.*; +import org.geotools.api.referencing.operation.MathTransform; +import org.geotools.api.referencing.operation.TransformException; +import org.geotools.data.DefaultTransaction; import org.geotools.data.shapefile.ShapefileDataStore; import org.geotools.data.shapefile.ShapefileDataStoreFactory; +import org.geotools.geometry.jts.JTS; import org.geotools.geopkg.GeoPkgDataStoreFactory; import org.geotools.referencing.CRS; import org.locationtech.jts.geom.*; @@ -219,12 +222,30 @@ public Geometry getGeometry() { ); if (geometryCollection.isEmpty()) { - throw new IllegalStateException("There are noe geometries in the shape file."); + throw new IllegalStateException("There are no geometries in the shape file."); } return geometryCollection.union(); } + /** + * Return the union of all geometries in the shape file and project it to the target crs. + * @param toCRS target coordinate system + */ + public Geometry getGeometry(String toCRS) { + try { + CoordinateReferenceSystem sourceCRS = CRS.decode(detectCRS()); + CoordinateReferenceSystem targetCRS = CRS.decode(toCRS); + + MathTransform ct = CRS.findMathTransform(sourceCRS, targetCRS); + + return JTS.transform(getGeometry(), ct); + + } catch (TransformException | FactoryException e) { + throw new IllegalStateException("Could not transform coordinates of the provided shape", e); + } + } + /** * Creates an index to query features from this shape file. * diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/CreateAvroNetwork.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/CreateAvroNetwork.java index c94b17f9335..04f06a7df91 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/CreateAvroNetwork.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/CreateAvroNetwork.java @@ -108,8 +108,11 @@ public Integer call() throws Exception { filter = filter.and(link -> p.matcher(link.getId().toString()).matches()); } + // Strings that could have been added in the list, due to command line parsing + modes.removeIf(m -> m.isBlank() || m.equals("none") || m.equals("\"") || m.equals("\"\"")); + // At least one of the specified modes needs to be contained - if (!modes.isEmpty() && !modes.equals(Set.of("none"))) { + if (!modes.isEmpty()) { filter = filter.and(link -> modes.stream().anyMatch(m -> link.getAllowedModes().contains(m))); } diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java index 048e2fa81b7..8d8e341154d 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/ApplyNetworkParams.java @@ -53,7 +53,8 @@ public class ApplyNetworkParams implements MATSimAppCommand { @CommandLine.Option(names = "--model", description = "Reference to the network model class", required = true) private Class modelClazz; - @CommandLine.Option(names = "--factor-bounds", split = ",", description = "Speed factor limits (lower,upper bound)", defaultValue = NetworkParamsOpt.DEFAULT_FACTOR_BOUNDS) + @CommandLine.Option(names = "--factor-bounds", split = ",", description = "Speed factor limits (lower, upper bound). " + + "Can be negative to indicate absolute speed bounds (in km/h)", defaultValue = NetworkParamsOpt.DEFAULT_FACTOR_BOUNDS) private double[] speedFactorBounds; @CommandLine.Option(names = "--capacity-bounds", split = ",", defaultValue = "0.4,0.6,0.8", @@ -234,30 +235,50 @@ private boolean applyFreeSpeed(Link link, Feature ft) { return false; } + double allowedSpeed = (double) link.getAttributes().getAttribute("allowed_speed"); + double freeSpeed = allowedSpeed * speedFactor; + boolean modified = false; - if (speedFactor > speedFactorBounds[1]) { + if (speedFactor > speedFactorBounds[1] && speedFactorBounds[1] >= 0) { log.warn("Reducing speed factor on {} from {} to {}", link.getId(), speedFactor, speedFactorBounds[1]); speedFactor = speedFactorBounds[1]; modified = true; } + // Use absolute bound for speed + if (freeSpeed > -speedFactorBounds[1]/3.6 && speedFactorBounds[1] < 0) { + log.warn("Reducing speed on {} from {} to {}", link.getId(), freeSpeed, -speedFactorBounds[1]/3.6); + speedFactor = (-speedFactorBounds[1] / 3.6) / allowedSpeed; + modified = true; + } + // Threshold for very low speed factors - if (speedFactor < speedFactorBounds[0]) { + if (speedFactor < speedFactorBounds[0] && speedFactorBounds[0] >= 0) { log.warn("Increasing speed factor on {} from {} to {}", link, speedFactor, speedFactorBounds[0]); speedFactor = speedFactorBounds[0]; modified = true; } - double freeSpeed = (double) link.getAttributes().getAttribute("allowed_speed") * speedFactor; + // Absolute negative speed factor + if (freeSpeed < -speedFactorBounds[0]/3.6 && speedFactorBounds[0] < 0) { + log.warn("Increasing speed on {} from {} to {}", link, freeSpeed, -speedFactorBounds[0]/3.6); + speedFactor = (-speedFactorBounds[0] / 3.6) / allowedSpeed; + modified = true; + } + // Recalculate with updated speed factor + freeSpeed = allowedSpeed * speedFactor; freeSpeed = BigDecimal.valueOf(freeSpeed).setScale(3, RoundingMode.HALF_EVEN).doubleValue(); if (decrease && freeSpeed > link.getFreespeed()) return false; link.setFreespeed(freeSpeed); - link.getAttributes().putAttribute("speed_factor", freeSpeed); + link.getAttributes().putAttribute( + "speed_factor", + BigDecimal.valueOf(freeSpeed).setScale(5, RoundingMode.HALF_EVEN).doubleValue() + ); return modified; } diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/EvalFreespeedParams.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/EvalFreespeedParams.java index cd2ba4e016a..68cd6099058 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/EvalFreespeedParams.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/EvalFreespeedParams.java @@ -121,12 +121,27 @@ static Result applyAndEvaluateParams( speedFactor = speedModel.predict(ft.features(), ft.categories()); // apply lower and upper bound - speedFactor = Math.max(speedFactorBounds[0], speedFactor); - speedFactor = Math.min(speedFactorBounds[1], speedFactor); + if (speedFactorBounds[0] >= 0) + speedFactor = Math.max(speedFactorBounds[0], speedFactor); + + if (speedFactorBounds[1] >= 0) + speedFactor = Math.min(speedFactorBounds[1], speedFactor); attributes.put(link.getId(), speedModel.getData(ft.features(), ft.categories())); - link.setFreespeed(allowedSpeed * speedFactor); + double freespeed = allowedSpeed * speedFactor; + + // Check absolute bounds on the freespeed + if (speedFactorBounds[0] < 0 && freespeed < -speedFactorBounds[0]/3.6) { + freespeed = -speedFactorBounds[0]/3.6; + speedFactor = freespeed / allowedSpeed; + } + if (speedFactorBounds[1] < 0 && freespeed > -speedFactorBounds[1]/3.6) { + freespeed = -speedFactorBounds[1]/3.6; + speedFactor = freespeed / allowedSpeed; + } + + link.setFreespeed(freespeed); link.getAttributes().putAttribute("speed_factor", speedFactor); } else diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FreespeedOptServer.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FreespeedOptServer.java index fef19850305..c17189b3a95 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FreespeedOptServer.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/params/FreespeedOptServer.java @@ -57,7 +57,8 @@ public class FreespeedOptServer implements MATSimAppCommand { @CommandLine.Parameters(arity = "1..*", description = "Input validation files loaded from APIs") private List validationFiles; - @CommandLine.Option(names = "--factor-bounds", split = ",", description = "Speed factor limits (lower,upper bound)", defaultValue = NetworkParamsOpt.DEFAULT_FACTOR_BOUNDS) + @CommandLine.Option(names = "--factor-bounds", split = ",", description = "Speed factor limits (lower, upper bound). " + + "Can be negative to indicate absolute speed bounds (in km/h)", defaultValue = NetworkParamsOpt.DEFAULT_FACTOR_BOUNDS) private double[] speedFactorBounds; @CommandLine.Option(names = "--ref-hours", description = "Reference hours", defaultValue = "3,21", split = ",") diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/pt/AdjustSameDepartureTimes.java b/contribs/application/src/main/java/org/matsim/application/prepare/pt/AdjustSameDepartureTimes.java new file mode 100644 index 00000000000..4d8b9378815 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/pt/AdjustSameDepartureTimes.java @@ -0,0 +1,154 @@ +package org.matsim.application.prepare.pt; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.core.utils.geometry.CoordUtils; +import org.matsim.core.utils.misc.OptionalTime; +import org.matsim.pt.transitSchedule.api.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +/** + * Some providers set the same departure and arrival times for multiple stops. + * This usually happens with on-demand buses, but can also happen on night buses where multiple stops can have a departure at the same minute. + * These departure times will lead to artifacts when using a pseudo network. + * The purpose of this class is to spread these departures more evently. + * However, in the case of on demand buses, the travel times will likely still be too optimistic. + */ +public class AdjustSameDepartureTimes implements Consumer { + + private static Logger log = LogManager.getLogger(AdjustSameDepartureTimes.class); + + private static OptionalTime add(OptionalTime x, double t) { + if (!x.isDefined()) { + return x; + } + return OptionalTime.defined(x.seconds() + t); + } + + @Override + public void accept(TransitSchedule schedule) { + for (TransitLine line : schedule.getTransitLines().values()) { + + List routes = new ArrayList<>(line.getRoutes().values()); + for (TransitRoute route : routes) { + List newStops = adjustDepartures(schedule.getFactory(), route); + + if (newStops == null) { + continue; + } + + log.info("Adjusted departures for route {} in line {}", route.getId(), line.getId()); + + line.removeRoute(route); + + TransitRoute newRoute = schedule.getFactory().createTransitRoute(route.getId(), route.getRoute(), newStops, route.getTransportMode()); + newRoute.setDescription(route.getDescription()); + for (Map.Entry e : route.getAttributes().getAsMap().entrySet()) { + newRoute.getAttributes().putAttribute(e.getKey(), e.getValue()); + } + route.getDepartures().values().forEach(newRoute::addDeparture); + + line.addRoute(newRoute); + } + } + + } + + private List adjustDepartures(TransitScheduleFactory f, TransitRoute route) { + + List stops = new ArrayList<>(route.getStops()); + + boolean adjusted = false; + + // Check if the times at the end of the schedule are the same + // These need to be calculated and can not be interpolated + // The arrival at the last stop is shifted by small travel time + if (stops.size() > 1) { + TransitRouteStop last = stops.getLast(); + TransitRouteStop secondLast = stops.get(stops.size() - 2); + + OptionalTime lastDep = last.getDepartureOffset().or(last.getArrivalOffset()); + OptionalTime secondLastDep = secondLast.getDepartureOffset().or(secondLast.getArrivalOffset()); + + if (lastDep.isDefined() && secondLastDep.isDefined() && lastDep.equals(secondLastDep)) { + // Calculate the time between the last two stops + double dist = Math.max(20, CoordUtils.calcEuclideanDistance(last.getStopFacility().getCoord(), secondLast.getStopFacility().getCoord())); + double time = dist / 10; // 10 m/s + + // Calculate the time for the last stop + TransitRouteStop newStop = f.createTransitRouteStop( + last.getStopFacility(), + add(last.getArrivalOffset(), time), + add(last.getDepartureOffset(), time) + ); + + newStop.setAwaitDepartureTime(last.isAwaitDepartureTime()); + newStop.setAllowAlighting(last.isAllowAlighting()); + newStop.setAllowBoarding(last.isAllowBoarding()); + + stops.set(stops.size() - 1, newStop); + adjusted = true; + } + } + + for (int i = 0; i < stops.size() - 1; ) { + + TransitRouteStop stop = stops.get(i); + OptionalTime dep = stop.getDepartureOffset().or(stop.getArrivalOffset()); + + if (!dep.isDefined()) { + i++; + continue; + } + + OptionalTime arr = null; + int j = i + 1; + for (; j < stops.size(); j++) { + TransitRouteStop nextStop = stops.get(j); + arr = nextStop.getArrivalOffset().or(nextStop.getDepartureOffset()); + if (!dep.equals(arr)) { + break; + } + } + + if (arr == null) { + i++; + continue; + } + + if (j > i + 1) { + double time = dep.seconds(); + double diff = (arr.seconds() - time) / (j - i); + + for (int k = i + 1; k < j; k++) { + TransitRouteStop stopToAdjust = stops.get(k); + int add = (int) (diff * (k - i)); + + TransitRouteStop newStop = f.createTransitRouteStop( + stopToAdjust.getStopFacility(), + add(stopToAdjust.getArrivalOffset(), add), + add(stopToAdjust.getDepartureOffset(), add) + ); + + newStop.setAwaitDepartureTime(stopToAdjust.isAwaitDepartureTime()); + newStop.setAllowAlighting(stopToAdjust.isAllowAlighting()); + newStop.setAllowBoarding(stopToAdjust.isAllowBoarding()); + + stops.set(k, newStop); + adjusted = true; + } + } + + i = j; + } + + if (adjusted) + return stops; + + return null; + } +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/pt/CreateTransitScheduleFromGtfs.java b/contribs/application/src/main/java/org/matsim/application/prepare/pt/CreateTransitScheduleFromGtfs.java index 5038d1f046c..ddbe0e7868a 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/pt/CreateTransitScheduleFromGtfs.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/pt/CreateTransitScheduleFromGtfs.java @@ -1,5 +1,6 @@ package org.matsim.application.prepare.pt; +import com.conveyal.gtfs.model.Route; import com.conveyal.gtfs.model.Stop; import org.apache.commons.io.FilenameUtils; import org.apache.logging.log4j.LogManager; @@ -31,10 +32,8 @@ import java.io.File; import java.nio.file.Path; import java.time.LocalDate; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; +import java.util.function.Consumer; import java.util.function.Predicate; @@ -77,6 +76,15 @@ public class CreateTransitScheduleFromGtfs implements MATSimAppCommand { @CommandLine.Option(names = "--include-stops", description = "Fully qualified class name to a Predicate for filtering certain stops") private Class includeStops; + @CommandLine.Option(names = "--transform-stops", description = "Fully qualified class name to a Consumer for transforming stops before usage") + private Class transformStops; + + @CommandLine.Option(names = "--transform-routes", description = "Fully qualified class name to a Consumer for transforming routes before usage") + private Class transformRoutes; + + @CommandLine.Option(names = "--transform-schedule", description = "Fully qualified class name to a Consumer to be executed after the schedule was created", arity = "0..*", split = ",") + private List> transformSchedule; + @CommandLine.Option(names = "--merge-stops", description = "Whether stops should be merged by coordinate") private boolean mergeStops; @@ -134,6 +142,15 @@ public Integer call() throws Exception { log.info("Using prefix: {}", prefix); } + if (transformStops != null) { + converter.setTransformStop(createConsumer(transformStops, Stop.class)); + } + + if (transformRoutes != null) { + converter.setTransformRoute(createConsumer(transformRoutes, Route.class)); + } + + converter.build().convert(); i++; } @@ -144,6 +161,24 @@ public Integer call() throws Exception { TransitSchedulePostProcessTools.copyEarlyDeparturesToFollowingNight(scenario.getTransitSchedule(), 6 * 3600, "copied"); } + if (transformSchedule != null && !transformSchedule.isEmpty()) { + for (Class c : transformSchedule) { + Consumer f = createConsumer(c, TransitSchedule.class); + log.info("Applying {} to created schedule", c.getName()); + f.accept(scenario.getTransitSchedule()); + } + } + + for (TransitLine line : scenario.getTransitSchedule().getTransitLines().values()) { + List routes = new ArrayList<>(line.getRoutes().values()); + for (TransitRoute route : routes) { + if (route.getDepartures().isEmpty()) { + log.warn("Route {} in line {} with no departures removed.", route.getId(), line.getId()); + line.removeRoute(route); + } + } + } + Network network = NetworkUtils.readNetwork(networkFile); Scenario ptScenario = getScenarioWithPseudoPtNetworkAndTransitVehicles(network, scenario.getTransitSchedule(), "pt_"); @@ -151,11 +186,14 @@ public Integer call() throws Exception { if (validate) { //Check schedule and network TransitScheduleValidator.ValidationResult checkResult = TransitScheduleValidator.validateAll(ptScenario.getTransitSchedule(), ptScenario.getNetwork()); + List warnings = checkResult.getWarnings(); + if (!warnings.isEmpty()) + log.warn("TransitScheduleValidator warnings: {}", String.join("\n", warnings)); + if (checkResult.isValid()) { log.info("TransitSchedule and Network valid according to TransitScheduleValidator"); - log.warn("TransitScheduleValidator warnings: {}", checkResult.getWarnings()); } else { - log.error(checkResult.getErrors()); + log.error("TransitScheduleValidator errors: {}", String.join("\n", checkResult.getErrors())); throw new RuntimeException("TransitSchedule and/or Network invalid"); } } @@ -170,6 +208,12 @@ public Integer call() throws Exception { return 0; } + @SuppressWarnings({"unchecked", "unused"}) + private Consumer createConsumer(Class consumer, Class type) throws ReflectiveOperationException { + return (Consumer) consumer.getDeclaredConstructor().newInstance(); + } + + @SuppressWarnings("unchecked") private Predicate createFilter(int i) throws Exception { Predicate filter = (stop) -> true; diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/scenario/CreateScenarioCutOut.java b/contribs/application/src/main/java/org/matsim/application/prepare/scenario/CreateScenarioCutOut.java index d7450553f5c..4dcd8a6bf5a 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/scenario/CreateScenarioCutOut.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/scenario/CreateScenarioCutOut.java @@ -2,10 +2,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.jts.geom.Geometry; -import org.locationtech.jts.geom.GeometryFactory; -import org.locationtech.jts.geom.LineString; +import org.locationtech.jts.geom.*; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; @@ -30,6 +27,7 @@ import org.matsim.core.population.algorithms.ParallelPersonAlgorithmUtils; import org.matsim.core.population.algorithms.PersonAlgorithm; import org.matsim.core.population.routes.NetworkRoute; +import org.matsim.core.router.DefaultAnalysisMainModeIdentifier; import org.matsim.core.router.TripStructureUtils; import org.matsim.core.router.TripStructureUtils.Trip; import org.matsim.core.router.costcalculators.OnlyTimeDependentTravelDisutility; @@ -212,6 +210,11 @@ public Integer call() throws Exception { return 2; } + if (eventPath != null && outputEvents == null) { + log.error("Events were given as input, that means --output-network-change-events must be set."); + return 2; + } + // Prepare required input-data Config config = ConfigUtils.createConfig(); config.global().setCoordinateSystem(crs.getInputCRS()); @@ -223,7 +226,7 @@ public Integer call() throws Exception { } scenario = ScenarioUtils.loadScenario(config); - geom = shp.getGeometry(); + geom = shp.getGeometry(crs.getInputCRS()); geomBuffer = geom.buffer(buffer); for (String mode : modes) @@ -240,7 +243,7 @@ public Integer call() throws Exception { manager.addHandler(tt); manager.initProcessing(); - EventsUtils.readEvents(manager, eventPath.toString()); + EventsUtils.readEvents(manager, eventPath); manager.finishProcessing(); } @@ -257,18 +260,32 @@ public Integer call() throws Exception { } } + log.info("Links in shape: {} out of {}", linksToKeep.size(), scenario.getNetwork().getLinks().size()); + + if (linksToKeep.isEmpty()) { + log.error("No links are in the resulting network. Check your input shape file and coordinate system"); + log.error("If using EPSG:4326 (WGS84), -Dorg.geotools.referencing.forceXY=true might help"); + return 1; + } + // Cut out the population and mark needed network parts ParallelPersonAlgorithmUtils.run(scenario.getPopulation(), Runtime.getRuntime().availableProcessors(), this); //Population + log.info("Persons in the original population: {}", scenario.getPopulation().getPersons().size()); log.info("Persons to delete: {}", personsToDelete.size()); for (Id personId : personsToDelete) { scenario.getPopulation().removePerson(personId); } - //Network - log.info("Links to add: {}", linksToKeep.size()); + log.info("Persons in the resulting scenario: {}", scenario.getPopulation().getPersons().size()); + + if (scenario.getPopulation().getPersons().isEmpty()) { + log.error("No persons are in the resulting population. Check if your input shape file and coordinate system is correct. Exiting ..."); + return 1; + } + // Network log.info("Additional links from routes to include: {}", linksToInclude.size()); log.info("number of links in original network: {}", scenario.getNetwork().getLinks().size()); @@ -295,8 +312,7 @@ public Integer call() throws Exception { ParallelPersonAlgorithmUtils.run(scenario.getPopulation(), Runtime.getRuntime().availableProcessors(), new CleanPersonLinkIds()); - log.info("Persons in the scenario: {}", scenario.getPopulation().getPersons().size()); - PopulationUtils.writePopulation(scenario.getPopulation(), outputPopulation.toString()); + PopulationUtils.writePopulation(scenario.getPopulation(), outputPopulation); if (facilityPath != null) { @@ -310,10 +326,10 @@ public Integer call() throws Exception { if (eventPath != null) { List events = generateNetworkChangeEvents(changeEventsInterval); - new NetworkChangeEventsWriter().write(outputEvents.toString(), events); + new NetworkChangeEventsWriter().write(outputEvents, events); } - NetworkUtils.writeNetwork(scenario.getNetwork(), outputNetwork.toString()); + NetworkUtils.writeNetwork(scenario.getNetwork(), outputNetwork); return 0; } @@ -346,7 +362,7 @@ private void filterFacilities() { } // Expensive check last - if (f.getCoord() != null && geom.contains(MGC.coord2Point(f.getCoord()))) + if (f.getCoord() != null && geom.contains(MGC.coord2Point(f.getCoord()))) facilitiesToInclude.add(f.getId()); } @@ -435,7 +451,13 @@ private Coord getActivityCoord(Activity activity) { if (scenario.getActivityFacilities() != null && activity.getFacilityId() != null && scenario.getActivityFacilities().getFacilities().containsKey(activity.getFacilityId())) return scenario.getActivityFacilities().getFacilities().get(activity.getFacilityId()).getCoord(); - return activity.getCoord(); + if (activity.getCoord() != null) + return activity.getCoord(); + + if (activity.getLinkId() != null && scenario.getNetwork().getLinks().containsKey(activity.getLinkId())) + return scenario.getNetwork().getLinks().get(activity.getLinkId()).getCoord(); + + return null; } /** @@ -483,34 +505,44 @@ public void run(Person person) { boolean keepPerson = false; List trips = TripStructureUtils.getTrips(person.getSelectedPlan()); - + List activities = TripStructureUtils.getActivities(person.getSelectedPlan(), TripStructureUtils.StageActivityHandling.ExcludeStageActivities); Set> linkIds = new HashSet<>(); Set> facilityIds = new HashSet<>(); - for (Trip trip : trips) { - Coord originCoord = getActivityCoord(trip.getOriginActivity()); - Coord destinationCoord = getActivityCoord(trip.getDestinationActivity()); - - if (originCoord == null || destinationCoord == null) { - if (noActCoordsWarnings++ < 10) - log.info("Activity coords of trip is null. Skipping Trip..."); + // Check activities first, some agent might be stationary + for (Activity act : activities) { + Coord coord = getActivityCoord(act); - continue; + if (coord == null && noActCoordsWarnings++ < 10) { + log.info("Activity coords for agent {} are null. Skipping Trip...", person.getId()); } - // keep all agents starting or ending in area - if (geom.contains(MGC.coord2Point(originCoord)) || geom.contains(MGC.coord2Point(destinationCoord))) { + if (coord != null && geom.contains(MGC.coord2Point(coord))) { keepPerson = true; } - LineString line = geoFactory.createLineString(new Coordinate[]{ - MGC.coord2Coordinate(originCoord), - MGC.coord2Coordinate(destinationCoord) - }); + if (act.getFacilityId() != null) + facilityIds.add(act.getFacilityId()); - // also keep persons traveling through or close to area (beeline) - if (line.intersects(geom)) { - keepPerson = true; + if (act.getLinkId() != null) + linkIds.add(act.getLinkId()); + + } + + for (Trip trip : trips) { + Coord originCoord = getActivityCoord(trip.getOriginActivity()); + Coord destinationCoord = getActivityCoord(trip.getDestinationActivity()); + + if (originCoord != null && destinationCoord != null) { + LineString line = geoFactory.createLineString(new Coordinate[]{ + MGC.coord2Coordinate(originCoord), + MGC.coord2Coordinate(destinationCoord) + }); + + // also keep persons traveling through or close to area (beeline) + if (line.intersects(geom)) { + keepPerson = true; + } } //Save route links @@ -546,20 +578,6 @@ public void run(Person person) { } // There is no additional link freespeed information, that we could save. So we are finished here } - - if (trip.getOriginActivity().getFacilityId() != null) - facilityIds.add(trip.getOriginActivity().getFacilityId()); - - if (trip.getDestinationActivity().getFacilityId() != null) - facilityIds.add(trip.getDestinationActivity().getFacilityId()); - - if (trip.getOriginActivity().getLinkId() != null) { - linkIds.add(trip.getOriginActivity().getLinkId()); - } - - if (trip.getDestinationActivity().getLinkId() != null) { - linkIds.add(trip.getDestinationActivity().getLinkId()); - } } } diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DefaultJobDurationCalculator.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DefaultJobDurationCalculator.java new file mode 100644 index 00000000000..42ddbc4068a --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DefaultJobDurationCalculator.java @@ -0,0 +1,37 @@ +package org.matsim.freightDemandGeneration; + +import org.matsim.api.core.v01.Scenario; + +public class DefaultJobDurationCalculator implements JobDurationCalculator { + @Override + public double calculateServiceDuration(Integer serviceTimePerUnit, int demandForThisService) { + return getDefaultCalculation(serviceTimePerUnit, demandForThisService); + } + + @Override + public double calculatePickupDuration(Integer pickupDurationPerUnit, int demandForThisShipment) { + return getDefaultCalculation(pickupDurationPerUnit, demandForThisShipment); + } + + @Override + public double calculateDeliveryDuration(Integer deliveryDurationPerUnit, int demandForThisShipment) { + return getDefaultCalculation(deliveryDurationPerUnit, demandForThisShipment); + } + + @Override + public void recalculateJobDurations(Scenario scenario) { + // do nothing + } + + /** + * @param timePerUnit time per unit + * @param demandForThisService demand for this service + * @return default calculation + */ + private int getDefaultCalculation(int timePerUnit, int demandForThisService) { + if (demandForThisService == 0) + return timePerUnit; + else + return timePerUnit * demandForThisService; + } +} diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java index e39eedd9ad4..63179128cc4 100644 --- a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java +++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java @@ -324,16 +324,18 @@ public String getTypeOfDemand() { * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file * @param population Population * @param shapeCategory Column name in the shape file for the data connection in the csv files - * @throws IOException if the csv file cannot be read + * @param jobDurationCalculator Calculator for the job duration + * @throws IOException if the csv file cannot be read */ static void readAndCreateDemand(Scenario scenario, Path csvLocationDemand, ShpOptions.Index indexShape, boolean combineSimilarJobs, - CoordinateTransformation crsTransformationNetworkAndShape, Population population, String shapeCategory) throws IOException { + CoordinateTransformation crsTransformationNetworkAndShape, Population population, String shapeCategory, + JobDurationCalculator jobDurationCalculator) throws IOException { Set demandInformation = readDemandInformation(csvLocationDemand); checkNewDemand(scenario, demandInformation, indexShape, shapeCategory); createDemandForCarriers(scenario, indexShape, demandInformation, population, combineSimilarJobs, - crsTransformationNetworkAndShape); + crsTransformationNetworkAndShape, jobDurationCalculator); } /** @@ -538,42 +540,45 @@ static void checkNewDemand(Scenario scenario, Set dema /** * Creates for every demand information the services/shipments for the carriers * - * @param scenario Scenario - * @param indexShape ShpOptions.Index for the shape file - * @param demandInformation Set with the demand information - * @param population Population - * @param combineSimilarJobs boolean if the jobs of the same carrier with same location and time will be combined - * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file + * @param scenario Scenario + * @param indexShape ShpOptions.Index for the shape file + * @param demandInformation Set with the demand information + * @param population Population + * @param combineSimilarJobs boolean if the jobs of the same carrier with same location and time will be combined + * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file + * @param jobDurationCalculator Calculator for the job duration */ static void createDemandForCarriers(Scenario scenario, ShpOptions.Index indexShape, - Set demandInformation, Population population, boolean combineSimilarJobs, - CoordinateTransformation crsTransformationNetworkAndShape) { + Set demandInformation, Population population, boolean combineSimilarJobs, + CoordinateTransformation crsTransformationNetworkAndShape, JobDurationCalculator jobDurationCalculator) { for (DemandInformationElement newDemandInformationElement : demandInformation) { log.info("Create demand for carrier {}", newDemandInformationElement.getCarrierName()); if (newDemandInformationElement.getTypeOfDemand().equals("service")) - createServices(scenario, newDemandInformationElement, indexShape, population, combineSimilarJobs, - crsTransformationNetworkAndShape); + createServices(scenario, newDemandInformationElement, indexShape, population, + crsTransformationNetworkAndShape, jobDurationCalculator); else if (newDemandInformationElement.getTypeOfDemand().equals("shipment")) - createShipments(scenario, newDemandInformationElement, indexShape, population, combineSimilarJobs, - crsTransformationNetworkAndShape); + createShipments(scenario, newDemandInformationElement, indexShape, population, + crsTransformationNetworkAndShape, jobDurationCalculator); } - + if (combineSimilarJobs) + combineSimilarJobs(scenario); + jobDurationCalculator.recalculateJobDurations(scenario); } /** * Creates the services. * - * @param scenario Scenario - * @param newDemandInformationElement single DemandInformationElement - * @param indexShape ShpOptions.Index - * @param population Population - * @param combineSimilarJobs boolean if the jobs of the same carrier with same location and time will be combined - * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file + * @param scenario Scenario + * @param newDemandInformationElement single DemandInformationElement + * @param indexShape ShpOptions.Index + * @param population Population + * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file + * @param jobDurationCalculator Calculator for the job duration */ private static void createServices(Scenario scenario, DemandInformationElement newDemandInformationElement, - ShpOptions.Index indexShape, Population population, boolean combineSimilarJobs, - CoordinateTransformation crsTransformationNetworkAndShape) { + ShpOptions.Index indexShape, Population population, + CoordinateTransformation crsTransformationNetworkAndShape, JobDurationCalculator jobDurationCalculator) { int countOfLinks = 1; int distributedDemand = 0; @@ -643,8 +648,8 @@ else if (samplingOption.equals("changeNumberOfLocationsWithDemand")) { Link link = findNextUsedLink(scenario, indexShape, possibleLinksForService, numberOfJobs, areasForServiceLocations, locationsOfServices, usedServiceLocations, possiblePersonsForService, nearestLinkPerPerson, crsTransformationNetworkAndShape, i); - double serviceTime = newDemandInformationElement.getFirstJobElementTimePerUnit(); int demandForThisLink = 1; + double serviceTime = jobDurationCalculator.calculateServiceDuration(newDemandInformationElement.getFirstJobElementTimePerUnit(), demandForThisLink); usedServiceLocations.add(link.getId().toString()); Id idNewService = Id.create( createJobId(scenario, newDemandInformationElement, link.getId(), null), @@ -673,13 +678,19 @@ else if (samplingOption.equals("changeNumberOfLocationsWithDemand")) { countOfLinks++; Carrier thisCarrier = CarriersUtils.getCarriers(scenario).getCarriers() .get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class)); - int numberOfJobsForDemand = calculateNumberOfJobsForDemand(thisCarrier, demandForThisLink); - for (int i = 0; i < numberOfJobsForDemand; i++) { - int singleDemandForThisLink = demandForThisLink / numberOfJobsForDemand; - if (i == numberOfJobsForDemand - 1) - singleDemandForThisLink = demandForThisLink - (numberOfJobsForDemand - 1) * singleDemandForThisLink; - double serviceTime = newDemandInformationElement.getFirstJobElementTimePerUnit() - * singleDemandForThisLink; + int handledDemand = 0; + //the number of jobs on this link is calculated based on the available vehicles + double largestPossibleDemandSize = getLargestVehicleCapacity(thisCarrier); + while (handledDemand < demandForThisLink) { + int singleDemandForThisLink; + if (demandForThisLink - handledDemand < largestPossibleDemandSize) + singleDemandForThisLink = demandForThisLink - handledDemand; + else + singleDemandForThisLink = (int)largestPossibleDemandSize; + handledDemand = handledDemand + singleDemandForThisLink; + double serviceTime = jobDurationCalculator.calculateServiceDuration( + newDemandInformationElement.getFirstJobElementTimePerUnit(), singleDemandForThisLink); + Id idNewService = Id.create( createJobId(scenario, newDemandInformationElement, link.getId(), null), CarrierService.class); @@ -718,16 +729,18 @@ else if (samplingOption.equals("changeNumberOfLocationsWithDemand")) { int demandForThisLink = calculateDemandForThisLink(demandToDistribute, numberOfJobs, distributedDemand, i); Carrier thisCarrier = CarriersUtils.getCarriers(scenario).getCarriers() .get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class)); - int numberOfJobsForDemand = calculateNumberOfJobsForDemand(thisCarrier, demandForThisLink); - for (int j = 0; j < numberOfJobsForDemand; j++) { - int singleDemandForThisLink = demandForThisLink / numberOfJobsForDemand; - if (j == numberOfJobsForDemand - 1) - singleDemandForThisLink = demandForThisLink - (numberOfJobsForDemand - 1) * singleDemandForThisLink; - double serviceTime; - if (singleDemandForThisLink == 0) - serviceTime = newDemandInformationElement.getFirstJobElementTimePerUnit(); + int handledDemand = 0; + //the number of jobs on this link is calculated based on the available vehicles + double largestPossibleDemandSize = getLargestVehicleCapacity(thisCarrier); + while (handledDemand < demandForThisLink || demandToDistribute == 0) { + int singleDemandForThisLink; + if (demandForThisLink - handledDemand < largestPossibleDemandSize) + singleDemandForThisLink = demandForThisLink - handledDemand; else - serviceTime = newDemandInformationElement.getFirstJobElementTimePerUnit() * demandForThisLink; + singleDemandForThisLink = (int)largestPossibleDemandSize; + handledDemand = handledDemand + singleDemandForThisLink; + double serviceTime = jobDurationCalculator.calculateServiceDuration( + newDemandInformationElement.getFirstJobElementTimePerUnit(), singleDemandForThisLink); usedServiceLocations.add(link.getId().toString()); Id idNewService = Id.create( @@ -740,28 +753,28 @@ else if (samplingOption.equals("changeNumberOfLocationsWithDemand")) { CarriersUtils.getCarriers(scenario).getCarriers() .get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class)).getServices() .put(thisService.getId(), thisService); + if (demandToDistribute == 0) + break; } } distributedDemand = distributedDemand + demandForThisLink; } } - if (combineSimilarJobs) - reduceNumberOfJobsIfSameCharacteristics(scenario, newDemandInformationElement); } /** * Creates the shipments of a carrier. * - * @param scenario Scenario - * @param newDemandInformationElement single DemandInformationElement - * @param indexShape ShpOptions.Index for the shape file - * @param population Population - * @param combineSimilarJobs boolean if the jobs of the same carrier with same location and time will be combined - * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file + * @param scenario Scenario + * @param newDemandInformationElement single DemandInformationElement + * @param indexShape ShpOptions.Index for the shape file + * @param population Population + * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file + * @param jobDurationCalculator Calculator for the job duration */ private static void createShipments(Scenario scenario, DemandInformationElement newDemandInformationElement, - ShpOptions.Index indexShape, Population population, boolean combineSimilarJobs, - CoordinateTransformation crsTransformationNetworkAndShape) { + ShpOptions.Index indexShape, Population population, + CoordinateTransformation crsTransformationNetworkAndShape, JobDurationCalculator jobDurationCalculator) { int countOfLinks = 1; int distributedDemand = 0; @@ -900,7 +913,7 @@ else if (population == null) if (!usedDeliveryLocations.contains(linkDelivery.getId().toString())) usedDeliveryLocations.add(linkDelivery.getId().toString()); - createSingleShipment(scenario, newDemandInformationElement, linkPickup, linkDelivery, demandForThisLink); + createSingleShipment(scenario, newDemandInformationElement, linkPickup, linkDelivery, demandForThisLink, jobDurationCalculator); } } else // creates a demand on each link, demand depends on the length of the link @@ -968,7 +981,7 @@ else if (numberOfPickupLocations != null) { if (demandForThisLink > 0) { createSingleShipment(scenario, newDemandInformationElement, linkPickup, linkDelivery, - demandForThisLink); + demandForThisLink, jobDurationCalculator); } distributedDemand = distributedDemand + demandForThisLink; } @@ -998,52 +1011,52 @@ else if (numberOfPickupLocations != null) { usedDeliveryLocations.add(linkDelivery.getId().toString()); createSingleShipment(scenario, newDemandInformationElement, linkPickup, linkDelivery, - demandForThisLink); + demandForThisLink, jobDurationCalculator); distributedDemand = distributedDemand + demandForThisLink; } } - if (combineSimilarJobs) - reduceNumberOfJobsIfSameCharacteristics(scenario, newDemandInformationElement); } - /** Creates a single shipment. + /** + * Creates a single shipment. + * * @param scenario Scenario * @param newDemandInformationElement single DemandInformationElement * @param linkPickup Link for the pickup * @param linkDelivery Link for the delivery * @param demandForThisLink Demand for this link + * @param jobDurationCalculator Calculator for the job duration */ private static void createSingleShipment(Scenario scenario, DemandInformationElement newDemandInformationElement, - Link linkPickup, Link linkDelivery, int demandForThisLink) { + Link linkPickup, Link linkDelivery, int demandForThisLink, JobDurationCalculator jobDurationCalculator) { Carrier thisCarrier = CarriersUtils.getCarriers(scenario).getCarriers() .get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class)); - int numberOfJobsForDemand = calculateNumberOfJobsForDemand(thisCarrier, demandForThisLink); - + double largestPossibleDemandSize = getLargestVehicleCapacity(thisCarrier); + int handledDemand = 0; TimeWindow timeWindowPickup = newDemandInformationElement.getFirstJobElementTimeWindow(); TimeWindow timeWindowDelivery = newDemandInformationElement.getSecondJobElementTimeWindow(); - for (int i = 0; i < numberOfJobsForDemand; i++) { + while (handledDemand < demandForThisLink || demandForThisLink == 0) { Id idNewShipment = Id.create(createJobId(scenario, newDemandInformationElement, linkPickup.getId(), linkDelivery.getId()), CarrierShipment.class); - double serviceTimePickup; - double serviceTimeDelivery; - int singleDemandForThisLink = Math.round ((float) demandForThisLink / numberOfJobsForDemand); - if (i == numberOfJobsForDemand - 1) - singleDemandForThisLink = demandForThisLink - (numberOfJobsForDemand - 1) * singleDemandForThisLink; - if (singleDemandForThisLink == 0) { - serviceTimePickup = newDemandInformationElement.getFirstJobElementTimePerUnit(); - serviceTimeDelivery = newDemandInformationElement.getSecondJobElementTimePerUnit(); - } else { - serviceTimePickup = newDemandInformationElement.getFirstJobElementTimePerUnit() * singleDemandForThisLink; - serviceTimeDelivery = newDemandInformationElement.getSecondJobElementTimePerUnit() * singleDemandForThisLink; - } + int singleDemandForThisLink; + if (demandForThisLink - handledDemand < largestPossibleDemandSize) + singleDemandForThisLink = demandForThisLink - handledDemand; + else + singleDemandForThisLink = (int)largestPossibleDemandSize; + handledDemand = handledDemand + singleDemandForThisLink; + double serviceTimePickup = jobDurationCalculator.calculatePickupDuration(newDemandInformationElement.getFirstJobElementTimePerUnit(), singleDemandForThisLink); + double serviceTimeDelivery = jobDurationCalculator.calculateDeliveryDuration(newDemandInformationElement.getSecondJobElementTimePerUnit(), singleDemandForThisLink); + CarrierShipment thisShipment = CarrierShipment.Builder .newInstance(idNewShipment, linkPickup.getId(), linkDelivery.getId(), singleDemandForThisLink) .setPickupServiceTime(serviceTimePickup).setPickupTimeWindow(timeWindowPickup) .setDeliveryServiceTime(serviceTimeDelivery).setDeliveryTimeWindow(timeWindowDelivery) .build(); thisCarrier.getShipments().put(thisShipment.getId(), thisShipment); + if (demandForThisLink == 0) + break; } } @@ -1051,21 +1064,16 @@ private static void createSingleShipment(Scenario scenario, DemandInformationEle * Method calculates the number of jobs for a demand on one link based on the largest vehicle capacity of the carrier. * * @param thisCarrier the carrier of a job - * @param demandForThisLink Demand for this link * @return Number of jobs for this demand */ - private static int calculateNumberOfJobsForDemand(Carrier thisCarrier, int demandForThisLink) { + private static double getLargestVehicleCapacity(Carrier thisCarrier) { double largestVehicleCapacity = 0; for (CarrierVehicle vehicle : thisCarrier.getCarrierCapabilities().getCarrierVehicles().values()) { if (vehicle.getType().getCapacity().getOther() > largestVehicleCapacity) { largestVehicleCapacity = vehicle.getType().getCapacity().getOther(); } } - if (demandForThisLink > largestVehicleCapacity) { - log.info("Demand {} is larger than the largest vehicle capacity ({}). Splitting demand into multiple jobs.", demandForThisLink, largestVehicleCapacity); - return (int) Math.ceil((double) demandForThisLink / largestVehicleCapacity); - } - return 1; + return largestVehicleCapacity; } /** @@ -1160,109 +1168,102 @@ private static int calculateDemandBasedOnLinkLength(int countOfLinks, int distri * If jobs of a carrier have the same characteristics (time window, location), * they will be combined to one job. * - * @param scenario Scenario - * @param newDemandInformationElement single DemandInformationElement + * @param scenario Scenario */ - private static void reduceNumberOfJobsIfSameCharacteristics(Scenario scenario, - DemandInformationElement newDemandInformationElement) { + private static void combineSimilarJobs(Scenario scenario) { log.warn( "The number of Jobs will be reduced if jobs have the same characteristics (e.g. time, location, carrier)"); - int connectedJobs = 0; - if (newDemandInformationElement.getTypeOfDemand().equals("shipment")) { - HashMap, CarrierShipment> shipmentsToRemove = new HashMap<>(); - ArrayList shipmentsToAdd = new ArrayList<>(); - Carrier thisCarrier = CarriersUtils.getCarriers(scenario).getCarriers() - .get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class)); - for (Id baseShipmentId : thisCarrier.getShipments().keySet()) { - if (!shipmentsToRemove.containsKey(baseShipmentId)) { - CarrierShipment baseShipment = thisCarrier.getShipments().get(baseShipmentId); - HashMap, CarrierShipment> shipmentsToConnect = new HashMap<>(); - shipmentsToConnect.put(baseShipmentId, baseShipment); - for (Id thisShipmentId : thisCarrier.getShipments().keySet()) { - if (!shipmentsToRemove.containsKey(thisShipmentId)) { - CarrierShipment thisShipment = thisCarrier.getShipments().get(thisShipmentId); - if (baseShipment.getId() != thisShipment.getId() + for (Carrier thisCarrier : CarriersUtils.getCarriers(scenario).getCarriers().values()) { + if (!thisCarrier.getShipments().isEmpty()) { + int shipmentsBeforeConnection = thisCarrier.getShipments().size(); + HashMap, CarrierShipment> shipmentsToRemove = new HashMap<>(); + ArrayList shipmentsToAdd = new ArrayList<>(); + for (Id baseShipmentId : thisCarrier.getShipments().keySet()) { + if (!shipmentsToRemove.containsKey(baseShipmentId)) { + CarrierShipment baseShipment = thisCarrier.getShipments().get(baseShipmentId); + HashMap, CarrierShipment> shipmentsToConnect = new HashMap<>(); + shipmentsToConnect.put(baseShipmentId, baseShipment); + for (Id thisShipmentId : thisCarrier.getShipments().keySet()) { + if (!shipmentsToRemove.containsKey(thisShipmentId)) { + CarrierShipment thisShipment = thisCarrier.getShipments().get(thisShipmentId); + if (baseShipment.getId() != thisShipment.getId() && baseShipment.getFrom() == thisShipment.getFrom() && baseShipment.getTo() == thisShipment.getTo() && baseShipment.getPickupTimeWindow() == thisShipment.getPickupTimeWindow() && baseShipment.getDeliveryTimeWindow() == thisShipment.getDeliveryTimeWindow()) - shipmentsToConnect.put(thisShipmentId, thisShipment); + shipmentsToConnect.put(thisShipmentId, thisShipment); + } } - } - Id idNewShipment = baseShipment.getId(); - int demandForThisLink = 0; - double serviceTimePickup = 0; - double serviceTimeDelivery = 0; - for (CarrierShipment carrierShipment : shipmentsToConnect.values()) { - demandForThisLink = demandForThisLink + carrierShipment.getSize(); - serviceTimePickup = serviceTimePickup + carrierShipment.getPickupServiceTime(); - serviceTimeDelivery = serviceTimeDelivery + carrierShipment.getDeliveryServiceTime(); - shipmentsToRemove.put(carrierShipment.getId(), carrierShipment); - connectedJobs++; - } - CarrierShipment newShipment = CarrierShipment.Builder + Id idNewShipment = baseShipment.getId(); + int demandForThisLink = 0; + double serviceTimePickup = 0; + double serviceTimeDelivery = 0; + for (CarrierShipment carrierShipment : shipmentsToConnect.values()) { + demandForThisLink = demandForThisLink + carrierShipment.getSize(); + serviceTimePickup = serviceTimePickup + carrierShipment.getPickupServiceTime(); + serviceTimeDelivery = serviceTimeDelivery + carrierShipment.getDeliveryServiceTime(); + shipmentsToRemove.put(carrierShipment.getId(), carrierShipment); + } + CarrierShipment newShipment = CarrierShipment.Builder .newInstance(idNewShipment, baseShipment.getFrom(), baseShipment.getTo(), demandForThisLink) .setPickupServiceTime(serviceTimePickup) .setPickupTimeWindow(baseShipment.getPickupTimeWindow()) .setDeliveryServiceTime(serviceTimeDelivery) .setDeliveryTimeWindow(baseShipment.getDeliveryTimeWindow()).build(); + shipmentsToAdd.add(newShipment); + } + } + for (CarrierShipment id : shipmentsToRemove.values()) + thisCarrier.getShipments().remove(id.getId(), id); - shipmentsToAdd.add(newShipment); - connectedJobs++; + for (CarrierShipment carrierShipment : shipmentsToAdd) { + thisCarrier.getShipments().put(carrierShipment.getId(), carrierShipment); } - } - for (CarrierShipment id : shipmentsToRemove.values()) - thisCarrier.getShipments().remove(id.getId(), id); - for (CarrierShipment carrierShipment : shipmentsToAdd) { - thisCarrier.getShipments().put(carrierShipment.getId(), carrierShipment); + log.warn("Number of reduced shipments for carrier {}: {}", thisCarrier.getId().toString(), shipmentsBeforeConnection - thisCarrier.getShipments().size()); } - log.warn("Number of reduced shipments: {}", connectedJobs); - } - if (newDemandInformationElement.getTypeOfDemand().equals("service")) { - HashMap, CarrierService> servicesToRemove = new HashMap<>(); - ArrayList servicesToAdd = new ArrayList<>(); - Carrier thisCarrier = CarriersUtils.getCarriers(scenario).getCarriers() - .get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class)); - for (Id baseServiceId : thisCarrier.getServices().keySet()) { - if (!servicesToRemove.containsKey(baseServiceId)) { - CarrierService baseService = thisCarrier.getServices().get(baseServiceId); - HashMap, CarrierService> servicesToConnect = new HashMap<>(); - servicesToConnect.put(baseServiceId, baseService); - for (Id thisServiceId : thisCarrier.getServices().keySet()) { - if (!servicesToRemove.containsKey(thisServiceId)) { - CarrierService thisService = thisCarrier.getServices().get(thisServiceId); - if (baseService.getId() != thisService.getId() + if (!thisCarrier.getServices().isEmpty()) { + int servicesBeforeConnection = thisCarrier.getServices().size(); + HashMap, CarrierService> servicesToRemove = new HashMap<>(); + ArrayList servicesToAdd = new ArrayList<>(); + for (Id baseServiceId : thisCarrier.getServices().keySet()) { + if (!servicesToRemove.containsKey(baseServiceId)) { + CarrierService baseService = thisCarrier.getServices().get(baseServiceId); + HashMap, CarrierService> servicesToConnect = new HashMap<>(); + servicesToConnect.put(baseServiceId, baseService); + for (Id thisServiceId : thisCarrier.getServices().keySet()) { + if (!servicesToRemove.containsKey(thisServiceId)) { + CarrierService thisService = thisCarrier.getServices().get(thisServiceId); + if (baseService.getId() != thisService.getId() && baseService.getLocationLinkId() == thisService.getLocationLinkId() && baseService - .getServiceStartTimeWindow() == thisService.getServiceStartTimeWindow()) - servicesToConnect.put(thisServiceId, thisService); + .getServiceStartTimeWindow() == thisService.getServiceStartTimeWindow()) + servicesToConnect.put(thisServiceId, thisService); + } } - } - Id idNewService = baseService.getId(); - int demandForThisLink = 0; - double serviceTimeService = 0; - for (CarrierService carrierService : servicesToConnect.values()) { - demandForThisLink = demandForThisLink + carrierService.getCapacityDemand(); - serviceTimeService = serviceTimeService + carrierService.getServiceDuration(); - servicesToRemove.put(carrierService.getId(), carrierService); - connectedJobs++; - } - CarrierService newService = CarrierService.Builder + Id idNewService = baseService.getId(); + int demandForThisLink = 0; + double serviceTimeService = 0; + for (CarrierService carrierService : servicesToConnect.values()) { + demandForThisLink = demandForThisLink + carrierService.getCapacityDemand(); + serviceTimeService = serviceTimeService + carrierService.getServiceDuration(); + servicesToRemove.put(carrierService.getId(), carrierService); + } + CarrierService newService = CarrierService.Builder .newInstance(idNewService, baseService.getLocationLinkId()) .setServiceDuration(serviceTimeService) .setServiceStartTimeWindow(baseService.getServiceStartTimeWindow()) .setCapacityDemand(demandForThisLink).build(); - servicesToAdd.add(newService); - connectedJobs++; + servicesToAdd.add(newService); + } } + for (CarrierService id : servicesToRemove.values()) + thisCarrier.getServices().remove(id.getId(), id); + for (CarrierService carrierService : servicesToAdd) { + thisCarrier.getServices().put(carrierService.getId(), carrierService); + } + log.warn("Number of reduced services for carrier {}: {}", thisCarrier.getId().toString(), servicesBeforeConnection - thisCarrier.getServices().size()); } - for (CarrierService id : servicesToRemove.values()) - thisCarrier.getServices().remove(id.getId(), id); - for (CarrierService carrierService : servicesToAdd) { - thisCarrier.getServices().put(carrierService.getId(), carrierService); - } - log.warn("Number of reduced shipments: {}", connectedJobs); } } diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java index 368dddaad69..d01a6226691 100644 --- a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java +++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java @@ -37,8 +37,8 @@ import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.geometry.CoordinateTransformation; import org.matsim.freight.carriers.*; -import org.matsim.freight.carriers.controler.CarrierModule; -import org.matsim.freight.carriers.controler.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.controller.CarrierModule; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; import org.matsim.freight.carriers.usecases.chessboard.CarrierScoringFunctionFactoryImpl; import picocli.CommandLine; @@ -62,6 +62,8 @@ + " * these files are given in the example project. See: TODO", showDefaultValues = true) public class FreightDemandGeneration implements MATSimAppCommand { + private final JobDurationCalculator jobDurationCalculator; + private enum CarrierInputOptions { readCarrierFile, createCarriersFromCSV, addCSVDataToExistingCarrierFileData } @@ -154,6 +156,16 @@ private enum OptionsOfVRPSolutions { @CommandLine.Option(names = "--defaultJspritIterations", description = "Set the default number of jsprit iterations.") private int defaultJspritIterations; + public FreightDemandGeneration() { + this.jobDurationCalculator = new DefaultJobDurationCalculator(); + log.info("Using default {} for job duration calculation", jobDurationCalculator.getClass().getSimpleName()); + } + + public FreightDemandGeneration(JobDurationCalculator jobDurationCalculator) { + this.jobDurationCalculator = jobDurationCalculator; + log.info("Using {} for job duration calculation", jobDurationCalculator.getClass().getSimpleName()); + } + public static void main(String[] args) { System.exit(new CommandLine(new FreightDemandGeneration()).execute(args)); } @@ -353,7 +365,7 @@ private void createDemand(DemandGenerationOptions selectedDemandGenerationOption case createDemandFromCSV -> // creates the demand by using the information given in the read csv file DemandReaderFromCSV.readAndCreateDemand(scenario, csvLocationDemand, indexShape, combineSimilarJobs, - crsTransformationNetworkAndShape, null, shapeCategory); + crsTransformationNetworkAndShape, null, shapeCategory, jobDurationCalculator); case createDemandFromCSVAndUsePopulation -> { /* * Option creates the demand by using the information given in the read csv file @@ -399,14 +411,14 @@ private void createDemand(DemandGenerationOptions selectedDemandGenerationOption case useHolePopulation: // uses the hole population as possible demand locations DemandReaderFromCSV.readAndCreateDemand(scenario, csvLocationDemand, indexShape, - combineSimilarJobs, crsTransformationNetworkAndShape, population, shapeCategory); + combineSimilarJobs, crsTransformationNetworkAndShape, population, shapeCategory, jobDurationCalculator); break; case usePopulationInShape: // uses only the population with home location in the given shape file FreightDemandGenerationUtils.reducePopulationToShapeArea(population, shp.createIndex(populationCRS, "_")); DemandReaderFromCSV.readAndCreateDemand(scenario, csvLocationDemand, indexShape, - combineSimilarJobs, crsTransformationNetworkAndShape, population, shapeCategory); + combineSimilarJobs, crsTransformationNetworkAndShape, population, shapeCategory, jobDurationCalculator); break; default: throw new RuntimeException("No valid population option selected!"); diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtils.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtils.java index c60a8a39390..ede28ace76d 100644 --- a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtils.java +++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtils.java @@ -152,7 +152,7 @@ static void createDemandLocationsFile(Controler controler) { writer.flush(); } catch (IOException e) { - e.printStackTrace(); + log.error("Could not write job locations file under " + "/outputLocationFile.xml.gz"); } log.info("Wrote job locations file under " + "/outputLocationFile.xml.gz"); } diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/JobDurationCalculator.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/JobDurationCalculator.java new file mode 100644 index 00000000000..85d30908fa0 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/JobDurationCalculator.java @@ -0,0 +1,39 @@ +package org.matsim.freightDemandGeneration; + +import org.matsim.api.core.v01.Scenario; + +public interface JobDurationCalculator { + /** + * Calculates the duration of a service in seconds. + * + * @param serviceDurationPerUnit in seconds + * @param demandForThisService amount of demand for this service + * @return duration in seconds + */ + double calculateServiceDuration(Integer serviceDurationPerUnit, int demandForThisService); + + /** + * Calculates the duration of a pickup in seconds. + * + * @param pickupDurationPerUnit in seconds + * @param demandForThisShipment amount of demand for this shipment + * @return duration in seconds + */ + double calculatePickupDuration(Integer pickupDurationPerUnit, int demandForThisShipment); + + /** + * Calculates the duration of a delivery in seconds. + * + * @param deliveryDurationPerUnit in seconds + * @param demandForThisShipment amount of demand for this shipment + * @return duration in seconds + */ + double calculateDeliveryDuration(Integer deliveryDurationPerUnit, int demandForThisShipment); + + /** + * Recalculates the job durations for all jobs in the scenario. The devault implementation does nothing. + * + * @param scenario scenario + */ + void recalculateJobDurations(Scenario scenario); +} diff --git a/contribs/application/src/test/java/org/matsim/freightDemandGeneration/DemandReaderFromCSVTest.java b/contribs/application/src/test/java/org/matsim/freightDemandGeneration/DemandReaderFromCSVTest.java index c27b251afc4..9cd21c16d9d 100644 --- a/contribs/application/src/test/java/org/matsim/freightDemandGeneration/DemandReaderFromCSVTest.java +++ b/contribs/application/src/test/java/org/matsim/freightDemandGeneration/DemandReaderFromCSVTest.java @@ -79,10 +79,10 @@ void demandCreationWithSampleWithChangeNumberOfLocations() throws IOException { String populationLocation = utils.getPackageInputDirectory() + "testPopulation.xml"; Population population = PopulationUtils.readPopulation(populationLocation); FreightDemandGenerationUtils.preparePopulation(population, 0.5, 1.0, "changeNumberOfLocationsWithDemand"); - + Boolean combineSimilarJobs = false; // run methods createDemandAndCheckCarrier(carrierCSVLocation, scenario, freightCarriersConfigGroup, indexShape, demandCSVLocation, shapeCategory, - population); + population, combineSimilarJobs); Network network = scenario.getNetwork(); @@ -147,10 +147,11 @@ void demandCreationWithSampleWithDemandOnLocation() throws IOException { String populationLocation = utils.getPackageInputDirectory() + "testPopulation.xml"; Population population = PopulationUtils.readPopulation(populationLocation); FreightDemandGenerationUtils.preparePopulation(population, 0.5, 1.0, "changeDemandOnLocation"); + Boolean combineSimilarJobs = false; - createDemandAndCheckCarrier(carrierCSVLocation, scenario, freightCarriersConfigGroup, indexShape, demandCSVLocation, shapeCategory, population); + createDemandAndCheckCarrier(carrierCSVLocation, scenario, freightCarriersConfigGroup, indexShape, demandCSVLocation, shapeCategory, + population, combineSimilarJobs); - // check carrier 1 Network network = scenario.getNetwork(); checkCarrier1and2(scenario, network, indexShape); @@ -194,6 +195,74 @@ void demandCreationWithSampleWithDemandOnLocation() throws IOException { } } + @Test + void demandCreationWithSampleWithDemandOnLocationWithCombiningJobs() throws IOException { + // read inputs + Config config = ConfigUtils.createConfig(); + config.network().setInputFile( + "https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"); + Scenario scenario = ScenarioUtils.loadScenario(config); + FreightCarriersConfigGroup freightCarriersConfigGroup = ConfigUtils.addOrGetModule(scenario.getConfig(), + FreightCarriersConfigGroup.class); + freightCarriersConfigGroup.setCarriersVehicleTypesFile(utils.getPackageInputDirectory() + "testVehicleTypes.xml"); + Path carrierCSVLocation = Path.of(utils.getPackageInputDirectory() + "testCarrierCSV.csv"); + Path demandCSVLocation = Path.of(utils.getPackageInputDirectory() + "testDemandCSV.csv"); + Path shapeFilePath = Path.of(utils.getPackageInputDirectory() + "testShape/testShape.shp"); + ShpOptions shp = new ShpOptions(shapeFilePath, "WGS84", null); + String shapeCategory = "Ortsteil"; + ShpOptions.Index indexShape = shp.createIndex("Ortsteil"); + String populationLocation = utils.getPackageInputDirectory() + "testPopulation.xml"; + Population population = PopulationUtils.readPopulation(populationLocation); + FreightDemandGenerationUtils.preparePopulation(population, 0.5, 1.0, "changeDemandOnLocation"); + Boolean combineSimilarJobs = true; + + createDemandAndCheckCarrier(carrierCSVLocation, scenario, freightCarriersConfigGroup, indexShape, demandCSVLocation, shapeCategory, + population, combineSimilarJobs); + + Network network = scenario.getNetwork(); + + checkCarrier1and2WithCombiningJobs(scenario, network, indexShape); + int countDemand; + Object2IntMap countShipmentsWithCertainDemand; + Map> locationsPerShipmentElement; + + // check carrier 3 + Carrier testCarrier3 = CarriersUtils.getCarriers(scenario).getCarriers() + .get(Id.create("testCarrier3", Carrier.class)); + Assertions.assertEquals(0, testCarrier3.getServices().size()); + Assertions.assertEquals(2, testCarrier3.getShipments().size()); + countShipmentsWithCertainDemand = new Object2IntOpenHashMap<>(); + locationsPerShipmentElement = new HashMap<>(); + countDemand = 0; + for (CarrierShipment shipment : testCarrier3.getShipments().values()) { + countShipmentsWithCertainDemand.merge((Integer) shipment.getSize(), 1, Integer::sum); + countDemand = countDemand + shipment.getSize(); + Assertions.assertEquals(10, shipment.getSize()); + Assertions.assertEquals(4000, shipment.getPickupServiceTime(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(2500, shipment.getDeliveryServiceTime(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(TimeWindow.newInstance(8000, 50000), shipment.getPickupTimeWindow()); + Assertions.assertEquals(TimeWindow.newInstance(10000, 60000), shipment.getDeliveryTimeWindow()); + locationsPerShipmentElement.computeIfAbsent("ShipmentElement1_pickup", (k) -> new HashSet<>()) + .add(shipment.getFrom().toString()); + locationsPerShipmentElement.computeIfAbsent("ShipmentElement1_delivery", (k) -> new HashSet<>()) + .add(shipment.getTo().toString()); + } + Assertions.assertEquals(20, countDemand); + Assertions.assertEquals(2, countShipmentsWithCertainDemand.getInt(10)); + Assertions.assertEquals(1, locationsPerShipmentElement.get("ShipmentElement1_pickup").size()); + Assertions.assertEquals(2, locationsPerShipmentElement.get("ShipmentElement1_delivery").size()); + for (String locationsOfShipmentElement : locationsPerShipmentElement.get("ShipmentElement1_delivery")) { + Link link = network.getLinks().get(Id.createLinkId(locationsOfShipmentElement)); + Assertions.assertTrue( + FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, null, null)); + Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, + new String[] { "area1" }, null)); + Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, + new String[] { "area2" }, null)); + } + } + + @Test void demandCreationNoSampling() throws IOException { // read inputs @@ -213,10 +282,11 @@ void demandCreationNoSampling() throws IOException { String populationLocation = utils.getPackageInputDirectory() + "testPopulation.xml"; Population population = PopulationUtils.readPopulation(populationLocation); FreightDemandGenerationUtils.preparePopulation(population, 0.5, 0.5, "changeDemandOnLocation"); + Boolean combineSimilarJobs = false; // run methods createDemandAndCheckCarrier(carrierCSVLocation, scenario, freightCarriersConfigGroup, indexShape, demandCSVLocation, shapeCategory, - population); + population, combineSimilarJobs); // check carrier 1 Network network = scenario.getNetwork(); @@ -367,7 +437,8 @@ void csvDemandReader() throws IOException { private static void createDemandAndCheckCarrier(Path carrierCSVLocation, Scenario scenario, FreightCarriersConfigGroup freightCarriersConfigGroup, ShpOptions.Index indexShape, Path demandCSVLocation, String shapeCategory, - Population population) throws IOException { + Population population, Boolean combineSimilarJobs) throws IOException { + JobDurationCalculator jobDurationCalculator = new DefaultJobDurationCalculator(); // run methods Set allNewCarrierInformation = CarrierReaderFromCSV .readCarrierInformation(carrierCSVLocation); @@ -375,8 +446,8 @@ private static void createDemandAndCheckCarrier(Path carrierCSVLocation, Scenari indexShape, 1, null); Set demandInformation = DemandReaderFromCSV.readDemandInformation(demandCSVLocation); DemandReaderFromCSV.checkNewDemand(scenario, demandInformation, indexShape, shapeCategory); - DemandReaderFromCSV.createDemandForCarriers(scenario, indexShape, demandInformation, population, false, - null); + DemandReaderFromCSV.createDemandForCarriers(scenario, indexShape, demandInformation, population, combineSimilarJobs, + null, jobDurationCalculator); Assertions.assertEquals(3, CarriersUtils.getCarriers(scenario).getCarriers().size()); Assertions.assertTrue( CarriersUtils.getCarriers(scenario).getCarriers().containsKey(Id.create("testCarrier1", Carrier.class))); @@ -491,4 +562,89 @@ private static void checkCarrier1and2(Scenario scenario, Network network, ShpOpt Assertions.assertEquals(1, locationsPerShipmentElement.get("ShipmentElement2_pickup").size()); Assertions.assertEquals(2, locationsPerShipmentElement.get("ShipmentElement2_delivery").size()); } + + /** + * Results after combing jobs. + * + * @param scenario the scenario + * @param network the network + * @param indexShape the index of the shape + */ + private static void checkCarrier1and2WithCombiningJobs(Scenario scenario, Network network, ShpOptions.Index indexShape) { + Carrier testCarrier1 = CarriersUtils.getCarriers(scenario).getCarriers() + .get(Id.create("testCarrier1", Carrier.class)); + Assertions.assertEquals(8, testCarrier1.getServices().size()); + Assertions.assertEquals(0, testCarrier1.getShipments().size()); + Object2IntMap countServicesWithCertainDemand = new Object2IntOpenHashMap<>(); + Map> locationsPerServiceElement = new HashMap<>(); + int countDemand = 0; + for (CarrierService service : testCarrier1.getServices().values()) { + countServicesWithCertainDemand.merge((Integer) service.getCapacityDemand(), 1, Integer::sum); + countDemand = countDemand + service.getCapacityDemand(); + if (service.getCapacityDemand() == 0) { + Assertions.assertEquals(180, service.getServiceDuration(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(TimeWindow.newInstance(3000, 13000), service.getServiceStartTimeWindow()); + locationsPerServiceElement.computeIfAbsent("serviceElement1", (k) -> new HashSet<>()) + .add(service.getLocationLinkId().toString()); + } else { + Assertions.assertEquals(service.getCapacityDemand() * 100, service.getServiceDuration(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(TimeWindow.newInstance(5000, 20000), service.getServiceStartTimeWindow()); + locationsPerServiceElement.computeIfAbsent("serviceElement2", (k) -> new HashSet<>()) + .add(service.getLocationLinkId().toString()); + } + } + Assertions.assertEquals(12, countDemand); + Assertions.assertEquals(4, countServicesWithCertainDemand.getInt(0)); + Assertions.assertEquals(4, locationsPerServiceElement.get("serviceElement1").size()); + for (String locationsOfServiceElement : locationsPerServiceElement.get("serviceElement1")) { + Link link = network.getLinks().get(Id.createLinkId(locationsOfServiceElement)); + Assertions.assertTrue( + FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, null, null)); + Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, + new String[] { "area1" }, null)); + Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, + new String[] { "area2" }, null)); + } + Assertions.assertEquals(4, locationsPerServiceElement.get("serviceElement2").size()); + Assertions.assertTrue(locationsPerServiceElement.get("serviceElement2").contains("i(2,0)")); + + // check carrier 2 + Carrier testCarrier2 = CarriersUtils.getCarriers(scenario).getCarriers() + .get(Id.create("testCarrier2", Carrier.class)); + Assertions.assertEquals(0, testCarrier2.getServices().size()); + Assertions.assertEquals(6, testCarrier2.getShipments().size()); + Object2IntMap countShipmentsWithCertainDemand = new Object2IntOpenHashMap<>(); + Map> locationsPerShipmentElement = new HashMap<>(); + countDemand = 0; + for (CarrierShipment shipment : testCarrier2.getShipments().values()) { + countShipmentsWithCertainDemand.merge((Integer) shipment.getSize(), 1, Integer::sum); + countDemand = countDemand + shipment.getSize(); + if (shipment.getSize() == 0) { + Assertions.assertEquals(300, shipment.getPickupServiceTime(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(350, shipment.getDeliveryServiceTime(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(TimeWindow.newInstance(10000, 45000), shipment.getPickupTimeWindow()); + Assertions.assertEquals(TimeWindow.newInstance(11000, 44000), shipment.getDeliveryTimeWindow()); + locationsPerShipmentElement.computeIfAbsent("ShipmentElement1_pickup", (k) -> new HashSet<>()) + .add(shipment.getFrom().toString()); + locationsPerShipmentElement.computeIfAbsent("ShipmentElement1_delivery", (k) -> new HashSet<>()) + .add(shipment.getTo().toString()); + } else { + Assertions.assertEquals(shipment.getSize() * 200, shipment.getPickupServiceTime(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(shipment.getSize() * 200, shipment.getDeliveryServiceTime(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(TimeWindow.newInstance(11000, 44000), shipment.getPickupTimeWindow()); + Assertions.assertEquals(TimeWindow.newInstance(20000, 40000), shipment.getDeliveryTimeWindow()); + locationsPerShipmentElement.computeIfAbsent("ShipmentElement2_pickup", (k) -> new HashSet<>()) + .add(shipment.getFrom().toString()); + locationsPerShipmentElement.computeIfAbsent("ShipmentElement2_delivery", (k) -> new HashSet<>()) + .add(shipment.getTo().toString()); + } + } + Assertions.assertEquals(15, countDemand); + Assertions.assertEquals(4, countShipmentsWithCertainDemand.getInt(0)); + Assertions.assertEquals(4, locationsPerShipmentElement.get("ShipmentElement1_pickup").size()); + Assertions.assertEquals(1, locationsPerShipmentElement.get("ShipmentElement1_delivery").size()); + Assertions.assertTrue(locationsPerShipmentElement.get("ShipmentElement1_delivery").contains("i(2,0)")); + Assertions.assertEquals(1, locationsPerShipmentElement.get("ShipmentElement2_pickup").size()); + Assertions.assertEquals(2, locationsPerShipmentElement.get("ShipmentElement2_delivery").size()); + } } diff --git a/contribs/av/pom.xml b/contribs/av/pom.xml index 1536e9e78ef..590c8f7e7a1 100644 --- a/contribs/av/pom.xml +++ b/contribs/av/pom.xml @@ -16,19 +16,19 @@ org.matsim.contrib dvrp - 2025.0-SNAPSHOT + ${project.parent.version} compile org.matsim.contrib taxi - 2025.0-SNAPSHOT + ${project.parent.version} compile org.matsim.contrib drt - 2025.0-SNAPSHOT + ${project.parent.version} compile diff --git a/contribs/bicycle/pom.xml b/contribs/bicycle/pom.xml index f3ffdc96601..9bd3a41df5e 100644 --- a/contribs/bicycle/pom.xml +++ b/contribs/bicycle/pom.xml @@ -23,7 +23,7 @@ org.matsim.contrib osm - 2025.0-SNAPSHOT + ${project.parent.version} compile diff --git a/contribs/cadytsIntegration/pom.xml b/contribs/cadytsIntegration/pom.xml index 2d4b716db7e..5fba4fc8e57 100644 --- a/contribs/cadytsIntegration/pom.xml +++ b/contribs/cadytsIntegration/pom.xml @@ -17,7 +17,7 @@ org.matsim.contrib analysis - 2025.0-SNAPSHOT + ${project.parent.version} 2012 diff --git a/contribs/cadytsIntegration/src/main/java/org/matsim/contrib/cadyts/car/PlansTranslatorBasedOnEvents.java b/contribs/cadytsIntegration/src/main/java/org/matsim/contrib/cadyts/car/PlansTranslatorBasedOnEvents.java index 90327b37b1e..1a325f8b4fe 100644 --- a/contribs/cadytsIntegration/src/main/java/org/matsim/contrib/cadyts/car/PlansTranslatorBasedOnEvents.java +++ b/contribs/cadytsIntegration/src/main/java/org/matsim/contrib/cadyts/car/PlansTranslatorBasedOnEvents.java @@ -59,8 +59,6 @@ public final class PlansTranslatorBasedOnEvents implements PlansTranslator private int iteration = -1; - // this is _only_ there for output: - Set plansEverSeen = new HashSet<>(); private static final String STR_PLANSTEPFACTORY = "planStepFactory"; private static final String STR_ITERATION = "iteration"; @@ -167,9 +165,6 @@ private PlanBuilder getPlanStepFactoryForPlan(final Plan selectedPlan) { // construct a new PlanBulder and attach it to the plan: planStepFactory = new PlanBuilder(); selectedPlan.getCustomAttributes().put(STR_PLANSTEPFACTORY, planStepFactory); - - // memorize the plan as being seen: - this.plansEverSeen.add(selectedPlan); } return planStepFactory; diff --git a/contribs/carsharing/pom.xml b/contribs/carsharing/pom.xml index 2580047b892..54eb37ac992 100644 --- a/contribs/carsharing/pom.xml +++ b/contribs/carsharing/pom.xml @@ -12,7 +12,7 @@ org.matsim.contrib dvrp - 2025.0-SNAPSHOT + ${project.parent.version} diff --git a/contribs/commercialTrafficApplications/pom.xml b/contribs/commercialTrafficApplications/pom.xml index 2d6f1061274..4804f34b6d9 100644 --- a/contribs/commercialTrafficApplications/pom.xml +++ b/contribs/commercialTrafficApplications/pom.xml @@ -14,13 +14,13 @@ org.matsim.contrib freight - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib drt - 2025.0-SNAPSHOT + ${project.parent.version} diff --git a/contribs/commercialTrafficApplications/src/test/java/org/matsim/contrib/commercialTrafficApplications/jointDemand/TestScenarioGeneration.java b/contribs/commercialTrafficApplications/src/test/java/org/matsim/contrib/commercialTrafficApplications/jointDemand/TestScenarioGeneration.java index 1d6b845a665..601038f2f73 100644 --- a/contribs/commercialTrafficApplications/src/test/java/org/matsim/contrib/commercialTrafficApplications/jointDemand/TestScenarioGeneration.java +++ b/contribs/commercialTrafficApplications/src/test/java/org/matsim/contrib/commercialTrafficApplications/jointDemand/TestScenarioGeneration.java @@ -126,8 +126,6 @@ private static CarrierVehicle getLightVehicle(Id id, VehicleType type, Id zones = new IdMap<>(Zone.class); - private final IdMap> zoneToLinksMap = new IdMap<>(Zone.class); + private final Map> index2Links; private final Network network; @@ -76,6 +77,7 @@ public SquareGridZoneSystem(Network network, double cellSize, boolean filterByNe this.rows = Math.max(1, (int) Math.ceil((maxY - minY) / cellSize)); this.cols = Math.max(1, (int)Math.ceil((maxX - minX) / cellSize)); this.internalZones = new Zone[rows * cols +1]; + this.index2Links = getIndexToLink(network); if(filterByNetwork) { network.getLinks().values().forEach(l -> getOrCreateZone(l.getToNode().getCoord())); @@ -111,7 +113,7 @@ public Optional getZoneForCoord(Coord coord) { @Override public List getLinksForZoneId(Id zone) { - return zoneToLinksMap.get(zone); + return this.index2Links.get(Integer.parseInt(zone.toString())); } private Optional getOrCreateZone(Coord coord) { @@ -126,13 +128,6 @@ private Optional getOrCreateZone(Coord coord) { if(zoneFilter.test(zone)) { internalZones[index] = zone; zones.put(zone.getId(), zone); - - for (Link link : network.getLinks().values()) { - if (getIndex(link.getToNode().getCoord()) == index) { - List links = zoneToLinksMap.computeIfAbsent(zone.getId(), zoneId -> new ArrayList<>()); - links.add(link); - } - } } else { return Optional.empty(); } @@ -140,6 +135,11 @@ private Optional getOrCreateZone(Coord coord) { return Optional.of(zone); } + private Map> getIndexToLink(Network network) { + return network.getLinks().values().stream() + .collect(Collectors.groupingBy(link -> getIndex(link.getToNode().getCoord()))); + } + private PreparedPolygon getGeometry(int r, int c) { List coords = new ArrayList<>(); coords.add(new Coord(minX + c * cellSize, minY + r * cellSize)); diff --git a/contribs/decongestion/pom.xml b/contribs/decongestion/pom.xml index 62d2f912040..992bd7c6a12 100644 --- a/contribs/decongestion/pom.xml +++ b/contribs/decongestion/pom.xml @@ -8,7 +8,7 @@ org.matsim.contrib otfvis - ${parent.version} + ${project.parent.version} test diff --git a/contribs/discrete_mode_choice/src/test/java/org/matsim/contrib/discrete_mode_choice/DeterminismTest.java b/contribs/discrete_mode_choice/src/test/java/org/matsim/contrib/discrete_mode_choice/DeterminismTest.java new file mode 100644 index 00000000000..bebc456de8f --- /dev/null +++ b/contribs/discrete_mode_choice/src/test/java/org/matsim/contrib/discrete_mode_choice/DeterminismTest.java @@ -0,0 +1,55 @@ +package org.matsim.contrib.discrete_mode_choice; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Scenario; +import org.matsim.contribs.discrete_mode_choice.modules.DiscreteModeChoiceModule; +import org.matsim.contribs.discrete_mode_choice.modules.ModeAvailabilityModule; +import org.matsim.contribs.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.controler.Controler; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.core.utils.misc.CRCChecksum; +import org.matsim.examples.ExamplesUtils; + +import java.net.URL; + +public class DeterminismTest { + private static void runConfig(URL configUrl, String outputDirectory) { + Config config = ConfigUtils.loadConfig(configUrl, new DiscreteModeChoiceConfigGroup()); + config.controller().setLastIteration(2); + config.controller().setOutputDirectory(outputDirectory); + config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + Scenario scenario = ScenarioUtils.createScenario(config); + ScenarioUtils.loadScenario(scenario); + Controler controler = new Controler(scenario); + controler.addOverridingModule(new DiscreteModeChoiceModule()); + controler.addOverridingModule(new ModeAvailabilityModule()); + controler.run(); + } + + + @Test + public void testSimulationDeterminism() { + Logger logger = LogManager.getLogger(DeterminismTest.class); + logger.info("Testing simulation determinism"); + URL configUrl = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("siouxfalls-2014"), "config_default.xml"); + int samples = 10; + for(int i=0; i org.matsim.contrib drt - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib ev - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib informed-mode-choice - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib simwrapper - 2025.0-SNAPSHOT + ${project.parent.version} @@ -45,7 +45,7 @@ org.matsim.contrib vsp - 2025.0-SNAPSHOT + ${project.parent.version} test diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtDashboard.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtDashboard.java index 6131d9f0edd..d20c0192c3e 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtDashboard.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtDashboard.java @@ -134,7 +134,7 @@ public void configure(Header header, Layout layout) { viz.title = "Spatial rejection distribution"; viz.description = "Requested (and rejected) origins and destinations."; viz.projection = this.crs; - viz.file = data.output("ITERS/it." + lastIteration + "/*rejections_" + drtConfigGroup.mode + ".csv"); + viz.file = data.output("*rejections_" + drtConfigGroup.mode + ".csv"); viz.addAggregation("rejections", "origins", "fromX", "fromY", "destinations", "toX", "toY"); viz.center = data.context().getCenter(); @@ -222,7 +222,7 @@ public void configure(Header header, Layout layout) { .el(Area.class, (viz, data) -> { viz.title = "Vehicle occupancy"; //actually, without title the area plot won't work viz.description = "Number of passengers on board at a time"; - viz.dataset = data.output("ITERS/it." + lastIteration + "/*occupancy_time_profiles_" + drtConfigGroup.mode + ".txt"); + viz.dataset = data.output("/*occupancy_time_profiles_" + drtConfigGroup.mode + ".txt"); viz.x = "time"; viz.xAxisName = "Time"; viz.yAxisName = "Vehicles [1]"; diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/fiss/RunFissDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/fiss/RunFissDrtScenarioIT.java index 120cff4f5a3..1c46945920b 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/fiss/RunFissDrtScenarioIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/fiss/RunFissDrtScenarioIT.java @@ -139,7 +139,7 @@ void test() { config.controller().setWriteEventsInterval(1); config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); - config.controller().setOutputDirectory("test/output/holzkirchen_shifts"); + config.controller().setOutputDirectory("test/output/RunFissDrtScenarioIT"); DrtOperationsParams operationsParams = (DrtOperationsParams) drtWithShiftsConfigGroup.createParameterSet(DrtOperationsParams.SET_NAME); ShiftsParams shiftsParams = (ShiftsParams) operationsParams.createParameterSet(ShiftsParams.SET_NAME); 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 01f5e27b837..61e3a64a97a 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 @@ -71,7 +71,7 @@ void testWithReattempts() { MultiModeDrtConfigGroup multiModeDrtConfigGroup = new MultiModeDrtConfigGroup(DrtWithExtensionsConfigGroup::new); DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup = (DrtWithExtensionsConfigGroup) multiModeDrtConfigGroup.createParameterSet("drt"); - final Controler run = prepare(drtWithShiftsConfigGroup, multiModeDrtConfigGroup); + final Controler run = prepare(drtWithShiftsConfigGroup, multiModeDrtConfigGroup, "_testWithReattempts"); Multiset> submittedPersons = HashMultiset.create(); Multiset> scheduledPersons = HashMultiset.create(); @@ -125,7 +125,7 @@ void testWithoutReattempts() { MultiModeDrtConfigGroup multiModeDrtConfigGroup = new MultiModeDrtConfigGroup(DrtWithExtensionsConfigGroup::new); DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup = (DrtWithExtensionsConfigGroup) multiModeDrtConfigGroup.createParameterSet("drt"); - final Controler run = prepare(drtWithShiftsConfigGroup, multiModeDrtConfigGroup); + final Controler run = prepare(drtWithShiftsConfigGroup, multiModeDrtConfigGroup, "_testWithoutReattempts"); Multiset> submittedPersons = HashMultiset.create(); Multiset> scheduledPersons = HashMultiset.create(); @@ -175,7 +175,7 @@ public void install() { } @NotNull - private Controler prepare(DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup, MultiModeDrtConfigGroup multiModeDrtConfigGroup) { + private Controler prepare(DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup, MultiModeDrtConfigGroup multiModeDrtConfigGroup, String outputSuffix) { drtWithShiftsConfigGroup.mode = TransportMode.drt; DefaultDrtOptimizationConstraintsSet defaultConstraintsSet = (DefaultDrtOptimizationConstraintsSet) drtWithShiftsConfigGroup.addOrGetDrtOptimizationConstraintsParams() @@ -245,7 +245,7 @@ private Controler prepare(DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup, config.controller().setWriteEventsInterval(1); config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); - config.controller().setOutputDirectory("test/output/prebooking_shifts"); + config.controller().setOutputDirectory("test/output/prebooking_shifts"+outputSuffix); DrtOperationsParams operationsParams = (DrtOperationsParams) drtWithShiftsConfigGroup.createParameterSet(DrtOperationsParams.SET_NAME); ShiftsParams shiftsParams = (ShiftsParams) operationsParams.createParameterSet(ShiftsParams.SET_NAME); diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunShiftDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunShiftDrtScenarioIT.java index acfc878a000..6f10693a452 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunShiftDrtScenarioIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunShiftDrtScenarioIT.java @@ -132,7 +132,7 @@ void test() { config.controller().setWriteEventsInterval(1); config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); - config.controller().setOutputDirectory("test/output/holzkirchen_shifts"); + config.controller().setOutputDirectory("test/output/RunShiftDrtScenarioIT"); DrtOperationsParams operationsParams = (DrtOperationsParams) drtWithShiftsConfigGroup.createParameterSet(DrtOperationsParams.SET_NAME); ShiftsParams shiftsParams = (ShiftsParams) operationsParams.createParameterSet(ShiftsParams.SET_NAME); diff --git a/contribs/drt/pom.xml b/contribs/drt/pom.xml index 7790f252b3c..99fd9d77ec7 100644 --- a/contribs/drt/pom.xml +++ b/contribs/drt/pom.xml @@ -15,19 +15,19 @@ org.matsim.contrib dvrp - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib otfvis - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib common - 2025.0-SNAPSHOT + ${project.parent.version} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalWaitTimesAnalyzer.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalWaitTimesAnalyzer.java index ce140ce1772..610511c61e2 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalWaitTimesAnalyzer.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalWaitTimesAnalyzer.java @@ -37,6 +37,7 @@ import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector; import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector.EventSequence; import org.matsim.contrib.drt.run.DrtConfigGroup; +import org.matsim.contrib.dvrp.optimizer.Request; import org.matsim.core.controler.events.IterationEndsEvent; import org.matsim.core.controler.events.ShutdownEvent; import org.matsim.core.controler.listener.IterationEndsListener; @@ -79,7 +80,7 @@ public void notifyIterationEnds(IterationEndsEvent event) { } public void write(String fileName) { - Map, DescriptiveStatistics> zoneStats = createZonalStats(); + Map, ZonalStatistics> zoneStats = createZonalStats(); BufferedWriter bw = IOUtils.getBufferedWriter(fileName); try { DecimalFormat format = new DecimalFormat(); @@ -90,7 +91,8 @@ public void write(String fileName) { String header = new StringJoiner(delimiter) .add("zone").add("centerX").add("centerY").add("nRequests") .add("sumWaitTime").add("meanWaitTime").add("min").add("max") - .add("p95").add("p90").add("p80").add("p75").add("p50").toString(); + .add("p95").add("p90").add("p80").add("p75").add("p50") + .add("rejections").add("rejectionRate").toString(); bw.append(header); // sorted output SortedSet> zoneIdsAndOutside = new TreeSet<>(zones.getZones().keySet()); @@ -100,7 +102,8 @@ public void write(String fileName) { Zone drtZone = zones.getZones().get(zoneId); String centerX = drtZone != null ? String.valueOf(drtZone.getCentroid().getX()) : notAvailableString; String centerY = drtZone != null ? String.valueOf(drtZone.getCentroid().getY()) : notAvailableString; - DescriptiveStatistics stats = zoneStats.get(zoneId); + DescriptiveStatistics stats = zoneStats.get(zoneId).waitStats; + Set> rejections = zoneStats.get(zoneId).rejections; bw.newLine(); bw.append( new StringJoiner(delimiter) @@ -116,7 +119,10 @@ public void write(String fileName) { .add(String.valueOf(stats.getPercentile(90))) .add(String.valueOf(stats.getPercentile(80))) .add(String.valueOf(stats.getPercentile(75))) - .add(String.valueOf(stats.getPercentile(50))).toString() + .add(String.valueOf(stats.getPercentile(50))) + .add(String.valueOf(rejections.size())) + .add(String.valueOf(rejections.size() / (double) (rejections.size() + stats.getN()))) + .toString() ); } bw.flush(); @@ -126,13 +132,15 @@ public void write(String fileName) { } } - private Map, DescriptiveStatistics> createZonalStats() { - Map, DescriptiveStatistics> zoneStats = new IdMap<>(Zone.class); + record ZonalStatistics(DescriptiveStatistics waitStats, Set> rejections){} + + private Map, ZonalStatistics> createZonalStats() { + Map, ZonalStatistics> zoneStats = new IdMap<>(Zone.class); // prepare stats for all zones for (Id zoneId : zones.getZones().keySet()) { - zoneStats.put(zoneId, new DescriptiveStatistics()); + zoneStats.put(zoneId, new ZonalStatistics(new DescriptiveStatistics(), new HashSet<>())); } - zoneStats.put(zoneIdForOutsideOfZonalSystem, new DescriptiveStatistics()); + zoneStats.put(zoneIdForOutsideOfZonalSystem, new ZonalStatistics(new DescriptiveStatistics(), new HashSet<>())); for (EventSequence seq : requestAnalyzer.getPerformedRequestSequences().values()) { for (Map.Entry, EventSequence.PersonEvents> entry : seq.getPersonEvents().entrySet()) { @@ -140,10 +148,17 @@ private Map, DescriptiveStatistics> createZonalStats() { Id zone = zones.getZoneForLinkId(seq.getSubmitted().getFromLinkId()) .map(Identifiable::getId).orElse(zoneIdForOutsideOfZonalSystem); double waitTime = entry.getValue().getPickedUp().get() .getTime() - seq.getSubmitted().getTime(); - zoneStats.get(zone).addValue(waitTime); + zoneStats.get(zone).waitStats.addValue(waitTime); } } } + + for (EventSequence seq : requestAnalyzer.getRejectedRequestSequences().values()) { + Id zone = zones.getZoneForLinkId(seq.getSubmitted().getFromLinkId()) + .map(Identifiable::getId).orElse(zoneIdForOutsideOfZonalSystem); + zoneStats.get(zone).rejections.add(seq.getSubmitted().getRequestId()); + } + return zoneStats; } @@ -191,16 +206,19 @@ private Collection convertGeometriesToSimpleFeatures(String targe simpleFeatureBuilder.add("p80", Double.class); simpleFeatureBuilder.add("p75", Double.class); simpleFeatureBuilder.add("p50", Double.class); + simpleFeatureBuilder.add("rejections", Double.class); + simpleFeatureBuilder.add("rejectRate", Double.class); SimpleFeatureBuilder builder = new SimpleFeatureBuilder(simpleFeatureBuilder.buildFeatureType()); Collection features = new ArrayList<>(); - Map, DescriptiveStatistics> zoneStats = createZonalStats(); + Map, ZonalStatistics> zoneStats = createZonalStats(); for (Zone zone : zones.getZones().values()) { - Object[] routeFeatureAttributes = new Object[14]; + Object[] routeFeatureAttributes = new Object[16]; Geometry geometry = zone.getPreparedGeometry() != null ? zone.getPreparedGeometry().getGeometry() : null; - DescriptiveStatistics stats = zoneStats.get(zone.getId()); + DescriptiveStatistics stats = zoneStats.get(zone.getId()).waitStats; + Set> rejections = zoneStats.get(zone.getId()).rejections; routeFeatureAttributes[0] = geometry; routeFeatureAttributes[1] = zone.getId(); routeFeatureAttributes[2] = zone.getCentroid().getX(); @@ -215,6 +233,8 @@ private Collection convertGeometriesToSimpleFeatures(String targe routeFeatureAttributes[11] = stats.getPercentile(80); routeFeatureAttributes[12] = stats.getPercentile(75); routeFeatureAttributes[13] = stats.getPercentile(50); + routeFeatureAttributes[14] = rejections.size(); + routeFeatureAttributes[15] = rejections.size() / (double) (rejections.size() + stats.getN()); try { features.add(builder.buildFeature(zone.getId().toString(), routeFeatureAttributes)); diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/plusOne/PlusOneRebalancingStrategy.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/plusOne/PlusOneRebalancingStrategy.java index 2c67ee8640f..12469c783fb 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/plusOne/PlusOneRebalancingStrategy.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/rebalancing/plusOne/PlusOneRebalancingStrategy.java @@ -99,7 +99,9 @@ public void handleEvent(DrtRequestSubmittedEvent event) { public void handleEvent(PassengerRequestScheduledEvent event) { if (event.getMode().equals(mode)) { Id linkId = potentialTargetLinks.remove(event.getRequestId()); - targets.add(new Target(linkId, event.getTime())); + if(linkId != null) { + targets.add(new Target(linkId, event.getTime())); + } } } 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 04d8df45161..a5dad2f114b 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 @@ -395,13 +395,23 @@ private void processRejections(double now) { 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); + + int index = WithinDayAgentUtils.getCurrentPlanElementIndex(agent); + Plan plan = WithinDayAgentUtils.getModifiablePlan(agent); + PlanElement planElement = plan.getPlanElements().get(index); + Activity activity; + if(planElement instanceof Activity currentActivity) { + activity = currentActivity; + } else { + // If the current element is a leg, the agent is walking towards the pickup location + // We make the agent stuck at the interaction activity + activity = (Activity) plan.getPlanElements().get(index+1); } + 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(); diff --git a/contribs/dvrp/pom.xml b/contribs/dvrp/pom.xml index 716fab806f2..e6fc424004c 100644 --- a/contribs/dvrp/pom.xml +++ b/contribs/dvrp/pom.xml @@ -24,17 +24,17 @@ org.matsim.contrib otfvis - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib common - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib ev - 2025.0-SNAPSHOT + ${project.parent.version} org.apache.commons diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/router/DvrpModeRoutingNetworkModule.java b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/router/DvrpModeRoutingNetworkModule.java index 076ce4876ec..3b8463a1119 100644 --- a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/router/DvrpModeRoutingNetworkModule.java +++ b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/router/DvrpModeRoutingNetworkModule.java @@ -20,6 +20,7 @@ package org.matsim.contrib.dvrp.router; +import java.io.File; import java.util.Collections; import java.util.Set; @@ -32,6 +33,7 @@ import org.matsim.contrib.zone.skims.FreeSpeedTravelTimeMatrix; import org.matsim.contrib.zone.skims.TravelTimeMatrix; import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigGroup; import org.matsim.core.config.groups.GlobalConfigGroup; import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.network.NetworkUtils; @@ -86,9 +88,16 @@ public void install() { DvrpTravelTimeMatrixParams matrixParams = dvrpConfigGroup.getTravelTimeMatrixParams(); ZoneSystem zoneSystem = ZoneSystemUtils.createZoneSystem(getConfig().getContext(), network, matrixParams.getZoneSystemParams(), getConfig().global().getCoordinateSystem(), zone -> true); - return FreeSpeedTravelTimeMatrix.createFreeSpeedMatrix(network, zoneSystem, - matrixParams, globalConfigGroup.getNumberOfThreads(), - qSimConfigGroup.getTimeStepSize()); + + + if (matrixParams.cachePath == null) { + return FreeSpeedTravelTimeMatrix.createFreeSpeedMatrix(network, zoneSystem, matrixParams, globalConfigGroup.getNumberOfThreads(), + qSimConfigGroup.getTimeStepSize()); + } else { + File cachePath = new File(ConfigGroup.getInputFileURL(getConfig().getContext(), matrixParams.cachePath).getPath()); + return FreeSpeedTravelTimeMatrix.createFreeSpeedMatrixFromCache(network, zoneSystem, matrixParams, globalConfigGroup.getNumberOfThreads(), + qSimConfigGroup.getTimeStepSize(), cachePath); + } })).in(Singleton.class); } else { //use DVRP-routing (dvrp-global) network diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/run/DvrpModule.java b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/run/DvrpModule.java index d31fe11499d..769ea423515 100644 --- a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/run/DvrpModule.java +++ b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/run/DvrpModule.java @@ -19,7 +19,7 @@ package org.matsim.contrib.dvrp.run; -import jakarta.inject.Provider; +import java.io.File; import org.matsim.api.core.v01.network.Network; import org.matsim.contrib.common.zones.ZoneSystem; @@ -33,6 +33,7 @@ import org.matsim.contrib.zone.skims.DvrpTravelTimeMatrixParams; import org.matsim.contrib.zone.skims.FreeSpeedTravelTimeMatrix; import org.matsim.contrib.zone.skims.TravelTimeMatrix; +import org.matsim.core.config.ConfigGroup; import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.mobsim.framework.MobsimTimer; @@ -44,6 +45,8 @@ import com.google.inject.name.Named; import com.google.inject.name.Names; +import jakarta.inject.Provider; + /** * This module initialises generic (i.e. not taxi or drt-specific) AND global (not mode-specific) dvrp objects. *

@@ -90,8 +93,15 @@ public TravelTimeMatrix get() { DvrpTravelTimeMatrixParams matrixParams = dvrpConfigGroup.getTravelTimeMatrixParams(); ZoneSystem zoneSystem = ZoneSystemUtils.createZoneSystem(getConfig().getContext(), network, matrixParams.getZoneSystemParams(), getConfig().global().getCoordinateSystem(), zone -> true); - return FreeSpeedTravelTimeMatrix.createFreeSpeedMatrix(network, zoneSystem, params, numberOfThreads, + + if (params.cachePath == null) { + return FreeSpeedTravelTimeMatrix.createFreeSpeedMatrix(network, zoneSystem, params, numberOfThreads, qSimConfigGroup.getTimeStepSize()); + } else { + File cachePath = new File(ConfigGroup.getInputFileURL(getConfig().getContext(), params.cachePath).getPath()); + return FreeSpeedTravelTimeMatrix.createFreeSpeedMatrixFromCache(network, zoneSystem, params, numberOfThreads, + qSimConfigGroup.getTimeStepSize(), cachePath); + } } }).in(Singleton.class); diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/DvrpTravelTimeMatrixParams.java b/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/DvrpTravelTimeMatrixParams.java index 52c3c332f09..9b959a87ba2 100644 --- a/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/DvrpTravelTimeMatrixParams.java +++ b/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/DvrpTravelTimeMatrixParams.java @@ -28,6 +28,7 @@ import org.matsim.contrib.common.zones.systems.grid.GISFileZoneSystemParams; import org.matsim.contrib.common.zones.systems.grid.h3.H3GridZoneSystemParams; import org.matsim.contrib.common.zones.systems.grid.square.SquareGridZoneSystemParams; +import org.matsim.core.config.ReflectiveConfigGroup.Parameter; /** * @author Michal Maciejewski (michalm) @@ -59,6 +60,9 @@ public class DvrpTravelTimeMatrixParams extends ReflectiveConfigGroupWithConfigu @NotNull private ZoneSystemParams zoneSystemParams; + @Parameter + @Comment("Caches the travel time matrix data into a binary file. If the file exists, the matrix will be read from the file, if not, the file will be created.") + public String cachePath = null; public DvrpTravelTimeMatrixParams() { super(SET_NAME); diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrix.java b/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrix.java index 6351dd3bce8..356625f4295 100644 --- a/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrix.java +++ b/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrix.java @@ -20,14 +20,34 @@ package org.matsim.contrib.zone.skims; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.IdSet; import org.matsim.api.core.v01.network.Network; import org.matsim.api.core.v01.network.Node; +import org.matsim.contrib.common.zones.Zone; import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.common.zones.ZoneSystemUtils; import org.matsim.contrib.dvrp.router.TimeAsTravelDisutility; import org.matsim.contrib.dvrp.trafficmonitoring.QSimFreeSpeedTravelTime; +import org.matsim.contrib.zone.skims.SparseMatrix.NodeAndTime; +import org.matsim.contrib.zone.skims.SparseMatrix.SparseRow; import org.matsim.core.router.util.TravelTime; +import com.google.common.base.Verify; +import com.google.common.collect.Sets; + /** * @author Michal Maciejewski (michalm) */ @@ -68,4 +88,151 @@ public int getTravelTime(Node fromNode, Node toNode, double departureTime) { public int getZonalTravelTime(Node fromNode, Node toNode, double departureTime) { return freeSpeedTravelTimeMatrix.get(zoneSystem.getZoneForNodeId(fromNode.getId()).orElseThrow(), zoneSystem.getZoneForNodeId(toNode.getId()).orElseThrow()); } + + public static FreeSpeedTravelTimeMatrix createFreeSpeedMatrixFromCache(Network dvrpNetwork, ZoneSystem zoneSystem, DvrpTravelTimeMatrixParams params, int numberOfThreads, double qSimTimeStepSize, File cachePath) { + boolean exists = cachePath.exists(); + + final FreeSpeedTravelTimeMatrix matrix; + if (exists) { + matrix = new FreeSpeedTravelTimeMatrix(dvrpNetwork, zoneSystem, cachePath); + } else { + matrix = createFreeSpeedMatrix(dvrpNetwork, zoneSystem, params, numberOfThreads, qSimTimeStepSize); + matrix.write(cachePath, dvrpNetwork); + } + + return matrix; + } + + public FreeSpeedTravelTimeMatrix(Network dvrpNetwork, ZoneSystem zoneSystem, File cachePath) { + this.zoneSystem = zoneSystem; + + try (DataInputStream inputStream = new DataInputStream(new FileInputStream(cachePath))) { + // number of zones + int numberOfZones = inputStream.readInt(); + Verify.verify(numberOfZones == zoneSystem.getZones().size()); + + // read zone list + List> zoneIds = new ArrayList<>(numberOfZones); + for (int i = 0; i < numberOfZones; i++) { + zoneIds.add(Id.create(inputStream.readUTF(), Zone.class)); + } + + IdSet systemZones = new IdSet<>(Zone.class); + systemZones.addAll(zoneSystem.getZones().keySet()); + + IdSet dataZones = new IdSet<>(Zone.class); + dataZones.addAll(zoneIds); + + Verify.verify(Sets.difference(systemZones, dataZones).size() == 0); + Verify.verify(Sets.difference(dataZones, systemZones).size() == 0); + + // fill matrix + freeSpeedTravelTimeMatrix = new Matrix(new HashSet<>(zoneSystem.getZones().values())); + + for (var from : zoneIds) { + for (var to : zoneIds) { + Zone fromZone = zoneSystem.getZones().get(from); + Zone toZone = zoneSystem.getZones().get(to); + freeSpeedTravelTimeMatrix.set(fromZone, toZone, inputStream.readInt()); + } + } + + // sparse matrix available? + boolean hasSparseMatrix = inputStream.readBoolean(); + + if (!hasSparseMatrix) { + freeSpeedTravelTimeSparseMatrix = null; + } else { + freeSpeedTravelTimeSparseMatrix = new SparseMatrix(); + + // read nodes + int numberOfNodes = inputStream.readInt(); + Verify.verify(numberOfNodes == dvrpNetwork.getNodes().size()); + + List nodes = new ArrayList<>(numberOfNodes); + for (int i = 0; i < numberOfNodes; i++) { + Id nodeId = Id.createNodeId(inputStream.readUTF()); + nodes.add(Objects.requireNonNull(dvrpNetwork.getNodes().get(nodeId))); + } + + // read rows + for (int i = 0; i < numberOfNodes; i++) { + Node from = nodes.get(i); + int numberOfElements = inputStream.readInt(); + + if (numberOfElements > 0) { + List nodeTimeList = new ArrayList<>(numberOfElements); + + for (int j = 0; j < numberOfElements; j++) { + Node to = nodes.get(inputStream.readInt()); + int value = inputStream.readInt(); + + nodeTimeList.add(new NodeAndTime(to.getId().index(), value)); + } + + SparseRow row = new SparseRow(nodeTimeList); + freeSpeedTravelTimeSparseMatrix.setRow(from, row); + } + } + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public void write(File outputPath, Network dvrpNetwork) { + try (DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(outputPath))) { + // obtain fixed order of zones + List zones = new ArrayList<>(zoneSystem.getZones().values()); + outputStream.writeInt(zones.size()); + for (Zone zone : zones) { + outputStream.writeUTF(zone.getId().toString()); + } + + // write matrix + for (var from : zones) { + for (var to : zones) { + int value = freeSpeedTravelTimeMatrix.get(from, to); + outputStream.writeInt(value); + } + } + + // write if sparse exists + outputStream.writeBoolean(freeSpeedTravelTimeSparseMatrix != null); + + if (freeSpeedTravelTimeSparseMatrix != null) { + // obtain fixed order of nodes + List nodes = new ArrayList<>(dvrpNetwork.getNodes().values()); + outputStream.writeInt(nodes.size()); + for (Node node : nodes) { + outputStream.writeUTF(node.getId().toString()); + } + + for (Node from : nodes) { + // write size of the matrix row + int rowSize = 0; + + for (Node to : nodes) { + int value = freeSpeedTravelTimeSparseMatrix.get(from, to); + if (value >= 0) { + rowSize++; + } + } + + outputStream.writeInt(rowSize); + + // write matrix row + for (Node to : nodes) { + int value = freeSpeedTravelTimeSparseMatrix.get(from, to); + if (value >= 0) { + outputStream.writeInt(nodes.indexOf(to)); + outputStream.writeInt(value); + } + } + } + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } } diff --git a/contribs/dvrp/src/test/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrixTest.java b/contribs/dvrp/src/test/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrixTest.java index 8aaf6001258..2cf4cc30934 100644 --- a/contribs/dvrp/src/test/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrixTest.java +++ b/contribs/dvrp/src/test/java/org/matsim/contrib/zone/skims/FreeSpeedTravelTimeMatrixTest.java @@ -22,7 +22,10 @@ import static org.assertj.core.api.Assertions.assertThat; +import java.io.File; + 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.network.Network; @@ -30,12 +33,16 @@ import org.matsim.contrib.common.zones.ZoneSystem; import org.matsim.contrib.common.zones.systems.grid.square.SquareGridZoneSystem; import org.matsim.core.network.NetworkUtils; +import org.matsim.testcases.MatsimTestUtils; /** * @author Michal Maciejewski (michalm) */ public class FreeSpeedTravelTimeMatrixTest { + @RegisterExtension + MatsimTestUtils utils = new MatsimTestUtils(); + private final Network network = NetworkUtils.createNetwork(); private final Node nodeA = NetworkUtils.createAndAddNode(network, Id.createNodeId("A"), new Coord(0, 0)); private final Node nodeB = NetworkUtils.createAndAddNode(network, Id.createNodeId("B"), new Coord(150, 150)); @@ -66,6 +73,23 @@ void matrix() { assertThat(matrix.getTravelTime(nodeC, nodeA, 0)).isEqualTo(0); assertThat(matrix.getTravelTime(nodeB, nodeC, 0)).isEqualTo(20 + 1); // 1 s for moving over nodes assertThat(matrix.getTravelTime(nodeC, nodeB, 0)).isEqualTo(10 + 1); // 1 s for moving over nodes + + // write and read cache + File cachePath = new File(utils.getOutputDirectory(), "cache.bin"); + matrix.write(cachePath, network); + matrix = FreeSpeedTravelTimeMatrix.createFreeSpeedMatrixFromCache(network, zoneSystem, null, 1, 1, cachePath); + + // distances between central nodes: A and B + assertThat(matrix.getTravelTime(nodeA, nodeA, 0)).isEqualTo(0); + assertThat(matrix.getTravelTime(nodeA, nodeB, 0)).isEqualTo(10 + 1); // 1 s for moving over nodes + assertThat(matrix.getTravelTime(nodeB, nodeA, 0)).isEqualTo(20 + 1); // 1 s for moving over nodes + assertThat(matrix.getTravelTime(nodeB, nodeB, 0)).isEqualTo(0); + + // non-central node: C and A are in the same zone; A is the central node + assertThat(matrix.getTravelTime(nodeA, nodeC, 0)).isEqualTo(0); + assertThat(matrix.getTravelTime(nodeC, nodeA, 0)).isEqualTo(0); + assertThat(matrix.getTravelTime(nodeB, nodeC, 0)).isEqualTo(20 + 1); // 1 s for moving over nodes + assertThat(matrix.getTravelTime(nodeC, nodeB, 0)).isEqualTo(10 + 1); // 1 s for moving over nodes } @Test @@ -87,5 +111,22 @@ void sparseMatrix() { assertThat(matrix.getTravelTime(nodeC, nodeA, 0)).isEqualTo(9 + 1); // 1 s for moving over nodes assertThat(matrix.getTravelTime(nodeB, nodeC, 0)).isEqualTo(20 + 11 + 2); // 2 s for moving over nodes assertThat(matrix.getTravelTime(nodeC, nodeB, 0)).isEqualTo(10 + 9 + 2); // 2 s for moving over nodes + + // write and read cache + File cachePath = new File(utils.getOutputDirectory(), "cache.bin"); + matrix.write(cachePath, network); + matrix = FreeSpeedTravelTimeMatrix.createFreeSpeedMatrixFromCache(network, zoneSystem, null, 1, 1, cachePath); + + // distances between central nodes: A and B + assertThat(matrix.getTravelTime(nodeA, nodeA, 0)).isEqualTo(0); + assertThat(matrix.getTravelTime(nodeA, nodeB, 0)).isEqualTo(10 + 1); // 1 s for moving over nodes + assertThat(matrix.getTravelTime(nodeB, nodeA, 0)).isEqualTo(20 + 1); // 1 s for moving over nodes + assertThat(matrix.getTravelTime(nodeB, nodeB, 0)).isEqualTo(0); + + // non-central node: C and A are in the same zone; A is the central node + assertThat(matrix.getTravelTime(nodeA, nodeC, 0)).isEqualTo(11 + 1); // 1 s for moving over nodes + assertThat(matrix.getTravelTime(nodeC, nodeA, 0)).isEqualTo(9 + 1); // 1 s for moving over nodes + assertThat(matrix.getTravelTime(nodeB, nodeC, 0)).isEqualTo(20 + 11 + 2); // 2 s for moving over nodes + assertThat(matrix.getTravelTime(nodeC, nodeB, 0)).isEqualTo(10 + 9 + 2); // 2 s for moving over nodes } } diff --git a/contribs/emissions/pom.xml b/contribs/emissions/pom.xml index 16d87bc8cdb..98daccca22b 100644 --- a/contribs/emissions/pom.xml +++ b/contribs/emissions/pom.xml @@ -58,7 +58,7 @@ org.matsim.contrib analysis - 2025.0-SNAPSHOT + ${project.parent.version} com.fasterxml.jackson.core diff --git a/contribs/emissions/src/main/java/org/matsim/contrib/emissions/OsmHbefaMapping.java b/contribs/emissions/src/main/java/org/matsim/contrib/emissions/OsmHbefaMapping.java index ccce2492711..fb492e2bfd3 100644 --- a/contribs/emissions/src/main/java/org/matsim/contrib/emissions/OsmHbefaMapping.java +++ b/contribs/emissions/src/main/java/org/matsim/contrib/emissions/OsmHbefaMapping.java @@ -85,6 +85,8 @@ public static OsmHbefaMapping build() { mapping.put("residential", new Hbefa("Access",30,50)); mapping.put("service", new Hbefa("Access",30,50)); mapping.put("living", new Hbefa("Access",30,50)); + mapping.put("cycleway", new Hbefa("Access",30,50)); + mapping.put("path", new Hbefa("Access",30,50)); return mapping; } diff --git a/contribs/emissions/src/main/java/org/matsim/contrib/emissions/events/EmissionEvent.java b/contribs/emissions/src/main/java/org/matsim/contrib/emissions/events/EmissionEvent.java index ae7c9c59e2a..180e79ca9fc 100644 --- a/contribs/emissions/src/main/java/org/matsim/contrib/emissions/events/EmissionEvent.java +++ b/contribs/emissions/src/main/java/org/matsim/contrib/emissions/events/EmissionEvent.java @@ -25,6 +25,7 @@ import org.matsim.api.core.v01.events.Event; import org.matsim.api.core.v01.network.Link; import org.matsim.contrib.emissions.Pollutant; +import org.matsim.core.utils.io.XmlUtils; import org.matsim.vehicles.Vehicle; import java.util.Map; @@ -67,4 +68,20 @@ public Map getAttributes() { } return attributes; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes common attributes + writeXMLStart(out); + + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_LINK_ID, this.linkId.toString()); + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_VEHICLE_ID, this.vehicleId.toString()); + + for (Map.Entry entry : emissions.entrySet()) { + out.append(entry.getKey().name()).append("=\""); + out.append((double) entry.getValue()).append("\" "); + } + + writeXMLEnd(out); + } } 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 a3059795499..1f0ccd3eaf5 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 @@ -201,7 +201,7 @@ public void handleEvent(Event event) { } private VehicleType createVehicleType() { - VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("dieselCarFullSpecified", VehicleType.class)); + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("dieselCarFullSpecified", VehicleType.class), TransportMode.car); EngineInformation engineInformation = vehicleType.getEngineInformation(); VehicleUtils.setHbefaVehicleCategory(engineInformation, "PASSENGER_CAR"); VehicleUtils.setHbefaTechnology(engineInformation, "diesel"); diff --git a/contribs/ev/pom.xml b/contribs/ev/pom.xml index e1c5144d706..120d63dfbe3 100644 --- a/contribs/ev/pom.xml +++ b/contribs/ev/pom.xml @@ -14,7 +14,7 @@ org.matsim.contrib common - 2025.0-SNAPSHOT + ${project.parent.version} org.apache.commons diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/Charger.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/Charger.java index 9bd2ef5bde9..921b950e41c 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/Charger.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/Charger.java @@ -24,8 +24,9 @@ import org.matsim.api.core.v01.Identifiable; import org.matsim.api.core.v01.network.Link; import org.matsim.contrib.ev.charging.ChargingLogic; +import org.matsim.utils.objectattributes.attributable.Attributable; -public interface Charger extends BasicLocation, Identifiable { +public interface Charger extends BasicLocation, Identifiable, Attributable { ChargerSpecification getSpecification(); ChargingLogic getLogic(); diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerDefaultImpl.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerDefaultImpl.java index d2efb68578d..7ceb1007f92 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerDefaultImpl.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerDefaultImpl.java @@ -26,6 +26,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.contrib.ev.charging.ChargingLogic; +import org.matsim.utils.objectattributes.attributable.Attributes; import com.google.common.base.Preconditions; @@ -77,6 +78,11 @@ public int getPlugCount() { return specification.getPlugCount(); } + @Override + public Attributes getAttributes() { + return specification.getAttributes(); + } + //TODO in order to add a separate coord: adapt DTD, ChargerSpecification and ChargerReader/Writer // Additionally, the reader and writer should convert coordinates if CRS different than that of the network @Override diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerReader.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerReader.java index 9864622b4cb..b3d6a4d6c36 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerReader.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerReader.java @@ -20,19 +20,33 @@ package org.matsim.contrib.ev.infrastructure; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; import java.util.Stack; import org.matsim.api.core.v01.Id; import org.matsim.contrib.ev.EvUnits; +import org.matsim.contrib.ev.infrastructure.ImmutableChargerSpecification.ChargerSpecificationBuilder; import org.matsim.core.utils.io.MatsimXmlParser; +import org.matsim.utils.objectattributes.AttributeConverter; +import org.matsim.utils.objectattributes.attributable.AttributesImpl; +import org.matsim.utils.objectattributes.attributable.AttributesXmlReaderDelegate; import org.xml.sax.Attributes; public final class ChargerReader extends MatsimXmlParser { private final static String CHARGER = "charger"; + private final static String ATTRIBUTES = "attributes"; + private final static String ATTRIBUTE = "attribute"; private final ChargingInfrastructureSpecification chargingInfrastructure; + private Map, AttributeConverter> attributeConverters = new HashMap<>(); + private final AttributesXmlReaderDelegate attributesReader = new AttributesXmlReaderDelegate(); + + private ChargerSpecificationBuilder currentBuilder = null; + private AttributesImpl currentAttributes = null; + public ChargerReader(ChargingInfrastructureSpecification chargingInfrastructure) { super(ValidationType.DTD_ONLY); this.chargingInfrastructure = chargingInfrastructure; @@ -41,15 +55,30 @@ public ChargerReader(ChargingInfrastructureSpecification chargingInfrastructure) @Override public void startTag(String name, Attributes atts, Stack context) { if (CHARGER.equals(name)) { - chargingInfrastructure.addChargerSpecification(createSpecification(atts)); + currentBuilder = createSpecification(atts); + } else if (ATTRIBUTES.equals(name)) { + currentAttributes = new AttributesImpl(); + attributesReader.startTag(name, atts, context, currentAttributes); + } else if (ATTRIBUTE.equals(name)) { + attributesReader.startTag(name, atts, context, currentAttributes); } } @Override public void endTag(String name, String content, Stack context) { + if (CHARGER.equals(name)) { + chargingInfrastructure.addChargerSpecification(currentBuilder.build()); + currentBuilder = null; + } else if (ATTRIBUTES.equals(name)) { + attributesReader.endTag(name, content, context); + currentBuilder.attributes(currentAttributes); + currentAttributes = null; + } else if (ATTRIBUTE.equals(name)) { + attributesReader.endTag(name, content, context); + } } - private ChargerSpecification createSpecification(Attributes atts) { + private ChargerSpecificationBuilder createSpecification(Attributes atts) { return ImmutableChargerSpecification.newBuilder() .id(Id.create(atts.getValue("id"), Charger.class)) .linkId(Id.createLinkId(atts.getValue("link"))) @@ -58,7 +87,14 @@ private ChargerSpecification createSpecification(Attributes atts) { .plugPower(EvUnits.kW_to_W(Double.parseDouble(atts.getValue("plug_power")))) .plugCount(Optional.ofNullable(atts.getValue("plug_count")) .map(Integer::parseInt) - .orElse(ChargerSpecification.DEFAULT_PLUG_COUNT)) - .build(); + .orElse(ChargerSpecification.DEFAULT_PLUG_COUNT)); } + + public void putAttributeConverters(Map, AttributeConverter> converters) { + this.attributeConverters.putAll(converters); + } + + public void putAttributeConverter(Class key, AttributeConverter converter) { + this.attributeConverters.put(key, converter); + } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerSpecification.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerSpecification.java index 14aafb14d12..73272087d0a 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerSpecification.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerSpecification.java @@ -23,6 +23,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Identifiable; import org.matsim.api.core.v01.network.Link; +import org.matsim.utils.objectattributes.attributable.Attributable; /** * ChargerSpecification is assumed to be immutable. @@ -34,7 +35,7 @@ * * @author Michal Maciejewski (michalm) */ -public interface ChargerSpecification extends Identifiable { +public interface ChargerSpecification extends Identifiable, Attributable { String DEFAULT_CHARGER_TYPE = "default"; int DEFAULT_PLUG_COUNT = 1; diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerWriter.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerWriter.java index 8955b266984..f62ee0729f6 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerWriter.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerWriter.java @@ -20,18 +20,27 @@ package org.matsim.contrib.ev.infrastructure; +import java.io.IOException; +import java.io.UncheckedIOException; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Stream; import org.matsim.contrib.ev.EvUnits; import org.matsim.core.utils.collections.Tuple; import org.matsim.core.utils.io.MatsimXmlWriter; +import org.matsim.utils.objectattributes.AttributeConverter; +import org.matsim.utils.objectattributes.attributable.AttributesXmlWriterDelegate; public final class ChargerWriter extends MatsimXmlWriter { private final Stream chargerSpecifications; + private Map, AttributeConverter> attributeConverters = new HashMap<>(); + private final AttributesXmlWriterDelegate attributesWriter = new AttributesXmlWriterDelegate(); + public ChargerWriter(Stream chargerSpecifications) { this.chargerSpecifications = chargerSpecifications; } @@ -45,13 +54,34 @@ public void write(String file) { close(); } - private void writeChargers() { + private void writeChargers() throws UncheckedIOException { chargerSpecifications.forEach(c -> { List> atts = Arrays.asList(Tuple.of("id", c.getId().toString()), Tuple.of("link", c.getLinkId() + ""), Tuple.of("type", c.getChargerType()), Tuple.of("plug_power", EvUnits.W_to_kW(c.getPlugPower()) + ""), Tuple.of("plug_count", c.getPlugCount() + "")); - writeStartTag("charger", atts, true); + if (c.getAttributes().size() == 0) { + writeStartTag("charger", atts, true); + } else { + writeStartTag("charger", atts, false); + + try { + this.writer.write("\n"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + attributesWriter.writeAttributes("\t\t", this.writer, c.getAttributes(), false); + writeEndTag("charger"); + } }); } + + public void putAttributeConverters(Map, AttributeConverter> converters) { + this.attributeConverters.putAll(converters); + } + + public void putAttributeConverter(Class key, AttributeConverter converter) { + this.attributeConverters.put(key, converter); + } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureModule.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureModule.java index f44bee53f11..dd85c2bb83b 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureModule.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureModule.java @@ -20,12 +20,16 @@ package org.matsim.contrib.ev.infrastructure; +import java.util.Collections; +import java.util.Map; + import org.matsim.api.core.v01.network.Network; import org.matsim.contrib.ev.EvConfigGroup; import org.matsim.contrib.ev.charging.ChargingLogic; import org.matsim.core.config.ConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.mobsim.qsim.AbstractQSimModule; +import org.matsim.utils.objectattributes.AttributeConverter; import com.google.inject.Inject; import com.google.inject.Key; @@ -55,11 +59,20 @@ public ChargingInfrastructureModule(Key networkKey) { public void install() { bind(Network.class).annotatedWith(Names.named(CHARGERS)).to(networkKey).asEagerSingleton(); - bind(ChargingInfrastructureSpecification.class).toProvider(() -> { - ChargingInfrastructureSpecification chargingInfrastructureSpecification = new ChargingInfrastructureSpecificationDefaultImpl(); - new ChargerReader(chargingInfrastructureSpecification).parse( - ConfigGroup.getInputFileURL(getConfig().getContext(), evCfg.chargersFile)); - return chargingInfrastructureSpecification; + bind(ChargingInfrastructureSpecification.class).toProvider(new Provider<>() { + @Inject + private Map,AttributeConverter> attributeConverters = Collections.emptyMap(); + + public ChargingInfrastructureSpecification get() { + ChargingInfrastructureSpecification chargingInfrastructureSpecification = new ChargingInfrastructureSpecificationDefaultImpl(); + + ChargerReader reader = new ChargerReader(chargingInfrastructureSpecification); + reader.putAttributeConverters(attributeConverters); + reader.parse( + ConfigGroup.getInputFileURL(getConfig().getContext(), evCfg.chargersFile)); + + return chargingInfrastructureSpecification; + } }).asEagerSingleton(); installQSimModule(new AbstractQSimModule() { diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ImmutableChargerSpecification.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ImmutableChargerSpecification.java index a3d7192b793..2987fe88677 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ImmutableChargerSpecification.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ImmutableChargerSpecification.java @@ -24,6 +24,8 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; +import org.matsim.utils.objectattributes.attributable.Attributes; +import org.matsim.utils.objectattributes.attributable.AttributesImpl; import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; @@ -39,6 +41,7 @@ public class ImmutableChargerSpecification implements ChargerSpecification { private final String chargerType; private final double plugPower; private final int plugCount; + private final Attributes attributes; private ImmutableChargerSpecification( ChargerSpecificationBuilder builder ) { id = Objects.requireNonNull(builder.id); @@ -46,6 +49,7 @@ private ImmutableChargerSpecification( ChargerSpecificationBuilder builder ) { chargerType = Objects.requireNonNull(builder.chargerType); plugPower = Objects.requireNonNull(builder.plugPower); plugCount = Objects.requireNonNull(builder.plugCount); + attributes = builder.attributes != null ? builder.attributes : new AttributesImpl(); Preconditions.checkArgument(plugPower >= 0, "Negative plugPower of charger: %s", id); Preconditions.checkArgument(plugCount >= 0, "Negative plugCount of charger: %s", id); @@ -90,6 +94,11 @@ public int getPlugCount() { return plugCount; } + @Override + public Attributes getAttributes() { + return attributes; + } + @Override public String toString() { return MoreObjects.toStringHelper(this) @@ -107,6 +116,7 @@ public static final class ChargerSpecificationBuilder{ private String chargerType; private Double plugPower; private Integer plugCount; + private Attributes attributes; private ChargerSpecificationBuilder() { } @@ -136,6 +146,11 @@ public ChargerSpecificationBuilder plugCount( int val ) { return this; } + public ChargerSpecificationBuilder attributes( Attributes val ) { + attributes = val; + return this; + } + public ImmutableChargerSpecification build() { return new ImmutableChargerSpecification(this); } diff --git a/contribs/ev/src/test/java/org/matsim/contrib/ev/infrastructure/ChargerReaderWriterTest.java b/contribs/ev/src/test/java/org/matsim/contrib/ev/infrastructure/ChargerReaderWriterTest.java new file mode 100644 index 00000000000..eb6e0f5c65f --- /dev/null +++ b/contribs/ev/src/test/java/org/matsim/contrib/ev/infrastructure/ChargerReaderWriterTest.java @@ -0,0 +1,108 @@ +package org.matsim.contrib.ev.infrastructure; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.api.core.v01.Id; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.utils.objectattributes.attributable.AttributesImpl; + +public class ChargerReaderWriterTest { + @RegisterExtension + MatsimTestUtils utils = new MatsimTestUtils(); + + @Test + public void testReadWriteChargers() { + ChargingInfrastructureSpecificationDefaultImpl infrastructure = new ChargingInfrastructureSpecificationDefaultImpl(); + + infrastructure.addChargerSpecification(ImmutableChargerSpecification.newBuilder() + .id(Id.create("charger1", Charger.class)) // + .chargerType("type1") // + .linkId(Id.createLinkId("link1")) // + .plugCount(1) // + .plugPower(1000.0) // + .build()); + + infrastructure.addChargerSpecification(ImmutableChargerSpecification.newBuilder() + .id(Id.create("charger2", Charger.class)) // + .chargerType("type2") // + .linkId(Id.createLinkId("link2")) // + .plugCount(2) // + .plugPower(2000.0) // + .build()); + + String path = utils.getOutputDirectory() + "/chargers.xml"; + new ChargerWriter(infrastructure.getChargerSpecifications().values().stream()).write(path); + + ChargingInfrastructureSpecificationDefaultImpl readInfrastructure = new ChargingInfrastructureSpecificationDefaultImpl(); + new ChargerReader(readInfrastructure).readFile(path); + + ChargerSpecification spec1 = readInfrastructure.getChargerSpecifications() + .get(Id.create("charger1", Charger.class)); + assertEquals("type1", spec1.getChargerType()); + assertEquals(Id.createLinkId("link1"), spec1.getLinkId()); + assertEquals(1, spec1.getPlugCount()); + assertEquals(1000.0, spec1.getPlugPower()); + + ChargerSpecification spec2 = readInfrastructure.getChargerSpecifications() + .get(Id.create("charger2", Charger.class)); + assertEquals("type2", spec2.getChargerType()); + assertEquals(Id.createLinkId("link2"), spec2.getLinkId()); + assertEquals(2, spec2.getPlugCount()); + assertEquals(2000.0, spec2.getPlugPower()); + } + + @Test + public void testReadWriteChargersWithAttributes() { + ChargingInfrastructureSpecificationDefaultImpl infrastructure = new ChargingInfrastructureSpecificationDefaultImpl(); + + AttributesImpl attributes1 = new AttributesImpl(); + attributes1.putAttribute("attribute1", "value1"); + + infrastructure.addChargerSpecification(ImmutableChargerSpecification.newBuilder() + .id(Id.create("charger1", Charger.class)) // + .chargerType("type1") // + .linkId(Id.createLinkId("link1")) // + .plugCount(1) // + .plugPower(1000.0) // + .attributes(attributes1) // + .build()); + + AttributesImpl attributes2 = new AttributesImpl(); + attributes2.putAttribute("attribute2", "value2"); + + infrastructure.addChargerSpecification(ImmutableChargerSpecification.newBuilder() + .id(Id.create("charger2", Charger.class)) // + .chargerType("type2") // + .linkId(Id.createLinkId("link2")) // + .plugCount(2) // + .plugPower(2000.0) // + .attributes(attributes2) // + .build()); + + String path = utils.getOutputDirectory() + "/chargers_with_attributes.xml"; + new ChargerWriter(infrastructure.getChargerSpecifications().values().stream()).write(path); + + ChargingInfrastructureSpecificationDefaultImpl readInfrastructure = new ChargingInfrastructureSpecificationDefaultImpl(); + new ChargerReader(readInfrastructure).readFile(path); + + ChargerSpecification spec1 = readInfrastructure.getChargerSpecifications() + .get(Id.create("charger1", Charger.class)); + assertEquals("type1", spec1.getChargerType()); + assertEquals(Id.createLinkId("link1"), spec1.getLinkId()); + assertEquals(1, spec1.getPlugCount()); + assertEquals(1000.0, spec1.getPlugPower()); + + assertEquals("value1", (String) spec1.getAttributes().getAttribute("attribute1")); + + ChargerSpecification spec2 = readInfrastructure.getChargerSpecifications() + .get(Id.create("charger2", Charger.class)); + assertEquals("type2", spec2.getChargerType()); + assertEquals(Id.createLinkId("link2"), spec2.getLinkId()); + assertEquals(2, spec2.getPlugCount()); + assertEquals(2000.0, spec2.getPlugPower()); + + assertEquals("value2", (String) spec2.getAttributes().getAttribute("attribute2")); + } +} diff --git a/contribs/freight/README.md b/contribs/freight/README.md index afdcbcd4abc..746cdba1bc1 100644 --- a/contribs/freight/README.md +++ b/contribs/freight/README.md @@ -1,10 +1,25 @@ # Freight -Package that plugs freight algorithms (programmed in external package jsprit) into matsim. +This contrib contains the following packages: + +## Carriers +(This is formally knows as 'freight contrib') + +Package that plugs vehicle routing problem algorithms (programmed in external package jsprit) into MATSim. A good starting point for jsprit is [ https://github.com/graphhopper/jsprit](https://github.com/graphhopper/jsprit). -For runnable code see, e.g., the packages org.matsim.contrib.freight.usecases.* above . +For runnable code see, e.g., the packages org.matsim.contrib.freight.carriers.usecases.* above . + +## Logistics +(This code comes from [https://github.com/matsim-vsp/logistics/](https://github.com/matsim-vsp/logistics/) ) + +This code deals with creating logistics chains for freight transport. + +Here the decision agent is the logistics service provider (LSP) who decides on the logistics chain to be used for a given freight transport request. +Therefore, it can use carriers (see above) and hubs. + +This package bases on work in the dfg-freight project. \ No newline at end of file diff --git a/contribs/freight/pom.xml b/contribs/freight/pom.xml index cfd34b6d514..c1df7ab953a 100644 --- a/contribs/freight/pom.xml +++ b/contribs/freight/pom.xml @@ -55,15 +55,23 @@ org.matsim.contrib roadpricing - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib otfvis - 2025.0-SNAPSHOT + ${project.parent.version} + + + + + + + + org.mockito mockito-core @@ -77,7 +85,7 @@ org.matsim matsim-examples - 2025.0-SNAPSHOT + ${project.parent.version} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/Carrier.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/Carrier.java index 8ee9e1812e5..e80fbb6c9fa 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/Carrier.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/Carrier.java @@ -21,13 +21,12 @@ package org.matsim.freight.carriers; +import java.util.List; +import java.util.Map; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.population.HasPlansAndId; import org.matsim.utils.objectattributes.attributable.Attributable; -import java.util.List; -import java.util.Map; - /** * A carrier. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierCapabilities.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierCapabilities.java index fa14ddfd9bb..879017be0f4 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierCapabilities.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierCapabilities.java @@ -21,12 +21,11 @@ package org.matsim.freight.carriers; +import java.util.*; import org.matsim.api.core.v01.Id; import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.VehicleType; -import java.util.*; - /** * This contains the capabilities/resources a carrier has/can deploy. * @@ -65,7 +64,7 @@ public Builder setFleetSize(FleetSize fleetSize){ /** * @deprecated Since the vehicle type is in the {@link CarrierVehicleTypes} * container, it should not be duplicated here. It is also not written - * to file when writing {@link CarrierPlanXmlWriterV2}. + * to file when writing. */ @Deprecated public Builder addType( VehicleType type ){ diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierImpl.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierImpl.java index 8dcc53adc75..54bebb6b9d2 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierImpl.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierImpl.java @@ -21,14 +21,13 @@ package org.matsim.freight.carriers; -import org.matsim.api.core.v01.Id; -import org.matsim.utils.objectattributes.attributable.Attributes; -import org.matsim.utils.objectattributes.attributable.AttributesImpl; - import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import org.matsim.api.core.v01.Id; +import org.matsim.utils.objectattributes.attributable.Attributes; +import org.matsim.utils.objectattributes.attributable.AttributesImpl; /** * This is a carrier that has capabilities and resources, jobs and plans to fulfill its obligations. diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierJob.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierJob.java new file mode 100644 index 00000000000..3654fbff36a --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierJob.java @@ -0,0 +1,19 @@ +package org.matsim.freight.carriers; + +import org.matsim.utils.objectattributes.attributable.Attributable; + +/** + * A job that a {@link Carrier} can do. + *

+ * In a first step this is more or less a marker interface. + *

+ * In the next steps it will be extended, as follows + * 1) existing common methods of {@link CarrierShipment} and {@link + * CarrierService} where moved up here + * 2) some similiar, but differently named methods of {@link + * CarrierShipment} and {@link CarrierService} were renamed to the same name and moved up here + * ... + * future) It maybe gets generalized in way, that we only have one job definition with 1 or 2 + * location(s). This then defines, if jsprit takes the job as a service or as a shipment. + */ +public interface CarrierJob extends Attributable {} diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlan.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlan.java index 9c51aac159e..e1f56c19d4a 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlan.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlan.java @@ -21,13 +21,12 @@ package org.matsim.freight.carriers; +import java.util.Collection; import org.matsim.api.core.v01.population.BasicPlan; import org.matsim.utils.objectattributes.attributable.Attributable; import org.matsim.utils.objectattributes.attributable.Attributes; import org.matsim.utils.objectattributes.attributable.AttributesImpl; -import java.util.Collection; - /** * * A specific plan of a carrier, and its score. diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanReaderV1.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanReaderV1.java index 4e13ad599b6..4bb90047d86 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanReaderV1.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanReaderV1.java @@ -21,6 +21,7 @@ package org.matsim.freight.carriers; +import java.util.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; @@ -34,8 +35,6 @@ import org.matsim.vehicles.VehicleType; import org.xml.sax.Attributes; -import java.util.*; - /** * A reader that reads carriers and their plans. * @@ -82,7 +81,7 @@ class CarrierPlanReaderV1 extends MatsimXmlParser { * Constructs a reader with an empty carriers-container for the carriers to be constructed. * * @param carriers which is a map that stores carriers - * @param carrierVehicleTypes + * @param carrierVehicleTypes which is a map that stores carrierVehicleTypes */ public CarrierPlanReaderV1( Carriers carriers, CarrierVehicleTypes carrierVehicleTypes ) { super(ValidationType.DTD_OR_XSD); @@ -188,7 +187,7 @@ public void startTag(String name, Attributes attributes, Stack context) { String vehicleId = attributes.getValue("vehicleId"); currentVehicle = vehicles.get(vehicleId); - currentTourBuilder = Tour.Builder.newInstance(); + currentTourBuilder = Tour.Builder.newInstance(Id.create("unknown", Tour.class)); break ; } case "leg": diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanWriter.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanWriter.java index 3d7922d9489..888bfcf5289 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanWriter.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanWriter.java @@ -22,9 +22,8 @@ package org.matsim.freight.carriers; import com.google.inject.Inject; -import org.matsim.utils.objectattributes.AttributeConverter; - import java.util.Map; +import org.matsim.utils.objectattributes.AttributeConverter; /** * @author mrieser / Simunto @@ -47,31 +46,6 @@ public void write(String filename) { this.writeV2_1(filename); } - /** - * @deprecated The underlining {@Link{CarrierPlanXmlWriterV1} is deprecated since April21 - */ - @Deprecated - public void writeV1(String filename) { - new CarrierPlanXmlWriterV1(this.carriers.getCarriers().values()).write(filename); - } - - - /** - * Writes out the Carriers file in version 2. - * Please use the method {@link #write(String)} instead to always ensure writing out to the newest format. - * - * @deprecated The underlining {@Link{CarrierPlanXmlWriterV2} is deprecated since Sep'22 - * - * @param filename Name of the file that should be written. - */ - @Deprecated public void writeV2(String filename) { - CarrierPlanXmlWriterV2 writer = new CarrierPlanXmlWriterV2(this.carriers); - if (this.attributeConverters != null) { - writer.putAttributeConverters(this.attributeConverters); - } - writer.write(filename); - } - /** * Writes out the Carriers file in version 2.1. * Please use the method {@link #write(String)} to always ensure writing out to the newest format. diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlParserV2.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlParserV2.java index a63697cfab4..271871b0970 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlParserV2.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlParserV2.java @@ -21,7 +21,10 @@ package org.matsim.freight.carriers; +import static org.matsim.freight.carriers.CarrierConstants.*; + import com.google.inject.Inject; +import java.util.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; @@ -40,10 +43,6 @@ import org.matsim.vehicles.VehicleType; import org.xml.sax.Attributes; -import java.util.*; - -import static org.matsim.freight.carriers.CarrierConstants.*; - class CarrierPlanXmlParserV2 extends MatsimXmlParser { public static final Logger logger = LogManager.getLogger(CarrierPlanXmlParserV2.class); @@ -78,7 +77,7 @@ class CarrierPlanXmlParserV2 extends MatsimXmlParser { * Constructs a reader with an empty carriers-container for the carriers to be constructed. * * @param carriers which is a map that stores carriers - * @param carrierVehicleTypes + * @param carrierVehicleTypes which is a map that stores vehicle types */ CarrierPlanXmlParserV2( Carriers carriers, CarrierVehicleTypes carrierVehicleTypes ) { super(ValidationType.XSD_ONLY); @@ -234,7 +233,7 @@ public void startTag(String name, Attributes atts, Stack context) { currentVehicle = vehicles.get(vehicleId); if (currentVehicle == null) throw new IllegalStateException("vehicle to vehicleId " + vehicleId + " is missing."); - currentTourBuilder = Tour.Builder.newInstance(); + currentTourBuilder = Tour.Builder.newInstance(Id.create("unknown", Tour.class)); break; case "leg": String depTime = atts.getValue("expected_dep_time"); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlParserV2_1.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlParserV2_1.java index 8503eb4acad..9c3f2b7a1e6 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlParserV2_1.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlParserV2_1.java @@ -21,7 +21,10 @@ package org.matsim.freight.carriers; +import static org.matsim.freight.carriers.CarrierConstants.*; + import com.google.inject.Inject; +import java.util.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; @@ -40,10 +43,6 @@ import org.matsim.vehicles.VehicleType; import org.xml.sax.Attributes; -import java.util.*; - -import static org.matsim.freight.carriers.CarrierConstants.*; - class CarrierPlanXmlParserV2_1 extends MatsimXmlParser { public static final Logger logger = LogManager.getLogger(CarrierPlanXmlParserV2_1.class); @@ -77,7 +76,7 @@ class CarrierPlanXmlParserV2_1 extends MatsimXmlParser { * Constructs a reader with an empty carriers-container for the carriers to be constructed. * * @param carriers which is a map that stores carriers - * @param carrierVehicleTypes + * @param carrierVehicleTypes which is a map that stores vehicle types */ CarrierPlanXmlParserV2_1(Carriers carriers, CarrierVehicleTypes carrierVehicleTypes ) { super(ValidationType.XSD_ONLY); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlReader.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlReader.java index 5155f5bdebc..4842ab434f9 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlReader.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlReader.java @@ -21,6 +21,9 @@ package org.matsim.freight.carriers; +import java.io.InputStream; +import java.net.URL; +import java.util.Stack; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.core.api.internal.MatsimReader; @@ -28,10 +31,6 @@ import org.xml.sax.Attributes; import org.xml.sax.SAXException; -import java.io.InputStream; -import java.net.URL; -import java.util.Stack; - /** * A reader that reads carriers and their plans. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV1.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV1.java deleted file mode 100644 index 510ea9b1ac3..00000000000 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV1.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * *********************************************************************** * - * project: org.matsim.* - * *********************************************************************** * - * * - * copyright : (C) 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.freight.carriers; - -import com.graphhopper.jsprit.core.problem.job.Shipment; -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.core.population.routes.NetworkRoute; -import org.matsim.core.utils.io.MatsimXmlWriter; -import org.matsim.core.utils.misc.Time; - -import java.io.BufferedWriter; -import java.io.IOException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -/** - * A writer that writes carriers and their plans in a xml-file. - * - * @author sschroeder - * - * @deprecated Use {@link CarrierPlanWriter} instead which writes the newest format - */ -@Deprecated -public class CarrierPlanXmlWriterV1 extends MatsimXmlWriter { - - @SuppressWarnings("unused") - private static final Logger logger = LogManager.getLogger(CarrierPlanXmlWriterV1.class); - - private final Collection carriers; - private int idCounter = 0; - private final Map> registeredShipments = new HashMap<>(); - - /** - * Constructs the writer with the carriers to be written. - * - * @param carriers to be written - */ - public CarrierPlanXmlWriterV1(Collection carriers) { - super(); - this.carriers = carriers; - } - - /** - * Writes carriers and their plans into a xml-file. - * - * @param filename should be the target xml-file - */ - public void write(String filename) { - logger.info("write carrier plans"); - try { - openFile(filename); - writeXmlHead(); - startCarriers(this.writer); - for (Carrier carrier : carriers) { - startCarrier(carrier, this.writer); - writeVehicles(carrier, this.writer); - writeShipments(carrier, this.writer); - writePlans(carrier, this.writer); - endCarrier(this.writer); - } - endCarriers(this.writer); - close(); - logger.info("done"); - } catch (IOException e) { - e.printStackTrace(); - logger.error(e); - System.exit(1); - } - } - - private void startCarriers(BufferedWriter writer) throws IOException { - writer.write("\t\n"); - } - - private void startCarrier(Carrier carrier, BufferedWriter writer) - throws IOException { - writer.write("\t\t\n"); - } - - private void writeVehicles(Carrier carrier, BufferedWriter writer) - throws IOException { - writer.write("\t\t\t\n"); - for (CarrierVehicle v : carrier.getCarrierCapabilities().getCarrierVehicles().values()) { - writer.write("\t\t\t\t\n"); - } - writer.write("\t\t\t\n\n"); - } - - private void writeShipments(Carrier carrier, BufferedWriter writer) - throws IOException { - writer.write("\t\t\t\n"); - for (CarrierShipment s : carrier.getShipments().values()) { - // CarrierShipment s = contract.getShipment(); - Id shipmentId = Id.create(++idCounter, Shipment.class); - registeredShipments.put(s, shipmentId); - writer.write("\t\t\t\t\n"); - } - writer.write("\t\t\t\n\n"); - } - - private String getTime(double time) { - return Time.writeTime(time); - } - - private void writePlans(Carrier carrier, BufferedWriter writer) - throws IOException { - if (carrier.getSelectedPlan() == null) { - return; - } - - for(CarrierPlan plan : carrier.getPlans()){ - writer.write("\t\t\t\n"); - - for (ScheduledTour tour : plan.getScheduledTours()) { - writer.write("\t\t\t\t\n"); - writer.write("\t\t\t\t\t\n"); - for (Tour.TourElement tourElement : tour.getTour().getTourElements()) { - if (tourElement instanceof Tour.Leg leg) { - writer.write("\t\t\t\t\t"); - if (leg.getRoute() != null) { - writer.write("\n"); - writer.write("\t\t\t\t\t\t"); - boolean firstLink = true; - for (Id id : ((NetworkRoute) leg.getRoute()).getLinkIds()) { - if (firstLink) { - writer.write(id.toString()); - firstLink = false; - } else { - writer.write(" " + id.toString()); - } - } - writer.write("\n"); - writer.write("\t\t\t\t\t\n"); - } else { - writer.write("\n"); - } - } - if (tourElement instanceof Tour.ShipmentBasedActivity act) { - writer.write("\t\t\t\t\t\n"); - } - - } - writer.write("\t\t\t\t\t\n"); - writer.write("\t\t\t\t\n"); - } - writer.write("\t\t\t\n\n"); - } - - } - - private void endCarrier(BufferedWriter writer) throws IOException { - writer.write("\t\t\n\n"); - registeredShipments.clear(); - } - - private void endCarriers(BufferedWriter writer) throws IOException { - writer.write("\t\n"); - - } -} diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2.java deleted file mode 100644 index b78af8aa3e6..00000000000 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - * *********************************************************************** * - * project: org.matsim.* - * *********************************************************************** * - * * - * copyright : (C) 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.freight.carriers; - -import com.google.inject.Inject; -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.core.population.routes.NetworkRoute; -import org.matsim.core.utils.collections.Tuple; -import org.matsim.core.utils.io.MatsimXmlWriter; -import org.matsim.core.utils.misc.Time; -import org.matsim.freight.carriers.Tour.Leg; -import org.matsim.freight.carriers.Tour.ServiceActivity; -import org.matsim.freight.carriers.Tour.ShipmentBasedActivity; -import org.matsim.freight.carriers.Tour.TourElement; -import org.matsim.utils.objectattributes.AttributeConverter; -import org.matsim.utils.objectattributes.attributable.AttributesXmlWriterDelegate; -import org.matsim.vehicles.VehicleType; - -import java.io.BufferedWriter; -import java.io.IOException; -import java.util.*; - -/** - * A writer that writes carriers and their plans in a xml-file. - * - * @author sschroeder - * - * @deprecated Use {@link CarrierPlanWriter} instead which writes the newest format - */ -@Deprecated -public class CarrierPlanXmlWriterV2 extends MatsimXmlWriter { - - @SuppressWarnings("unused") - private static final Logger logger = LogManager.getLogger(CarrierPlanXmlWriterV2.class); - - private final Collection carriers; - - private final Map> registeredShipments = new HashMap<>(); - - private final Map> serviceMap = new HashMap<>(); - - private final AttributesXmlWriterDelegate attributesWriter = new AttributesXmlWriterDelegate(); - private final List> atts = new ArrayList<>(); - - - /** - * Constructs the writer with the carriers to be written. - * - * @param carriers to be written - */ - public CarrierPlanXmlWriterV2(Carriers carriers) { - super(); - this.carriers = carriers.getCarriers().values(); - } - - @Inject - public void putAttributeConverters( final Map, AttributeConverter> converters ) { - attributesWriter.putAttributeConverters( converters ); - } - - /** - * Writes carriers and their plans into a xml-file. - * - * @param filename should be the target xml-file - */ - public void write(String filename) { - logger.info("write carrier plans"); - try { - openFile(filename); - writeXmlHead(); - - startCarriers(this.writer); - for (Carrier carrier : carriers) { - startCarrier(carrier, this.writer); - writeVehiclesAndTheirTypes(carrier, this.writer); - writeShipments(carrier, this.writer); - writeServices(carrier,this.writer); - writePlans(carrier, this.writer); - endCarrier(this.writer); - } - endCarriers(this.writer); - close(); - logger.info("done"); - } catch (IOException e) { - e.printStackTrace(); - logger.error(e); - System.exit(1); - } - } - - private void startCarriers(BufferedWriter writer) throws IOException { - writer.write("\t\n"); - } - - private void startCarrier(Carrier carrier, BufferedWriter writer) - throws IOException { - writer.write("\t\t\n"); - attributesWriter.writeAttributes("\t\t\t", writer, carrier.getAttributes()); - } - - private void writeVehiclesAndTheirTypes(Carrier carrier, BufferedWriter writer)throws IOException { - writer.write("\t\t\t\n"); - //vehicles - writer.write("\t\t\t\t\n"); - for (CarrierVehicle v : carrier.getCarrierCapabilities().getCarrierVehicles().values()) { - Id vehicleTypeId = v.getVehicleTypeId(); - if(vehicleTypeId == null) vehicleTypeId = v.getType() == null ? null : v.getType().getId(); - if(vehicleTypeId == null) throw new IllegalStateException("vehicleTypeId is missing."); - writer.write("\t\t\t\t\t\n"); - } - writer.write("\t\t\t\t\n\n"); - writer.write("\t\t\t\n\n"); - } - - private void writeShipments(Carrier carrier, BufferedWriter writer) throws IOException { - if(carrier.getShipments().isEmpty()) return; - writer.write("\t\t\t\n"); - for (CarrierShipment s : carrier.getShipments().values()) { - // CarrierShipment s = contract.getShipment(); - Id shipmentId = s.getId(); - registeredShipments.put(s, shipmentId); - writer.write("\t\t\t\t\n"); - } else { - writer.write("\">\n"); - this.attributesWriter.writeAttributes("\t\t\t\t\t", writer, s.getAttributes()); - writer.write("\t\t\t\t\n"); - } - } - writer.write("\t\t\t\n\n"); - } - - private void writeServices(Carrier carrier, BufferedWriter writer) throws IOException { - writer.write("\t\t\t\n"); - for (CarrierService s : carrier.getServices().values()) { - serviceMap.put(s, s.getId()); - writer.write("\t\t\t\t\n"); - } else { - writer.write("\">\n"); - this.attributesWriter.writeAttributes("\t\t\t\t\t", writer, s.getAttributes()); - writer.write("\t\t\t\t\n"); - } - - } - writer.write("\t\t\t\n\n"); - - } - - private String getTime(double time) { - return Time.writeTime(time); - } - - private void writePlans(Carrier carrier, BufferedWriter writer) - throws IOException { - if (carrier.getSelectedPlan() == null) { - return; - } - - for(CarrierPlan plan : carrier.getPlans()){ - writer.write("\t\t\t\n"); - - for (ScheduledTour tour : plan.getScheduledTours()) { - writer.write("\t\t\t\t\n"); - writer.write("\t\t\t\t\t\n"); - for (TourElement tourElement : tour.getTour().getTourElements()) { - if (tourElement instanceof Leg leg) { - writer.write("\t\t\t\t\t"); - if (leg.getRoute() != null) { - writer.write("\n"); - writer.write("\t\t\t\t\t\t"); - boolean firstLink = true; - for (Id id : ((NetworkRoute) leg.getRoute()) - .getLinkIds()) { - if (firstLink) { - writer.write(id.toString()); - firstLink = false; - } else { - writer.write(" " + id.toString()); - } - } - writer.write("\n"); - writer.write("\t\t\t\t\t\n"); - } else { - writer.write("\n"); - } - } - else if (tourElement instanceof ShipmentBasedActivity act) { - writer.write("\t\t\t\t\t\n"); - } - else if (tourElement instanceof ServiceActivity act){ - writer.write("\t\t\t\t\t\n"); - } - - } - writer.write("\t\t\t\t\t\n"); - writer.write("\t\t\t\t\n"); - } - writer.write("\t\t\t\n\n"); - } - - } - - private void endCarrier(BufferedWriter writer) throws IOException { - writer.write("\t\t\n\n"); - registeredShipments.clear(); - } - - private void endCarriers(BufferedWriter writer) throws IOException { - writer.write("\t\n"); - - } -} diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2_1.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2_1.java index 92699982378..6195fb3834f 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2_1.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2_1.java @@ -21,7 +21,16 @@ package org.matsim.freight.carriers; +import static org.matsim.freight.carriers.CarrierConstants.*; + import com.google.inject.Inject; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; @@ -34,16 +43,6 @@ import org.matsim.utils.objectattributes.attributable.AttributesXmlWriterDelegate; import org.matsim.vehicles.VehicleType; -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import static org.matsim.freight.carriers.CarrierConstants.*; - /** * A writer that writes carriers and their plans in a xml-file. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierService.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierService.java index b7106fa6de9..69a5ce75e42 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierService.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierService.java @@ -27,8 +27,7 @@ import org.matsim.utils.objectattributes.attributable.Attributes; import org.matsim.utils.objectattributes.attributable.AttributesImpl; - -public final class CarrierService implements Attributable { +public final class CarrierService implements CarrierJob { public static class Builder { @@ -56,10 +55,10 @@ public Builder setName(String name){ } /** - * By default it is [0.0,Integer.MaxValue]. + * By default, it is [0.0,Integer.MaxValue]. * - * @param serviceDuration - * @return + * @param serviceDuration duration of the service + * @return the builder */ public Builder setServiceDuration(double serviceDuration){ this.serviceTime = serviceDuration; @@ -72,8 +71,8 @@ public Builder setServiceDuration(double serviceDuration){ *

Note that the time-window restricts the start-time of the service (i.e. serviceActivity). If one works with hard time-windows (which means that * time-windows must be met) than the service is allowed to start between startTimeWindow.getStart() and startTimeWindow.getEnd(). * - * @param startTimeWindow - * @return + * @param startTimeWindow time-window for the service + * @return the builder */ public Builder setServiceStartTimeWindow(TimeWindow startTimeWindow){ this.timeWindow = startTimeWindow; diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierShipment.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierShipment.java index 9472ffaac91..b378db94620 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierShipment.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierShipment.java @@ -36,7 +36,7 @@ * @author sschroeder * */ -public final class CarrierShipment implements Attributable { +public final class CarrierShipment implements CarrierJob { /** * A builder that builds shipments. @@ -54,10 +54,10 @@ public static class Builder { *

The builder is init with the shipment's origin (from), destination (to) and with the shipment's size. * The default-value for serviceTime is 0.0. The default-value for a timeWindow is [start=0.0, end=Double.maxValue()]. * - * @param from - * @param to - * @param size - * @return the builder + * @param from the origin + * @param to the destination + * @param size size of the shipment + * @return the builder */ @Deprecated public static Builder newInstance(Id from, Id to, int size){ @@ -70,11 +70,11 @@ public static Builder newInstance(Id from, Id to, int size){ *

The builder is init with the shipment's origin (from), destination (to) and with the shipment's size. * The default-value for serviceTime is 0.0. The default-value for a timeWindow is [start=0.0, end=Double.maxValue()]. * - * @param id - * @param from - * @param to - * @param size - * @return the builder + * @param id the id of the shipment + * @param from the origin + * @param to the destination + * @param size size of the shipment + * @return the builder */ public static Builder newInstance(Id id, Id from, Id to, int size){ return new Builder(id, from,to,size); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicle.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicle.java index 917052a65fe..7d317af7d26 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicle.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicle.java @@ -46,8 +46,8 @@ public final class CarrierVehicle implements Vehicle { *

* The default values for other fields (being implicitly set) are [capacity=0][earliestStart=0.0][latestEnd=Integer.MaxValue()]. * - * @param vehicleId - * @param locationId + * @param vehicleId the vehicle id + * @param locationId the location id * @return CarrierVehicle * @see CarrierVehicle */ @@ -68,9 +68,9 @@ public static class Builder { *

* The default values for other fields (being implicitly set) are [capacity=0][earliestStart=0.0][latestEnd=Integer.MaxValue()]. * - * @param vehicleId - * @param locationId - * @param vehicleType + * @param vehicleId the vehicle id + * @param locationId the location id + * @param vehicleType the vehicle type * @return a new vehicle builder */ public static Builder newInstance( Id vehicleId, Id locationId, VehicleType vehicleType ){ @@ -91,29 +91,6 @@ public Builder( Id vehicleId, Id locationId, VehicleType vehicleT this.type = vehicleType; } - /** - * @param type - * @deprecated The vehicleType need now to be set in the constructor kai/kai jan'22 - */ - @Deprecated - public Builder setType( VehicleType type ){ - log.warn(".setType has no functionality anymore and is deprecated"); -// this.type=type; - return this; - } - - /** - * @param typeId - * @deprecated The vehicleTypeId is no longer needed and was confusing -> Use getType().getId kai/kai jan'22 - */ - @Deprecated - public Builder setTypeId(Id typeId ){ - log.warn(".setTypeId has no functionality anymore and is deprecated"); -// this.typeId = typeId; - return this; - } - - public Builder setEarliestStart(double earliestStart){ this.earliestStart=earliestStart; return this; @@ -151,10 +128,7 @@ private CarrierVehicle(Builder builder){ public Id getLinkId() { return locationId; } - /** - * @deprecated -- please inline. kai, jul'22 - */ - @Deprecated public Id getLocation() { return getLinkId(); } + @Override public Id getId() { return vehicleId; diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleType.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleType.java index 16b7e92a03d..7033a3454d7 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleType.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleType.java @@ -57,30 +57,13 @@ public static class Builder { *

* The defaults are [fix=0.0][perDistanceUnit=1.0][perTimeUnit=0.0]. * - * @param typeId + * @param typeId the type id * @return a type builder */ public static Builder newInstance(Id typeId){ return new Builder(typeId); } - /** - * Returns a new instance of builder initialized with the typeId and the values the given from existing CarrierVehicleType. - *

- * Can be used for create a new, modified CarrierVehicleType basing on an existing one. - * Values can be changed within the builder afterwards. - * - * @param carrierVehicleType - * @param typeId - * @return a type builder - * - * @deprecated Use {@link #newInstance(Id)} instead - */ - @Deprecated(since = "sep'19", forRemoval = true) - public static Builder newInstance(Id typeId, CarrierVehicleType carrierVehicleType){ - throw new RuntimeException("not implemented") ; - } - private Builder(Id typeId){ this.delegate = VehicleUtils.getFactory().createVehicleType( typeId ) ; } @@ -89,8 +72,8 @@ private Builder(Id typeId){ * Sets fixed costs of vehicle. * *

By default it is 0. - * @param fix - * @return + * @param fix fixed costs + * @return this builder */ public Builder setFixCost(double fix){ this.delegate.getCostInformation().setFixedCost( fix ) ; @@ -102,8 +85,8 @@ public Builder setFixCost(double fix){ * *

By default it is 1. * - * @param perDistanceUnit - * @return + * @param perDistanceUnit costs per distance-unit + * @return this builder */ public Builder setCostPerDistanceUnit(double perDistanceUnit){ this.delegate.getCostInformation().setCostsPerMeter( perDistanceUnit ) ; @@ -115,8 +98,8 @@ public Builder setCostPerDistanceUnit(double perDistanceUnit){ * *

By default it is 0. * - * @param perTimeUnit - * @return + * @param perTimeUnit costs per time-unit + * @return this builder */ public Builder setCostPerTimeUnit(double perTimeUnit){ this.delegate.getCostInformation().setCostsPerSecond( perTimeUnit ) ; @@ -126,8 +109,8 @@ public Builder setCostPerTimeUnit(double perTimeUnit){ /** * Sets description. * - * @param description - * @return this builder + * @param description the description + * @return this builder */ public Builder setDescription(String description){ this.delegate.setDescription( description ) ; @@ -139,8 +122,8 @@ public Builder setDescription(String description){ * *

By default, the capacity is 0. * - * @param capacity - * @return this builder + * @param capacity the capacity of the vehicle-type + * @return this builder */ public Builder setCapacity(int capacity){ this.delegate.getCapacity().setOther( capacity ); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReader.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReader.java index f10e5fc9bd5..0d8d070c5c6 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReader.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReader.java @@ -21,6 +21,10 @@ package org.matsim.freight.carriers; +import java.io.InputStream; +import java.net.URL; +import java.util.Map; +import java.util.Stack; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; @@ -33,11 +37,6 @@ import org.xml.sax.Attributes; import org.xml.sax.SAXException; -import java.io.InputStream; -import java.net.URL; -import java.util.Map; -import java.util.Stack; - /** * Reader reading carrierVehicleTypes from a xml-file. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReaderV1.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReaderV1.java index 61718d49850..f1cb66dac45 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReaderV1.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeReaderV1.java @@ -21,9 +21,11 @@ package org.matsim.freight.carriers; +import java.util.Stack; 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.TransportMode; import org.matsim.core.gbl.Gbl; import org.matsim.core.utils.io.MatsimXmlParser; import org.matsim.vehicles.CostInformation; @@ -32,8 +34,6 @@ import org.matsim.vehicles.VehicleUtils; import org.xml.sax.Attributes; -import java.util.Stack; - class CarrierVehicleTypeReaderV1 extends MatsimXmlParser { private static final Logger log = LogManager.getLogger(CarrierVehicleTypeReaderV1.class) ; @@ -54,6 +54,9 @@ public void startTag( String name, Attributes attributes, Stack context if(name.equals("vehicleType")){ Id currentTypeId = Id.create( attributes.getValue( "id" ), VehicleType.class ); this.currentType = VehicleUtils.getFactory().createVehicleType( currentTypeId ) ; + // If no network mode is given, assume car, this is to be backwards compatible + // The v2 format will not make this assumption, and the network mode will be required + this.currentType.setNetworkMode(TransportMode.car); } if(name.equals("allowableWeight")){ // String weight = atts.getValue("weight"); @@ -69,9 +72,8 @@ public void startTag( String name, Attributes attributes, Stack context } if(name.equals("engineInformation")){ EngineInformation engineInfo = this.currentType.getEngineInformation() ; - VehicleUtils.setFuelConsumption(this.currentType, Double.parseDouble(attributes.getValue( "gasConsumption" ))); - engineInfo.setFuelConsumption( Double.parseDouble( attributes.getValue( "gasConsumption" ) ) ); - engineInfo.setFuelType( EngineInformation.FuelType.valueOf( attributes.getValue( "fuelType" ) ) ); + VehicleUtils.setHbefaTechnology(engineInfo, attributes.getValue( "fuelType")); + VehicleUtils.setFuelConsumptionLitersPerMeter(engineInfo, Double.parseDouble(attributes.getValue( "gasConsumption" ))); } if(name.equals("costInformation")){ diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeWriter.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeWriter.java index 4fbd8d68bbb..573f8441cae 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeWriter.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeWriter.java @@ -21,6 +21,7 @@ package org.matsim.freight.carriers; +import java.util.Map; import org.matsim.api.core.v01.Id; import org.matsim.core.api.internal.MatsimWriter; import org.matsim.vehicles.MatsimVehicleWriter; @@ -28,8 +29,6 @@ import org.matsim.vehicles.VehicleUtils; import org.matsim.vehicles.Vehicles; -import java.util.Map; - /** * A writer that writes carriers and their plans in a xml-file. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeWriterV1.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeWriterV1.java deleted file mode 100644 index 823123e916a..00000000000 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeWriterV1.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * *********************************************************************** * - * project: org.matsim.* - * *********************************************************************** * - * * - * copyright : (C) 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.freight.carriers; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.matsim.core.utils.io.MatsimXmlWriter; -import org.matsim.vehicles.CostInformation; -import org.matsim.vehicles.EngineInformation; -import org.matsim.vehicles.VehicleType; - -import java.io.BufferedWriter; -import java.io.IOException; - -@Deprecated // only there if someone insists on writing V1 -public final class CarrierVehicleTypeWriterV1 extends MatsimXmlWriter { - - @SuppressWarnings("unused") - private static final Logger logger = LogManager.getLogger(CarrierVehicleTypeWriter.class ); - - private final CarrierVehicleTypes vehicleTypes; - - - public CarrierVehicleTypeWriterV1(CarrierVehicleTypes carrierVehicleTypes) { - super(); - this.vehicleTypes = carrierVehicleTypes; - } - - - public void write(String filename) { - logger.info("write vehicle-types"); - try { - openFile(filename); - writeXmlHead(); - writeTypes(this.writer); - close(); - logger.info("done"); - } catch ( IOException e) { - e.printStackTrace(); - logger.error(e); - System.exit(1); - } - } - - private void writeTypes( BufferedWriter writer )throws IOException { - writer.write("\t\n"); - for( VehicleType type : vehicleTypes.getVehicleTypes().values()){ - writer.write("\t\t\n"); - writer.write("\t\t\t" + type.getDescription() + "\n"); - EngineInformation engineInformation = type.getEngineInformation(); - if(engineInformation != null && !engineInformation.getAttributes().isEmpty()) { - writer.write("\t\t\t\n"); - } - writer.write("\t\t\t" + type.getCapacity().getWeightInTons() + "\n" ); - CostInformation vehicleCostInformation = type.getCostInformation(); - if(vehicleCostInformation == null) throw new IllegalStateException("vehicleCostInformation is missing."); - writer.write("\t\t\t\n"); - writer.write("\t\t\n"); - } - writer.write("\t\n\n"); - } - - - -} diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypes.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypes.java index e9900cdc6cb..0250412938a 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypes.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypes.java @@ -21,11 +21,10 @@ package org.matsim.freight.carriers; -import org.matsim.api.core.v01.Id; -import org.matsim.vehicles.VehicleType; - import java.util.HashMap; import java.util.Map; +import org.matsim.api.core.v01.Id; +import org.matsim.vehicles.VehicleType; /** * VehicleTypeContainer mapping all vehicleTypes. diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/Carriers.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/Carriers.java index f13f0bc56ae..4512008b9e8 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/Carriers.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/Carriers.java @@ -21,13 +21,12 @@ package org.matsim.freight.carriers; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.matsim.api.core.v01.Id; - import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Id; /** * A container that maps carriers. diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarriersUtils.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarriersUtils.java index 7c8e7220e3e..e99be9d98db 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarriersUtils.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarriersUtils.java @@ -28,6 +28,10 @@ import com.graphhopper.jsprit.core.problem.job.Shipment; import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution; import com.graphhopper.jsprit.core.util.Solutions; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; +import javax.management.InvalidAttributeValueException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; @@ -44,11 +48,6 @@ import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.VehicleType; -import javax.management.InvalidAttributeValueException; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; - public class CarriersUtils { static final String CARRIER_VEHICLE = "carrierVehicle"; @@ -338,7 +337,7 @@ public static Carriers getOrCreateCarriers(Scenario scenario) { public static Carriers addOrGetCarriers(Scenario scenario) { // I have separated getOrCreateCarriers and getCarriers, since when the - // controler is started, it is better to fail if the carriers are not found. + // controller is started, it is better to fail if the carriers are not found. // kai, oct'19 Carriers carriers = (Carriers) scenario.getScenarioElement(CARRIERS); if (carriers == null) { @@ -382,8 +381,6 @@ public static void loadCarriersAccordingToFreightConfig(Scenario scenario) { Carriers carriers = addOrGetCarriers(scenario); // also registers with scenario new CarrierPlanXmlReader(carriers, vehTypes).readURL( IOUtils.extendUrl(scenario.getConfig().getContext(), freightCarriersConfigGroup.getCarriersFile())); - -// new CarrierVehicleTypeLoader( carriers ).loadVehicleTypes( vehTypes ); } /** diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/FreightCarriersConfigGroup.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/FreightCarriersConfigGroup.java index 1aed1a936f2..2474df19550 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/FreightCarriersConfigGroup.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/FreightCarriersConfigGroup.java @@ -22,11 +22,10 @@ package org.matsim.freight.carriers; import jakarta.validation.constraints.Positive; -import org.matsim.core.config.ConfigGroup; -import org.matsim.core.config.ReflectiveConfigGroup; - import java.net.URL; import java.util.Map; +import org.matsim.core.config.ConfigGroup; +import org.matsim.core.config.ReflectiveConfigGroup; public class FreightCarriersConfigGroup extends ReflectiveConfigGroup { diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/ScheduledTour.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/ScheduledTour.java index 6a133ebc71c..84eeb1907a1 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/ScheduledTour.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/ScheduledTour.java @@ -37,9 +37,9 @@ public class ScheduledTour { *

Look at the builder. It might be easier to build a scheduled tour. * You get the builder this way: ScheduledTour.Builder.newInstance(carrierVehicle). * - * @param tour - * @param vehicle - * @param departureTime + * @param tour The scheduled tour. + * @param vehicle The vehicle for the tour. + * @param departureTime The time when the vehicle starts the tour. * @return a scheduledTour * @see ScheduledTour */ diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/TimeWindow.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/TimeWindow.java index 8c5e9fc0d25..1eadbe077c0 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/TimeWindow.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/TimeWindow.java @@ -24,7 +24,6 @@ import org.matsim.core.utils.misc.Time; - /** * Q: What happens/should happen if the time window is not sufficient to unload, or * the vehicle arrives after the time window? diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/Tour.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/Tour.java index cb522e857fb..55f72325237 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/Tour.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/Tour.java @@ -21,6 +21,7 @@ package org.matsim.freight.carriers; +import java.util.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; @@ -30,8 +31,6 @@ import org.matsim.core.population.routes.NetworkRoute; import org.matsim.core.population.routes.RouteUtils; -import java.util.*; - /** * This is a tour of a carrier which is a sequence of activities and legs. *

@@ -62,21 +61,6 @@ public static class Builder { private End end; - /** - * Returns a new tour builder. - * - * @deprecated - * Please use {@link #newInstance(Id)} instead. kmt sep'22 - *

- * - * - * @return the builder including "unknown" as tourId - */ - @Deprecated - public static Builder newInstance(){ - return new Builder(Id.create("unknown", Tour.class)); - } - /** * Returns a new tour builder. * This now also includes an Id for this tour. @@ -98,8 +82,8 @@ private Builder(Id tourId) { * *

Tour start should correspond to the locationId of the vehicle that runs the tour. * - * @param startLinkId - * @return the builder again + * @param startLinkId linkId of the start location + * @return the builder again */ public Builder scheduleStart(Id startLinkId) { scheduleStart(startLinkId, TimeWindow.newInstance(0.0, Double.MAX_VALUE)); @@ -121,7 +105,7 @@ public void scheduleEnd(Id endLinkId, TimeWindow timeWindow){ /** * Schedules the end of the tour (in terms of locationId). * - * @param endLinkId + * @param endLinkId linkId of the end location */ public void scheduleEnd(Id endLinkId) { scheduleEnd(endLinkId, TimeWindow.newInstance(0.0, Double.MAX_VALUE)); @@ -132,8 +116,8 @@ public void scheduleEnd(Id endLinkId) { * *

Consider that a leg follows an activity. Otherwise, an exception occurs. * - * @param leg - * @throws IllegalStateException if leg is null or if previous element is not an activity. + * @param leg the leg to be added + * @throws IllegalStateException if leg is null or if previous element is not an activity. */ public Builder addLeg(Leg leg) { Gbl.assertNotNull(leg); @@ -156,9 +140,9 @@ public Leg createLeg(Route route, double dep_time, double transportTime) { /** * Inserts leg at the beginning of a tour. * - * @param leg - * @return the builder - * @throws IllegalStateException if leg is null + * @param leg the leg to be inserted + * @return the builder + * @throws IllegalStateException if leg is null */ @Deprecated public Builder insertLegAtBeginning(Leg leg) { @@ -170,9 +154,9 @@ public Builder insertLegAtBeginning(Leg leg) { /** * Schedules a pickup of the shipment right at the beginning of the tour. * - * @param shipment - * @return the builder - * @throws IllegalStateException if shipment is null or shipment has already been picked up. + * @param shipment the shipment to be picked up + * @return the builder + * @throws IllegalStateException if shipment is null or shipment has already been picked up. */ @Deprecated public Builder schedulePickupAtBeginning(CarrierShipment shipment) { @@ -218,8 +202,8 @@ private void assertLastElementIsLeg() { /** * Schedules a delivery of a shipment, i.e. adds a delivery activity to current tour. * - * @param shipment - * @throws IllegalStateException if shipment is null or if shipment has not been picked up yet or if last element is not a leg. + * @param shipment the shipment to be delivered + * @throws IllegalStateException if shipment is null or if shipment has not been picked up yet or if last element is not a leg. */ public void scheduleDelivery(CarrierShipment shipment) { Gbl.assertNotNull(shipment); @@ -272,10 +256,10 @@ public Leg createLeg() { /** * Creates and returns a network route. * - * @param startLinkId - * @param linkIds - * @param endLinkId - * @return NetworkRoute + * @param startLinkId start link id + * @param linkIds list of link ids that form the route + * @param endLinkId end link id + * @return NetworkRoute * @see NetworkRoute */ public NetworkRoute createRoute(Id startLinkId, List> linkIds, Id endLinkId) { diff --git a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/CarrierLoadAnalysis.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/CarrierLoadAnalysis.java similarity index 78% rename from contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/CarrierLoadAnalysis.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/CarrierLoadAnalysis.java index 7e858ee725d..37a4651ce7e 100644 --- a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/CarrierLoadAnalysis.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/CarrierLoadAnalysis.java @@ -21,53 +21,47 @@ package org.matsim.freight.carriers.analysis; +import static org.matsim.freight.carriers.events.CarrierEventAttributes.ATTRIBUTE_CAPACITYDEMAND; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.Map; 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.Scenario; -import org.matsim.api.core.v01.events.Event; import org.matsim.freight.carriers.Carriers; import org.matsim.freight.carriers.events.CarrierShipmentDeliveryStartEvent; import org.matsim.freight.carriers.events.CarrierShipmentPickupStartEvent; -import org.matsim.core.events.handler.BasicEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierShipmentDeliveryStartEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierShipmentPickupStartEventHandler; import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.VehicleType; import org.matsim.vehicles.VehicleUtils; -import java.io.BufferedWriter; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Comparator; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.Map; - -import static org.matsim.freight.carriers.events.CarrierEventAttributes.ATTRIBUTE_CAPACITYDEMAND; - /** * @author Kai Martins-Turner (kturner) */ -public class CarrierLoadAnalysis implements BasicEventHandler { +public class CarrierLoadAnalysis implements CarrierShipmentPickupStartEventHandler, CarrierShipmentDeliveryStartEventHandler { private static final Logger log = LogManager.getLogger(CarrierLoadAnalysis.class); - + private final String delimiter; Carriers carriers; private final Map, LinkedList> vehicle2Load = new LinkedHashMap<>(); - public CarrierLoadAnalysis(Carriers carriers) { + public CarrierLoadAnalysis(String delimiter, Carriers carriers) { + this.delimiter = delimiter; this.carriers = carriers; } - @Override public void handleEvent(Event event) { - if (event.getEventType().equals(CarrierShipmentPickupStartEvent.EVENT_TYPE)) { - handlePickup( event); - } if (event.getEventType().equals(CarrierShipmentDeliveryStartEvent.EVENT_TYPE)) { - handleDelivery(event); - } - } - - private void handlePickup(Event event) { + @Override + public void handleEvent(CarrierShipmentPickupStartEvent event) { Id vehicleId = Id.createVehicleId(event.getAttributes().get("vehicle")); Integer demand = Integer.valueOf(event.getAttributes().get(ATTRIBUTE_CAPACITYDEMAND)); @@ -82,8 +76,8 @@ private void handlePickup(Event event) { vehicle2Load.put(vehicleId, list); } - - private void handleDelivery(Event event) { + @Override + public void handleEvent(CarrierShipmentDeliveryStartEvent event) { Id vehicleId = Id.createVehicleId(event.getAttributes().get("vehicle")); Integer demand = Integer.valueOf(event.getAttributes().get(ATTRIBUTE_CAPACITYDEMAND)); @@ -95,12 +89,16 @@ private void handleDelivery(Event event) { void writeLoadPerVehicle(String analysisOutputDirectory, Scenario scenario) throws IOException { log.info("Writing out vehicle load analysis ..."); //Load per vehicle - String fileName = analysisOutputDirectory + "Load_perVehicle.tsv"; + String fileName = Path.of(analysisOutputDirectory).resolve("Load_perVehicle.tsv").toString(); BufferedWriter bw1 = new BufferedWriter(new FileWriter(fileName)); //Write headline: - bw1.write("vehicleId \t capacity \t maxLoad \t load state during tour"); + bw1.write(String.join(delimiter,"vehicleId", + "vehicleTypeId", + "capacity", + "maxLoad", + "load state during tour")); bw1.newLine(); for (Id vehicleId : vehicle2Load.keySet()) { @@ -112,13 +110,14 @@ void writeLoadPerVehicle(String analysisOutputDirectory, Scenario scenario) thro final Double capacity = vehicleType.getCapacity().getOther(); bw1.write(vehicleId.toString()); - bw1.write("\t" + capacity); - bw1.write("\t" + maxLoad); - bw1.write("\t" + load); + bw1.write(delimiter + vehicleType.getId().toString()); + bw1.write(delimiter + capacity); + bw1.write(delimiter + maxLoad); + bw1.write(delimiter + load); bw1.newLine(); } bw1.close(); - log.info("Output written to " + fileName); + log.info("Output written to {}", fileName); } } diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/CarrierPlanAnalysis.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/CarrierPlanAnalysis.java new file mode 100644 index 00000000000..610c376a5db --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/CarrierPlanAnalysis.java @@ -0,0 +1,156 @@ +/* + * *********************************************************************** * + * project: org.matsim.* + * *********************************************************************** * + * * + * copyright : (C) 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.freight.carriers.analysis; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Path; +import java.util.TreeMap; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Id; +import org.matsim.core.utils.misc.Time; +import org.matsim.freight.carriers.*; + +/** + * Some basic analysis / data collection for {@link Carriers}(files) + *

+ * For all carriers it writes out the: + * - score of the selected plan + * - number of tours (= vehicles) of the selected plan + * - number of Services (input) + * - number of Services (handled) + * - number of shipments (input) + * - number of shipments (handled) + * - number of not handled jobs + * - number of planned demand size + * - number of handled demand size + * to a tsv-file. + * + * @author Kai Martins-Turner (kturner), Ricardo Ewert + */ +public class CarrierPlanAnalysis { + + private static final Logger log = LogManager.getLogger(CarrierPlanAnalysis.class); + public final String delimiter; + + Carriers carriers; + + public CarrierPlanAnalysis(String delimiter, Carriers carriers) { + this.delimiter = delimiter; + this.carriers = carriers; + } + + public void runAnalysisAndWriteStats(String analysisOutputDirectory) throws IOException { + log.info("Writing out carrier analysis ..."); + //Load per vehicle + String fileName = Path.of(analysisOutputDirectory).resolve("Carrier_stats.tsv").toString(); + + try (BufferedWriter bw1 = new BufferedWriter(new FileWriter(fileName))) { + + //Write headline: + bw1.write(String.join(delimiter, + "carrierId", + "MATSimScoreSelectedPlan", + "jSpritScoreSelectedPlan", + "nuOfTours", + "nuOfShipments(input)", + "nuOfShipments(handled)", + "nuOfServices(input)", + "nuOfServices(handled)", + "noOfNotHandledJobs", + "nuOfPlanedDemandSize", + "nuOfHandledDemandSize", + "jspritComputationTime[HH:mm:ss]" + )); + bw1.newLine(); + + final TreeMap, Carrier> sortedCarrierMap = new TreeMap<>(carriers.getCarriers()); + + for (Carrier carrier : sortedCarrierMap.values()) { + + int numberOfPlanedShipments = carrier.getShipments().size(); + int numberOfPlanedServices = carrier.getServices().size(); + int numberOfHandledPickups = (int) carrier.getSelectedPlan().getScheduledTours().stream().mapToDouble( + t -> t.getTour().getTourElements().stream().filter(te -> te instanceof Tour.Pickup).count()).sum(); + int numberOfHandledDeliveries = (int) carrier.getSelectedPlan().getScheduledTours().stream().mapToDouble( + t -> t.getTour().getTourElements().stream().filter(te -> te instanceof Tour.Delivery).count()).sum(); + int nuOfServiceHandled = (int) carrier.getSelectedPlan().getScheduledTours().stream().mapToDouble( + t -> t.getTour().getTourElements().stream().filter(te -> te instanceof Tour.ServiceActivity).count()).sum(); + int numberOfPlanedDemandSize; + int numberOfHandledDemandSize; + int notHandledJobs; + if (numberOfPlanedShipments > 0) { + numberOfPlanedDemandSize = carrier.getShipments().values().stream().mapToInt(CarrierShipment::getSize).sum(); + numberOfHandledDemandSize = carrier.getSelectedPlan().getScheduledTours().stream().mapToInt( + t -> t.getTour().getTourElements().stream().filter(te -> te instanceof Tour.Pickup).mapToInt( + te -> (((Tour.Pickup) te).getShipment().getSize())).sum()).sum(); + notHandledJobs = numberOfPlanedShipments - numberOfHandledPickups; + } else { + numberOfPlanedDemandSize = carrier.getServices().values().stream().mapToInt(CarrierService::getCapacityDemand).sum(); + numberOfHandledDemandSize = carrier.getSelectedPlan().getScheduledTours().stream().mapToInt( + t -> t.getTour().getTourElements().stream().filter(te -> te instanceof Tour.ServiceActivity).mapToInt( + te -> ((Tour.ServiceActivity) te).getService().getCapacityDemand()).sum()).sum(); + notHandledJobs = numberOfPlanedServices - nuOfServiceHandled; + } + + if (numberOfPlanedServices != nuOfServiceHandled) { + log.warn("Number of services in input and handled are not equal for carrier {}. Jobs Input: {}, Jobs Handled: {}", + carrier.getId(), numberOfPlanedServices, nuOfServiceHandled); + } + if (numberOfPlanedShipments != numberOfHandledPickups) { + log.warn("Number of shipments in input and handled are not equal for carrier {}. Jobs Input: {}, Jobs Handled: {}", + carrier.getId(), numberOfPlanedShipments, numberOfHandledPickups); + } + if (numberOfHandledDeliveries != numberOfHandledPickups) { + log.warn( + "Number of handled pickups and deliveries are not equal for carrier {}. Pickups: {}, Deliveries: {}. This should not happen!!", + carrier.getId(), numberOfHandledPickups, numberOfHandledDeliveries); + } + bw1.write(carrier.getId().toString()); + bw1.write(delimiter + carrier.getSelectedPlan().getScore()); + bw1.write(delimiter + carrier.getSelectedPlan().getJspritScore()); + bw1.write(delimiter + carrier.getSelectedPlan().getScheduledTours().size()); + bw1.write(delimiter + numberOfPlanedShipments); + bw1.write(delimiter + numberOfHandledPickups); + bw1.write(delimiter + numberOfPlanedServices); + bw1.write(delimiter + nuOfServiceHandled); + bw1.write(delimiter + notHandledJobs); + bw1.write(delimiter + numberOfPlanedDemandSize); + bw1.write(delimiter + numberOfHandledDemandSize); + if (CarriersUtils.getJspritComputationTime(carrier) != Integer.MIN_VALUE) + bw1.write(delimiter + Time.writeTime(CarriersUtils.getJspritComputationTime(carrier), Time.TIMEFORMAT_HHMMSS)); + else + bw1.write(delimiter + "null"); + + bw1.newLine(); + } + + bw1.close(); + log.info("Output written to {}", fileName); + } catch (IOException e) { + log.error("Error writing output to file: {}", fileName); + throw e; + } + } +} diff --git a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java similarity index 70% rename from contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java index 3037716368c..4e53c559222 100644 --- a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/FreightTimeAndDistanceAnalysisEventsHandler.java @@ -21,38 +21,43 @@ package org.matsim.freight.carriers.analysis; +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Path; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.TreeMap; 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.Scenario; -import org.matsim.api.core.v01.events.Event; import org.matsim.api.core.v01.events.LinkEnterEvent; import org.matsim.api.core.v01.events.LinkLeaveEvent; import org.matsim.api.core.v01.events.VehicleEntersTrafficEvent; import org.matsim.api.core.v01.events.VehicleLeavesTrafficEvent; +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.VehicleEntersTrafficEventHandler; +import org.matsim.api.core.v01.events.handler.VehicleLeavesTrafficEventHandler; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.CarriersUtils; import org.matsim.freight.carriers.Tour; import org.matsim.freight.carriers.events.CarrierTourEndEvent; import org.matsim.freight.carriers.events.CarrierTourStartEvent; -import org.matsim.core.events.handler.BasicEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierTourEndEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierTourStartEventHandler; import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.VehicleType; import org.matsim.vehicles.VehicleUtils; -import java.io.BufferedWriter; -import java.io.FileWriter; -import java.io.IOException; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.TreeMap; - /** * @author Kai Martins-Turner (kturner) */ -public class FreightTimeAndDistanceAnalysisEventsHandler implements BasicEventHandler { +public class FreightTimeAndDistanceAnalysisEventsHandler implements CarrierTourStartEventHandler, CarrierTourEndEventHandler, LinkEnterEventHandler, LinkLeaveEventHandler, VehicleEntersTrafficEventHandler, VehicleLeavesTrafficEventHandler { private final static Logger log = LogManager.getLogger(FreightTimeAndDistanceAnalysisEventsHandler.class); + private final String delimiter; private final Scenario scenario; private final Map, Double> vehicleId2TourDuration = new LinkedHashMap<>(); @@ -74,21 +79,24 @@ public class FreightTimeAndDistanceAnalysisEventsHandler implements BasicEventHa private final Map, Double> vehicleEnteredLinkTime = new LinkedHashMap<>(); - public FreightTimeAndDistanceAnalysisEventsHandler(Scenario scenario) { + public FreightTimeAndDistanceAnalysisEventsHandler(String delimiter, Scenario scenario) { + this.delimiter = delimiter; this.scenario = scenario; } - private void handleEvent(CarrierTourStartEvent event) { + @Override + public void handleEvent(CarrierTourStartEvent event) { // Save time of freight tour start final String key = event.getCarrierId().toString() + "_" + event.getTourId().toString(); tourStartTime.put(key, event.getTime()); } //Fix costs for vehicle usage - private void handleEvent(CarrierTourEndEvent event) { + @Override + public void handleEvent(CarrierTourEndEvent event) { final String key = event.getCarrierId().toString() + "_" + event.getTourId().toString(); double tourDuration = event.getTime() - tourStartTime.get(key); - vehicleId2TourDuration.put(event.getVehicleId(), tourDuration); + vehicleId2TourDuration.put(event.getVehicleId(), tourDuration); //TODO, check if this may overwrite old data and if this is intended to do so VehicleType vehType = VehicleUtils.findVehicle(event.getVehicleId(), scenario).getType(); vehicleTypeId2SumOfTourDuration.merge(vehType.getId(), tourDuration, Double::sum); @@ -99,7 +107,13 @@ private void handleEvent(CarrierTourEndEvent event) { vehicleId2VehicleType.putIfAbsent(event.getVehicleId(), vehType); } - private void handleEvent(LinkEnterEvent event) { + @Override + public void handleEvent(VehicleEntersTrafficEvent event){ + vehicleEnteredLinkTime.put(event.getVehicleId(), event.getTime()); + } + + @Override + public void handleEvent(LinkEnterEvent event) { final double distance = scenario.getNetwork().getLinks().get(event.getLinkId()).getLength(); vehicleId2TourLength.merge(event.getVehicleId(), distance, Double::sum); vehicleEnteredLinkTime.put(event.getVehicleId(), event.getTime()); //Safe time when entering the link. @@ -109,7 +123,8 @@ private void handleEvent(LinkEnterEvent event) { } //If the vehicle leaves a link at the end, the travelTime is calculated and stored. - private void handleEvent(LinkLeaveEvent event){ + @Override + public void handleEvent(LinkLeaveEvent event){ final Id vehicleId = event.getVehicleId(); if (vehicleEnteredLinkTime.containsKey(vehicleId)){ double tt = event.getTime() - vehicleEnteredLinkTime.get(vehicleId); @@ -123,7 +138,8 @@ private void handleEvent(LinkLeaveEvent event){ } //If the vehicle leaves a link because it reached its destination, the travelTime is calculated and stored. - private void handleEvent(VehicleLeavesTrafficEvent event){ + @Override + public void handleEvent(VehicleLeavesTrafficEvent event){ final Id vehicleId = event.getVehicleId(); if (vehicleEnteredLinkTime.containsKey(vehicleId)){ double tt = event.getTime() - vehicleEnteredLinkTime.get(vehicleId); @@ -136,39 +152,31 @@ private void handleEvent(VehicleLeavesTrafficEvent event){ } } - private void handleEvent(VehicleEntersTrafficEvent event){ - vehicleEnteredLinkTime.put(event.getVehicleId(), event.getTime()); - } - - @Override public void handleEvent(Event event) { - if (event instanceof CarrierTourStartEvent carrierTourStartEvent) { - handleEvent(carrierTourStartEvent); - } else if (event instanceof CarrierTourEndEvent carrierTourEndEvent) { - handleEvent(carrierTourEndEvent); - } else if (event instanceof LinkEnterEvent linkEnterEvent) { - handleEvent(linkEnterEvent); - } else if (event instanceof LinkLeaveEvent linkLeaveEvent) { - handleEvent(linkLeaveEvent); - } else if (event instanceof VehicleLeavesTrafficEvent vehicleLeavesTrafficEvent) { - handleEvent(vehicleLeavesTrafficEvent); - } else if (event instanceof VehicleEntersTrafficEvent vehicleEntersTrafficEvent) { - handleEvent(vehicleEntersTrafficEvent); - } - } - void writeTravelTimeAndDistancePerVehicle(String analysisOutputDirectory, Scenario scenario) throws IOException { log.info("Writing out Time & Distance & Costs ... perVehicle"); //Travel time and distance per vehicle - String fileName = analysisOutputDirectory + "TimeDistance_perVehicle.tsv"; + String fileName = Path.of(analysisOutputDirectory).resolve("TimeDistance_perVehicle.tsv").toString(); BufferedWriter bw1 = new BufferedWriter(new FileWriter(fileName)); //Write headline: - bw1.write("vehicleId \t carrierId \t vehicleTypeId \t tourId \t " - + "tourDuration[s] \t tourDuration[h] \t" - + "travelDistance[m] \t travelDistance[km] \t " + - "travelTime[s] \t travelTime[h] \t" + - "costPerSecond[EUR/s] \t costPerMeter[EUR/m] \t fixedCosts[EUR] \t varCostsTime[EUR] \t varCostsDist[EUR] \t totalCosts[EUR]"); + bw1.write(String.join(delimiter, + "vehicleId", + "carrierId", + "vehicleTypeId", + "tourId", + "tourDuration[s]", + "tourDuration[h]", + "travelDistance[m]", + "travelDistance[km]", + "travelTime[s]", + "travelTime[h]", + "costPerSecond[EUR/s]", + "costPerMeter[EUR/m]", + "fixedCosts[EUR]", + "varCostsTime[EUR]", + "varCostsDist[EUR]", + "totalCosts[EUR]")); bw1.newLine(); for (Id vehicleId : vehicleId2VehicleType.keySet()) { @@ -188,34 +196,33 @@ void writeTravelTimeAndDistancePerVehicle(String analysisOutputDirectory, Scenar final double totalVehCosts = fixedCost + varCostsTime + varCostsDist; bw1.write(vehicleId.toString()); - bw1.write("\t" + vehicleId2CarrierId.get(vehicleId)); - bw1.write("\t" + vehicleType.getId().toString()); - bw1.write("\t" + vehicleId2TourId.get(vehicleId)); + bw1.write(delimiter + vehicleId2CarrierId.get(vehicleId)); + bw1.write(delimiter + vehicleType.getId().toString()); + bw1.write(delimiter + vehicleId2TourId.get(vehicleId)); - bw1.write("\t" + durationInSeconds); - bw1.write("\t" + durationInSeconds /3600); + bw1.write(delimiter + durationInSeconds); + bw1.write(delimiter + durationInSeconds /3600); - bw1.write("\t" + distanceInMeters); - bw1.write("\t" + distanceInMeters/1000); + bw1.write(delimiter + distanceInMeters); + bw1.write(delimiter + distanceInMeters/1000); - bw1.write("\t" + travelTimeInSeconds); - bw1.write("\t" + travelTimeInSeconds /3600); + bw1.write(delimiter + travelTimeInSeconds); + bw1.write(delimiter + travelTimeInSeconds /3600); - bw1.write("\t" + costsPerSecond); - bw1.write("\t" + costsPerMeter); - bw1.write("\t" + fixedCost); - bw1.write("\t" + varCostsTime); - bw1.write("\t" + varCostsDist); - bw1.write("\t" + totalVehCosts); + bw1.write(delimiter + costsPerSecond); + bw1.write(delimiter + costsPerMeter); + bw1.write(delimiter + fixedCost); + bw1.write(delimiter + varCostsTime); + bw1.write(delimiter + varCostsDist); + bw1.write(delimiter + totalVehCosts); bw1.newLine(); } bw1.close(); - log.info("Output written to " + fileName); + log.info("Output written to {}", fileName); } - void writeTravelTimeAndDistancePerVehicleType(String analysisOutputDirectory, Scenario scenario) throws IOException { log.info("Writing out Time & Distance & Costs ... perVehicleType"); @@ -226,16 +233,26 @@ void writeTravelTimeAndDistancePerVehicleType(String analysisOutputDirectory, Sc vehicleTypesMap.putIfAbsent(vehicleType.getId(), vehicleType); } - String fileName = analysisOutputDirectory + "TimeDistance_perVehicleType.tsv"; + String fileName = Path.of(analysisOutputDirectory).resolve("TimeDistance_perVehicleType.tsv").toString(); BufferedWriter bw1 = new BufferedWriter(new FileWriter(fileName)); //Write headline: - bw1.write("vehicleTypeId \t nuOfVehicles \t " + - "SumOfTourDuration[s] \t SumOfTourDuration[h] \t" + - "SumOfTravelDistances[m] \t SumOfTravelDistances[km] \t " + - "SumOfTravelTime[s] \t SumOfTravelTime[h] \t" + - "costPerSecond[EUR/s] \t costPerMeter[EUR/m] \t fixedCosts[EUR/veh] \t" + - "varCostsTime[EUR] \t varCostsDist[EUR] \t fixedCosts[EUR] \t totalCosts[EUR]"); + bw1.write(String.join(delimiter, + "vehicleTypeId", + "nuOfVehicles", + "SumOfTourDuration[s]", + "SumOfTourDuration[h]", + "SumOfTravelDistances[m]", + "SumOfTravelDistances[km]", + "SumOfTravelTime[s]", + "SumOfTravelTime[h]", + "costPerSecond[EUR/s]", + "costPerMeter[EUR/m]", + "fixedCosts[EUR/veh]", + "varCostsTime[EUR]", + "varCostsDist[EUR]", + "fixedCosts[EUR]", + "totalCosts[EUR]")); bw1.newLine(); for (VehicleType vehicleType : vehicleTypesMap.values()) { @@ -255,25 +272,25 @@ void writeTravelTimeAndDistancePerVehicleType(String analysisOutputDirectory, Sc bw1.write(vehicleType.getId().toString()); - bw1.write("\t" + nuOfVehicles); - bw1.write("\t" + sumOfTourDurationInSeconds); - bw1.write("\t" + sumOfTourDurationInSeconds / 3600); - bw1.write("\t" + sumOfDistanceInMeters); - bw1.write("\t" + sumOfDistanceInMeters / 1000); - bw1.write("\t" + sumOfTravelTimeInSeconds); - bw1.write("\t" + sumOfTravelTimeInSeconds / 3600); - bw1.write("\t" + costRatePerSecond); - bw1.write("\t" + costRatePerMeter); - bw1.write("\t" + fixedCostPerVeh); - bw1.write("\t" + sumOfVarCostsTime); - bw1.write("\t" + sumOfVarCostsDistance); - bw1.write("\t" + sumOfFixCosts); - bw1.write("\t" + (sumOfFixCosts + sumOfVarCostsTime + sumOfVarCostsDistance)); + bw1.write(delimiter + nuOfVehicles); + bw1.write(delimiter + sumOfTourDurationInSeconds); + bw1.write(delimiter + sumOfTourDurationInSeconds / 3600); + bw1.write(delimiter + sumOfDistanceInMeters); + bw1.write(delimiter + sumOfDistanceInMeters / 1000); + bw1.write(delimiter + sumOfTravelTimeInSeconds); + bw1.write(delimiter + sumOfTravelTimeInSeconds / 3600); + bw1.write(delimiter + costRatePerSecond); + bw1.write(delimiter + costRatePerMeter); + bw1.write(delimiter + fixedCostPerVeh); + bw1.write(delimiter + sumOfVarCostsTime); + bw1.write(delimiter + sumOfVarCostsDistance); + bw1.write(delimiter + sumOfFixCosts); + bw1.write(delimiter + (sumOfFixCosts + sumOfVarCostsTime + sumOfVarCostsDistance)); bw1.newLine(); } bw1.close(); - log.info("Output written to " + fileName); + log.info("Output written to {}", fileName); } } diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java new file mode 100644 index 00000000000..d6a01e09409 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java @@ -0,0 +1,191 @@ +/* + * *********************************************************************** * + * project: org.matsim.* + * *********************************************************************** * + * * + * copyright : (C) 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.freight.carriers.analysis; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Scenario; +import org.matsim.core.api.experimental.events.EventsManager; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.events.EventsUtils; +import org.matsim.core.events.MatsimEventsReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.Carriers; +import org.matsim.freight.carriers.CarriersUtils; +import org.matsim.freight.carriers.FreightCarriersConfigGroup; +import org.matsim.freight.carriers.events.CarrierEventsReaders; + +//import static org.matsim.application.ApplicationUtils.globFile; + + +/** + * A first approach for some analysis based on the freight events introduced in 2022/23. + * This class comes from teaching SimGV in the winter term 2022/23. + *

+ * This class should get extended and prepared as a standardized analysis for freight output. + * This should also get aligned with the current development in Simwrapper. + * Todo: Add some tests. + * + * @author kturner (Kai Martins-Turner) + */ +public class RunFreightAnalysisEventBased { + + private static final Logger log = LogManager.getLogger(RunFreightAnalysisEventBased.class); + + //Where is your simulation output, that should be analysed? + private String EVENTS_PATH = null; + private final String ANALYSIS_OUTPUT_PATH; + private Scenario scenario = null; + private Carriers carriers = null; + private final String delimiter = "\t"; + + //TODO discuss renaming without EventBased. If this becomes the standard carrier output + /** + * This constructor automatically searches for the necessary output file in a simulation run output. + * + * @param simOutputPath The output directory of the simulation run + * @param analysisOutputPath The directory where the result of the analysis should go to + * @param globalCrs The CRS of the simulation + */ + public RunFreightAnalysisEventBased(String simOutputPath, String analysisOutputPath, String globalCrs) { + + this.ANALYSIS_OUTPUT_PATH = analysisOutputPath; +// this.EVENTS_PATH = globFile(simOutputPath, "*output_events.*"); +// Path vehiclesPath = globFile(simOutputPath, "*output_allVehicles.*"); +// Path networkPath = globFile(simOutputPath, "*output_network.*"); +// Path carriersPath = globFile(simOutputPath, "*output_carriers.*"); +// Path carriersVehicleTypesPath = globFile(simOutputPath, "*output_carriersVehicleTypes.*"); + + // the better version with the globFile method is not available since there is a circular dependency between the modules application and freight + + this.EVENTS_PATH = Path.of(simOutputPath).resolve("output_events.xml.gz").toString(); + String vehiclesPath = Path.of(simOutputPath).resolve("output_allVehicles.xml.gz").toString(); + String networkPath = Path.of(simOutputPath).resolve("output_network.xml.gz").toString(); + String carriersPath = Path.of(simOutputPath).resolve("output_carriers.xml.gz").toString(); + String carriersVehicleTypesPath = Path.of(simOutputPath).resolve("output_carriersVehicleTypes.xml.gz").toString(); + + createScenarioForFreightAnalysis(vehiclesPath, networkPath, carriersPath, carriersVehicleTypesPath, globalCrs); + } + + /** + * Alternative if you want to set the paths to the necessary resources directly. + * + * @param networkPath Path to the network file + * @param vehiclesPath Path to the vehicle file + * @param carriersPath Path to the carriers file + * @param carriersVehicleTypesPath Path to the carriersVehicleTypes file + * @param eventsPath Path to the events file + * @param analysisOutputPath Path to the output directory + * @param globalCrs The CRS of the simulation + */ + public RunFreightAnalysisEventBased(String networkPath, String vehiclesPath, String carriersPath, String carriersVehicleTypesPath, String eventsPath, + String analysisOutputPath, String globalCrs) { + this.EVENTS_PATH = eventsPath; + this.ANALYSIS_OUTPUT_PATH = analysisOutputPath; + + createScenarioForFreightAnalysis(vehiclesPath, networkPath, carriersPath, carriersVehicleTypesPath, globalCrs); + } + + /** + * Constructor, if you only want to have the carrier analysis. + * + * @param carriers The carriers to be analysed + * @param analysisOutputPath The directory where the result of the analysis should go to + */ + public RunFreightAnalysisEventBased(Carriers carriers, String analysisOutputPath) { + this.carriers = carriers; + this.ANALYSIS_OUTPUT_PATH = analysisOutputPath; + } + + private void createScenarioForFreightAnalysis(String vehiclesPath, String networkPath, String carriersPath, String carriersVehicleTypesPath, + String globalCrs) { + Config config = ConfigUtils.createConfig(); + config.vehicles().setVehiclesFile(vehiclesPath); + config.network().setInputFile(networkPath); + config.plans().setInputFile(null); + config.eventsManager().setNumberOfThreads(null); + config.eventsManager().setEstimatedNumberOfEvents(null); + config.global().setNumberOfThreads(1); + config.global().setCoordinateSystem(globalCrs); + + //freight settings + FreightCarriersConfigGroup freightCarriersConfigGroup = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightCarriersConfigGroup.setCarriersFile(carriersPath); + freightCarriersConfigGroup.setCarriersVehicleTypesFile(carriersVehicleTypesPath.toString()); + + scenario = ScenarioUtils.loadScenario(config); + + //load carriers according to freight config + CarriersUtils.loadCarriersAccordingToFreightConfig( scenario ); + this.carriers = CarriersUtils.addOrGetCarriers(scenario); + } + + public void runCarriersAnalysis() throws IOException { + + //Where to store the analysis output? + File folder = new File(String.valueOf(ANALYSIS_OUTPUT_PATH)); + folder.mkdirs(); + if (allCarriersHavePlans(carriers)) { + CarrierPlanAnalysis carrierPlanAnalysis = new CarrierPlanAnalysis(delimiter, carriers); + carrierPlanAnalysis.runAnalysisAndWriteStats(ANALYSIS_OUTPUT_PATH); + } + else { + log.warn("########## Not all carriers have plans. Skipping CarrierPlanAnalysis."); //TODO perhaps skipp complete analysis + } + } + public void runCompleteAnalysis() throws IOException { + runCarriersAnalysis(); + + // Prepare eventsManager - start of event based Analysis; + EventsManager eventsManager = EventsUtils.createEventsManager(); + + FreightTimeAndDistanceAnalysisEventsHandler freightTimeAndDistanceAnalysisEventsHandler = new FreightTimeAndDistanceAnalysisEventsHandler(delimiter, scenario); + eventsManager.addHandler(freightTimeAndDistanceAnalysisEventsHandler); + + CarrierLoadAnalysis carrierLoadAnalysis = new CarrierLoadAnalysis(delimiter, CarriersUtils.getCarriers(scenario)); + eventsManager.addHandler(carrierLoadAnalysis); + + eventsManager.initProcessing(); + MatsimEventsReader matsimEventsReader = CarrierEventsReaders.createEventsReader(eventsManager); + + matsimEventsReader.readFile(EVENTS_PATH); + eventsManager.finishProcessing(); + + log.info("Analysis completed."); + log.info("Writing output..."); + freightTimeAndDistanceAnalysisEventsHandler.writeTravelTimeAndDistancePerVehicle(ANALYSIS_OUTPUT_PATH, scenario); + freightTimeAndDistanceAnalysisEventsHandler.writeTravelTimeAndDistancePerVehicleType(ANALYSIS_OUTPUT_PATH, scenario); + carrierLoadAnalysis.writeLoadPerVehicle(ANALYSIS_OUTPUT_PATH, scenario); + } + + private boolean allCarriersHavePlans(Carriers carriers) { + for (Carrier carrier : carriers.getCarriers().values()) + if (carrier.getSelectedPlan() == null) return false; + + return true; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierAgent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierAgent.java similarity index 99% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierAgent.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierAgent.java index da31ae5637d..1afe10da4d0 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierAgent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierAgent.java @@ -19,8 +19,9 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; +import java.util.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; @@ -38,8 +39,6 @@ import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.VehicleUtils; -import java.util.*; - /** * This keeps track of the carrier during simulation. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierAgentTracker.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierAgentTracker.java similarity index 99% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierAgentTracker.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierAgentTracker.java index 09c4036d92f..f2bd02a204e 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierAgentTracker.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierAgentTracker.java @@ -19,9 +19,10 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; import com.google.inject.Inject; +import java.util.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; @@ -35,8 +36,6 @@ import org.matsim.freight.carriers.events.CarrierEventCreator; import org.matsim.freight.carriers.events.CarrierEventCreatorUtils; -import java.util.*; - /** * This keeps track of all carrierAgents during simulation. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierControlerListener.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierControllerListener.java similarity index 92% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierControlerListener.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierControllerListener.java index f8a103bcbe5..136fecf4725 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierControlerListener.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierControllerListener.java @@ -19,9 +19,10 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; import jakarta.inject.Inject; +import javax.annotation.Nullable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Scenario; @@ -31,8 +32,6 @@ import org.matsim.core.controler.listener.ScoringListener; import org.matsim.freight.carriers.CarriersUtils; -import javax.annotation.Nullable; - /** * Controls the workflow of the simulation. *

@@ -46,13 +45,13 @@ * // not sure if this _should_ be public, but current LSP design makes this necessary. kai, sep'20 */ -public class CarrierControlerListener implements ScoringListener, ReplanningListener { +public class CarrierControllerListener implements ScoringListener, ReplanningListener { // not sure if this _should_ be public, but current LSP design makes this necessary. // It is done analogue to CarrierAgentTracker. kmt oct'22 @SuppressWarnings("unused") - private static final Logger log = LogManager.getLogger( CarrierControlerListener.class ) ; + private static final Logger log = LogManager.getLogger( CarrierControllerListener.class ) ; private final CarrierStrategyManager strategyManager; private final CarrierAgentTracker carrierAgentTracker; @@ -62,7 +61,8 @@ public class CarrierControlerListener implements ScoringListener, ReplanningList /** * Constructs a controller with a set of carriers, re-planning capabilities and scoring-functions. */ - @Inject CarrierControlerListener( @Nullable CarrierStrategyManager strategyManager, CarrierAgentTracker carrierAgentTracker ) { + @Inject + CarrierControllerListener(@Nullable CarrierStrategyManager strategyManager, CarrierAgentTracker carrierAgentTracker ) { // The current default is bind( CarrierStrategyManager.class ).toProvider( () -> null ); this.strategyManager = strategyManager; this.carrierAgentTracker = carrierAgentTracker; diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierControlerUtils.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierControllerUtils.java similarity index 94% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierControlerUtils.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierControllerUtils.java index fe19207bfcc..5d15a6821f0 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierControlerUtils.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierControllerUtils.java @@ -19,7 +19,7 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; /** * Utils class for (package-private) content of freight.carriers.controler - package; @@ -27,7 +27,7 @@ * @author kturner * */ -public class CarrierControlerUtils { +public class CarrierControllerUtils { public static CarrierStrategyManager createDefaultCarrierStrategyManager() { return new CarrierStrategyManagerImpl(); 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/controller/CarrierDriverAgent.java similarity index 99% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierDriverAgent.java index c7f030f3457..ba8e40e3d71 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierDriverAgent.java @@ -19,8 +19,13 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; @@ -41,12 +46,6 @@ import org.matsim.freight.carriers.events.CarrierEventCreator; import org.matsim.vehicles.Vehicle; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - /** * This keeps track of a scheduledTour during simulation and can thus be seen as the driver of the vehicle that runs the tour. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierModule.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierModule.java similarity index 97% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierModule.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierModule.java index e2b9e1d8354..d95e1e7ac18 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierModule.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierModule.java @@ -19,11 +19,12 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; +import java.util.List; import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.events.Event; import org.matsim.api.core.v01.population.Activity; @@ -38,8 +39,6 @@ import org.matsim.core.scoring.ScoringFunction; import org.matsim.freight.carriers.*; -import java.util.List; - public final class CarrierModule extends AbstractModule { @@ -49,8 +48,8 @@ public final class CarrierModule extends AbstractModule { bind(Carriers.class).toProvider( new CarrierProvider() ).asEagerSingleton(); // needs to be eager since it is still scenario construction. kai, oct'19 // this is probably ok - bind(CarrierControlerListener.class).in( Singleton.class ); - addControlerListenerBinding().to(CarrierControlerListener.class); + bind(CarrierControllerListener.class).in( Singleton.class ); + addControlerListenerBinding().to(CarrierControllerListener.class); bind(CarrierAgentTracker.class).in( Singleton.class ); addEventHandlerBinding().to( CarrierAgentTracker.class ); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierReRouteVehicles.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierReRouteVehicles.java similarity index 95% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierReRouteVehicles.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierReRouteVehicles.java index f59ba81c930..a2e32470a88 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierReRouteVehicles.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierReRouteVehicles.java @@ -19,7 +19,7 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -77,8 +77,8 @@ private CarrierReRouteVehicles( LeastCostPathCalculator router, Network network, /** * Routes the carrierPlan in time and space. * - * @param carrierPlan - * @throws IllegalStateException if carrierPlan is null. + * @param carrierPlan the carrierPlan to be routed. + * @throws IllegalStateException if carrierPlan is null. * @see CarrierTimeAndSpaceTourRouter */ @Override diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierScoringFunctionFactory.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierScoringFunctionFactory.java similarity index 96% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierScoringFunctionFactory.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierScoringFunctionFactory.java index c73a41b3008..79338a48884 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierScoringFunctionFactory.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierScoringFunctionFactory.java @@ -19,7 +19,7 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; import org.matsim.core.scoring.ScoringFunction; import org.matsim.freight.carriers.Carrier; diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierStrategyManager.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierStrategyManager.java similarity index 98% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierStrategyManager.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierStrategyManager.java index f1d6d06e84e..8a7a3cfa263 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierStrategyManager.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierStrategyManager.java @@ -19,7 +19,7 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; import com.google.inject.Provider; import org.matsim.core.replanning.GenericStrategyManager; diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierStrategyManagerImpl.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierStrategyManagerImpl.java similarity index 98% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierStrategyManagerImpl.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierStrategyManagerImpl.java index 5bcad45b183..8a673af527b 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierStrategyManagerImpl.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierStrategyManagerImpl.java @@ -19,8 +19,9 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; +import java.util.List; import org.matsim.api.core.v01.population.HasPlansAndId; import org.matsim.core.replanning.GenericPlanStrategy; import org.matsim.core.replanning.GenericStrategyManager; @@ -30,8 +31,6 @@ import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.CarrierPlan; -import java.util.List; - class CarrierStrategyManagerImpl implements CarrierStrategyManager{ final GenericStrategyManager delegate = new GenericStrategyManagerImpl<>(); @Override public void addStrategy( GenericPlanStrategy strategy, String subpopulation, double weight ){ diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierTimeAllocationMutator.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierTimeAllocationMutator.java similarity index 98% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierTimeAllocationMutator.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierTimeAllocationMutator.java index 3b7fc83af01..b38a96a8fd2 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierTimeAllocationMutator.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierTimeAllocationMutator.java @@ -18,17 +18,16 @@ * *********************************************************************** * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; +import java.util.ArrayList; +import java.util.Collection; import org.matsim.core.gbl.MatsimRandom; import org.matsim.core.replanning.ReplanningContext; import org.matsim.core.replanning.modules.GenericPlanStrategyModule; import org.matsim.freight.carriers.CarrierPlan; import org.matsim.freight.carriers.ScheduledTour; -import java.util.ArrayList; -import java.util.Collection; - /** * @author nagel * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierTimeAndSpaceTourRouter.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierTimeAndSpaceTourRouter.java similarity index 96% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierTimeAndSpaceTourRouter.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierTimeAndSpaceTourRouter.java index 0a6a7399c9f..b02c5938e42 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierTimeAndSpaceTourRouter.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierTimeAndSpaceTourRouter.java @@ -19,8 +19,10 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; +import java.util.ArrayList; +import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; @@ -41,9 +43,6 @@ import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.VehicleType; -import java.util.ArrayList; -import java.util.List; - /** * Router routing scheduledTours. * @@ -94,9 +93,9 @@ public Attributes getAttributes() { /** * Constructs the timeAndSpaceRouter with a leastCostPathCalculator, network and travelTime. - * @param router - * @param network - * @param travelTime + * @param router the leastCostPathCalculator + * @param network the network + * @param travelTime the travelTime * @see LeastCostPathCalculator, Network, TravelTime */ public CarrierTimeAndSpaceTourRouter( LeastCostPathCalculator router, Network network, TravelTime travelTime ) { @@ -111,7 +110,7 @@ public CarrierTimeAndSpaceTourRouter( LeastCostPathCalculator router, Network ne * *

Uses a leastCostPathCalculator to calculate a route/path from one activity to another. It starts at the departureTime of * the scheduledTour and determines activity arrival and departure times considering activities time-windows. - * @param tour + * @param tour the scheduledTour to be routed. */ public void route(ScheduledTour tour) { MatsimVehicleAdapter matsimVehicle = new MatsimVehicleAdapter(tour.getVehicle()); 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/controller/CarrierVehicleReRouter.java similarity index 98% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierVehicleReRouter.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierVehicleReRouter.java index cd03cb5fd94..1d9a02d74d0 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierVehicleReRouter.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/CarrierVehicleReRouter.java @@ -19,7 +19,7 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm; import com.graphhopper.jsprit.core.algorithm.state.StateManager; @@ -35,6 +35,7 @@ import com.graphhopper.jsprit.io.algorithm.AlgorithmConfig; import com.graphhopper.jsprit.io.algorithm.AlgorithmConfigXmlReader; import com.graphhopper.jsprit.io.algorithm.VehicleRoutingAlgorithms; +import java.util.Collection; import org.matsim.api.core.v01.network.Network; import org.matsim.contrib.roadpricing.RoadPricingScheme; import org.matsim.core.replanning.ReplanningContext; @@ -45,9 +46,6 @@ import org.matsim.freight.carriers.CarrierVehicleTypes; import org.matsim.freight.carriers.jsprit.MatsimJspritFactory; import org.matsim.freight.carriers.jsprit.NetworkBasedTransportCosts; -import org.matsim.freight.carriers.jsprit.VehicleTypeDependentRoadPricingCalculator; - -import java.util.Collection; class CarrierVehicleReRouter implements GenericPlanStrategyModule{ diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/FreightActivity.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/FreightActivity.java similarity index 98% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/FreightActivity.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/FreightActivity.java index 42cd58ae587..ee3f0e65afc 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/FreightActivity.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/FreightActivity.java @@ -19,7 +19,7 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/FreightAgentSource.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/FreightAgentSource.java similarity index 98% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/FreightAgentSource.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/FreightAgentSource.java index f5613f1a961..c1550c49701 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/FreightAgentSource.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/FreightAgentSource.java @@ -19,9 +19,11 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; import com.google.inject.Inject; +import java.util.ArrayList; +import java.util.Collection; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; @@ -35,8 +37,6 @@ import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.VehicleUtils; -import java.util.ArrayList; -import java.util.Collection; /** * Created by IntelliJ IDEA. User: zilske Date: 10/31/11 Time: 5:59 PM To change * this template use File | Settings | File Templates. diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/WithinDayActivityReScheduling.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/WithinDayActivityReScheduling.java similarity index 98% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/controler/WithinDayActivityReScheduling.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/controller/WithinDayActivityReScheduling.java index 285939a7174..0e4cbebfa6d 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/WithinDayActivityReScheduling.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controller/WithinDayActivityReScheduling.java @@ -19,9 +19,12 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; import com.google.inject.Inject; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; @@ -38,10 +41,6 @@ import org.matsim.freight.carriers.Tour.Start; import org.matsim.freight.carriers.Tour.TourActivity; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - /* * Physically enforces beginnings of time windows for freight activities, i.e. freight agents * wait before closed doors until they can deliver / pick up their goods. diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/AbstractCarrierEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/AbstractCarrierEvent.java index 1380144b9b4..497bc3dca7e 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/AbstractCarrierEvent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/AbstractCarrierEvent.java @@ -21,6 +21,7 @@ package org.matsim.freight.carriers.events; +import java.util.Map; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.Event; import org.matsim.api.core.v01.events.HasLinkId; @@ -29,8 +30,6 @@ import org.matsim.freight.carriers.Carrier; import org.matsim.vehicles.Vehicle; -import java.util.Map; - /** * A general freight event contains the information (= {@link Id}) of the * - {@link Carrier} diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierEventsReaders.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierEventsReaders.java index 23c9176a0ff..ee06d87ba6d 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierEventsReaders.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierEventsReaders.java @@ -21,11 +21,10 @@ package org.matsim.freight.carriers.events; +import java.util.Map; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.events.MatsimEventsReader; -import java.util.Map; - /** * Creates an {@link MatsimEventsReader} that also handles the carrier specific events. *

diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierServiceEndEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierServiceEndEvent.java index bfd8ad7d68c..f806248471c 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierServiceEndEvent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierServiceEndEvent.java @@ -21,6 +21,7 @@ package org.matsim.freight.carriers.events; +import java.util.Map; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.GenericEvent; import org.matsim.api.core.v01.network.Link; @@ -28,8 +29,6 @@ import org.matsim.freight.carriers.CarrierService; import org.matsim.vehicles.Vehicle; -import java.util.Map; - /** * An event, that informs that a Freight {@link CarrierService} activity has ended. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierServiceStartEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierServiceStartEvent.java index 1b866d5ce5b..d1b4d816ace 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierServiceStartEvent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierServiceStartEvent.java @@ -21,6 +21,7 @@ package org.matsim.freight.carriers.events; +import java.util.Map; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.GenericEvent; import org.matsim.api.core.v01.network.Link; @@ -28,8 +29,6 @@ import org.matsim.freight.carriers.CarrierService; import org.matsim.vehicles.Vehicle; -import java.util.Map; - /** * An event, that informs that a Freight {@link CarrierService} activity has started. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryEndEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryEndEvent.java index c02717031fa..8f60260a067 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryEndEvent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryEndEvent.java @@ -21,6 +21,7 @@ package org.matsim.freight.carriers.events; +import java.util.Map; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.GenericEvent; import org.matsim.api.core.v01.network.Link; @@ -28,8 +29,6 @@ import org.matsim.freight.carriers.CarrierShipment; import org.matsim.vehicles.Vehicle; -import java.util.Map; - /** * An event, that informs that a Freight {@link CarrierShipment} delivery-activity has ended. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryStartEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryStartEvent.java index 43cf21fc752..a30035968c0 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryStartEvent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryStartEvent.java @@ -21,6 +21,9 @@ package org.matsim.freight.carriers.events; +import static org.matsim.freight.carriers.events.CarrierEventAttributes.*; + +import java.util.Map; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.GenericEvent; import org.matsim.api.core.v01.network.Link; @@ -28,10 +31,6 @@ import org.matsim.freight.carriers.CarrierShipment; import org.matsim.vehicles.Vehicle; -import java.util.Map; - -import static org.matsim.freight.carriers.events.CarrierEventAttributes.*; - /** * An event, that informs that a Freight {@link CarrierShipment} delivery-activity has started. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentPickupEndEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentPickupEndEvent.java index 90e1fd137b7..4316e6f4dfe 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentPickupEndEvent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentPickupEndEvent.java @@ -21,6 +21,9 @@ package org.matsim.freight.carriers.events; +import static org.matsim.freight.carriers.events.CarrierEventAttributes.*; + +import java.util.Map; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.GenericEvent; import org.matsim.api.core.v01.network.Link; @@ -28,10 +31,6 @@ import org.matsim.freight.carriers.CarrierShipment; import org.matsim.vehicles.Vehicle; -import java.util.Map; - -import static org.matsim.freight.carriers.events.CarrierEventAttributes.*; - /** * An event, that informs that a Freight {@link CarrierShipment} pickup-activity has ended. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentPickupStartEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentPickupStartEvent.java index ab36e627190..fe851a10138 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentPickupStartEvent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentPickupStartEvent.java @@ -21,6 +21,7 @@ package org.matsim.freight.carriers.events; +import java.util.Map; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.GenericEvent; import org.matsim.api.core.v01.network.Link; @@ -28,8 +29,6 @@ import org.matsim.freight.carriers.CarrierShipment; import org.matsim.vehicles.Vehicle; -import java.util.Map; - /** * An event, that informs that a Freight {@link CarrierShipment} pickup-activity has started. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourEndEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourEndEvent.java index 82e133f2166..1c0e3579312 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourEndEvent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourEndEvent.java @@ -21,6 +21,7 @@ package org.matsim.freight.carriers.events; +import java.util.Map; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.GenericEvent; import org.matsim.api.core.v01.network.Link; @@ -28,8 +29,6 @@ import org.matsim.freight.carriers.Tour; import org.matsim.vehicles.Vehicle; -import java.util.Map; - /** * An event, that informs when a Freight {@link Tour} has ended. * There are NO specific information of the tour given, because the {@link Tour} is determined by the {@link Vehicle} and its {@link Carrier}. diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourStartEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourStartEvent.java index 9c64e8213b2..aa4ff9f1084 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourStartEvent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourStartEvent.java @@ -21,6 +21,9 @@ package org.matsim.freight.carriers.events; +import static org.matsim.freight.carriers.events.CarrierEventAttributes.ATTRIBUTE_TOUR_ID; + +import java.util.Map; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.GenericEvent; import org.matsim.api.core.v01.network.Link; @@ -28,10 +31,6 @@ import org.matsim.freight.carriers.Tour; import org.matsim.vehicles.Vehicle; -import java.util.Map; - -import static org.matsim.freight.carriers.events.CarrierEventAttributes.ATTRIBUTE_TOUR_ID; - /** * An event, that informs when a Freight {@link Tour} has started. * There are NO specific information of the tour given, because the {@link Tour} is determined by the {@link Vehicle} and its {@link Carrier}. diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourStartEventCreator.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourStartEventCreator.java index aacf3e6ef12..fea34b4f577 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourStartEventCreator.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierTourStartEventCreator.java @@ -21,6 +21,7 @@ package org.matsim.freight.carriers.events; +import java.util.TreeMap; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.ActivityEndEvent; import org.matsim.api.core.v01.events.Event; @@ -32,8 +33,6 @@ import org.matsim.freight.carriers.ScheduledTour; import org.matsim.vehicles.Vehicle; -import java.util.TreeMap; - /*package-private*/ final class CarrierTourStartEventCreator implements CarrierEventCreator { final TreeMap, ActivityEndEvent> endEventMap = new TreeMap<>(); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierServiceStartEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierServiceStartEventHandler.java index a8ea55c13e8..362974eae3f 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierServiceStartEventHandler.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierServiceStartEventHandler.java @@ -24,7 +24,6 @@ import org.matsim.core.events.handler.EventHandler; import org.matsim.freight.carriers.events.CarrierServiceStartEvent; - public interface CarrierServiceStartEventHandler extends EventHandler { void handleEvent( CarrierServiceStartEvent event ); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourEndEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourEndEventHandler.java index 2d30ce4d70c..d14a5d285cf 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourEndEventHandler.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourEndEventHandler.java @@ -24,7 +24,6 @@ import org.matsim.core.events.handler.EventHandler; import org.matsim.freight.carriers.events.CarrierTourEndEvent; - public interface CarrierTourEndEventHandler extends EventHandler { void handleEvent( CarrierTourEndEvent event ); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourStartEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourStartEventHandler.java index 5f4b26ce4bb..3a7997cc9ef 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourStartEventHandler.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourStartEventHandler.java @@ -24,7 +24,6 @@ import org.matsim.core.events.handler.EventHandler; import org.matsim.freight.carriers.events.CarrierTourStartEvent; - public interface CarrierTourStartEventHandler extends EventHandler { void handleEvent( CarrierTourStartEvent event ); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/Vehicle2CarrierEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/Vehicle2CarrierEventHandler.java index bc9236decbf..0d5b9902f57 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/Vehicle2CarrierEventHandler.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/Vehicle2CarrierEventHandler.java @@ -20,15 +20,14 @@ */ package org.matsim.freight.carriers.events.eventhandler; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.matsim.api.core.v01.Id; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.events.CarrierTourEndEvent; import org.matsim.freight.carriers.events.CarrierTourStartEvent; import org.matsim.vehicles.Vehicle; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - /** * Basic event handler that collects the relation between vehicles and carrier. * Necessary since link enter and leave events do not contain any information of the carrier. diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/DistanceConstraint.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/DistanceConstraint.java index 068c70506cd..8615e0b3d75 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/DistanceConstraint.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/DistanceConstraint.java @@ -94,7 +94,7 @@ public ConstraintsStatus fulfilled(JobInsertionContext context, TourActivity pre consumptionPerMeter = VehicleUtils .getEnergyConsumptionKWhPerMeter(vehicleTypeOfNewVehicle.getEngineInformation()); else - consumptionPerMeter = VehicleUtils.getFuelConsumption(vehicleTypeOfNewVehicle); + consumptionPerMeter = VehicleUtils.getFuelConsumptionLitersPerMeter(vehicleTypeOfNewVehicle.getEngineInformation()); double routeDistance = calculateRouteDistance(context, newVehicle); double routeConsumption = routeDistance * (consumptionPerMeter); @@ -212,9 +212,9 @@ private double calculateRouteDistance(JobInsertionContext context, Vehicle newVe * directly behind the new pickup. This method gives back the minimal distance * of this three options. * - * @param context - * @param newInvestigatedPickup - * @param nextAct + * @param context the context of the job insertion + * @param newInvestigatedPickup the new pickup which should be added to the tour + * @param nextAct the next activity after the new pickup * @return minimal distance of the associated delivery */ private double findMinimalAdditionalDistance(JobInsertionContext context, TourActivity newInvestigatedPickup, @@ -283,8 +283,8 @@ private double findMinimalAdditionalDistance(JobInsertionContext context, TourAc /** * Checks if the find possible distance is the minimal one. * - * @param minimalAdditionalDistance - * @param possibleAdditionalDistance + * @param minimalAdditionalDistance the minimal additional distance + * @param possibleAdditionalDistance the possible additional distance * @return the minimal transport distance */ private double findMinimalDistance(double minimalAdditionalDistance, double possibleAdditionalDistance) { diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/MatsimJspritFactory.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/MatsimJspritFactory.java index 8710e50c7ba..00cf9347716 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/MatsimJspritFactory.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/MatsimJspritFactory.java @@ -45,6 +45,10 @@ import com.graphhopper.jsprit.io.algorithm.AlgorithmConfig; import com.graphhopper.jsprit.io.algorithm.AlgorithmConfigXmlReader; import com.graphhopper.jsprit.io.algorithm.VehicleRoutingAlgorithms; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Coord; @@ -57,11 +61,6 @@ import org.matsim.vehicles.VehicleType; import org.matsim.vehicles.VehicleUtils; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - /** * A factory that creates matsim-object from jsprit * (...) and vice versa. @@ -686,9 +685,6 @@ public static Carrier createCarrier(String carrierId, VehicleRoutingProblem vrp) capabilityBuilder.setFleetSize(CarrierCapabilities.FleetSize.FINITE); } else capabilityBuilder.setFleetSize(CarrierCapabilities.FleetSize.INFINITE); - for (com.graphhopper.jsprit.core.problem.vehicle.VehicleType type : vrp.getTypes()) { - capabilityBuilder.addType(createMatsimVehicleType(type)); - } for (Vehicle vehicle : vrp.getVehicles()) { capabilityBuilder.addVehicle(createCarrierVehicle(vehicle)); } 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 e6d8e1a0e45..aa18f9d2487 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 @@ -26,6 +26,8 @@ import com.graphhopper.jsprit.core.problem.driver.Driver; import com.graphhopper.jsprit.core.problem.vehicle.Vehicle; import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; @@ -45,9 +47,6 @@ import org.matsim.vehicles.VehicleType; import org.matsim.vehicles.VehicleUtils; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - /** * This calculates transport-times, transport-costs and the distance to cover * the distance from one location to another. It calculates these values based @@ -658,12 +657,12 @@ private VehicleImpl getDefaultVehicle(Location fromId) { private void informEndCalc() { for (InternalLeastCostPathCalculatorListener l : listeners) - l.endCalculation(Thread.currentThread().getId()); + l.endCalculation(Thread.currentThread().threadId()); } private void informStartCalc() { for (InternalLeastCostPathCalculatorListener l : listeners) - l.startCalculation(Thread.currentThread().getId()); + l.startCalculation(Thread.currentThread().threadId()); } /** @@ -853,11 +852,11 @@ public LeastCostPathCalculator getRouter() { } private LeastCostPathCalculator createLeastCostPathCalculator() { - LeastCostPathCalculator router = routerCache.get(Thread.currentThread().getId()); + LeastCostPathCalculator router = routerCache.get(Thread.currentThread().threadId()); if (router == null) { LeastCostPathCalculator newRouter = leastCostPathCalculatorFactory.createPathCalculator(network, travelDisutility, travelTime); - router = routerCache.putIfAbsent(Thread.currentThread().getId(), newRouter); + router = routerCache.putIfAbsent(Thread.currentThread().threadId(), newRouter); if (router == null) { router = newRouter; } diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsFactory.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsFactory.java index 6a0be5414f0..558ec523a81 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsFactory.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsFactory.java @@ -21,19 +21,18 @@ package org.matsim.freight.carriers.jsprit; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.TransportMode; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.router.util.TravelTime; -import org.matsim.freight.carriers.FreightCarriersConfigGroup; import org.matsim.freight.carriers.Carriers; +import org.matsim.freight.carriers.FreightCarriersConfigGroup; import org.matsim.vehicles.VehicleType; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - /** * @author steffenaxer */ diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkRouter.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkRouter.java index 7dac94a1c8c..2388801503b 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkRouter.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkRouter.java @@ -22,7 +22,7 @@ import org.matsim.freight.carriers.CarrierPlan; import org.matsim.freight.carriers.ScheduledTour; -import org.matsim.freight.carriers.controler.CarrierTimeAndSpaceTourRouter; +import org.matsim.freight.carriers.controller.CarrierTimeAndSpaceTourRouter; /** * Router that routes {@link CarrierPlan}. 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 6175780ab9a..7c9541f5777 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 @@ -21,14 +21,12 @@ package org.matsim.freight.carriers.jsprit; import com.graphhopper.jsprit.core.problem.vehicle.VehicleType; +import java.util.*; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.contrib.roadpricing.RoadPricingScheme; import org.matsim.contrib.roadpricing.RoadPricingSchemeImpl.Cost; -import java.util.*; - - /** * Calculator that manages and calculates vehicle type dependent road pricing schemas. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/analysis/CarrierScoreStats.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/analysis/CarrierScoreStats.java index 84556de1a14..ab4fa18632f 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/analysis/CarrierScoreStats.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/analysis/CarrierScoreStats.java @@ -21,6 +21,10 @@ package org.matsim.freight.carriers.usecases.analysis; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.Locale; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.core.controler.events.IterationEndsEvent; @@ -35,11 +39,6 @@ import org.matsim.freight.carriers.CarrierPlan; import org.matsim.freight.carriers.Carriers; -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.util.Locale; - /** * As you can see, it is basically a copy of {@link org.matsim.analysis.ScoreStatsControlerListener}. However, it is modified to score {@link Carrier}s * rather than Persons. (Oct'13, schroeder) diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/analysis/LegHistogram.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/analysis/LegHistogram.java index fff393eee93..1954eff762e 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/analysis/LegHistogram.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/analysis/LegHistogram.java @@ -22,6 +22,14 @@ package org.matsim.freight.carriers.usecases.analysis; import jakarta.inject.Inject; +import java.awt.*; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintStream; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartUtils; import org.jfree.chart.JFreeChart; @@ -42,15 +50,6 @@ import org.matsim.api.core.v01.population.Population; import org.matsim.core.utils.misc.Time; -import java.awt.*; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.PrintStream; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - /** * It is a copy of {@link org.matsim.analysis.LegHistogram}. It is modified to include or exclude persons. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/CarrierScoringFunctionFactoryImpl.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/CarrierScoringFunctionFactoryImpl.java index 759b3da5890..ee2b54c9399 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/CarrierScoringFunctionFactoryImpl.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/CarrierScoringFunctionFactoryImpl.java @@ -22,6 +22,8 @@ package org.matsim.freight.carriers.usecases.chessboard; import com.google.inject.Inject; +import java.util.HashSet; +import java.util.Set; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; @@ -36,14 +38,11 @@ import org.matsim.core.scoring.ScoringFunction; import org.matsim.core.scoring.SumScoringFunction; import org.matsim.freight.carriers.*; -import org.matsim.freight.carriers.controler.CarrierScoringFunctionFactory; -import org.matsim.freight.carriers.controler.FreightActivity; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.controller.FreightActivity; import org.matsim.freight.carriers.jsprit.VehicleTypeDependentRoadPricingCalculator; import org.matsim.vehicles.Vehicle; -import java.util.HashSet; -import java.util.Set; - /** * Defines example carrier scoring function (factory). * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/FreightScenarioCreator.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/FreightScenarioCreator.java index c258d01e703..3d291829b77 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/FreightScenarioCreator.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/FreightScenarioCreator.java @@ -21,6 +21,9 @@ package org.matsim.freight.carriers.usecases.chessboard; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.network.Link; @@ -34,10 +37,6 @@ import org.matsim.vehicles.VehicleType; import org.matsim.vehicles.VehicleUtils; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - /** * Creates chessboard freight scenario. * diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/InitialCarrierPlanCreator.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/InitialCarrierPlanCreator.java index fb2979e4be1..72c6d90df96 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/InitialCarrierPlanCreator.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/InitialCarrierPlanCreator.java @@ -34,6 +34,7 @@ import com.graphhopper.jsprit.io.algorithm.AlgorithmConfig; import com.graphhopper.jsprit.io.algorithm.AlgorithmConfigXmlReader; import com.graphhopper.jsprit.io.algorithm.VehicleRoutingAlgorithms; +import java.util.Collection; import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.network.Network; import org.matsim.core.config.Config; @@ -44,8 +45,6 @@ import org.matsim.freight.carriers.jsprit.NetworkBasedTransportCosts; import org.matsim.freight.carriers.jsprit.NetworkRouter; -import java.util.Collection; - final class InitialCarrierPlanCreator { private final Network network; @@ -166,8 +165,6 @@ public static void main(String[] args) { Carriers carriers = new Carriers(); new CarrierPlanXmlReader(carriers, types ).readFile("input/usecases/chessboard/freight/carrierPlansWithoutRoutes_10minTW.xml" ); - new CarrierVehicleTypeLoader(carriers).loadVehicleTypes(types); - for(Carrier carrier : carriers.getCarriers().values()){ CarrierPlan plan = new InitialCarrierPlanCreator(scenario.getNetwork()).createPlan(carrier); carrier.addPlan(plan); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/InnerOuterCityScenarioCreator.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/InnerOuterCityScenarioCreator.java index d5b48f1df69..789a5681a46 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/InnerOuterCityScenarioCreator.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/InnerOuterCityScenarioCreator.java @@ -21,12 +21,11 @@ package org.matsim.freight.carriers.usecases.chessboard; -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.network.Link; - import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; final class InnerOuterCityScenarioCreator { diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/PassengerScenarioCreator.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/PassengerScenarioCreator.java index 3a742ced5e6..1060931835e 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/PassengerScenarioCreator.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/PassengerScenarioCreator.java @@ -21,6 +21,8 @@ package org.matsim.freight.carriers.usecases.chessboard; +import java.util.ArrayList; +import java.util.List; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.TransportMode; @@ -36,9 +38,6 @@ import org.matsim.core.router.util.LeastCostPathCalculator.Path; import org.matsim.core.scenario.ScenarioUtils; -import java.util.ArrayList; -import java.util.List; - final class PassengerScenarioCreator { static int agentCounter = 1; diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/PlotPlans.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/PlotPlans.java index 838ac5463ae..9e615dda9f4 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/PlotPlans.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/PlotPlans.java @@ -47,8 +47,6 @@ public static void main(String[] args) { // new CarrierPlanXmlReader(carriers).read("input/usecases/chessboard/freight/singleCarrierTwentyActivities.xml"); new CarrierPlanXmlReader(carriers, types ).readFile("output/ITERS/it.140/140.carrierPlans.xml" ); - new CarrierVehicleTypeLoader(carriers).loadVehicleTypes(types); - final Carrier carrier = carriers.getCarriers().get(Id.create("carrier1",Carrier.class)); VehicleRoutingProblem.Builder vrpBuilder = MatsimJspritFactory.createRoutingProblemBuilder(carrier, scenario.getNetwork()); VehicleRoutingProblem vrp = vrpBuilder.build(); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/RunChessboard.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/RunChessboard.java index e8f7887cfea..ff62264a468 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/RunChessboard.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/RunChessboard.java @@ -23,14 +23,13 @@ import com.google.inject.Provider; import jakarta.inject.Inject; +import java.util.Map; import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.network.Network; 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.controler.OutputDirectoryHierarchy; +import org.matsim.core.controler.*; import org.matsim.core.controler.events.IterationEndsEvent; import org.matsim.core.controler.listener.IterationEndsListener; import org.matsim.core.replanning.GenericPlanStrategyImpl; @@ -46,12 +45,10 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.freight.carriers.*; -import org.matsim.freight.carriers.controler.*; +import org.matsim.freight.carriers.controller.*; import org.matsim.freight.carriers.usecases.analysis.CarrierScoreStats; import org.matsim.freight.carriers.usecases.analysis.LegHistogram; -import java.util.Map; - public final class RunChessboard { public static void main(String[] args){ @@ -74,11 +71,11 @@ public static void main(String[] args){ Carriers carriers = CarriersUtils.addOrGetCarriers( scenario ); CarrierVehicleTypes types = CarriersUtils.getCarrierVehicleTypes( scenario ); - Controler controler = new Controler( scenario); + Controller controller = ControllerUtils.createController( scenario ); - controler.addOverridingModule(new CarrierModule() ); + controller.addOverridingModule(new CarrierModule() ); - controler.addOverridingModule(new AbstractModule() { + controller.addOverridingModule(new AbstractModule() { @Override public void install() { @@ -113,7 +110,7 @@ public void install() { } }); - controler.run(); + controller.run(); } @@ -139,7 +136,7 @@ private static class MyCarrierPlanStrategyManagerProvider implements Provider strategy = new GenericPlanStrategyImpl<>( new ExpBetaPlanChanger.Factory().build() ); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/RunPassengerAlongWithCarriers.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/RunPassengerAlongWithCarriers.java index 9d54c7299e1..2561968e1f2 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/RunPassengerAlongWithCarriers.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/RunPassengerAlongWithCarriers.java @@ -23,16 +23,15 @@ import com.google.inject.Provider; import jakarta.inject.Inject; +import java.net.URL; +import java.util.Map; import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.network.Network; import org.matsim.core.api.experimental.events.EventsManager; 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.controler.MatsimServices; -import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.controler.*; import org.matsim.core.controler.listener.IterationEndsListener; import org.matsim.core.gbl.Gbl; import org.matsim.core.replanning.GenericPlanStrategyImpl; @@ -47,13 +46,10 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.freight.carriers.*; -import org.matsim.freight.carriers.controler.*; +import org.matsim.freight.carriers.controller.*; import org.matsim.freight.carriers.usecases.analysis.CarrierScoreStats; import org.matsim.freight.carriers.usecases.analysis.LegHistogram; -import java.net.URL; -import java.util.Map; - final class RunPassengerAlongWithCarriers { final static URL url = ExamplesUtils.getTestScenarioURL("freight-chessboard-9x9"); @@ -67,7 +63,7 @@ public void run() { Scenario scenario = prepareScenario(config); - Controler controler = new Controler(scenario); + Controller controller = ControllerUtils.createController(scenario); CarrierVehicleTypes types = new CarrierVehicleTypes(); new CarrierVehicleTypeReader(types).readURL( IOUtils.extendUrl(url, "vehicleTypes.xml" ) ); @@ -75,9 +71,9 @@ public void run() { final Carriers carriers = new Carriers(); new CarrierPlanXmlReader(carriers, types ).readURL( IOUtils.extendUrl(url, "carrierPlans.xml" ) ); - controler.addOverridingModule( new CarrierModule() ); + controller.addOverridingModule( new CarrierModule() ); - controler.addOverridingModule( new AbstractModule(){ + controller.addOverridingModule( new AbstractModule(){ @Override public void install(){ this.bind( CarrierStrategyManager.class ).toProvider( new MyCarrierPlanStrategyManagerFactory(types) ); this.bind( CarrierScoringFunctionFactory.class ).toInstance(carrier -> { @@ -91,15 +87,16 @@ public void run() { } ); - prepareFreightOutputDataAndStats(scenario, controler.getEvents(), controler, carriers); + prepareFreightOutputDataAndStats(scenario, controller.getEvents(), controller, carriers); - controler.run(); + controller.run(); } public Config prepareConfig() { Config config = ConfigUtils.loadConfig(IOUtils.extendUrl(url, "config.xml")); config.controller().setOverwriteFileSetting( OutputDirectoryHierarchy.OverwriteFileSetting.overwriteExistingFiles ); + config.controller().setLastIteration(5); config.global().setRandomSeed(4177); config.controller().setOutputDirectory("./output/"); return config; @@ -153,7 +150,7 @@ public MyCarrierPlanStrategyManagerFactory(CarrierVehicleTypes types) { final TravelDisutility travelDisutility = CarrierTravelDisutilities.createBaseDisutility(types, modeTravelTimes.get(TransportMode.car ) ); final LeastCostPathCalculator router = leastCostPathCalculatorFactory.createPathCalculator(network, travelDisutility, modeTravelTimes.get(TransportMode.car)); - final CarrierStrategyManager carrierStrategyManager = CarrierControlerUtils.createDefaultCarrierStrategyManager(); + final CarrierStrategyManager carrierStrategyManager = CarrierControllerUtils.createDefaultCarrierStrategyManager(); carrierStrategyManager.setMaxPlansPerAgent(5); carrierStrategyManager.addStrategy(new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 0.95); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/SelectBestPlanAndOptimizeItsVehicleRouteFactory.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/SelectBestPlanAndOptimizeItsVehicleRouteFactory.java index 0051af3de81..a043c85d958 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/SelectBestPlanAndOptimizeItsVehicleRouteFactory.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/usecases/chessboard/SelectBestPlanAndOptimizeItsVehicleRouteFactory.java @@ -30,6 +30,8 @@ import com.graphhopper.jsprit.core.problem.vehicle.Vehicle; import com.graphhopper.jsprit.core.util.Solutions; import com.graphhopper.jsprit.io.algorithm.VehicleRoutingAlgorithms; +import java.net.URL; +import java.util.Collection; import org.matsim.api.core.v01.network.Network; import org.matsim.core.replanning.GenericPlanStrategy; import org.matsim.core.replanning.GenericPlanStrategyImpl; @@ -46,9 +48,6 @@ import org.matsim.freight.carriers.jsprit.NetworkBasedTransportCosts; import org.matsim.freight.carriers.jsprit.NetworkRouter; -import java.net.URL; -import java.util.Collection; - final class SelectBestPlanAndOptimizeItsVehicleRouteFactory { final URL url = ExamplesUtils.getTestScenarioURL("freight-chessboard-9x9"); diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/ForwardLogisticChainSchedulerImpl.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/ForwardLogisticChainSchedulerImpl.java new file mode 100644 index 00000000000..71d76c307ce --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/ForwardLogisticChainSchedulerImpl.java @@ -0,0 +1,189 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import java.util.ArrayList; +import org.matsim.api.core.v01.Id; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * .... Macht 3 Schritte: 1.) the LSPShipments are handed over to the first {@link + * LogisticChainElement} of their {@link LogisticChain} 2.) the neighbors, i.e. the predecessors and + * successors of all {@link LSPResource}s are determined 3.) the Resources are brought into the + * right sequence according to the algorithm. + * + *

When traversing this list of {@link LSPResource}s, the operations in each {@link LSPResource} + * are scheduled individually by calling their {@link LSPResourceScheduler}. + */ +/* package-private */ class ForwardLogisticChainSchedulerImpl implements LogisticChainScheduler { + + /** + * The Resources are brought into the right sequence according to the algorithm. The result of + * this algorithm is a list of Resources that is later traversed from the front to the back, i.e. + * starting with the entry at index 0. In the algorithm, this list is called sortedResourceList. + */ + private final ArrayList sortedResourceList; + + /** + * The determination of the neighborhood structure among the Resources resulted in the + * neighborList. + */ + private final ArrayList neighbourList; + + private LSP lsp; + private int bufferTime; + + ForwardLogisticChainSchedulerImpl() { + this.sortedResourceList = new ArrayList<>(); + this.neighbourList = new ArrayList<>(); + } + + @Override + public void scheduleLogisticChain() { + insertShipmentsAtBeginning(); + setResourceNeighbours(); + sortResources(); + for (LSPResource resource : sortedResourceList) { + resource.schedule(bufferTime, lsp.getSelectedPlan()); + } + } + + @Override + public void setEmbeddingContainer(LSP lsp) { + this.lsp = lsp; + } + + private void setResourceNeighbours() { + // internal data structure, try to ignore when looking from outside. kai/kai, jan'22 + neighbourList.clear(); + for (LSPResource resource : lsp.getResources()) { + ResourceNeighbours neighbours = new ResourceNeighbours(resource); + for (LogisticChainElement element : resource.getClientElements()) { + LogisticChainElement predecessor = element.getPreviousElement(); + LSPResource previousResource = predecessor.getResource(); + neighbours.addPredecessor(previousResource); + LogisticChainElement successor = element.getNextElement(); + LSPResource nextResource = successor.getResource(); + neighbours.addSuccessor(nextResource); + } + neighbourList.add(neighbours); + } + } + + private void sortResources() { + sortedResourceList.clear(); + while (!neighbourList.isEmpty()) { + for (ResourceNeighbours neighbours : neighbourList) { + if (allPredecessorsAlreadyScheduled(neighbours) + && noSuccessorAlreadyScheduled(neighbours)) { + sortedResourceList.add(neighbours.resource); + neighbourList.remove(neighbours); + } + } + } + } + + private boolean allPredecessorsAlreadyScheduled(ResourceNeighbours neighbours) { + if (neighbours.predecessors.isEmpty()) { + return true; + } + + for (LSPResource predecessor : neighbours.predecessors) { + if (!sortedResourceList.contains(predecessor)) { + return true; + } + } + return false; + } + + private boolean noSuccessorAlreadyScheduled(ResourceNeighbours neighbours) { + if (neighbours.successors.isEmpty()) { + return true; + } + + for (LSPResource successor : neighbours.successors) { + if (!sortedResourceList.contains(successor)) { + return true; + } + } + return false; + } + + private void insertShipmentsAtBeginning() { + for (LogisticChain solution : lsp.getSelectedPlan().getLogisticChains()) { + LogisticChainElement firstElement = getFirstElement(solution); + assert firstElement != null; + for (Id lspShipmentId : solution.getLspShipmentIds()) { + var shipment = LSPUtils.findLspShipment(lsp, lspShipmentId); + assert shipment != null; + firstElement + .getIncomingShipments() + .addShipment(shipment.getPickupTimeWindow().getStart(), shipment); + } + } + } + + private LogisticChainElement getFirstElement(LogisticChain solution) { + for (LogisticChainElement element : solution.getLogisticChainElements()) { + if (element.getPreviousElement() == null) { + return element; + } + } + return null; + } + + @Override + public void setBufferTime(int bufferTime) { + this.bufferTime = bufferTime; + } + + /** + * The relationship between different {@link LSPResource}s allows to handle various supply + * structures that the {@link LSP} might decide to maintain. Thus, a {@link LSPResource} can have + * several successors or predecessors or can be used by several different {@link LogisticChain}s. + * The neighborhood structure among the {@link LSPResource}s is stored in instances of the class + * {@link ResourceNeighbours} which contain references on the considered {@link LSPResource} and + * on the set of immediate successors respective predecessors. As the result of this step, a + * collection of {@link ResourceNeighbours} called neighborList is created that contains the + * neighbors of all {@link LSPResource}s in the plan of the considered {@link LSP}. + */ + private static class ResourceNeighbours { + // internal data structure, try to ignore when looking from outside. kai/kai, jan'22 + + private final ArrayList predecessors; + private final ArrayList successors; + private final LSPResource resource; + + private ResourceNeighbours(LSPResource resource) { + this.resource = resource; + this.predecessors = new ArrayList<>(); + this.successors = new ArrayList<>(); + } + + private void addPredecessor(LSPResource resource) { + this.predecessors.add(resource); + } + + private void addSuccessor(LSPResource resource) { + this.successors.add(resource); + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/FreightLogisticsConfigGroup.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/FreightLogisticsConfigGroup.java new file mode 100644 index 00000000000..bab230379ba --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/FreightLogisticsConfigGroup.java @@ -0,0 +1,142 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics; + +import java.net.URL; +import java.util.Map; +import org.matsim.core.config.ConfigGroup; +import org.matsim.core.config.ReflectiveConfigGroup; + +public class FreightLogisticsConfigGroup extends ReflectiveConfigGroup { + + public static final String GROUPNAME="freightLogistics" ; + + private String lspsFile; + static final String LSPS_FILE = "lspsFile"; + private static final String LSPS_FILE_DESC = "Freight LogisticsServiceProviders (LSP)s File, according to MATSim logistics extension as part of MATSim's freight contrib."; + + public FreightLogisticsConfigGroup() { + super(GROUPNAME); + } + + //### CarriersFile ### + /** + * @return -- {@value #LSPS_FILE_DESC} + */ + @StringGetter(LSPS_FILE) + public String getLspsFile() { + return lspsFile; + } + + URL getLspsFileUrl(URL context) { + return ConfigGroup.getInputFileURL(context, this.lspsFile); + } + + /** + * @param -- {@value #LSPS_FILE_DESC} + */ + @StringSetter(LSPS_FILE) + public void setLspsFile(String lspsFile) { + this.lspsFile = lspsFile; + } + + + + //--- + // Commenting this out, because in a frist step I think it is better/ more streight forward to have the VRP logic in the carriers as an attribute. + // please see {@link CarrierSchedulerUtils#setVrpLogic(carrier, VRPLogic)} and {@link CarrierSchedulerUtils#getVrpLogic(carrier)} + //--- + +// static final String VRP_LOGIC_OF_DISTRIBUTION_CARRIER = "vrpLogicOfDistributionCarrier"; +// private LSPUtils.LogicOfVrp vrpLogicOfDistributionCarrier = LSPUtils.LogicOfVrp.serviceBased; +// private static final String VRP_LOGIC_OF_DISTRIBUTION_CARRIER_DESC = "Define, on which type of jobs the VRP of the **distribution** carrier will base on:" + Arrays.toString(LSPUtils.LogicOfVrp.values()); +// +// static final String VRP_LOGIC_OF_MAINRUN_CARRIER = "vrpLogicOfMainRunCarrier"; +// private LSPUtils.LogicOfVrp vrpLogicOfMainRunCarrier = LSPUtils.LogicOfVrp.serviceBased; +// private static final String VRP_LOGIC_OF_MAINRUN_CARRIER_DESC = "Define, on which type of jobs the VRP of the **MainRun** carrier will base on:" + Arrays.toString(LSPUtils.LogicOfVrp.values()); +// +// static final String VRP_LOGIC_OF_COLLECTION_CARRIER = "vrpLogicOfCollectionCarrier"; +// private LSPUtils.LogicOfVrp vrpLogicOfCollectionCarrier = LSPUtils.LogicOfVrp.serviceBased; +// private static final String VRP_LOGIC_OF_COLLECTION_CARRIER_DESC = "Define, on which type of jobs the VRP of the **Collection** carrier will base on:" + Arrays.toString(LSPUtils.LogicOfVrp.values()); +// +// /** +// * +// * @return The internal type of jobs, on which the VRPs of the distribution carrier bases on. +// */ +// @StringGetter(VRP_LOGIC_OF_DISTRIBUTION_CARRIER) +// public LSPUtils.LogicOfVrp getVrpLogicOfDistributionCarrier() { +// return vrpLogicOfDistributionCarrier; +// } +// +// /** +// * @param vrpLogicOfDistributionCarrier {@value #VRP_LOGIC_OF_DISTRIBUTION_CARRIER} +// */ +// @StringSetter(VRP_LOGIC_OF_DISTRIBUTION_CARRIER) +// public void setVrpLogicOfDistributionCarrier(LSPUtils.LogicOfVrp vrpLogicOfDistributionCarrier) { +// this.vrpLogicOfDistributionCarrier = vrpLogicOfDistributionCarrier; +// } +// +// /** +// * @return The internal type of jobs, on which the VRPs of the main run carrier bases on. +// */ +// @StringGetter(FreightLogisticsConfigGroup.VRP_LOGIC_OF_MAINRUN_CARRIER) +// public LSPUtils.LogicOfVrp getVrpLogicOfMainRunCarrier() { +// return vrpLogicOfMainRunCarrier; +// } +// +// /** +// * @param vrpLogicOfMainRunCarrier {@value #VRP_LOGIC_OF_MAINRUN_CARRIER} +// */ +// @StringSetter(FreightLogisticsConfigGroup.VRP_LOGIC_OF_MAINRUN_CARRIER) +// public void setVrpLogicOfMainRunCarrier(LSPUtils.LogicOfVrp vrpLogicOfMainRunCarrier) { +// this.vrpLogicOfMainRunCarrier = vrpLogicOfMainRunCarrier; +// } +// +// /** +// * @return The internal type of jobs, on which the VRPs of the collection carrier bases on. +// */ +// @StringGetter(FreightLogisticsConfigGroup.VRP_LOGIC_OF_COLLECTION_CARRIER) +// public LSPUtils.LogicOfVrp getVrpLogicOfCollectionCarrier() { +// return vrpLogicOfCollectionCarrier; +// } +// +// /** +// * @param vrpLogicOfCollectionCarrier {@value #VRP_LOGIC_OF_COLLECTION_CARRIER} +// */ +// @StringSetter(FreightLogisticsConfigGroup.VRP_LOGIC_OF_COLLECTION_CARRIER) +// public void setVrpLogicOfCollectionCarrier(LSPUtils.LogicOfVrp vrpLogicOfCollectionCarrier) { +// this.vrpLogicOfCollectionCarrier = vrpLogicOfCollectionCarrier; +// } + + //--- + //--- + @Override + public Map getComments() { + Map map = super.getComments(); + map.put(LSPS_FILE, LSPS_FILE_DESC); +// map.put(VRP_LOGIC_OF_DISTRIBUTION_CARRIER, VRP_LOGIC_OF_DISTRIBUTION_CARRIER_DESC); +// map.put(VRP_LOGIC_OF_MAINRUN_CARRIER, VRP_LOGIC_OF_MAINRUN_CARRIER_DESC); +// map.put(VRP_LOGIC_OF_COLLECTION_CARRIER, VRP_LOGIC_OF_COLLECTION_CARRIER_DESC); + return map; + } + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/HasBackpointer.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/HasBackpointer.java new file mode 100644 index 00000000000..73f97386951 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/HasBackpointer.java @@ -0,0 +1,12 @@ +package org.matsim.freight.logistics; + +@SuppressWarnings("InterfaceMayBeAnnotatedFunctional") +public interface HasBackpointer { + // In general, we set backpointers when we add to the container. + + // yy maybe also have interface HasSettableBackpointer? + void setEmbeddingContainer(T pointer); + + // T getEmbeddingContainer(); + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/HasLspShipmentId.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/HasLspShipmentId.java new file mode 100644 index 00000000000..e3ddd1fc2f5 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/HasLspShipmentId.java @@ -0,0 +1,32 @@ +/* *********************************************************************** * + * project: org.matsim.* * + * * + * *********************************************************************** * + * * + * copyright : (C) 2008 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.freight.logistics; + +import org.matsim.api.core.v01.Id; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * @author Kai Martins-Turner (kturner) + */ +public interface HasLspShipmentId { + + String ATTRIBUTE_LSP_SHIPMENT_ID = "lspShipmentId"; + + Id getLspShipmentId(); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/HasSimulationTrackers.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/HasSimulationTrackers.java new file mode 100644 index 00000000000..33ba50074ed --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/HasSimulationTrackers.java @@ -0,0 +1,14 @@ +package org.matsim.freight.logistics; + +import java.util.Collection; + +// One could say that the simulation trackers are the decorators that convert the data objects into +// behavioral objects. In core matsim, we instead +// create behavioral objects, which contain the data objects. E.g. MobsimAgent, DriverAgent, +// CarrierAgent, etc. kai, may'22 +public interface HasSimulationTrackers { + + void addSimulationTracker(LSPSimulationTracker tracker); + + Collection> getSimulationTrackers(); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/InitialShipmentAssigner.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/InitialShipmentAssigner.java new file mode 100644 index 00000000000..eb6ff6287e7 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/InitialShipmentAssigner.java @@ -0,0 +1,43 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * Takes an {@link LspShipment} and normally assigns it to something that belongs to an {@link LSP}. + *
+ * After changes in fall 2023 (see master thesis of nrichter), the assingment is + * there to be done one time initially. + *
+ * If there are several {@link LogisticChain}s in a {@link LSPPlan}, the {@link LSP} has to assign each {@link + * LspShipment} to the suitable {@link LogisticChain}. For this purpose, each {@link LSPPlan} + * (or only the LSP? - kmt'jan'24), contains a pluggable strategy + * that is contained in classes implementing the interface {@link InitialShipmentAssigner}.
+ *
+ * During iterations, it can happen that the {@link LspShipment} should be moved to another + * {@link LogisticChain} of the same {@link LSPPlan}. This is now (since fall 2023; see master + * thesis of nrichter) part of the (innovative) **Replanning** strategies. + */ +public interface InitialShipmentAssigner { + + void assignToPlan(LSPPlan lspPlan, LspShipment lspShipment); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/KnowsLSP.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/KnowsLSP.java new file mode 100644 index 00000000000..60a9c8ea190 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/KnowsLSP.java @@ -0,0 +1,7 @@ +package org.matsim.freight.logistics; + +interface KnowsLSP { + LSP getLSP(); + + void setLSP(LSP lsp); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSP.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSP.java new file mode 100644 index 00000000000..0486cd0f958 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSP.java @@ -0,0 +1,53 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import java.util.Collection; +import org.matsim.api.core.v01.population.HasPlansAndId; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * In the class library, the interface LSP has the following tasks: 1. Maintain one or several + * transport chains through which {@link LspShipment}s are routed. 2. Assign {@link LspShipment}s to + * the suitable transport chain. --> {@link InitialShipmentAssigner}. 3. Interact with the agents that + * embody the demand side of the freight transport market, if they are specified in the setting. 4. + * Coordinate carriers that are in charge of the physical transport. + */ +public interface LSP extends HasPlansAndId, HasSimulationTrackers { + + /** yyyy does this have to be exposed? */ + Collection getLspShipments(); + + /** ok (behavioral method) */ + void scheduleLogisticChains(); + + /** yyyy does this have to be exposed? */ + Collection getResources(); + + /** ok (behavioral method) */ + void scoreSelectedPlan(); + + /** + * @param lspShipment ok (LSP needs to be told that it is responsible for lspShipment) + */ + void assignShipmentToLSP(LspShipment lspShipment); + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPCarrierResource.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPCarrierResource.java new file mode 100644 index 00000000000..1a26be79a61 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPCarrierResource.java @@ -0,0 +1,28 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import org.matsim.freight.carriers.Carrier; + +public interface LSPCarrierResource extends LSPResource { + + Carrier getCarrier(); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPConstants.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPConstants.java new file mode 100644 index 00000000000..44df1603232 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPConstants.java @@ -0,0 +1,29 @@ +package org.matsim.freight.logistics; + +import org.matsim.freight.carriers.CarrierConstants; + +public abstract class LSPConstants extends CarrierConstants { + + public static final String CAPACITY_NEED_FIXED = "capacityNeedFixed"; + public static final String CAPACITY_NEED_LINEAR = "capacityNeedLinear"; + public static final String CHAIN_ID = "chainId"; + public static final String ELEMENT = "element"; + public static final String END_TIME = "endTime"; + public static final String FIXED_COST = "fixedCost"; + public static final String HUB = "hub"; + public static final String LOCATION = "location"; + public static final String LOGISTIC_CHAIN = "logisticChain"; + public static final String LOGISTIC_CHAINS = "logisticChains"; + public static final String LOGISTIC_CHAIN_ELEMENT = "logisticChainElement"; + public static final String LSP = "lsp"; + public static final String LSPS = "lsps"; + public static final String LSP_PLAN = "LspPlan"; + public static final String LSP_PLANS = "LspPlans"; + public static final String RESOURCES = "resources"; + public static final String RESOURCE_ID = "resourceId"; + public static final String SCHEDULER = "scheduler"; + public static final String SHIPMENT_PLAN = "shipmentPlan"; + public static final String SHIPMENT_PLANS = "shipmentPlans"; + public static final String START_TIME = "startTime"; + public static final String TYPE = "type"; +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPControllerListener.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPControllerListener.java new file mode 100644 index 00000000000..0da2e144cbc --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPControllerListener.java @@ -0,0 +1,253 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import jakarta.inject.Inject; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.annotation.Nullable; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Scenario; +import org.matsim.core.api.experimental.events.EventsManager; +import org.matsim.core.controler.MatsimServices; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.controler.events.*; +import org.matsim.core.controler.listener.*; +import org.matsim.core.events.handler.EventHandler; +import org.matsim.core.gbl.Gbl; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.CarrierPlanWriter; +import org.matsim.freight.carriers.Carriers; +import org.matsim.freight.carriers.CarriersUtils; +import org.matsim.freight.carriers.controller.CarrierAgentTracker; +import org.matsim.freight.logistics.io.LSPPlanXmlWriter; +import org.matsim.freight.logistics.shipment.LspShipment; + +class LSPControllerListener + implements StartupListener, + BeforeMobsimListener, + AfterMobsimListener, + ScoringListener, + ReplanningListener, + IterationStartsListener, + IterationEndsListener, + ShutdownListener { + private static final Logger log = LogManager.getLogger(LSPControllerListener.class); + private final Scenario scenario; + private final List registeredHandlers = new ArrayList<>(); + + private static int addListenerCnt = 0; + private static final int maxAddListenerCnt = 1; + + @Inject private EventsManager eventsManager; + @Inject private MatsimServices matsimServices; + @Inject private LSPScorerFactory lspScoringFunctionFactory; + @Inject @Nullable private LSPStrategyManager strategyManager; + @Inject private OutputDirectoryHierarchy controlerIO; + @Inject private CarrierAgentTracker carrierAgentTracker; + + + @Inject + LSPControllerListener(Scenario scenario) { + this.scenario = scenario; + } + + @Override + public void notifyStartup(StartupEvent event) { + //Ensure that all ressource Ids are only there once. + + checkForUniqueResourceIds(); + + } + +/** +* For later steps, e.g. scoring the Ids of the {@link LSPResource} ids must be unique. + * Otherwise, there are scored several times. + *

+ * For the future we may reduce it to unique {@link LSPResource} ids PER {@link LSP}. + * This means, that the events (also from the carriers) need to have an information obout the LSP it belongs to and that + * in scoring and analysis this must be taken into account. What itself is another source for errors... + * KMT jul'24 +*/ + private void checkForUniqueResourceIds() { + List duplicates = new ArrayList<>(); + Set set = new HashSet<>(); + + LSPs lsps = LSPUtils.getLSPs(scenario); + for (LSP lsp : lsps.getLSPs().values()) { + for (LSPResource lspResource : lsp.getResources()) { + String idString = lspResource.getId().toString(); + if (set.contains(idString)) { + duplicates.add(idString); + } else { + set.add(idString); + } + } + } + + if (!duplicates.isEmpty()) { + log.error("There are non-unique ressource Ids. This must not be! The duplicate ids are: {}.", duplicates.toString()); + log.error("You may also use output_lsp.xml to check were the duplicates are located"); + log.error("Aborting now ..."); + throw new RuntimeException(); + } + } + + @Override + public void notifyBeforeMobsim(BeforeMobsimEvent event) { + LSPs lsps = LSPUtils.getLSPs(scenario); + + // TODO: Why do we add all simTrackers in every iteration beforeMobsim starts? + // Doing so results in a lot of "not adding eventsHandler since already added" warnings. + // @KN: Would it be possible to do it in (simulation) startup and therefor only oce? + for (LSP lsp : lsps.getLSPs().values()) { + ((LSPImpl) lsp).setScorer(lspScoringFunctionFactory.createScoringFunction()); + + // simulation trackers of lsp: + registerSimulationTrackers(lsp); + + // simulation trackers of resources: + for (LSPResource resource : lsp.getResources()) { + registerSimulationTrackers(resource); + } + + // simulation trackers of shipments: + for (LspShipment lspShipment : lsp.getLspShipments()) { + registerSimulationTrackers(lspShipment); + } + + // simulation trackers of solutions: + for (LogisticChain solution : lsp.getSelectedPlan().getLogisticChains()) { + registerSimulationTrackers(solution); + + // simulation trackers of solution elements: + for (LogisticChainElement element : solution.getLogisticChainElements()) { + registerSimulationTrackers(element); + + // simulation trackers of resources: + registerSimulationTrackers(element.getResource()); + } + } + } + } + + private void registerSimulationTrackers(HasSimulationTrackers hasSimulationTrackers) { + // get all simulation trackers ... + for (LSPSimulationTracker simulationTracker : + hasSimulationTrackers.getSimulationTrackers()) { + // ... register them ... + if (!registeredHandlers.contains(simulationTracker)) { + log.info("adding eventsHandler: {}", simulationTracker); + eventsManager.addHandler(simulationTracker); + registeredHandlers.add(simulationTracker); + matsimServices.addControlerListener(simulationTracker); + simulationTracker.setEventsManager(eventsManager); + } else if ( addListenerCnt < maxAddListenerCnt ){ + log.warn("not adding eventsHandler since already added: {}", simulationTracker); + addListenerCnt++; + if (addListenerCnt == maxAddListenerCnt) { + log.warn(Gbl.FUTURE_SUPPRESSED); + } + } + } + + } + + @Override + public void notifyReplanning(ReplanningEvent event) { + if (strategyManager == null) { + throw new RuntimeException( + "You need to set LSPStrategyManager to something meaningful to run iterations."); + } + + LSPs lsps = LSPUtils.getLSPs(scenario); + strategyManager.run( + lsps.getLSPs().values(), event.getIteration(), event.getReplanningContext()); + + for (LSP lsp : lsps.getLSPs().values()) { + lsp.getSelectedPlan() + .getShipmentPlans() + .clear(); // clear ShipmentPlans to start with clear(n) state. Otherwise, some of the times were + // accumulating over the time. :( + lsp.scheduleLogisticChains(); + } + + // Update carriers in scenario and CarrierAgentTracker + carrierAgentTracker.getCarriers().getCarriers().clear(); + for (Carrier carrier : getCarriersFromLSP().getCarriers().values()) { + CarriersUtils.getCarriers(scenario).addCarrier(carrier); + carrierAgentTracker.getCarriers().addCarrier(carrier); + } + } + + @Override + public void notifyScoring(ScoringEvent scoringEvent) { + for (LSP lsp : LSPUtils.getLSPs(scenario).getLSPs().values()) { + lsp.scoreSelectedPlan(); + } + // yyyyyy might make more sense to register the lsps directly as scoring controler listener (??) + } + + @Override + public void notifyAfterMobsim(AfterMobsimEvent event) {} + + Carriers getCarriersFromLSP() { + LSPs lsps = LSPUtils.getLSPs(scenario); + assert !lsps.getLSPs().isEmpty(); + + Carriers carriers = new Carriers(); + for (LSP lsp : lsps.getLSPs().values()) { + LSPPlan selectedPlan = lsp.getSelectedPlan(); + for (LogisticChain solution : selectedPlan.getLogisticChains()) { + for (LogisticChainElement element : solution.getLogisticChainElements()) { + if (element.getResource() instanceof LSPCarrierResource carrierResource) { + Carrier carrier = carrierResource.getCarrier(); + if (!carriers.getCarriers().containsKey(carrier.getId())) { + carriers.addCarrier(carrier); + } + } + } + } + } + return carriers; + } + + @Override + public void notifyIterationStarts(IterationStartsEvent event) {} + + @Override + public void notifyIterationEnds(IterationEndsEvent event) { + new LSPPlanXmlWriter(LSPUtils.getLSPs(scenario)) + .write(controlerIO.getIterationFilename(event.getIteration(), "lsps.xml")); + } + + @Override + public void notifyShutdown(ShutdownEvent event) { + new LSPPlanXmlWriter(LSPUtils.getLSPs(scenario)) + .write(controlerIO.getOutputPath() + "/output_lsps.xml.gz"); + new CarrierPlanWriter(CarriersUtils.getCarriers(scenario)) + .write(controlerIO.getOutputPath() + "/output_carriers.xml.gz"); + } + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPDataObject.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPDataObject.java new file mode 100644 index 00000000000..ff150a79d88 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPDataObject.java @@ -0,0 +1,45 @@ +package org.matsim.freight.logistics; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Identifiable; +import org.matsim.utils.objectattributes.attributable.Attributable; +import org.matsim.utils.objectattributes.attributable.Attributes; +import org.matsim.utils.objectattributes.attributable.AttributesImpl; + +public class LSPDataObject implements HasSimulationTrackers, Attributable, Identifiable { + + private final Collection> trackers = new LinkedList<>(); + private final Attributes attributes = new AttributesImpl(); + private final Id id; + + public LSPDataObject(Id id) { + this.id = id; + } + + @Override + public final void addSimulationTracker(LSPSimulationTracker tracker) { + this.trackers.add(tracker); + tracker.setEmbeddingContainer((T) this); + // It may not be possible to do this without this cast. Since "this" only knows that it is at + // least an LSPDataObject, and only we + // know that it is truly of type T. kai, jun'22 + } + + @Override + public final Collection> getSimulationTrackers() { + return Collections.unmodifiableCollection(this.trackers); + } + + @Override + public final Attributes getAttributes() { + return attributes; + } + + @Override + public final Id getId() { + return id; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPImpl.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPImpl.java new file mode 100644 index 00000000000..d25cbfb043a --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPImpl.java @@ -0,0 +1,163 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.freight.logistics.shipment.LspShipment; + +/* package-private */ class LSPImpl extends LSPDataObject implements LSP { + private static final Logger log = LogManager.getLogger(LSPImpl.class); + + private final Collection lspShipments; + private final ArrayList lspPlans; + private final LogisticChainScheduler logisticChainScheduler; + private final Collection resources; + private LSPPlan selectedPlan; + private LSPScorer scorer; + + // private LSPReplanner replanner; + + LSPImpl(LSPUtils.LSPBuilder builder) { + super(builder.id); + this.lspShipments = new ArrayList<>(); + this.lspPlans = new ArrayList<>(); + this.logisticChainScheduler = builder.logisticChainScheduler; + this.logisticChainScheduler.setEmbeddingContainer(this); + this.selectedPlan = builder.initialPlan; + this.selectedPlan.setLSP(this); + this.lspPlans.add(builder.initialPlan); + this.resources = builder.resources; + } + + public static LSPPlan copyPlan(LSPPlan plan2copy) { + List newPlanChains = new ArrayList<>(); + for (LogisticChain initialPlanChain : plan2copy.getLogisticChains()) { + LogisticChain newPlanChain = + LSPUtils.LogisticChainBuilder.newInstance(initialPlanChain.getId()).build(); + newPlanChain.getLogisticChainElements().addAll(initialPlanChain.getLogisticChainElements()); + newPlanChain.getLspShipmentIds().addAll(initialPlanChain.getLspShipmentIds()); + newPlanChains.add(newPlanChain); + } + + LSPPlan copiedPlan = LSPUtils.createLSPPlan(); + copiedPlan.setInitialShipmentAssigner(plan2copy.getInitialShipmentAssigner()); + copiedPlan.setLSP(plan2copy.getLSP()); + copiedPlan.setScore(plan2copy.getScore()); + copiedPlan.setType(plan2copy.getType()); + copiedPlan.getLogisticChains().addAll(newPlanChains); + return copiedPlan; + } + + /** + * This is used from {@link LSPControllerListener} and not meant to be used from user code. Users + * should bind {@link LSPScorerFactory}. + */ + /* package-private */ void setScorer(LSPScorer scorer) { + this.scorer = scorer; + scorer.setEmbeddingContainer(this); + this.addSimulationTracker(scorer); + } + + @Override + public void scheduleLogisticChains() { + logisticChainScheduler.scheduleLogisticChain(); + } + + @Override + public boolean addPlan(LSPPlan plan) { + for (LogisticChain solution : plan.getLogisticChains()) { + for (LogisticChainElement element : solution.getLogisticChainElements()) { + if (!resources.contains(element.getResource())) { + resources.add(element.getResource()); + } + } + } + plan.setLSP(this); + return lspPlans.add(plan); + } + + @Override + public LSPPlan createCopyOfSelectedPlanAndMakeSelected() { + LSPPlan newPlan = LSPImpl.copyPlan(this.selectedPlan); + this.setSelectedPlan(newPlan); + return newPlan; + } + + @Override + public ArrayList getPlans() { + return lspPlans; + } + + @Override + public LSPPlan getSelectedPlan() { + return selectedPlan; + } + + @Override + public void setSelectedPlan(LSPPlan selectedPlan) { + if (!lspPlans.contains(selectedPlan)) { + lspPlans.add(selectedPlan); + } + this.selectedPlan = selectedPlan; + } + + @Override + public boolean removePlan(LSPPlan lspPlan) { + if (lspPlans.contains(lspPlan)) { + lspPlans.remove(lspPlan); + return true; + } else { + return false; + } + } + + @Override + public Collection getResources() { + return resources; + } + + public void scoreSelectedPlan() { + if (this.scorer != null) { + this.selectedPlan.setScore(scorer.getScoreForCurrentPlan()); + } else { + throw new RuntimeException("trying to score the current LSP plan, but scorer is not set."); + } + } + + @Override + public void assignShipmentToLSP(LspShipment lspShipment) { + // shipment.setLspId(this.getId()); // und rückweg dann auch darüber und dann + // lsp.getselectedPlan.getShipment... + lspShipments.add(lspShipment); + for (LSPPlan lspPlan : lspPlans) { + lspPlan.getInitialShipmentAssigner().assignToPlan(lspPlan, lspShipment); + } + } + + @Override + public Collection getLspShipments() { + return this.lspShipments; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPModule.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPModule.java new file mode 100644 index 00000000000..520aead053b --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPModule.java @@ -0,0 +1,184 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import jakarta.inject.Inject; +import jakarta.inject.Singleton; +import java.util.List; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.population.HasPlansAndId; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.events.BeforeMobsimEvent; +import org.matsim.core.controler.listener.BeforeMobsimListener; +import org.matsim.core.mobsim.qsim.AbstractQSimModule; +import org.matsim.core.mobsim.qsim.components.QSimComponentsConfigGroup; +import org.matsim.core.replanning.GenericPlanStrategy; +import org.matsim.core.replanning.ReplanningContext; +import org.matsim.core.replanning.selectors.PlanSelector; +import org.matsim.freight.carriers.FreightCarriersConfigGroup; +import org.matsim.freight.carriers.controller.*; +import org.matsim.freight.logistics.analysis.LspScoreStatsModule; + +public class LSPModule extends AbstractModule { + private static final Logger log = LogManager.getLogger(LSPModule.class); + + @Override + public void install() { + FreightCarriersConfigGroup freightConfig = + ConfigUtils.addOrGetModule(getConfig(), FreightCarriersConfigGroup.class); + + bind(LSPControllerListener.class).in(Singleton.class); + addControlerListenerBinding().to(LSPControllerListener.class); + + install(new CarrierModule()); + install(new LspScoreStatsModule()); + + // this switches on certain qsim components: + QSimComponentsConfigGroup qsimComponents = + ConfigUtils.addOrGetModule(getConfig(), QSimComponentsConfigGroup.class); + List abc = qsimComponents.getActiveComponents(); + abc.add(FreightAgentSource.COMPONENT_NAME); + switch (freightConfig.getTimeWindowHandling()) { + case ignore: + break; + case enforceBeginnings: + //// abc.add( WithinDayActivityReScheduling.COMPONENT_NAME ); + log.warn( + "LSP has never hedged against time window openings; this is probably wrong; but I don't know what to do ..."); + // break; + default: + throw new IllegalStateException( + "Unexpected value: " + freightConfig.getTimeWindowHandling()); + } + qsimComponents.setActiveComponents(abc); + + // this installs qsim components, which are switched on (or not) via the above syntax: + this.installQSimModule( + new AbstractQSimModule() { + @Override + protected void configureQSim() { + this.bind(FreightAgentSource.class).in(Singleton.class); + this.addQSimComponentBinding(FreightAgentSource.COMPONENT_NAME) + .to(FreightAgentSource.class); + switch (freightConfig.getTimeWindowHandling()) { + case ignore: + break; + case enforceBeginnings: + //// + // this.addQSimComponentBinding(WithinDayActivityReScheduling.COMPONENT_NAME).to( + // WithinDayActivityReScheduling.class ); + log.warn( + "LSP has never hedged against time window openings; this is probably wrong; but I don't know what to do ..."); + // break; + default: + throw new IllegalStateException( + "Unexpected value: " + freightConfig.getTimeWindowHandling()); + } + } + }); + + // the scorers are necessary to run a zeroth iteration to the end: + bind(LSPScorerFactory.class).to(LSPScoringFunctionFactoryDummyImpl.class); + + // for iterations, one needs to replace the following with something meaningful. If nothing + // else, there are "empty implementations" that do nothing. kai, jul'22 + bind(LSPStrategyManager.class).toProvider(() -> null); + + this.addControlerListenerBinding().to(DumpLSPPlans.class); + } + + private static class LSPScoringFunctionFactoryDummyImpl implements LSPScorerFactory { + @Override + public LSPScorer createScoringFunction() { + return new LSPScorer() { + @Override + public double getScoreForCurrentPlan() { + return Double.NEGATIVE_INFINITY; + } + + @Override + public void setEmbeddingContainer(LSP pointer) {} + }; + } + } + + public static final class LSPStrategyManagerEmptyImpl implements LSPStrategyManager { + + @Override + public void addStrategy( + GenericPlanStrategy strategy, String subpopulation, double weight) { + throw new RuntimeException("not implemented"); + } + + @Override + public void run( + Iterable> persons, + int iteration, + ReplanningContext replanningContext) { + log.warn("Running iterations without a strategy may lead to unclear results."); // "run" is + // possible, but will not do anything. kai, jul'22 + } + + @Override + public void setMaxPlansPerAgent(int maxPlansPerAgent) { + throw new RuntimeException("not implemented"); + } + + @Override + public void addChangeRequest(int iteration, GenericPlanStrategy strategy, String subpopulation, double newWeight) { + throw new RuntimeException("not implemented"); + } + + @Override + public void setPlanSelectorForRemoval(PlanSelector planSelector) { + throw new RuntimeException("not implemented"); + } + + @Override + public List> getStrategies(String subpopulation) { + throw new RuntimeException("not implemented"); + } + + @Override + public List getWeights(String subpopulation) { + throw new RuntimeException("not implemented"); + } + } + + public static final class DumpLSPPlans implements BeforeMobsimListener { + @Inject Scenario scenario; + + @Override + public void notifyBeforeMobsim(BeforeMobsimEvent event) { + LSPs lsps = LSPUtils.getLSPs(scenario); + for (LSP lsp : lsps.getLSPs().values()) { + log.info("Dumping plan(s) of [LSP={}] ; [No of plans={}]", lsp.getId(), lsp.getPlans().size()); + for (LSPPlan plan : lsp.getPlans()) { + log.info("[LSPPlan: {}]", plan.toString()); + } + log.info("Plan(s) of [LSP={}] dumped.", lsp.getId()); + } + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPPlan.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPPlan.java new file mode 100644 index 00000000000..c6c3d48d4f2 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPPlan.java @@ -0,0 +1,59 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import java.util.Collection; +import org.matsim.api.core.v01.population.BasicPlan; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlan; + +/** + * This interface has the following properties: + * + *
    + *
  • As a {@link BasicPlan} it has a score, so it can be used for evolutionary learning. kai, + * may'22 + *
  • An {@link LspShipment} is added via lspPlan#getAssigner().assignToSolution(shipment). The + * {@link InitialShipmentAssigner} assigns it deterministically to a {@link LogisticChain}. + *
+ */ +public interface LSPPlan extends BasicPlan, KnowsLSP { + + LSPPlan addLogisticChain(LogisticChain solution); + + Collection getLogisticChains(); + + /** + * yy My intuition would be to replace lspPlan#getAssigner().assignToSolution( shipment ) by + * lspPlan.addShipment( shipment ). kai, may'22 + */ + InitialShipmentAssigner getInitialShipmentAssigner(); + + LSPPlan setInitialShipmentAssigner(InitialShipmentAssigner assigner); + + Collection getShipmentPlans(); + + LSPPlan addShipmentPlan(LspShipmentPlan lspShipmentPlan); + + String getType(); + + void setType(final String type); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPPlanImpl.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPPlanImpl.java new file mode 100644 index 00000000000..a1bfe4e25cc --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPPlanImpl.java @@ -0,0 +1,127 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import java.util.ArrayList; +import java.util.Collection; +import org.matsim.freight.logistics.shipment.LspShipmentPlan; + +public class LSPPlanImpl implements LSPPlan { + + private final Collection logisticChains; + private final Collection lspShipmentPlans; + private LSP lsp; + private Double score = null; + private InitialShipmentAssigner assigner; + private String type = null; + + public LSPPlanImpl() { + this.logisticChains = new ArrayList<>(); + this.lspShipmentPlans = new ArrayList<>(); + } + + @Override + public LSPPlan addLogisticChain(LogisticChain solution) { + this.logisticChains.add(solution); + solution.setLSP(this.lsp); + return this; + } + + @Override + public Collection getLogisticChains() { + return logisticChains; + } + + @Override + public InitialShipmentAssigner getInitialShipmentAssigner() { + return assigner; + } + + @Override + public LSPPlan setInitialShipmentAssigner(InitialShipmentAssigner assigner) { + this.assigner = assigner; + return this; + } + + @Override + public Collection getShipmentPlans() { + return this.lspShipmentPlans; + } + + @Override + public LSPPlan addShipmentPlan(LspShipmentPlan lspShipmentPlan) { + this.lspShipmentPlans.add(lspShipmentPlan); + return null; + } + + @Override + public Double getScore() { + return score; + } + + @Override + public void setScore(Double score) { + this.score = score; + } + + @Override + public String getType() { + return this.type; + } + + @Override + public void setType(final String type) { + this.type = type; + } + + @Override + public LSP getLSP() { + return lsp; + } + + @Override + public void setLSP(LSP lsp) { + this.lsp = lsp; + for (LogisticChain solution : logisticChains) { + solution.setLSP(lsp); + } + } + + @Override + public String toString() { + StringBuilder strb = new StringBuilder(); + strb.append("[score=").append(this.score).append("]"); + strb.append(", [type=").append(this.type).append("]"); + for (LogisticChain logisticChain : this.logisticChains) { + strb.append(", [LogisticChainId=") + .append(logisticChain.getId()) + .append("], [No of LogisticChainElements=") + .append(logisticChain.getLogisticChainElements().size()) + .append("] \n"); + if (!logisticChain.getLogisticChainElements().isEmpty()) { + for (LogisticChainElement solutionElement : logisticChain.getLogisticChainElements()) { + strb.append("\t \t").append(solutionElement.toString()).append("\n"); + } + } + } + return strb.toString(); + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPResource.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPResource.java new file mode 100644 index 00000000000..4f1e595ebe0 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPResource.java @@ -0,0 +1,40 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import java.util.Collection; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Identifiable; +import org.matsim.api.core.v01.network.Link; +import org.matsim.utils.objectattributes.attributable.Attributable; + +/** */ +public interface LSPResource + extends Identifiable, HasSimulationTrackers, Attributable { + + Id getStartLinkId(); + + Id getEndLinkId(); + + Collection getClientElements(); + + void schedule(int bufferTime, LSPPlan lspPlan); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPResourceScheduler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPResourceScheduler.java new file mode 100644 index 00000000000..c63d9258742 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPResourceScheduler.java @@ -0,0 +1,106 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import java.util.ArrayList; +import java.util.Comparator; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; + +/** + * Resources are scheduled separately by calling their individual scheduling algorithm. + * + *

Within this algorithm, some methods are abstract, whereas others have a default implementation + * for forward scheduling. The former ones are specified in a suitable way by the corresponding + * Resource whereas the latter are only specified in the abstract parent class in order to + * coordinate the way in which the LSPShipments are handed over between subsequent Resources. The + * abstract methods deal with aspects that are specific to the Resource which contains the + * implementation of the ResourceScheduler. + * + *

Forwarding of LSPShipments is done by the two methods presortIncomingShipments() and + * switchHandledShipments(int bufferTime). + */ +public abstract class LSPResourceScheduler { + + protected LSPResource resource; + protected ArrayList lspShipmentsToSchedule; + + protected LSPPlan lspPlan; + + public final void scheduleShipments(LSPPlan lspPlan, LSPResource resource, int bufferTime) { + this.lspPlan = lspPlan; + this.resource = resource; + this.lspShipmentsToSchedule = new ArrayList<>(); + initializeValues(resource); + presortIncomingShipments(); + scheduleResource(); + updateShipments(); + switchHandledShipments(bufferTime); + lspShipmentsToSchedule.clear(); + } + + /** + * Is in charge of the initialization of the actual scheduling process for the concerned Resource. + * Depending on the concrete shape of this process, there are mainly values to be deleted that are + * still stored from the previous iteration or the infrastructure for the used algorithm has to be + * set up. + * + * @param resource The LSPRessource + */ + protected abstract void initializeValues(LSPResource resource); + + /** Controls the actual scheduling process that depends on the shape and task of the Resource. */ + protected abstract void scheduleResource(); + + /** + * Endows the involved {@link LspShipment}s with information that resulted from the scheduling in + * a narrow sense in scheduleResource(). The information can be divided into two main components. + * 1.) the schedule of the {@link LspShipment}s is updated if necessary 2.) the information for a + * later logging of the is added. + */ + protected abstract void updateShipments(); + + private void presortIncomingShipments() { + this.lspShipmentsToSchedule = new ArrayList<>(); + for (LogisticChainElement element : resource.getClientElements()) { + lspShipmentsToSchedule.addAll(element.getIncomingShipments().getLspShipmentsWTime()); + } + lspShipmentsToSchedule.sort(Comparator.comparingDouble(LspShipmentUtils::getTimeOfLspShipment)); + } + + private void switchHandledShipments(int bufferTime) { + for (LspShipment lspShipmentWithTime : lspShipmentsToSchedule) { + var shipmentPlan = LspShipmentUtils.getOrCreateShipmentPlan(lspPlan, lspShipmentWithTime.getId()); + double endOfTransportTime = shipmentPlan.getMostRecentEntry().getEndTime() + bufferTime; + LspShipmentUtils.setTimeOfLspShipment(lspShipmentWithTime, endOfTransportTime); + for (LogisticChainElement element : resource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipmentWithTime)) { + element.getIncomingShipments().getLspShipmentsWTime().remove(lspShipmentWithTime); + element.getOutgoingShipments().getLspShipmentsWTime().add(lspShipmentWithTime); + if (element.getNextElement() != null) { + element.getNextElement().getIncomingShipments().getLspShipmentsWTime().add(lspShipmentWithTime); + element.getOutgoingShipments().getLspShipmentsWTime().remove(lspShipmentWithTime); + } + } + } + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPScorer.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPScorer.java new file mode 100644 index 00000000000..4f4916c0510 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPScorer.java @@ -0,0 +1,43 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import org.matsim.api.core.v01.population.Activity; +import org.matsim.core.controler.listener.ControlerListener; +import org.matsim.core.events.handler.EventHandler; +import org.matsim.core.scoring.ScoringFunction; +import org.matsim.freight.carriers.Carrier; + +/** + * This is somewhat similar to the MATSim core {@link ScoringFunction}, which is also used for + * {@link Carrier}s. A difference, however, is that it does not implement the separate methods + * {@link ScoringFunction#handleActivity(Activity)} etc., but is just an {@link EventHandler} and a + * {@link ControlerListener}. (This is, in some sense, the old design for {@link ScoringFunction}, + * and one, where I am still not sure if the new design is truly better.) In any case, here there is + * not a question: LSP scoring is not so much about activities and legs, since those are handled + * through the carrier scoring, and need to be pulled in by the lsp scoring if the company is + * vertically integrated (i.e. if the LSP owns its carriers). + * + *

also @see {@link LSPScorerFactory} + */ +public interface LSPScorer extends LSPSimulationTracker { + double getScoreForCurrentPlan(); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPScorerFactory.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPScorerFactory.java new file mode 100644 index 00000000000..e5a5d7ea78f --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPScorerFactory.java @@ -0,0 +1,7 @@ +package org.matsim.freight.logistics; + +import org.matsim.core.api.internal.MatsimFactory; + +public interface LSPScorerFactory extends MatsimFactory { + LSPScorer createScoringFunction(); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPSimulationTracker.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPSimulationTracker.java new file mode 100644 index 00000000000..55d967c293b --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPSimulationTracker.java @@ -0,0 +1,32 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import org.matsim.core.api.experimental.events.EventsManager; +import org.matsim.core.controler.listener.ControlerListener; +import org.matsim.core.events.handler.EventHandler; + +public interface LSPSimulationTracker + extends ControlerListener, EventHandler, HasBackpointer { + // In general, we set backpointers when we add to the container. So specifically, we set the + // backpointer to which the tracker points when the tracker is added. + default void setEventsManager(EventsManager eventsManager) {} +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPStrategyManager.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPStrategyManager.java new file mode 100644 index 00000000000..79d7c5a64bc --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPStrategyManager.java @@ -0,0 +1,44 @@ +/* + * *********************************************************************** * + * project: org.matsim.* + * *********************************************************************** * + * * + * copyright : (C) 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.freight.logistics; + +import jakarta.inject.Provider; +import org.matsim.core.replanning.GenericStrategyManager; + +/** + * The current (jul'22) logic of this is: + * + *

    + *
  • There is a null binding of this interface in {@link LSPModule}. If one wants to use + * strategies, this needs to be overwritten. + *
  • Normally, the strategy manager is fixed infrastructure, and should just be configured. + * However, since it is not yet there before injection, it also cannot be configured before + * injection. Core matsim solves that by writing the corresponding configuration into the + * config. We could, in principle, do the same here. Don't want to do this yet. + *
  • So way to configure this "in code" is to bind {@link LSPStrategyManager} to a {@link + * Provider } and then configure it in the provider. + *
+ */ +public interface LSPStrategyManager extends GenericStrategyManager { + // (this is mostly there so that it can be guice-bound. kai, jul'22) + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPStrategyManagerImpl.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPStrategyManagerImpl.java new file mode 100644 index 00000000000..f628d4f2ab4 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPStrategyManagerImpl.java @@ -0,0 +1,71 @@ +package org.matsim.freight.logistics; + +import java.util.List; +import org.matsim.api.core.v01.population.HasPlansAndId; +import org.matsim.core.replanning.GenericPlanStrategy; +import org.matsim.core.replanning.GenericStrategyManager; +import org.matsim.core.replanning.GenericStrategyManagerImpl; +import org.matsim.core.replanning.ReplanningContext; +import org.matsim.core.replanning.selectors.PlanSelector; + +/** + * Normally, this would be infrastructure that is configurable via the config. Since we ain't there + * yet, the way to configure this is something like: + * + *
+ *         bind( LSPStrategyManager.class ).to( new Provider() {
+ *                 public LSPStrategyManager.get() {
+ *                         LSPStrategyManager manager = new LSPStrategyManagerImpl();
+ *                         manager.addStrategy(...)
+ *                         ...
+ *                         return manager;
+ *                 }
+ *         }
+ * 
+ */ +public class LSPStrategyManagerImpl implements LSPStrategyManager { + final GenericStrategyManager delegate = new GenericStrategyManagerImpl<>(); + + @Override + public void addStrategy( + GenericPlanStrategy strategy, String subpopulation, double weight) { + delegate.addStrategy(strategy, subpopulation, weight); + } + + @Override + public void run( + Iterable> persons, + int iteration, + ReplanningContext replanningContext) { + delegate.run(persons, iteration, replanningContext); + } + + @Override + public void setMaxPlansPerAgent(int maxPlansPerAgent) { + delegate.setMaxPlansPerAgent(maxPlansPerAgent); + } + + @Override + public void addChangeRequest( + int iteration, + GenericPlanStrategy strategy, + String subpopulation, + double newWeight) { + delegate.addChangeRequest(iteration, strategy, subpopulation, newWeight); + } + + @Override + public void setPlanSelectorForRemoval(PlanSelector planSelector) { + delegate.setPlanSelectorForRemoval(planSelector); + } + + @Override + public List> getStrategies(String subpopulation) { + return delegate.getStrategies(subpopulation); + } + + @Override + public List getWeights(String subpopulation) { + return delegate.getWeights(subpopulation); + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPUtils.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPUtils.java new file mode 100644 index 00000000000..e40c44e95b6 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPUtils.java @@ -0,0 +1,271 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import java.util.ArrayList; +import java.util.Collection; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.freight.carriers.Carriers; +import org.matsim.freight.carriers.CarriersUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlan; +import org.matsim.utils.objectattributes.attributable.Attributable; + +public final class LSPUtils { + private static final String lspsString = "lsps"; + + private LSPUtils() {} // do not instantiate + + public static LSPPlan createLSPPlan() { + return new LSPPlanImpl(); + } + + + /** + * Checks, is the plan the selcted plan. + * (This is adapted copy from PersonUtils.isSelected(plan) ) + * @param lspPlan the plan to check + * @return true if the plan is the selected plan. false, if not. + */ + public static boolean isPlanTheSelectedPlan(LSPPlan lspPlan) { + return lspPlan.getLSP().getSelectedPlan() == lspPlan; + } + + public static LogisticChainScheduler createForwardLogisiticChainScheduler() { + return new ForwardLogisticChainSchedulerImpl(); + } + + public static WaitingShipments createWaitingShipments() { + return new WaitingShipmentsImpl(); + } + + public static void addLSPs(Scenario scenario, LSPs lsps) { + Carriers carriers = CarriersUtils.addOrGetCarriers(scenario); + // Register carriers from all lsps + for (LSP lsp : lsps.getLSPs().values()) { + for (LSPResource lspResource : lsp.getResources()) { + if (lspResource instanceof LSPCarrierResource lspCarrierResource) { + carriers.addCarrier(lspCarrierResource.getCarrier()); + } + } + } + scenario.addScenarioElement(lspsString, lsps); + } + + public static LSPs getLSPs(Scenario scenario) { + Object result = scenario.getScenarioElement(lspsString); + if (result == null) { + throw new RuntimeException( + "there is no scenario element of type " + + lspsString + + ". You will need something like LSPUtils.addLSPs( scenario, lsps) somewhere."); + } + return (LSPs) result; + } + + public static Double getVariableCost(Attributable attributable) { + return (Double) attributable.getAttributes().getAttribute("variableCost"); + } + + public static void setVariableCost(Attributable attributable, Double variableCost) { + attributable.getAttributes().putAttribute("variableCost", variableCost); + } + + public static Double getFixedCost(Attributable attributable) { + return (Double) attributable.getAttributes().getAttribute("fixedCost"); + } + + // The following would be closer to how we have done it elsewhere (scenario containers are + // mutable). kai, may'22' + // public static LSPs createOrGetLPSs( Scenario scenario ){ + // Object result = scenario.getScenarioElement( lspsString ); + // LSPs lsps; + // if ( result != null ) { + // lsps = (LSPs) result; + // } else { + // lsps = new LSPs( ); + // scenario.addScenarioElement( lspsString, lsps ); + // } + // return lsps; + // } + + public static void setFixedCost(Attributable attributable, Double fixedCost) { + attributable.getAttributes().putAttribute("fixedCost", fixedCost); + } + + /** + * Gives back the {@link LspShipment} object of the {@link LSP}, which matches to the shipmentId + * + * @param lsp In this LSP this method tries to find the shipment. + * @param shipmentId Id of the shipment that should be found. + * @return the lspShipment object or null, if it is not found. + */ + public static LspShipment findLspShipment(LSP lsp, Id shipmentId) { + for (LspShipment lspShipment : lsp.getLspShipments()) { + if (lspShipment.getId().equals(shipmentId)) { + return lspShipment; + } + } + return null; + } + + /** + * Returns the {@link LspShipmentPlan} of an {@link LspShipment}. + * + * @param lspPlan the lspPlan: It contains the information of its shipmentPlans + * @param shipmentId Id of the shipment that should be found. + * @return the shipmentPlan object or null, if it is not found. + */ + public static LspShipmentPlan findLspShipmentPlan(LSPPlan lspPlan, Id shipmentId) { + for (LspShipmentPlan lspShipmentPlan : lspPlan.getShipmentPlans()) { + if (lspShipmentPlan.getLspShipmentId().equals(shipmentId)) { + return lspShipmentPlan; + } + } + return null; + } + + public enum LogicOfVrp {serviceBased, shipmentBased} + + public static final class LSPBuilder { + final Collection resources; + final Id id; + LogisticChainScheduler logisticChainScheduler; + LSPPlan initialPlan; + + private LSPBuilder(Id id) { + this.id = id; // this line was not there until today. kai, may'22 + this.resources = new ArrayList<>(); + } + + public static LSPBuilder getInstance(Id id) { + return new LSPBuilder(id); + } + + public LSPBuilder setLogisticChainScheduler(LogisticChainScheduler logisticChainScheduler) { + this.logisticChainScheduler = logisticChainScheduler; + return this; + } + + // /** + // * @deprecated -- It feels attractive to attach this to the "agent". A big disadvantage + // with this approach, however, is that + // * we cannot use injection ... since we cannot inject as many scorers as we have agents. + // (At least this is what I think.) Which means + // * that the approach in matsim core and in carriers to have XxxScoringFunctionFactory is + // better for what we are doing here. yyyyyy So + // * this needs to be changed. kai, jul'22 + // */ + // public LSPBuilder setSolutionScorer(LSPScorer scorer) { + // this.scorer = scorer; + // return this; + // } + + // /** + // * @deprecated -- It feels attractive to attach this to the "agent". A big disadvantage + // with this approach, however, is that + // * we cannot use injection ... since we cannot inject as many replanners as we have + // agents. (At least this is what I think.) yyyyyy So + // * this needs to be changed. kai, jul'22 + // */ + // public LSPBuilder setReplanner(LSPReplanner replanner) { + // this.replanner = replanner; + // return this; + // } + // never used. Thus disabling it. kai, jul'22 + + public LSPBuilder setInitialPlan(LSPPlan plan) { + this.initialPlan = plan; + for (LogisticChain solution : plan.getLogisticChains()) { + for (LogisticChainElement element : solution.getLogisticChainElements()) { + if (!resources.contains(element.getResource())) { + resources.add(element.getResource()); + } + } + } + return this; + } + + public LSP build() { + return new LSPImpl(this); + } + } + + public static final class LogisticChainBuilder { + final Id id; + final Collection elements; + // final Collection eventHandlers; + final Collection> trackers; + + private LogisticChainBuilder(Id id) { + this.elements = new ArrayList<>(); + this.trackers = new ArrayList<>(); + this.id = id; + } + + public static LogisticChainBuilder newInstance(Id id) { + return new LogisticChainBuilder(id); + } + + public LogisticChainBuilder addLogisticChainElement(LogisticChainElement element) { + elements.add(element); + return this; + } + + public LogisticChainBuilder addTracker(LSPSimulationTracker tracker) { + trackers.add(tracker); + return this; + } + + public LogisticChain build() { + //TODO: Prüfe of das alle Elemente Verbunden sind (in irgendeiner Art). Plus Hinweis auf die Änderung. + + return new LogisticChainImpl(this); + } + } + + public static final class LogisticChainElementBuilder { + final Id id; + final WaitingShipments incomingShipments; + final WaitingShipments outgoingShipments; + LSPResource resource; + + private LogisticChainElementBuilder(Id id) { + this.id = id; + this.incomingShipments = createWaitingShipments(); + this.outgoingShipments = createWaitingShipments(); + } + + public static LogisticChainElementBuilder newInstance(Id id) { + return new LogisticChainElementBuilder(id); + } + + public LogisticChainElementBuilder setResource(LSPResource resource) { + this.resource = resource; + return this; + } + + public LogisticChainElement build() { + return new LogisticChainElementImpl(this); + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPs.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPs.java new file mode 100644 index 00000000000..7adfc6d430e --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LSPs.java @@ -0,0 +1,45 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; +import org.matsim.api.core.v01.Id; + +public class LSPs { + + private final Map, LSP> lsps = new LinkedHashMap<>(); + + public LSPs(Collection lsps) { + makeMap(lsps); + } + + private void makeMap(Collection lsps) { + for (LSP c : lsps) { + this.lsps.put(c.getId(), c); + } + } + + public Map, LSP> getLSPs() { + return lsps; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LogisticChain.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LogisticChain.java new file mode 100644 index 00000000000..f1b19be6c8f --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LogisticChain.java @@ -0,0 +1,48 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import java.util.Collection; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Identifiable; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.utils.objectattributes.attributable.Attributable; + +/** + * A LogisticsSolution can be seen as a representative of a transport chain. It consists of several + * chain links that implement the interface {@link LogisticChainElement}. The latter is more a + * logical than a physical entity. Physical entities, in turn, are housed inside classes that + * implement the interface {@link LSPResource}. This introduction of an intermediate layer allows + * physical Resources to be used by several {@link LogisticChain}s and thus transport chains. + */ +@SuppressWarnings("GrazieInspection") +public interface LogisticChain + extends Identifiable, + KnowsLSP, + HasSimulationTrackers, + Attributable { + + Collection getLogisticChainElements(); + + Collection> getLspShipmentIds(); + + void addShipmentToChain(LspShipment lspShipment); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LogisticChainElement.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LogisticChainElement.java new file mode 100644 index 00000000000..67a16b43462 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LogisticChainElement.java @@ -0,0 +1,55 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import org.matsim.api.core.v01.Identifiable; +import org.matsim.utils.objectattributes.attributable.Attributable; + +public interface LogisticChainElement + extends Identifiable, + HasBackpointer, + HasSimulationTrackers, + Attributable { + + void connectWithNextElement(LogisticChainElement element); + + /** + * The logistics solution element wraps around a resource. Don't know why we need this wrapping. + * + * @return the resource + */ + LSPResource getResource(); + + LogisticChainElement getPreviousElement(); + + LogisticChainElement getNextElement(); + + /** + * This collection stores LSPShipments that are waiting for their treatment in this element or + * more precisely the Resource that is in charge of the actual physical handling. + * + * @return WaitingShipments + */ + WaitingShipments getIncomingShipments(); + + /** Shipments that have already been treated. */ + WaitingShipments getOutgoingShipments(); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LogisticChainElementImpl.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LogisticChainElementImpl.java new file mode 100644 index 00000000000..757c7714e5b --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LogisticChainElementImpl.java @@ -0,0 +1,103 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +/* package-private */ class LogisticChainElementImpl extends LSPDataObject + implements LogisticChainElement { + + private final LSPResource resource; + private final WaitingShipments incomingShipments; + private final WaitingShipments outgoingShipments; + // die beiden nicht im Builder. Die können erst in der Solution als ganzes gesetzt werden + private LogisticChainElement previousElement; + private LogisticChainElement nextElement; + + LogisticChainElementImpl(LSPUtils.LogisticChainElementBuilder builder) { + super(builder.id); + this.resource = builder.resource; + this.incomingShipments = builder.incomingShipments; + this.outgoingShipments = builder.outgoingShipments; + resource.getClientElements().add(this); + } + + @Override + public void connectWithNextElement(LogisticChainElement element) { + this.nextElement = element; + ((LogisticChainElementImpl) element).previousElement = this; + } + + @Override + public LSPResource getResource() { + return resource; + } + + @Override + public WaitingShipments getIncomingShipments() { + return incomingShipments; + } + + @Override + public WaitingShipments getOutgoingShipments() { + return outgoingShipments; + } + + @Override + public void setEmbeddingContainer(LogisticChain logisticChain) { + /* not */ + } + + @Override + public LogisticChainElement getPreviousElement() { + return previousElement; + } + + @Override + public LogisticChainElement getNextElement() { + return nextElement; + } + + @Override + public String toString() { + StringBuilder strb = new StringBuilder(); + strb.append("LogisticsSolutionElementImpl{") + .append("resourceId=") + .append(resource.getId()) + .append(", incomingShipments=") + .append(incomingShipments) + .append(", outgoingShipments=") + .append(outgoingShipments); + + if (previousElement != null) { + strb.append(", previousElementId=").append(previousElement.getId()); + } else { + strb.append(", previousElementId=").append("null"); + } + + if (nextElement != null) { + strb.append(", nextElementId=").append(nextElement.getId()); + } else { + strb.append(", nextElementId=").append("null"); + } + + strb.append('}'); + return strb.toString(); + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LogisticChainImpl.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LogisticChainImpl.java new file mode 100644 index 00000000000..a8d50917504 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LogisticChainImpl.java @@ -0,0 +1,97 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import java.util.ArrayList; +import java.util.Collection; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Id; +import org.matsim.freight.logistics.shipment.LspShipment; + +/* package-private */ class LogisticChainImpl extends LSPDataObject + implements LogisticChain { + private static final Logger log = LogManager.getLogger(LogisticChainImpl.class); + + private final Collection logisticChainElements; + private final Collection> lspShipmentIds; + private LSP lsp; + + LogisticChainImpl(LSPUtils.LogisticChainBuilder builder) { + super(builder.id); + this.logisticChainElements = builder.elements; + for (LogisticChainElement element : this.logisticChainElements) { + element.setEmbeddingContainer(this); + } + this.lspShipmentIds = new ArrayList<>(); + } + + @Override + public LSP getLSP() { + return lsp; + } + + @Override + public void setLSP(LSP lsp) { + this.lsp = lsp; + } + + @Override + public Collection getLogisticChainElements() { + return logisticChainElements; + } + + @Override + public Collection> getLspShipmentIds() { + return lspShipmentIds; + } + + @Override + public void addShipmentToChain(LspShipment lspShipment) { + lspShipmentIds.add(lspShipment.getId()); + } + + @Override + public String toString() { + StringBuilder strb = new StringBuilder(); + strb.append("LogisticsSolutionImpl{") + .append("[No of SolutionsElements=") + .append(logisticChainElements.size()) + .append("] \n"); + if (!logisticChainElements.isEmpty()) { + strb.append("{SolutionElements="); + for (LogisticChainElement solutionElement : logisticChainElements) { + strb.append("\n [").append(solutionElement.toString()).append("]"); + } + strb.append("}"); + } + strb.append("[No of Shipments=").append(lspShipmentIds.size()).append("] \n"); + if (!lspShipmentIds.isEmpty()) { + strb.append("{ShipmentIds="); + for (Id lspShipmentId : lspShipmentIds) { + strb.append("[").append(lspShipmentId.toString()).append("]"); + } + strb.append("}"); + } + strb.append('}'); + return strb.toString(); + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/LogisticChainScheduler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/LogisticChainScheduler.java new file mode 100644 index 00000000000..e950405e979 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/LogisticChainScheduler.java @@ -0,0 +1,47 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * Serve the purpose of routing a set of {@link LspShipment}s + * through a set of {@link LogisticChain}s, which, in turn, consist of several {@link + * LogisticChainElement}s and the corresponding {@link LSPResource}s. + */ +public interface LogisticChainScheduler extends HasBackpointer { + + void scheduleLogisticChain(); + + /** + * The buffer time is only taken into account in planning / scheduling. The idea is to + * ensure that the goods are available for the next ressource "in time", because the scheduling + * does not take into account any congestion during the simulation. E.g. if multiple vehicle are + * leaving the depot at the same time and thus influence each other.
+ * It is not intended to be available as buffer in the simulation itself -> It does not + * influence the events and shipmentLogs. As a consequence, the transportation (in simulation, + * events, ...) is in many cases earlier than scheduled. (Information from TM after asking; KMT + * 17.11.23) + * + * @param bufferTime for scheduling [in sec] + */ + void setBufferTime(int bufferTime); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/WaitingShipments.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/WaitingShipments.java new file mode 100644 index 00000000000..55e72fa3e5d --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/WaitingShipments.java @@ -0,0 +1,51 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import java.util.Collection; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * Each LogisticsSolutionElement maintains two collections of WaitingShipments. Instances of the + * latter class contain tuples of LSPShipments and time stamps. + * + *

The first of these collections stores LSPShipments that are waiting for their treatment in + * this element or more precisely the Resource that is in charge of the actual physical handling. + * + *

The second one stores shipments that have already been treated. + * + *

At the beginning of the scheduling process, all LSPShipments are added to the collection of + * incoming shipments of the first LogisticsSolutionElement of the LogisticsSolution to which they + * were assigned before. The tuples in the collection of WaitingShipments thus consist of the + * shipments themselves and a time stamp that states when they arrived there (see 3.9). In the case + * of the first LogisticsSolutionElement, this time stamp corresponds to the start time window of + * the LSPShipment + */ +public interface WaitingShipments { + + void addShipment(double time, LspShipment lspShipment); + + Collection getSortedLspShipments(); + + Collection getLspShipmentsWTime(); + + void clear(); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/WaitingShipmentsImpl.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/WaitingShipmentsImpl.java new file mode 100644 index 00000000000..6404d32a802 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/WaitingShipmentsImpl.java @@ -0,0 +1,73 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; + +/* package-private */ class WaitingShipmentsImpl implements WaitingShipments { + + private final List shipments; + + WaitingShipmentsImpl() { + this.shipments = new ArrayList<>(); + } + + @Override + public void addShipment(double time, LspShipment lspShipment) { + LspShipmentUtils.setTimeOfLspShipment(lspShipment, time); + this.shipments.add(lspShipment); + shipments.sort(Comparator.comparingDouble(LspShipmentUtils::getTimeOfLspShipment)); + } + + @Override + public Collection getSortedLspShipments() { + shipments.sort(Comparator.comparingDouble(LspShipmentUtils::getTimeOfLspShipment)); + return shipments; + } + + public void clear() { + shipments.clear(); + } + + @Override + public Collection getLspShipmentsWTime() { + return shipments; + } + + @Override + public String toString() { + StringBuilder strb = new StringBuilder(); + strb.append("WaitingShipmentsImpl{").append("No of Shipments= ").append(shipments.size()); + if (!shipments.isEmpty()) { + strb.append("; ShipmentIds="); + for (LspShipment shipment : getSortedLspShipments()) { + strb.append("[").append(shipment.getId()).append("]"); + } + } + strb.append('}'); + return strb.toString(); + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/analysis/Driver2VehicleEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/analysis/Driver2VehicleEventHandler.java new file mode 100644 index 00000000000..906541a3e41 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/analysis/Driver2VehicleEventHandler.java @@ -0,0 +1,71 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.analysis; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.events.VehicleEntersTrafficEvent; +import org.matsim.api.core.v01.events.VehicleLeavesTrafficEvent; +import org.matsim.api.core.v01.events.handler.VehicleEntersTrafficEventHandler; +import org.matsim.api.core.v01.events.handler.VehicleLeavesTrafficEventHandler; +import org.matsim.api.core.v01.population.Person; +import org.matsim.vehicles.Vehicle; + +/** + * Basic event handler that collects the relation between vehicles and drivers. + * Necessary since link enter and leave events do not contain the driver anymore. + *

+ * This is the vice-versa implementation of {@link org.matsim.core.events.algorithms.Vehicle2DriverEventHandler}. + *

+ * In a first step only used internally. When needed more often, I have nothing against putting it more central. -> matsim-libs + * + * @author kturner + */ +public class Driver2VehicleEventHandler implements VehicleEntersTrafficEventHandler, VehicleLeavesTrafficEventHandler { + + private final Map, Id> driversVehicles = new ConcurrentHashMap<>(); + + @Override + public void reset(int iteration) { + driversVehicles.clear(); + } + + @Override + public void handleEvent(VehicleEntersTrafficEvent event) { + driversVehicles.put(event.getPersonId(), event.getVehicleId()); + } + + @Override + public void handleEvent(VehicleLeavesTrafficEvent event) { + driversVehicles.remove(event.getPersonId()); + } + + /** + * @param personId the unique driver identifier. + * @return vehicle id of the driver's vehicle + */ + public Id getVehicleOfDriver(Id personId) { + return driversVehicles.get(personId); + } + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/analysis/LspScoreStats.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/analysis/LspScoreStats.java new file mode 100644 index 00000000000..297e99fc5b7 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/analysis/LspScoreStats.java @@ -0,0 +1,35 @@ + +/* + * *********************************************************************** * + * * project: org.matsim.* + * * ScoreStats.java + * * * + * * *********************************************************************** * + * * * + * * copyright : (C) 2014 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.freight.logistics.analysis; + +import java.util.Map; + +public interface LspScoreStats { + + /** + * @return the history of scores in last iterations + */ + Map> getScoreHistory(); + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/analysis/LspScoreStatsControlerListener.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/analysis/LspScoreStatsControlerListener.java new file mode 100644 index 00000000000..2a687b82f0f --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/analysis/LspScoreStatsControlerListener.java @@ -0,0 +1,286 @@ +/* *********************************************************************** * + * project: org.matsim.* + * ScoreStats.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.freight.logistics.analysis; + +import jakarta.inject.Inject; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.*; +import java.util.stream.Collectors; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Scenario; +import org.matsim.core.config.groups.ControllerConfigGroup; +import org.matsim.core.config.groups.GlobalConfigGroup; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.controler.events.IterationEndsEvent; +import org.matsim.core.controler.events.ShutdownEvent; +import org.matsim.core.controler.events.StartupEvent; +import org.matsim.core.controler.listener.IterationEndsListener; +import org.matsim.core.controler.listener.ShutdownListener; +import org.matsim.core.controler.listener.StartupListener; +import org.matsim.core.population.PopulationUtils; +import org.matsim.core.utils.charts.XYLineChart; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.freight.logistics.LSP; +import org.matsim.freight.logistics.LSPPlan; +import org.matsim.freight.logistics.LSPUtils; +import org.matsim.freight.logistics.LSPs; + +/** + * Calculates at the end of each iteration the following statistics: + *

    + *
  • average score of the selected plan
  • + *
  • average of the score of the worst plan of each agent
  • + *
  • average of the score of the best plan of each agent
  • + *
  • average of the average score of all plans of each agent
  • + *
+ * Plans with undefined scores + * are not included in the statistics. The calculated values are written to a file, each iteration on + * a separate line. + * + * @author mrieser + */ +public class LspScoreStatsControlerListener implements StartupListener, IterationEndsListener, ShutdownListener, LspScoreStats { + + private static final String LSP_SCORESTATS = "lsp_scorestats"; + + public enum ScoreItem { worst, best, average, executed } + + private final LSPs lsps; + private final OutputDirectoryHierarchy controllerIO; + private final String delimiter; + private final BufferedWriter out; + + private final ControllerConfigGroup controllerConfigGroup; + + private final Map> scoreHistory = new HashMap<>(); + + private final Map perLsp = new HashMap<>(); + + private int minIteration = 0; + + private final static Logger log = LogManager.getLogger(LspScoreStatsControlerListener.class); + + @Inject + LspScoreStatsControlerListener(ControllerConfigGroup controllerConfigGroup, Scenario scenario, OutputDirectoryHierarchy controllerIO, + GlobalConfigGroup globalConfig ) { + this.controllerConfigGroup = controllerConfigGroup; + this.lsps = LSPUtils.getLSPs(scenario); + this.controllerIO = controllerIO; + this.delimiter = globalConfig.getDefaultDelimiter(); + this.out = IOUtils.getBufferedWriter(controllerIO.getOutputFilename(LSP_SCORESTATS + ".csv")); + + //TODO: Das hier dann mal ansehen, weil es ja nun nicht mehr via Subpobulations ist.. Vermutlich brauche ich nur die LSPIds... + Set lspIds = lsps.getLSPs().values().stream() + .map(PopulationUtils::getSubpopulation) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + for (String lspId : lspIds) { + this.perLsp.put(lspId, new ScoreHist(new HashMap<>(), IOUtils.getBufferedWriter(controllerIO.getOutputFilename(LSP_SCORESTATS + "_" + lspId + ".csv")))); + } + + try { + this.out.write("iteration" + this.delimiter + "avg_executed" + this.delimiter + + "avg_worst" + this.delimiter + "avg_average" + this.delimiter + "avg_best\n"); + for (Map.Entry e : this.perLsp.entrySet()) { + e.getValue().out.write("iteration" + this.delimiter + "avg_executed" + this.delimiter + + "avg_worst" + this.delimiter + "avg_average" + this.delimiter + "avg_best\n"); + } + + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public void notifyStartup(final StartupEvent event) { + this.minIteration = this.controllerConfigGroup.getFirstIteration(); + // int maxIter = controlerConfigGroup.getLastIteration(); + // int iterations = maxIter - this.minIteration; + // if (iterations > 5000) iterations = 5000; // limit the history size + for ( ScoreItem item : ScoreItem.values() ) { + this.scoreHistory.put( item, new TreeMap<>() ) ; + this.perLsp.forEach((s, data) -> data.hist.put(item, new TreeMap<>())); + } + } + + @Override + public void notifyIterationEnds(final IterationEndsEvent event) { + collectScoreInfo(event); + if (isWriteGraph(event)) { + writePng(); + } + } + + private boolean isWriteGraph(IterationEndsEvent event) { + // create chart when data of more than one iteration is available. + return this.controllerConfigGroup.getCreateGraphsInterval() > 0 && + event.getIteration() % this.controllerConfigGroup.getCreateGraphsInterval() == 0 && + event.getIteration() > this.minIteration; + } + + private void collectScoreInfo(final IterationEndsEvent event) { + ScoreInfo info = new ScoreInfo(); + + Map perLsp = new HashMap<>(); + this.perLsp.forEach((subpop, d) -> perLsp.put(subpop, new ScoreInfo())); + + for (LSP lsp : this.lsps.getLSPs().values()) { + info.update(lsp); + String subpop = PopulationUtils.getSubpopulation(lsp); + if (subpop != null) + perLsp.get(subpop).update(lsp); + } + + + log.info("-- avg. score of the executed plan of each agent: " + (info.sumExecutedScores / info.nofExecutedScores)); + log.info("-- avg. score of the worst plan of each agent: " + (info.sumScoreWorst / info.nofScoreWorst)); + log.info("-- avg. of the avg. plan score per agent: " + (info.sumAvgScores / info.nofAvgScores)); + log.info("-- avg. score of the best plan of each agent: " + (info.sumScoreBest / info.nofScoreBest)); + + try { + info.write(event.getIteration(), this.out, this.delimiter); + for (Map.Entry e : this.perLsp.entrySet()) { + perLsp.get(e.getKey()).write(event.getIteration(), e.getValue().out, this.delimiter); + } + + } catch (IOException e) { + e.printStackTrace(); + } + +// int index = event.getIteration() - this.minIteration; + + this.scoreHistory.get( ScoreItem.worst ).put( event.getIteration(), info.sumScoreWorst / info.nofScoreWorst ) ; + this.scoreHistory.get( ScoreItem.best ).put( event.getIteration(), info.sumScoreBest / info.nofScoreBest ) ; + this.scoreHistory.get( ScoreItem.average ).put( event.getIteration(), info.sumAvgScores / info.nofAvgScores ) ; + this.scoreHistory.get( ScoreItem.executed ).put( event.getIteration(), info.sumExecutedScores / info.nofExecutedScores ) ; + } + + private void writePng() { + XYLineChart chart = new XYLineChart("Score Statistics", "iteration", "score"); + chart.addSeries("avg. worst score", this.scoreHistory.get( ScoreItem.worst ) ) ; + chart.addSeries("avg. best score", this.scoreHistory.get( ScoreItem.best) ); + chart.addSeries("avg. of plans' average score", this.scoreHistory.get( ScoreItem.average) ); + chart.addSeries("avg. executed score", this.scoreHistory.get( ScoreItem.executed ) ); + chart.addMatsimLogo(); + chart.saveAsPng(this.controllerIO.getOutputFilename(LSP_SCORESTATS + ".png"), 800, 600); + } + + @Override + public void notifyShutdown(final ShutdownEvent controlerShudownEvent) { + try { + this.out.close(); + for (ScoreHist data : this.perLsp.values()) { + data.out.close(); + } + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } + + @Override + public Map> getScoreHistory() { + return Collections.unmodifiableMap( this.scoreHistory ) ; + } + + private record ScoreHist(Map> hist, BufferedWriter out) {} + + private static final class ScoreInfo { + double sumScoreWorst = 0.0; + double sumScoreBest = 0.0; + double sumAvgScores = 0.0; + double sumExecutedScores = 0.0; + int nofScoreWorst = 0; + int nofScoreBest = 0; + int nofAvgScores = 0; + int nofExecutedScores = 0; + + private void update(LSP lsp) { + LSPPlan worstPlan = null; + LSPPlan bestPlan = null; + double worstScore = Double.POSITIVE_INFINITY; + double bestScore = Double.NEGATIVE_INFINITY; + double sumScores = 0.0; + double cntScores = 0; + for (LSPPlan plan : lsp.getPlans()) { + + if (plan.getScore() == null) { + continue; + } + double score = plan.getScore(); + + // worst plan + if (worstPlan == null) { + worstPlan = plan; + worstScore = score; + } else if (score < worstScore) { + worstPlan = plan; + worstScore = score; + } + + // best plan + if (bestPlan == null) { + bestPlan = plan; + bestScore = score; + } else if (score > bestScore) { + bestPlan = plan; + bestScore = score; + } + + // avg. score + sumScores += score; + cntScores++; + + // executed plan? + if (LSPUtils.isPlanTheSelectedPlan(plan)) { + this.sumExecutedScores += score; + this.nofExecutedScores++; + } + } + + if (worstPlan != null) { + this.nofScoreWorst++; + this.sumScoreWorst += worstScore; + } + if (bestPlan != null) { + this.nofScoreBest++; + this.sumScoreBest += bestScore; + } + if (cntScores > 0) { + this.sumAvgScores += (sumScores / cntScores); + this.nofAvgScores++; + } + } + + private void write(int iteration, BufferedWriter out, String delimiter) throws IOException { + out.write(iteration + delimiter + + (this.sumExecutedScores / this.nofExecutedScores) + delimiter + + (this.sumScoreWorst / this.nofScoreWorst) + delimiter + + (this.sumAvgScores / this.nofAvgScores) + delimiter + + (this.sumScoreBest / this.nofScoreBest) + "\n"); + out.flush(); + } + + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/analysis/LspScoreStatsModule.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/analysis/LspScoreStatsModule.java new file mode 100644 index 00000000000..948b206388d --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/analysis/LspScoreStatsModule.java @@ -0,0 +1,35 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * ScoreStatsModule.java + * * * + * * *********************************************************************** * + * * * + * * copyright : (C) 2014 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.freight.logistics.analysis; + +import com.google.inject.Singleton; +import org.matsim.core.controler.AbstractModule; + +public class LspScoreStatsModule extends AbstractModule { + @Override + public void install() { + bind(LspScoreStatsControlerListener.class).in(Singleton.class); + addControlerListenerBinding().to(LspScoreStatsControlerListener.class); + bind(LspScoreStats.class).to(LspScoreStatsControlerListener.class); + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/analysis/Vehicle2CarrierEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/analysis/Vehicle2CarrierEventHandler.java new file mode 100644 index 00000000000..d7230ab3d41 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/analysis/Vehicle2CarrierEventHandler.java @@ -0,0 +1,71 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.analysis; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import org.matsim.api.core.v01.Id; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.events.CarrierTourEndEvent; +import org.matsim.freight.carriers.events.CarrierTourStartEvent; +import org.matsim.freight.carriers.events.eventhandler.CarrierTourEndEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierTourStartEventHandler; +import org.matsim.vehicles.Vehicle; + +/** + * Basic event handler that collects the relation between vehicles and carrier. + * Necessary since there is no event having all this information together. + *

+ * This is a modified implementation of {@link org.matsim.core.events.algorithms.Vehicle2DriverEventHandler}. + *

+ * In a first step only used internally. When needed more often, I have nothing against putting it more central. -> matsim-libs + * + * @author kturner + */ +public class Vehicle2CarrierEventHandler implements CarrierTourStartEventHandler, CarrierTourEndEventHandler { + + private final Map, Id> vehicle2carrier = new ConcurrentHashMap<>(); + + @Override + public void reset(int iteration) { + vehicle2carrier.clear(); + } + + @Override + public void handleEvent(CarrierTourStartEvent event) { + vehicle2carrier.put(event.getVehicleId(), event.getCarrierId()); + } + + @Override + public void handleEvent(CarrierTourEndEvent event) { + vehicle2carrier.remove(event.getVehicleId()); + } + + /** + * @param vehicleId the unique vehicle Id + * @return id of the vehicle's carrier + */ + public Id getCarrierOfVehicle(Id vehicleId) { + return vehicle2carrier.get(vehicleId); + } + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/events/AbstractLogisticEvent.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/events/AbstractLogisticEvent.java new file mode 100644 index 00000000000..fd9791a6831 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/events/AbstractLogisticEvent.java @@ -0,0 +1,55 @@ +package org.matsim.freight.logistics.events; + +import java.util.Map; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.events.Event; +import org.matsim.api.core.v01.events.HasLinkId; +import org.matsim.api.core.v01.network.Link; +import org.matsim.freight.logistics.HasLspShipmentId; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * A general logistic event contains the information (= {@link Id}) of the - the location (= {@link + * Link}) - the lspShipment (= {@link LspShipment}) belonging to it. + * + *

Please note, that general _freight_ events can be found in the freight contrib. + * + * @author Kai Martins-Turner (kturner) + */ +public abstract class AbstractLogisticEvent extends Event implements HasLinkId, HasLspShipmentId { + + private final Id linkId; + private final Id lspShipmentId; + + public AbstractLogisticEvent(double time, Id linkId, Id lspShipmentId) { + super(time); + this.linkId = linkId; + this.lspShipmentId = lspShipmentId; + } + + /** + * @return id of the {@link LspShipment} + */ + @Override + public final Id getLspShipmentId() { + return lspShipmentId; + } + + @Override + public final Id getLinkId() { + return linkId; + } + + /** + * Adds the {@link Id< LspShipment >} to the list of attributes. {@link Id} is handled by + * superclass {@link Event} + * + * @return The map of attributes + */ + @Override + public Map getAttributes() { + Map attr = super.getAttributes(); + attr.put(ATTRIBUTE_LSP_SHIPMENT_ID, lspShipmentId.toString()); + return attr; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/events/HandlingInHubStartedEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/events/HandlingInHubStartedEventHandler.java new file mode 100644 index 00000000000..b8b9c6e900e --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/events/HandlingInHubStartedEventHandler.java @@ -0,0 +1,11 @@ +package org.matsim.freight.logistics.events; + +import org.matsim.core.events.handler.EventHandler; + +/** + * @author Kai Martins-Turner (kturner) + */ +public interface HandlingInHubStartedEventHandler extends EventHandler { + + void handleEvent(HandlingInHubStartsEvent event); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/events/HandlingInHubStartsEvent.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/events/HandlingInHubStartsEvent.java new file mode 100644 index 00000000000..c7e9f4a754d --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/events/HandlingInHubStartsEvent.java @@ -0,0 +1,88 @@ +/* + * *********************************************************************** * + * project: org.matsim.* + * *********************************************************************** * + * * + * copyright : (C) 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.freight.logistics.events; + +import static org.matsim.freight.logistics.events.LspEventAttributes.ATTRIBUTE_EXP_HANDLING_DURATION; +import static org.matsim.freight.logistics.events.LspEventAttributes.ATTRIBUTE_HUB_ID; + +import java.util.Map; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.events.GenericEvent; +import org.matsim.api.core.v01.network.Link; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * An event, that informs that the handling of a {@link LspShipment} in a hub has started. + * + * @author Kai Martins-Turner (kturner) + */ +public final class HandlingInHubStartsEvent extends AbstractLogisticEvent { + + public static final String EVENT_TYPE = "Handling_started"; + private final Id hubId; + private final double expHandlingDuration; + + public HandlingInHubStartsEvent( + double time, + Id linkId, + Id lspShipmentId, + Id hubId, + double expHandlingDuration) { + super(time, linkId, lspShipmentId); + this.hubId = hubId; + this.expHandlingDuration = expHandlingDuration; + } + + public static HandlingInHubStartsEvent convert(GenericEvent event) { + Map attributes = event.getAttributes(); + double time = Double.parseDouble(attributes.get(ATTRIBUTE_TIME)); + Id linkId = Id.createLinkId(attributes.get(ATTRIBUTE_LINK)); + Id lspSipmentId = + Id.create(attributes.get(ATTRIBUTE_LSP_SHIPMENT_ID), LspShipment.class); + var hubId = Id.create(attributes.get(ATTRIBUTE_HUB_ID), LSPResource.class); + double expHandlingDuration = + Double.parseDouble(attributes.get(ATTRIBUTE_EXP_HANDLING_DURATION)); + return new HandlingInHubStartsEvent(time, linkId, lspSipmentId, hubId, expHandlingDuration); + } + + @Override + public String getEventType() { + return EVENT_TYPE; + } + + public Id getHubId() { + return hubId; + } + + public double getExpHandlingDuration() { + return expHandlingDuration; + } + + @Override + public Map getAttributes() { + Map attr = super.getAttributes(); + attr.put(ATTRIBUTE_HUB_ID, hubId.toString()); + attr.put(ATTRIBUTE_EXP_HANDLING_DURATION, String.valueOf(expHandlingDuration)); + return attr; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/events/LspEventAttributes.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/events/LspEventAttributes.java new file mode 100644 index 00000000000..830862b6f5b --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/events/LspEventAttributes.java @@ -0,0 +1,32 @@ +/* + * *********************************************************************** * + * project: org.matsim.* + * *********************************************************************** * + * * + * copyright : (C) 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.freight.logistics.events; + +/** + * Some constants, that are used for the Attributes of different logistic events. + * + * @author Kai Martins-Turner (kturner) + */ +public class LspEventAttributes { + public static final String ATTRIBUTE_HUB_ID = "hubId"; + public static final String ATTRIBUTE_EXP_HANDLING_DURATION = "expHandlingDuration"; +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV1Test.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/events/LspEventCreator.java similarity index 50% rename from contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV1Test.java rename to contribs/freight/src/main/java/org/matsim/freight/logistics/events/LspEventCreator.java index f4840b577ae..b5a0933fa7c 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV1Test.java +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/events/LspEventCreator.java @@ -19,37 +19,18 @@ * */ -package org.matsim.freight.carriers; +package org.matsim.freight.logistics.events; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Id; -import org.matsim.freight.carriers.*; -import org.matsim.testcases.MatsimTestUtils; -import org.matsim.vehicles.VehicleType; -import org.matsim.vehicles.VehicleUtils; +import org.matsim.api.core.v01.events.Event; +import org.matsim.api.core.v01.population.Activity; +import org.matsim.freight.logistics.shipment.LspShipment; /** + * @author Kai Martins-Turner (kturner) */ -public class CarrierPlanXmlWriterV1Test { - - @RegisterExtension - private MatsimTestUtils testUtils = new MatsimTestUtils(); - - @Test - void testCarrierPlanWriterWrites() { - - CarrierVehicleTypes carrierVehicleTypes = new CarrierVehicleTypes(); - new CarrierVehicleTypeReader( carrierVehicleTypes ).readFile( testUtils.getPackageInputDirectory() + "vehicleTypes_v2.xml" ); - VehicleType defaultVehicleType = VehicleUtils.getFactory().createVehicleType( Id.create("default", VehicleType.class ) ); - carrierVehicleTypes.getVehicleTypes().put( defaultVehicleType.getId(), defaultVehicleType ); - - Carriers carriers = new Carriers(); - CarrierPlanReaderV1 carrierPlanReaderV1 = new CarrierPlanReaderV1(carriers, carrierVehicleTypes ); - carrierPlanReaderV1.readFile(testUtils.getClassInputDirectory() + "carrierPlansEquils.xml"); - CarrierPlanXmlWriterV1 planWriter = new CarrierPlanXmlWriterV1(carriers.getCarriers().values()); - planWriter.write(testUtils.getOutputDirectory() + "carrierPlansEquilsWritten.xml"); - } - +public interface LspEventCreator { + // I am unsure, if I need the activity or not. kmt 'dec22 + Event createEvent(Event event, Id lspShipmentId, Activity activity); } diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeLoader.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/events/LspEventsReader.java similarity index 51% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeLoader.java rename to contribs/freight/src/main/java/org/matsim/freight/logistics/events/LspEventsReader.java index c9fbe45d4ad..b65cf79b7c0 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarrierVehicleTypeLoader.java +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/events/LspEventsReader.java @@ -19,47 +19,35 @@ * */ -package org.matsim.freight.carriers; +package org.matsim.freight.logistics.events; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import java.util.Map; +import java.util.TreeMap; +import org.matsim.core.api.experimental.events.EventsManager; +import org.matsim.core.events.MatsimEventsReader; +import org.matsim.freight.carriers.events.CarrierEventsReaders; +import org.matsim.freight.logistics.LSP; /** - * @deprecated Functionality is removed. VehicleTypes must be set (and available) when creating the vehicle. kai/kai jan'22 - *

- * Loader that loads/assigns vehicleTypes to their vehicles and carriers respectively. - * - * @author sschroeder + * Creates an {@link MatsimEventsReader} that also handles the {@link + * LSP} specific events. * + * @author kturner (Kai Martins-Turner) */ -@Deprecated -public class CarrierVehicleTypeLoader { - - @SuppressWarnings("unused") - private static final Logger logger = LogManager.getLogger(CarrierVehicleTypeLoader.class); - - /** - * Constructs the loader with the carriers the types should be assigned to. - * - * @param carriers - * - * * @deprecated Functionality is removed. VehicleTypes must be set (and available) when creating the vehicle. kai/kai jan'22 - */ - @Deprecated - public CarrierVehicleTypeLoader(Carriers carriers) { - super(); - } +public class LspEventsReader { - /** - * Assigns types to carriers and their vehicles. - * - * @param types - * - * @deprecated Functionality is removed. VehicleTypes must be set (and available) when creating the vehicle. kai/kai jan'22 - */ - @Deprecated - public void loadVehicleTypes(CarrierVehicleTypes types){ - logger.error("Functionality is removed. VehicleTypes must be set (and available) when creating the vehicle."); - } + public static Map createCustomEventMappers() { + Map map = + new TreeMap<>( + CarrierEventsReaders + .createCustomEventMappers()); // also get all the Carrier-related EventMapper + map.put(HandlingInHubStartsEvent.EVENT_TYPE, HandlingInHubStartsEvent::convert); + return map; + } + public static MatsimEventsReader createEventsReader(EventsManager eventsManager) { + MatsimEventsReader reader = new MatsimEventsReader(eventsManager); + createCustomEventMappers().forEach(reader::addCustomEventMapper); + return reader; + } } diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/ExampleConstants.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/ExampleConstants.java new file mode 100644 index 00000000000..02939778990 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/ExampleConstants.java @@ -0,0 +1,83 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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 * + * * + * *********************************************************************** + */ + +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples; + +import java.util.Arrays; +import java.util.List; + +public class ExampleConstants { + //Both, the ingoing and outgoing links are tolled. -> Please be aware of it. + public static final List TOLLED_LINK_LIST_BERLIN_BOTH_DIRECTIONS = + Arrays.asList( + "70831", "14691", "49319", "70830", "17284", "65008", "65007", "62413", "17283", "144164", + "144165", "4606", "118311", "4607", "15423", "53820", "15422", "138286", "69167", + "138287", "17057", "74648", "74647", "113641", "10307", "10306", "51775", "155051", + "51776", "150042", "150043", "150164", "90583", "96329", "19320", "132511", "19321", + "64851", "144180", "34042", "124770", "34041", "74891", "144184", "124769", "35018", + "35017", "77379", "35256", "108717", "113640", "157261", "142799", "157262", "52995", + "934", "52996", "935", "95587", "95588", "17150", "147460", "147461", "54024", "54023", + "152801", "144506", "145715", "144505", "156464", "17125", "17126", "114545", "114546", + "140792", "17127", "17248", "17128", "17249", "156458", "35463", "159609", "35462", + "159608", "22046", "154715", "22047", "144373", "154716", "155927", "155926", "144372", + "96330", "61139", "98190", "144126", "144127", "61011", "61010", "156463", "63682", + "47555", "73006", "94867", "138930", "94866", "133488", "138931", "47554", "73005", + "58893", "116395", "116394", "144136", "1158", "1157", "58894", "61269", "79237", + "144137", "732", "149702", "733", "77854", "4785", "55946", "77855", "4786", "55945", + "90018", "61264", "61263", "86201", "77738", "120646", "77739", "26507", "108414", + "108415", "17115", "66841", "26506", "78255", "78254", "118561", "35447", "147535", + "17116", "118560", "61270", "102480", "51917", "62494", "72973", "51918", "72972", + "72050", "72051", "147027", "33258", "61169", "18419", "102479", "20863", "61170", + "43048", "43049", "69459", "73037", "18420", "69458", "3255", "3254", "73036", "27017", + "76094", "41429", "74241", "76095", "149583", "74240", "35426", "81688", "81689", "12686", + "25848", "25849", "64459", "115416", "149592", "74374", "115417", "81474", "81475", + "36983", "36984", "36985", "36986", "52917", "52918", "64460", "40311", "108695", "40310", + "79385", "119212", "155909", "119213", "119334", "119335", "112023", "48277", "48278", + "106946", "91853", "91854", "102288", "69129", "102287", "13607", "2985", "64482", + "156612", "8983", "156613", "67517", "28548", "28549", "83543", "145734", "83542", + "149536", "149537", "151175", "151174", "18159", "8994", "93250", "147370", "53001", + "5918", "24153", "79875", "147369", "36147", "53002", "138543", "138542", "104212", + "137699", "137698", "41960", "104211", "18160", "41723", "41724", "3505", "123744", + "81389", "104205", "104206", "112065", "49320", "84772", "37107", "142803"); + public static final List TOLLED_LINK_LIST_GRID = Arrays.asList( + "i(3,4)", "i(3,6)", "i(7,5)R", "i(7,7)R", "j(4,8)R", "j(6,8)R", "j(3,4)", "j(5,4)"); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleSchedulingOfInitialPlan.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleSchedulingOfInitialPlan.java new file mode 100644 index 00000000000..8715df32602 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleSchedulingOfInitialPlan.java @@ -0,0 +1,209 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.initialPlans; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Random; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +/*package-private*/ class ExampleSchedulingOfInitialPlan { + + private static LSP createInitialLSP(Scenario scenario) { + + // The Carrier for the resource of the sole LogisticsSolutionElement of the LSP is created + Id carrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id vollectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle carrierVehicle = + CarrierVehicle.newInstance(vollectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities capabilities = CarrierCapabilities.Builder.newInstance() + .addVehicle(carrierVehicle) + .setFleetSize(FleetSize.INFINITE) + .build(); + + Carrier carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + // The Resource i.e. the Resource is created + LSPResource collectionResource = + ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance( + carrier) + .setCollectionScheduler( + ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + // The adapter is now inserted into the only LogisticsSolutionElement of the only + // LogisticsSolution of the LSP + LogisticChainElement collectionElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + // The LogisticsSolutionElement is now inserted into the only LogisticsSolution of the LSP + LogisticChain collectionSolution = + LSPUtils.LogisticChainBuilder.newInstance( + Id.create("CollectionSolution", LogisticChain.class)) + .addLogisticChainElement(collectionElement) + .build(); + + // The initial plan of the lsp is generated and the assigner and the solution from above are + // added + LSPPlan collectionPlan = LSPUtils.createLSPPlan(); + InitialShipmentAssigner assigner = + ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + collectionPlan.setInitialShipmentAssigner(assigner); + collectionPlan.addLogisticChain(collectionSolution); + + // The exogenous list of Resources for the SolutionScheduler is compiled and the Scheduler is + // added to the LSPBuilder + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + LogisticChainScheduler simpleScheduler = + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + + return LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)) + .setInitialPlan(collectionPlan) + .setLogisticChainScheduler(simpleScheduler) + .build(); + } + + private static Collection createInitialLSPShipments(Network network) { + ArrayList shipmentList = new ArrayList<>(); + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + + // Create five LSPShipments that are located in the left half of the network. + for (int i = 1; i < 6; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + Random random = new Random(1); + int capacityDemand = random.nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, random); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 + && pendingFromLink.getFromNode().getCoord().getY() <= 4000 + && pendingFromLink.getToNode().getCoord().getX() <= 4000 + && pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + builder.setToLinkId(Id.createLinkId("(4 2) (4 3)")); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + shipmentList.add(builder.build()); + } + return shipmentList; + } + + public static void main(String[] args) { + + // Set up required MATSim classes + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()) + .readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + // Create LSP and lspShipments + LSP lsp = createInitialLSP(scenario); + Collection lspShipments = createInitialLSPShipments(network); + + // assign the lspShipments to the LSP + for (LspShipment lspShipment : lspShipments) { + lsp.assignShipmentToLSP(lspShipment); + } + + // schedule the LSP with the lspShipments and according to the scheduler of the Resource + lsp.scheduleLogisticChains(); + + // print the schedules for the assigned LSPShipments + for (LspShipment lspShipment : lspShipments) { + System.out.println("Shipment: " + lspShipment.getId()); + ArrayList scheduleElements = + new ArrayList<>( + LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), lspShipment.getId()) + .getPlanElements() + .values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = + new ArrayList<>(lspShipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement element : + LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), lspShipment.getId()) + .getPlanElements() + .values()) { + System.out.println( + // "Solution Id: " + element.getSolutionElement().getEmbeddingContainer().getId() + + " SolutionElement Id: " + + element.getLogisticChainElement().getId() + + " Resource Id: " + + element.getResourceId() + + " Type: " + + element.getElementType() + + " Start Time: " + + element.getStartTime() + + " End Time: " + + element.getEndTime()); + } + System.out.println(); + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleSchedulingOfTransportChain.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleSchedulingOfTransportChain.java new file mode 100644 index 00000000000..eb01dda6b7e --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleSchedulingOfTransportChain.java @@ -0,0 +1,388 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.initialPlans; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Random; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.DistributionCarrierResourceBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +/*A transport chain with five elements (collection-> reloading -> main run -> reloading -> delivery) is created and scheduled + * + */ + +/*package-private*/ class ExampleSchedulingOfTransportChain { + + private static LSP createInitialLSP(Scenario scenario) { + + Network network = scenario.getNetwork(); + + // The Carrier for collection is created + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id vollectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle carrierVehicle = + CarrierVehicle.newInstance(vollectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(carrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities capabilities = capabilitiesBuilder.build(); + + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(capabilities); + + // The collection adapter i.e. the Resource is created + LSPResource collectionResource = + ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance( + collectionCarrier) + .setCollectionScheduler( + ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + // The adapter is now inserted into the corresponding LogisticsSolutionElement of the only + // LogisticsSolution of the LSP + LogisticChainElement collectionElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + // The first reloading adapter i.e. the Resource is created + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + TransshipmentHubBuilder firstTransshipmentHubBuilder = + ResourceImplementationUtils.TransshipmentHubBuilder.newInstance( + firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + + // The scheduler for the first reloading point is created + final LSPResourceScheduler firstHubScheduler = + ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed(10) + .setCapacityNeedLinear(1) + .build(); + + // The scheduler is added to the Resource and the Resource is created + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstHubScheduler); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + // The SolutionElement for the first reloading point is created + Id firstHubElementId = + Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = + LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + // The Carrier for the main run Resource is created + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + final VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50 / 3.6); + mainRunVehType.setNetworkMode(TransportMode.car); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = + CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + CarrierCapabilities mainRunCapabilities = + CarrierCapabilities.Builder.newInstance() + .addVehicle(mainRunCarrierVehicle) + .setFleetSize(FleetSize.INFINITE) + .build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + // The adapter i.e. the main run resource is created + LSPResource mainRunResource = + ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .build(); + + // The LogisticsSolutionElement for the main run Resource is created + LogisticChainElement mainRunElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + // The second reloading adapter i.e. the Resource is created + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + + // The scheduler for the second reloading point is created + LSPResourceScheduler secondHubScheduler = + ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed(10) + .setCapacityNeedLinear(1) + .build(); + + LSPResource secondTransshipmentHubResource = + ResourceImplementationUtils.TransshipmentHubBuilder.newInstance( + secondTransshipmentHubId, secondTransshipmentHub_LinkId, scenario) + .setTransshipmentHubScheduler(secondHubScheduler) + .build(); + + // The adapter is now inserted into the corresponding LogisticsSolutionElement of the only + // LogisticsSolution of the LSP + Id secondHubElementId = + Id.create("SecondHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = + LSPUtils.LogisticChainElementBuilder.newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTransshipmentHubResource); + LogisticChainElement secondHubElement = secondHubElementBuilder.build(); + + // The Carrier for distribution is created + Id distributionCarrierId = Id.create("DistributionCarrier", Carrier.class); + Id distributionVehTypeId = Id.create("DistributionCarrierVehicleType", VehicleType.class); + final VehicleType distributionVehType = VehicleUtils.createVehicleType(distributionVehTypeId, TransportMode.car); + distributionVehType.getCapacity().setOther(10); + distributionVehType.getCostInformation().setCostsPerMeter(0.0004); + distributionVehType.getCostInformation().setCostsPerSecond(0.38); + distributionVehType.getCostInformation().setFixedCost(49.); + distributionVehType.setMaximumVelocity(50 / 3.6); + distributionVehType.setNetworkMode(TransportMode.car); + + + Id distributionLinkId = Id.createLinkId("(14 2) (14 3)"); + Id distributionVehicleId = Id.createVehicleId("DistributionVehicle"); + CarrierVehicle distributionCarrierVehicle = + CarrierVehicle.newInstance(distributionVehicleId, distributionLinkId, distributionVehType); + + CarrierCapabilities.Builder distributionCapabilitiesBuilder = + CarrierCapabilities.Builder.newInstance(); + distributionCapabilitiesBuilder.addVehicle(distributionCarrierVehicle); + distributionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities distributionCapabilities = distributionCapabilitiesBuilder.build(); + Carrier distributionCarrier = CarriersUtils.createCarrier(distributionCarrierId); + distributionCarrier.setCarrierCapabilities(distributionCapabilities); + + // The distribution adapter i.e. the Resource is created + DistributionCarrierResourceBuilder distributionResourceBuilder = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + distributionCarrier); + distributionResourceBuilder.setLocationLinkId(distributionLinkId); + + // The scheduler for the Resource is created and added. This is where jsprit comes into play. + distributionResourceBuilder.setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)); + LSPResource distributionResource = distributionResourceBuilder.build(); + + // The adapter is now inserted into the corresponding LogisticsSolutionElement of the only + // LogisticsSolution of the LSP + Id distributionElementId = + Id.create("DistributionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder distributionBuilder = + LSPUtils.LogisticChainElementBuilder.newInstance(distributionElementId); + distributionBuilder.setResource(distributionResource); + LogisticChainElement distributionElement = distributionBuilder.build(); + + // The Order of the logisticsSolutionElements is now specified + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + secondHubElement.connectWithNextElement(distributionElement); + + // The SolutionElements are now inserted into the only LogisticsSolution of the LSP + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = + LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + completeSolutionBuilder.addLogisticChainElement(mainRunElement); + completeSolutionBuilder.addLogisticChainElement(secondHubElement); + completeSolutionBuilder.addLogisticChainElement(distributionElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + // The initial plan of the lsp is generated and the assigner and the solution from above are + // added + LSPPlan completePlan = LSPUtils.createLSPPlan(); + InitialShipmentAssigner assigner = + ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = + LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + + // The exogenous list of Resources for the SolutionScheduler is compiled and the Scheduler is + // added to the LSPBuilder + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + resourcesList.add(secondTransshipmentHubResource); + resourcesList.add(distributionResource); + + // SolutionScheduler forwardSolutionScheduler = LSPUtils.createForwardSolutionScheduler(); + // //Ist der "nicht einfache" Scheduler. TODO braucht der keine RessourcenListe oder ähnliches? + // --> Offenbar ja, weil Null Pointer. argh! + // completeLSPBuilder.setSolutionScheduler(forwardSolutionScheduler); + + LogisticChainScheduler simpleScheduler = + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + + return completeLSPBuilder.build(); + } + + private static Collection createInitialLSPShipments(Network network) { + ArrayList shipmentList = new ArrayList<>(); + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + Random rand = new Random(1); + for (int i = 1; i < 6; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = rand.nextInt(10); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, rand); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 + && pendingToLink.getFromNode().getCoord().getY() <= 4000 + && pendingToLink.getFromNode().getCoord().getX() >= 14000 + && pendingToLink.getToNode().getCoord().getX() <= 18000 + && pendingToLink.getToNode().getCoord().getY() <= 4000 + && pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + } + + while (true) { + Collections.shuffle(linkList, rand); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 + && pendingFromLink.getFromNode().getCoord().getY() <= 4000 + && pendingFromLink.getToNode().getCoord().getX() <= 4000 + && pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + shipmentList.add(builder.build()); + } + return shipmentList; + } + + public static void main(String[] args) { + + // Set up required MATSim classes + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()) + .readFile("scenarios/2regions/2regions-network.xml"); + + // Create LSP and shipments + LSP lsp = createInitialLSP(scenario); + Collection lspShipments = createInitialLSPShipments(scenario.getNetwork()); + + // assign the shipments to the LSP + for (LspShipment lspShipment : lspShipments) { + lsp.assignShipmentToLSP(lspShipment); + } + + // schedule the LSP with the shipments and according to the scheduler of the Resource + lsp.scheduleLogisticChains(); + + // print the schedules for the assigned LSPShipments + for (LspShipment lspShipment : lsp.getLspShipments()) { + ArrayList elementList = + new ArrayList<>( + LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), lspShipment.getId()) + .getPlanElements() + .values()); + elementList.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + System.out.println("Shipment: " + lspShipment.getId()); + for (LspShipmentPlanElement element : elementList) { + System.out.println( + element.getLogisticChainElement().getId() + + "\t\t" + + element.getResourceId() + + "\t\t" + + element.getElementType() + + "\t\t" + + element.getStartTime() + + "\t\t" + + element.getEndTime()); + } + System.out.println(); + } + + // for (LSPResource lspResource : lsp.getResources()) { + // if (lspResource instanceof Carrier ) { + // ((Carrier) lspResource).getShipments().toString(); + // } + // } + // the above cast keeps complaining when I refactor; in consequence, I am becoming doubtful if + // this condition can ever be satisfied. + // also not sure what the code stub might be doing: It is converting to string, but not doing + // anything with it. kai, may'22 + + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleSchedulingOfTransportChainHubsVsDirect.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleSchedulingOfTransportChainHubsVsDirect.java new file mode 100644 index 00000000000..8daef42c974 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleSchedulingOfTransportChainHubsVsDirect.java @@ -0,0 +1,620 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.initialPlans; + +import java.util.*; +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.Scenario; +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.config.CommandLine; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.*; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.RandomPlanSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.carriers.events.CarrierServiceEndEvent; +import org.matsim.freight.carriers.events.CarrierTourEndEvent; +import org.matsim.freight.carriers.events.eventhandler.CarrierServiceEndEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierTourEndEventHandler; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.examples.lspReplanning.AssignmentStrategyFactory; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +/** + * The LSP have to possibilities to send the goods from the first depot to the recipients: A) via + * another hub and then distributed or B) directly from the depot + * + *

This examples bases on the Example ExampleSchedulingOfTransportChain.class -- the collection + * Part is removed, Chain is now starting at the CollectionHub + * + *

Scheduler = Macht die Pläne für die Fahrzeuge für die nächste MATSim-Iteration. Er plant es + * für jede Ressource. --> jede Ressource hat einen eigenen Scheduler: 1.) Simple: Nimm die + * mitgegebene Reihenfolge. 2.) + */ +/*package-private*/ final class ExampleSchedulingOfTransportChainHubsVsDirect { + + private static final Logger log = + LogManager.getLogger(ExampleSchedulingOfTransportChainHubsVsDirect.class); + + private ExampleSchedulingOfTransportChainHubsVsDirect() {} // so it cannot be instantiated + + public static void main(String[] args) { + + final SolutionType solutionType; + + for (String arg : args) { + log.warn(arg); + } + + // Set up required MATSim classes + + Config config = ConfigUtils.createConfig(); + if (args.length != 0) { + for (String arg : args) { + log.warn(arg); + } + ConfigUtils.applyCommandline(config, args); + + CommandLine cmd = ConfigUtils.getCommandLine(args); + solutionType = SolutionType.valueOf(cmd.getOption("solutionType").orElseThrow()); + + } else { + solutionType = SolutionType.onePlan_direct; + log.warn("SolutionType was set in code to: {}", solutionType); + config.controller().setOutputDirectory("output/ChainVsDirect/" + solutionType); + config.controller().setLastIteration(2); + } + config + .controller() + .setOverwriteFileSetting( + OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + // The VSP default settings are designed for person transport simulation. After talking to Kai, + // they will be set to WARN here. Kai MT may'23 + config.vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + log.warn("solutionType= {}", solutionType); + + config.network().setInputFile("scenarios/2regions/2regions-network.xml"); + + log.info("Starting ..."); + log.info("Set up required MATSim classes"); + + Scenario scenario = ScenarioUtils.loadScenario(config); + + // ######## + + log.info("create LSP"); + LSP lsp = createInitialLSP(scenario, solutionType); + + log.info("create initial LSPShipments"); + log.info("assign the shipments to the LSP"); + for (LspShipment lspShipment : createInitialLSPShipments(scenario.getNetwork())) { + lsp.assignShipmentToLSP(lspShipment); + } + + log.info("schedule the LSP with the shipments and according to the scheduler of the Resource"); + lsp.scheduleLogisticChains(); + + log.info("Set up simulation controller and LSPModule"); + LSPUtils.addLSPs(scenario, new LSPs(Collections.singletonList(lsp))); + + // @KMT: LSPModule ist vom Design her nur im Zusammenhang mit dem Controler sinnvoll. Damit kann + // man dann auch vollständig auf + // Injection setzen. + + Controller controller = ControllerUtils.createController(scenario); + controller.addOverridingModule(new LSPModule()); + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); + + // bind( LSPStrategyManager.class ).toInstance( new + // LSPModule.LSPStrategyManagerEmptyImpl() ); + // The above means there will be no replanning. The below needs at least one strategy + // to be happy. kai, jul'22 + bind(LSPStrategyManager.class) + .toProvider( + () -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy( + new AssignmentStrategyFactory().createStrategy(), null, 1); + return strategyManager; + }); + bind(CarrierStrategyManager.class) + .toProvider( + () -> { + CarrierStrategyManager strategyManager = + CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy( + new GenericPlanStrategyImpl<>(new RandomPlanSelector<>()), null, 1); + return strategyManager; + }); + } + }); + + log.info("Run MATSim"); + + controller.run(); + + // print the schedules for the assigned LSPShipments + log.info("print the schedules for the assigned LSPShipments"); + ResourceImplementationUtils.printResults_shipmentPlan( + config.controller().getOutputDirectory(), lsp); + + log.info("Done."); + } + + private static LSP createInitialLSP(Scenario scenario, SolutionType solutionType) { + + Network network = scenario.getNetwork(); + + LSPUtils.LSPBuilder lspBuilder = + switch (solutionType) { + case onePlan_withHub -> LSPUtils.LSPBuilder.getInstance( + Id.create("LSPwithReloading", LSP.class)); + case onePlan_direct, twoPlans_directAndHub -> LSPUtils.LSPBuilder.getInstance(Id.create("LSPdirect", LSP.class)); + }; + + // lspBuilder.setSolutionScorer(new MyLSPScorer()); + + final Id depotLinkId = + Id.createLinkId("(4 2) (4 3)"); // TODO: Hochziehen aber non-static. + final Id hubLinkId = Id.createLinkId("(14 2) (14 3)"); + + LogisticChainElement depotElement; + { + // The SolutionElement for the first reloading point is created + + log.info(""); + log.info("Create depot"); + + // The scheduler for the first reloading point is created --> this will be the depot in this + // use case + LSPResourceScheduler depotScheduler = + ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed(10) // Time needed, fixed (for Scheduler) + .setCapacityNeedLinear(1) // additional time needed per shipmentSize (for Scheduler) + .build(); + + // The scheduler is added to the Resource and the Resource is created + LSPResource depotResource = + ResourceImplementationUtils.TransshipmentHubBuilder.newInstance( + Id.create("Depot", LSPResource.class), depotLinkId, scenario) + .setTransshipmentHubScheduler(depotScheduler) + .build(); + + depotElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("DepotElement", LogisticChainElement.class)) + .setResource(depotResource) + .build(); // Nicht unbedingt nötig, aber nehme den alten Hub nun als Depot. Waren + // werden dann dort "Zusammengestellt". + // Maybe TODO: Depot als LogisticSolutionElement raus nehmen.(?) + } + + // The LogisticsSolutionElement for the main run Resource is created + LogisticChainElement mainRunElement; + { + log.info(""); + log.info("The Carrier for the main run is created"); + Carrier mainRunCarrier = + CarriersUtils.createCarrier(Id.create("MainRunCarrier", Carrier.class)); + + Id mainRunCarrierVehicleType = Id.create("MainRunCarrierVehicleType", VehicleType.class); + VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunCarrierVehicleType, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50 / 3.6); + mainRunVehType.setNetworkMode(TransportMode.car); + + CarrierVehicle mainRunCarrierVehicle = + CarrierVehicle.Builder.newInstance( + Id.createVehicleId("MainRunVehicle"), depotLinkId, mainRunVehType) + .build(); + + mainRunCarrier.setCarrierCapabilities( + CarrierCapabilities.Builder.newInstance() + .addVehicle(mainRunCarrierVehicle) + .setFleetSize(FleetSize.INFINITE) + .build()); + + // The scheduler for the main run Resource is created and added to the Resource + LSPResource mainRunResource = + ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setFromLinkId(depotLinkId) + .setToLinkId(hubLinkId) + .setMainRunCarrierScheduler( + ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .build(); + + mainRunElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + } + + LogisticChainElement hubElement; + { + log.info(""); + log.info("The second reloading adapter (hub) i.e. the Resource is created"); + // The scheduler for the second reloading point is created + LSPResourceScheduler hubScheduler = + ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed(10) + .setCapacityNeedLinear(1) + .build(); + + // The scheduler is added to the Resource and the Resource is created + // The second reloading adapter i.e. the Resource is created + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + LSPResource hubResource = + ResourceImplementationUtils.TransshipmentHubBuilder.newInstance( + secondTransshipmentHubId, hubLinkId, scenario) + .setTransshipmentHubScheduler(hubScheduler) + .build(); + + // The adapter is now inserted into the corresponding LogisticsSolutionElement of the only + // LogisticsSolution of the LSP + hubElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("SecondHubElement", LogisticChainElement.class)) + .setResource(hubResource) + .build(); + } + + LogisticChainElement distributionElement; + { + // The Carrier for distribution from reloading Point is created + VehicleType distributionVehType = + createCarrierVehicleType("DistributionCarrierVehicleType"); + + CarrierVehicle distributionCarrierVehicle = + CarrierVehicle.Builder.newInstance( + Id.createVehicleId("DistributionVehicle"), hubLinkId, distributionVehType) + .build(); + + Carrier distributionCarrier = + CarriersUtils.createCarrier(Id.create("DistributionCarrier", Carrier.class)); + distributionCarrier.setCarrierCapabilities( + CarrierCapabilities.Builder.newInstance() + .addVehicle(distributionCarrierVehicle) + .setFleetSize(FleetSize.INFINITE) + .build()); + + // The distribution adapter i.e. the Resource is created + LSPResource distributionResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + distributionCarrier) + .setLocationLinkId(hubLinkId) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + // (The scheduler is where jsprit comes into play.) + + // The adapter is now inserted into the corresponding LogisticsSolutionElement of the only + // LogisticsSolution of the LSP + + distributionElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("DistributionElement", LogisticChainElement.class)) + .setResource(distributionResource) + .build(); + } + + // ### New (KMT): Carrier for direct distribution from Depot (without 2nd reloading Point) + LogisticChainElement directDistributionElement; + { + // The Carrier for distribution from reloading Point is created + VehicleType directdistributionVehType = + createCarrierVehicleType("DirectDistributionCarrierVehicleType"); + + CarrierVehicle directDistributionCarrierVehicle = + CarrierVehicle.Builder.newInstance( + Id.createVehicleId("DirectDistributionVehicle"), + depotLinkId, + directdistributionVehType) + .build(); + + CarrierCapabilities directDistributionCarrierCapabilities = + CarrierCapabilities.Builder.newInstance() + .addVehicle(directDistributionCarrierVehicle) + .setFleetSize(FleetSize.INFINITE) + .build(); + Carrier directDistributionCarrier = + CarriersUtils.createCarrier(Id.create("DirectDistributionCarrier", Carrier.class)); + directDistributionCarrier.setCarrierCapabilities(directDistributionCarrierCapabilities); + + // The distribution adapter i.e. the Resource is created + LSPResource directDistributionResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + directDistributionCarrier) + .setLocationLinkId(depotLinkId) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + // (The scheduler is where jsprit comes into play.) + + // The adapter is now inserted into the corresponding LogisticsSolutionElement of the only + // LogisticsSolution of the LSP + directDistributionElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("DirectDistributionElement", LogisticChainElement.class)) + .setResource(directDistributionResource) + .build(); + } + // ### end new + + // TODO: Beide Lösungen anbieten und "bessere" oder zunächst "eine" auswählen" + + // TODO: Für die Auswahl "CostInfo an die Solutions dran heften. + + // The SolutionElements are now inserted into the only LogisticsSolution of the LSP. + // Die Reihenfolge des Hinzufügens ist egal, da weiter oben die jeweils direkten + // Vorgänger/Nachfolger bestimmt wurden. + + switch (solutionType) { + case onePlan_withHub -> { + // ### This is the original solution with mainRun - TranshipmentHub - distributionRun + log.info("Creating LSP with one plan: reloading at hub"); + + LSPPlan lspPlan_Reloading = + createLSPPlan_reloading(depotElement, mainRunElement, hubElement, distributionElement); + + return lspBuilder + .setInitialPlan(lspPlan_Reloading) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + createResourcesListFromLSPPlan(lspPlan_Reloading))) + .build(); + } + case onePlan_direct -> { + // ### This is the new solution with directDistribution from the Depot. + log.info("Creating LSP with one plan: direct distribution from the depot"); + + LSPPlan lspPlan_direct = createLSPPlan_direct(depotElement, directDistributionElement); + + return lspBuilder + .setInitialPlan(lspPlan_direct) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + createResourcesListFromLSPPlan(lspPlan_direct))) + .build(); + } + case twoPlans_directAndHub -> { + log.info( + "Creating LSP with two plans: i) direct distribution from the depot ii) reloading at hub"); + + log.error( + "This is totally untested. I can neither say if it will work nor if it will do anything useful - kmt feb22"); + + // TODO: Habe das vorziehen vor das switch statement rückgängig gemacht, weil es sideeffekte + // hatte -> Die dürften hier auch sein!!!! (KMT may22) + // Die createLSPPlan_reloading(..) Methoden sind nicht unabhängig voneinander. + // Das liegt wohl am statischen und das dann dort wieder Verknüpfungen gesetzt werden --> + // Hier auch aufpassen + LSPPlan lspPlan_Reloading = + createLSPPlan_reloading(depotElement, mainRunElement, hubElement, distributionElement); + LSPPlan lspPlan_direct = createLSPPlan_direct(depotElement, directDistributionElement); + + // TODO: Müsste nicht eigentlich der SolutionScheduler dann auf Ebene der einzelnen Pläne + // (mit ihren Solutions) sein?? kmt Feb22 + // So muss ich erst die Ressourcen aus beiden hinzuzufügenden Plänen aufsammeln, damit die + // dann schon in den Builder können. Irgendwie unschön. + List resourcesList = createResourcesListFromLSPPlan(lspPlan_direct); + resourcesList.addAll(createResourcesListFromLSPPlan(lspPlan_Reloading)); + + final LSP lsp = + lspBuilder + .setInitialPlan(lspPlan_direct) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + resourcesList)) + .build(); + + lsp.addPlan(lspPlan_Reloading); // adding the second plan + + return lsp; + } + default -> throw new IllegalStateException("Unexpected value: " + solutionType); + } + } + + private static List createResourcesListFromLSPPlan(LSPPlan lspPlanWithReloading) { + log.info("Collecting all LSPResources from the LSPPlan"); + List resourcesList = + new ArrayList<>(); // TODO: Mahe daraus ein Set, damit jede Resource nur einmal drin ist? + // kmt Feb22 + for (LogisticChain solution : lspPlanWithReloading.getLogisticChains()) { + for (LogisticChainElement solutionElement : solution.getLogisticChainElements()) { + resourcesList.add(solutionElement.getResource()); + } + } + return resourcesList; + } + + private static LSPPlan createLSPPlan_direct( + LogisticChainElement depotElement, LogisticChainElement directDistributionElement) { + log.info(""); + log.info("The order of the logisticsSolutionElements is now specified"); + depotElement.connectWithNextElement(directDistributionElement); + + log.info(""); + log.info("set up logistic Solution - direct distribution from the depot is created"); + + LogisticChain completeSolutionDirect = + LSPUtils.LogisticChainBuilder.newInstance( + Id.create("SolutionDirectId", LogisticChain.class)) + .addLogisticChainElement(depotElement) + .addLogisticChainElement(directDistributionElement) + .build(); + + log.info(""); + log.info( + "The initial plan of the lsp is generated and the assigner and the solution from above are added"); + + return LSPUtils.createLSPPlan() + .setInitialShipmentAssigner(ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner()) + .addLogisticChain(completeSolutionDirect); + } + + private static LSPPlan createLSPPlan_reloading( + LogisticChainElement depotElement, + LogisticChainElement mainRunElement, + LogisticChainElement hubElement, + LogisticChainElement distributionElement) { + log.info(""); + log.info("set up logistic Solution - original with hub usage solution is created"); + + // Das ist wichtig, damit er die Kette zur Verfügung hat. + depotElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(hubElement); + hubElement.connectWithNextElement(distributionElement); + + LogisticChain completeSolutionWithReloading = + LSPUtils.LogisticChainBuilder.newInstance( + Id.create("SolutionWithTransshipmentHubId", LogisticChain.class)) + .addLogisticChainElement(depotElement) + .addLogisticChainElement(mainRunElement) + .addLogisticChainElement(hubElement) + .addLogisticChainElement(distributionElement) + .build(); + + log.info(""); + log.info( + "The initial plan of the lsp is generated and the assigner and the solution from above are added"); + + return LSPUtils.createLSPPlan() + .setInitialShipmentAssigner(ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner()) + .addLogisticChain(completeSolutionWithReloading); + } + + private static VehicleType createCarrierVehicleType(String vehicleTypeId) { + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create(vehicleTypeId, VehicleType.class), TransportMode.car); + vehicleType.getCapacity().setOther(10); + vehicleType.getCostInformation().setCostsPerMeter(0.0004); + vehicleType.getCostInformation().setCostsPerSecond(0.38); + vehicleType.getCostInformation().setFixedCost(49.); + vehicleType.setMaximumVelocity(50 / 3.6); + vehicleType.setNetworkMode(TransportMode.car); + + return vehicleType; + } + + private static Collection createInitialLSPShipments(Network network) { + ArrayList shipmentList = new ArrayList<>(); + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + Random rand = new Random(1); + for (int i = 1; i < 6; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = rand.nextInt(10); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, rand); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 + && pendingToLink.getFromNode().getCoord().getY() <= 4000 + && pendingToLink.getFromNode().getCoord().getX() >= 14000 + && pendingToLink.getToNode().getCoord().getX() <= 18000 + && pendingToLink.getToNode().getCoord().getY() <= 4000 + && pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + } + + builder.setFromLinkId( + Id.createLinkId( + "(4 2) (4 3)")); // Here was the "first" reloading Point, now called depot. + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment lspShipment = builder.build(); + shipmentList.add(lspShipment); + } + return shipmentList; + } + + enum SolutionType { + onePlan_withHub, + onePlan_direct, + twoPlans_directAndHub + } + + private static class MyLSPScorer + implements LSPScorer, CarrierTourEndEventHandler, CarrierServiceEndEventHandler { + private double score = 0.; + + @Override + public double getScoreForCurrentPlan() { + return score; + } + + @Override + public void setEmbeddingContainer(LSP pointer) {} + + @Override + public void handleEvent(CarrierTourEndEvent event) { + score++; + // use event handlers to compute score. In this case, score is incremented by one every time + // a CarrierService and a tour ends. + } + + @Override + public void reset(int iteration) { + score = 0.; + } + + @Override + public void handleEvent(CarrierServiceEndEvent event) { + score++; + // use event handlers to compute score. In this case, score is incremented by one every time + // a CarrierService and a tour ends. + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleTestOutput.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleTestOutput.java new file mode 100644 index 00000000000..7cfc3b4ca82 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleTestOutput.java @@ -0,0 +1,61 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.initialPlans; + +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.VspExperimentalConfigGroup; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; + +class ExampleTestOutput { + + public static void main(String[] args) { + + Config config = + ConfigUtils.loadConfig( + IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("equil"), "config.xml")); + + config + .controller() + .setOverwriteFileSetting( + OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setLastIteration(1); + + Scenario scenario = ScenarioUtils.loadScenario(config); + + Controller controller = ControllerUtils.createController(scenario); + + // The VSP default settings are designed for person transport simulation. After talking to Kai, + // they will be set to WARN here. Kai MT may'23 + controller + .getConfig() + .vspExperimental() + .setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleTwoEchelonGrid.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleTwoEchelonGrid.java new file mode 100644 index 00000000000..b289d95c39a --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleTwoEchelonGrid.java @@ -0,0 +1,535 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.initialPlans; + +import java.util.*; +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.Scenario; +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.config.CommandLine; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.*; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.BestPlanSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +/** + * This is an academic example for the 2-echelon problem. It uses the 9x9-grid network from the + * matsim-examples. + * + *

The depot is located at the outer border of the network, while the jobs are located in the + * middle area. The {@link LSP} has two different {@link LSPPlan}s: 1) direct delivery from the + * depot 2) Using a TransshipmentHubResource: All goods were brought from the depot to the hub, + * reloaded and then brought from the hub to the customers + * + *

The decision which of these plans is chosen should be made via the Score of the plans. We will + * modify the costs of the vehicles and/or for using(having) the Transshipment hub. Depending on + * this setting, the plan selection should be done accordingly. + * + *

Please note: This example is in part on existing examples, but I start from the scratch for a) + * see, if this works and b) have a "clean" class :) + * + * @author Kai Martins-Turner (kturner) + */ +final class ExampleTwoEchelonGrid { + + // Run Settings + static final double HUBCOSTS_FIX = 100; + private static final DemandSetting demandSetting = DemandSetting.oneCustomer; + private static final CarrierCostSetting costSetting = CarrierCostSetting.lowerCost4LastMile; + private static final double TOLL_VALUE = 1000; + + private static final Logger log = LogManager.getLogger(ExampleTwoEchelonGrid.class); + + private static final Id DEPOT_LINK_ID = Id.createLinkId("i(5,0)"); + private static final Id HUB_LINK_ID = Id.createLinkId("j(5,3)"); + private static final VehicleType VEH_TYPE_LARGE_50 = createVehTypeLarge50(); + private static final VehicleType VEH_TYPE_SMALL_05 = createVehTypeSmall05(); + + + private ExampleTwoEchelonGrid() {} // so it cannot be instantiated + + public static void main(String[] args) { + log.info("Prepare Config"); + Config config = prepareConfig(args); + + log.info("Prepare scenario"); + Scenario scenario = prepareScenario(config); + + log.info("Prepare Controler"); + Controller controller = ControllerUtils.createController(scenario); + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + // bind( CarrierScoringFunctionFactory.class ).toInstance( new MyCarrierScorer()); + final MyEventBasedCarrierScorer carrierScorer = new MyEventBasedCarrierScorer(); + carrierScorer.setToll(TOLL_VALUE); + + bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); + bind(CarrierStrategyManager.class) + .toProvider( + () -> { + CarrierStrategyManager strategyManager = + CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy( + new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + return strategyManager; + }); + bind(LSPStrategyManager.class) + .toProvider( + () -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy( + new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + return strategyManager; + }); + bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); + } + }); + + log.info("Run MATSim"); + log.warn("Runs settings were: Demand: {}\n CarrierCosts: {}\n HubCosts: " + HUBCOSTS_FIX + "\n tollValue: " + TOLL_VALUE, demandSetting, costSetting); + + // The VSP default settings are designed for person transport simulation. After talking to Kai, + // they will be set to WARN here. Kai MT may'23 + controller + .getConfig() + .vspExperimental() + .setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + log.info("Some results ...."); + + for (LSP lsp : LSPUtils.getLSPs(controller.getScenario()).getLSPs().values()) { + ResourceImplementationUtils.printScores(controller.getControlerIO().getOutputPath(), lsp); + ResourceImplementationUtils.printShipmentsOfLSP( + controller.getControlerIO().getOutputPath(), lsp); + ResourceImplementationUtils.printResults_shipmentPlan( + controller.getControlerIO().getOutputPath(), lsp); + ResourceImplementationUtils.printResults_shipmentLog( + controller.getControlerIO().getOutputPath(), lsp); + } + log.info("Done."); + } + + private static Config prepareConfig(String[] args) { + Config config = ConfigUtils.createConfig(); + if (args.length != 0) { + for (String arg : args) { + log.warn(arg); + } + ConfigUtils.applyCommandline(config, args); + + CommandLine cmd = ConfigUtils.getCommandLine(args); + } else { + config + .controller() + .setOutputDirectory( + "output/2echelon_" + + demandSetting + + "_" + + costSetting + + "_" + + HUBCOSTS_FIX + + "_" + + TOLL_VALUE); + config.controller().setLastIteration(2); + } + + config + .network() + .setInputFile( + String.valueOf( + IOUtils.extendUrl( + ExamplesUtils.getTestScenarioURL("freight-chessboard-9x9"), "grid9x9.xml"))); + config + .controller() + .setOverwriteFileSetting( + OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setWriteEventsInterval(1); + + FreightCarriersConfigGroup freightConfig = + ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + return config; + } + + private static Scenario prepareScenario(Config config) { + Scenario scenario = ScenarioUtils.loadScenario(config); + + // Change speed on all links to 30 km/h (8.33333 m/s) for easier computation --> Freeflow TT per + // link is 2min + for (Link link : scenario.getNetwork().getLinks().values()) { + link.setFreespeed(30 / 3.6); + link.setCapacity(1000); + } + + log.info("Add LSP to the scenario"); + LSPUtils.addLSPs(scenario, new LSPs(Collections.singletonList(createLSP(scenario)))); + + return scenario; + } + + private static LSP createLSP(Scenario scenario) { + log.info("create LSP"); + Network network = scenario.getNetwork(); + + LSPPlan lspPlan_direct; + { + log.info("Create lspPlan for direct delivery"); + + Carrier directCarrier = + CarriersUtils.createCarrier(Id.create("directCarrier", Carrier.class)); + directCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + directCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("directTruck"), DEPOT_LINK_ID, VEH_TYPE_LARGE_50)); + LSPResource directCarrierRessource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + directCarrier) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement directCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("directCarrierLSE", LogisticChainElement.class)) + .setResource(directCarrierRessource) + .build(); + + LogisticChain solution_direct = + LSPUtils.LogisticChainBuilder.newInstance( + Id.create("directSolution", LogisticChain.class)) + .addLogisticChainElement(directCarrierElement) + .build(); + + final InitialShipmentAssigner singleSolutionShipmentAssigner = + ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + lspPlan_direct = + LSPUtils.createLSPPlan() + .addLogisticChain(solution_direct) + .setInitialShipmentAssigner(singleSolutionShipmentAssigner); + } + + LSPPlan lspPlan_withHub; + { + log.info("Create lspPlan with Hub"); + + Carrier mainCarrier = CarriersUtils.createCarrier(Id.create("mainCarrier", Carrier.class)); + mainCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + mainCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("mainTruck"), DEPOT_LINK_ID, VEH_TYPE_LARGE_50)); + LSPResource mainCarrierRessource = + ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainCarrier) + .setFromLinkId(DEPOT_LINK_ID) + .setMainRunCarrierScheduler( + ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setToLinkId(HUB_LINK_ID) + .setVehicleReturn(ResourceImplementationUtils.VehicleReturn.returnToFromLink) + .build(); + + LogisticChainElement mainCarrierLSE = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("mainCarrierLSE", LogisticChainElement.class)) + .setResource(mainCarrierRessource) + .build(); + + // The scheduler for the first reloading point is created --> this will be the depot in this + // use case + LSPResourceScheduler hubScheduler = + ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed(10) // Time needed, fixed (for Scheduler) + .setCapacityNeedLinear(1) // additional time needed per shipmentSize (for Scheduler) + .build(); + + // The scheduler is added to the Resource and the Resource is created + LSPResource hubResource = + ResourceImplementationUtils.TransshipmentHubBuilder.newInstance( + Id.create("Hub", LSPResource.class), HUB_LINK_ID, scenario) + .setTransshipmentHubScheduler(hubScheduler) + .build(); + LSPUtils.setFixedCost( + hubResource, HUBCOSTS_FIX); // Set fixed costs (per day) for the availability of the hub. + + LogisticChainElement hubLSE = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("HubLSE", LogisticChainElement.class)) + .setResource(hubResource) + .build(); // Nicht unbedingt nötig, aber nehme den alten Hub nun als Depot. Waren + // werden dann dort "Zusammengestellt". + + Carrier distributionCarrier = + CarriersUtils.createCarrier(Id.create("distributionCarrier", Carrier.class)); + distributionCarrier + .getCarrierCapabilities() + .setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + final VehicleType vehType; + switch (costSetting) { + case sameCost -> vehType = VEH_TYPE_LARGE_50; + case lowerCost4LastMile -> vehType = VEH_TYPE_SMALL_05; + default -> throw new IllegalStateException("Unexpected value: " + costSetting); + } + CarriersUtils.addCarrierVehicle( + distributionCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("distributionTruck"), HUB_LINK_ID, vehType)); + LSPResource distributionCarrierRessource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + distributionCarrier) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement distributionCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("distributionCarrierLSE", LogisticChainElement.class)) + .setResource(distributionCarrierRessource) + .build(); + + // Kettenbildung per hand, damit dann klar ist, wie das Scheduling ablaufen soll. TODO: + // Vielleicht bekommt man das noch eleganter hin. + // z.B. in der Reihenfolge in der die solutionsElements der LogisticsSolution zugeordnet + // werden: ".addSolutionElement(..)" + mainCarrierLSE.connectWithNextElement(hubLSE); + hubLSE.connectWithNextElement(distributionCarrierElement); + + LogisticChain solution_withHub = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("hubSolution", LogisticChain.class)) + .addLogisticChainElement(mainCarrierLSE) + .addLogisticChainElement(hubLSE) + .addLogisticChainElement(distributionCarrierElement) + .build(); + + lspPlan_withHub = + LSPUtils.createLSPPlan() + .addLogisticChain(solution_withHub) + .setInitialShipmentAssigner(ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner()); + } + + // Todo: Auch das ist wirr: Muss hier alle sammeln, damit man die dann im LSPBuilder dem + // SolutionScheduler mitgeben kann. Im Nachgang packt man dann aber erst den zweiten Plan dazu + // ... urgs KMT'Jul22 + List lspPlans = new ArrayList<>(); + lspPlans.add(lspPlan_withHub); + lspPlans.add(lspPlan_direct); + + LSP lsp = + LSPUtils.LSPBuilder.getInstance(Id.create("myLSP", LSP.class)) + .setInitialPlan(lspPlan_direct) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + createResourcesListFromLSPPlans(lspPlans))) + .build(); + lsp.addPlan(lspPlan_withHub); // add the second plan to the lsp + + log.info("create initial LSPShipments"); + log.info("assign the shipments to the LSP"); + for (LspShipment lspShipment : createInitialLSPShipments(network)) { + lsp.assignShipmentToLSP(lspShipment); + } + + log.info("schedule the LSP with the shipments and according to the scheduler of the Resource"); + lsp.scheduleLogisticChains(); + + return lsp; + } + + private static Collection createInitialLSPShipments(Network network) { + List shipmentList = new ArrayList<>(); + + switch (demandSetting) { + case oneCustomer -> { + Id id = Id.create("Shipment_" + 1, LspShipment.class); + int capacityDemand = 1; + + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + + builder.setCapacityDemand(capacityDemand); + builder.setFromLinkId(DEPOT_LINK_ID); + builder.setToLinkId(Id.createLinkId("i(5,5)R")); + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + shipmentList.add(builder.build()); + + return shipmentList; + } + case tenCustomers -> { + Random rand1 = MatsimRandom.getLocalInstance(); + Random rand2 = MatsimRandom.getLocalInstance(); + + List zoneLinkList = + Arrays.asList( + "i(4,4)", "i(5,4)", "i(6,4)", "i(4,6)", "i(5,6)", "i(6,6)", "j(3,5)", "j(3,6)", + "j(3,7)", "j(5,5)", "j(5,6)", "j(5,7)", "i(4,5)R", "i(5,5)R", "i(6,5)R", "i(4,7)R", + "i(5,7)R", "i(6,7)R", "j(4,5)R", "j(4,6)R", "j(4,7)R", "j(6,5)R", "j(6,6)R", + "j(6,7)R"); + for (String linkIdString : zoneLinkList) { + if (!network.getLinks().containsKey(Id.createLinkId(linkIdString))) { + throw new RuntimeException("Link is not in Network!"); + } + } + + for (int i = 1; i <= 10; i++) { + Id id = Id.create("Shipment_" + i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = + LspShipmentUtils.LspShipmentBuilder.newInstance(id); + + int capacityDemand = + rand1.nextInt(5) + 1; // Random is drawn from 0 (incl) to bound (excl) -> adding 1. + builder.setCapacityDemand(capacityDemand); + + builder.setFromLinkId(DEPOT_LINK_ID); + final Id toLinkId = + Id.createLinkId(zoneLinkList.get(rand2.nextInt(zoneLinkList.size() - 1))); + builder.setToLinkId(toLinkId); + + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + shipmentList.add(builder.build()); + } + return shipmentList; + } + default -> throw new IllegalStateException("Unexpected value: " + demandSetting); + } + } + + // TODO: This is maybe something that can go into a utils class ... KMT jul22 + private static List createResourcesListFromLSPPlans(List lspPlans) { + log.info("Collecting all LSPResources from the LSPPlans"); + List resourcesList = + new ArrayList<>(); // TODO: Mache daraus ein Set, damit jede Resource nur einmal drin ist? + // kmt Feb22 + for (LSPPlan lspPlan : lspPlans) { + for (LogisticChain solution : lspPlan.getLogisticChains()) { + for (LogisticChainElement solutionElement : solution.getLogisticChainElements()) { + resourcesList.add(solutionElement.getResource()); + } + } + } + return resourcesList; + } + + enum DemandSetting { + oneCustomer, + tenCustomers + } + + enum CarrierCostSetting { + sameCost, + lowerCost4LastMile + } + + + private static VehicleType createVehTypeLarge50() { + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("large50", VehicleType.class), TransportMode.car); + vehicleType.getCapacity().setOther(50); + vehicleType.getCostInformation().setCostsPerMeter(0.01); + vehicleType.getCostInformation().setCostsPerSecond(0.01); + vehicleType.getCostInformation().setFixedCost(150.); + vehicleType.setMaximumVelocity(10); + vehicleType.setNetworkMode(TransportMode.car); + + return vehicleType; + } + + private static VehicleType createVehTypeSmall05() { + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("small05", VehicleType.class), TransportMode.car); + vehicleType.getCapacity().setOther(5); + vehicleType.getCostInformation().setCostsPerMeter(0.001); + vehicleType.getCostInformation().setCostsPerSecond(0.005); + vehicleType.getCostInformation().setFixedCost(25.); + vehicleType.setMaximumVelocity(10); + vehicleType.setNetworkMode(TransportMode.car); + + return vehicleType; + } + + // @Override public ScoringFunction createScoringFunction(Carrier carrier ){ + // + // return new ScoringFunction(){ + // + // private double score; + // + // @Override public void handleActivity( Activity activity ){ + // score--; + // } + // @Override public void handleLeg( Leg leg ){ + // score = score - 10; + // } + // @Override public void agentStuck( double time ){ + // } + // @Override public void addMoney( double amount ){ + // } + // @Override public void addScore( double amount ){ + // } + // @Override public void finish(){ + // } + // @Override public double getScore(){ + // return score; + // } + // @Override public void handleEvent( Event event ){ + // score = score - 0.01; + // } + // }; + // } + // } + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleTwoEchelonGrid_NR.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleTwoEchelonGrid_NR.java new file mode 100644 index 00000000000..ffaf4c0aa48 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/ExampleTwoEchelonGrid_NR.java @@ -0,0 +1,544 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.initialPlans; + +import java.util.*; +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.Scenario; +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.config.CommandLine; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.*; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.BestPlanSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.io.LSPPlanXmlReader; +import org.matsim.freight.logistics.io.LSPPlanXmlWriter; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +/** + * This is an academic example for the 2-echelon problem. It uses the 9x9-grid network from the + * matsim-examples. + * + *

The depot is located at the outer border of the network, while the jobs are located in the + * middle area. The {@link LSP} has two different {@link LSPPlan}s: 1) direct delivery from the + * depot 2) Using a TransshipmentHubResource: All goods were brought from the depot to the hub, + * reloaded and then brought from the hub to the customers + * + *

The decision which of these plans is chosen should be made via the Score of the plans. We will + * modify the costs of the vehicles and/or for using(having) the Transshipment hub. Depending on + * this setting, the plan selection should be done accordingly. + * + *

Please note: This example is in part on existing examples, but I start from the scratch for a) + * see, if this works and b) have a "clean" class :) + * + * @author Kai Martins-Turner (kturner) + */ +final class ExampleTwoEchelonGrid_NR { + + // Run Settings + static final double HUBCOSTS_FIX = 100; + private static final DemandSetting demandSetting = DemandSetting.tenCustomers; + private static final CarrierCostSetting costSetting = CarrierCostSetting.lowerCost4LastMile; + private static final double TOLL_VALUE = 1000; + + private static final Logger log = LogManager.getLogger(ExampleTwoEchelonGrid_NR.class); + + private static final Id DEPOT_LINK_ID = Id.createLinkId("i(5,0)"); + private static final Id HUB_LINK_ID = Id.createLinkId("j(5,3)"); + + private static final VehicleType VEH_TYPE_LARGE_50 = createVehTypeLarge50(); + private static final VehicleType VEH_TYPE_SMALL_05 = createVehTypeSmall05(); + + private static VehicleType createVehTypeLarge50() { + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("large50", VehicleType.class), TransportMode.car); + vehicleType.getCapacity().setOther(50); + vehicleType.getCostInformation().setCostsPerMeter(0.01); + vehicleType.getCostInformation().setCostsPerSecond(0.01); + vehicleType.getCostInformation().setFixedCost(150.); + vehicleType.setMaximumVelocity(10); + vehicleType.setNetworkMode(TransportMode.car); + + return vehicleType; + } + + private static VehicleType createVehTypeSmall05() { + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("small05", VehicleType.class), TransportMode.car); + vehicleType.getCapacity().setOther(5); + vehicleType.getCostInformation().setCostsPerMeter(0.001); + vehicleType.getCostInformation().setCostsPerSecond(0.005); + vehicleType.getCostInformation().setFixedCost(25.); + vehicleType.setMaximumVelocity(10); + vehicleType.setNetworkMode(TransportMode.car); + + return vehicleType; + } + + private ExampleTwoEchelonGrid_NR() {} // so it cannot be instantiated + + public static void main(String[] args) { + log.info("Prepare Config"); + Config config = prepareConfig(args); + + log.info("Prepare scenario"); + Scenario scenario = prepareScenario(config); + + log.info("Prepare Controler"); + Controller controller = ControllerUtils.createController(scenario); + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + // bind( CarrierScoringFunctionFactory.class ).toInstance( new MyCarrierScorer()); + final MyEventBasedCarrierScorer carrierScorer = new MyEventBasedCarrierScorer(); + carrierScorer.setToll(TOLL_VALUE); + + bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); + bind(CarrierStrategyManager.class) + .toProvider( + () -> { + CarrierStrategyManager strategyManager = + CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy( + new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + return strategyManager; + }); + bind(LSPStrategyManager.class) + .toProvider( + () -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy( + new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + return strategyManager; + }); + bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); + } + }); + + log.info("Run MATSim"); + log.warn("Runs settings were: Demand: {}\n CarrierCosts: {}\n HubCosts: " + HUBCOSTS_FIX + "\n tollValue: " + TOLL_VALUE, demandSetting, costSetting); + // The VSP default settings are designed for person transport simulation. After talking to Kai, + // they will be set to WARN here. Kai MT may'23 + controller + .getConfig() + .vspExperimental() + .setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + // Ggf. muss der Ordner noch erstellt werden (?) + new LSPPlanXmlWriter(LSPUtils.getLSPs(controller.getScenario())) + .write(controller.getConfig().controller().getOutputDirectory() + "/lsps.xml"); + new LSPPlanXmlReader( + LSPUtils.getLSPs(controller.getScenario()), + CarriersUtils.getCarriers(controller.getScenario())); + new CarrierPlanWriter(CarriersUtils.getCarriers(controller.getScenario())) + .write(controller.getConfig().controller().getOutputDirectory() + "/carriers.xml"); + + log.info("Some results ...."); + + for (LSP lsp : LSPUtils.getLSPs(controller.getScenario()).getLSPs().values()) { + ResourceImplementationUtils.printScores(controller.getControlerIO().getOutputPath(), lsp); + ResourceImplementationUtils.printShipmentsOfLSP( + controller.getControlerIO().getOutputPath(), lsp); + ResourceImplementationUtils.printResults_shipmentPlan( + controller.getControlerIO().getOutputPath(), lsp); + ResourceImplementationUtils.printResults_shipmentLog( + controller.getControlerIO().getOutputPath(), lsp); + } + log.info("Done."); + } + + private static Config prepareConfig(String[] args) { + Config config = ConfigUtils.createConfig(); + if (args.length != 0) { + for (String arg : args) { + log.warn(arg); + } + ConfigUtils.applyCommandline(config, args); + + CommandLine cmd = ConfigUtils.getCommandLine(args); + } else { + config + .controller() + .setOutputDirectory( + "output/2echelon_" + + demandSetting + + "_" + + costSetting + + "_" + + HUBCOSTS_FIX + + "_" + + TOLL_VALUE); + config.controller().setLastIteration(2); + } + + config + .network() + .setInputFile( + String.valueOf( + IOUtils.extendUrl( + ExamplesUtils.getTestScenarioURL("freight-chessboard-9x9"), "grid9x9.xml"))); + config + .controller() + .setOverwriteFileSetting( + OutputDirectoryHierarchy.OverwriteFileSetting.overwriteExistingFiles); + config.controller().setWriteEventsInterval(1); + + FreightCarriersConfigGroup freightConfig = + ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + return config; + } + + private static Scenario prepareScenario(Config config) { + Scenario scenario = ScenarioUtils.loadScenario(config); + + // Change speed on all links to 30 km/h (8.33333 m/s) for easier computation --> Freeflow TT per + // link is 2min + for (Link link : scenario.getNetwork().getLinks().values()) { + link.setFreespeed(30 / 3.6); + link.setCapacity(1000); + } + + log.info("Add LSP to the scenario"); + LSPUtils.addLSPs(scenario, new LSPs(Collections.singletonList(createLSP(scenario)))); + + return scenario; + } + + private static LSP createLSP(Scenario scenario) { + log.info("create LSP"); + Network network = scenario.getNetwork(); + + LSPPlan lspPlan_direct; + { + log.info("Create lspPlan for direct delivery"); + + Carrier directCarrier = + CarriersUtils.createCarrier(Id.create("directCarrier", Carrier.class)); + directCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + directCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("directTruck"), DEPOT_LINK_ID, VEH_TYPE_LARGE_50)); + LSPResource directCarrierRessource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + directCarrier) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement directCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("directCarrierLSE", LogisticChainElement.class)) + .setResource(directCarrierRessource) + .build(); + + LogisticChain solution_direct = + LSPUtils.LogisticChainBuilder.newInstance( + Id.create("directSolution", LogisticChain.class)) + .addLogisticChainElement(directCarrierElement) + .build(); + + final InitialShipmentAssigner singleSolutionShipmentAssigner = + ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + lspPlan_direct = + LSPUtils.createLSPPlan() + .addLogisticChain(solution_direct) + .setInitialShipmentAssigner(singleSolutionShipmentAssigner); + } + + LSPPlan lspPlan_withHub; + { + log.info("Create lspPlan with Hub"); + + Carrier mainCarrier = CarriersUtils.createCarrier(Id.create("mainCarrier", Carrier.class)); + mainCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + mainCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("mainTruck"), DEPOT_LINK_ID, VEH_TYPE_LARGE_50)); + LSPResource mainCarrierRessource = + ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainCarrier) + .setFromLinkId(DEPOT_LINK_ID) + .setMainRunCarrierScheduler( + ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setToLinkId(HUB_LINK_ID) + .setVehicleReturn(ResourceImplementationUtils.VehicleReturn.returnToFromLink) + .build(); + + LogisticChainElement mainCarrierLSE = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("mainCarrierLSE", LogisticChainElement.class)) + .setResource(mainCarrierRessource) + .build(); + + // The scheduler for the first reloading point is created --> this will be the depot in this + // use case + LSPResourceScheduler hubScheduler = + ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed(10) // Time needed, fixed (for Scheduler) + .setCapacityNeedLinear(1) // additional time needed per shipmentSize (for Scheduler) + .build(); + + // The scheduler is added to the Resource and the Resource is created + LSPResource hubResource = + ResourceImplementationUtils.TransshipmentHubBuilder.newInstance( + Id.create("Hub", LSPResource.class), HUB_LINK_ID, scenario) + .setTransshipmentHubScheduler(hubScheduler) + .build(); + LSPUtils.setFixedCost( + hubResource, HUBCOSTS_FIX); // Set fixed costs (per day) for the availability of the hub. + + LogisticChainElement hubLSE = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("HubLSE", LogisticChainElement.class)) + .setResource(hubResource) + .build(); // Nicht unbedingt nötig, aber nehme den alten Hub nun als Depot. Waren + // werden dann dort "Zusammengestellt". + + Carrier distributionCarrier = + CarriersUtils.createCarrier(Id.create("distributionCarrier", Carrier.class)); + distributionCarrier + .getCarrierCapabilities() + .setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + final VehicleType vehType; + switch (costSetting) { + case sameCost -> vehType = VEH_TYPE_LARGE_50; + case lowerCost4LastMile -> vehType = VEH_TYPE_SMALL_05; + default -> throw new IllegalStateException("Unexpected value: " + costSetting); + } + CarriersUtils.addCarrierVehicle( + distributionCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("distributionTruck"), HUB_LINK_ID, vehType)); + LSPResource distributionCarrierRessource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + distributionCarrier) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement distributionCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("distributionCarrierLSE", LogisticChainElement.class)) + .setResource(distributionCarrierRessource) + .build(); + + // Kettenbildung per hand, damit dann klar ist, wie das Scheduling ablaufen soll. TODO: + // Vielleicht bekommt man das noch eleganter hin. + // z.B. in der Reihenfolge in der die solutionsElements der LogisticsSolution zugeordnet + // werden: ".addSolutionElement(..)" + mainCarrierLSE.connectWithNextElement(hubLSE); + hubLSE.connectWithNextElement(distributionCarrierElement); + + LogisticChain solution_withHub = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("hubSolution", LogisticChain.class)) + .addLogisticChainElement(mainCarrierLSE) + .addLogisticChainElement(hubLSE) + .addLogisticChainElement(distributionCarrierElement) + .build(); + + lspPlan_withHub = + LSPUtils.createLSPPlan() + .addLogisticChain(solution_withHub) + .setInitialShipmentAssigner(ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner()); + } + + // Todo: Auch das ist wirr: Muss hier alle sammeln, damit man die dann im LSPBuilder dem + // SolutionScheduler mitgeben kann. Im Nachgang packt man dann aber erst den zweiten Plan dazu + // ... urgs KMT'Jul22 + List lspPlans = new ArrayList<>(); + lspPlans.add(lspPlan_withHub); + lspPlans.add(lspPlan_direct); + + LSP lsp = + LSPUtils.LSPBuilder.getInstance(Id.create("myLSP", LSP.class)) + .setInitialPlan(lspPlan_direct) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + createResourcesListFromLSPPlans(lspPlans))) + .build(); + lsp.addPlan(lspPlan_withHub); // add the second plan to the lsp + + log.info("create initial LSPShipments"); + log.info("assign the shipments to the LSP"); + for (LspShipment lspShipment : createInitialLSPShipments(network)) { + lsp.assignShipmentToLSP(lspShipment); + } + + log.info("schedule the LSP with the shipments and according to the scheduler of the Resource"); + lsp.scheduleLogisticChains(); + + return lsp; + } + + private static Collection createInitialLSPShipments(Network network) { + List shipmentList = new ArrayList<>(); + + switch (demandSetting) { + case oneCustomer -> { + Id id = Id.create("Shipment_" + 1, LspShipment.class); + int capacityDemand = 1; + + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + + builder.setCapacityDemand(capacityDemand); + builder.setFromLinkId(DEPOT_LINK_ID); + builder.setToLinkId(Id.createLinkId("i(5,5)R")); + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + shipmentList.add(builder.build()); + + return shipmentList; + } + case tenCustomers -> { + Random rand1 = MatsimRandom.getLocalInstance(); + Random rand2 = MatsimRandom.getLocalInstance(); + + List zoneLinkList = + Arrays.asList( + "i(4,4)", "i(5,4)", "i(6,4)", "i(4,6)", "i(5,6)", "i(6,6)", "j(3,5)", "j(3,6)", + "j(3,7)", "j(5,5)", "j(5,6)", "j(5,7)", "i(4,5)R", "i(5,5)R", "i(6,5)R", "i(4,7)R", + "i(5,7)R", "i(6,7)R", "j(4,5)R", "j(4,6)R", "j(4,7)R", "j(6,5)R", "j(6,6)R", + "j(6,7)R"); + for (String linkIdString : zoneLinkList) { + if (!network.getLinks().containsKey(Id.createLinkId(linkIdString))) { + throw new RuntimeException("Link is not in Network!"); + } + } + + for (int i = 1; i <= 10; i++) { + Id id = Id.create("Shipment_" + i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = + LspShipmentUtils.LspShipmentBuilder.newInstance(id); + + int capacityDemand = + rand1.nextInt(5) + 1; // Random is drawn from 0 (incl) to bound (excl) -> adding 1. + builder.setCapacityDemand(capacityDemand); + + builder.setFromLinkId(DEPOT_LINK_ID); + final Id toLinkId = + Id.createLinkId(zoneLinkList.get(rand2.nextInt(zoneLinkList.size() - 1))); + builder.setToLinkId(toLinkId); + + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + shipmentList.add(builder.build()); + } + return shipmentList; + } + default -> throw new IllegalStateException("Unexpected value: " + demandSetting); + } + } + + // TODO: This is maybe something that can go into a utils class ... KMT jul22 + private static List createResourcesListFromLSPPlans(List lspPlans) { + log.info("Collecting all LSPResources from the LSPPlans"); + List resourcesList = + new ArrayList<>(); // TODO: Mache daraus ein Set, damit jede Resource nur einmal drin ist? + // kmt Feb22 + for (LSPPlan lspPlan : lspPlans) { + for (LogisticChain solution : lspPlan.getLogisticChains()) { + for (LogisticChainElement solutionElement : solution.getLogisticChainElements()) { + resourcesList.add(solutionElement.getResource()); + } + } + } + return resourcesList; + } + + enum DemandSetting { + oneCustomer, + tenCustomers + } + + enum CarrierCostSetting { + sameCost, + lowerCost4LastMile + } + + // @Override public ScoringFunction createScoringFunction(Carrier carrier ){ + // + // return new ScoringFunction(){ + // + // private double score; + // + // @Override public void handleActivity( Activity activity ){ + // score--; + // } + // @Override public void handleLeg( Leg leg ){ + // score = score - 10; + // } + // @Override public void agentStuck( double time ){ + // } + // @Override public void addMoney( double amount ){ + // } + // @Override public void addScore( double amount ){ + // } + // @Override public void finish(){ + // } + // @Override public double getScore(){ + // return score; + // } + // @Override public void handleEvent( Event event ){ + // score = score - 0.01; + // } + // }; + // } + // } + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/MyCarrierScorer.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/MyCarrierScorer.java new file mode 100644 index 00000000000..83b1fa4dc3a --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/MyCarrierScorer.java @@ -0,0 +1,61 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.initialPlans; + +import org.matsim.core.scoring.ScoringFunction; +import org.matsim.core.scoring.SumScoringFunction; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; + +/** + * @author Kai Martins-Turner (kturner) + */ +class MyCarrierScorer implements CarrierScoringFunctionFactory { + + public ScoringFunction createScoringFunction(Carrier carrier) { + SumScoringFunction sf = new SumScoringFunction(); + TakeJspritScore takeJspritScore = new TakeJspritScore(carrier); + sf.addScoringFunction(takeJspritScore); + return sf; + } + + private class TakeJspritScore implements SumScoringFunction.BasicScoring { + + private final Carrier carrier; + + public TakeJspritScore(Carrier carrier) { + super(); + this.carrier = carrier; + } + + @Override + public void finish() {} + + @Override + public double getScore() { + if (carrier.getSelectedPlan().getScore() != null) { + return carrier.getSelectedPlan().getScore(); + } + return Double.NEGATIVE_INFINITY; + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/MyEventBasedCarrierScorer.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/MyEventBasedCarrierScorer.java new file mode 100644 index 00000000000..846ecf3b5fe --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/MyEventBasedCarrierScorer.java @@ -0,0 +1,219 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.initialPlans; + +import jakarta.inject.Inject; +import java.util.*; +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.Scenario; +import org.matsim.api.core.v01.events.Event; +import org.matsim.api.core.v01.events.LinkEnterEvent; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.scoring.ScoringFunction; +import org.matsim.core.scoring.SumScoringFunction; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.Tour; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.events.CarrierTourEndEvent; +import org.matsim.freight.carriers.events.CarrierTourStartEvent; +import org.matsim.freight.logistics.examples.ExampleConstants; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +/** + * @author Kai Martins-Turner (kturner) + */ +class MyEventBasedCarrierScorer implements CarrierScoringFunctionFactory { + + @Inject private Network network; + + @Inject private Scenario scenario; + + private double toll; + + public ScoringFunction createScoringFunction(Carrier carrier) { + SumScoringFunction sf = new SumScoringFunction(); + sf.addScoringFunction(new EventBasedScoring()); + sf.addScoringFunction(new LinkBasedTollScoring(toll, List.of("large50"))); + return sf; + } + + void setToll(double toll) { + this.toll = toll; + } + + /** + * Calculate the carrier's score based on Events. Currently, it includes: - fixed costs (using + * CarrierTourEndEvent) - time-dependent costs (using FreightTourStart- and -EndEvent) - + * distance-dependent costs (using LinkEnterEvent) + */ + private class EventBasedScoring implements SumScoringFunction.ArbitraryEventScoring { + + final Logger log = LogManager.getLogger(EventBasedScoring.class); + private final double MAX_SHIFT_DURATION = 8 * 3600; + private final Map vehicleType2TourDuration = new LinkedHashMap<>(); + private final Map vehicleType2ScoredFixCosts = new LinkedHashMap<>(); + private final Map, Double> tourStartTime = new LinkedHashMap<>(); + private double score; + + public EventBasedScoring() { + super(); + } + + @Override + public void finish() {} + + @Override + public double getScore() { + return score; + } + + @Override + public void handleEvent(Event event) { + log.debug(event.toString()); + switch (event) { + case CarrierTourStartEvent freightTourStartEvent -> handleEvent(freightTourStartEvent); + case CarrierTourEndEvent freightTourEndEvent -> handleEvent(freightTourEndEvent); + case LinkEnterEvent linkEnterEvent -> handleEvent(linkEnterEvent); + default -> { + } + } + } + + private void handleEvent(CarrierTourStartEvent event) { + // Save time of freight tour start + tourStartTime.put(event.getTourId(), event.getTime()); + } + + // Fix costs for vehicle usage + private void handleEvent(CarrierTourEndEvent event) { + // Fix costs for vehicle usage + final VehicleType vehicleType = + (VehicleUtils.findVehicle(event.getVehicleId(), scenario)).getType(); + + double tourDuration = event.getTime() - tourStartTime.get(event.getTourId()); + { // limit fixed costs of vehicles if vehicles could be reused during shift + if (tourDuration > MAX_SHIFT_DURATION) { + throw new RuntimeException( + "Duration of tour is longer than max shift defined in scoring fct, caused by event:" + + event + + " tourDuration: " + + tourDuration + + " max shift duration: " + + MAX_SHIFT_DURATION); + } + + // sum up tour durations + if (vehicleType2TourDuration.containsKey(vehicleType)) { + vehicleType2TourDuration.put( + vehicleType, vehicleType2TourDuration.get(vehicleType) + tourDuration); + } else { + vehicleType2TourDuration.put(vehicleType, tourDuration); + } + + // scoring needed? + final double currentNuOfVehiclesNeeded = + Math.ceil(vehicleType2TourDuration.get(vehicleType) / MAX_SHIFT_DURATION); + final Integer nuAlreadyScored = vehicleType2ScoredFixCosts.get(vehicleType); + if (nuAlreadyScored == null) { + log.info("Score fixed costs for vehicle type: {}", vehicleType.getId().toString()); + score = score - vehicleType.getCostInformation().getFixedCosts(); + vehicleType2ScoredFixCosts.put(vehicleType, 1); + } else if (currentNuOfVehiclesNeeded > nuAlreadyScored) { + log.info("Score fixed costs for vehicle type: {}", vehicleType.getId().toString()); + score = score - vehicleType.getCostInformation().getFixedCosts(); + vehicleType2ScoredFixCosts.put( + vehicleType, vehicleType2ScoredFixCosts.get(vehicleType) + 1); + } + } + + // variable costs per time + score = score - (tourDuration * vehicleType.getCostInformation().getCostsPerSecond()); + } + + private void handleEvent(LinkEnterEvent event) { + final double distance = network.getLinks().get(event.getLinkId()).getLength(); + final double costPerMeter = + (VehicleUtils.findVehicle(event.getVehicleId(), scenario)) + .getType() + .getCostInformation() + .getCostsPerMeter(); + // variable costs per distance + score = score - (distance * costPerMeter); + } + } + + /** + * Calculate some toll for driving on a link This a lazy implementation of a cordon toll. A + * vehicle is only tolled once. + */ + class LinkBasedTollScoring implements SumScoringFunction.ArbitraryEventScoring { + + final Logger log = LogManager.getLogger(EventBasedScoring.class); + + private final double toll; + private final List vehicleTypesToBeTolled; + private final List> tolledVehicles = new ArrayList<>(); + private double score; + + public LinkBasedTollScoring(double toll, List vehicleTypesToBeTolled) { + super(); + this.toll = toll; + this.vehicleTypesToBeTolled = vehicleTypesToBeTolled; + } + + @Override + public void finish() {} + + @Override + public double getScore() { + return score; + } + + @Override + public void handleEvent(Event event) { + if (event instanceof LinkEnterEvent linkEnterEvent) { + handleEvent(linkEnterEvent); + } + } + + private void handleEvent(LinkEnterEvent event) { + List tolledLinkList = ExampleConstants.TOLLED_LINK_LIST_GRID; + + final Id vehicleTypeId = + (VehicleUtils.findVehicle(event.getVehicleId(), scenario)).getType().getId(); + + // toll a vehicle only once. + if (!tolledVehicles.contains(event.getVehicleId())) + if (vehicleTypesToBeTolled.contains(vehicleTypeId.toString())) { + if (tolledLinkList.contains(event.getLinkId().toString())) { + log.info("Tolling caused by event: {}", event); + tolledVehicles.add(event.getVehicleId()); + score = score - toll; + } + } + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/MyLSPScorer.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/MyLSPScorer.java new file mode 100644 index 00000000000..3a70e72d252 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/initialPlans/MyLSPScorer.java @@ -0,0 +1,103 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.initialPlans; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.TransshipmentHubResource; + +/** + * A scorer for the LSP. It uses the scores of the - carriers: Take the carrier's score and add it + * to the LSP's score - hubs: currently a very simple fixed costs scoring (see below {@link + * #scoreHub()}) + * + * @author Kai Martins-Turner (kturner) + */ +/*package-private*/ class MyLSPScorer implements LSPScorer { + final Logger logger = LogManager.getLogger(MyLSPScorer.class); + private double score = 0; + private LSP lsp; + + @Override + public void reset(int iteration) { + score = 0.; + } + + @Override + public double getScoreForCurrentPlan() { + scoreLspCarriers(); + scoreHub(); + scoreMissingShipments(); + return score; + } + + private void scoreLspCarriers() { + var lspPlan = lsp.getSelectedPlan(); + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + for (LogisticChainElement logisticChainElement : logisticChain.getLogisticChainElements()) { + if (logisticChainElement.getResource() instanceof LSPCarrierResource carrierResource) { + var carriersScore = carrierResource.getCarrier().getSelectedPlan().getScore(); + if (carriersScore != null) { + score = score + carriersScore; + } + } + } + } + } + + /** + * If a hub resource is in the selected plan of the LSP, it will get scored. + * + *

This is somehow a quickfix, because the hubs do **not** have any own events yet. This needs + * to be implemented later KMT oct'22 + */ + private void scoreHub() { + var lspPlan = lsp.getSelectedPlan(); + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + for (LogisticChainElement logisticChainElement : logisticChain.getLogisticChainElements()) { + if (logisticChainElement.getResource() instanceof TransshipmentHubResource hub) { + score = score - LSPUtils.getFixedCost(hub); + } + } + } + } + + private void scoreMissingShipments() { + LSPPlan lspPlan = lsp.getSelectedPlan(); + int lspPlanShipmentCount = + lspPlan.getLogisticChains().stream() + .mapToInt(logisticChain -> logisticChain.getLspShipmentIds().size()) + .sum(); + if (lspPlanShipmentCount != lsp.getLspShipments().size()) { + logger.error( + "LspPlan doesn't contain the same number of shipments as LSP, " + + "shipments probably lost during replanning."); + score -= 10000; + } + } + + @Override + public void setEmbeddingContainer(LSP pointer) { + this.lsp = pointer; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspReplanning/AssignmentStrategyFactory.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspReplanning/AssignmentStrategyFactory.java new file mode 100644 index 00000000000..cf2056d9bbc --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspReplanning/AssignmentStrategyFactory.java @@ -0,0 +1,88 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.lspReplanning; + +import org.matsim.core.replanning.GenericPlanStrategy; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.ReplanningContext; +import org.matsim.core.replanning.modules.GenericPlanStrategyModule; +import org.matsim.core.replanning.selectors.RandomPlanSelector; +import org.matsim.freight.logistics.LSP; +import org.matsim.freight.logistics.LSPPlan; +import org.matsim.freight.logistics.LogisticChain; +import org.matsim.freight.logistics.LogisticChainElement; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; + +/** + * @deprecated This class is a work-around. Please do not use this method for any new runs! + *

The plan-handling below was previously done in the LSPControlerListener during replanning. + * Since we (nrichter, kturner) are now running with one replanning strategies, which will allow + * to move shipments within the same (LSP) plan to a different logisticChain. As a consequence, + * the code below is not needed for us (starting from now). More than that, it is in part + * working against the new workflow, because the (re) assignment should **not** be done during + * replanning anymore. + *

The code here is used so that the old stuff from (tm). It keeps this old behaviour (and + * tests passing) with its own strategy, instead running it for everyone. + *

nrichter, kturner Jul'23 + */ +@Deprecated +public class AssignmentStrategyFactory { + + public AssignmentStrategyFactory() {} + + public GenericPlanStrategy createStrategy() { + + GenericPlanStrategyImpl strategy = + new GenericPlanStrategyImpl<>(new RandomPlanSelector<>()); + GenericPlanStrategyModule assignmentModule = + new GenericPlanStrategyModule<>() { + + @Override + public void prepareReplanning(ReplanningContext replanningContext) {} + + @Override + public void handlePlan(LSPPlan lspPlan) { + + for (LogisticChain solution : lspPlan.getLogisticChains()) { + solution.getLspShipmentIds().clear(); + for (LogisticChainElement element : solution.getLogisticChainElements()) { + element.getIncomingShipments().clear(); + element.getOutgoingShipments().clear(); + } + } + + for (LspShipment lspShipment : lspPlan.getLSP().getLspShipments()) { + LspShipmentUtils.getOrCreateShipmentPlan(lspPlan, lspShipment.getId()).clear(); + lspShipment.getShipmentLog().clear(); + lspPlan.getInitialShipmentAssigner().assignToPlan(lspPlan, lspShipment); + } + } + + @Override + public void finishReplanning() {} + }; + + strategy.addStrategyModule(assignmentModule); + return strategy; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspReplanning/ExampleLSPReplanning.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspReplanning/ExampleLSPReplanning.java new file mode 100644 index 00000000000..20bde8fb6a5 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspReplanning/ExampleLSPReplanning.java @@ -0,0 +1,31 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.lspReplanning; + +/** +* Please refer to the + * - org.matsim.freight.logistics.example.lsp.multipleChains.ExampleMultipleOneEchelonChainsReplanning for an example with Replanning + *

+ * - CollectionLSPReplanningTest for an idea, how replanning works (old way -- will be removed in the future). +*/ +@Deprecated +/*package-private*/ class ExampleLSPReplanning {} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspReplanning/MaybeTodayAssigner.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspReplanning/MaybeTodayAssigner.java new file mode 100644 index 00000000000..15850ba29de --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspReplanning/MaybeTodayAssigner.java @@ -0,0 +1,56 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.lspReplanning; + +import java.util.Random; +import org.matsim.core.gbl.Gbl; +import org.matsim.freight.logistics.InitialShipmentAssigner; +import org.matsim.freight.logistics.LSPPlan; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** +* This class is deprecated and will be removed in the future. + * It follows the old and no longer wanted approach. + * Now, an Assigner is used to assign all LSPShipments to one LogisticChain of the LSPPlan. + *

+ * This class here is in contrast used as a Replanning strategy. This behavior is not wanted anymore. + * KMT, Jul'24 +*/ +@Deprecated +/*package-private*/ class MaybeTodayAssigner implements InitialShipmentAssigner { + + private final Random random; + + public MaybeTodayAssigner() { + this.random = new Random(1); + } + + @Override + public void assignToPlan(LSPPlan lspPlan, LspShipment lspShipment) { + boolean assignToday = random.nextBoolean(); + if (assignToday) { + Gbl.assertIf(lspPlan.getLogisticChains().size() == 1); + lspPlan.getLogisticChains().iterator().next().addShipmentToChain(lspShipment); + } + } + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspReplanning/TomorrowShipmentAssignerStrategyFactory.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspReplanning/TomorrowShipmentAssignerStrategyFactory.java new file mode 100644 index 00000000000..2c96a7910b9 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspReplanning/TomorrowShipmentAssignerStrategyFactory.java @@ -0,0 +1,92 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.lspReplanning; + +import java.util.Collection; +import org.matsim.core.replanning.GenericPlanStrategy; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.ReplanningContext; +import org.matsim.core.replanning.modules.GenericPlanStrategyModule; +import org.matsim.core.replanning.selectors.BestPlanSelector; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; + +@Deprecated +/*package-private*/ class TomorrowShipmentAssignerStrategyFactory { + + private final InitialShipmentAssigner assigner; + + /*package-private*/ TomorrowShipmentAssignerStrategyFactory(InitialShipmentAssigner assigner) { + this.assigner = assigner; + } + + /*package-private*/ GenericPlanStrategy createStrategy() { + GenericPlanStrategyImpl strategy = + new GenericPlanStrategyImpl<>(new BestPlanSelector<>()); + + GenericPlanStrategyModule tomorrowModule = + new GenericPlanStrategyModule<>() { + + @Override + public void prepareReplanning(ReplanningContext replanningContext) { + // TODO Auto-generated method stub + + } + + @Override + public void handlePlan(LSPPlan plan) { + plan.getLogisticChains().iterator().next().getLspShipmentIds().clear(); + plan.setInitialShipmentAssigner(assigner); + // LSP lsp = assigner.getLSP(); + LSP lsp = plan.getLSP(); + Collection lspShipments = lsp.getLspShipments(); + for (LspShipment lspShipment : lspShipments) { + assigner.assignToPlan(plan, lspShipment); + } + + for (LogisticChain solution : plan.getLogisticChains()) { + solution.getLspShipmentIds().clear(); + for (LogisticChainElement element : solution.getLogisticChainElements()) { + element.getIncomingShipments().clear(); + element.getOutgoingShipments().clear(); + } + } + + for (LspShipment lspShipment : plan.getLSP().getLspShipments()) { + LspShipmentUtils.getOrCreateShipmentPlan(plan, lspShipment.getId()).clear(); + lspShipment.getShipmentLog().clear(); + plan.getInitialShipmentAssigner().assignToPlan(plan, lspShipment); + } + } + + @Override + public void finishReplanning() { + // TODO Auto-generated method stub + + } + }; + + strategy.addStrategyModule(tomorrowModule); + return strategy; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspReplanning/package-info.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspReplanning/package-info.java new file mode 100644 index 00000000000..3a42f344ada --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspReplanning/package-info.java @@ -0,0 +1,36 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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 * + * * + * *********************************************************************** + */ + +/** + * @deprecated This package is deprecated and will be removed in the future. + * It follows the old and no longer wanted approach. + * Now, an Assigner is used to assign all LSPShipments to one LogisticChain of the LSPPlan. + *

+ * This class here is in contrast used as a Replanning strategy. This behavior is not wanted anymore. + *

+ * Please use the new approach as shown in + * {@link org.matsim.freight.logistics.example.lsp.multipleChains} ExampleMultipleOneEchelonChainsReplanning instead. + * ((The old approach is still available in CollectionLSPReplanningTest but will get removed earlier or later)). + *

+ * KMT, Jul'24 + * */ +@Deprecated +package org.matsim.freight.logistics.examples.lspReplanning; diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspScoring/ExampleLSPScoring.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspScoring/ExampleLSPScoring.java new file mode 100644 index 00000000000..69f9cc76a59 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/lspScoring/ExampleLSPScoring.java @@ -0,0 +1,265 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.lspScoring; + +import java.util.*; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.carriers.events.CarrierServiceEndEvent; +import org.matsim.freight.carriers.events.eventhandler.CarrierServiceEndEventHandler; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +/* Example for customized scoring. Each customer that is visited will give a random tip between zero and five + * + * + */ + +/*package-private*/ final class ExampleLSPScoring { + + private ExampleLSPScoring() {} + + private static LSP createLSPWithScorer(Scenario scenario) { + + // The Carrier for the resource of the sole LogisticsSolutionElement of the LSP is created + final VehicleType carrierVehType = VehicleUtils.createVehicleType( Id.create("CollectionCarrierVehicleType", VehicleType.class), TransportMode.car); + carrierVehType.getCapacity().setOther(10); + carrierVehType.getCostInformation().setCostsPerMeter(0.0004); + carrierVehType.getCostInformation().setCostsPerSecond(0.38); + carrierVehType.getCostInformation().setFixedCost(49.); + carrierVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + + CarrierCapabilities capabilities = + CarrierCapabilities.Builder.newInstance() + .addVehicle(CarrierVehicle.newInstance(Id.createVehicleId("CollectionVehicle"), collectionLinkId, carrierVehType)) + .setFleetSize(FleetSize.INFINITE) + .build(); + + Carrier carrier = CarriersUtils.createCarrier(Id.create("CollectionCarrier", Carrier.class)); + carrier.setCarrierCapabilities(capabilities); + + // The Resource i.e. the Resource is created + // The scheduler for the Resource is created and added. This is where jsprit comes into play. + LSPResource lspResource = + ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance( + carrier) + .setCollectionScheduler( + ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + // The adapter is now inserted into the only LogisticsSolutionElement of the only + // LogisticsSolution of the LSP + LogisticChainElement logisticChainElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(lspResource) + .build(); + + // The LogisticsSolutionElement is now inserted into the only LogisticsSolution of the LSP + LogisticChain logisticChain = + LSPUtils.LogisticChainBuilder.newInstance( + Id.create("CollectionSolution", LogisticChain.class)) + .addLogisticChainElement(logisticChainElement) + .build(); + + // The initial plan of the lsp is generated and the assigner and the solution from above are + // added + LSPPlan lspPlan = + LSPUtils.createLSPPlan() + .setInitialShipmentAssigner(ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner()) + .addLogisticChain(logisticChain); + + // The exogenous list of Resources for the SolutionScheduler is compiled and the Scheduler is + // added to the LSPBuilder + + return LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)) + .setInitialPlan(lspPlan) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + Collections.singletonList(lspResource))) + // .setSolutionScorer(new TipScorer()) + .build(); + } + + private static Collection createInitialLSPShipments(Network network) { + List shipmentList = new ArrayList<>(); + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + + // Create five LSPShipments that are located in the left half of the network. + for (int i = 1; i < 6; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + Random random = new Random(1); + int capacityDemand = random.nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, random); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 + && pendingFromLink.getFromNode().getCoord().getY() <= 4000 + && pendingFromLink.getToNode().getCoord().getX() <= 4000 + && pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + builder.setToLinkId(Id.createLinkId("(4 2) (4 3)")); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + shipmentList.add(builder.build()); + } + return shipmentList; + } + + public static void main(String[] args) { + + Config config = prepareConfig(); + + Scenario scenario = prepareScenario(config); + + Controller controller = prepareController(scenario); + + // The VSP default settings are designed for person transport simulation. After talking to Kai, + // they will be set to WARN here. Kai MT may'23 + controller + .getConfig() + .vspExperimental() + .setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + for (LSP lsp2 : LSPUtils.getLSPs(scenario).getLSPs().values()) { + System.out.println("The tip of all customers was: " + lsp2.getSelectedPlan().getScore()); + } + } + + static Controller prepareController(Scenario scenario) { + // Start the Mobsim one iteration is sufficient for scoring + Controller controller = ControllerUtils.createController(scenario); + controller.addOverridingModule(new LSPModule()); + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + bind(LSPScorerFactory.class).toInstance(TipScorer::new); + } + }); + return controller; + } + + static Scenario prepareScenario(Config config) { + Scenario scenario = ScenarioUtils.loadScenario(config); + + // Create LSP and lspShipments + LSP lsp = createLSPWithScorer(scenario); + Collection lspShipments = createInitialLSPShipments(scenario.getNetwork()); + + // assign the lspShipments to the LSP + for (LspShipment lspShipment : lspShipments) { + lsp.assignShipmentToLSP(lspShipment); + } + + // schedule the LSP with the lspShipments and according to the scheduler of the Resource + lsp.scheduleLogisticChains(); + + // Prepare LSPModule and add the LSP + LSPs lsps = new LSPs(Collections.singletonList(lsp)); + LSPUtils.addLSPs(scenario, lsps); + return scenario; + } + + static Config prepareConfig() { + // Set up required MATSim classes + Config config = ConfigUtils.createConfig(); + + config.network().setInputFile("scenarios/2regions/2regions-network.xml"); + + config.controller().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + return config; + } + + /*package-private*/ static class TipScorer + implements LSPScorer, LSPSimulationTracker, CarrierServiceEndEventHandler { + + private static final Logger log = LogManager.getLogger(TipScorer.class); + + private final Random tipRandom; + private double tipSum; + + /*package-private*/ TipScorer() { + tipRandom = new Random(1); + tipSum = 0; + } + + @Override + public double getScoreForCurrentPlan() { + return tipSum; + } + + @Override + public void setEmbeddingContainer(LSP pointer) { + // backpointer not needed here, therefor not memorizing it. kai, jun'22 + } + + @Override + public void handleEvent(CarrierServiceEndEvent event) { + double tip = tipRandom.nextDouble() * 5; + log.warn("tipSum={}; tip={}", tipSum, tip); + tipSum += tip; + } + + @Override + public void reset(int iteration) { + tipSum = 0.; + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/mobsimExamples/ExampleMobsimOfSimpleLSP.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/mobsimExamples/ExampleMobsimOfSimpleLSP.java new file mode 100644 index 00000000000..59fb551c08b --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/mobsimExamples/ExampleMobsimOfSimpleLSP.java @@ -0,0 +1,263 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.mobsimExamples; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Random; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +/*package-private*/ class ExampleMobsimOfSimpleLSP { + + public static void main(String[] args) { + // Set up required MATSim classes + Config config = new Config(); + config.addCoreModules(); + + if (args.length != 0) { + ConfigUtils.applyCommandline(config, args); + } + + FreightCarriersConfigGroup freightConfig = + ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()) + .readFile("scenarios/2regions/2regions-network.xml"); + + // Create LSP and lspShipments + LSP lsp = createInitialLSP(scenario); + Collection lspShipments = createInitialLSPShipments(scenario.getNetwork()); + + // assign the lspShipments to the LSP + for (LspShipment lspShipment : lspShipments) { + lsp.assignShipmentToLSP(lspShipment); + } + + // schedule the LSP with the lspShipments and according to the scheduler of the Resource + lsp.scheduleLogisticChains(); + + // set up simulation controller and LSPModule + ArrayList lspList = new ArrayList<>(); + lspList.add(lsp); + LSPs lsps = new LSPs(lspList); + LSPUtils.addLSPs(scenario, lsps); + + config.controller().setFirstIteration(0); + config.controller().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.overwriteExistingFiles); + + Controller controller = ControllerUtils.createController(scenario); + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + // The VSP default settings are designed for person transport simulation. After talking to Kai, + // they will be set to WARN here. Kai MT may'23 + controller + .getConfig() + .vspExperimental() + .setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + for (LspShipment lspShipment : lsp.getLspShipments()) { + System.out.println("LspShipment: " + lspShipment.getId()); + ArrayList scheduleElements = + new ArrayList<>( + LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), lspShipment.getId()) + .getPlanElements() + .values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = + new ArrayList<>(lspShipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (int i = 0; + i + < LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), lspShipment.getId()) + .getPlanElements() + .size(); + i++) { + System.out.println( + "Scheduled: " + + scheduleElements.get(i).getLogisticChainElement().getId() + + " " + + scheduleElements.get(i).getResourceId() + + " " + + scheduleElements.get(i).getElementType() + + " Start: " + + scheduleElements.get(i).getStartTime() + + " End: " + + scheduleElements.get(i).getEndTime()); + } + System.out.println(); + for (int i = 0; i < lspShipment.getShipmentLog().getPlanElements().size(); i++) { + System.out.println( + "Logged: " + + logElements.get(i).getLogisticChainElement().getId() + + " " + + logElements.get(i).getResourceId() + + " " + + logElements.get(i).getElementType() + + " Start: " + + logElements.get(i).getStartTime() + + " End: " + + logElements.get(i).getEndTime()); + } + System.out.println(); + } + } + + private static LSP createInitialLSP(Scenario scenario) { + + // The Carrier for the resource of the sole LogisticsSolutionElement of the LSP is created + Id carrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id vollectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle carrierVehicle = + CarrierVehicle.newInstance(vollectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities capabilities = CarrierCapabilities.Builder.newInstance() + .addVehicle(carrierVehicle) + .setFleetSize(FleetSize.INFINITE) + .build(); + + Carrier carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + // The Resource i.e. the Resource is created + LSPResource collectionResource = + ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(carrier) + .setCollectionScheduler( + ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + // The adapter is now inserted into the only LogisticsSolutionElement of the only + // LogisticsSolution of the LSP + LogisticChainElement collectionElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + // The LogisticsSolutionElement is now inserted into the only LogisticsSolution of the LSP + LogisticChain collectionSolution = + LSPUtils.LogisticChainBuilder.newInstance( + Id.create("CollectionSolution", LogisticChain.class)) + .addLogisticChainElement(collectionElement) + .build(); + + // The initial plan of the lsp is generated and the assigner and the solution from above are + // added + LSPPlan collectionPlan = LSPUtils.createLSPPlan(); + InitialShipmentAssigner assigner = + ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + collectionPlan.setInitialShipmentAssigner(assigner); + collectionPlan.addLogisticChain(collectionSolution); + + LSPUtils.LSPBuilder collectionLSPBuilder = + LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + collectionLSPBuilder.setInitialPlan(collectionPlan); + + // The exogenous list of Resources for the SolutionScheduler is compiled and the Scheduler is + // added to the LSPBuilder + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + LogisticChainScheduler simpleScheduler = + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + collectionLSPBuilder.setLogisticChainScheduler(simpleScheduler); + + return collectionLSPBuilder.build(); + } + + private static Collection createInitialLSPShipments(Network network) { + ArrayList shipmentList = new ArrayList<>(); + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + + // Create five LSPShipments that are located in the left half of the network. + for (int i = 1; i < 6; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + Random random = new Random(1); + int capacityDemand = random.nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, random); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 + && pendingFromLink.getFromNode().getCoord().getY() <= 4000 + && pendingFromLink.getToNode().getCoord().getX() <= 4000 + && pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + builder.setToLinkId(Id.createLinkId("(4 2) (4 3)")); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + shipmentList.add(builder.build()); + } + return shipmentList; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/mobsimExamples/ExampleMobsimOfTransportChain.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/mobsimExamples/ExampleMobsimOfTransportChain.java new file mode 100644 index 00000000000..1853cc27331 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/mobsimExamples/ExampleMobsimOfTransportChain.java @@ -0,0 +1,420 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.mobsimExamples; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Random; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +/*package-private*/ class ExampleMobsimOfTransportChain { + + private static LSP createInitialLSP(Scenario scenario) { + + Network network = scenario.getNetwork(); + + // The Carrier for collection is created + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id vollectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle carrierVehicle = + CarrierVehicle.newInstance(vollectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities capabilities = CarrierCapabilities.Builder.newInstance() + .addVehicle(carrierVehicle) + .setFleetSize(FleetSize.INFINITE) + .build(); + + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(capabilities); + + // The collection adapter i.e. the Resource is created + LSPResource collectionResource = + ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance( + collectionCarrier) + .setCollectionScheduler( + ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + // The adapter is now inserted into the corresponding LogisticsSolutionElement of the only + // LogisticsSolution of the LSP + LogisticChainElement collectionElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + // The first reloading adapter i.e. the Resource is created + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + TransshipmentHubBuilder firstTransshipmentHubBuilder = + ResourceImplementationUtils.TransshipmentHubBuilder.newInstance( + firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + + // The scheduler for the first reloading point is created + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = + ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + // The scheduler is added to the Resource and the Resource is created + firstTransshipmentHubBuilder.setTransshipmentHubScheduler( + firstReloadingSchedulerBuilder.build()); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + // The SolutionElement for the first reloading point is created + Id firstHubElementId = + Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = + LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + // The Carrier for the main run Resource is created + final Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + final Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + final VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50 / 3.6); + mainRunVehType.setNetworkMode(TransportMode.car); + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + CarrierCapabilities mainRunCapabilities = + CarrierCapabilities.Builder.newInstance() + .addVehicle(mainRunCarrierVehicle) + .setFleetSize(FleetSize.INFINITE) + .build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + // The adapter i.e. the main run resource is created + LSPResource mainRunResource = + ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .build(); + + // The LogisticsSolutionElement for the main run Resource is created + Id mainRunElementId = + Id.create("MainRunElement", LogisticChainElement.class); + LogisticChainElement mainRunElement = + LSPUtils.LogisticChainElementBuilder.newInstance(mainRunElementId) + .setResource(mainRunResource) + .build(); + + // The second reloading adapter i.e. the Resource is created + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + TransshipmentHubBuilder secondTransshipmentHubBuilder = + ResourceImplementationUtils.TransshipmentHubBuilder.newInstance( + secondTransshipmentHubId, secondTransshipmentHub_LinkId, scenario); + + // The scheduler for the second reloading point is created + TranshipmentHubSchedulerBuilder secondSchedulerBuilder = + ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + secondSchedulerBuilder.setCapacityNeedFixed(10); + secondSchedulerBuilder.setCapacityNeedLinear(1); + + // The scheduler is added to the Resource and the Resource is created + secondTransshipmentHubBuilder.setTransshipmentHubScheduler(secondSchedulerBuilder.build()); + LSPResource secondTranshipmentHubResource = secondTransshipmentHubBuilder.build(); + + // The adapter is now inserted into the corresponding LogisticsSolutionElement of the only + // LogisticsSolution of the LSP + Id secondHubElementId = + Id.create("SecondHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = + LSPUtils.LogisticChainElementBuilder.newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTranshipmentHubResource); + LogisticChainElement secondHubElement = secondHubElementBuilder.build(); + + // The Carrier for distribution is created + Id distributionCarrierId = Id.create("DistributionCarrier", Carrier.class); + Id distributionVehTypeId = + Id.create("DistributionCarrierVehicleType", VehicleType.class); + VehicleType distributionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + distributionVehType.getCapacity().setOther(10); + distributionVehType.getCostInformation().setCostsPerMeter(0.0004); + distributionVehType.getCostInformation().setCostsPerSecond(0.38); + distributionVehType.getCostInformation().setFixedCost(49.); + distributionVehType.setMaximumVelocity(50 / 3.6); + + Id distributionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id distributionVehicleId = Id.createVehicleId("DistributionVehicle"); + CarrierVehicle distributionCarrierVehicle = + CarrierVehicle.newInstance(distributionVehicleId, distributionLinkId, distributionVehType); + + CarrierCapabilities distributionCapabilities = CarrierCapabilities.Builder.newInstance() + .addVehicle(distributionCarrierVehicle) + .setFleetSize(FleetSize.INFINITE) + .build(); + + Carrier distributionCarrier = CarriersUtils.createCarrier(distributionCarrierId); + distributionCarrier.setCarrierCapabilities(distributionCapabilities); + + // The distribution adapter i.e. the Resource is created + LSPResource distributionResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + distributionCarrier) + .setLocationLinkId(distributionLinkId) + // The scheduler for the Resource is created and added. This is where jsprit comes into + // play. + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + // The adapter is now inserted into the corresponding LogisticsSolutionElement of the only + // LogisticsSolution of the LSP + Id distributionElementId = + Id.create("DistributionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder distributionBuilder = + LSPUtils.LogisticChainElementBuilder.newInstance(distributionElementId); + distributionBuilder.setResource(distributionResource); + LogisticChainElement distributionElement = distributionBuilder.build(); + + // The Order of the logisticsSolutionElements is now specified + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + secondHubElement.connectWithNextElement(distributionElement); + + // The SolutionElements are now inserted into the only LogisticsSolution of the LSP + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = + LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + completeSolutionBuilder.addLogisticChainElement(mainRunElement); + completeSolutionBuilder.addLogisticChainElement(secondHubElement); + completeSolutionBuilder.addLogisticChainElement(distributionElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + // The initial plan of the lsp is generated and the assigner and the solution from above are + // added + LSPPlan completePlan = LSPUtils.createLSPPlan(); + InitialShipmentAssigner assigner = + ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = + LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + + // The exogenous list of Resources for the SolutionScheduler is compiled and the Scheduler is + // added to the LSPBuilder + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + resourcesList.add(secondTranshipmentHubResource); + resourcesList.add(distributionResource); + LogisticChainScheduler simpleScheduler = + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + + return completeLSPBuilder.build(); + } + + private static Collection createInitialLSPShipments(Network network) { + ArrayList shipmentList = new ArrayList<>(); + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + Random rand = new Random(1); + for (int i = 1; i < 6; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = rand.nextInt(10); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, rand); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 + && pendingToLink.getFromNode().getCoord().getY() <= 4000 + && pendingToLink.getFromNode().getCoord().getX() >= 14000 + && pendingToLink.getToNode().getCoord().getX() <= 18000 + && pendingToLink.getToNode().getCoord().getY() <= 4000 + && pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + } + + while (true) { + Collections.shuffle(linkList, rand); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 + && pendingFromLink.getFromNode().getCoord().getY() <= 4000 + && pendingFromLink.getToNode().getCoord().getX() <= 4000 + && pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + shipmentList.add(builder.build()); + } + return shipmentList; + } + + public static void main(String[] args) { + // Set up required MATSim classes + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()) + .readFile("scenarios/2regions/2regions-network.xml"); + + // Create LSP and lspShipments + LSP lsp = createInitialLSP(scenario); + Collection lspShipments = createInitialLSPShipments(scenario.getNetwork()); + + // assign the lspShipments to the LSP + for (LspShipment lspShipment : lspShipments) { + lsp.assignShipmentToLSP(lspShipment); + } + + // schedule the LSP with the lspShipments and according to the scheduler of the Resource + lsp.scheduleLogisticChains(); + + // set up simulation controller and LSPModule + ArrayList lspList = new ArrayList<>(); + lspList.add(lsp); + LSPs lsps = new LSPs(lspList); + LSPUtils.addLSPs(scenario, lsps); + + Controller controller = ControllerUtils.createController(scenario); + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + install( + new LSPModule()); // this is the better syntax, having everything in one module. + // kai, may'22 + } + }); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.overwriteExistingFiles); + config.network().setInputFile("scenarios/2regions/2regions-network.xml"); + // The VSP default settings are designed for person transport simulation. After talking to Kai, + // they will be set to WARN here. Kai MT may'23 + controller + .getConfig() + .vspExperimental() + .setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + for (LspShipment lspShipment : lsp.getLspShipments()) { + System.out.println("Shipment: " + lspShipment.getId()); + ArrayList scheduleElements = + new ArrayList<>( + LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), lspShipment.getId()) + .getPlanElements() + .values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = + new ArrayList<>(lspShipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (int i = 0; + i + < LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), lspShipment.getId()) + .getPlanElements() + .size(); + i++) { + System.out.println( + "Scheduled: " + + scheduleElements.get(i).getLogisticChainElement().getId() + + " " + + scheduleElements.get(i).getResourceId() + + " " + + scheduleElements.get(i).getElementType() + + " Start: " + + scheduleElements.get(i).getStartTime() + + " End: " + + scheduleElements.get(i).getEndTime()); + } + System.out.println(); + for (int i = 0; i < lspShipment.getShipmentLog().getPlanElements().size(); i++) { + System.out.println( + "Logged: " + + logElements.get(i).getLogisticChainElement().getId() + + " " + + logElements.get(i).getResourceId() + + " " + + logElements.get(i).getElementType() + + " Start: " + + logElements.get(i).getStartTime() + + " End: " + + logElements.get(i).getEndTime()); + } + System.out.println(); + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/EventBasedCarrierScorer4MultipleChains.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/EventBasedCarrierScorer4MultipleChains.java new file mode 100644 index 00000000000..5469d53b508 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/EventBasedCarrierScorer4MultipleChains.java @@ -0,0 +1,201 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import com.google.inject.Inject; +import java.util.*; +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.Scenario; +import org.matsim.api.core.v01.events.*; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.scoring.ScoringFunction; +import org.matsim.core.scoring.SumScoringFunction; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.Tour; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.events.CarrierTourEndEvent; +import org.matsim.freight.carriers.events.CarrierTourStartEvent; +import org.matsim.freight.logistics.analysis.Vehicle2CarrierEventHandler; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +/** + * @author Kai Martins-Turner (kturner) + */ +class EventBasedCarrierScorer4MultipleChains implements CarrierScoringFunctionFactory { + + @Inject private Network network; + @Inject private Scenario scenario; + + private Id carrierId; + + private double toll; + private List tolledVehicleTypes = new ArrayList<>(); + private List tolledLinks = new ArrayList<>(); + + public ScoringFunction createScoringFunction(Carrier carrier) { + this.carrierId = carrier.getId(); + SumScoringFunction sf = new SumScoringFunction(); + sf.addScoringFunction(new EventBasedScoring()); + sf.addScoringFunction(new LinkBasedTollScoring(toll, tolledVehicleTypes, tolledLinks)); + return sf; + } + + void setToll(double toll) { + this.toll = toll; + } + + void setTolledVehicleTypes(List tolledVehicleTypes) { + this.tolledVehicleTypes = tolledVehicleTypes; + } + + void setTolledLinks(List tolledLinks) { + this.tolledLinks = tolledLinks; + } + + /** + * Calculate the carrier's score based on Events. Currently, it includes: - fixed costs (using + * CarrierTourEndEvent) - time-dependent costs (using FreightTourStart- and -EndEvent) - + * distance-dependent costs (using LinkEnterEvent) + */ + private class EventBasedScoring implements SumScoringFunction.ArbitraryEventScoring { + + final Logger log = LogManager.getLogger(EventBasedScoring.class); + private final Map, Double> tourStartTime = new LinkedHashMap<>(); + private double score; + + public EventBasedScoring() { + super(); + } + + @Override + public void finish() {} + + @Override + public double getScore() { + return score; + } + + @Override + public void handleEvent(Event event) { + log.debug(event.toString()); + switch (event) { + case CarrierTourStartEvent carrierTourStartEvent -> handleEvent(carrierTourStartEvent); + case CarrierTourEndEvent carrierTourEndEvent -> handleEvent(carrierTourEndEvent); + case LinkEnterEvent linkEnterEvent -> handleEvent(linkEnterEvent); + default -> {} + } + } + + private void handleEvent(CarrierTourStartEvent event) { + // Save time of freight tour start + tourStartTime.put(event.getTourId(), event.getTime()); + } + + // scores fix costs for vehicle usage and variable costs per time + private void handleEvent(CarrierTourEndEvent event) { + // Fix costs for vehicle usage + final VehicleType vehicleType = + (VehicleUtils.findVehicle(event.getVehicleId(), scenario)).getType(); + + double tourDuration = event.getTime() - tourStartTime.get(event.getTourId()); + + log.info("Score fixed costs for vehicle type: {}", vehicleType.getId().toString()); + score = score - vehicleType.getCostInformation().getFixedCosts(); + + // variable costs per time + score = score - (tourDuration * vehicleType.getCostInformation().getCostsPerSecond()); + } + + // scores variable costs per distance + private void handleEvent(LinkEnterEvent event) { + final double distance = network.getLinks().get(event.getLinkId()).getLength(); + final double costPerMeter = + (VehicleUtils.findVehicle(event.getVehicleId(), scenario)) + .getType() + .getCostInformation() + .getCostsPerMeter(); + // variable costs per distance + score = score - (distance * costPerMeter); + } + } + + /** + * Calculate some toll for driving on a link This a lazy implementation of a cordon toll. A + * vehicle is only tolled once. + */ + class LinkBasedTollScoring implements SumScoringFunction.ArbitraryEventScoring { + + final Logger log = LogManager.getLogger(EventBasedScoring.class); + + private final double toll; + private final List vehicleTypesToBeTolled; + private double score; + private List tolledLinkList; + private final Vehicle2CarrierEventHandler v2c = new Vehicle2CarrierEventHandler(); + + public LinkBasedTollScoring(double toll, List vehicleTypeToBeTolled, List tolledLinkListBerlin) { + super(); + this.vehicleTypesToBeTolled = vehicleTypeToBeTolled; + this.tolledLinkList = tolledLinkListBerlin; + this.toll = toll; + } + + @Override + public void finish() {} + + @Override + public double getScore() { + return score; + } + + @Override + public void handleEvent(Event event) { + + switch (event) { + case LinkEnterEvent linkEnterEvent -> handleEvent(linkEnterEvent); + case CarrierTourStartEvent carrierTourStartEvent -> v2c.handleEvent(carrierTourStartEvent); + case CarrierTourEndEvent carrierTourEndEvent -> v2c.handleEvent(carrierTourEndEvent); + default -> {} + } + + } + + private void handleEvent(LinkEnterEvent event) { + final Id vehicleTypeId = (VehicleUtils.findVehicle(event.getVehicleId(), scenario)).getType().getId(); + + Id vehicleId = event.getVehicleId(); + if (vehicleTypesToBeTolled.contains(vehicleTypeId.toString())) { + if (tolledLinkList.contains(event.getLinkId().toString())) { + Id carrierIdOfVehicle = v2c.getCarrierOfVehicle(vehicleId); + if (carrierId.equals(carrierIdOfVehicle)) { + log.info("Tolling caused by event: {}, tollvalue {}", event, toll); + score = score - toll; + } + } + } + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/EventBasedCarrierScorer4MultipleChainsInclToll.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/EventBasedCarrierScorer4MultipleChainsInclToll.java new file mode 100644 index 00000000000..292c95e72c2 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/EventBasedCarrierScorer4MultipleChainsInclToll.java @@ -0,0 +1,159 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import com.google.inject.Inject; +import java.util.*; +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.Scenario; +import org.matsim.api.core.v01.events.*; +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.population.Person; +import org.matsim.core.scoring.ScoringFunction; +import org.matsim.core.scoring.SumScoringFunction; +import org.matsim.core.scoring.SumScoringFunction.ArbitraryEventScoring; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.Tour; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.events.CarrierTourEndEvent; +import org.matsim.freight.carriers.events.CarrierTourStartEvent; +import org.matsim.freight.logistics.analysis.Driver2VehicleEventHandler; +import org.matsim.freight.logistics.analysis.Vehicle2CarrierEventHandler; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +/** + * @author Kai Martins-Turner (kturner) + */ +class EventBasedCarrierScorer4MultipleChainsInclToll implements CarrierScoringFunctionFactory { + + @Inject private Network network; + @Inject private Scenario scenario; + + private Id carrierId; + + public ScoringFunction createScoringFunction(Carrier carrier) { + this.carrierId = carrier.getId(); + SumScoringFunction sf = new SumScoringFunction(); + sf.addScoringFunction(new EventBasedScoring()); + return sf; + } + + + /** + * Calculate the carrier's score based on Events. Currently, it includes: - fixed costs (using + * CarrierTourEndEvent) - time-dependent costs (using FreightTourStart- and -EndEvent) - + * distance-dependent costs (using LinkEnterEvent) + * tolls (using PersonMoneyEvent) + */ + private class EventBasedScoring implements ArbitraryEventScoring { + + final Logger log = LogManager.getLogger(EventBasedScoring.class); + private final Map, Double> tourStartTime = new LinkedHashMap<>(); + private final Driver2VehicleEventHandler d2v = new Driver2VehicleEventHandler(); + private final Vehicle2CarrierEventHandler v2c = new Vehicle2CarrierEventHandler(); + private double score; + + public EventBasedScoring() { + super(); + } + + @Override + public void finish() {} + + @Override + public double getScore() { + return score; + } + + @Override + public void handleEvent(Event event) { + log.debug(event.toString()); + switch (event) { + case CarrierTourStartEvent carrierTourStartEvent -> handleEvent(carrierTourStartEvent); + case CarrierTourEndEvent carrierTourEndEvent -> handleEvent(carrierTourEndEvent); + case LinkEnterEvent linkEnterEvent -> handleEvent(linkEnterEvent); + case PersonMoneyEvent personMoneyEvent -> handleEvent(personMoneyEvent); + case VehicleEntersTrafficEvent vehicleEntersTrafficEvent -> d2v.handleEvent(vehicleEntersTrafficEvent); + case VehicleLeavesTrafficEvent vehicleLeavesTrafficEvent -> d2v.handleEvent(vehicleLeavesTrafficEvent); + default -> {} + } + } + + private void handleEvent(CarrierTourStartEvent event) { + v2c.handleEvent(event); + // Save time of freight tour start + tourStartTime.put(event.getTourId(), event.getTime()); + } + + // scores fix costs for vehicle usage and variable costs per time + private void handleEvent(CarrierTourEndEvent event) { + v2c.handleEvent(event); + // Fix costs for vehicle usage + final VehicleType vehicleType = (VehicleUtils.findVehicle(event.getVehicleId(), scenario)).getType(); + + double tourDuration = event.getTime() - tourStartTime.get(event.getTourId()); + + log.info("Score fixed costs for vehicle type: {}", vehicleType.getId().toString()); + score = score - vehicleType.getCostInformation().getFixedCosts(); + + // variable costs per time + score = score - (tourDuration * vehicleType.getCostInformation().getCostsPerSecond()); + } + + // scores variable costs per distance + private void handleEvent(LinkEnterEvent event) { + final double distance = network.getLinks().get(event.getLinkId()).getLength(); + final double costPerMeter = + (VehicleUtils.findVehicle(event.getVehicleId(), scenario)) + .getType() + .getCostInformation() + .getCostsPerMeter(); + // variable costs per distance + score = score - (distance * costPerMeter); + } + + private final List> tolledPersons = new ArrayList<>(); + + // scores tolls for vehicles driving on tolled links + private void handleEvent(PersonMoneyEvent event) { + double tollValue = 0; + + if (event.getPurpose().equals("toll")) { + Id vehicleId = d2v.getVehicleOfDriver(event.getPersonId()); + if (vehicleId != null) { + Id carrierIdOfVehicle = v2c.getCarrierOfVehicle(vehicleId); + if (carrierId.equals(carrierIdOfVehicle)) { + tollValue = event.getAmount(); + log.info("Tolling caused by event: {}, tollvalue {}", event, tollValue); + score = score + tollValue; + } + + } + } + } + } + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleGroceryDeliveryMultipleChains.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleGroceryDeliveryMultipleChains.java new file mode 100644 index 00000000000..e2bb5db2bc0 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleGroceryDeliveryMultipleChains.java @@ -0,0 +1,343 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import static org.matsim.freight.logistics.examples.multipleChains.MultipleChainsUtils.createLSPShipmentsFromCarrierShipments; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +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.Scenario; +import org.matsim.api.core.v01.network.Link; +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.VspExperimentalConfigGroup; +import org.matsim.core.controler.*; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.BestPlanSelector; +import org.matsim.core.replanning.selectors.ExpBetaPlanSelector; +import org.matsim.core.replanning.selectors.GenericWorstPlanForRemovalSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.examples.ExampleConstants; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.vehicles.VehicleType; + +final class ExampleGroceryDeliveryMultipleChains { + + private static final Logger log = + LogManager.getLogger(ExampleGroceryDeliveryMultipleChains.class); + private static final Id HUB_LINK_ID = Id.createLinkId("91085"); + private static final double TOLL_VALUE = 1000; + static final double HUBCOSTS_FIX = 100; + private static final List TOLLED_LINKS = ExampleConstants.TOLLED_LINK_LIST_BERLIN_BOTH_DIRECTIONS; + + private ExampleGroceryDeliveryMultipleChains() {} + + public static void main(String[] args) { + log.info("Prepare config"); + Config config = prepareConfig(args); + + log.info("Prepare scenario"); + Scenario scenario = prepareScenario(config); + + log.info("Prepare controller"); + Controller controller = ControllerUtils.createController(scenario); + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + final EventBasedCarrierScorer4MultipleChains carrierScorer = + new EventBasedCarrierScorer4MultipleChains(); + carrierScorer.setToll(TOLL_VALUE); + carrierScorer.setTolledVehicleTypes( List.of("heavy40t")); + carrierScorer.setTolledLinks(TOLLED_LINKS); + bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); + bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); + bind(CarrierStrategyManager.class) + .toProvider( + () -> { + CarrierStrategyManager strategyManager = + CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy( + new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + return strategyManager; + }); + bind(LSPStrategyManager.class) + .toProvider( + () -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new ExpBetaPlanSelector<>(new ScoringConfigGroup())), null, 1); + strategyManager.addStrategy(RandomShiftingStrategyFactory.createStrategy(), null, 1); + strategyManager.setMaxPlansPerAgent(5); + strategyManager.setPlanSelectorForRemoval(new GenericWorstPlanForRemovalSelector<>()); + return strategyManager; + }); + } + }); + + log.info("Run MATSim"); + + // The VSP default settings are designed for person transport simulation. After talking to Kai, + // they will be set to WARN here. Kai MT may'23 + controller + .getConfig() + .vspExperimental() + .setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + log.info("Done."); + } + + private static Config prepareConfig(String[] args) { + Config config = ConfigUtils.createConfig(); + if (args.length != 0) { + for (String arg : args) { + log.warn(arg); + } + ConfigUtils.applyCommandline(config, args); + } else { + config.controller().setOutputDirectory("output/groceryDelivery_kmt"); + config.controller().setLastIteration(20); + } + + config.network().setInputFile( + "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/berlin-v5.5-10pct/input/berlin-v5.5-network.xml.gz"); + config.controller().setOverwriteFileSetting( + OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setWriteEventsInterval(1); + + FreightCarriersConfigGroup freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + return config; + } + + private static Scenario prepareScenario(Config config) { + Scenario scenario = ScenarioUtils.loadScenario(config); + + log.info("Add LSP to the scenario"); + LSPUtils.addLSPs(scenario, new LSPs(Collections.singletonList(createLSP(scenario)))); + + return scenario; + } + + private static LSP createLSP(Scenario scenario) { + String carrierPlanFile = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/projects/freight/foodRetailing_wo_rangeConstraint/input/CarrierLEH_v2_withFleet_Shipment_OneTW_PickupTime_ICEVandBEV.xml"; + String vehicleTypeFile = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/projects/freight/foodRetailing_wo_rangeConstraint/input/vehicleTypesBVWP100_DC_noTax.xml"; + + CarrierVehicleTypes vehicleTypes = new CarrierVehicleTypes(); + CarrierVehicleTypeReader vehicleTypeReader = new CarrierVehicleTypeReader(vehicleTypes); + vehicleTypeReader.readFile(vehicleTypeFile); + + Carriers carriers = new Carriers(); + CarrierPlanXmlReader carrierReader = new CarrierPlanXmlReader(carriers, vehicleTypes); + carrierReader.readFile(carrierPlanFile); + + Carrier carrier = carriers.getCarriers() + .get(Id.create("kaufland_VERBRAUCHERMARKT_TROCKEN", CarrierImpl.class)); + Id depotLinkFromVehicles = carrier + .getCarrierCapabilities() + .getCarrierVehicles() + .values() + .iterator() + .next() + .getLinkId(); + + log.info("create LSP"); + + LSPPlan multipleMixedEchelonChainsPlan; + { + LogisticChain directChain; + { + Carrier singleCarrier = CarriersUtils.createCarrier(Id.create("singleCarrier", Carrier.class)); + singleCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle(singleCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("singleCarrier"), + depotLinkFromVehicles, + vehicleTypes.getVehicleTypes().get(Id.create("heavy40t", VehicleType.class)))); + LSPResource singleCarrierResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + singleCarrier) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement singleCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("directCarrierElement", LogisticChainElement.class)) + .setResource(singleCarrierResource) + .build(); + + directChain = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("directChain", LogisticChain.class)) + .addLogisticChainElement(singleCarrierElement) + .build(); + } + + LogisticChain hubChain; + { + Carrier mainCarrier = CarriersUtils.createCarrier(Id.create("mainCarrier", Carrier.class)); + mainCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + mainCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("mainTruck"), + depotLinkFromVehicles, + vehicleTypes.getVehicleTypes().get(Id.create("heavy40t", VehicleType.class)))); + LSPResource mainCarrierResource = + ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance( + mainCarrier) + .setFromLinkId(depotLinkFromVehicles) + .setMainRunCarrierScheduler( + ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setToLinkId(HUB_LINK_ID) + .setVehicleReturn(ResourceImplementationUtils.VehicleReturn.returnToFromLink) + .build(); + + LogisticChainElement mainCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("mainCarrierElement", LogisticChainElement.class)) + .setResource(mainCarrierResource) + .build(); + + LSPResourceScheduler hubScheduler = + ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed(10) + .setCapacityNeedLinear(1) + .build(); + + LSPResource hubResource = + ResourceImplementationUtils.TransshipmentHubBuilder.newInstance( + Id.create("Hub", LSPResource.class), HUB_LINK_ID, scenario) + .setTransshipmentHubScheduler(hubScheduler) + .build(); + + LSPUtils.setFixedCost(hubResource, HUBCOSTS_FIX); + + LogisticChainElement hubElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("HubElement", LogisticChainElement.class)) + .setResource(hubResource) + .build(); + + Carrier distributionCarrier = + CarriersUtils.createCarrier(Id.create("distributionCarrier", Carrier.class)); + distributionCarrier + .getCarrierCapabilities() + .setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + distributionCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("distributionTruck"), + HUB_LINK_ID, + vehicleTypes + .getVehicleTypes() + .get(Id.create("heavy40t_electro", VehicleType.class)))); + LSPResource distributionCarrierResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + distributionCarrier) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement distributionCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("distributionCarrierElement", LogisticChainElement.class)) + .setResource(distributionCarrierResource) + .build(); + + mainCarrierElement.connectWithNextElement(hubElement); + hubElement.connectWithNextElement(distributionCarrierElement); + + hubChain = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("hubChain", LogisticChain.class)) + .addLogisticChainElement(mainCarrierElement) + .addLogisticChainElement(hubElement) + .addLogisticChainElement(distributionCarrierElement) + .build(); + } + + multipleMixedEchelonChainsPlan = + LSPUtils.createLSPPlan() + .addLogisticChain(directChain) + .addLogisticChain(hubChain) + .setInitialShipmentAssigner(MultipleChainsUtils.createRandomLogisticChainShipmentAssigner()); + } + + List lspPlans = new ArrayList<>(); + lspPlans.add(multipleMixedEchelonChainsPlan); + + LSP lsp = + LSPUtils.LSPBuilder.getInstance(Id.create("myLSP", LSP.class)) + .setInitialPlan(multipleMixedEchelonChainsPlan) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + createResourcesListFromLSPPlans(lspPlans))) + .build(); + + log.info("create initial LSPShipments"); + log.info("assign the shipments to the LSP"); + for (LspShipment lspShipment : createLSPShipmentsFromCarrierShipments(carrier)) { + lsp.assignShipmentToLSP(lspShipment); + } + + log.info("schedule the LSP with the shipments and according to the scheduler of the Resource"); + lsp.scheduleLogisticChains(); + + return lsp; + } + + private static List createResourcesListFromLSPPlans(List lspPlans) { + log.info("Collecting all LSPResources from the LSPPlans"); + List resourceList = new ArrayList<>(); + for (LSPPlan lspPlan : lspPlans) { + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + for (LogisticChainElement logisticChainElement : logisticChain.getLogisticChainElements()) { + resourceList.add(logisticChainElement.getResource()); + } + } + } + return resourceList; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleMultipleMixedEchelonChains.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleMultipleMixedEchelonChains.java new file mode 100644 index 00000000000..fcf31169400 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleMultipleMixedEchelonChains.java @@ -0,0 +1,498 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import java.util.*; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.*; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.BestPlanSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.examples.ExampleConstants; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +final class ExampleMultipleMixedEchelonChains { + + static final double HUBCOSTS_FIX = 100; + private static final Logger log = LogManager.getLogger(ExampleMultipleMixedEchelonChains.class); + private static final double TOLL_VALUE = 1000; + private static final Id DEPOT_LINK_ID = Id.createLinkId("i(5,0)"); + private static final Id HUB_LINK_ID = Id.createLinkId("j(5,3)"); + private static final VehicleType VEH_TYPE_LARGE_50 = createVehTypeLarge50(); + private static final VehicleType VEH_TYPE_SMALL_05 = createVehTypeSmall05(); + + private static VehicleType createVehTypeLarge50() { + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("large50", VehicleType.class), TransportMode.car); + vehicleType.getCapacity().setOther(50); + vehicleType.getCostInformation().setCostsPerMeter(0.01); + vehicleType.getCostInformation().setCostsPerSecond(0.01); + vehicleType.getCostInformation().setFixedCost(150.); + vehicleType.setMaximumVelocity(10); + vehicleType.setNetworkMode(TransportMode.car); + + return vehicleType; + } + + private static VehicleType createVehTypeSmall05() { + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("small05", VehicleType.class), TransportMode.car); + vehicleType.getCapacity().setOther(5); + vehicleType.getCostInformation().setCostsPerMeter(0.001); + vehicleType.getCostInformation().setCostsPerSecond(0.005); + vehicleType.getCostInformation().setFixedCost(25.); + vehicleType.setMaximumVelocity(10); + vehicleType.setNetworkMode(TransportMode.car); + + return vehicleType; + } + + private ExampleMultipleMixedEchelonChains() {} + + public static void main(String[] args) { + log.info("Prepare config"); + Config config = prepareConfig(args); + + log.info("Prepare scenario"); + Scenario scenario = prepareScenario(config); + + log.info("Prepare controller"); + Controller controller = ControllerUtils.createController(scenario); + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + final EventBasedCarrierScorer4MultipleChains carrierScorer = + new EventBasedCarrierScorer4MultipleChains(); + bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); + carrierScorer.setToll(TOLL_VALUE); + carrierScorer.setTolledVehicleTypes( List.of("heavy40t")); + carrierScorer.setTolledLinks(ExampleConstants.TOLLED_LINK_LIST_BERLIN_BOTH_DIRECTIONS); + bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); + bind(CarrierStrategyManager.class) + .toProvider( + () -> { + CarrierStrategyManager strategyManager = + CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy( + new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + return strategyManager; + }); + bind(LSPStrategyManager.class) + .toProvider( + () -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy( + new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + return strategyManager; + }); + } + }); + + log.info("Run MATSim"); + + // The VSP default settings are designed for person transport simulation. After talking to Kai, + // they will be set to WARN here. Kai MT may'23 + controller + .getConfig() + .vspExperimental() + .setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + log.info("Done."); + } + + private static Config prepareConfig(String[] args) { + Config config = ConfigUtils.createConfig(); + if (args.length != 0) { + for (String arg : args) { + log.warn(arg); + } + ConfigUtils.applyCommandline(config, args); + } else { + config.controller().setOutputDirectory("output/multipleMixedEchelonChains_twoPlans"); + config.controller().setLastIteration(2); + } + config + .network() + .setInputFile( + String.valueOf( + IOUtils.extendUrl( + ExamplesUtils.getTestScenarioURL("freight-chessboard-9x9"), "grid9x9.xml"))); + config + .controller() + .setOverwriteFileSetting( + OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setWriteEventsInterval(1); + + FreightCarriersConfigGroup freightConfig = + ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + return config; + } + + private static Scenario prepareScenario(Config config) { + Scenario scenario = ScenarioUtils.loadScenario(config); + + for (Link link : scenario.getNetwork().getLinks().values()) { + link.setFreespeed(30 / 3.6); + link.setCapacity(1000); + } + + log.info("Add LSP to the scenario"); + LSPUtils.addLSPs(scenario, new LSPs(Collections.singletonList(createLSP(scenario)))); + + return scenario; + } + + private static LSP createLSP(Scenario scenario) { + log.info("create LSP"); + Network network = scenario.getNetwork(); + + LSPPlan singleTwoEchelonChainPlan; + { + LogisticChain hubChain1; + { + Carrier mainCarrier1 = CarriersUtils.createCarrier(Id.create("mainCarrier", Carrier.class)); + mainCarrier1.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + mainCarrier1, + CarrierVehicle.newInstance( + Id.createVehicleId("mainTruck"), DEPOT_LINK_ID, VEH_TYPE_LARGE_50)); + LSPResource mainCarrierResource1 = + ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance( + mainCarrier1) + .setFromLinkId(DEPOT_LINK_ID) + .setMainRunCarrierScheduler( + ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setToLinkId(HUB_LINK_ID) + .setVehicleReturn(ResourceImplementationUtils.VehicleReturn.returnToFromLink) + .build(); + + LogisticChainElement mainCarrierElement1 = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("mainCarrierElement", LogisticChainElement.class)) + .setResource(mainCarrierResource1) + .build(); + + LSPResourceScheduler hubScheduler1 = + ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed(10) + .setCapacityNeedLinear(1) + .build(); + + LSPResource hubResource1 = + ResourceImplementationUtils.TransshipmentHubBuilder.newInstance( + Id.create("Hub", LSPResource.class), HUB_LINK_ID, scenario) + .setTransshipmentHubScheduler(hubScheduler1) + .build(); + LSPUtils.setFixedCost(hubResource1, HUBCOSTS_FIX); + + LogisticChainElement hubElement1 = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("HubElement", LogisticChainElement.class)) + .setResource(hubResource1) + .build(); + + Carrier distributionCarrier1 = + CarriersUtils.createCarrier(Id.create("distributionCarrier", Carrier.class)); + distributionCarrier1 + .getCarrierCapabilities() + .setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + distributionCarrier1, + CarrierVehicle.newInstance( + Id.createVehicleId("distributionTruck"), HUB_LINK_ID, VEH_TYPE_SMALL_05)); + LSPResource distributionCarrierResource1 = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + distributionCarrier1) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement distributionCarrierElement1 = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("distributionCarrierElement", LogisticChainElement.class)) + .setResource(distributionCarrierResource1) + .build(); + + mainCarrierElement1.connectWithNextElement(hubElement1); + hubElement1.connectWithNextElement(distributionCarrierElement1); + + hubChain1 = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("hubChain", LogisticChain.class)) + .addLogisticChainElement(mainCarrierElement1) + .addLogisticChainElement(hubElement1) + .addLogisticChainElement(distributionCarrierElement1) + .build(); + } + + singleTwoEchelonChainPlan = + LSPUtils.createLSPPlan() + .addLogisticChain(hubChain1) + .setInitialShipmentAssigner( + MultipleChainsUtils.createPrimaryLogisticChainShipmentAssigner()); + } + + // A plan with a direct chain and a hub chain is created + LSPPlan multipleMixedEchelonChainsPlan; + { + LogisticChain directChain; + { + Carrier singleCarrier = + CarriersUtils.createCarrier(Id.create("singleCarrier", Carrier.class)); + singleCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + singleCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("singleCarrier"), DEPOT_LINK_ID, VEH_TYPE_SMALL_05)); + LSPResource singleCarrierResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + singleCarrier) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement singleCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("directCarrierElement", LogisticChainElement.class)) + .setResource(singleCarrierResource) + .build(); + + directChain = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("directChain", LogisticChain.class)) + .addLogisticChainElement(singleCarrierElement) + .build(); + } + + LogisticChain hubChain; + { + Carrier mainCarrier = CarriersUtils.createCarrier(Id.create("mainCarrier", Carrier.class)); + mainCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + mainCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("mainTruck"), DEPOT_LINK_ID, VEH_TYPE_LARGE_50)); + LSPResource mainCarrierResource = + ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance( + mainCarrier) + .setFromLinkId(DEPOT_LINK_ID) + .setMainRunCarrierScheduler( + ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setToLinkId(HUB_LINK_ID) + .setVehicleReturn(ResourceImplementationUtils.VehicleReturn.returnToFromLink) + .build(); + + LogisticChainElement mainCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("mainCarrierElement", LogisticChainElement.class)) + .setResource(mainCarrierResource) + .build(); + + LSPResourceScheduler hubScheduler = + ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed(10) + .setCapacityNeedLinear(1) + .build(); + + LSPResource hubResource = + ResourceImplementationUtils.TransshipmentHubBuilder.newInstance( + Id.create("Hub", LSPResource.class), HUB_LINK_ID, scenario) + .setTransshipmentHubScheduler(hubScheduler) + .build(); + LSPUtils.setFixedCost(hubResource, HUBCOSTS_FIX); + + LogisticChainElement hubElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("HubElement", LogisticChainElement.class)) + .setResource(hubResource) + .build(); + + Carrier distributionCarrier = + CarriersUtils.createCarrier(Id.create("distributionCarrier", Carrier.class)); + distributionCarrier + .getCarrierCapabilities() + .setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + distributionCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("distributionTruck"), HUB_LINK_ID, VEH_TYPE_SMALL_05)); + LSPResource distributionCarrierResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + distributionCarrier) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement distributionCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("distributionCarrierElement", LogisticChainElement.class)) + .setResource(distributionCarrierResource) + .build(); + + mainCarrierElement.connectWithNextElement(hubElement); + hubElement.connectWithNextElement(distributionCarrierElement); + + hubChain = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("hubChain", LogisticChain.class)) + .addLogisticChainElement(mainCarrierElement) + .addLogisticChainElement(hubElement) + .addLogisticChainElement(distributionCarrierElement) + .build(); + } + + multipleMixedEchelonChainsPlan = + LSPUtils.createLSPPlan() + .addLogisticChain(hubChain) + .addLogisticChain(directChain) + .setInitialShipmentAssigner( + MultipleChainsUtils.createRoundRobinLogisticChainShipmentAssigner()); + } + + List lspPlans = new ArrayList<>(); + lspPlans.add(singleTwoEchelonChainPlan); + lspPlans.add(multipleMixedEchelonChainsPlan); + + LSP lsp = + LSPUtils.LSPBuilder.getInstance(Id.create("myLSP", LSP.class)) + .setInitialPlan(singleTwoEchelonChainPlan) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + createResourcesListFromLSPPlans(lspPlans))) + .build(); + + log.info("create initial LSPShipments"); + log.info("assign the shipments to the LSP"); + for (LspShipment lspShipment : createInitialLSPShipments(network)) { + lsp.assignShipmentToLSP(lspShipment); + } + + log.info("schedule the LSP with the shipments and according to the scheduler of the Resource"); + lsp.scheduleLogisticChains(); + + return lsp; + } + + private static Collection createInitialLSPShipments(Network network) { + List shipmentList = new ArrayList<>(); + + Random rand = MatsimRandom.getLocalInstance(); + + int capacityDemand = 1; + + List zoneLinkList = + Arrays.asList( + "i(4,4)", "i(5,4)", "i(6,4)", "i(4,6)", "i(5,6)", "i(6,6)", "j(3,5)", "j(3,6)", + "j(3,7)", "j(5,5)", "j(5,6)", "j(5,7)", "i(4,5)R", "i(5,5)R", "i(6,5)R", "i(4,7)R", + "i(5,7)R", "i(6,7)R", "j(4,5)R", "j(4,6)R", "j(4,7)R", "j(6,5)R", "j(6,6)R", "j(6,7)R"); + for (String linkIdString : zoneLinkList) { + if (!network.getLinks().containsKey(Id.createLinkId(linkIdString))) { + throw new RuntimeException("Link is not in Network!"); + } + } + + for (int i = 1; i <= 10; i++) { + if (i % 2 != 0) { + Id id = Id.create("ShipmentInside_" + i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + + builder.setCapacityDemand(capacityDemand); + builder.setFromLinkId(DEPOT_LINK_ID); + final Id toLinkId = + Id.createLinkId(zoneLinkList.get(rand.nextInt(zoneLinkList.size() - 1))); + builder.setToLinkId(toLinkId); + + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + shipmentList.add(builder.build()); + } else { + Id id = Id.create("ShipmentOutside_" + i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + + builder.setCapacityDemand(capacityDemand); + builder.setFromLinkId(DEPOT_LINK_ID); + final Id toLinkId = Id.createLinkId("i(9,0)"); + builder.setToLinkId(toLinkId); + + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + shipmentList.add(builder.build()); + } + } + return shipmentList; + } + + private static List createResourcesListFromLSPPlans(List lspPlans) { + log.info("Collecting all LSPResources from the LSPPlans"); + List resourceList = new ArrayList<>(); + for (LSPPlan lspPlan : lspPlans) { + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + for (LogisticChainElement logisticChainElement : logisticChain.getLogisticChainElements()) { + resourceList.add(logisticChainElement.getResource()); + } + } + } + return resourceList; + } + + enum AssignerSetting { + primary, + roundRobin + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleMultipleOneEchelonChains.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleMultipleOneEchelonChains.java new file mode 100644 index 00000000000..6e01b0e38ac --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleMultipleOneEchelonChains.java @@ -0,0 +1,390 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.*; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.BestPlanSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +final class ExampleMultipleOneEchelonChains { + + private static final Logger log = LogManager.getLogger(ExampleMultipleOneEchelonChains.class); + + private static final DemandSetting demandSetting = DemandSetting.fiveUnits; + private static final Id DEPOT_LINK_ID = Id.createLinkId("i(5,0)"); + private static final VehicleType VEH_TYPE_LARGE_50 = createVehTypeLarge50(); + private static final VehicleType VEH_TYPE_SMALL_05 = createVehTypeSmall05(); + + private static VehicleType createVehTypeLarge50() { + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("large50", VehicleType.class), TransportMode.car); + vehicleType.getCapacity().setOther(50); + vehicleType.getCostInformation().setCostsPerMeter(0.01); + vehicleType.getCostInformation().setCostsPerSecond(0.01); + vehicleType.getCostInformation().setFixedCost(150.); + vehicleType.setMaximumVelocity(10); + vehicleType.setNetworkMode(TransportMode.car); + + return vehicleType; + } + + private static VehicleType createVehTypeSmall05() { + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("small05", VehicleType.class), TransportMode.car); + vehicleType.getCapacity().setOther(5); + vehicleType.getCostInformation().setCostsPerMeter(0.001); + vehicleType.getCostInformation().setCostsPerSecond(0.005); + vehicleType.getCostInformation().setFixedCost(25.); + vehicleType.setMaximumVelocity(10); + vehicleType.setNetworkMode(TransportMode.car); + + return vehicleType; + } + + + private ExampleMultipleOneEchelonChains() {} + + public static void main(String[] args) { + log.info("Prepare config"); + Config config = prepareConfig(args); + + log.info("Prepare scenario"); + Scenario scenario = prepareScenario(config); + + log.info("Prepare controller"); + Controller controller = ControllerUtils.createController(scenario); + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + final EventBasedCarrierScorer4MultipleChains carrierScorer = + new EventBasedCarrierScorer4MultipleChains(); + bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); + bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); + bind(CarrierStrategyManager.class) + .toProvider( + () -> { + CarrierStrategyManager strategyManager = + CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy( + new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + return strategyManager; + }); + bind(LSPStrategyManager.class) + .toProvider( + () -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy( + new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + return strategyManager; + }); + } + }); + + log.info("Run MATSim"); + + // The VSP default settings are designed for person transport simulation. After talking to Kai, + // they will be set to WARN here. Kai MT may'23 + controller + .getConfig() + .vspExperimental() + .setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + log.info("Done."); + } + + private static Config prepareConfig(String[] args) { + Config config = ConfigUtils.createConfig(); + if (args.length != 0) { + for (String arg : args) { + log.warn(arg); + } + ConfigUtils.applyCommandline(config, args); + } else { + config.controller().setOutputDirectory("output/multipleOneEchelonChains_" + demandSetting); + config.controller().setLastIteration(2); + } + config + .network() + .setInputFile( + String.valueOf( + IOUtils.extendUrl( + ExamplesUtils.getTestScenarioURL("freight-chessboard-9x9"), "grid9x9.xml"))); + config + .controller() + .setOverwriteFileSetting( + OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setWriteEventsInterval(1); + + FreightCarriersConfigGroup freightConfig = + ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + return config; + } + + private static Scenario prepareScenario(Config config) { + Scenario scenario = ScenarioUtils.loadScenario(config); + + for (Link link : scenario.getNetwork().getLinks().values()) { + link.setFreespeed(30 / 3.6); + link.setCapacity(1000); + } + + log.info("Add LSP to the scenario"); + LSPUtils.addLSPs(scenario, new LSPs(Collections.singletonList(createLSP(scenario)))); + + return scenario; + } + + private static LSP createLSP(Scenario scenario) { + log.info("create LSP"); + Network network = scenario.getNetwork(); + + // A plan with one logistic chain, containing a single carrier is created + LSPPlan singleOneEchelonChainPlan; + { + Carrier singleCarrier = + CarriersUtils.createCarrier(Id.create("singleCarrier", Carrier.class)); + singleCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + singleCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("veh_large"), DEPOT_LINK_ID, VEH_TYPE_LARGE_50)); + LSPResource singleCarrierResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + singleCarrier) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement singleCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("singleCarrierElement", LogisticChainElement.class)) + .setResource(singleCarrierResource) + .build(); + + LogisticChain singleChain = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("singleChain", LogisticChain.class)) + .addLogisticChainElement(singleCarrierElement) + .build(); + + final InitialShipmentAssigner singleSolutionShipmentAssigner = + MultipleChainsUtils.createPrimaryLogisticChainShipmentAssigner(); + singleOneEchelonChainPlan = + LSPUtils.createLSPPlan() + .addLogisticChain(singleChain) + .setInitialShipmentAssigner(singleSolutionShipmentAssigner); + } + + // A plan with two different logistic chains on the left and right, with respective carriers is + // created + LSPPlan multipleOneEchelonChainsPlan; + { + LogisticChainElement leftCarrierElement; + { + Carrier carrierLeft = CarriersUtils.createCarrier(Id.create("carrierLeft", Carrier.class)); + carrierLeft.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + carrierLeft, + CarrierVehicle.newInstance( + Id.createVehicleId("veh_small"), DEPOT_LINK_ID, VEH_TYPE_SMALL_05)); + LSPResource carrierLeftResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + carrierLeft) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + leftCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("leftCarrierElement", LogisticChainElement.class)) + .setResource(carrierLeftResource) + .build(); + } + + LogisticChainElement rightCarrierElement; + { + Carrier carrierRight = + CarriersUtils.createCarrier(Id.create("carrierRight", Carrier.class)); + carrierRight.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + carrierRight, + CarrierVehicle.newInstance( + Id.createVehicleId("veh_small"), DEPOT_LINK_ID, VEH_TYPE_SMALL_05)); + LSPResource carrierRightResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + carrierRight) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + rightCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("rightCarrierElement", LogisticChainElement.class)) + .setResource(carrierRightResource) + .build(); + } + + LogisticChain leftChain = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("leftChain", LogisticChain.class)) + .addLogisticChainElement(leftCarrierElement) + .build(); + + LogisticChain rightChain = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("rightChain", LogisticChain.class)) + .addLogisticChainElement(rightCarrierElement) + .build(); + + final InitialShipmentAssigner shipmentAssigner = + MultipleChainsUtils.createRoundRobinLogisticChainShipmentAssigner(); + multipleOneEchelonChainsPlan = + LSPUtils.createLSPPlan() + .addLogisticChain(leftChain) + .addLogisticChain(rightChain) + .setInitialShipmentAssigner(shipmentAssigner); + } + + List lspPlans = new ArrayList<>(); + lspPlans.add(singleOneEchelonChainPlan); + lspPlans.add(multipleOneEchelonChainsPlan); + + LSP lsp = + LSPUtils.LSPBuilder.getInstance(Id.create("myLSP", LSP.class)) + .setInitialPlan(singleOneEchelonChainPlan) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + createResourcesListFromLSPPlans(lspPlans))) + .build(); + lsp.addPlan(multipleOneEchelonChainsPlan); + + log.info("create initial LSPShipments"); + log.info("assign the shipments to the LSP"); + for (LspShipment lspShipment : createInitialLSPShipments()) { + lsp.assignShipmentToLSP(lspShipment); + } + + log.info("schedule the LSP with the shipments and according to the scheduler of the Resource"); + lsp.scheduleLogisticChains(); + + return lsp; + } + + private static Collection createInitialLSPShipments() { + List lspShipmentList = new ArrayList<>(); + int capacityDemand; + + switch (demandSetting) { + case oneUnit -> capacityDemand = 1; + case fiveUnits -> capacityDemand = 5; + default -> throw new IllegalStateException("Unexpected value: " + demandSetting); + } + + for (int i = 1; i <= 10; i++) { + if (i % 2 != 0) { + Id id = Id.create("ShipmentLeft_" + i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + + builder.setCapacityDemand(capacityDemand); + builder.setFromLinkId(DEPOT_LINK_ID); + final Id shipmentLeftLinkId = Id.createLinkId("i(1,9)R"); + builder.setToLinkId(shipmentLeftLinkId); + + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + lspShipmentList.add(builder.build()); + } else { + Id id = Id.create("ShipmentRight_" + i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + + builder.setCapacityDemand(capacityDemand); + builder.setFromLinkId(DEPOT_LINK_ID); + final Id shipmentRightLinkId = Id.createLinkId("j(9,9)"); + builder.setToLinkId(shipmentRightLinkId); + + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + lspShipmentList.add(builder.build()); + } + } + return lspShipmentList; + } + + private static List createResourcesListFromLSPPlans(List lspPlans) { + log.info("Collecting all LSPResources from the LSPPlans"); + List resourceList = new ArrayList<>(); + for (LSPPlan lspPlan : lspPlans) { + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + for (LogisticChainElement logisticChainElement : logisticChain.getLogisticChainElements()) { + resourceList.add(logisticChainElement.getResource()); + } + } + } + return resourceList; + } + + enum DemandSetting { + oneUnit, + fiveUnits + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleMultipleOneEchelonChainsReplanning.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleMultipleOneEchelonChainsReplanning.java new file mode 100644 index 00000000000..4012855405c --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleMultipleOneEchelonChainsReplanning.java @@ -0,0 +1,401 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.*; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.BestPlanSelector; +import org.matsim.core.replanning.selectors.ExpBetaPlanSelector; +import org.matsim.core.replanning.selectors.GenericWorstPlanForRemovalSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +final class ExampleMultipleOneEchelonChainsReplanning { + + private static final Logger log = + LogManager.getLogger(ExampleMultipleOneEchelonChainsReplanning.class); + + private static final Id DEPOT_LINK_ID = Id.createLinkId("i(5,0)"); + + private static final VehicleType VEH_TYPE_LARGE_50 = createVehTypeLarge50(); + private static final VehicleType VEH_TYPE_SMALL_05 = createVehTypeSmall05(); + + private static VehicleType createVehTypeLarge50() { + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("large50", VehicleType.class), TransportMode.car); + vehicleType.getCapacity().setOther(50); + vehicleType.getCostInformation().setCostsPerMeter(0.01); + vehicleType.getCostInformation().setCostsPerSecond(0.01); + vehicleType.getCostInformation().setFixedCost(150.); + vehicleType.setMaximumVelocity(10); + vehicleType.setNetworkMode(TransportMode.car); + + return vehicleType; + } + + private static VehicleType createVehTypeSmall05() { + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("small05", VehicleType.class), TransportMode.car); + vehicleType.getCapacity().setOther(5); + vehicleType.getCostInformation().setCostsPerMeter(0.001); + vehicleType.getCostInformation().setCostsPerSecond(0.005); + vehicleType.getCostInformation().setFixedCost(25.); + vehicleType.setMaximumVelocity(10); + vehicleType.setNetworkMode(TransportMode.car); + + return vehicleType; + } + + private ExampleMultipleOneEchelonChainsReplanning() {} + + public static void main(String[] args) { + log.info("Prepare config"); + Config config = prepareConfig(args); + + log.info("Prepare scenario"); + Scenario scenario = prepareScenario(config); + + log.info("Prepare controller"); + Controller controller = ControllerUtils.createController(scenario); + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + final EventBasedCarrierScorer4MultipleChains carrierScorer = + new EventBasedCarrierScorer4MultipleChains(); + bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); + bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); + bind(CarrierStrategyManager.class) + .toProvider( + () -> { + CarrierStrategyManager strategyManager = + CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy( + new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + return strategyManager; + }); + bind(LSPStrategyManager.class) + .toProvider( + () -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy( + new GenericPlanStrategyImpl<>( + new ExpBetaPlanSelector<>(new ScoringConfigGroup())), + null, + 1); + strategyManager.addStrategy( + RandomShiftingStrategyFactory.createStrategy(), null, 1); + // + // strategyManager.addStrategy(ProximityStrategyFactory.createStrategy(scenario.getNetwork()), null, 1); + strategyManager.setMaxPlansPerAgent(5); + strategyManager.setPlanSelectorForRemoval( + new GenericWorstPlanForRemovalSelector<>()); + return strategyManager; + }); + } + }); + + // TODO: Innovation switch not working + config.replanning().setFractionOfIterationsToDisableInnovation(0.8); + + log.info("Run MATSim"); + + // The VSP default settings are designed for person transport simulation. After talking to Kai, + // they will be set to WARN here. Kai MT may'23 + controller + .getConfig() + .vspExperimental() + .setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + log.info("Done."); + } + + private static Config prepareConfig(String[] args) { + Config config = ConfigUtils.createConfig(); + if (args.length != 0) { + for (String arg : args) { + log.warn(arg); + } + ConfigUtils.applyCommandline(config, args); + } else { + config.controller().setOutputDirectory("output/multipleOneEchelonChainsReplanning"); + config.controller().setLastIteration(10); + } + config + .network() + .setInputFile( + String.valueOf( + IOUtils.extendUrl( + ExamplesUtils.getTestScenarioURL("freight-chessboard-9x9"), "grid9x9.xml"))); + config + .controller() + .setOverwriteFileSetting( + OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setWriteEventsInterval(1); + + FreightCarriersConfigGroup freightConfig = + ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + return config; + } + + private static Scenario prepareScenario(Config config) { + Scenario scenario = ScenarioUtils.loadScenario(config); + + for (Link link : scenario.getNetwork().getLinks().values()) { + link.setFreespeed(30 / 3.6); + link.setCapacity(1000); + } + + log.info("Add LSP to the scenario"); + LSPUtils.addLSPs(scenario, new LSPs(Collections.singletonList(createLSP(scenario)))); + + return scenario; + } + + private static LSP createLSP(Scenario scenario) { + log.info("create LSP"); + Network network = scenario.getNetwork(); + + // A plan with one logistic chain, containing a single carrier is created + LSPPlan singleOneEchelonChainPlan; + { + Carrier singleCarrier = + CarriersUtils.createCarrier(Id.create("singleCarrier", Carrier.class)); + singleCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + singleCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("veh_large"), DEPOT_LINK_ID, VEH_TYPE_LARGE_50)); + LSPResource singleCarrierResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + singleCarrier) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement singleCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("singleCarrierElement", LogisticChainElement.class)) + .setResource(singleCarrierResource) + .build(); + + LogisticChain singleChain = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("singleChain", LogisticChain.class)) + .addLogisticChainElement(singleCarrierElement) + .build(); + + final InitialShipmentAssigner singleSolutionShipmentAssigner = + MultipleChainsUtils.createPrimaryLogisticChainShipmentAssigner(); + singleOneEchelonChainPlan = + LSPUtils.createLSPPlan() + .addLogisticChain(singleChain) + .setInitialShipmentAssigner(singleSolutionShipmentAssigner); + + singleOneEchelonChainPlan.setType( + MultipleChainsUtils.LspPlanTypes.SINGLE_ONE_ECHELON_CHAIN.toString()); + } + + // A plan with two different logistic chains on the left and right, with respective carriers is + // created + LSPPlan multipleOneEchelonChainsPlan; + { + LogisticChainElement leftCarrierElement; + { + Carrier carrierLeft = CarriersUtils.createCarrier(Id.create("carrierLeft", Carrier.class)); + carrierLeft.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + carrierLeft, + CarrierVehicle.newInstance( + Id.createVehicleId("veh_small"), DEPOT_LINK_ID, VEH_TYPE_SMALL_05)); + LSPResource carrierLeftResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + carrierLeft) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + leftCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("leftCarrierElement", LogisticChainElement.class)) + .setResource(carrierLeftResource) + .build(); + } + + LogisticChainElement rightCarrierElement; + { + Carrier carrierRight = + CarriersUtils.createCarrier(Id.create("carrierRight", Carrier.class)); + carrierRight.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + carrierRight, + CarrierVehicle.newInstance( + Id.createVehicleId("veh_small"), DEPOT_LINK_ID, VEH_TYPE_SMALL_05)); + LSPResource carrierRightResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + carrierRight) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + rightCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("rightCarrierElement", LogisticChainElement.class)) + .setResource(carrierRightResource) + .build(); + } + + LogisticChain leftChain = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("leftChain", LogisticChain.class)) + .addLogisticChainElement(leftCarrierElement) + .build(); + + LogisticChain rightChain = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("rightChain", LogisticChain.class)) + .addLogisticChainElement(rightCarrierElement) + .build(); + + final InitialShipmentAssigner shipmentAssigner = + MultipleChainsUtils.createRandomLogisticChainShipmentAssigner(); + multipleOneEchelonChainsPlan = + LSPUtils.createLSPPlan() + .addLogisticChain(leftChain) + .addLogisticChain(rightChain) + .setInitialShipmentAssigner(shipmentAssigner); + + multipleOneEchelonChainsPlan.setType( + MultipleChainsUtils.LspPlanTypes.MULTIPLE_ONE_ECHELON_CHAINS.toString()); + } + + List lspPlans = new ArrayList<>(); + lspPlans.add(singleOneEchelonChainPlan); + lspPlans.add(multipleOneEchelonChainsPlan); + + LSP lsp = + LSPUtils.LSPBuilder.getInstance(Id.create("myLSP", LSP.class)) + .setInitialPlan(singleOneEchelonChainPlan) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + createResourcesListFromLSPPlans(lspPlans))) + .build(); + lsp.addPlan(multipleOneEchelonChainsPlan); + + log.info("create initial LSPShipments"); + log.info("assign the shipments to the LSP"); + for (LspShipment lspShipment : createInitialLSPShipments()) { + lsp.assignShipmentToLSP(lspShipment); + } + + log.info("schedule the LSP with the shipments and according to the scheduler of the Resource"); + lsp.scheduleLogisticChains(); + + return lsp; + } + + private static Collection createInitialLSPShipments() { + List shipmentList = new ArrayList<>(); + int capacityDemand = 1; + + for (int i = 1; i <= 10; i++) { + if (i % 2 != 0) { + Id id = Id.create("ShipmentLeft_" + i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + + builder.setCapacityDemand(capacityDemand); + builder.setFromLinkId(DEPOT_LINK_ID); + final Id shipmentLeftLinkId = Id.createLinkId("i(1,9)R"); + builder.setToLinkId(shipmentLeftLinkId); + + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + shipmentList.add(builder.build()); + } else { + Id id = Id.create("ShipmentRight_" + i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + + builder.setCapacityDemand(capacityDemand); + builder.setFromLinkId(DEPOT_LINK_ID); + final Id shipmentRightLinkId = Id.createLinkId("j(9,9)"); + builder.setToLinkId(shipmentRightLinkId); + + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + shipmentList.add(builder.build()); + } + } + return shipmentList; + } + + private static List createResourcesListFromLSPPlans(List lspPlans) { + log.info("Collecting all LSPResources from the LSPPlans"); + List resourceList = new ArrayList<>(); + for (LSPPlan lspPlan : lspPlans) { + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + for (LogisticChainElement logisticChainElement : logisticChain.getLogisticChainElements()) { + resourceList.add(logisticChainElement.getResource()); + } + } + } + return resourceList; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleMultipleTwoEchelonChainsReplanning.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleMultipleTwoEchelonChainsReplanning.java new file mode 100644 index 00000000000..a0204e7fb36 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleMultipleTwoEchelonChainsReplanning.java @@ -0,0 +1,441 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.*; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.BestPlanSelector; +import org.matsim.core.replanning.selectors.ExpBetaPlanSelector; +import org.matsim.core.replanning.selectors.GenericWorstPlanForRemovalSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +final class ExampleMultipleTwoEchelonChainsReplanning { + + static final double HUBCOSTS_FIX = 100; + private static final Logger log = + LogManager.getLogger(ExampleMultipleTwoEchelonChainsReplanning.class); + private static final Id DEPOT_LINK_ID = Id.createLinkId("i(5,0)"); + private static final Id HUB_LEFT_LINK_ID = Id.createLinkId("i(1,5)R"); + private static final Id HUB_RIGHT_LINK_ID = Id.createLinkId("j(9,5)"); + + private static final VehicleType VEH_TYPE_LARGE_50 = createVehTypeLarge50(); + private static final VehicleType VEH_TYPE_SMALL_05 = createVehTypeSmall05(); + + private static VehicleType createVehTypeLarge50() { + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("large50", VehicleType.class), TransportMode.car); + vehicleType.getCapacity().setOther(50); + vehicleType.getCostInformation().setCostsPerMeter(0.01); + vehicleType.getCostInformation().setCostsPerSecond(0.01); + vehicleType.getCostInformation().setFixedCost(150.); + vehicleType.setMaximumVelocity(10); + vehicleType.setNetworkMode(TransportMode.car); + + return vehicleType; + } + + private static VehicleType createVehTypeSmall05() { + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("small05", VehicleType.class), TransportMode.car); + vehicleType.getCapacity().setOther(5); + vehicleType.getCostInformation().setCostsPerMeter(0.001); + vehicleType.getCostInformation().setCostsPerSecond(0.005); + vehicleType.getCostInformation().setFixedCost(25.); + vehicleType.setMaximumVelocity(10); + vehicleType.setNetworkMode(TransportMode.car); + + return vehicleType; + } + + private ExampleMultipleTwoEchelonChainsReplanning() {} + + public static void main(String[] args) { + log.info("Prepare config"); + Config config = prepareConfig(args); + + log.info("Prepare scenario"); + Scenario scenario = prepareScenario(config); + + log.info("Prepare controller"); + Controller controller = ControllerUtils.createController(scenario); + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + + // @formatter:off + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + final EventBasedCarrierScorer4MultipleChains carrierScorer = new EventBasedCarrierScorer4MultipleChains(); + bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); + bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); + bind(CarrierStrategyManager.class).toProvider( () -> { + CarrierStrategyManager strategyManager = CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy( new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + return strategyManager; + }); + bind(LSPStrategyManager.class).toProvider( () -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy( new GenericPlanStrategyImpl<>( new ExpBetaPlanSelector<>(new ScoringConfigGroup())), null, 1); + strategyManager.addStrategy( ProximityStrategyFactory.createStrategy(scenario.getNetwork()), null, 1); + strategyManager.setMaxPlansPerAgent(5); + strategyManager.setPlanSelectorForRemoval( new GenericWorstPlanForRemovalSelector<>()); + return strategyManager; + }); + } + }); + // @formatter:on + + log.info("Run MATSim"); + + // The VSP default settings are designed for person transport simulation. After talking to Kai, + // they will be set to WARN here. Kai MT may'23 + controller + .getConfig() + .vspExperimental() + .setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + log.info("Done."); + } + + private static Config prepareConfig(String[] args) { + Config config = ConfigUtils.createConfig(); + if (args.length != 0) { + for (String arg : args) { + log.warn(arg); + } + ConfigUtils.applyCommandline(config, args); + } else { + config.controller().setOutputDirectory("output/multipleTwoEchelonChainsReplanning"); + config.controller().setLastIteration(8); + } + config + .network() + .setInputFile( + String.valueOf( + IOUtils.extendUrl( + ExamplesUtils.getTestScenarioURL("freight-chessboard-9x9"), "grid9x9.xml"))); + config + .controller() + .setOverwriteFileSetting( + OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setWriteEventsInterval(1); + + FreightCarriersConfigGroup freightConfig = + ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + return config; + } + + private static Scenario prepareScenario(Config config) { + Scenario scenario = ScenarioUtils.loadScenario(config); + + for (Link link : scenario.getNetwork().getLinks().values()) { + link.setFreespeed(30 / 3.6); + link.setCapacity(1000); + } + + log.info("Add LSP to the scenario"); + LSPUtils.addLSPs(scenario, new LSPs(Collections.singletonList(createLSP(scenario)))); + + return scenario; + } + + private static LSP createLSP(Scenario scenario) { + log.info("create LSP"); + Network network = scenario.getNetwork(); + + // A plan with a two hub chains is created + LSPPlan multipleTwoEchelonChainsPlan; + { + LogisticChain hubChainLeft; + { + Carrier mainCarrierLeft = + CarriersUtils.createCarrier(Id.create("mainCarrierLeft", Carrier.class)); + mainCarrierLeft + .getCarrierCapabilities() + .setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + mainCarrierLeft, + CarrierVehicle.newInstance( + Id.createVehicleId("mainTruck"), DEPOT_LINK_ID, VEH_TYPE_LARGE_50)); + LSPResource mainCarrierResourceLeft = + ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainCarrierLeft) + .setFromLinkId(DEPOT_LINK_ID) + .setMainRunCarrierScheduler( + ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setToLinkId(HUB_LEFT_LINK_ID) + .setVehicleReturn(ResourceImplementationUtils.VehicleReturn.returnToFromLink) + .build(); + + LogisticChainElement mainCarrierElementLeft = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("mainCarrierElementLeft", LogisticChainElement.class)) + .setResource(mainCarrierResourceLeft) + .build(); + + LSPResourceScheduler hubSchedulerLeft = + ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed(10) + .setCapacityNeedLinear(1) + .build(); + + LSPResource hubResourceLeft = + ResourceImplementationUtils.TransshipmentHubBuilder.newInstance( + Id.create("HubLeft", LSPResource.class), HUB_LEFT_LINK_ID, scenario) + .setTransshipmentHubScheduler(hubSchedulerLeft) + .build(); + LSPUtils.setFixedCost(hubResourceLeft, HUBCOSTS_FIX); + + LogisticChainElement hubElementLeft = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("HubElement", LogisticChainElement.class)) + .setResource(hubResourceLeft) + .build(); + + Carrier distributionCarrierLeft = + CarriersUtils.createCarrier(Id.create("distributionCarrierLeft", Carrier.class)); + distributionCarrierLeft + .getCarrierCapabilities() + .setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + distributionCarrierLeft, + CarrierVehicle.newInstance( + Id.createVehicleId("distributionTruck"), HUB_LEFT_LINK_ID, VEH_TYPE_SMALL_05)); + LSPResource distributionCarrierResourceLeft = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + distributionCarrierLeft) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement distributionCarrierElementLeft = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("distributionCarrierElementLeft", LogisticChainElement.class)) + .setResource(distributionCarrierResourceLeft) + .build(); + + mainCarrierElementLeft.connectWithNextElement(hubElementLeft); + hubElementLeft.connectWithNextElement(distributionCarrierElementLeft); + + hubChainLeft = + LSPUtils.LogisticChainBuilder.newInstance( + Id.create("hubChainLeft", LogisticChain.class)) + .addLogisticChainElement(mainCarrierElementLeft) + .addLogisticChainElement(hubElementLeft) + .addLogisticChainElement(distributionCarrierElementLeft) + .build(); + } + + LogisticChain hubChainRight; + { + Carrier mainCarrier = CarriersUtils.createCarrier(Id.create("mainCarrier", Carrier.class)); + mainCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + mainCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("mainTruck"), DEPOT_LINK_ID, VEH_TYPE_LARGE_50)); + LSPResource mainCarrierResource = + ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainCarrier) + .setFromLinkId(DEPOT_LINK_ID) + .setMainRunCarrierScheduler( + ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setToLinkId(HUB_RIGHT_LINK_ID) + .setVehicleReturn(ResourceImplementationUtils.VehicleReturn.returnToFromLink) + .build(); + + LogisticChainElement mainCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("mainCarrierElement", LogisticChainElement.class)) + .setResource(mainCarrierResource) + .build(); + + LSPResourceScheduler hubScheduler = + ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed(10) + .setCapacityNeedLinear(1) + .build(); + + LSPResource hubResourceRight = + ResourceImplementationUtils.TransshipmentHubBuilder.newInstance( + Id.create("HubRight", LSPResource.class), HUB_RIGHT_LINK_ID, scenario) + .setTransshipmentHubScheduler(hubScheduler) + .build(); + LSPUtils.setFixedCost(hubResourceRight, HUBCOSTS_FIX); + + LogisticChainElement hubElementRight = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("HubElement", LogisticChainElement.class)) + .setResource(hubResourceRight) + .build(); + + Carrier distributionCarrier = + CarriersUtils.createCarrier(Id.create("distributionCarrier", Carrier.class)); + distributionCarrier + .getCarrierCapabilities() + .setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + distributionCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("distributionTruck"), HUB_RIGHT_LINK_ID, VEH_TYPE_SMALL_05)); + LSPResource distributionCarrierResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + distributionCarrier) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement distributionCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("distributionCarrierElement", LogisticChainElement.class)) + .setResource(distributionCarrierResource) + .build(); + + mainCarrierElement.connectWithNextElement(hubElementRight); + hubElementRight.connectWithNextElement(distributionCarrierElement); + + hubChainRight = + LSPUtils.LogisticChainBuilder.newInstance( + Id.create("hubChainRight", LogisticChain.class)) + .addLogisticChainElement(mainCarrierElement) + .addLogisticChainElement(hubElementRight) + .addLogisticChainElement(distributionCarrierElement) + .build(); + } + + multipleTwoEchelonChainsPlan = + LSPUtils.createLSPPlan() + .addLogisticChain(hubChainLeft) + .addLogisticChain(hubChainRight) + .setInitialShipmentAssigner(MultipleChainsUtils.createRandomLogisticChainShipmentAssigner()); + } + + List lspPlans = new ArrayList<>(); + lspPlans.add(multipleTwoEchelonChainsPlan); + + LSP lsp = + LSPUtils.LSPBuilder.getInstance(Id.create("myLSP", LSP.class)) + .setInitialPlan(multipleTwoEchelonChainsPlan) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + createResourcesListFromLSPPlans(lspPlans))) + .build(); + + log.info("create initial LSPShipments"); + log.info("assign the shipments to the LSP"); + for (LspShipment lspShipment : createInitialLSPShipments()) { + lsp.assignShipmentToLSP(lspShipment); + } + + log.info("schedule the LSP with the shipments and according to the scheduler of the Resource"); + lsp.scheduleLogisticChains(); + + return lsp; + } + + private static Collection createInitialLSPShipments() { + List shipmentList = new ArrayList<>(); + int capacityDemand = 1; + + for (int i = 1; i <= 10; i++) { + if (i % 2 != 0) { + Id id = Id.create("ShipmentLeft_" + i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + + builder.setCapacityDemand(capacityDemand); + builder.setFromLinkId(DEPOT_LINK_ID); + final Id shipmentLeftLinkId = Id.createLinkId("i(1,9)R"); + builder.setToLinkId(shipmentLeftLinkId); + + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + shipmentList.add(builder.build()); + } else { + Id id = Id.create("ShipmentRight_" + i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + + builder.setCapacityDemand(capacityDemand); + builder.setFromLinkId(DEPOT_LINK_ID); + final Id shipmentRightLinkId = Id.createLinkId("j(9,9)"); + builder.setToLinkId(shipmentRightLinkId); + + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + shipmentList.add(builder.build()); + } + } + return shipmentList; + } + + private static List createResourcesListFromLSPPlans(List lspPlans) { + log.info("Collecting all LSPResources from the LSPPlans"); + List resourceList = new ArrayList<>(); + for (LSPPlan lspPlan : lspPlans) { + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + for (LogisticChainElement logisticChainElement : logisticChain.getLogisticChainElements()) { + resourceList.add(logisticChainElement.getResource()); + } + } + } + return resourceList; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleTwoLspsGroceryDeliveryMultipleChains.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleTwoLspsGroceryDeliveryMultipleChains.java new file mode 100644 index 00000000000..1ed5bcc050d --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleTwoLspsGroceryDeliveryMultipleChains.java @@ -0,0 +1,455 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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 * + * * + * *********************************************************************** + */ + +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import java.io.IOException; +import java.util.*; +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.Scenario; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.network.Link; +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.VspExperimentalConfigGroup; +import org.matsim.core.controler.*; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.BestPlanSelector; +import org.matsim.core.replanning.selectors.ExpBetaPlanSelector; +import org.matsim.core.replanning.selectors.GenericWorstPlanForRemovalSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.analysis.RunFreightAnalysisEventBased; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.examples.ExampleConstants; +import org.matsim.freight.logistics.resourceImplementations.CarrierSchedulerUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.vehicles.VehicleType; + +/** + * This bases on {@link ExampleGroceryDeliveryMultipleChains}. + * Now it will include two different LSPs + * + */ +final class ExampleTwoLspsGroceryDeliveryMultipleChains { + + private static final Logger log = LogManager.getLogger(ExampleTwoLspsGroceryDeliveryMultipleChains.class); + + private static final Id HUB_LINK_ID_NEUKOELLN = Id.createLinkId("91085"); + private static final double HUBCOSTS_FIX = 100; + + private static final List TOLLED_LINKS = ExampleConstants.TOLLED_LINK_LIST_BERLIN_BOTH_DIRECTIONS; + private static final List TOLLED_VEHICLE_TYPES = List.of("heavy40t"); // Für welche Fahrzeugtypen soll das MautSchema gelten? + private static final double TOLL_VALUE = 1000; + + private static final String CARRIER_PLAN_FILE = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/projects/freight/foodRetailing_wo_rangeConstraint/input/CarrierLEH_v2_withFleet_Shipment_OneTW_PickupTime_ICEVandBEV.xml"; + private static final String VEHICLE_TYPE_FILE = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/projects/freight/foodRetailing_wo_rangeConstraint/input/vehicleTypesBVWP100_DC_noTax.xml"; + private static final String EDEKA_SUPERMARKT_TROCKEN = "edeka_SUPERMARKT_TROCKEN"; + private static final String KAUFLAND_VERBRAUCHERMARKT_TROCKEN = "kaufland_VERBRAUCHERMARKT_TROCKEN"; + + private static final String OUTPUT_DIRECTORY = "output/groceryDelivery_kmt_1000_1LSPb"; + + + private ExampleTwoLspsGroceryDeliveryMultipleChains() {} + + public static void main(String[] args) { + log.info("Prepare config"); + Config config = prepareConfig(args); + + log.info("Prepare scenario"); + Scenario scenario = ScenarioUtils.loadScenario(config); + + CarrierVehicleTypes vehicleTypes = new CarrierVehicleTypes(); + CarrierVehicleTypeReader vehicleTypeReader = new CarrierVehicleTypeReader(vehicleTypes); + vehicleTypeReader.readFile(VEHICLE_TYPE_FILE); + //The following is needed, because since fall 2024 the vehicle types are not assigned to a network mode by default. + for (VehicleType vehicleType : vehicleTypes.getVehicleTypes().values()) { + vehicleType.setNetworkMode(TransportMode.car); + } + + Carriers carriers = new Carriers(); + CarrierPlanXmlReader carrierReader = new CarrierPlanXmlReader(carriers, vehicleTypes); + carrierReader.readFile(CARRIER_PLAN_FILE); + + Carrier carrierEdeka = carriers.getCarriers().get(Id.create(EDEKA_SUPERMARKT_TROCKEN, CarrierImpl.class)); + Carrier carrierKaufland = carriers.getCarriers().get(Id.create(KAUFLAND_VERBRAUCHERMARKT_TROCKEN, CarrierImpl.class)); + + log.info("Add LSP(s) to the scenario"); + Collection lsps = new LinkedList<>(); + lsps.add(createLspWithTwoChains(scenario, "Edeka", MultipleChainsUtils.createLSPShipmentsFromCarrierShipments(carrierEdeka), getDepotLinkFromVehicle(carrierEdeka), HUB_LINK_ID_NEUKOELLN, vehicleTypes, vehicleTypes, vehicleTypes)); + lsps.add(createLspWithTwoChains(scenario, "Kaufland", MultipleChainsUtils.createLSPShipmentsFromCarrierShipments(carrierKaufland), getDepotLinkFromVehicle(carrierKaufland), HUB_LINK_ID_NEUKOELLN, vehicleTypes, vehicleTypes, vehicleTypes)); + lsps.add(createLspWithDirectChain(scenario, "Edeka_DIRECT", MultipleChainsUtils.createLSPShipmentsFromCarrierShipments(carrierEdeka), getDepotLinkFromVehicle(carrierEdeka), vehicleTypes)); + lsps.add(createLspWithDirectChain(scenario, "Kaufland_DIRECT", MultipleChainsUtils.createLSPShipmentsFromCarrierShipments(carrierKaufland), getDepotLinkFromVehicle(carrierKaufland), vehicleTypes)); + LSPUtils.addLSPs(scenario, new LSPs(lsps)); + + Controller controller = prepareController(scenario); + + log.info("Run MATSim"); + + controller.run(); + + runCarrierAnalysis(controller.getControlerIO().getOutputPath(), config); + + log.info("Done."); + } + + private static Config prepareConfig(String[] args) { + Config config = ConfigUtils.createConfig(); + if (args.length != 0) { + for (String arg : args) { + log.warn(arg); + } + ConfigUtils.applyCommandline(config, args); + } else { + config.controller().setOutputDirectory(OUTPUT_DIRECTORY); + config.controller().setLastIteration(1); + } + + config.network().setInputFile("https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/berlin-v5.5-10pct/input/berlin-v5.5-network.xml.gz"); + config.global().setCoordinateSystem("EPSG:31468"); + config.global().setRandomSeed(4177); + config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + + // The VSP default settings are designed for person transport simulation. After talking to Kai, + // they will be set to WARN here. Kai MT may'23 + config.vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + + FreightCarriersConfigGroup freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + return config; + } + + private static Controller prepareController(Scenario scenario) { + log.info("Prepare controller"); + Controller controller = ControllerUtils.createController(scenario); + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + final EventBasedCarrierScorer4MultipleChains carrierScorer = + new EventBasedCarrierScorer4MultipleChains(); + carrierScorer.setToll(TOLL_VALUE); + carrierScorer.setTolledVehicleTypes(TOLLED_VEHICLE_TYPES); + carrierScorer.setTolledLinks(TOLLED_LINKS); + bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); + bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); + bind(CarrierStrategyManager.class) + .toProvider( + () -> { + CarrierStrategyManager strategyManager = + CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy( + new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + return strategyManager; + }); + bind(LSPStrategyManager.class) + .toProvider( + () -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new ExpBetaPlanSelector<>(new ScoringConfigGroup())), null, 1); + strategyManager.addStrategy(RandomShiftingStrategyFactory.createStrategy(), null, 4); + strategyManager.setMaxPlansPerAgent(5); + strategyManager.setPlanSelectorForRemoval(new GenericWorstPlanForRemovalSelector<>()); + return strategyManager; + }); + } + }); + return controller; + } + + private static void runCarrierAnalysis(String outputPath, Config config) { + RunFreightAnalysisEventBased freightAnalysis = new RunFreightAnalysisEventBased(outputPath +"/", outputPath +"/Analysis/", config.global().getCoordinateSystem()); + try { + freightAnalysis.runCompleteAnalysis(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Creates an LSP with two chains: + * - direct delivery + * - 2-echelon delivery + *

+ * TODO: Es sollten dann am Besten direkt die zur Verfügung stehenden VehicleTypes übergeben werden und diese dann hier jeweils (alle) hinzugefügt werden. + * Aktuell erfolgt die Auswahl ja noch hier. Das sollte dann aber nicht mehr so sein, sondern bereits weiter upstream definiert werden. + * kmt Jul'24 + * + * @param scenario the scenario, used e.g. for getting the network and register some stuff + * @param lspName String of LSP's Id + * @param lspShipments Collection of LSPShipments to be assigned to the LSP + * @param depotLinkId Id of the depot link + * @param hubLinkId location of the hub + * @param vehicleTypesMainRun vehicle types for the main run (2e-chain) + * @param vehicleTypesDistributionRun vehicle types for the distribution run (2e-chain) + * @param vehicleTypesDirect vehicle types for the direct run (direct chain) + * @return the LSP + */ + private static LSP createLspWithTwoChains(Scenario scenario, String lspName, Collection lspShipments, Id depotLinkId, Id hubLinkId, CarrierVehicleTypes vehicleTypesMainRun, CarrierVehicleTypes vehicleTypesDistributionRun, CarrierVehicleTypes vehicleTypesDirect) { + log.info("create LSP"); + //Chains + LogisticChain directChain = createDirectChain(scenario, lspName, depotLinkId, vehicleTypesDirect); + LogisticChain twoEchelonChain = createTwoEchelonChain(scenario, lspName, hubLinkId, depotLinkId, vehicleTypesMainRun, vehicleTypesDistributionRun); + + LSPPlan multipleMixedEchelonChainsPlan = + LSPUtils.createLSPPlan() + .addLogisticChain(directChain) + .addLogisticChain(twoEchelonChain) + .setInitialShipmentAssigner(MultipleChainsUtils.createRandomLogisticChainShipmentAssigner()); + + List lspPlans = List.of(multipleMixedEchelonChainsPlan); + + LSP lsp = LSPUtils.LSPBuilder.getInstance(Id.create(lspName, LSP.class)) + .setInitialPlan(multipleMixedEchelonChainsPlan) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + createResourcesListFromLSPPlans(lspPlans))) + .build(); + + log.info("assign the shipments to the LSP"); + for (LspShipment lspShipment : lspShipments) { + lsp.assignShipmentToLSP(lspShipment); + } + + log.info("schedule the LSP with the shipments and according to the scheduler of the Resource"); + lsp.scheduleLogisticChains(); + + return lsp; + } + + private static Id getDepotLinkFromVehicle(Carrier carrier) { + return carrier + .getCarrierCapabilities() + .getCarrierVehicles() + .values() + .iterator() + .next() + .getLinkId(); + } + + /* + TODO: Es sollten dann am Besten direkt die zur Verfügung stehenden VehicleTypes übergeben werden und diese dann hier jeweils (alle) hinzugefügt werden. + Aktuell erfolgt die Auswahl ja noch hier. Das sollte dann aber nicht mehr so sein, sondern bereits weiter upstream definiert werden. + kmt Jul'24 + */ + private static LogisticChain createTwoEchelonChain(Scenario scenario, String lspName, Id hubLinkId, Id depotLinkFromVehicles, CarrierVehicleTypes vehicleTypesMainRun, CarrierVehicleTypes vehicleTypesDistributionRun) { + LogisticChain hubChain; + Carrier mainCarrier = CarriersUtils.createCarrier(Id.create(lspName +"_mainCarrier", Carrier.class)); + mainCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + mainCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("mainTruck"), + depotLinkFromVehicles, + vehicleTypesMainRun.getVehicleTypes().get(Id.create("heavy40t", VehicleType.class)))); + LSPResource mainCarrierResource = + ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance( + mainCarrier) + .setFromLinkId(depotLinkFromVehicles) + .setMainRunCarrierScheduler( + ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setToLinkId(hubLinkId) + .setVehicleReturn(ResourceImplementationUtils.VehicleReturn.returnToFromLink) + .build(); + + LogisticChainElement mainCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("mainCarrierElement", LogisticChainElement.class)) + .setResource(mainCarrierResource) + .build(); + + LSPResourceScheduler hubScheduler = + ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed(10) + .setCapacityNeedLinear(1) + .build(); + + LSPResource hubResource = + ResourceImplementationUtils.TransshipmentHubBuilder.newInstance( + Id.create(lspName +"_Hub", LSPResource.class), hubLinkId, scenario) + .setTransshipmentHubScheduler(hubScheduler) + .build(); + + LSPUtils.setFixedCost(hubResource, HUBCOSTS_FIX); + + LogisticChainElement hubElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("HubElement", LogisticChainElement.class)) + .setResource(hubResource) + .build(); + + Carrier distributionCarrier = + CarriersUtils.createCarrier(Id.create(lspName +"_distributionCarrier", Carrier.class)); + distributionCarrier + .getCarrierCapabilities() + //.setNumberOfJspritIterations // TODO Das mal hier einbauen. --> Ist aktuell in CarrierUtils. + .setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + CarrierSchedulerUtils.setVrpLogic(distributionCarrier, LSPUtils.LogicOfVrp.serviceBased); + + CarriersUtils.addCarrierVehicle( + distributionCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("distributionTruck"), + hubLinkId, + vehicleTypesDistributionRun + .getVehicleTypes() + .get(Id.create("heavy40t_electro", VehicleType.class)))); + LSPResource distributionCarrierResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + distributionCarrier) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement distributionCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("distributionCarrierElement", LogisticChainElement.class)) + .setResource(distributionCarrierResource) + .build(); + + mainCarrierElement.connectWithNextElement(hubElement); + hubElement.connectWithNextElement(distributionCarrierElement); + + //TODO: Hier das Verbinden einfügen und in der Reihenfolge ist es. KMT Nov'24 + hubChain = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("hubChain", LogisticChain.class)) + .addLogisticChainElement(mainCarrierElement) + .addLogisticChainElement(hubElement) + .addLogisticChainElement(distributionCarrierElement) + .build(); + return hubChain; + } + + /** + * Creates an LSP with direct chains: + * + * @param scenario the scenario, used e.g. for getting the network and register some stuff + * @param lspName String of LSP's Id + * @param lspShipments Collection of LSPShipments to be assigned to the LSP + * @param depotLinkId Id of the depot link + * @param vehicleTypesDirect vehicle types for the direct run (direct chain) + * @return the LSP + */ + private static LSP createLspWithDirectChain(Scenario scenario, String lspName, Collection lspShipments, Id depotLinkId, CarrierVehicleTypes vehicleTypesDirect) { + log.info("create LSP"); + + LSPPlan lspPlan = LSPUtils.createLSPPlan() + .addLogisticChain(createDirectChain(scenario, lspName, depotLinkId, vehicleTypesDirect)) + .setInitialShipmentAssigner(MultipleChainsUtils.createRandomLogisticChainShipmentAssigner()); + + LSP lsp = + LSPUtils.LSPBuilder.getInstance(Id.create(lspName, LSP.class)) + .setInitialPlan(lspPlan) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + createResourcesListFromLSPPlans(List.of(lspPlan)))) + .build(); + + log.info("assign the shipments to the LSP"); + for (LspShipment lspShipment : lspShipments) { + lsp.assignShipmentToLSP(lspShipment); + } + + log.info("schedule the LSP with the shipments and according to the scheduler of the Resource"); + lsp.scheduleLogisticChains(); + + return lsp; + } + + + private static LogisticChain createDirectChain(Scenario scenario, String lspName, Id depotLinkFromVehicles, CarrierVehicleTypes vehicleTypes) { + LogisticChain directChain; + Carrier directCarrier = CarriersUtils.createCarrier(Id.create(lspName +"_directCarrier", Carrier.class)); + directCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + CarrierSchedulerUtils.setVrpLogic(directCarrier, LSPUtils.LogicOfVrp.serviceBased); + + CarriersUtils.addCarrierVehicle(directCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("directCarrierTruck"), + depotLinkFromVehicles, + vehicleTypes.getVehicleTypes().get(Id.create("heavy40t", VehicleType.class)))); + LSPResource singleCarrierResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(directCarrier) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement singleCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("directCarrierElement", LogisticChainElement.class)) + .setResource(singleCarrierResource) + .build(); + + directChain = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("directChain", LogisticChain.class)) + .addLogisticChainElement(singleCarrierElement) + .build(); + return directChain; + } + + private static List createResourcesListFromLSPPlans(List lspPlans) { + log.info("Collecting all LSPResources from the LSPPlans"); + List resourceList = new ArrayList<>(); + for (LSPPlan lspPlan : lspPlans) { + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + for (LogisticChainElement logisticChainElement : logisticChain.getLogisticChainElements()) { + resourceList.add(logisticChainElement.getResource()); + } + } + } + return resourceList; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleTwoLspsGroceryDeliveryMultipleChainsWithToll.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleTwoLspsGroceryDeliveryMultipleChainsWithToll.java new file mode 100644 index 00000000000..cd397b50937 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ExampleTwoLspsGroceryDeliveryMultipleChainsWithToll.java @@ -0,0 +1,482 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import java.io.IOException; +import java.util.*; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.analysis.personMoney.PersonMoneyEventsAnalysisModule; +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.network.Link; +import org.matsim.contrib.roadpricing.*; +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.VspExperimentalConfigGroup; +import org.matsim.core.controler.*; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.BestPlanSelector; +import org.matsim.core.replanning.selectors.ExpBetaPlanSelector; +import org.matsim.core.replanning.selectors.GenericWorstPlanForRemovalSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.misc.Time; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.analysis.RunFreightAnalysisEventBased; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.examples.ExampleConstants; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +/** + * This bases on {@link ExampleTwoLspsGroceryDeliveryMultipleChains}. + * It is extended in a way that it will use the roadpricing contrib... + * This class is here only for development and will be merged into {@link ExampleTwoLspsGroceryDeliveryMultipleChains} + * once the result is satisfying. + * KMT, Jul'24 + */ +final class ExampleTwoLspsGroceryDeliveryMultipleChainsWithToll { + + private static final Logger log = LogManager.getLogger(ExampleTwoLspsGroceryDeliveryMultipleChainsWithToll.class); + + private static final Id HUB_LINK_ID_NEUKOELLN = Id.createLinkId("91085"); + private static final double HUBCOSTS_FIX = 100; + + private static final List TOLLED_LINKS = ExampleConstants.TOLLED_LINK_LIST_BERLIN_BOTH_DIRECTIONS; + private static final List TOLLED_VEHICLE_TYPES = List.of("heavy40t"); // Für welche Fahrzeugtypen soll das MautSchema gelten? + private static final double TOLL_VALUE = 1000; + + private static final String CARRIER_PLAN_FILE = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/projects/freight/foodRetailing_wo_rangeConstraint/input/CarrierLEH_v2_withFleet_Shipment_OneTW_PickupTime_ICEVandBEV.xml"; + private static final String VEHICLE_TYPE_FILE = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/projects/freight/foodRetailing_wo_rangeConstraint/input/vehicleTypesBVWP100_DC_noTax.xml"; + private static final String EDEKA_SUPERMARKT_TROCKEN = "edeka_SUPERMARKT_TROCKEN"; + private static final String KAUFLAND_VERBRAUCHERMARKT_TROCKEN = "kaufland_VERBRAUCHERMARKT_TROCKEN"; + + private static final String OUTPUT_DIRECTORY = "output/groceryDelivery_kmt_1000_newTollScoring_1it"; + + + private ExampleTwoLspsGroceryDeliveryMultipleChainsWithToll() {} + + public static void main(String[] args) { + log.info("Prepare config"); + Config config = prepareConfig(args); + + log.info("Prepare scenario"); + Scenario scenario = ScenarioUtils.loadScenario(config); + + CarrierVehicleTypes vehicleTypes = new CarrierVehicleTypes(); + CarrierVehicleTypeReader vehicleTypeReader = new CarrierVehicleTypeReader(vehicleTypes); + vehicleTypeReader.readFile(VEHICLE_TYPE_FILE); + //The following is needed, because since fall 2024 the vehicle types are not assigned to a network mode by default. + for (VehicleType vehicleType : vehicleTypes.getVehicleTypes().values()) { + vehicleType.setNetworkMode(TransportMode.car); + } + + Carriers carriers = new Carriers(); + CarrierPlanXmlReader carrierReader = new CarrierPlanXmlReader(carriers, vehicleTypes); + carrierReader.readFile(CARRIER_PLAN_FILE); + + Carrier carrierEdeka = carriers.getCarriers().get(Id.create(EDEKA_SUPERMARKT_TROCKEN, CarrierImpl.class)); + Carrier carrierKaufland = carriers.getCarriers().get(Id.create(KAUFLAND_VERBRAUCHERMARKT_TROCKEN, CarrierImpl.class)); + + RoadPricingScheme rpScheme = setUpRoadpricing(scenario); + + log.info("Add LSP(s) to the scenario"); + Collection lsps = new LinkedList<>(); + lsps.add(createLspWithTwoChains(scenario, "Edeka", MultipleChainsUtils.createLSPShipmentsFromCarrierShipments(carrierEdeka), getDepotLinkFromVehicle(carrierEdeka), HUB_LINK_ID_NEUKOELLN, vehicleTypes, vehicleTypes, vehicleTypes)); + lsps.add(createLspWithTwoChains(scenario, "Kaufland", MultipleChainsUtils.createLSPShipmentsFromCarrierShipments(carrierKaufland), getDepotLinkFromVehicle(carrierKaufland), HUB_LINK_ID_NEUKOELLN, vehicleTypes, vehicleTypes, vehicleTypes)); + lsps.add(createLspWithDirectChain(scenario, "Edeka_DIRECT", MultipleChainsUtils.createLSPShipmentsFromCarrierShipments(carrierEdeka), getDepotLinkFromVehicle(carrierEdeka), vehicleTypes)); + lsps.add(createLspWithDirectChain(scenario, "Kaufland_DIRECT", MultipleChainsUtils.createLSPShipmentsFromCarrierShipments(carrierKaufland), getDepotLinkFromVehicle(carrierKaufland), vehicleTypes)); + LSPUtils.addLSPs(scenario, new LSPs(lsps)); + + + Controller controller = prepareController(scenario, rpScheme); + + log.info("Run MATSim"); + + // The VSP default settings are designed for person transport simulation. After talking to Kai, + // they will be set to WARN here. Kai MT may'23 + controller + .getConfig() + .vspExperimental() + .setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + runCarrierAnalysis(controller.getControlerIO().getOutputPath(), config); + + log.info("Done."); + } + + private static Config prepareConfig(String[] args) { + Config config = ConfigUtils.createConfig(); + if (args.length != 0) { + for (String arg : args) { + log.warn(arg); + } + ConfigUtils.applyCommandline(config, args); + } else { + config.controller().setOutputDirectory(OUTPUT_DIRECTORY); + config.controller().setLastIteration(1); + } + + config.network().setInputFile("https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/berlin-v5.5-10pct/input/berlin-v5.5-network.xml.gz"); + config.global().setCoordinateSystem("EPSG:31468"); + config.global().setRandomSeed(4177); + config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + + FreightCarriersConfigGroup freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + return config; + } + + private static Controller prepareController(Scenario scenario, RoadPricingScheme rpScheme) { + log.info("Prepare controller"); + Controller controller = ControllerUtils.createController(scenario); + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + install(new PersonMoneyEventsAnalysisModule()); + } + }); + + controller.addOverridingModule( + new AbstractModule() { + @Override + public void install() { + bind(CarrierScoringFunctionFactory.class).toInstance(new EventBasedCarrierScorer4MultipleChainsInclToll()); + bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); + bind(CarrierStrategyManager.class) + .toProvider( + () -> { + CarrierStrategyManager strategyManager = + CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy( + new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + return strategyManager; + }); + bind(LSPStrategyManager.class) + .toProvider( + () -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new ExpBetaPlanSelector<>(new ScoringConfigGroup())), null, 1); + strategyManager.addStrategy(RandomShiftingStrategyFactory.createStrategy(), null, 4); + strategyManager.setMaxPlansPerAgent(5); + strategyManager.setPlanSelectorForRemoval(new GenericWorstPlanForRemovalSelector<>()); + return strategyManager; + }); + } + }); + if (!rpScheme.getTolledLinkIds().isEmpty()) { + // RoadPricing.configure(controller); + controller.addOverridingModule( new RoadPricingModule(rpScheme) ); + } + return controller; + } + + /* + * Set up roadpricing --- this is a copy paste from KMT lecture in GVSim --> need some adaptions + * TODO Adapt settings + */ + + private static RoadPricingSchemeUsingTollFactor setUpRoadpricing(Scenario scenario) { + + //Create Rp Scheme from code. + RoadPricingSchemeImpl scheme = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); + + /* Configure roadpricing scheme. */ + RoadPricingUtils.setName(scheme, "MautFromCodeKMT"); + RoadPricingUtils.setType(scheme, RoadPricingScheme.TOLL_TYPE_LINK); + RoadPricingUtils.setDescription(scheme, "Mautdaten erstellt aus Link-Liste."); + + /* Add general toll. */ + for (String linkIdString : TOLLED_LINKS) { + RoadPricingUtils.addLink(scheme, Id.createLinkId(linkIdString)); + } + + RoadPricingUtils.createAndAddGeneralCost(scheme, + Time.parseTime("00:00:00"), + Time.parseTime("72:00:00"), + TOLL_VALUE); + ///___ End creating from Code + + // Wenn FzgTypId in Liste, erfolgt die Bemautung mit dem Kostensatz (Faktor = 1), + // sonst mit 0 (Faktor = 0). ((MATSim seite) + TollFactor tollFactor = + (personId, vehicleId, linkId, time) -> { + var vehTypeId = VehicleUtils.findVehicle(vehicleId, scenario).getType().getId(); + if (TOLLED_VEHICLE_TYPES.contains(vehTypeId.toString())) { + return 1; + } else { + return 0; + } + }; + + return new RoadPricingSchemeUsingTollFactor(scheme, tollFactor); + } + + private static void runCarrierAnalysis(String outputPath, Config config) { + RunFreightAnalysisEventBased freightAnalysis = new RunFreightAnalysisEventBased(outputPath +"/", outputPath +"/Analysis/", config.global().getCoordinateSystem()); + try { + freightAnalysis.runCompleteAnalysis(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Creates an LSP with two chains: + * - direct delivery + * - 2-echelon delivery + *

+ * TODO: Es sollten dann am Besten direkt die zur Verfügung stehenden VehicleTypes übergeben werden und diese dann hier jeweils (alle) hinzugefügt werden. + * Aktuell erfolgt die Auswahl ja noch hier. Das sollte dann aber nicht mehr so sein, sondern bereits weiter upstream definiert werden. + * kmt Jul'24 + * + * @param scenario the scenario, used e.g. for getting the network and register some stuff + * @param lspName String of LSP's Id + * @param lspShipments Collection of LSPShipments to be assigned to the LSP + * @param depotLinkId Id of the depot link + * @param hubLinkId location of the hub + * @param vehicleTypesMainRun vehicle types for the main run (2e-chain) + * @param vehicleTypesDistributionRun vehicle types for the distribution run (2e-chain) + * @param vehicleTypesDirect vehicle types for the direct run (direct chain) + * @return the LSP + */ + private static LSP createLspWithTwoChains(Scenario scenario, String lspName, Collection lspShipments, Id depotLinkId, Id hubLinkId, CarrierVehicleTypes vehicleTypesMainRun, CarrierVehicleTypes vehicleTypesDistributionRun, CarrierVehicleTypes vehicleTypesDirect) { + log.info("create LSP"); + //Chains + LogisticChain directChain = createDirectChain(scenario, lspName, depotLinkId, vehicleTypesDirect); + LogisticChain twoEchelonChain = createTwoEchelonChain(scenario, lspName, hubLinkId, depotLinkId, vehicleTypesMainRun, vehicleTypesDistributionRun); + + LSPPlan multipleMixedEchelonChainsPlan = + LSPUtils.createLSPPlan() + .addLogisticChain(directChain) + .addLogisticChain(twoEchelonChain) + .setInitialShipmentAssigner(MultipleChainsUtils.createRandomLogisticChainShipmentAssigner()); + + List lspPlans = List.of(multipleMixedEchelonChainsPlan); + + LSP lsp = LSPUtils.LSPBuilder.getInstance(Id.create(lspName, LSP.class)) + .setInitialPlan(multipleMixedEchelonChainsPlan) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + createResourcesListFromLSPPlans(lspPlans))) + .build(); + + log.info("assign the shipments to the LSP"); + for (LspShipment lspShipment : lspShipments) { + lsp.assignShipmentToLSP(lspShipment); + } + + log.info("schedule the LSP with the shipments and according to the scheduler of the Resource"); + lsp.scheduleLogisticChains(); + + return lsp; + } + + private static Id getDepotLinkFromVehicle(Carrier carrier) { + return carrier + .getCarrierCapabilities() + .getCarrierVehicles() + .values() + .iterator() + .next() + .getLinkId(); + } + + /* + TODO: Es sollten dann am Besten direkt die zur Verfügung stehenden VehicleTypes übergeben werden und diese dann hier jeweils (alle) hinzugefügt werden. + Aktuell erfolgt die Auswahl ja noch hier. Das sollte dann aber nicht mehr so sein, sondern bereits weiter upstream definiert werden. + kmt Jul'24 + */ + private static LogisticChain createTwoEchelonChain(Scenario scenario, String lspName, Id hubLinkId, Id depotLinkFromVehicles, CarrierVehicleTypes vehicleTypesMainRun, CarrierVehicleTypes vehicleTypesDistributionRun) { + LogisticChain hubChain; + Carrier mainCarrier = CarriersUtils.createCarrier(Id.create(lspName +"_mainCarrier", Carrier.class)); + mainCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + mainCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("mainTruck"), + depotLinkFromVehicles, + vehicleTypesMainRun.getVehicleTypes().get(Id.create("heavy40t", VehicleType.class)))); + LSPResource mainCarrierResource = + ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance( + mainCarrier) + .setFromLinkId(depotLinkFromVehicles) + .setMainRunCarrierScheduler( + ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setToLinkId(hubLinkId) + .setVehicleReturn(ResourceImplementationUtils.VehicleReturn.returnToFromLink) + .build(); + + LogisticChainElement mainCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("mainCarrierElement", LogisticChainElement.class)) + .setResource(mainCarrierResource) + .build(); + + LSPResourceScheduler hubScheduler = + ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed(10) + .setCapacityNeedLinear(1) + .build(); + + LSPResource hubResource = + ResourceImplementationUtils.TransshipmentHubBuilder.newInstance( + Id.create(lspName +"_Hub", LSPResource.class), hubLinkId, scenario) + .setTransshipmentHubScheduler(hubScheduler) + .build(); + + LSPUtils.setFixedCost(hubResource, HUBCOSTS_FIX); + + LogisticChainElement hubElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("HubElement", LogisticChainElement.class)) + .setResource(hubResource) + .build(); + + Carrier distributionCarrier = + CarriersUtils.createCarrier(Id.create(lspName +"_distributionCarrier", Carrier.class)); + distributionCarrier + .getCarrierCapabilities() + //.setNumberOfJspritIterations // TODO Das mal hier einbauen. --> Ist aktuell in CarrierUtils. + .setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle( + distributionCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("distributionTruck"), + hubLinkId, + vehicleTypesDistributionRun + .getVehicleTypes() + .get(Id.create("heavy40t_electro", VehicleType.class)))); + LSPResource distributionCarrierResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + distributionCarrier) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement distributionCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("distributionCarrierElement", LogisticChainElement.class)) + .setResource(distributionCarrierResource) + .build(); + + mainCarrierElement.connectWithNextElement(hubElement); + hubElement.connectWithNextElement(distributionCarrierElement); + + hubChain = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("hubChain", LogisticChain.class)) + .addLogisticChainElement(mainCarrierElement) + .addLogisticChainElement(hubElement) + .addLogisticChainElement(distributionCarrierElement) + .build(); + return hubChain; + } + + /** + * Creates an LSP with direct chains: + * + * @param scenario the scenario, used e.g. for getting the network and register some stuff + * @param lspName String of LSP's Id + * @param lspShipments Collection of LSPShipments to be assigned to the LSP + * @param depotLinkId Id of the depot link + * @param vehicleTypesDirect vehicle types for the direct run (direct chain) + * @return the LSP + */ + private static LSP createLspWithDirectChain(Scenario scenario, String lspName, Collection lspShipments, Id depotLinkId, CarrierVehicleTypes vehicleTypesDirect) { + log.info("create LSP"); + + LSPPlan lspPlan = LSPUtils.createLSPPlan() + .addLogisticChain(createDirectChain(scenario, lspName, depotLinkId, vehicleTypesDirect)) + .setInitialShipmentAssigner(MultipleChainsUtils.createRandomLogisticChainShipmentAssigner()); + + LSP lsp = + LSPUtils.LSPBuilder.getInstance(Id.create(lspName, LSP.class)) + .setInitialPlan(lspPlan) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + createResourcesListFromLSPPlans(List.of(lspPlan)))) + .build(); + + log.info("assign the shipments to the LSP"); + for (LspShipment lspShipment : lspShipments) { + lsp.assignShipmentToLSP(lspShipment); + } + + log.info("schedule the LSP with the shipments and according to the scheduler of the Resource"); + lsp.scheduleLogisticChains(); + + return lsp; + } + + + private static LogisticChain createDirectChain(Scenario scenario, String lspName, Id depotLinkFromVehicles, CarrierVehicleTypes vehicleTypes) { + LogisticChain directChain; + Carrier directCarrier = CarriersUtils.createCarrier(Id.create(lspName +"_directCarrier", Carrier.class)); + directCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle(directCarrier, + CarrierVehicle.newInstance( + Id.createVehicleId("directCarrierTruck"), + depotLinkFromVehicles, + vehicleTypes.getVehicleTypes().get(Id.create("heavy40t", VehicleType.class)))); + LSPResource singleCarrierResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(directCarrier) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement singleCarrierElement = + LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("directCarrierElement", LogisticChainElement.class)) + .setResource(singleCarrierResource) + .build(); + + directChain = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("directChain", LogisticChain.class)) + .addLogisticChainElement(singleCarrierElement) + .build(); + return directChain; + } + + private static List createResourcesListFromLSPPlans(List lspPlans) { + log.info("Collecting all LSPResources from the LSPPlans"); + List resourceList = new ArrayList<>(); + for (LSPPlan lspPlan : lspPlans) { + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + for (LogisticChainElement logisticChainElement : logisticChain.getLogisticChainElements()) { + resourceList.add(logisticChainElement.getResource()); + } + } + } + return resourceList; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/MultipleChainsUtils.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/MultipleChainsUtils.java new file mode 100644 index 00000000000..30517805da5 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/MultipleChainsUtils.java @@ -0,0 +1,98 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import static java.util.stream.Collectors.toMap; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; +import org.matsim.api.core.v01.Id; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.CarrierShipment; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; + +class MultipleChainsUtils { + private MultipleChainsUtils() {} + + public static RandomLogisticChainShipmentAssigner createRandomLogisticChainShipmentAssigner() { + return new RandomLogisticChainShipmentAssigner(); + } + + public static RoundRobinLogisticChainShipmentAssigner + createRoundRobinLogisticChainShipmentAssigner() { + return new RoundRobinLogisticChainShipmentAssigner(); + } + + public static PrimaryLogisticChainShipmentAssigner createPrimaryLogisticChainShipmentAssigner() { + return new PrimaryLogisticChainShipmentAssigner(); + } + + public static Collection createLSPShipmentsFromCarrierShipments(Carrier carrier) { + List shipmentList = new ArrayList<>(); + + List carrierShipments = carrier.getShipments().values().stream().toList(); + + for (CarrierShipment shipment : carrierShipments) { + LspShipmentUtils.LspShipmentBuilder builder = + LspShipmentUtils.LspShipmentBuilder.newInstance( + Id.create(shipment.getId().toString(), LspShipment.class)); + builder.setCapacityDemand(shipment.getSize()); + builder.setFromLinkId(shipment.getFrom()); + builder.setToLinkId(shipment.getTo()); + builder.setStartTimeWindow(shipment.getPickupTimeWindow()); + builder.setEndTimeWindow(shipment.getDeliveryTimeWindow()); + builder.setPickupServiceTime(shipment.getPickupServiceTime()); + builder.setDeliveryServiceTime(shipment.getDeliveryServiceTime()); + shipmentList.add(builder.build()); + } + return shipmentList; + } + + public enum LspPlanTypes { + SINGLE_ONE_ECHELON_CHAIN("singleOneEchelonChain"), + SINGLE_TWO_ECHELON_CHAIN("singleTwoEchelonChain"), + MULTIPLE_ONE_ECHELON_CHAINS("multipleOneEchelonChains"), + MULTIPLE_TWO_ECHELON_CHAINS("multipleTwoEchelonChains"), + MULTIPLE_MIXED_ECHELON_CHAINS("multipleMixedEchelonChains"); + + private static final Map stringToEnum = + Stream.of(values()).collect(toMap(Object::toString, e -> e)); + private final String label; + + LspPlanTypes(String label) { + this.label = label; + } + + public static LspPlanTypes fromString(String label) { + return stringToEnum.get(label); + } + + @Override + public String toString() { + return label; + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/MyLSPScorer.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/MyLSPScorer.java new file mode 100644 index 00000000000..e82311ffcbf --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/MyLSPScorer.java @@ -0,0 +1,104 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.TransshipmentHubResource; + +/** + * A scorer for the LSP. It uses the scores of the - carriers: Take the carrier's score and add it + * to the LSP's score - hubs: currently a very simple fixed costs scoring (see below {@link + * #scoreHub()}) + * + * @author Kai Martins-Turner (kturner) + */ +/*package-private*/ class MyLSPScorer implements LSPScorer { + final Logger logger = LogManager.getLogger(MyLSPScorer.class); + private double score = 0; + private LSP lsp; + + @Override + public void reset(int iteration) { + score = 0.; + } + + @Override + public double getScoreForCurrentPlan() { + scoreLspCarriers(); + scoreHub(); + scoreMissingShipments(); + return score; + } + + private void scoreLspCarriers() { + var lspPlan = lsp.getSelectedPlan(); + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + for (LogisticChainElement logisticChainElement : logisticChain.getLogisticChainElements()) { + if (logisticChainElement.getResource() instanceof LSPCarrierResource carrierResource) { + var carriersScore = carrierResource.getCarrier().getSelectedPlan().getScore(); + if (carriersScore != null) { + score = score + carriersScore; + } + } + } + } + } + + /** + * If a hub resource is in the selected plan of the LSP, it will get scored. + * + *

This is somehow a quickfix, because the hubs do **not** have any own events yet. This needs + * to be implemented later KMT oct'22 + */ + private void scoreHub() { + var lspPlan = lsp.getSelectedPlan(); + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + for (LogisticChainElement logisticChainElement : logisticChain.getLogisticChainElements()) { + if (logisticChainElement.getResource() instanceof TransshipmentHubResource hub) { + score = score - LSPUtils.getFixedCost(hub); + } + } + } + } + + private void scoreMissingShipments() { + LSPPlan lspPlan = lsp.getSelectedPlan(); + int lspPlanShipmentCount = + lspPlan.getLogisticChains().stream() + .mapToInt(logisticChain -> logisticChain.getLspShipmentIds().size()) + .sum(); + int shipmentCountDifference = lsp.getLspShipments().size() - lspPlanShipmentCount; + if (shipmentCountDifference > 0) { + logger.error( + "LspPlan contains less shipments than LSP, " + + "shipments probably lost during replanning."); + score -= 10000 * shipmentCountDifference; + } + } + + @Override + public void setEmbeddingContainer(LSP pointer) { + this.lsp = pointer; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/PrimaryLogisticChainShipmentAssigner.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/PrimaryLogisticChainShipmentAssigner.java new file mode 100644 index 00000000000..62365040897 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/PrimaryLogisticChainShipmentAssigner.java @@ -0,0 +1,46 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import org.matsim.core.gbl.Gbl; +import org.matsim.freight.logistics.InitialShipmentAssigner; +import org.matsim.freight.logistics.LSPPlan; +import org.matsim.freight.logistics.LogisticChain; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * The {@link LspShipment} is assigned to the first {@link LogisticChain}. In case of one chain the + * shipment is assigned to that chain. If there are more chains, the shipment is assigned to the + * first of all chains. Requirements: There must be at least one logisticChain in the plan + */ +class PrimaryLogisticChainShipmentAssigner implements InitialShipmentAssigner { + + + public PrimaryLogisticChainShipmentAssigner() {} + + @Override + public void assignToPlan(LSPPlan lspPlan, LspShipment lspShipment) { + Gbl.assertIf(!lspPlan.getLogisticChains().isEmpty()); + LogisticChain firstLogisticChain = lspPlan.getLogisticChains().iterator().next(); + firstLogisticChain.addShipmentToChain(lspShipment); + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ProximityStrategyFactory.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ProximityStrategyFactory.java new file mode 100644 index 00000000000..1e48dec8363 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/ProximityStrategyFactory.java @@ -0,0 +1,149 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +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.config.groups.ScoringConfigGroup; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.replanning.GenericPlanStrategy; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.ReplanningContext; +import org.matsim.core.replanning.modules.GenericPlanStrategyModule; +import org.matsim.core.replanning.selectors.ExpBetaPlanSelector; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * This strategy removes **one** randomly selected shipment from logistic chain with the most shipments and reassign it to the chain with the closest chain. + * The distance is measured as the Euclidean distance between the shipment's destination and the resource's start link. + * This strategy allows to slowly change the plans and therefore follow the iterative learning process. + * + * @author nrichter (during his master thesis @VSP) + */ +final class ProximityStrategyFactory { + //This is ok so as long as it is **non-public**. + //Before making it public, it should be configurable either via config or Injection. + //KMT, KN (Jan'24) + + // yyyy This factory class contains a long anonymous class. It seems that it should be the other way round: The anonymous class should be a proper + // class, and the factory method (or maybe just normal constructor) should be contained in the class. At some point, try to exchange. kmt & kai, mar'24 + + // @formatter:off + + private ProximityStrategyFactory() {} // class contains only static methods; do not instantiate + + static GenericPlanStrategy createStrategy(Network network) { + + GenericPlanStrategyImpl strategy = new GenericPlanStrategyImpl<>(new ExpBetaPlanSelector<>(new ScoringConfigGroup())); + GenericPlanStrategyModule randomModule = new GenericPlanStrategyModule<>() { + + @Override + public void prepareReplanning(ReplanningContext replanningContext) {} + + @Override + public void handlePlan(LSPPlan lspPlan) { + + // Shifting shipments only makes sense for multiple chains + if (lspPlan.getLogisticChains().size() < 2) return; + + LSP lsp = lspPlan.getLSP(); + double minDistance = Double.MAX_VALUE; + LSPResource minDistanceResource = null; + + // get all shipments assigned to the LSP + Map, LspShipment> lspShipmentById = new HashMap<>(); + for (LspShipment lspShipment : lsp.getLspShipments()) { + lspShipmentById.put(lspShipment.getId(), lspShipment); + } + + // Retrieve all shipments in the logistic chains of the plan + // These should be all shipments of the lsp, but not necessarily if shipments got lost + ArrayList shipments = new ArrayList<>(); + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + for (Id id : logisticChain.getLspShipmentIds()) { + LspShipment lspShipment = lspShipmentById.get(id); + if (lspShipment != null) { + shipments.add(lspShipment); + } + } + } + + // pick a random lspShipment from the shipments contained in the plan + int shipmentIndex = MatsimRandom.getRandom().nextInt(shipments.size()); + LspShipment lspShipment = shipments.get(shipmentIndex); + + // Collect all resources of the logistic chains of the LSP plan + ArrayList resources = new ArrayList<>(); + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + for (LogisticChainElement logisticChainElement : + logisticChain.getLogisticChainElements()) { + resources.add(logisticChainElement.getResource()); + } + } + + // get the resource with the smallest distance to the lspShipment + for (LSPResource resource : resources) { + Link shipmentLink = network.getLinks().get(lspShipment.getTo()); + Link resourceLink = network.getLinks().get(resource.getStartLinkId()); + double distance = + NetworkUtils.getEuclideanDistance( + shipmentLink.getFromNode().getCoord(), resourceLink.getFromNode().getCoord()); + if (distance < minDistance) { + minDistance = distance; + minDistanceResource = resource; + } + } + + // add randomly picked lspShipment to chain with resource of the smallest distance + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + for (LogisticChainElement logisticChainElement : + logisticChain.getLogisticChainElements()) { + if (logisticChainElement.getResource().equals(minDistanceResource)) { + logisticChain.getLspShipmentIds().add(lspShipment.getId()); + } + } + } + + // remove the lspShipment from the previous logistic chain, can be the same as the new + // logistic chain + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + if (logisticChain.getLspShipmentIds().contains(lspShipment.getId())) { + logisticChain.getLspShipmentIds().remove(lspShipment.getId()); + break; + } + } + } + + @Override + public void finishReplanning() {} + }; + + strategy.addStrategyModule(randomModule); + return strategy; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RandomDistributionAllShipmentsStrategyFactory.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RandomDistributionAllShipmentsStrategyFactory.java new file mode 100644 index 00000000000..64371400ab9 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RandomDistributionAllShipmentsStrategyFactory.java @@ -0,0 +1,90 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import java.util.ArrayList; +import java.util.List; +import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.replanning.GenericPlanStrategy; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.ReplanningContext; +import org.matsim.core.replanning.modules.GenericPlanStrategyModule; +import org.matsim.core.replanning.selectors.ExpBetaPlanSelector; +import org.matsim.freight.logistics.LSP; +import org.matsim.freight.logistics.LSPPlan; +import org.matsim.freight.logistics.LogisticChain; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * This strategy removes **all** shipments from the logistic chains and reassigns them randomly. + * It does not seem to be a very useful strategy in terms of going forward towards a (local) optimum, as long as it is the only one. + * But it is i) a good example how to write such a strategy and ii) can be used to reshuffle the current state and find a new starting point when running with different strategies. + * @author nrichter (during his master thesis @VSP) + */ +final class RandomDistributionAllShipmentsStrategyFactory { + //This is ok so as long as it is **non-public**. + //Before making it public, it should be configurable either via config or Injection. + //KMT, KN (Jan'24) + + private + RandomDistributionAllShipmentsStrategyFactory() {} // class contains only static methods; do not + // instantiate + + static GenericPlanStrategy createStrategy() { + + GenericPlanStrategyImpl strategy = + new GenericPlanStrategyImpl<>(new ExpBetaPlanSelector<>(new ScoringConfigGroup())); + GenericPlanStrategyModule randomModule = + new GenericPlanStrategyModule<>() { + + @Override + public void prepareReplanning(ReplanningContext replanningContext) {} + + @Override + public void handlePlan(LSPPlan lspPlan) { + + // Shifting shipments only makes sense for multiple chains + if (lspPlan.getLogisticChains().size() < 2) return; + + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + logisticChain.getLspShipmentIds().clear(); + } + + LSP lsp = lspPlan.getLSP(); + List logisticChains = + new ArrayList<>(lsp.getSelectedPlan().getLogisticChains()); + + for (LspShipment lspShipment : lsp.getLspShipments()) { + int index = MatsimRandom.getRandom().nextInt(logisticChains.size()); + logisticChains.get(index).addShipmentToChain(lspShipment); + } + } + + @Override + public void finishReplanning() {} + }; + + strategy.addStrategyModule(randomModule); + return strategy; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RandomLogisticChainShipmentAssigner.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RandomLogisticChainShipmentAssigner.java new file mode 100644 index 00000000000..6cd0c2389c6 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RandomLogisticChainShipmentAssigner.java @@ -0,0 +1,56 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import org.matsim.core.gbl.Gbl; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.freight.logistics.InitialShipmentAssigner; +import org.matsim.freight.logistics.LSPPlan; +import org.matsim.freight.logistics.LogisticChain; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * The {@link LspShipment} is assigned randomly to a {@link LogisticChain}. The logistic chains of a + * plan are collected in a list. The chain to which the shipment is to be assigned is selected by a + * seeded random index. Requirements: There must be at least one logisticChain in the plan. + */ +class RandomLogisticChainShipmentAssigner implements InitialShipmentAssigner { + + private final Random random; + + RandomLogisticChainShipmentAssigner() { + MatsimRandom.reset(); + this.random = MatsimRandom.getLocalInstance(); + } + + @Override + public void assignToPlan(LSPPlan lspPlan, LspShipment lspShipment) { + Gbl.assertIf(!lspPlan.getLogisticChains().isEmpty()); + List logisticChains = new ArrayList<>(lspPlan.getLogisticChains()); + int index = random.nextInt(logisticChains.size()); + LogisticChain logisticChain = logisticChains.get(index); + logisticChain.addShipmentToChain(lspShipment); + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RandomShiftingStrategyFactory.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RandomShiftingStrategyFactory.java new file mode 100644 index 00000000000..45ae711dcf1 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RandomShiftingStrategyFactory.java @@ -0,0 +1,115 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Random; +import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.replanning.GenericPlanStrategy; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.ReplanningContext; +import org.matsim.core.replanning.modules.GenericPlanStrategyModule; +import org.matsim.core.replanning.selectors.ExpBetaPlanSelector; +import org.matsim.freight.logistics.LSP; +import org.matsim.freight.logistics.LSPPlan; +import org.matsim.freight.logistics.LogisticChain; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * This strategy removes **one** randomly selected shipment from the logistic chain it was assigned to and reassign it to another chain. + * This strategy allows to slowly change the plans and therefore follow the iterative learning process. + * But it is i) slow, because it needs a lot of iterations and ii) has a high chance to get stuck in a local optimum. + * @author nrichter (during his master thesis @VSP) + */ +class RandomShiftingStrategyFactory { + + private static Random random = null; + + //This is ok so as long as it is **non-public**. + //Before making it public, it should be configurable either via config or Injection. + //KMT, KN (Jan'24) + RandomShiftingStrategyFactory() {} // class contains only static methods; do not instantiate. + + static GenericPlanStrategy createStrategy() { + + MatsimRandom.reset(); + random = MatsimRandom.getLocalInstance(); + + GenericPlanStrategyImpl strategy = new GenericPlanStrategyImpl<>(new ExpBetaPlanSelector<>(new ScoringConfigGroup())); + GenericPlanStrategyModule randomModule = new GenericPlanStrategyModule<>() { + + @Override + public void prepareReplanning(ReplanningContext replanningContext) {} + + @Override + public void handlePlan(LSPPlan lspPlan) { + + // Shifting lspShipments only makes sense for multiple chains + if (lspPlan.getLogisticChains().size() < 2) return; + + LSP lsp = lspPlan.getLSP(); + + // Make a new list of lspShipments and pick a random lspShipment from it + List lspShipments = new ArrayList<>(lsp.getLspShipments()); + int shipmentIndex = random.nextInt(lsp.getLspShipments().size()); + LspShipment lspShipment = lspShipments.get(shipmentIndex); + + // Find and remove the random lspShipment from its current logistic chain + LogisticChain sourceLogisticChain = null; + for (LogisticChain logisticChain : lsp.getSelectedPlan().getLogisticChains()) { + if (logisticChain.getLspShipmentIds().remove(lspShipment.getId())) { + sourceLogisticChain = logisticChain; + break; + } + } + + // Find a new logistic chain for the lspShipment + // Ensure that the chain selected is not the same as the one it was removed from + int chainIndex; + LogisticChain targetLogisticChain = null; + do { + chainIndex = random.nextInt(lsp.getSelectedPlan().getLogisticChains().size()); + Iterator iterator = lsp.getSelectedPlan().getLogisticChains().iterator(); + for (int i = 0; iterator.hasNext(); i++) { + targetLogisticChain = iterator.next(); + if (i == chainIndex) { + break; + } + } + } while (targetLogisticChain == sourceLogisticChain); + + // Add the lspShipment to the new logistic chain + assert targetLogisticChain != null; + targetLogisticChain.addShipmentToChain(lspShipment); + } + + @Override + public void finishReplanning() {} + }; + + strategy.addStrategyModule(randomModule); + return strategy; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RebalancingStrategyFactory.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RebalancingStrategyFactory.java new file mode 100644 index 00000000000..a9b08f9469c --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RebalancingStrategyFactory.java @@ -0,0 +1,110 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import org.matsim.api.core.v01.Id; +import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.replanning.GenericPlanStrategy; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.ReplanningContext; +import org.matsim.core.replanning.modules.GenericPlanStrategyModule; +import org.matsim.core.replanning.selectors.ExpBetaPlanSelector; +import org.matsim.freight.logistics.LSP; +import org.matsim.freight.logistics.LSPPlan; +import org.matsim.freight.logistics.LogisticChain; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * This strategy removes **one** randomly selected shipment from logistic chain with the most shipments and reassign it to one of the chains with the lowest number of shipments. + * This strategy allows to slowly change the plans and therefore follow the iterative learning process. But is moves towards a solution with all chains having the same number of shipments. + * For me (KMT) the use case is not obvious, when used as only strategy, but it can have its use in a set of strategies. + * @author nrichter (during his master thesis @VSP) + */ +class RebalancingStrategyFactory { + //This is ok so as long as it is **non-public**. + //Before making it public, it should be configurable either via config or Injection. + //KMT, KN (Jan'24) + + private RebalancingStrategyFactory() {} // class contains only static methods; do not instantiate + + static GenericPlanStrategy createStrategy() { + + GenericPlanStrategyImpl strategy = + new GenericPlanStrategyImpl<>(new ExpBetaPlanSelector<>(new ScoringConfigGroup())); + GenericPlanStrategyModule loadBalancingModule = + new GenericPlanStrategyModule<>() { + + @Override + public void prepareReplanning(ReplanningContext replanningContext) {} + + @Override + public void handlePlan(LSPPlan lspPlan) { + + // Shifting shipments only makes sense for multiple chains + if (lspPlan.getLogisticChains().size() < 2) return; + + LSP lsp = lspPlan.getLSP(); + Map shipmentCountByChain = new HashMap<>(); + LogisticChain minChain; + LogisticChain maxChain; + + // fill the shipmentCountByChain map with each chain's shipment count + for (LogisticChain chain : lsp.getSelectedPlan().getLogisticChains()) { + shipmentCountByChain.put(chain, chain.getLspShipmentIds().size()); + } + + // find the chains with the minimum and maximum shipment counts + minChain = + Collections.min(shipmentCountByChain.entrySet(), Map.Entry.comparingByValue()) + .getKey(); + maxChain = + Collections.max(shipmentCountByChain.entrySet(), Map.Entry.comparingByValue()) + .getKey(); + + // If min and max chains are the same, no need to shift shipments + if (minChain.equals(maxChain)) return; + + // get the first shipment ID from the chain with the maximum shipment count + Id shipmentIdForReplanning = maxChain.getLspShipmentIds().iterator().next(); + + // iterate through the chains and move the shipment from the max chain to the min chain + for (LogisticChain logisticChain : lsp.getSelectedPlan().getLogisticChains()) { + if (logisticChain.equals(maxChain)) { + logisticChain.getLspShipmentIds().remove(shipmentIdForReplanning); + } + if (logisticChain.equals(minChain)) { + logisticChain.getLspShipmentIds().add(shipmentIdForReplanning); + } + } + } + + @Override + public void finishReplanning() {} + }; + + strategy.addStrategyModule(loadBalancingModule); + return strategy; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RoundRobinDistributionAllShipmentsStrategyFactory.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RoundRobinDistributionAllShipmentsStrategyFactory.java new file mode 100644 index 00000000000..74ac28b39a5 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RoundRobinDistributionAllShipmentsStrategyFactory.java @@ -0,0 +1,97 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.multipleChains; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.replanning.GenericPlanStrategy; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.ReplanningContext; +import org.matsim.core.replanning.modules.GenericPlanStrategyModule; +import org.matsim.core.replanning.selectors.ExpBetaPlanSelector; +import org.matsim.freight.logistics.LSP; +import org.matsim.freight.logistics.LSPPlan; +import org.matsim.freight.logistics.LogisticChain; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * This strategy removes **all** shipments from the logistic chains and reassigns them. + * The reassignment is done in a round-robin fashion, so that in the hand all chains have the same number of shipments. + * It does not seem to be a very useful strategy in terms of going forward towards a (local) optimum, as long as it is the only one. + * + * @author nrichter (during his master thesis @VSP) + */ +/*package-private*/ class RoundRobinDistributionAllShipmentsStrategyFactory { + //This is ok so as long as it is **non-public**. + //Before making it public, it should be configurable either via config or Injection. + //KMT, KN (Jan'24) + + private + RoundRobinDistributionAllShipmentsStrategyFactory() {} // class contains only static methods; do + // not instantiate + + /*package-private*/ static GenericPlanStrategy createStrategy() { + GenericPlanStrategyImpl strategy = + new GenericPlanStrategyImpl<>(new ExpBetaPlanSelector<>(new ScoringConfigGroup())); + GenericPlanStrategyModule roundRobinModule = + new GenericPlanStrategyModule<>() { + + @Override + public void prepareReplanning(ReplanningContext replanningContext) {} + + @Override + public void handlePlan(LSPPlan lspPlan) { + + // Shifting shipments only makes sense for multiple chains + if (lspPlan.getLogisticChains().size() < 2) return; + + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + logisticChain.getLspShipmentIds().clear(); + } + + LSP lsp = lspPlan.getLSP(); + Map shipmentCountByChain = new LinkedHashMap<>(); + + for (LspShipment lspShipment : lsp.getLspShipments()) { + if (shipmentCountByChain.isEmpty()) { + for (LogisticChain chain : lsp.getSelectedPlan().getLogisticChains()) { + shipmentCountByChain.put(chain, 0); + } + } + LogisticChain minChain = + Collections.min(shipmentCountByChain.entrySet(), Map.Entry.comparingByValue()) + .getKey(); + minChain.addShipmentToChain(lspShipment); + shipmentCountByChain.merge(minChain, 1, Integer::sum); + } + } + + @Override + public void finishReplanning() {} + }; + + strategy.addStrategyModule(roundRobinModule); + return strategy; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RoundRobinLogisticChainShipmentAssigner.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RoundRobinLogisticChainShipmentAssigner.java new file mode 100644 index 00000000000..c7d1dfae611 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/multipleChains/RoundRobinLogisticChainShipmentAssigner.java @@ -0,0 +1,64 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import org.matsim.core.gbl.Gbl; +import org.matsim.freight.logistics.InitialShipmentAssigner; +import org.matsim.freight.logistics.LSPPlan; +import org.matsim.freight.logistics.LogisticChain; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * The {@link LspShipment} is assigned consecutively to a {@link LogisticChain}. In case of one + * chain the shipment is assigned to that chain. If there are more chains, the shipment is assigned + * to the chain which has the least shipments to this point and thus distributes the shipments + * evenly in sequence across the logistics chains. Requirements: There must be at least one + * logisticChain in the plan + */ +class RoundRobinLogisticChainShipmentAssigner implements InitialShipmentAssigner { + + // map of logistic chains and their number of assigned shipments in order of addition + final Map shipmentCountByChain = new LinkedHashMap<>(); + + RoundRobinLogisticChainShipmentAssigner() {} + + @Override + public void assignToPlan(LSPPlan lspPlan, LspShipment lspShipment) { + Gbl.assertIf(!lspPlan.getLogisticChains().isEmpty()); + // prepare the map if empty for the first time with each number of assigned shipments being zero + if (shipmentCountByChain.isEmpty()) { + for (LogisticChain chain : lspPlan.getLogisticChains()) { + shipmentCountByChain.put(chain, 0); + } + } + + // assign the shipment to the chain with the least number of assigned shipments so far, increase + // its value by one + LogisticChain minChain = + Collections.min(shipmentCountByChain.entrySet(), Map.Entry.comparingByValue()).getKey(); + minChain.addShipmentToChain(lspShipment); + shipmentCountByChain.merge(minChain, 1, Integer::sum); + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/requirementsChecking/BlueRequirement.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/requirementsChecking/BlueRequirement.java new file mode 100644 index 00000000000..4137417af9f --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/requirementsChecking/BlueRequirement.java @@ -0,0 +1,58 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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 * + * * + * *********************************************************************** + */ + +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.requirementsChecking; + +import static org.matsim.freight.logistics.examples.requirementsChecking.ExampleCheckRequirementsOfAssigner.ATTRIBUTE_COLOR; + +import org.matsim.freight.logistics.LogisticChain; +import org.matsim.freight.logistics.shipment.LspShipmentRequirement; + +/*package-private*/ class BlueRequirement implements LspShipmentRequirement { + + static final String BLUE = "blue"; + + @Override + public boolean checkRequirement(LogisticChain solution) { + return solution.getAttributes().getAttribute(ATTRIBUTE_COLOR).equals(BLUE); + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/requirementsChecking/ExampleCheckRequirementsOfAssigner.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/requirementsChecking/ExampleCheckRequirementsOfAssigner.java new file mode 100644 index 00000000000..a918de5f531 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/requirementsChecking/ExampleCheckRequirementsOfAssigner.java @@ -0,0 +1,262 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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 * + * * + * *********************************************************************** + */ + +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.requirementsChecking; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Random; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +class ExampleCheckRequirementsOfAssigner { + + static final String ATTRIBUTE_COLOR = "color"; + + private static LSP createLSPWithProperties(Scenario scenario) { + + final Network network = scenario.getNetwork(); + + // Create red LogisticsSolution which has the corresponding info + final Id redCarrierId = Id.create("RedCarrier", Carrier.class); + final Id collectionVehTypeId = Id.create("RedCarrierVehicleType", VehicleType.class); + final VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + collectionVehType.setNetworkMode(TransportMode.car); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id redVehicleId = Id.createVehicleId("RedVehicle"); + CarrierVehicle redVehicle = + CarrierVehicle.newInstance(redVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities redCapabilities = + CarrierCapabilities.Builder.newInstance() + .addVehicle(redVehicle) + .setFleetSize(FleetSize.INFINITE) + .build(); + Carrier redCarrier = CarriersUtils.createCarrier(redCarrierId); + redCarrier.setCarrierCapabilities(redCapabilities); + + LSPResource redResource = + ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(redCarrier) + .setCollectionScheduler( + ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + Id redElementId = Id.create("RedElement", LogisticChainElement.class); + LogisticChainElement redElement = + LSPUtils.LogisticChainElementBuilder.newInstance(redElementId) + .setResource(redResource) + .build(); + + Id redSolutionId = Id.create("RedSolution", LogisticChain.class); + LSPUtils.LogisticChainBuilder redSolutionBuilder = + LSPUtils.LogisticChainBuilder.newInstance(redSolutionId); + redSolutionBuilder.addLogisticChainElement(redElement); + LogisticChain redSolution = redSolutionBuilder.build(); + + // Add info that shows the world the color of the solution + redSolution.getAttributes().putAttribute(ATTRIBUTE_COLOR, RedRequirement.RED); + + // Create blue LogisticsSolution which has the corresponding info + Id blueCarrierId = Id.create("BlueCarrier", Carrier.class); + Id blueVehicleId = Id.createVehicleId("BlueVehicle"); + CarrierVehicle blueVehicle = + CarrierVehicle.newInstance(blueVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities blueCapabilities = + CarrierCapabilities.Builder.newInstance() + .addVehicle(blueVehicle) + .setFleetSize(FleetSize.INFINITE) + .build(); + Carrier blueCarrier = CarriersUtils.createCarrier(blueCarrierId); + blueCarrier.setCarrierCapabilities(blueCapabilities); + + LSPResource blueResource = + ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(blueCarrier) + .setCollectionScheduler( + ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + Id blueElementId = Id.create("BlueCElement", LogisticChainElement.class); + LogisticChainElement blueElement = + LSPUtils.LogisticChainElementBuilder.newInstance(blueElementId) + .setResource(blueResource) + .build(); + + LogisticChain blueSolution = + LSPUtils.LogisticChainBuilder.newInstance(Id.create("BlueSolution", LogisticChain.class)) + .addLogisticChainElement(blueElement) + .build(); + + // Add info that shows the world the color of the solution + blueSolution.getAttributes().putAttribute(ATTRIBUTE_COLOR, BlueRequirement.BLUE); + + // Create the initial plan, add assigner that checks requirements of the shipments when + // assigning and add both solutions (red and blue) to the + // plan. + LSPPlan plan = + LSPUtils.createLSPPlan() + .setInitialShipmentAssigner(new RequirementsAssigner()) + .addLogisticChain(redSolution) + .addLogisticChain(blueSolution); + + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(redResource); + resourcesList.add(blueResource); + + return LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)) + .setInitialPlan(plan) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + resourcesList)) + .build(); + } + + public static Collection createShipmentsWithRequirements(Network network) { + // Create ten shipments with either a red or blue requirement, i.e. that they only can be + // transported in a solution with the matching color + ArrayList shipmentList = new ArrayList<>(); + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + + Random rand = new Random(1); + + for (int i = 1; i < 11; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = rand.nextInt(10); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 + && pendingFromLink.getFromNode().getCoord().getY() <= 4000 + && pendingFromLink.getToNode().getCoord().getX() <= 4000 + && pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + builder.setToLinkId(Id.createLinkId("(4 2) (4 3)")); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + boolean blue = rand.nextBoolean(); + if (blue) { + builder.addRequirement(new BlueRequirement()); + } else { + builder.addRequirement(new RedRequirement()); + } + + shipmentList.add(builder.build()); + } + + return shipmentList; + } + + public static void main(String[] args) { + + // Set up required MATSim classes + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()) + .readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + // Create LSP and lspShipments + LSP lsp = createLSPWithProperties(scenario); + Collection lspShipments = createShipmentsWithRequirements(network); + + // assign the lspShipments to the LSP + for (LspShipment lspShipment : lspShipments) { + lsp.assignShipmentToLSP(lspShipment); + } + + for (LogisticChain logisticChain : lsp.getSelectedPlan().getLogisticChains()) { + if (logisticChain.getId().toString().equals("RedSolution")) { + for (Id lspShipmentId : logisticChain.getLspShipmentIds()) { + LspShipment lspShipment = LSPUtils.findLspShipment(lsp, lspShipmentId); + if (lspShipment != null && !(lspShipment.getRequirements().iterator().next() instanceof RedRequirement)) { + break; + } + } + System.out.println("All lspShipments in " + logisticChain.getId() + " are red"); + } + if (logisticChain.getId().toString().equals("BlueSolution")) { + for (Id lspShipmentId : logisticChain.getLspShipmentIds()) { + LspShipment shipment = LSPUtils.findLspShipment(lsp, lspShipmentId); + if (shipment != null && !(shipment.getRequirements().iterator().next() instanceof BlueRequirement)) { + break; + } + } + System.out.println("All lspShipments in " + logisticChain.getId() + " are blue"); + } + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/requirementsChecking/RedRequirement.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/requirementsChecking/RedRequirement.java new file mode 100644 index 00000000000..0422427ab30 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/requirementsChecking/RedRequirement.java @@ -0,0 +1,59 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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 * + * * + * *********************************************************************** + */ + +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.requirementsChecking; + +import org.matsim.freight.logistics.LogisticChain; +import org.matsim.freight.logistics.shipment.LspShipmentRequirement; + +/*package-private*/ class RedRequirement implements LspShipmentRequirement { + + static final String RED = "red"; + + @Override + public boolean checkRequirement(LogisticChain solution) { + return solution + .getAttributes() + .getAttribute(ExampleCheckRequirementsOfAssigner.ATTRIBUTE_COLOR) + .equals(RED); + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/requirementsChecking/RequirementsAssigner.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/requirementsChecking/RequirementsAssigner.java new file mode 100644 index 00000000000..e47b3d358e8 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/requirementsChecking/RequirementsAssigner.java @@ -0,0 +1,79 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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 * + * * + * *********************************************************************** + */ + +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.requirementsChecking; + +import java.util.ArrayList; +import java.util.Collection; +import org.matsim.freight.logistics.InitialShipmentAssigner; +import org.matsim.freight.logistics.LSPPlan; +import org.matsim.freight.logistics.LogisticChain; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentRequirement; + +class RequirementsAssigner implements InitialShipmentAssigner { + + private final Collection feasibleLogisticChains; + + public RequirementsAssigner() { + this.feasibleLogisticChains = new ArrayList<>(); + } + + @Override + public void assignToPlan(LSPPlan lspPlan, LspShipment lspShipment) { + feasibleLogisticChains.clear(); + + label: + for (LogisticChain solution : lspPlan.getLogisticChains()) { + for (LspShipmentRequirement requirement : lspShipment.getRequirements()) { + if (!requirement.checkRequirement(solution)) { + + continue label; + } + } + feasibleLogisticChains.add(solution); + } + LogisticChain chosenSolution = feasibleLogisticChains.iterator().next(); + chosenSolution.addShipmentToChain(lspShipment); + } + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/simulationTrackers/CollectionServiceHandler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/simulationTrackers/CollectionServiceHandler.java new file mode 100644 index 00000000000..1bbc708aa92 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/simulationTrackers/CollectionServiceHandler.java @@ -0,0 +1,111 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.simulationTrackers; + +import java.util.ArrayList; +import java.util.Collection; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.freight.carriers.CarrierService; +import org.matsim.freight.carriers.events.CarrierServiceEndEvent; +import org.matsim.freight.carriers.events.CarrierServiceStartEvent; +import org.matsim.freight.carriers.events.eventhandler.CarrierServiceEndEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierServiceStartEventHandler; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleUtils; +import org.matsim.vehicles.Vehicles; + +/*package-private*/ class CollectionServiceHandler + implements CarrierServiceStartEventHandler, CarrierServiceEndEventHandler { + + private final Collection tuples; + private final Vehicles allVehicles; + private double totalLoadingCosts; + private int totalNumberOfShipments; + private int totalWeightOfShipments; + + public CollectionServiceHandler(Scenario scenario) { + this.allVehicles = VehicleUtils.getOrCreateAllvehicles(scenario); + this.tuples = new ArrayList<>(); + } + + @Override + public void reset(int iteration) { + tuples.clear(); + totalNumberOfShipments = 0; + totalWeightOfShipments = 0; + } + + @Override + public void handleEvent(CarrierServiceEndEvent event) { + System.out.println("Service Ends"); + double loadingCosts; + for (ServiceTuple tuple : tuples) { + if (tuple.getServiceId() == event.getServiceId()) { + double serviceDuration = event.getTime() - tuple.getStartTime(); + + final Vehicle vehicle = allVehicles.getVehicles().get(event.getVehicleId()); + loadingCosts = serviceDuration * vehicle.getType().getCostInformation().getCostsPerSecond(); + totalLoadingCosts = totalLoadingCosts + loadingCosts; + tuples.remove(tuple); + break; + } + } + } + + @Override + public void handleEvent(CarrierServiceStartEvent event) { + totalNumberOfShipments++; + totalWeightOfShipments = totalWeightOfShipments + event.getCapacityDemand(); + tuples.add(new ServiceTuple(event.getServiceId(), event.getTime())); + } + + public double getTotalLoadingCosts() { + return totalLoadingCosts; + } + + public int getTotalNumberOfShipments() { + return totalNumberOfShipments; + } + + public int getTotalWeightOfShipments() { + return totalWeightOfShipments; + } + + private static class ServiceTuple { + private final Id serviceId; + private final double startTime; + + public ServiceTuple(Id serviceId, double startTime) { + this.serviceId = serviceId; + this.startTime = startTime; + } + + public Id getServiceId() { + return serviceId; + } + + public double getStartTime() { + return startTime; + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/simulationTrackers/DistanceAndTimeHandler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/simulationTrackers/DistanceAndTimeHandler.java new file mode 100644 index 00000000000..5eece04dd0e --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/simulationTrackers/DistanceAndTimeHandler.java @@ -0,0 +1,101 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.simulationTrackers; + +import java.util.LinkedHashMap; +import java.util.Map; +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.Scenario; +import org.matsim.api.core.v01.events.LinkEnterEvent; +import org.matsim.api.core.v01.events.LinkLeaveEvent; +import org.matsim.api.core.v01.events.VehicleLeavesTrafficEvent; +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.VehicleLeavesTrafficEventHandler; +import org.matsim.api.core.v01.network.Network; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleUtils; +import org.matsim.vehicles.Vehicles; + +/*package-private*/ class DistanceAndTimeHandler + implements LinkEnterEventHandler, VehicleLeavesTrafficEventHandler, LinkLeaveEventHandler { + private static final Logger log = LogManager.getLogger(DistanceAndTimeHandler.class); + + private final Map, LinkEnterEvent> events; + private final Vehicles allVehicles; + private final Network network; + private double distanceCosts; + private double timeCosts; + + DistanceAndTimeHandler(Scenario scenario) { + this.network = scenario.getNetwork(); + this.events = new LinkedHashMap<>(); + this.allVehicles = VehicleUtils.getOrCreateAllvehicles(scenario); + } + + @Override + public void handleEvent(LinkEnterEvent event) { + events.put(event.getVehicleId(), event); + } + + @Override + public void reset(int iteration) { + events.clear(); + } + + @Override + public void handleEvent(VehicleLeavesTrafficEvent leaveEvent) { + processLeaveEvent(leaveEvent.getVehicleId(), leaveEvent.getTime()); + } + + @Override + public void handleEvent(LinkLeaveEvent leaveEvent) { + processLeaveEvent(leaveEvent.getVehicleId(), leaveEvent.getTime()); + } + + private void processLeaveEvent(Id vehicleId, double time) { + + LinkEnterEvent enterEvent = events.remove(vehicleId); + if (enterEvent != null) { + Vehicle carrierVehicle = this.allVehicles.getVehicles().get(vehicleId); + double linkDuration = time - enterEvent.getTime(); + timeCosts += linkDuration * carrierVehicle.getType().getCostInformation().getCostsPerSecond(); + double linkLength = network.getLinks().get(enterEvent.getLinkId()).getLength(); + distanceCosts += + linkLength * carrierVehicle.getType().getCostInformation().getCostsPerMeter(); + } + // (there might not be a corresponding enter event if vehicle just entered traffic. Could add + // that as well, but then we would need to compensate for fact that this covers little distance. + // kai, jul'22) + + } + + public double getDistanceCosts() { + return distanceCosts; + } + + public double getTimeCosts() { + return timeCosts; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/simulationTrackers/ExampleSimulationTrackers.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/simulationTrackers/ExampleSimulationTrackers.java new file mode 100644 index 00000000000..26959c6081d --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/simulationTrackers/ExampleSimulationTrackers.java @@ -0,0 +1,215 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.simulationTrackers; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Random; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.Controler; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +/*package-private*/ class ExampleSimulationTrackers { + + /*package-private*/ + static LSP createLSPWithTracker(Scenario scenario) { + + // The Carrier for the resource of the sole LogisticsSolutionElement of the LSP is created + Id carrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id vollectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle carrierVehicle = + CarrierVehicle.newInstance(vollectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities capabilities = CarrierCapabilities.Builder.newInstance() + .addVehicle(carrierVehicle) + .setFleetSize(FleetSize.INFINITE) + .build(); + + Carrier carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + // The Resource i.e. the Resource is created + + LSPResource collectionResource = + ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance( + carrier) + .setCollectionScheduler( + ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + // The adapter is now inserted into the only LogisticsSolutionElement of the only + // LogisticsSolution of the LSP + LogisticChainElement collectionElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + // The LogisticsSolutionElement is now inserted into the only LogisticsSolution of the LSP + Id collectionSolutionId = Id.create("CollectionSolution", LogisticChain.class); + LogisticChain collectionSolution = + LSPUtils.LogisticChainBuilder.newInstance(collectionSolutionId) + .addLogisticChainElement(collectionElement) + .build(); + + // Create cost tracker and add it to solution + LinearCostTracker tracker = new LinearCostTracker(0.2); + tracker.getEventHandlers().add(new TourStartHandler(scenario)); + tracker.getEventHandlers().add(new CollectionServiceHandler(scenario)); + tracker.getEventHandlers().add(new DistanceAndTimeHandler(scenario)); + collectionSolution.addSimulationTracker(tracker); + + // The initial plan of the lsp is generated and the assigner and the solution from above are + // added + LSPPlan collectionPlan = LSPUtils.createLSPPlan(); + InitialShipmentAssigner assigner = + ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + collectionPlan.setInitialShipmentAssigner(assigner); + collectionPlan.addLogisticChain(collectionSolution); + + LSPUtils.LSPBuilder collectionLSPBuilder = + LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + collectionLSPBuilder.setInitialPlan(collectionPlan); + + // The exogenous list of Resources for the SolutionScheduler is compiled and the Scheduler is + // added to the LSPBuilder + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + LogisticChainScheduler simpleScheduler = + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + collectionLSPBuilder.setLogisticChainScheduler(simpleScheduler); + + return collectionLSPBuilder.build(); + } + + public static Collection createInitialLSPShipments(Network network) { + ArrayList shipmentList = new ArrayList<>(); + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + + // Create five LSPShipments that are located in the left half of the network. + for (int i = 1; i < 6; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + Random random = new Random(1); + int capacityDemand = random.nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, random); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 + && pendingFromLink.getFromNode().getCoord().getY() <= 4000 + && pendingFromLink.getToNode().getCoord().getX() <= 4000 + && pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + builder.setToLinkId(Id.createLinkId("(4 2) (4 3)")); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + shipmentList.add(builder.build()); + } + return shipmentList; + } + + public static void main(String[] args) { + + // Set up required MATSim classes + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()) + .readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + // Create LSP and lspShipments + LSP lsp = createLSPWithTracker(scenario); + Collection lspShipments = createInitialLSPShipments(network); + + // assign the lspShipments to the LSP + for (LspShipment lspShipment : lspShipments) { + lsp.assignShipmentToLSP(lspShipment); + } + + // schedule the LSP with the lspShipments and according to the scheduler of the Resource + lsp.scheduleLogisticChains(); + + // Prepare LSPModule and add the LSP + ArrayList lspList = new ArrayList<>(); + lspList.add(lsp); + LSPs lsps = new LSPs(lspList); + LSPUtils.addLSPs(scenario, lsps); + + // Start the Mobsim one iteration is sufficient for tracking + Controler controler = new Controler(config); + controler.addOverridingModule(new LSPModule()); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.overwriteExistingFiles); + config.network().setInputFile("scenarios/2regions/2regions-network.xml"); + // The VSP default settings are designed for person transport simulation. After talking to Kai, + // they will be set to WARN here. Kai MT may'23 + controler + .getConfig() + .vspExperimental() + .setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controler.run(); + + // Retrieve cost info from lsp + for (LogisticChain solution : lsp.getSelectedPlan().getLogisticChains()) { + System.out.println(solution.getAttributes().getAttribute("cost_function")); + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/simulationTrackers/LinearCostTracker.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/simulationTrackers/LinearCostTracker.java new file mode 100644 index 00000000000..8a8fbb9f2a2 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/simulationTrackers/LinearCostTracker.java @@ -0,0 +1,173 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.simulationTrackers; + +import java.util.ArrayList; +import java.util.Collection; +import org.matsim.api.core.v01.events.LinkEnterEvent; +import org.matsim.api.core.v01.events.LinkLeaveEvent; +import org.matsim.api.core.v01.events.VehicleLeavesTrafficEvent; +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.VehicleLeavesTrafficEventHandler; +import org.matsim.core.controler.events.AfterMobsimEvent; +import org.matsim.core.controler.listener.AfterMobsimListener; +import org.matsim.core.events.handler.EventHandler; +import org.matsim.freight.carriers.events.CarrierServiceEndEvent; +import org.matsim.freight.carriers.events.CarrierServiceStartEvent; +import org.matsim.freight.carriers.events.CarrierTourStartEvent; +import org.matsim.freight.carriers.events.eventhandler.CarrierServiceEndEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierServiceStartEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierTourStartEventHandler; +import org.matsim.freight.logistics.LSPSimulationTracker; +import org.matsim.freight.logistics.LSPUtils; +import org.matsim.freight.logistics.LogisticChain; + +/*package-private*/ class LinearCostTracker + implements AfterMobsimListener, + LSPSimulationTracker, + LinkEnterEventHandler, + VehicleLeavesTrafficEventHandler, + CarrierTourStartEventHandler, + CarrierServiceStartEventHandler, + CarrierServiceEndEventHandler, + LinkLeaveEventHandler { + + private final Collection eventHandlers; + private final double shareOfFixedCosts; + // private final Collection infos; + private double distanceCosts; + private double timeCosts; + private double loadingCosts; + private double vehicleFixedCosts; + private int totalNumberOfShipments; + private int totalWeightOfShipments; + private double fixedUnitCosts; + private double linearUnitCosts; + private LogisticChain logisticChain; + + public LinearCostTracker(double shareOfFixedCosts) { + this.shareOfFixedCosts = shareOfFixedCosts; + this.eventHandlers = new ArrayList<>(); + } + + public final Collection getEventHandlers() { + return eventHandlers; + } + + @Override + public void notifyAfterMobsim(AfterMobsimEvent event) { + for (EventHandler handler : eventHandlers) { + if (handler instanceof TourStartHandler startHandler) { + this.vehicleFixedCosts = startHandler.getVehicleFixedCosts(); + } + if (handler instanceof DistanceAndTimeHandler distanceHandler) { + this.distanceCosts = distanceHandler.getDistanceCosts(); + this.timeCosts = distanceHandler.getTimeCosts(); + } + if (handler instanceof CollectionServiceHandler collectionHandler) { + totalNumberOfShipments = collectionHandler.getTotalNumberOfShipments(); + System.out.println(totalNumberOfShipments); + totalWeightOfShipments = collectionHandler.getTotalWeightOfShipments(); + loadingCosts = collectionHandler.getTotalLoadingCosts(); + } + } + + double totalCosts = distanceCosts + timeCosts + loadingCosts + vehicleFixedCosts; + fixedUnitCosts = (totalCosts * shareOfFixedCosts) / totalNumberOfShipments; + linearUnitCosts = (totalCosts * (1 - shareOfFixedCosts)) / totalWeightOfShipments; + + LSPUtils.setFixedCost(this.logisticChain, fixedUnitCosts); + LSPUtils.setVariableCost(this.logisticChain, linearUnitCosts); + } + + @Override + public void reset(int iteration) { + distanceCosts = 0; + timeCosts = 0; + loadingCosts = 0; + vehicleFixedCosts = 0; + totalNumberOfShipments = 0; + totalWeightOfShipments = 0; + fixedUnitCosts = 0; + linearUnitCosts = 0; + } + + @Override + public void setEmbeddingContainer(LogisticChain pointer) { + this.logisticChain = pointer; + } + + @Override + public void handleEvent(LinkEnterEvent event) { + for (EventHandler eventHandler : this.eventHandlers) { + if (eventHandler instanceof LinkEnterEventHandler) { + ((LinkEnterEventHandler) eventHandler).handleEvent(event); + } + } + } + + @Override + public void handleEvent(VehicleLeavesTrafficEvent event) { + for (EventHandler eventHandler : this.eventHandlers) { + if (eventHandler instanceof VehicleLeavesTrafficEventHandler) { + ((VehicleLeavesTrafficEventHandler) eventHandler).handleEvent(event); + } + } + } + + @Override + public void handleEvent(CarrierTourStartEvent event) { + for (EventHandler eventHandler : this.eventHandlers) { + if (eventHandler instanceof CarrierTourStartEventHandler) { + ((CarrierTourStartEventHandler) eventHandler).handleEvent(event); + } + } + } + + @Override + public void handleEvent(CarrierServiceEndEvent event) { + for (EventHandler eventHandler : this.eventHandlers) { + if (eventHandler instanceof CarrierServiceEndEventHandler) { + ((CarrierServiceEndEventHandler) eventHandler).handleEvent(event); + } + } + } + + @Override + public void handleEvent(CarrierServiceStartEvent event) { + for (EventHandler eventHandler : this.eventHandlers) { + if (eventHandler instanceof CarrierServiceStartEventHandler) { + ((CarrierServiceStartEventHandler) eventHandler).handleEvent(event); + } + } + } + + @Override + public void handleEvent(LinkLeaveEvent event) { + for (EventHandler eventHandler : this.eventHandlers) { + if (eventHandler instanceof LinkLeaveEventHandler) { + ((LinkLeaveEventHandler) eventHandler).handleEvent(event); + } + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/simulationTrackers/TourStartHandler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/simulationTrackers/TourStartHandler.java new file mode 100644 index 00000000000..79b92965cf1 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/examples/simulationTrackers/TourStartHandler.java @@ -0,0 +1,83 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.simulationTrackers; + +import java.util.Collection; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Scenario; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.events.CarrierTourStartEvent; +import org.matsim.freight.carriers.events.eventhandler.CarrierTourStartEventHandler; + +/*package-private*/ class TourStartHandler implements CarrierTourStartEventHandler { + + private static final Logger log = LogManager.getLogger(TourStartHandler.class); + private final Carriers carriers; + private double vehicleFixedCosts; + + public TourStartHandler(Scenario scenario) { + this.carriers = CarriersUtils.addOrGetCarriers(scenario); + } + + @Override + public void reset(int iteration) { + vehicleFixedCosts = 0; + } + + @Override + public void handleEvent(CarrierTourStartEvent event) { + log.warn("handling tour start event={}", event.toString()); + + CarrierVehicle carrierVehicle = null; + /* + * This somehow a workaround, because the Vehicle can't get received from the (MATSim) allVehicle container. + * At the TourStartEvent stage, the event.getVehicle is still not known ("null"), because it bases on ActivityEndEvent. + * And since it is the first ActEndEvent of the person, it never entered a vehicle before -.- + * + * My preferred approach would have been something like + * final Vehicle vehicle = allVehicles.getVehicles().get(event.getVehicleId()); + * kmt sep'22 + */ + Carrier carrier = carriers.getCarriers().get(event.getCarrierId()); + Collection scheduledTours = carrier.getSelectedPlan().getScheduledTours(); + for (ScheduledTour scheduledTour : scheduledTours) { + if (scheduledTour.getTour().getId() == event.getTourId()) { + carrierVehicle = scheduledTour.getVehicle(); + break; + } + } + assert carrierVehicle != null; + vehicleFixedCosts = + vehicleFixedCosts + carrierVehicle.getType().getCostInformation().getFixedCosts(); + } + + /** + * ATTENTION: Does this really give back the costs of the current vehicle? Or is the value maybe + * overwritten if another event happens before calling the getFixedCosts function? kmt sep'22 + * + * @return the fixedCosts + */ + public double getVehicleFixedCosts() { + return vehicleFixedCosts; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/io/LSPPlanXmlParserV1.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/io/LSPPlanXmlParserV1.java new file mode 100644 index 00000000000..e555e9adccf --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/io/LSPPlanXmlParserV1.java @@ -0,0 +1,437 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2023 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.freight.logistics.io; + +import static org.matsim.freight.logistics.LSPConstants.*; +import static org.matsim.utils.objectattributes.attributable.AttributesUtils.ATTRIBUTE; +import static org.matsim.utils.objectattributes.attributable.AttributesUtils.ATTRIBUTES; + +import java.util.*; +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.core.gbl.Gbl; +import org.matsim.core.utils.io.MatsimXmlParser; +import org.matsim.core.utils.misc.Time; +import org.matsim.freight.carriers.*; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.TransshipmentHubResource; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.utils.objectattributes.attributable.AttributesXmlReaderDelegate; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; +import org.xml.sax.Attributes; + +/** + * Reads data out of LSPPlans file and builds the LSPs with their according resources, shipments and + * plans. StartTag mainly for parsing data, endTag for assigning data to according LSP. + * + * @author nrichter (Niclas Richter) + */ +class LSPPlanXmlParserV1 extends MatsimXmlParser { + + public static final Logger logger = LogManager.getLogger(LSPPlanXmlParserV1.class); + private final LSPs lsPs; + private final Carriers carriers; + private final Map elementIdResourceIdMap = new LinkedHashMap<>(); + private final Map planElements = new LinkedHashMap<>(); + private final AttributesXmlReaderDelegate attributesReader = new AttributesXmlReaderDelegate(); + private final List logisticChains = new LinkedList<>(); + private LSP currentLsp = null; + private Carrier currentCarrier = null; + private LspShipment currentShipment = null; + private LSPPlan currentLspPlan = null; + private CarrierCapabilities.Builder capabilityBuilder; + private TransshipmentHubResource hubResource; + private String currentHubId; + private Double currentHubFixedCost; + private String currentHubLocation; + private String chainId; + private Double score; + private String selected; + private String shipmentPlanId; + private String shipmentChainId; + + LSPPlanXmlParserV1(LSPs lsPs, Carriers carriers) { + super(ValidationType.XSD_ONLY); + this.lsPs = lsPs; + this.carriers = carriers; + } + + @Override + public void startTag(String name, Attributes atts, Stack context) { + org.matsim.utils.objectattributes.attributable.Attributes currAttributes; + switch (name) { + case LSP -> { + String lspId = atts.getValue(ID); + Gbl.assertNotNull(lspId); + currentLsp = + LSPUtils.LSPBuilder.getInstance(Id.create(lspId, LSP.class)) + .setLogisticChainScheduler( + ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler( + Collections.emptyList())) + .setInitialPlan(new LSPPlanImpl()) + .build(); + } + case CARRIER -> { + String carrierId = atts.getValue(ID); + Gbl.assertNotNull(carrierId); + currentCarrier = carriers.getCarriers().get(Id.create(carrierId, Carrier.class)); + } + case HUB -> { + currentHubId = atts.getValue(ID); + Gbl.assertNotNull(currentHubId); + currentHubLocation = atts.getValue(LOCATION); + Gbl.assertNotNull(currentHubLocation); + currentHubFixedCost = Double.parseDouble(atts.getValue(FIXED_COST)); + Gbl.assertNotNull(currentHubFixedCost); + } + case CAPABILITIES -> { + String fleetSize = atts.getValue(FLEET_SIZE); + Gbl.assertNotNull(fleetSize); + this.capabilityBuilder = CarrierCapabilities.Builder.newInstance(); + if (fleetSize.toUpperCase().equals(CarrierCapabilities.FleetSize.FINITE.toString())) { + this.capabilityBuilder.setFleetSize(CarrierCapabilities.FleetSize.FINITE); + } else { + this.capabilityBuilder.setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + } + } + case SCHEDULER -> { + double capacityNeedFixed = Double.parseDouble(atts.getValue(CAPACITY_NEED_FIXED)); + double capacityNeedLinear = Double.parseDouble(atts.getValue(CAPACITY_NEED_LINEAR)); + hubResource = + ResourceImplementationUtils.TransshipmentHubBuilder.newInstance( + Id.create(currentHubId, LSPResource.class), + Id.createLinkId(currentHubLocation), + null) + .setTransshipmentHubScheduler( + ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed( + capacityNeedFixed) // Time needed, fixed (for Scheduler) + .setCapacityNeedLinear( + capacityNeedLinear) // additional time needed per shipmentSize (for + // Scheduler) + .build()) + .build(); + } + case ATTRIBUTES -> { + switch (context.peek()) { + case SHIPMENT -> currAttributes = currentShipment.getAttributes(); + case LSP -> currAttributes = currentLsp.getAttributes(); + default -> throw new RuntimeException( + "could not derive context for attributes. context=" + context.peek()); + } + attributesReader.startTag(name, atts, context, currAttributes); + } + case ATTRIBUTE -> { + currAttributes = currentCarrier.getAttributes(); + Gbl.assertNotNull(currAttributes); + attributesReader.startTag(name, atts, context, currAttributes); + } + case VEHICLE -> { + String vehicleId = atts.getValue(ID); + Gbl.assertNotNull(vehicleId); + + String depotLinkId = atts.getValue(DEPOT_LINK_ID); + Gbl.assertNotNull(depotLinkId); + + String typeId = atts.getValue(TYPE_ID); + Gbl.assertNotNull(typeId); + VehicleType vehicleType = + VehicleUtils.createVehicleType(Id.create(typeId, VehicleType.class)); + Gbl.assertNotNull(vehicleType); + + CarrierVehicle.Builder vehicleBuilder = + CarrierVehicle.Builder.newInstance( + Id.create(vehicleId, Vehicle.class), + Id.create(depotLinkId, Link.class), + vehicleType); + String startTime = atts.getValue(EARLIEST_START); + if (startTime != null) vehicleBuilder.setEarliestStart(parseTimeToDouble(startTime)); + String endTime = atts.getValue(LATEST_END); + if (endTime != null) vehicleBuilder.setLatestEnd(parseTimeToDouble(endTime)); + + CarrierVehicle vehicle = vehicleBuilder.build(); + capabilityBuilder.addVehicle(vehicle); + } + case SHIPMENT -> { + String shipmentId = atts.getValue(ID); + Gbl.assertNotNull(shipmentId); + Id id = Id.create(shipmentId, LspShipment.class); + + String from = atts.getValue(FROM); + Gbl.assertNotNull(from); + String to = atts.getValue(TO); + Gbl.assertNotNull(to); + String sizeString = atts.getValue(SIZE); + Gbl.assertNotNull(sizeString); + int size = Integer.parseInt(sizeString); + LspShipmentUtils.LspShipmentBuilder shipmentBuilder = + LspShipmentUtils.LspShipmentBuilder.newInstance(id); + + shipmentBuilder.setFromLinkId(Id.createLinkId(from)); + shipmentBuilder.setToLinkId(Id.createLinkId(to)); + shipmentBuilder.setCapacityDemand(size); + + String startPickup = atts.getValue(START_PICKUP); + String endPickup = atts.getValue(END_PICKUP); + String startDelivery = atts.getValue(START_DELIVERY); + String endDelivery = atts.getValue(END_DELIVERY); + String pickupServiceTime = atts.getValue(PICKUP_SERVICE_TIME); + String deliveryServiceTime = atts.getValue(DELIVERY_SERVICE_TIME); + + if (startPickup != null && endPickup != null) + shipmentBuilder.setStartTimeWindow( + TimeWindow.newInstance(parseTimeToDouble(startPickup), parseTimeToDouble(endPickup))); + if (startDelivery != null && endDelivery != null) + shipmentBuilder.setEndTimeWindow( + TimeWindow.newInstance( + parseTimeToDouble(startDelivery), parseTimeToDouble(endDelivery))); + if (pickupServiceTime != null) + shipmentBuilder.setPickupServiceTime(parseTimeToDouble(pickupServiceTime)); + if (deliveryServiceTime != null) + shipmentBuilder.setDeliveryServiceTime(parseTimeToDouble(deliveryServiceTime)); + + currentShipment = shipmentBuilder.build(); + currentLsp.getLspShipments().add(currentShipment); + } + case LSP_PLAN -> { + currentLspPlan = LSPUtils.createLSPPlan(); + score = Double.valueOf(atts.getValue(SCORE)); + Gbl.assertNotNull(score); + selected = atts.getValue(SELECTED); + Gbl.assertNotNull(selected); + } + case LOGISTIC_CHAIN -> { + chainId = atts.getValue(ID); + Gbl.assertNotNull(chainId); + } + case RESOURCES -> {} + case LOGISTIC_CHAIN_ELEMENT -> { + String logisticChainElementId = atts.getValue(ID); + String resourceId = atts.getValue(RESOURCE_ID); + + elementIdResourceIdMap.put(logisticChainElementId, resourceId); + } + case SHIPMENT_PLAN -> { + shipmentPlanId = atts.getValue(SHIPMENT_ID); + Gbl.assertNotNull(shipmentPlanId); + shipmentChainId = atts.getValue(CHAIN_ID); + Gbl.assertNotNull(shipmentChainId); + } + case ELEMENT -> { + String elementId = atts.getValue(ID); + Gbl.assertNotNull(elementId); + + String type = atts.getValue(TYPE); + Gbl.assertNotNull(type); + + String startTime = atts.getValue(START_TIME); + Gbl.assertNotNull(startTime); + + String endTime = atts.getValue(END_TIME); + Gbl.assertNotNull(endTime); + + String resourceId = atts.getValue(RESOURCE_ID); + Gbl.assertNotNull(resourceId); + + LspShipmentPlanElement planElement = null; + + switch (type) { + case "LOAD" -> { + var planElementBuilder = LspShipmentUtils.ScheduledShipmentLoadBuilder.newInstance(); + planElementBuilder.setStartTime(parseTimeToDouble(startTime)); + planElementBuilder.setEndTime(parseTimeToDouble(endTime)); + planElementBuilder.setResourceId(Id.create(resourceId, LSPResource.class)); + planElement = planElementBuilder.build(); + } + case "TRANSPORT" -> { + var planElementBuilder = LspShipmentUtils.ScheduledShipmentTransportBuilder.newInstance(); + planElementBuilder.setStartTime(parseTimeToDouble(startTime)); + planElementBuilder.setEndTime(parseTimeToDouble(endTime)); + planElementBuilder.setResourceId(Id.create(resourceId, LSPResource.class)); + planElement = planElementBuilder.build(); + } + case "UNLOAD" -> { + var planElementBuilder = LspShipmentUtils.ScheduledShipmentUnloadBuilder.newInstance(); + planElementBuilder.setStartTime(parseTimeToDouble(startTime)); + planElementBuilder.setEndTime(parseTimeToDouble(endTime)); + planElementBuilder.setResourceId(Id.create(resourceId, LSPResource.class)); + planElement = planElementBuilder.build(); + } + case "HANDLE" -> { + var planElementBuilder = LspShipmentUtils.ScheduledShipmentHandleBuilder.newInstance(); + planElementBuilder.setStartTime(parseTimeToDouble(startTime)); + planElementBuilder.setEndTime(parseTimeToDouble(endTime)); + planElementBuilder.setResourceId(Id.create(resourceId, LSPResource.class)); + planElement = planElementBuilder.build(); + } + } + planElements.put(elementId, planElement); + } + } + } + + @Override + public void endTag(String name, String content, Stack context) { + switch (name) { + case LSP -> { + Gbl.assertNotNull(currentLsp); + Gbl.assertNotNull(lsPs); + Gbl.assertNotNull(lsPs.getLSPs()); + currentLsp.getPlans().removeFirst(); // empty plan zero was set for initialization of currentLSP + lsPs.getLSPs().put(currentLsp.getId(), currentLsp); + currentLsp = null; + } + case CARRIER -> { + Gbl.assertNotNull(currentCarrier); + Gbl.assertNotNull(carriers); + Gbl.assertNotNull(carriers.getCarriers()); + LSPResource lspResource; + + switch (ResourceImplementationUtils.getCarrierType(currentCarrier)) { + case collectionCarrier -> lspResource = + ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance( + currentCarrier) + .setCollectionScheduler( + ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(null)) + .build(); + case mainRunCarrier -> lspResource = + ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(currentCarrier) + .setMainRunCarrierScheduler( + ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(null)) + .build(); + case distributionCarrier -> lspResource = + ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance( + currentCarrier) + .setDistributionScheduler( + ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(null)) + .build(); + default -> throw new IllegalStateException( + "Unexpected value: " + currentCarrier.getAttributes().toString()); + } + Gbl.assertNotNull(lspResource); + currentLsp.getResources().add(lspResource); + currentCarrier = null; + } + case HUB -> { + currentLsp.getResources().add(hubResource); + LSPUtils.setFixedCost(hubResource, currentHubFixedCost); + hubResource = null; + currentHubFixedCost = null; + currentHubLocation = null; + currentHubId = null; + } + case CAPABILITIES -> currentCarrier.setCarrierCapabilities(capabilityBuilder.build()); + case ATTRIBUTE -> attributesReader.endTag(name, content, context); + case SHIPMENT -> this.currentShipment = null; + case LSP_PLAN -> {} + + case LOGISTIC_CHAINS -> { + currentLspPlan = LSPUtils.createLSPPlan(); + + for (LogisticChain logisticChain : logisticChains) { + currentLspPlan.addLogisticChain(logisticChain); + } + + currentLspPlan.setScore(score); + currentLspPlan.setLSP(currentLsp); + if (selected.equals("true")) { + currentLsp.setSelectedPlan(currentLspPlan); + } else { + currentLsp.addPlan(currentLspPlan); + } + + logisticChains.clear(); + } + + case LOGISTIC_CHAIN -> { + LSPResource resource; + List logisticChainElements = new LinkedList<>(); + + for (Map.Entry entry : elementIdResourceIdMap.entrySet()) { + for (LSPResource currentResource : currentLsp.getResources()) { + if (currentResource.getId().toString().equals(entry.getValue())) { + resource = currentResource; + Gbl.assertNotNull(resource); + LogisticChainElement logisticChainElement = + LSPUtils.LogisticChainElementBuilder.newInstance( + Id.create(entry.getKey(), LogisticChainElement.class)) + .setResource(resource) + .build(); + logisticChainElements.add(logisticChainElement); + } + } + } + + elementIdResourceIdMap.clear(); + + LogisticChain currentLogisticChain = + LSPUtils.LogisticChainBuilder.newInstance(Id.create(chainId, LogisticChain.class)) + .addLogisticChainElement(logisticChainElements.getFirst()) + .build(); + + for (int i = 1; + i < logisticChainElements.size(); + i++) { // element 0 was already added in Builder as first element. + logisticChainElements.get(i - 1).connectWithNextElement(logisticChainElements.get(i)); + currentLogisticChain.getLogisticChainElements().add(logisticChainElements.get(i)); + } + + logisticChains.add(currentLogisticChain); + } + + case SHIPMENT_PLAN -> { + for (LspShipment lspShipment : currentLsp.getLspShipments()) { + if (lspShipment.getId().toString().equals(shipmentPlanId)) { + for (Map.Entry planElement : planElements.entrySet()) { + LspShipmentUtils.getOrCreateShipmentPlan(currentLspPlan, lspShipment.getId()) + .addPlanElement( + Id.create(planElement.getKey(), LspShipmentPlanElement.class), + planElement.getValue()); + } + } + for (LogisticChain logisticChain : currentLspPlan.getLogisticChains()) { + if (logisticChain.getId().toString().equals(shipmentChainId) + && lspShipment.getId().toString().equals(shipmentPlanId)) { + logisticChain.addShipmentToChain(lspShipment); + } + } + } + shipmentPlanId = null; + planElements.clear(); + } + } + } + + private double parseTimeToDouble(String timeString) { + if (timeString.contains(":")) { + return Time.parseTime(timeString); + } else { + return Double.parseDouble(timeString); + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/io/LSPPlanXmlReader.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/io/LSPPlanXmlReader.java new file mode 100644 index 00000000000..3f84c85cda2 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/io/LSPPlanXmlReader.java @@ -0,0 +1,116 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2023 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.freight.logistics.io; + +import java.net.URL; +import java.util.Stack; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.core.api.internal.MatsimReader; +import org.matsim.core.utils.io.MatsimXmlParser; +import org.matsim.freight.carriers.Carriers; +import org.matsim.freight.logistics.LSPConstants; +import org.matsim.freight.logistics.LSPs; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +/** + * Delegates a LSPPlanXmlParser according to declared schema definition file + * + * @author nrichter (Niclas Richter) + */ +public final class LSPPlanXmlReader implements MatsimReader { + private static final Logger log = LogManager.getLogger(LSPPlanXmlReader.class); + private final LSPsPlanParser parser; + + public LSPPlanXmlReader(final LSPs lsPs, Carriers carriers) { + System.setProperty("matsim.preferLocalDtds", "true"); + this.parser = new LSPsPlanParser(lsPs, carriers); + } + + public void readFile(String filename) { + try { + this.parser.setValidating(true); + this.parser.readFile(filename); + } catch (Exception e) { + log.warn("### Exception found while trying to read LSPPlan: Message: {} ; cause: {} ; class {}", e.getMessage(), e.getCause(), e.getClass()); + throw e; + } + } + + public void readURL(URL url) { + try { + this.parser.readURL(url); + } catch (Exception e) { + log.warn("### Exception found while trying to read LSPPlan: Message: {} ; cause: {} ; class {}", e.getMessage(), e.getCause(), e.getClass()); + if (e.getCause() + .getMessage() + .contains( + "cvc-elt.1")) { // "Cannot find the declaration of element" -> exception comes most + // probably because no validation information was found + log.warn("read with validation = true failed. Try it again without validation... url: {}", url.toString()); + parser.setValidating(true); + parser.readURL(url); + } else { // other problem: e.g. validation does not work, because of missing validation file. + throw e; + } + } + } + + private static final class LSPsPlanParser extends MatsimXmlParser { + private final LSPs lsPs; + private final Carriers carriers; + + private MatsimXmlParser delegate = null; + + LSPsPlanParser(LSPs lsPs, Carriers carriers) { + super(ValidationType.XSD_ONLY); + this.lsPs = lsPs; + this.carriers = carriers; + } + + public void startTag(String name, Attributes attributes, Stack context) { + if (LSPConstants.LSPS.equalsIgnoreCase(name)) { + String str = attributes.getValue("xsi:schemaLocation"); + log.info("Found following schemaLocation in lsPs definition file: {}", str); + if (str.contains("lspsDefinitions_v1.xsd")) { + delegate = new LSPPlanXmlParserV1(lsPs, carriers); + } else { + throw new RuntimeException("no reader found for " + str); + } + } else { + this.delegate.startTag(name, attributes, context); + } + } + + public void endTag(String name, String content, Stack context) { + this.delegate.endTag(name, content, context); + } + + public void endDocument() { + try { + this.delegate.endDocument(); + } catch (SAXException var2) { + throw new RuntimeException(var2); + } + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/io/LSPPlanXmlWriter.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/io/LSPPlanXmlWriter.java new file mode 100644 index 00000000000..2c97a9ae99e --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/io/LSPPlanXmlWriter.java @@ -0,0 +1,220 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2023 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.freight.logistics.io; + +import static org.matsim.freight.logistics.LSPConstants.*; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Id; +import org.matsim.core.gbl.Gbl; +import org.matsim.core.utils.collections.Tuple; +import org.matsim.core.utils.io.MatsimXmlWriter; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.LSP; +import org.matsim.freight.logistics.resourceImplementations.TransshipmentHubResource; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; + +/** + * Writes out resources, shipments and plans for each LSP in an XML-file including header for + * validating against respective XSD and setting up according writer. Uses variables defined in + * LSPConstants-class for the elements and attributes within the XML. + * + * @author nrichter (Niclas Richter) + */ +public class LSPPlanXmlWriter extends MatsimXmlWriter { + + private static final Logger logger = LogManager.getLogger(LSPPlanXmlWriter.class); + + private final Collection lsPs; + + public LSPPlanXmlWriter(LSPs lsPs) { + super(); + this.lsPs = lsPs.getLSPs().values(); + } + + public void write(String filename) { + logger.info(Gbl.aboutToWrite("lsps", filename)); + try { + this.openFile(filename); + this.writeXmlHead(); + this.writeRootElement(); + for (LSP lsp : lsPs) { + this.startLSP(lsp); + this.writeResources(lsp); + this.writeShipments(lsp); + this.writePlans(lsp, this.writer); + this.writeEndTag(LSP); + } + this.writeEndTag(LSPConstants.LSPS); + this.close(); + logger.info("done"); + } catch (IOException e) { + e.printStackTrace(); + logger.error(e); + System.exit(1); + } + } + + private void writeRootElement() throws IOException { + List> atts = new ArrayList<>(); + atts.add(createTuple(XMLNS, MatsimXmlWriter.MATSIM_NAMESPACE)); + atts.add(createTuple(XMLNS + ":xsi", DEFAULTSCHEMANAMESPACELOCATION)); + atts.add( + createTuple( + "xsi:schemaLocation", + MATSIM_NAMESPACE + " " + DEFAULT_DTD_LOCATION + "lspsDefinitions_v1.xsd")); + this.writeStartTag(LSPConstants.LSPS, atts); + this.writer.write(NL); + } + + private void startLSP(LSP lsp) throws IOException { + this.writeStartTag(LSP, List.of(createTuple(ID, lsp.getId().toString()))); + } + + private void writeResources(LSP lsp) throws IOException { + if (lsp.getResources().isEmpty()) return; + this.writeStartTag(RESOURCES, null); + for (LSPResource resource : lsp.getResources()) { + if (resource instanceof TransshipmentHubResource hub) { + List> tupleList = new ArrayList<>(); + tupleList.add(new Tuple<>(ID, hub.getId().toString())); + tupleList.add(new Tuple<>(LOCATION, hub.getStartLinkId().toString())); + if (hub.getAttributes().getAttribute(FIXED_COST) != null) { + tupleList.add( + new Tuple<>(FIXED_COST, hub.getAttributes().getAttribute(FIXED_COST).toString())); + } + this.writeStartTag(HUB, tupleList); + this.writeStartTag( + SCHEDULER, + List.of( + createTuple(CAPACITY_NEED_FIXED, hub.getCapacityNeedFixed()), + createTuple(CAPACITY_NEED_LINEAR, hub.getCapacityNeedLinear())), + true); + this.writeEndTag(HUB); + } + if (resource instanceof LSPCarrierResource carrierResource) { + this.writeStartTag( + CARRIER, List.of(createTuple(ID, carrierResource.getId().toString())), true); + } + } + this.writeEndTag(RESOURCES); + } + + private void writeShipments(LSP lsp) throws IOException { + if (lsp.getLspShipments().isEmpty()) return; + this.writeStartTag(SHIPMENTS, null); + for (LspShipment lspShipment : lsp.getLspShipments()) { + this.writeStartTag( + SHIPMENT, + List.of( + createTuple(ID, lspShipment.getId().toString()), + createTuple(FROM, lspShipment.getFrom().toString()), + createTuple(TO, lspShipment.getTo().toString()), + createTuple(SIZE, lspShipment.getSize()), + createTuple(START_PICKUP, lspShipment.getPickupTimeWindow().getStart()), + createTuple(END_PICKUP, lspShipment.getPickupTimeWindow().getEnd()), + createTuple(START_DELIVERY, lspShipment.getDeliveryTimeWindow().getStart()), + createTuple(END_DELIVERY, lspShipment.getDeliveryTimeWindow().getEnd()), + createTuple(PICKUP_SERVICE_TIME, lspShipment.getPickupServiceTime()), + createTuple(DELIVERY_SERVICE_TIME, lspShipment.getDeliveryServiceTime())), + true); + } + this.writeEndTag(SHIPMENTS); + } + + private void writePlans(LSP lsp, BufferedWriter writer) throws IOException { + if (lsp.getPlans().isEmpty()) return; + this.writeStartTag(LSP_PLANS, null); + + for (LSPPlan plan : lsp.getPlans()) { + if (plan.getScore() != null && lsp.getSelectedPlan() != null) { + if (plan == lsp.getSelectedPlan()) { + this.writeStartTag( + LSP_PLAN, + List.of(createTuple(SCORE, plan.getScore()), createTuple(SELECTED, "true"))); + } else { + this.writeStartTag( + LSP_PLAN, + List.of(createTuple(SCORE, plan.getScore()), createTuple(SELECTED, "false"))); + } + } else { + this.writeStartTag(LSP_PLAN, List.of(createTuple(SELECTED, "false"))); + } + + this.writeStartTag(LOGISTIC_CHAINS, null); + for (LogisticChain chain : plan.getLogisticChains()) { + writeStartTag(LOGISTIC_CHAIN, List.of(createTuple(ID, chain.getId().toString()))); + for (LogisticChainElement chainElement : chain.getLogisticChainElements()) { + this.writeStartTag( + LOGISTIC_CHAIN_ELEMENT, + List.of( + createTuple(ID, chainElement.getId().toString()), + createTuple(RESOURCE_ID, chainElement.getResource().getId().toString())), + true); + } + writeEndTag(LOGISTIC_CHAIN); + } + writeEndTag(LOGISTIC_CHAINS); + + writeStartTag(SHIPMENT_PLANS, null); + for (LogisticChain chain : plan.getLogisticChains()) { + for (Id shipmentId : chain.getLspShipmentIds()) { + if (chain.getLspShipmentIds().contains(shipmentId)) { + this.writeStartTag( + SHIPMENT_PLAN, + List.of( + createTuple(SHIPMENT_ID, shipmentId.toString()), + createTuple(CHAIN_ID, chain.getId().toString()))); + } + LspShipment lspShipment = LSPUtils.findLspShipment(lsp, shipmentId); + assert lspShipment != null; + final Map, LspShipmentPlanElement> planElements = + LspShipmentUtils.getOrCreateShipmentPlan(plan, lspShipment.getId()).getPlanElements(); + for (Id elementId : planElements.keySet()) { + LspShipmentPlanElement element = planElements.get(elementId); + this.writeStartTag( + ELEMENT, + List.of( + createTuple(ID, elementId.toString()), + createTuple(TYPE, element.getElementType()), + createTuple(START_TIME, element.getStartTime()), + createTuple(END_TIME, element.getEndTime()), + createTuple(RESOURCE_ID, element.getResourceId().toString())), + true); + } + writeEndTag(SHIPMENT_PLAN); + } + } + writeEndTag(SHIPMENT_PLANS); + writeEndTag(LSP_PLAN); + } + this.writeEndTag(LSP_PLANS); + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/CarrierSchedulerUtils.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/CarrierSchedulerUtils.java new file mode 100644 index 00000000000..deb8e984b2e --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/CarrierSchedulerUtils.java @@ -0,0 +1,145 @@ +package org.matsim.freight.logistics.resourceImplementations; + +import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm; +import com.graphhopper.jsprit.core.algorithm.box.Jsprit; +import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem; +import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution; +import com.graphhopper.jsprit.core.util.Solutions; +import java.util.List; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.roadpricing.RoadPricingScheme; +import org.matsim.contrib.roadpricing.RoadPricingUtils; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.CarrierPlan; +import org.matsim.freight.carriers.CarriersUtils; +import org.matsim.freight.carriers.jsprit.MatsimJspritFactory; +import org.matsim.freight.carriers.jsprit.NetworkBasedTransportCosts; +import org.matsim.freight.carriers.jsprit.NetworkRouter; +import org.matsim.freight.logistics.LSPUtils; + +/** + * This class contains some code fragments, that are used in the different *CarrierScheduler + * classes. To avoid code duplication these methods are extracted and located here more centralized. + * + * @author Kai Martins-Turner (kturner) + */ +public class CarrierSchedulerUtils { + private static final Logger log = LogManager.getLogger(CarrierSchedulerUtils.class); + private static final String LOGIC_OF_VRP = "logicOfVrp"; + + /** + * Creates a VehicleRoutingProblem from a carrier and a network and solves it with Jsprit. + * If a roadPricingScheme is given, the tolls are considered in the routing costs. + *

+ * This looks for me (KMT) similar to what is done in {@link org.matsim.freight.carriers.CarriersUtils#runJsprit(Scenario)}. + * So, maybe this can be more simplify. + * + * @param carrier Carrier for which the problem should be solved + * @param scenario the scenario + * @return Carrier with the solution of the VehicleRoutingProblem and the routed plan. + */ + public static Carrier solveVrpWithJsprit(Carrier carrier, Scenario scenario) { + // Maybe it make sense to store this object instead of rebuilding it for each carrier (in each iteration) ??? + // pro: save computation time + // con: interdependencies, if something changes in the network (load), the object is not up-to-date & it is not clear, if the object is thread safe + // Decision for the time being: rebuild it for each carrier to have a clear state KMT/KN Aug'24 + NetworkBasedTransportCosts netbasedTransportCosts; + Network network = scenario.getNetwork(); + RoadPricingScheme roadPricingScheme = null; + try { + roadPricingScheme = RoadPricingUtils.getRoadPricingScheme(scenario); + } catch (Exception e) { + log.info("Was not able getting RoadPricingScheme. Tolls cannot be considered.", e); + } + if (roadPricingScheme != null) { + netbasedTransportCosts = NetworkBasedTransportCosts.Builder.newInstance(network, ResourceImplementationUtils.getVehicleTypeCollection(carrier)) + .setRoadPricingScheme(roadPricingScheme) + .build(); + } else { + log.debug("RoadPricingScheme is null. Tolls cannot be considered."); + netbasedTransportCosts = NetworkBasedTransportCosts.Builder.newInstance(network, ResourceImplementationUtils.getVehicleTypeCollection(carrier)) + .build(); + } + + VehicleRoutingProblem vrp = + MatsimJspritFactory.createRoutingProblemBuilder(carrier, network) + .setRoutingCost(netbasedTransportCosts) + .build(); + + //If jspritIterations are not set (get.... returns a negativ value), set it to 1 + int jspritIterations; + if (CarriersUtils.getJspritIterations(carrier) >= 1) { + jspritIterations = CarriersUtils.getJspritIterations(carrier); + } else { + log.info("Jsprit iterations are not set (properly) for carrier {}. Set to 1.", carrier.getId()); + jspritIterations = 1; + } + + VehicleRoutingAlgorithm vra = Jsprit.createAlgorithm(vrp); + vra.setMaxIterations(jspritIterations); + VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions()); + + CarrierPlan plan = MatsimJspritFactory.createPlan(carrier, solution); + NetworkRouter.routePlan(plan, netbasedTransportCosts); + carrier.addPlan(plan); + carrier.setSelectedPlan(plan); + return carrier; + } + + public static Double sumUpScore(List scheduledPlans) { + double score = 0; + for (CarrierPlan scheduledPlan : scheduledPlans) { + if (scheduledPlan.getScore() != null) { + score = score + scheduledPlan.getScore(); + } + } + return score; + } + + /** + * Sum up the jsprit score of the given list of CarrierPlans. + * As a consequence this is not from the one and only jsprit run, but from all jsprit runs af the different auxiliary carriers. + * @param scheduledPlans the scheduled plans with the jsprit results + * @return the summ of the scores coming from jsprit + */ + public static Double sumUpJspritScore(List scheduledPlans) { + double jspritScore = 0; + for (CarrierPlan scheduledPlan : scheduledPlans) { + if (scheduledPlan.getJspritScore() != null) { + jspritScore = jspritScore + scheduledPlan.getJspritScore(); } + } + return jspritScore; + } + + /** + * Setter for the internal solving logic of a VRP. + * This decides later, whether the VRP is build base on {@link org.matsim.freight.carriers.CarrierService}s or {@link org.matsim.freight.carriers.CarrierShipment}s. + * + * @param carrier The carrier for which the setting should be set. + * @param logicOfVrp the logic of the VRP + */ + public static void setVrpLogic(Carrier carrier, LSPUtils.LogicOfVrp logicOfVrp){ + carrier.getAttributes().putAttribute(LOGIC_OF_VRP, logicOfVrp); + } + + /** + * Getter for the internal solving logic of a VRP. + * This decides later, whether the VRP is build base on {@link org.matsim.freight.carriers.CarrierService}s or {@link org.matsim.freight.carriers.CarrierShipment}s. + * + * @param carrier The carrier for which the setting should be got. + * @return the logic of the VRP, returns {@link LSPUtils.LogicOfVrp#serviceBased} if not set. + */ + public static LSPUtils.LogicOfVrp getVrpLogic(Carrier carrier){ + LSPUtils.LogicOfVrp result = (LSPUtils.LogicOfVrp) carrier.getAttributes().getAttribute(LOGIC_OF_VRP); + if (result == null){ + log.error("VRPLogic not found for carrier {}. Will return {}", carrier.getId(), LSPUtils.LogicOfVrp.serviceBased); + return LSPUtils.LogicOfVrp.serviceBased; + } else { + return result ; + } + } + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/CollectionCarrierResource.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/CollectionCarrierResource.java new file mode 100644 index 00000000000..f54e29ff6d9 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/CollectionCarrierResource.java @@ -0,0 +1,85 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import java.util.Collection; +import java.util.List; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.CarrierVehicle; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.CollectionCarrierResourceBuilder; + +/*package-private*/ class CollectionCarrierResource extends LSPDataObject + implements LSPCarrierResource { + + private final Carrier carrier; + private final List clientElements; + private final CollectionCarrierScheduler collectionScheduler; + + CollectionCarrierResource(CollectionCarrierResourceBuilder builder) { + super(builder.id); + this.collectionScheduler = builder.collectionScheduler; + this.clientElements = builder.clientElements; + this.carrier = builder.carrier; + } + + @Override + public Id getStartLinkId() { + Id depotLinkId = null; + for (CarrierVehicle vehicle : carrier.getCarrierCapabilities().getCarrierVehicles().values()) { + if (depotLinkId == null || depotLinkId == vehicle.getLinkId()) { + depotLinkId = vehicle.getLinkId(); + } + } + + return depotLinkId; + } + + @Override + public Id getEndLinkId() { + Id depotLinkId = null; + for (CarrierVehicle vehicle : carrier.getCarrierCapabilities().getCarrierVehicles().values()) { + if (depotLinkId == null || depotLinkId == vehicle.getLinkId()) { + depotLinkId = vehicle.getLinkId(); + } + } + + return depotLinkId; + } + + @Override + public Collection getClientElements() { + return clientElements; + } + + @Override + public void schedule(int bufferTime, LSPPlan lspPlan) { + collectionScheduler.scheduleShipments(lspPlan, this, bufferTime); + } + + public Carrier getCarrier() { + return carrier; + } + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/CollectionCarrierScheduler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/CollectionCarrierScheduler.java new file mode 100644 index 00000000000..0534d285f7c --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/CollectionCarrierScheduler.java @@ -0,0 +1,247 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import java.util.Objects; +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.Scenario; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.Tour.Leg; +import org.matsim.freight.carriers.Tour.ServiceActivity; +import org.matsim.freight.carriers.Tour.TourElement; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; + +/** + * Schedules the {@link CollectionCarrierResource}. + * + *

Converts the {@link LspShipment}s into {@link CarrierService}s that are needed for the {@link + * Carrier} from the freight contrib of MATSim and then routes the vehicles of this {@link Carrier} + * through the network by calling the corresponding methods of jsprit + */ +/*package-private*/ class CollectionCarrierScheduler extends LSPResourceScheduler { + + Logger log = LogManager.getLogger(CollectionCarrierScheduler.class); + + private Carrier carrier; + private CollectionCarrierResource resource; + private final Scenario scenario; + + /** + * Constructor for the CollectionCarrierScheduler. + * TODO: In the future, the scenario should come via injection(?) This here is only a dirty workaround. KMT'Aug'24 + * + * @param scenario the road pricing scheme + */ + CollectionCarrierScheduler(Scenario scenario) { + this.scenario = scenario; + } + + @Override + public void initializeValues(LSPResource resource) { + if (resource.getClass() == CollectionCarrierResource.class) { + this.resource = (CollectionCarrierResource) resource; + this.carrier = this.resource.getCarrier(); + this.carrier.getServices().clear(); + this.carrier.getShipments().clear(); + this.carrier.getPlans().clear(); + } + } + + @Override + public void scheduleResource() { + for (LspShipment lspShipmentToBeAssigned : lspShipmentsToSchedule) { + CarrierService carrierService = convertToCarrierService(lspShipmentToBeAssigned); + carrier.getServices().put(carrierService.getId(), carrierService); + } + CarrierSchedulerUtils.solveVrpWithJsprit(carrier, scenario); + } + + private CarrierService convertToCarrierService(LspShipment lspShipment) { + Id serviceId = Id.create(lspShipment.getId().toString(), CarrierService.class); + CarrierService carrierService = CarrierService.Builder.newInstance(serviceId, lspShipment.getFrom()) + .setServiceStartTimeWindow(TimeWindow.newInstance(lspShipment.getPickupTimeWindow().getStart(), lspShipment.getPickupTimeWindow().getEnd())) + .setCapacityDemand(lspShipment.getSize()) + .setServiceDuration(lspShipment.getDeliveryServiceTime()) + .build(); + //ensure that the ids of the lspShipment and the carrierService are the same. This is needed for updating the LSPShipmentPlan + if (! Objects.equals(lspShipment.getId().toString(), carrierService.getId().toString())) { + log.error("Id of LspShipment: {} and CarrierService: {} do not match", lspShipment.getId().toString(), carrierService.getId().toString(), + new IllegalStateException("Id of LspShipment and CarrierService do not match")); + } + return carrierService; + } + + @Override + protected void updateShipments() { + for (LspShipment lspShipment : lspShipmentsToSchedule) { + for (ScheduledTour scheduledTour : carrier.getSelectedPlan().getScheduledTours()) { + Tour tour = scheduledTour.getTour(); + for (TourElement element : tour.getTourElements()) { + if (element instanceof ServiceActivity serviceActivity) { + if (Objects.equals(lspShipment.getId().toString(), serviceActivity.getService().getId().toString())) { + addShipmentLoadElement(lspShipment, tour, serviceActivity); + addShipmentTransportElement(lspShipment, tour, serviceActivity); + addShipmentUnloadElement(lspShipment, tour); + addCollectionTourEndEventHandler(serviceActivity.getService(), lspShipment, resource, tour); + addCollectionServiceEventHandler(serviceActivity.getService(), lspShipment, resource); + } + } + } + } + } + } + + private void addShipmentLoadElement( + LspShipment lspShipment, Tour tour, ServiceActivity serviceActivity) { + + LspShipmentUtils.ScheduledShipmentLoadBuilder builder = + LspShipmentUtils.ScheduledShipmentLoadBuilder.newInstance(); + builder.setResourceId(resource.getId()); + + for (LogisticChainElement element : resource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipment)) { + builder.setLogisticChainElement(element); + } + } + + int serviceIndex = tour.getTourElements().indexOf(serviceActivity); + Leg legBeforeService = (Leg) tour.getTourElements().get(serviceIndex - 1); + double startTimeOfLoading = + legBeforeService.getExpectedDepartureTime() + legBeforeService.getExpectedTransportTime(); + builder.setStartTime(startTimeOfLoading); + builder.setEndTime(startTimeOfLoading + lspShipment.getDeliveryServiceTime()); + + LspShipmentPlanElement load = builder.build(); + String idString = + load.getResourceId() + "" + load.getLogisticChainElement().getId() + load.getElementType(); + Id id = Id.create(idString, LspShipmentPlanElement.class); + LspShipmentUtils.getOrCreateShipmentPlan(super.lspPlan, lspShipment.getId()) + .addPlanElement(id, load); + } + + private void addShipmentTransportElement( + LspShipment lspShipment, Tour tour, Tour.ServiceActivity serviceActivity) { + + LspShipmentUtils.ScheduledShipmentTransportBuilder builder = + LspShipmentUtils.ScheduledShipmentTransportBuilder.newInstance(); + builder.setResourceId(resource.getId()); + + for (LogisticChainElement element : resource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipment)) { + builder.setLogisticChainElement(element); + } + } + + int serviceIndex = tour.getTourElements().indexOf(serviceActivity); + Leg legAfterService = (Leg) tour.getTourElements().get(serviceIndex + 1); + double startTimeOfTransport = legAfterService.getExpectedDepartureTime(); + builder.setStartTime(startTimeOfTransport); + Leg lastLeg = (Leg) tour.getTourElements().getLast(); + double endTimeOfTransport = lastLeg.getExpectedDepartureTime() + lastLeg.getExpectedTransportTime(); + builder.setEndTime(endTimeOfTransport); + builder.setCarrierId(carrier.getId()); + builder.setFromLinkId(serviceActivity.getLocation()); + builder.setToLinkId(tour.getEndLinkId()); + builder.setCarrierService(serviceActivity.getService()); + LspShipmentPlanElement transport = builder.build(); + String idString = + transport.getResourceId() + + "" + + transport.getLogisticChainElement().getId() + + transport.getElementType(); + Id id = Id.create(idString, LspShipmentPlanElement.class); + LspShipmentUtils.getOrCreateShipmentPlan(super.lspPlan, lspShipment.getId()) + .addPlanElement(id, transport); + } + + private void addCollectionServiceEventHandler( + CarrierService carrierService, LspShipment lspShipment, LSPCarrierResource resource) { + + for (LogisticChainElement element : this.resource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipment)) { + CollectionServiceEndEventHandler endHandler = + new CollectionServiceEndEventHandler( + carrierService, lspShipment, element, resource); + lspShipment.addSimulationTracker(endHandler); + break; + } + } + } + + private void addCollectionTourEndEventHandler( + CarrierService carrierService, + LspShipment lspShipment, + LSPCarrierResource resource, + Tour tour) { + for (LogisticChainElement element : this.resource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipment)) { + LSPTourEndEventHandler handler = + new LSPTourEndEventHandler( + lspShipment, carrierService, element, resource, tour); + lspShipment.addSimulationTracker(handler); + break; + } + } + } + + private void addShipmentUnloadElement(LspShipment lspShipment, Tour tour) { + + LspShipmentUtils.ScheduledShipmentUnloadBuilder builder = + LspShipmentUtils.ScheduledShipmentUnloadBuilder.newInstance(); + builder.setResourceId(resource.getId()); + for (LogisticChainElement element : resource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipment)) { + builder.setLogisticsChainElement(element); + } + } + Leg lastLeg = (Leg) tour.getTourElements().getLast(); + double startTime = lastLeg.getExpectedDepartureTime() + lastLeg.getExpectedTransportTime(); + builder.setStartTime(startTime); + builder.setEndTime(startTime + getUnloadEndTime(tour)); + + LspShipmentPlanElement unload = builder.build(); + String idString = + unload.getResourceId() + + "" + + unload.getLogisticChainElement().getId() + + unload.getElementType(); + Id id = Id.create(idString, LspShipmentPlanElement.class); + LspShipmentUtils.getOrCreateShipmentPlan(super.lspPlan, lspShipment.getId()) + .addPlanElement(id, unload); + } + + private double getUnloadEndTime(Tour tour) { + double unloadEndTime = 0; + for (TourElement element : tour.getTourElements()) { + if (element instanceof Tour.ServiceActivity serviceActivity) { + unloadEndTime = unloadEndTime + serviceActivity.getDuration(); + } + } + return unloadEndTime; + } + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/CollectionServiceEndEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/CollectionServiceEndEventHandler.java new file mode 100644 index 00000000000..ffd8f53ca59 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/CollectionServiceEndEventHandler.java @@ -0,0 +1,135 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import org.matsim.api.core.v01.Id; +import org.matsim.core.controler.events.AfterMobsimEvent; +import org.matsim.core.controler.listener.AfterMobsimListener; +import org.matsim.freight.carriers.CarrierService; +import org.matsim.freight.carriers.events.CarrierServiceEndEvent; +import org.matsim.freight.carriers.events.eventhandler.CarrierServiceEndEventHandler; +import org.matsim.freight.logistics.LSPCarrierResource; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LSPSimulationTracker; +import org.matsim.freight.logistics.LogisticChainElement; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentLeg; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; + +/*package-private*/ class CollectionServiceEndEventHandler + implements AfterMobsimListener, + CarrierServiceEndEventHandler, + LSPSimulationTracker { + + private final CarrierService carrierService; + private final LogisticChainElement logisticChainElement; + private final LSPCarrierResource resource; + private LspShipment lspShipment; + + public CollectionServiceEndEventHandler( + CarrierService carrierService, + LspShipment lspShipment, + LogisticChainElement element, + LSPCarrierResource resource) { + this.carrierService = carrierService; + this.lspShipment = lspShipment; + this.logisticChainElement = element; + this.resource = resource; + } + + @Override + public void reset(int iteration) { + // TODO Auto-generated method stub + + } + + @Override + public void handleEvent(CarrierServiceEndEvent event) { + if (event.getServiceId() == carrierService.getId() + && event.getCarrierId() == resource.getCarrier().getId()) { + logLoad(event); + logTransport(event); + } + } + + private void logLoad(CarrierServiceEndEvent event) { + LspShipmentUtils.LoggedShipmentLoadBuilder builder = + LspShipmentUtils.LoggedShipmentLoadBuilder.newInstance(); + builder.setStartTime(event.getTime() - event.getServiceDuration()); + builder.setEndTime(event.getTime()); + builder.setLogisticsChainElement(logisticChainElement); + builder.setResourceId(resource.getId()); + builder.setLinkId(event.getLinkId()); + builder.setCarrierId(event.getCarrierId()); + LspShipmentPlanElement loggedShipmentLoad = builder.build(); + String idString = + loggedShipmentLoad.getResourceId() + + "" + + loggedShipmentLoad.getLogisticChainElement().getId() + + loggedShipmentLoad.getElementType(); + Id loadId = Id.create(idString, LspShipmentPlanElement.class); + lspShipment.getShipmentLog().addPlanElement(loadId, loggedShipmentLoad); + } + + private void logTransport(CarrierServiceEndEvent event) { + LspShipmentUtils.LoggedShipmentTransportBuilder builder = + LspShipmentUtils.LoggedShipmentTransportBuilder.newInstance(); + builder.setStartTime(event.getTime()); + builder.setLogisticChainElement(logisticChainElement); + builder.setResourceId(resource.getId()); + builder.setFromLinkId(event.getLinkId()); + builder.setCarrierId(event.getCarrierId()); + LspShipmentLeg transport = builder.build(); + String idString = + transport.getResourceId() + + "" + + transport.getLogisticChainElement().getId() + + transport.getElementType(); + Id transportId = Id.create(idString, LspShipmentPlanElement.class); + lspShipment.getShipmentLog().addPlanElement(transportId, transport); + } + + public CarrierService getCarrierService() { + return carrierService; + } + + public LspShipment getLspShipment() { + return lspShipment; + } + + public LogisticChainElement getElement() { + return logisticChainElement; + } + + public Id getResourceId() { + return resource.getId(); + } + + @Override + public void setEmbeddingContainer(LspShipment pointer) { + this.lspShipment = pointer; + } + + @Override + public void notifyAfterMobsim(AfterMobsimEvent event) {} +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/DistributionCarrierResource.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/DistributionCarrierResource.java new file mode 100644 index 00000000000..00ca29acceb --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/DistributionCarrierResource.java @@ -0,0 +1,83 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import java.util.Collection; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.CarrierVehicle; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.DistributionCarrierResourceBuilder; + +/*package-private*/ class DistributionCarrierResource extends LSPDataObject + implements LSPCarrierResource { + + private final Carrier carrier; + private final Collection clientElements; + private final DistributionCarrierScheduler distributionHandler; + + DistributionCarrierResource(DistributionCarrierResourceBuilder builder) { + super(builder.id); + this.distributionHandler = builder.distributionHandler; + this.clientElements = builder.clientElements; + this.carrier = builder.carrier; + } + + @Override + public Id getStartLinkId() { + Id depotLinkId = null; + for (CarrierVehicle vehicle : carrier.getCarrierCapabilities().getCarrierVehicles().values()) { + if (depotLinkId == null || depotLinkId == vehicle.getLinkId()) { + depotLinkId = vehicle.getLinkId(); + } + } + + return depotLinkId; + } + + @Override + public Id getEndLinkId() { + Id depotLinkId = null; + for (CarrierVehicle vehicle : carrier.getCarrierCapabilities().getCarrierVehicles().values()) { + if (depotLinkId == null || depotLinkId == vehicle.getLinkId()) { + depotLinkId = vehicle.getLinkId(); + } + } + + return depotLinkId; + } + + @Override + public Collection getClientElements() { + return clientElements; + } + + @Override + public void schedule(int bufferTime, LSPPlan lspPlan) { + distributionHandler.scheduleShipments(lspPlan, this, bufferTime); + } + + public Carrier getCarrier() { + return carrier; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/DistributionCarrierScheduler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/DistributionCarrierScheduler.java new file mode 100644 index 00000000000..51704f91cb9 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/DistributionCarrierScheduler.java @@ -0,0 +1,480 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import java.util.*; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.locationtech.jts.util.Assert; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.carriers.Tour.Leg; +import org.matsim.freight.carriers.Tour.TourElement; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.VehicleType; + +/** + * Ähnlich zu CollectionCarrierScheduler: Nun werden Sendungen verteilt statt eingesammelt. + * + *

BUT: scheduleResource() is different from the one used in the case of collection. The + * LSPShipments are not simply handed over to jsprit which calculates the vehicle tours, but rather + * loaded into a waiting distribution vehicle in the order of their arrival at the depot. Once this + * vehicle is full, the tour for this single one is planned by jsprit. All vehicles are thus filled + * and scheduled consecutively. + */ +/*package-private*/ class DistributionCarrierScheduler extends LSPResourceScheduler { + + Logger log = LogManager.getLogger(DistributionCarrierScheduler.class); + + private Carrier carrier; + private DistributionCarrierResource resource; + private int carrierCnt = 1; + private final Scenario scenario; + + + /** + * Constructor for the DistributionCarrierScheduler. + * TODO: In the future, the scenario should come via injection(?) This here is only a dirty workaround. KMT'Aug'24 + * + * @param scenario the scenario + */ + DistributionCarrierScheduler(Scenario scenario) { + this.scenario = scenario; + } + + @Override + protected void initializeValues(LSPResource resource) { + if (resource.getClass() == DistributionCarrierResource.class) { + this.resource = (DistributionCarrierResource) resource; + this.carrier = this.resource.getCarrier(); + this.carrier.getServices().clear(); + this.carrier.getShipments().clear(); + this.carrier.getPlans().clear(); + } + } + + @Override + protected void scheduleResource() { + int load = 0; + double cumulatedLoadingTime = 0; + double availabilityTimeOfLastShipment = 0; + ArrayList copyOfAssignedShipments = new ArrayList<>(lspShipmentsToSchedule); + ArrayList shipmentsInCurrentTour = new ArrayList<>(); + List scheduledPlans = new LinkedList<>(); + + for (LspShipment lspShipment : copyOfAssignedShipments) { + // TODO KMT: Verstehe es nur mäßig, was er hier mit den Fahrzeugtypen macht. Er nimmt einfach + // das erste/nächste(?) und schaut ob es da rein passt... Aber was ist, wenn es mehrere + // gibt??? + VehicleType vehicleType = ResourceImplementationUtils.getVehicleTypeCollection(carrier).iterator().next(); + if ((load + lspShipment.getSize()) > vehicleType.getCapacity().getOther().intValue()) { + load = 0; + Carrier auxiliaryCarrier = + CarrierSchedulerUtils.solveVrpWithJsprit( + createAuxiliaryCarrier(shipmentsInCurrentTour, availabilityTimeOfLastShipment + cumulatedLoadingTime), + scenario); + scheduledPlans.add(auxiliaryCarrier.getSelectedPlan()); + var vrpLogic = CarrierSchedulerUtils.getVrpLogic(carrier); + switch (vrpLogic) { + case serviceBased -> { carrier.getServices().putAll(auxiliaryCarrier.getServices()); } + case shipmentBased -> { carrier.getShipments().putAll(auxiliaryCarrier.getShipments()); } + default -> throw new IllegalStateException("Unexpected value: " + vrpLogic); + } + + cumulatedLoadingTime = 0; + shipmentsInCurrentTour.clear(); + } + shipmentsInCurrentTour.add(lspShipment); + load = load + lspShipment.getSize(); + cumulatedLoadingTime = cumulatedLoadingTime + lspShipment.getDeliveryServiceTime(); + availabilityTimeOfLastShipment = LspShipmentUtils.getTimeOfLspShipment(lspShipment); + } + + if (!shipmentsInCurrentTour.isEmpty()) { + Carrier auxiliaryCarrier = + CarrierSchedulerUtils.solveVrpWithJsprit( + createAuxiliaryCarrier(shipmentsInCurrentTour, availabilityTimeOfLastShipment + cumulatedLoadingTime), + scenario); + scheduledPlans.add(auxiliaryCarrier.getSelectedPlan()); + + switch (CarrierSchedulerUtils.getVrpLogic(carrier)) { + case serviceBased -> { carrier.getServices().putAll(auxiliaryCarrier.getServices()); } + case shipmentBased -> { carrier.getShipments().putAll(auxiliaryCarrier.getShipments()); + //TODO: When using shipmentbased, only ONE Vrp should be created and solved. -> No need for the auxiliary carrier(s). KMT'Aug 24 + //Then we can also just pass all the vehicles over :) + //And need the TimeWindows for the Shipments... + } + default -> throw new IllegalStateException("Unexpected value: " + CarrierSchedulerUtils.getVrpLogic(carrier)); + } + shipmentsInCurrentTour.clear(); + } + + CarrierPlan plan = new CarrierPlan(carrier, unifyTourIds(scheduledPlans)); + plan.setScore(CarrierSchedulerUtils.sumUpScore(scheduledPlans)); + plan.setJspritScore(CarrierSchedulerUtils.sumUpJspritScore(scheduledPlans)); + carrier.addPlan(plan); + carrier.setSelectedPlan(plan); + } + + /** + * This method unifies the tourIds of the CollectionCarrier. + * + *

It is done because in the current setup, there is one (auxiliary) Carrier per Tour. ---> in + * each Carrier the Tour has the id 1. In a second step all of that tours were put together in one + * single carrier {@link #scheduleResource()} But now, this carrier can have several tours, all + * with the same id (1). + * + *

In this method all tours copied but with a new (unique) TourId. + * + *

This is a workaround. In my (KMT, sep'22) opinion it would be better to switch so {@link + * CarrierShipment}s instead of {@link CarrierService} and use only on DistributionCarrier with + * only one VRP and only one jsprit-Run. This would avoid this workaround and also improve the + * solution, because than the DistributionCarrier can decide on it one which shipments will go + * into which tours + * + * @param carrierPlans Collection of CarrierPlans + * @return Collection the scheduledTours with unified tour Ids. + */ + // private Collection unifyTourIds(Collection scheduledTours) { + private Collection unifyTourIds(Collection carrierPlans) { + int tourIdIndex = 1; + List scheduledToursUnified = new LinkedList<>(); + + for (CarrierPlan carrierPlan : carrierPlans) { + for (ScheduledTour scheduledTour : carrierPlan.getScheduledTours()) { + var newTour = + scheduledTour + .getTour() + .duplicateWithNewId(Id.create("dist_" + tourIdIndex, Tour.class)); + tourIdIndex++; + var newScheduledTour = + ScheduledTour.newInstance( + newTour, scheduledTour.getVehicle(), scheduledTour.getDeparture()); + scheduledToursUnified.add(newScheduledTour); + } + } + return scheduledToursUnified; + } + + private CarrierService convertToCarrierService(LspShipment lspShipment) { + Id serviceId = Id.create(lspShipment.getId().toString(), CarrierService.class); + CarrierService carrierService = CarrierService.Builder.newInstance(serviceId, lspShipment.getTo()) + //TODO TimeWindows are not set. This seems to be a problem. KMT'Aug'24 + //If added here, we also need to decide what happens, if the vehicles StartTime (plus TT) is > TimeWindowEnd .... + .setCapacityDemand(lspShipment.getSize()) + .setServiceDuration(lspShipment.getDeliveryServiceTime()) + .build(); + //ensure that the ids of the lspShipment and the carrierService are the same. This is needed for updating the LSPShipmentPlan + if (! Objects.equals(lspShipment.getId().toString(), carrierService.getId().toString())) { + log.error("Id of LspShipment: {} and CarrierService: {} do not match", lspShipment.getId().toString(), carrierService.getId().toString(), + new IllegalStateException("Id of LspShipment and CarrierService do not match")); + } + return carrierService; + } + + /** + * This method converts a LspShipment to a CarrierShipment. + * Please note: This method may get removed in the future, in case that the LSPShipment and the CarrierShipment are merged. KMT'Aug'24 + + * @param lspShipment the LspShipment to convert + * @return a CarrierShipment + */ + private CarrierShipment convertToCarrierShipment(LspShipment lspShipment) { + Id serviceId = Id.create(lspShipment.getId().toString(), CarrierShipment.class); + CarrierShipment carrierShipment = CarrierShipment.Builder.newInstance(serviceId, lspShipment.getFrom(), lspShipment.getTo(), lspShipment.getSize()) + //TODO TimeWindows are not set. This seems to be a problem. KMT'Aug'24 + //If added here, we also need to decide what happens, if the vehicles StartTime (plus TT) is > TimeWindowEnd .... + .setDeliveryServiceTime(lspShipment.getDeliveryServiceTime()) + .build(); + //ensure that the ids of the lspShipment and the carrierShipment are the same. This is needed for updating the LSPShipmentPlan + if (! Objects.equals(lspShipment.getId().toString(), carrierShipment.getId().toString())) { + log.error("Id of LspShipment: {} and CarrierService: {} do not match", lspShipment.getId().toString(), carrierShipment.getId().toString(), + new IllegalStateException("Id of LspShipment and CarrierService do not match")); + } + return carrierShipment; + } + + + @Override + protected void updateShipments() { + for (LspShipment lspShipment : lspShipmentsToSchedule) { + for (ScheduledTour scheduledTour : carrier.getSelectedPlan().getScheduledTours()) { + Tour tour = scheduledTour.getTour(); + + switch (CarrierSchedulerUtils.getVrpLogic(carrier)) { + case serviceBased -> { + for (TourElement element : tour.getTourElements()) { + if (element instanceof Tour.ServiceActivity serviceActivity) { + if (Objects.equals(lspShipment.getId().toString(), serviceActivity.getService().getId().toString())) { + addShipmentLoadElement(lspShipment, tour); + addShipmentTransportElement(lspShipment, tour, serviceActivity); + addShipmentUnloadElement(lspShipment, serviceActivity); + addDistributionTourStartEventHandler(serviceActivity, lspShipment, resource, tour); + addDistributionServiceEventHandler(serviceActivity, lspShipment, resource); + } + } + } + } + case shipmentBased -> { + //TODO needs to get fixed. KMT'Aug'24 + for (TourElement element : tour.getTourElements()) { + if (element instanceof Tour.Delivery deliveryActivity) { + if (Objects.equals(lspShipment.getId().toString(), deliveryActivity.getShipment().getId().toString())) { + addShipmentLoadElement(lspShipment, tour); + addShipmentTransportElement(lspShipment, tour, deliveryActivity); + addShipmentUnloadElement(lspShipment, deliveryActivity); + addDistributionTourStartEventHandler(deliveryActivity, lspShipment, resource, tour); + addDistributionServiceEventHandler(deliveryActivity, lspShipment, resource); + } + } + } + } + default -> + throw new IllegalStateException( + "Unexpected value: " + CarrierSchedulerUtils.getVrpLogic(carrier)); + } + } + } + } + + private void addShipmentLoadElement(LspShipment lspShipment, Tour tour) { + LspShipmentUtils.ScheduledShipmentLoadBuilder builder = + LspShipmentUtils.ScheduledShipmentLoadBuilder.newInstance(); + builder.setResourceId(resource.getId()); + + for (LogisticChainElement element : resource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipment)) { + builder.setLogisticChainElement(element); + } + } + + int startIndex = tour.getTourElements().indexOf(tour.getTourElements().indexOf(tour.getStart())); + Leg legAfterStart = (Leg) tour.getTourElements().get(startIndex + 1); + double startTimeOfTransport = legAfterStart.getExpectedDepartureTime(); + double cumulatedLoadingTime = 0; + for (TourElement element : tour.getTourElements()) { + if (element instanceof Tour.ServiceActivity activity) { + cumulatedLoadingTime = cumulatedLoadingTime + activity.getDuration(); + } + } + builder.setStartTime(startTimeOfTransport - cumulatedLoadingTime); + builder.setEndTime(startTimeOfTransport); + + LspShipmentPlanElement load = builder.build(); + String idString = + load.getResourceId() + "" + load.getLogisticChainElement().getId() + load.getElementType(); + Id id = Id.create(idString, LspShipmentPlanElement.class); + LspShipmentUtils.getOrCreateShipmentPlan(super.lspPlan, lspShipment.getId()) + .addPlanElement(id, load); + } + + private void addShipmentTransportElement( + LspShipment lspShipment, Tour tour, Tour.TourActivity tourActivity) { + + LspShipmentUtils.ScheduledShipmentTransportBuilder builder = + LspShipmentUtils.ScheduledShipmentTransportBuilder.newInstance(); + builder.setResourceId(resource.getId()); + + for (LogisticChainElement element : resource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipment)) { + builder.setLogisticChainElement(element); + } + } + + int startIndex = tour.getTourElements().indexOf(tour.getTourElements().indexOf(tour.getStart())); + final Leg legAfterStart = (Leg) tour.getTourElements().get(startIndex + 1); + final int serviceIndex = tour.getTourElements().indexOf(tourActivity); + final Leg legBeforeService = (Leg) tour.getTourElements().get(serviceIndex - 1); + final double startTimeOfTransport = legAfterStart.getExpectedDepartureTime(); + final double endTimeOfTransport = + legBeforeService.getExpectedTransportTime() + legBeforeService.getExpectedDepartureTime(); + Assert.isTrue( + endTimeOfTransport >= startTimeOfTransport, + "latest End must be later than earliest start. start: " + + startTimeOfTransport + + " ; end: " + + endTimeOfTransport); + + builder.setStartTime(startTimeOfTransport); + builder.setEndTime(endTimeOfTransport); + builder.setCarrierId(carrier.getId()); + builder.setFromLinkId(tour.getStartLinkId()); + builder.setToLinkId(tourActivity.getLocation()); + switch( tourActivity ){ + case Tour.ServiceActivity serviceActivity -> builder.setCarrierService( serviceActivity.getService() ); + case Tour.ShipmentBasedActivity shipment -> builder.setCarrierShipment( shipment.getShipment() ); + default -> throw new IllegalStateException("Unexpected value: " + tourActivity); + // yyyy: At the jsprit level, it makes sense to have these different since services run about 10x faster than shipments. However, + // at the matsim level we could consider to either only have shipments (from depot to xx for what used to be services), or only have + // services. See also MATSim issue #3510 kai/kai, oct'24 + } + LspShipmentPlanElement transport = builder.build(); + String idString = + transport.getResourceId() + + "" + + transport.getLogisticChainElement().getId() + + transport.getElementType(); + Id id = Id.create(idString, LspShipmentPlanElement.class); + LspShipmentUtils.getOrCreateShipmentPlan(super.lspPlan, lspShipment.getId()) + .addPlanElement(id, transport); + } + + private void addShipmentUnloadElement(LspShipment tuple, Tour.TourActivity tourActivity) { + + LspShipmentUtils.ScheduledShipmentUnloadBuilder builder = + LspShipmentUtils.ScheduledShipmentUnloadBuilder.newInstance(); + builder.setResourceId(resource.getId()); + + for (LogisticChainElement element : resource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(tuple)) { + builder.setLogisticsChainElement(element); + } + } + + final double startTime = tourActivity.getExpectedArrival(); + final double endTime = startTime + tourActivity.getDuration(); + //Todo: Check if it also works with shipmentBased activity, or if we in that case need the way with the switch-case and the data from the shipmentBasedActivity. KMT Oct'24 + +// switch( tourActivity ){ +// case Tour.ServiceActivity serviceActivity -> { +// startTime = tourActivity.getExpectedArrival(); +// endTime = startTime + tourActivity.getDuration(); +// +//// startTime = serviceActivity.getExpectedArrival(); //Why is there also a arrivalTime in the Tour.ServiceActivity? Why do not take the date in TourActivity.getExpectedArrivalTime()? KMT Oct'24 +//// endTime = startTime + serviceActivity.getDuration(); +// } +// case Tour.ShipmentBasedActivity shipmentBasedActivity -> { +// //Todo: Not tested ; maybe we need to take the data from the shipment itself (as is was originally done with the service: serviceActivity.getService() ,..... KMT Oct'24 +// startTime = shipmentBasedActivity.getExpectedArrival(); //Why is there also a arrivalTime in the Tour.ServiceActivity? Why do not take the date in TourActivity.getExpectedArrivalTime()? KMT Oct'24 +// endTime = startTime + shipmentBasedActivity.getDuration(); +// +// } +// default -> {} +// } + + Assert.isTrue( + endTime >= startTime, + "latest End must be later than earliest start. start: " + startTime + " ; end: " + endTime); + + builder.setStartTime(startTime); + builder.setEndTime(endTime); + + LspShipmentPlanElement unload = builder.build(); + String idString = + unload.getResourceId() + + String.valueOf(unload.getLogisticChainElement().getId()) + + unload.getElementType(); + Id id = Id.create(idString, LspShipmentPlanElement.class); + LspShipmentUtils.getOrCreateShipmentPlan(super.lspPlan, tuple.getId()) + .addPlanElement(id, unload); + } + + private Carrier createAuxiliaryCarrier(ArrayList shipmentsInCurrentTour, double startTime) { + final Id carrierId = Id.create(carrier.getId().toString() + carrierCnt, Carrier.class); + carrierCnt++; + + CarrierVehicle carrierVehicle = carrier.getCarrierCapabilities().getCarrierVehicles().values().iterator().next(); + CarrierVehicle cv = CarrierVehicle.Builder.newInstance( + carrierVehicle.getId(), carrierVehicle.getLinkId(), carrierVehicle.getType()) + .setEarliestStart(startTime) + .setLatestEnd(24 * 60 * 60) + .build(); + Carrier auxiliaryCarrier = CarriersUtils.createCarrier(carrierId); + auxiliaryCarrier.getCarrierCapabilities().getCarrierVehicles().put(cv.getId(), cv); + auxiliaryCarrier.getCarrierCapabilities().setFleetSize(FleetSize.FINITE); + + switch (CarrierSchedulerUtils.getVrpLogic(carrier)) { + case serviceBased -> { + for (LspShipment lspShipment : shipmentsInCurrentTour) { + CarrierService carrierService = convertToCarrierService(lspShipment); + auxiliaryCarrier.getServices().put(carrierService.getId(), carrierService); + } + } + case shipmentBased -> { + for (LspShipment lspShipment : shipmentsInCurrentTour) { + CarrierShipment carrierShipment = convertToCarrierShipment(lspShipment); + auxiliaryCarrier.getShipments().put(carrierShipment.getId(), carrierShipment); + } + } + default -> throw new IllegalStateException("Unexpected value: " + CarrierSchedulerUtils.getVrpLogic(carrier)); + } + + + return auxiliaryCarrier; + } + + private void addDistributionServiceEventHandler( + Tour.TourActivity tourActivity, + LspShipment lspShipment, + LSPCarrierResource resource) { + + for (LogisticChainElement element : this.resource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipment)) { + DistributionServiceStartEventHandler handler; + switch (tourActivity) { + case Tour.ServiceActivity serviceActivity-> { + handler = new DistributionServiceStartEventHandler(serviceActivity.getService(), lspShipment, element, resource, null); + } + case Tour.ShipmentBasedActivity shipmentBasedActivity-> { + handler = new DistributionServiceStartEventHandler(null, lspShipment, element, resource, shipmentBasedActivity.getShipment()); + } + default -> throw new IllegalStateException("Unexpected value: " + tourActivity); + } + + lspShipment.addSimulationTracker(handler); + break; + } + } + } + + private void addDistributionTourStartEventHandler( + Tour.TourActivity tourActivity, + LspShipment lspShipment, + LSPCarrierResource resource, + Tour tour) { + + for (LogisticChainElement element : this.resource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipment)) { + LSPTourStartEventHandler handler; + switch (tourActivity) { + case Tour.ServiceActivity serviceActivity-> { + handler = new LSPTourStartEventHandler(lspShipment, serviceActivity.getService(), element, resource, tour, null); + } + case Tour.ShipmentBasedActivity shipmentBasedActivity-> { + handler = new LSPTourStartEventHandler(lspShipment, null , element, resource, tour, shipmentBasedActivity.getShipment()); + } + default -> throw new IllegalStateException("Unexpected value: " + tourActivity); + } + + lspShipment.addSimulationTracker(handler); + break; + } + } + } + + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/DistributionServiceStartEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/DistributionServiceStartEventHandler.java new file mode 100644 index 00000000000..047ade24f65 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/DistributionServiceStartEventHandler.java @@ -0,0 +1,175 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import org.matsim.api.core.v01.Id; +import org.matsim.core.controler.events.AfterMobsimEvent; +import org.matsim.core.controler.listener.AfterMobsimListener; +import org.matsim.freight.carriers.CarrierService; +import org.matsim.freight.carriers.CarrierShipment; +import org.matsim.freight.carriers.events.CarrierServiceStartEvent; +import org.matsim.freight.carriers.events.CarrierShipmentDeliveryStartEvent; +import org.matsim.freight.carriers.events.eventhandler.CarrierServiceStartEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierShipmentDeliveryStartEventHandler; +import org.matsim.freight.logistics.LSPCarrierResource; +import org.matsim.freight.logistics.LSPSimulationTracker; +import org.matsim.freight.logistics.LogisticChainElement; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentLeg; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; + +/*package-private*/ class DistributionServiceStartEventHandler + implements AfterMobsimListener, + CarrierServiceStartEventHandler, + CarrierShipmentDeliveryStartEventHandler, + LSPSimulationTracker { + + private final CarrierService carrierService; + private final CarrierShipment carrierShipment; + private final LogisticChainElement logisticChainElement; + private final LSPCarrierResource resource; + private LspShipment lspShipment; + + DistributionServiceStartEventHandler( + CarrierService carrierService, + LspShipment lspShipment, + LogisticChainElement element, + LSPCarrierResource resource, + CarrierShipment carrierShipment) { + this.carrierShipment = carrierShipment; + this.carrierService = carrierService; + this.lspShipment = lspShipment; + this.logisticChainElement = element; + this.resource = resource; + } + + @Override + public void reset(int iteration) { + // TODO Auto-generated method stub + + } + + @Override + public void handleEvent(CarrierServiceStartEvent event) { + if (event.getServiceId() == carrierService.getId() + && event.getCarrierId() == resource.getCarrier().getId()) { + logTransport(event); + logUnload(event); + } + } + + @Override + public void handleEvent(CarrierShipmentDeliveryStartEvent event) { + if (event.getShipmentId() == this.carrierShipment.getId() + && event.getCarrierId() == resource.getCarrier().getId()) { + logTransport(event); + logUnload(event); + } + } + + private void logTransport(CarrierServiceStartEvent event) { + String idString = resource.getId() + "" + logisticChainElement.getId() + "TRANSPORT"; + Id id = Id.create(idString, LspShipmentPlanElement.class); + LspShipmentPlanElement abstractPlanElement = + lspShipment.getShipmentLog().getPlanElements().get(id); + if (abstractPlanElement instanceof LspShipmentLeg transport) { + transport.setEndTime(event.getTime()); + } + } + + //TODO: Inhaltlich ansehen, was hier passiert. Ist aktuell nur Copy und Paste aus Service-Variante + private void logTransport(CarrierShipmentDeliveryStartEvent event) { + String idString = resource.getId() + "" + logisticChainElement.getId() + "TRANSPORT"; + Id id = Id.create(idString, LspShipmentPlanElement.class); + LspShipmentPlanElement abstractPlanElement = + lspShipment.getShipmentLog().getPlanElements().get(id); + if (abstractPlanElement instanceof LspShipmentLeg transport) { + transport.setEndTime(event.getTime()); + } + } + + private void logUnload(CarrierServiceStartEvent event) { + LspShipmentUtils.LoggedShipmentUnloadBuilder builder = + LspShipmentUtils.LoggedShipmentUnloadBuilder.newInstance(); + builder.setCarrierId(event.getCarrierId()); + builder.setLinkId(event.getLinkId()); + builder.setLogisticChainElement(logisticChainElement); + builder.setResourceId(resource.getId()); + builder.setStartTime(event.getTime()); + builder.setEndTime(event.getTime() + event.getServiceDuration()); + LspShipmentPlanElement unload = builder.build(); + String idString = + unload.getResourceId() + + "" + + unload.getLogisticChainElement().getId() + + unload.getElementType(); + Id unloadId = Id.create(idString, LspShipmentPlanElement.class); + lspShipment.getShipmentLog().addPlanElement(unloadId, unload); + } + + //TODO: Inhaltlich ansehen, was hier passiert. Ist aktuell nur Copy und Paste aus Service-Variante + private void logUnload(CarrierShipmentDeliveryStartEvent event) { + LspShipmentUtils.LoggedShipmentUnloadBuilder builder = + LspShipmentUtils.LoggedShipmentUnloadBuilder.newInstance(); + builder.setCarrierId(event.getCarrierId()); + builder.setLinkId(event.getLinkId()); + builder.setLogisticChainElement(logisticChainElement); + builder.setResourceId(resource.getId()); + builder.setStartTime(event.getTime()); + builder.setEndTime(event.getTime() + event.getDeliveryDuration()); + LspShipmentPlanElement unload = builder.build(); + String idString = + unload.getResourceId() + + "" + + unload.getLogisticChainElement().getId() + + unload.getElementType(); + Id unloadId = Id.create(idString, LspShipmentPlanElement.class); + lspShipment.getShipmentLog().addPlanElement(unloadId, unload); + } + + //Todo: Wird das auch inhaltlich irgendwo genutzt,oder ist das nur für die Tests da? + //todo ctd. Brauchen wir den CarrierService hier eigentlich wirklich oder kann das zurück gebaut werden? KMT Okt'24 + public CarrierService getCarrierService() { + return carrierService; + } + + public LspShipment getLspShipment() { + return lspShipment; + } + + public LogisticChainElement getLogisticChainElement() { + return logisticChainElement; + } + + public LSPCarrierResource getResource() { + return resource; + } + + @Override + public void setEmbeddingContainer(LspShipment pointer) { + this.lspShipment = pointer; + } + + @Override + public void notifyAfterMobsim(AfterMobsimEvent event) {} +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/LSPTourEndEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/LSPTourEndEventHandler.java new file mode 100644 index 00000000000..db316c2e849 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/LSPTourEndEventHandler.java @@ -0,0 +1,156 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.controler.events.AfterMobsimEvent; +import org.matsim.core.controler.listener.AfterMobsimListener; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.CarrierService; +import org.matsim.freight.carriers.Tour; +import org.matsim.freight.carriers.Tour.ServiceActivity; +import org.matsim.freight.carriers.Tour.TourElement; +import org.matsim.freight.carriers.events.CarrierTourEndEvent; +import org.matsim.freight.carriers.events.eventhandler.CarrierTourEndEventHandler; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentLeg; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; + +/*package-private*/ class LSPTourEndEventHandler + implements AfterMobsimListener, CarrierTourEndEventHandler, LSPSimulationTracker { + + private final CarrierService carrierService; + private final LogisticChainElement logisticChainElement; + private final LSPCarrierResource resource; + private final Tour tour; + private LspShipment lspShipment; + + public LSPTourEndEventHandler( + LspShipment lspShipment, + CarrierService carrierService, + LogisticChainElement logisticChainElement, + LSPCarrierResource resource, + Tour tour) { + this.lspShipment = lspShipment; + this.carrierService = carrierService; + this.logisticChainElement = logisticChainElement; + this.resource = resource; + this.tour = tour; + } + + @Override + public void reset(int iteration) { + // TODO Auto-generated method stub + } + + @Override + public void handleEvent(CarrierTourEndEvent event) { + if (event.getTourId().equals(tour.getId())) { + for (TourElement element : tour.getTourElements()) { + if (element instanceof ServiceActivity serviceActivity) { + if (serviceActivity.getService().getId() == carrierService.getId() + && event.getCarrierId() == resource.getCarrier().getId()) { + if (resource instanceof CollectionCarrierResource) { + logTransport(event.getTime(), tour.getEndLinkId()); + logUnload( + event.getCarrierId(), + event.getTime(), + event.getTime() + getTotalUnloadingTime(tour)); + } else if (resource instanceof MainRunCarrierResource) { + logUnload( + event.getCarrierId(), + event.getTime() - getTotalUnloadingTime(tour), + event.getTime()); + logTransport(event.getTime() - getTotalUnloadingTime(tour), event.getLinkId()); + } + } + } + } + } + } + + private void logUnload(Id carrierId, double startTime, double endTime) { + LspShipmentUtils.LoggedShipmentUnloadBuilder builder = + LspShipmentUtils.LoggedShipmentUnloadBuilder.newInstance(); + builder.setStartTime(startTime); + builder.setEndTime(endTime); + builder.setLogisticChainElement(logisticChainElement); + builder.setResourceId(resource.getId()); + builder.setCarrierId(carrierId); + LspShipmentPlanElement unload = builder.build(); + String idString = + unload.getResourceId().toString() + + unload.getLogisticChainElement().getId() + + unload.getElementType(); + Id unloadId = Id.create(idString, LspShipmentPlanElement.class); + lspShipment.getShipmentLog().addPlanElement(unloadId, unload); + } + + private void logTransport(double endTime, Id endLinkId) { + String idString = resource.getId().toString() + logisticChainElement.getId() + "TRANSPORT"; + LspShipmentPlanElement abstractPlanElement = + lspShipment + .getShipmentLog() + .getPlanElements() + .get(Id.create(idString, LspShipmentPlanElement.class)); + if (abstractPlanElement instanceof LspShipmentLeg transport) { + transport.setEndTime(endTime); + transport.setToLinkId(endLinkId); + } + } + + private double getTotalUnloadingTime(Tour tour) { + double totalTime = 0; + for (TourElement element : tour.getTourElements()) { + if (element instanceof ServiceActivity serviceActivity) { + totalTime = totalTime + serviceActivity.getDuration(); + } + } + return totalTime; + } + + public CarrierService getCarrierService() { + return carrierService; + } + + public LspShipment getLspShipment() { + return lspShipment; + } + + public LogisticChainElement getLogisticChainElement() { + return logisticChainElement; + } + + public Id getResourceId() { + return resource.getId(); + } + + @Override + public void setEmbeddingContainer(LspShipment pointer) { + this.lspShipment = pointer; + } + + @Override + public void notifyAfterMobsim(AfterMobsimEvent event) {} +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/LSPTourStartEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/LSPTourStartEventHandler.java new file mode 100644 index 00000000000..46a0ae0e709 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/LSPTourStartEventHandler.java @@ -0,0 +1,173 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import java.util.Objects; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.CarrierService; +import org.matsim.freight.carriers.CarrierShipment; +import org.matsim.freight.carriers.Tour; +import org.matsim.freight.carriers.Tour.ServiceActivity; +import org.matsim.freight.carriers.Tour.TourElement; +import org.matsim.freight.carriers.events.CarrierTourStartEvent; +import org.matsim.freight.carriers.events.eventhandler.CarrierTourStartEventHandler; +import org.matsim.freight.logistics.LSPCarrierResource; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LSPSimulationTracker; +import org.matsim.freight.logistics.LogisticChainElement; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentLeg; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; + +/*package-private*/ class LSPTourStartEventHandler + implements CarrierTourStartEventHandler, LSPSimulationTracker { + + private final Tour tour; + private final CarrierService carrierService; + private final CarrierShipment carrierShipment; + private final LogisticChainElement logisticChainElement; + private final LSPCarrierResource resource; + private LspShipment lspShipment; + + public LSPTourStartEventHandler( + LspShipment lspShipment, + CarrierService carrierService, + LogisticChainElement logisticChainElement, + LSPCarrierResource resource, + Tour tour, + CarrierShipment carrierShipment) + { + this.lspShipment = lspShipment; + this.carrierService = carrierService; + this.carrierShipment = carrierShipment; + this.logisticChainElement = logisticChainElement; + this.resource = resource; + this.tour = tour; + } + + @Override + public void reset(int iteration) { + // TODO Auto-generated method stub + } + + @Override + public void handleEvent(CarrierTourStartEvent event) { + if (event.getTourId().equals(tour.getId()) && event.getCarrierId() == resource.getCarrier().getId()) { + for (TourElement tourElement : tour.getTourElements()) { + switch (tourElement) { + //This could even be short, if the Id would be available already on the level of Tour.TourActivity. KMT Oct'24 + case ServiceActivity serviceActivity -> { + if (serviceActivity.getService().getId() == carrierService.getId()) { + logLoadAndTransport(event); + } + } + case Tour.ShipmentBasedActivity shipmentBasedActivity -> { + if (Objects.equals(shipmentBasedActivity.getShipment().getId().toString(), carrierService.getId().toString())) { + logLoadAndTransport(event); + } + } + case null, default -> {} + } + } + } + } + + private void logLoadAndTransport(CarrierTourStartEvent event) { + if (resource instanceof DistributionCarrierResource || resource instanceof MainRunCarrierResource) { + logLoad(event.getCarrierId(), event.getLinkId(), event.getTime() - getCumulatedLoadingTime(tour), event.getTime()); + logTransport(event.getCarrierId(), event.getLinkId(), tour.getEndLinkId(), event.getTime()); + } + } + + private void logLoad(Id carrierId, Id linkId, double startTime, double endTime) { + LspShipmentUtils.LoggedShipmentLoadBuilder builder = + LspShipmentUtils.LoggedShipmentLoadBuilder.newInstance(); + builder.setCarrierId(carrierId); + builder.setLinkId(linkId); + builder.setLogisticsChainElement(logisticChainElement); + builder.setResourceId(resource.getId()); + builder.setStartTime(startTime); + builder.setEndTime(endTime); + LspShipmentPlanElement loggedShipmentLoad = builder.build(); + String idString = + loggedShipmentLoad.getResourceId() + + "" + + loggedShipmentLoad.getLogisticChainElement().getId() + + loggedShipmentLoad.getElementType(); + Id loadId = Id.create(idString, LspShipmentPlanElement.class); + lspShipment.getShipmentLog().addPlanElement(loadId, loggedShipmentLoad); + } + + private void logTransport(Id carrierId, Id fromLinkId, + Id toLinkId, double startTime) { + LspShipmentUtils.LoggedShipmentTransportBuilder builder = + LspShipmentUtils.LoggedShipmentTransportBuilder.newInstance(); + builder.setCarrierId(carrierId); + builder.setFromLinkId(fromLinkId); + builder.setToLinkId(toLinkId); + builder.setLogisticChainElement(logisticChainElement); + builder.setResourceId(resource.getId()); + builder.setStartTime(startTime); + LspShipmentLeg transport = builder.build(); + String idString = + transport.getResourceId() + + "" + + transport.getLogisticChainElement().getId() + + transport.getElementType(); + Id transportId = Id.create(idString, LspShipmentPlanElement.class); + lspShipment.getShipmentLog().addPlanElement(transportId, transport); + } + + private double getCumulatedLoadingTime(Tour tour) { + double cumulatedLoadingTime = 0; + for (TourElement tourElement : tour.getTourElements()) { + if (tourElement instanceof ServiceActivity serviceActivity) { + cumulatedLoadingTime = cumulatedLoadingTime + serviceActivity.getDuration(); + } + } + return cumulatedLoadingTime; + } + + public CarrierService getCarrierService() { + return carrierService; + } + + public LspShipment getLspShipment() { + return lspShipment; + } + + public LogisticChainElement getLogisticChainElement() { + return logisticChainElement; + } + + public Id getResourceId() { + return resource.getId(); + } + + @Override + public void setEmbeddingContainer(LspShipment pointer) { + this.lspShipment = pointer; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/MainRunCarrierResource.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/MainRunCarrierResource.java new file mode 100644 index 00000000000..8dd7eb1f0a3 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/MainRunCarrierResource.java @@ -0,0 +1,88 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import java.util.Collection; +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.freight.carriers.Carrier; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.MainRunCarrierResourceBuilder; + +/*package-private*/ class MainRunCarrierResource extends LSPDataObject + implements LSPCarrierResource { + + private static final Logger log = LogManager.getLogger(MainRunCarrierResource.class); + + private final Carrier carrier; + private final Id fromLinkId; + private final Id toLinkId; + private final Collection clientElements; + private final MainRunCarrierScheduler mainRunScheduler; + + private final ResourceImplementationUtils.VehicleReturn vehicleReturn; + + MainRunCarrierResource(MainRunCarrierResourceBuilder builder) { + super(builder.getId()); + this.carrier = builder.getCarrier(); + this.fromLinkId = builder.getFromLinkId(); + this.toLinkId = builder.getToLinkId(); + this.clientElements = builder.getClientElements(); + this.mainRunScheduler = builder.getMainRunScheduler(); + if (builder.getVehicleReturn() != null) { + this.vehicleReturn = builder.getVehicleReturn(); + } else { + log.warn("Return behaviour was not specified. Using the following setting as default: {}", ResourceImplementationUtils.VehicleReturn.endAtToLink); + this.vehicleReturn = ResourceImplementationUtils.VehicleReturn.endAtToLink; + } + } + + @Override + public Id getStartLinkId() { + return fromLinkId; + } + + @Override + public Id getEndLinkId() { + return toLinkId; + } + + @Override + public Collection getClientElements() { + return clientElements; + } + + @Override + public void schedule(int bufferTime, LSPPlan lspPlan) { + mainRunScheduler.scheduleShipments(lspPlan, this, bufferTime); + } + + public Carrier getCarrier() { + return carrier; + } + + public ResourceImplementationUtils.VehicleReturn getVehicleReturn() { + return vehicleReturn; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/MainRunCarrierScheduler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/MainRunCarrierScheduler.java new file mode 100644 index 00000000000..99f49186e11 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/MainRunCarrierScheduler.java @@ -0,0 +1,388 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import java.util.*; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.population.routes.NetworkRoute; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.Tour.Leg; +import org.matsim.freight.carriers.Tour.TourElement; +import org.matsim.freight.carriers.jsprit.NetworkBasedTransportCosts; +import org.matsim.freight.carriers.jsprit.NetworkRouter; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.VehicleType; + +/** + * In the case of the MainRunResource, the incoming LSPShipments are bundled together until their + * total weight exceeds the capacity of the deployed vehicle type. Then, this bundle of LSPShipments + * is converted to a scheduled tour from the freight contrib of MATSim. The start of this tour is + * located at the first TranshipmentHub and the end at the second one. All LSPShipments are + * converted to services that take place at the end point of the tour. + * + *

Tour is routed by MATSim Network Router. + * + *

* The tour starts after the last shipment * has arrived and the time necessary for loading all + * shipments into the vehicle * has passed. + */ +/*package-private*/ class MainRunCarrierScheduler extends LSPResourceScheduler { + + private Carrier carrier; + private MainRunCarrierResource resource; + private ArrayList pairs; + private final Scenario scenario; + private int tourIdIndex = 1; // Have unique TourIds for the MainRun. + + /*package-private*/ MainRunCarrierScheduler(Scenario scenario) { + this.pairs = new ArrayList<>(); + this.scenario = scenario; + } + + @Override + protected void initializeValues(LSPResource resource) { + this.pairs = new ArrayList<>(); + if (resource.getClass() == MainRunCarrierResource.class) { + this.resource = (MainRunCarrierResource) resource; + this.carrier = this.resource.getCarrier(); + this.carrier.getServices().clear(); + this.carrier.getShipments().clear(); + this.carrier.getPlans().clear(); + } + } + + @Override + protected void scheduleResource() { + int load = 0; + List copyOfAssignedShipments = new ArrayList<>(lspShipmentsToSchedule); + copyOfAssignedShipments.sort(Comparator.comparingDouble(LspShipmentUtils::getTimeOfLspShipment)); + ArrayList shipmentsInCurrentTour = new ArrayList<>(); + // ArrayList scheduledTours = new ArrayList<>(); + List scheduledPlans = new LinkedList<>(); + + for (LspShipment lspShipment : copyOfAssignedShipments) { + // Add job as "services" to the carrier. So the carrier has this available + CarrierService carrierService = convertToCarrierService(lspShipment); + carrier.getServices().put(carrierService.getId(), carrierService); + + VehicleType vehicleType = + ResourceImplementationUtils.getVehicleTypeCollection(carrier).iterator().next(); + if ((load + lspShipment.getSize()) + > vehicleType.getCapacity().getOther().intValue()) { + load = 0; + CarrierPlan plan = createPlan(carrier, shipmentsInCurrentTour); + scheduledPlans.add(plan); + shipmentsInCurrentTour.clear(); + } + shipmentsInCurrentTour.add(lspShipment); + load = load + lspShipment.getSize(); + } + if (!shipmentsInCurrentTour.isEmpty()) { + CarrierPlan plan = createPlan(carrier, shipmentsInCurrentTour); + scheduledPlans.add(plan); + shipmentsInCurrentTour.clear(); + } + + List scheduledTours = new LinkedList<>(); + for (CarrierPlan scheduledPlan : scheduledPlans) { + scheduledTours.addAll(scheduledPlan.getScheduledTours()); + } + CarrierPlan plan = new CarrierPlan(carrier, scheduledTours); + plan.setScore(CarrierSchedulerUtils.sumUpScore(scheduledPlans)); + carrier.addPlan(plan); + carrier.setSelectedPlan(plan); + } + + private CarrierPlan createPlan(Carrier carrier, List lspShipments) { + + // TODO: Allgemein: Hier ist alles manuell zusammen gesetzt; es findet KEINE Tourenplanung + // statt! + NetworkBasedTransportCosts.Builder tpcostsBuilder = + NetworkBasedTransportCosts.Builder.newInstance( + scenario.getNetwork(), + ResourceImplementationUtils.getVehicleTypeCollection(resource.getCarrier())); + NetworkBasedTransportCosts netbasedTransportcosts = tpcostsBuilder.build(); + Collection tours = new ArrayList<>(); + + Tour.Builder tourBuilder = Tour.Builder.newInstance(Id.create(tourIdIndex, Tour.class)); + tourIdIndex++; + tourBuilder.scheduleStart(Id.create(resource.getStartLinkId(), Link.class)); + + double totalLoadingTime = 0; + double latestLspShipmentTime = 0; + + for (LspShipment lspShipment : lspShipments) { + totalLoadingTime = totalLoadingTime + lspShipment.getDeliveryServiceTime(); + if (LspShipmentUtils.getTimeOfLspShipment(lspShipment) > latestLspShipmentTime) { + latestLspShipmentTime = LspShipmentUtils.getTimeOfLspShipment(lspShipment); + } + tourBuilder.addLeg(new Leg()); + CarrierService carrierService = convertToCarrierService(lspShipment); + pairs.add(new LSPShipmentCarrierServicePair(lspShipment, carrierService)); + tourBuilder.scheduleService(carrierService); + } + + tourBuilder.addLeg(new Leg()); + switch (resource.getVehicleReturn()) { + case returnToFromLink -> // The more "urban" behaviour: The vehicle returns to its origin + // (startLink). + tourBuilder.scheduleEnd(Id.create(resource.getStartLinkId(), Link.class)); + case endAtToLink -> // The more "long-distance" behaviour: The vehicle ends at its destination + // (toLink). + tourBuilder.scheduleEnd(Id.create(resource.getEndLinkId(), Link.class)); + default -> throw new IllegalStateException( + "Unexpected value: " + resource.getVehicleReturn()); + } + Tour vehicleTour = tourBuilder.build(); + CarrierVehicle vehicle = + carrier.getCarrierCapabilities().getCarrierVehicles().values().iterator().next(); + double tourStartTime = latestLspShipmentTime + totalLoadingTime; + ScheduledTour sTour = ScheduledTour.newInstance(vehicleTour, vehicle, tourStartTime); + + tours.add(sTour); + CarrierPlan plan = new CarrierPlan(carrier, tours); + NetworkRouter.routePlan(plan, netbasedTransportcosts); + plan.setScore(scorePlanManually(plan)); + return plan; + } + + /** + * For the main run, there is currently (nov'22) no jsprit planning. The plan is instead + * constructed manually. As a consequence, there is no score (from jsprit) for this plan + * available. To avoid issues in later scoring of the LSP, we would like to hava also a score for + * the MainRunCarrier. This is calculated here manually + * + *

It bases on the - vehicle's fixed costs - distance dependent costs - (expected) travel time + * dependent costs NOT included is the calculation of activity times,... But this is currently + * also missing e.g. in the distributionCarrier, where the VRP setup does not include this :( + * + * @param plan The carrierPlan, that should get scored. + * @return the calculated score + */ + private double scorePlanManually(CarrierPlan plan) { + // score plan // Note: Activities are not scored, but they are also NOT scored for the + // Distribution carrier (as the VRP is currently set up) kmt nov'22 + double score = 0.; + for (ScheduledTour scheduledTour : plan.getScheduledTours()) { + // vehicle fixed costs + score = score + scheduledTour.getVehicle().getType().getCostInformation().getFixedCosts(); + + // distance + double distance = 0.0; + double time = 0.0; + for (TourElement tourElement : scheduledTour.getTour().getTourElements()) { + if (tourElement instanceof Leg leg) { + // distance + NetworkRoute route = (NetworkRoute) leg.getRoute(); + for (Id linkId : route.getLinkIds()) { + distance = distance + scenario.getNetwork().getLinks().get(linkId).getLength(); + } + if (route.getEndLinkId() + != route + .getStartLinkId()) { // Do not calculate any distance, if start and endpoint are + // identical + distance = + distance + scenario.getNetwork().getLinks().get(route.getEndLinkId()).getLength(); + } + + // travel time (exp.) + time = time + leg.getExpectedTransportTime(); + } + } + score = + score + + scheduledTour.getVehicle().getType().getCostInformation().getCostsPerMeter() + * distance; + score = + score + + scheduledTour.getVehicle().getType().getCostInformation().getCostsPerSecond() + * time; + } + return (-score); // negative, because we are looking at "costs" instead of "utility" + } + + private CarrierService convertToCarrierService(LspShipment lspShipment) { + Id serviceId = + Id.create(lspShipment.getId().toString(), CarrierService.class); + CarrierService.Builder builder = + CarrierService.Builder.newInstance(serviceId, resource.getEndLinkId()); + builder.setCapacityDemand(lspShipment.getSize()); + builder.setServiceDuration(lspShipment.getDeliveryServiceTime()); + return builder.build(); + } + + @Override + protected void updateShipments() { + for (LspShipment LspShipment : lspShipmentsToSchedule) { + for (ScheduledTour scheduledTour : carrier.getSelectedPlan().getScheduledTours()) { + Tour tour = scheduledTour.getTour(); + for (TourElement element : tour.getTourElements()) { + if (element instanceof Tour.ServiceActivity serviceActivity) { + LSPShipmentCarrierServicePair carrierPair = + new LSPShipmentCarrierServicePair( + LspShipment, serviceActivity.getService()); + for (LSPShipmentCarrierServicePair pair : pairs) { + if (pair.lspShipment == carrierPair.lspShipment + && pair.carrierService.getId() == carrierPair.carrierService.getId()) { + addShipmentLoadElement(LspShipment, tour); + addShipmentTransportElement(LspShipment, tour, serviceActivity); + addShipmentUnloadElement(LspShipment, tour); + addMainTourRunStartEventHandler(pair.carrierService, LspShipment, resource, tour); + addMainRunTourEndEventHandler(pair.carrierService, LspShipment, resource, tour); + } + } + } + } + } + } + } + + private void addShipmentLoadElement(LspShipment lspShipment, Tour tour) { + LspShipmentUtils.ScheduledShipmentLoadBuilder builder = + LspShipmentUtils.ScheduledShipmentLoadBuilder.newInstance(); + builder.setResourceId(resource.getId()); + for (LogisticChainElement element : resource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipment)) { + builder.setLogisticChainElement(element); + } + } + int startIndex = tour.getTourElements().indexOf(tour.getTourElements().indexOf(tour.getStart())); + Leg legAfterStart = (Leg) tour.getTourElements().get(startIndex + 1); + double startTimeOfTransport = legAfterStart.getExpectedDepartureTime(); + double cumulatedLoadingTime = 0; + for (TourElement element : tour.getTourElements()) { + if (element instanceof Tour.ServiceActivity activity) { + cumulatedLoadingTime = cumulatedLoadingTime + activity.getDuration(); + } + } + builder.setStartTime(startTimeOfTransport - cumulatedLoadingTime); + builder.setEndTime(startTimeOfTransport); + + LspShipmentPlanElement load = builder.build(); + String idString = + load.getResourceId() + + String.valueOf(load.getLogisticChainElement().getId()) + + load.getElementType(); + Id id = Id.create(idString, LspShipmentPlanElement.class); + LspShipmentUtils.getOrCreateShipmentPlan(super.lspPlan, lspShipment.getId()) + .addPlanElement(id, load); + } + + private void addShipmentTransportElement(LspShipment lspShipment, Tour tour, Tour.ServiceActivity serviceActivity) { + LspShipmentUtils.ScheduledShipmentTransportBuilder builder = + LspShipmentUtils.ScheduledShipmentTransportBuilder.newInstance(); + builder.setResourceId(resource.getId()); + for (LogisticChainElement element : resource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipment)) { + builder.setLogisticChainElement(element); + } + } + int startIndex = tour.getTourElements().indexOf(tour.getTourElements().indexOf(tour.getStart())); + Leg legAfterStart = (Leg) tour.getTourElements().get(startIndex + 1); + double startTimeOfTransport = legAfterStart.getExpectedDepartureTime(); + builder.setStartTime(startTimeOfTransport); + builder.setEndTime(legAfterStart.getExpectedTransportTime() + startTimeOfTransport); + builder.setCarrierId(carrier.getId()); + builder.setFromLinkId(tour.getStartLinkId()); + builder.setToLinkId(tour.getEndLinkId()); + builder.setCarrierService(serviceActivity.getService()); + LspShipmentPlanElement transport = builder.build(); + String idString = + transport.getResourceId() + + String.valueOf(transport.getLogisticChainElement().getId()) + + transport.getElementType(); + Id id = Id.create(idString, LspShipmentPlanElement.class); + LspShipmentUtils.getOrCreateShipmentPlan(super.lspPlan, lspShipment.getId()) + .addPlanElement(id, transport); + } + + private void addShipmentUnloadElement(LspShipment lspShipment, Tour tour) { + LspShipmentUtils.ScheduledShipmentUnloadBuilder builder = + LspShipmentUtils.ScheduledShipmentUnloadBuilder.newInstance(); + builder.setResourceId(resource.getId()); + for (LogisticChainElement element : resource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipment)) { + builder.setLogisticsChainElement(element); + } + } + double cumulatedLoadingTime = 0; + for (TourElement element : tour.getTourElements()) { + if (element instanceof Tour.ServiceActivity activity) { + cumulatedLoadingTime = cumulatedLoadingTime + activity.getDuration(); + } + } + int startIndex = tour.getTourElements().indexOf(tour.getTourElements().indexOf(tour.getStart())); + Leg legAfterStart = (Leg) tour.getTourElements().get(startIndex + 1); + builder.setStartTime( + legAfterStart.getExpectedDepartureTime() + legAfterStart.getExpectedTransportTime()); + builder.setEndTime( + legAfterStart.getExpectedDepartureTime() + + legAfterStart.getExpectedTransportTime() + + cumulatedLoadingTime); + + LspShipmentPlanElement unload = builder.build(); + String idString = + unload.getResourceId() + + String.valueOf(unload.getLogisticChainElement().getId()) + + unload.getElementType(); + Id id = Id.create(idString, LspShipmentPlanElement.class); + LspShipmentUtils.getOrCreateShipmentPlan(super.lspPlan, lspShipment.getId()) + .addPlanElement(id, unload); + } + + private void addMainTourRunStartEventHandler( + CarrierService carrierService, + LspShipment lspShipment, + LSPCarrierResource resource, + Tour tour) { + + for (LogisticChainElement element : this.resource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipment)) { + LSPTourStartEventHandler handler = + new LSPTourStartEventHandler(lspShipment, carrierService, element, resource, tour, null); + lspShipment.addSimulationTracker(handler); + break; + } + } + } + + private void addMainRunTourEndEventHandler( + CarrierService carrierService, + LspShipment lspShipment, + LSPCarrierResource resource, + Tour tour) { + for (LogisticChainElement element : this.resource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipment)) { + LSPTourEndEventHandler handler = + new LSPTourEndEventHandler(lspShipment, carrierService, element, resource, tour); + lspShipment.addSimulationTracker(handler); + break; + } + } + } + + private record LSPShipmentCarrierServicePair(LspShipment lspShipment, CarrierService carrierService) {} +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/ResourceImplementationUtils.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/ResourceImplementationUtils.java new file mode 100644 index 00000000000..7e361725627 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/ResourceImplementationUtils.java @@ -0,0 +1,498 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.util.*; +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.Scenario; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.CarrierVehicle; +import org.matsim.freight.logistics.LSP; +import org.matsim.freight.logistics.LSPPlan; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LSPResourceScheduler; +import org.matsim.freight.logistics.LogisticChainElement; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.VehicleType; + +@SuppressWarnings("ClassEscapesDefinedScope") +public class ResourceImplementationUtils { + + private static final Logger log = LogManager.getLogger(ResourceImplementationUtils.class); + private static final String CARRIER_TYPE_ATTR = "carrierType"; + + public static SimpleForwardLogisticChainScheduler + createDefaultSimpleForwardLogisticChainScheduler(List resources) { + return new SimpleForwardLogisticChainScheduler(resources); + } + + public static SingleLogisticChainShipmentAssigner createSingleLogisticChainShipmentAssigner() { + return new SingleLogisticChainShipmentAssigner(); + } + + /** + * Collects all the vehicleTyps from the different Vehicle of the carrier. This is needed since we + * do not use carrier.getCarrierCapabilities().getVehicleTypes() any more as second field to safe + * vehicleTypes ... TODO: Maybe move to CarriersUtils in MATSim-libs / freight contrib. + * + *

KMT/Jul22 + * + * @param carrier the carrier + * @return Collection of VehicleTypes + */ + public static Collection getVehicleTypeCollection(Carrier carrier) { + Set vehicleTypeCollection = new HashSet<>(); + for (CarrierVehicle carrierVehicle : + carrier.getCarrierCapabilities().getCarrierVehicles().values()) { + vehicleTypeCollection.add(carrierVehicle.getType()); + } + return vehicleTypeCollection; + } + + public static void printShipmentsOfLSP(String outputDir, LSP lsp) { + System.out.println("Writing out shipments of LSP"); + try (BufferedWriter writer = + IOUtils.getBufferedWriter(outputDir + "/" + lsp.getId().toString() + "_shipments.tsv")) { + final String str0 = "LSP: " + lsp.getId(); + System.out.println(str0); + writer.write(str0 + "\n"); + for (LspShipment lspShipment : lsp.getLspShipments()) { + final String str1 = "Shipment: " + lspShipment; + System.out.println(str1); + writer.write(str1 + "\n"); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void printResults_shipmentPlan(String outputDir, LSP lsp) { + System.out.println("Writing out shipmentPlan for LSP"); + try (BufferedWriter writer = + IOUtils.getBufferedWriter(outputDir + "/" + lsp.getId().toString() + "_schedules.tsv")) { + final String str0 = "LSP: " + lsp.getId(); + System.out.println(str0); + writer.write(str0 + "\n"); + for (LspShipment shipment : lsp.getLspShipments()) { + ArrayList elementList = + new ArrayList<>( + LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()) + .getPlanElements() + .values()); + elementList.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + writeShipmentWithPlanElements(writer, shipment, elementList); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + private static void writeShipmentWithPlanElements( + BufferedWriter writer, LspShipment lspShipment, ArrayList elementList) + throws IOException { + final String str1 = "Shipment: " + lspShipment; + System.out.println(str1); + writer.write(str1 + "\n"); + for (LspShipmentPlanElement element : elementList) { + final String str2 = + element.getLogisticChainElement().getId() + + "\t\t" + + element.getResourceId() + + "\t\t" + + element.getElementType() + + "\t\t" + + element.getStartTime() + + "\t\t" + + element.getEndTime(); + System.out.println(str2); + writer.write(str2 + "\n"); + } + System.out.println(); + writer.write("\n"); + } + + /** + * Prints out the log of the shipment - this is not the shipment's plan Maybe the log will get + * removed soon. kmt sep/oct'22 + * + * @param outputDir path, defining the location for the results + * @param lsp the LSP, for which the results should be written out. + */ + public static void printResults_shipmentLog(String outputDir, LSP lsp) { + System.out.println("Writing out shipmentLog for LSP"); + try (BufferedWriter writer = + IOUtils.getBufferedWriter(outputDir + "/" + lsp.getId().toString() + "_shipmentLogs.tsv")) { + final String str0 = "LSP: " + lsp.getId(); + System.out.println(str0); + writer.write(str0 + "\n"); + for (LspShipment lspShipment : lsp.getLspShipments()) { + ArrayList elementList = + new ArrayList<>(lspShipment.getShipmentLog().getPlanElements().values()); + elementList.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + writeShipmentWithPlanElements(writer, lspShipment, elementList); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void printScores(String outputDir, LSP lsp) { + System.out.println("Writing out scores for LSP"); + try (BufferedWriter writer = + IOUtils.getBufferedWriter(outputDir + "/" + lsp.getId().toString() + "_scores.tsv")) { + final String str0 = "LSP: " + lsp.getId(); + System.out.println(str0); + writer.write(str0 + "\n"); + final String str1 = + "The LSP `` " + + lsp.getId() + + " ´´ has the following number of plans: " + + lsp.getPlans().size() + + "\n The scores are: "; + System.out.println(str1); + writer.write(str1 + "\n"); + for (LSPPlan plan : lsp.getPlans()) { + final String str2 = "Score: " + plan.getScore().toString(); + System.out.println(str2); + writer.write(str2 + "\n"); + } + final String str3 = "The selected plan has the score: " + lsp.getSelectedPlan().getScore(); + System.out.println(str3); + writer.write(str3 + "\n"); + System.out.println("###"); + writer.write("### \n"); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static CARRIER_TYPE getCarrierType(Carrier carrier) { + if (carrier.getAttributes().getAttribute(CARRIER_TYPE_ATTR) + instanceof CARRIER_TYPE carrierType) { + return carrierType; + } else { + String result = (String) carrier.getAttributes().getAttribute(CARRIER_TYPE_ATTR); + if (result == null) { + log.warn("Requested attribute " + CARRIER_TYPE_ATTR + " does not exists. Will return {}", CARRIER_TYPE.undefined); + return CARRIER_TYPE.undefined; + } else { + return CARRIER_TYPE.valueOf(result); + } + } + } + + public static void setCarrierType(Carrier carrier, CARRIER_TYPE carrierType) { + carrier.getAttributes().putAttribute(CARRIER_TYPE_ATTR, carrierType); + } + + /** + * Utils method to create a DistributionCarrierScheduler + * TODO: In the future, the scheduler should get the scenario via injection. This here is only a dirty workaround. KMT'Aug'24 + * + * @param scenario the scenario + */ + public static DistributionCarrierScheduler createDefaultDistributionCarrierScheduler(Scenario scenario) { + return new DistributionCarrierScheduler(scenario); + } + + /** + * Utils method to create a CollectionCarrierScheduler + * TODO: In the future, the scheduler should get the scenario via injection. This here is only a dirty workaround. KMT'Aug'24 + * + * @param scenario the scenario + */ + public static CollectionCarrierScheduler createDefaultCollectionCarrierScheduler(Scenario scenario) { + return new CollectionCarrierScheduler(scenario); + } + + /** + * Utils method to create a MainRunCarrierScheduler + * TODO: In the future, the scheduler should get the scenario via injection. This here is only a dirty workaround. KMT'Aug'24 + * + * @param scenario the scenario + */ + public static MainRunCarrierScheduler createDefaultMainRunCarrierScheduler(Scenario scenario) { + return new MainRunCarrierScheduler(scenario); + } + + public enum VehicleReturn { + returnToFromLink, + endAtToLink + } + + public enum CARRIER_TYPE { + collectionCarrier, + mainRunCarrier, + distributionCarrier, + undefined + } + + @SuppressWarnings("ClassEscapesDefinedScope") + public static class DistributionCarrierResourceBuilder { + + final Id id; + final ArrayList clientElements; + final Carrier carrier; + Id locationLinkId; + DistributionCarrierScheduler distributionHandler; + + private DistributionCarrierResourceBuilder(Carrier carrier) { + this.id = Id.create(carrier.getId().toString(), LSPResource.class); + setCarrierType(carrier, CARRIER_TYPE.distributionCarrier); + this.carrier = carrier; + this.clientElements = new ArrayList<>(); + } + + public static DistributionCarrierResourceBuilder newInstance(Carrier carrier) { + return new DistributionCarrierResourceBuilder(carrier); + } + + public DistributionCarrierResourceBuilder setLocationLinkId(Id locationLinkId) { + this.locationLinkId = locationLinkId; + return this; + } + + public DistributionCarrierResourceBuilder setDistributionScheduler( + DistributionCarrierScheduler distributionCarrierScheduler) { + this.distributionHandler = distributionCarrierScheduler; + return this; + } + + public DistributionCarrierResource build() { + return new DistributionCarrierResource(this); + } + } + + @SuppressWarnings("ClassEscapesDefinedScope") + public static class CollectionCarrierResourceBuilder { + + final Id id; + final ArrayList clientElements; + final Carrier carrier; + Id locationLinkId; + CollectionCarrierScheduler collectionScheduler; + + private CollectionCarrierResourceBuilder(Carrier carrier) { + this.id = Id.create(carrier.getId().toString(), LSPResource.class); + setCarrierType(carrier, CARRIER_TYPE.collectionCarrier); + this.carrier = carrier; + this.clientElements = new ArrayList<>(); + } + + public static CollectionCarrierResourceBuilder newInstance(Carrier carrier) { + return new CollectionCarrierResourceBuilder(carrier); + } + + public CollectionCarrierResourceBuilder setLocationLinkId(Id locationLinkId) { + this.locationLinkId = locationLinkId; + return this; + } + + public CollectionCarrierResourceBuilder setCollectionScheduler( + CollectionCarrierScheduler collectionCarrierScheduler) { + this.collectionScheduler = collectionCarrierScheduler; + return this; + } + + public CollectionCarrierResource build() { + return new CollectionCarrierResource(this); + } + } + + @SuppressWarnings("ClassEscapesDefinedScope") + public static class MainRunCarrierResourceBuilder { + + private final Id id; + private final ArrayList clientElements; + private Carrier carrier; + private Id fromLinkId; + private Id toLinkId; + private MainRunCarrierScheduler mainRunScheduler; + private VehicleReturn vehicleReturn; + + private MainRunCarrierResourceBuilder(Carrier carrier) { + this.id = Id.create(carrier.getId().toString(), LSPResource.class); + setCarrierType(carrier, CARRIER_TYPE.mainRunCarrier); + this.carrier = carrier; + this.clientElements = new ArrayList<>(); + } + + public static MainRunCarrierResourceBuilder newInstance(Carrier carrier) { + return new MainRunCarrierResourceBuilder(carrier); + } + + public MainRunCarrierResourceBuilder setMainRunCarrierScheduler( + MainRunCarrierScheduler mainRunScheduler) { + this.mainRunScheduler = mainRunScheduler; + return this; + } + + public MainRunCarrierResource build() { + return new MainRunCarrierResource(this); + } + + Id getId() { + return id; + } + + Carrier getCarrier() { + return carrier; + } + + public MainRunCarrierResourceBuilder setCarrier(Carrier carrier) { + setCarrierType(carrier, CARRIER_TYPE.mainRunCarrier); + this.carrier = carrier; + return this; + } + + Id getFromLinkId() { + return fromLinkId; + } + + // --- Getter --- + + public MainRunCarrierResourceBuilder setFromLinkId(Id fromLinkId) { + this.fromLinkId = fromLinkId; + return this; + } + + Id getToLinkId() { + return toLinkId; + } + + public MainRunCarrierResourceBuilder setToLinkId(Id toLinkId) { + this.toLinkId = toLinkId; + return this; + } + + ArrayList getClientElements() { + return clientElements; + } + + MainRunCarrierScheduler getMainRunScheduler() { + return mainRunScheduler; + } + + VehicleReturn getVehicleReturn() { + return vehicleReturn; + } + + public MainRunCarrierResourceBuilder setVehicleReturn(VehicleReturn vehicleReturn) { + this.vehicleReturn = vehicleReturn; + return this; + } + } + + @SuppressWarnings("ClassEscapesDefinedScope") + public static class TranshipmentHubSchedulerBuilder { + private double capacityNeedLinear; + private double capacityNeedFixed; + + private TranshipmentHubSchedulerBuilder() {} + + public static TranshipmentHubSchedulerBuilder newInstance() { + return new TranshipmentHubSchedulerBuilder(); + } + + public TransshipmentHubScheduler build() { + return new TransshipmentHubScheduler(this); + } + + double getCapacityNeedLinear() { + return capacityNeedLinear; + } + + public TranshipmentHubSchedulerBuilder setCapacityNeedLinear(double capacityNeedLinear) { + this.capacityNeedLinear = capacityNeedLinear; + return this; + } + + // --- Getters --- + + double getCapacityNeedFixed() { + return capacityNeedFixed; + } + + public TranshipmentHubSchedulerBuilder setCapacityNeedFixed(double capacityNeedFixed) { + this.capacityNeedFixed = capacityNeedFixed; + return this; + } + } + + public static final class TransshipmentHubBuilder { + + private final Id id; + private final Id locationLinkId; + private final ArrayList clientElements; + private final Scenario scenario; + private TransshipmentHubScheduler transshipmentHubScheduler; + + private TransshipmentHubBuilder( + Id id, Id locationLinkId, Scenario scenario) { + this.id = id; + this.clientElements = new ArrayList<>(); + this.locationLinkId = locationLinkId; + this.scenario = scenario; + } + + public static TransshipmentHubBuilder newInstance( + Id id, Id locationLinkId, Scenario scenario) { + return new TransshipmentHubBuilder(id, locationLinkId, scenario); + } + + public TransshipmentHubResource build() { + return new TransshipmentHubResource(this, scenario); + } + + Id getId() { + return id; + } + + // --- Getters --- + + Id getLocationLinkId() { + return locationLinkId; + } + + TransshipmentHubScheduler getTransshipmentHubScheduler() { + return transshipmentHubScheduler; + } + + public TransshipmentHubBuilder setTransshipmentHubScheduler( + LSPResourceScheduler TranshipmentHubScheduler) { + this.transshipmentHubScheduler = (TransshipmentHubScheduler) TranshipmentHubScheduler; + return this; + } + + ArrayList getClientElements() { + return clientElements; + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/SimpleForwardLogisticChainScheduler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/SimpleForwardLogisticChainScheduler.java new file mode 100644 index 00000000000..f046b80c846 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/SimpleForwardLogisticChainScheduler.java @@ -0,0 +1,102 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import java.util.List; +import org.matsim.api.core.v01.Id; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * In the class SimpleForwardSolutionScheduler two tasks are performed: + * + *

1.) the {@link LspShipment}s that were assigned to the suitable {@link LogisticChain} by the + * {@link InitialShipmentAssigner} in a previous step are handed over to the first {@link + * LogisticChainElement}. + * + *

2.) all {@link LSPResource}s that were handed over to the SimpleForwardSolutionScheduler + * exogenously, are now scheduled sequentially in an order that was also specified exogenously. This + * order ensures that each {@link LogisticChain} is traversed from the first to the last {@link + * LogisticChainElement}. During this procedure, the concerned {@link LspShipment}s are taken from + * the collection of incoming shipments, handled by the {@link LSPResource} in charge and then added + * to the collection of outgoing shipments of the client {@link LogisticChainElement}. + * + *

The SimpleForwardSolutionScheduler needs the sequence in which the Resources are scheduled as + * exogenous input. + * + *

The expression "`forward"' refers to the fact that in both cases the scheduling process starts + * at the first element of each {@link LogisticChain} and from the earliest possible point of time. + */ +/*package-private*/ class SimpleForwardLogisticChainScheduler implements LogisticChainScheduler { + + private final List resources; + private LSP lsp; + private int bufferTime; + + SimpleForwardLogisticChainScheduler(List resources) { + this.resources = resources; + } + + @Override + public void scheduleLogisticChain() { + insertShipmentsAtBeginning(); + for (LSPResource resource : resources) { + for (LSPResource lspResource : lsp.getResources()) { + if (lspResource == resource) { + lspResource.schedule(bufferTime, lsp.getSelectedPlan()); + } + } + } + } + + @Override + public void setEmbeddingContainer(LSP lsp) { + this.lsp = lsp; + } + + private void insertShipmentsAtBeginning() { + for (LogisticChain solution : lsp.getSelectedPlan().getLogisticChains()) { + LogisticChainElement firstElement = getFirstElement(solution); + assert firstElement != null; + for (Id lspShipmentId : solution.getLspShipmentIds()) { + var shipment = LSPUtils.findLspShipment(lsp, lspShipmentId); + assert shipment != null; + firstElement + .getIncomingShipments() + .addShipment(shipment.getPickupTimeWindow().getStart(), shipment); + } + } + } + + private LogisticChainElement getFirstElement(LogisticChain solution) { + for (LogisticChainElement element : solution.getLogisticChainElements()) { + if (element.getPreviousElement() == null) { + return element; + } + } + return null; + } + + @Override + public void setBufferTime(int bufferTime) { + this.bufferTime = bufferTime; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/SingleLogisticChainShipmentAssigner.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/SingleLogisticChainShipmentAssigner.java new file mode 100644 index 00000000000..a377be24ca3 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/SingleLogisticChainShipmentAssigner.java @@ -0,0 +1,48 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import org.matsim.core.gbl.Gbl; +import org.matsim.freight.logistics.InitialShipmentAssigner; +import org.matsim.freight.logistics.LSPPlan; +import org.matsim.freight.logistics.LogisticChain; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * Ganz einfacher {@link InitialShipmentAssigner}: Voraussetzung: Der {@link LSPPlan} hat genau 1 {@link + * LogisticChain}. + * + *

Dann wird das {@link LspShipment} diesem zugeordnet. + * + *

(Falls die Voraussetzung "exakt 1 LogisticChain pro Plan" nicht erfüllt ist, kommt eine + * RuntimeException) + */ +class SingleLogisticChainShipmentAssigner implements InitialShipmentAssigner { + + SingleLogisticChainShipmentAssigner() {} + + @Override + public void assignToPlan(LSPPlan lspPlan, LspShipment lspShipment) { + Gbl.assertIf(lspPlan.getLogisticChains().size() == 1); + LogisticChain singleSolution = lspPlan.getLogisticChains().iterator().next(); + singleSolution.addShipmentToChain(lspShipment); + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/TransshipmentHubResource.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/TransshipmentHubResource.java new file mode 100644 index 00000000000..fd168b32b2b --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/TransshipmentHubResource.java @@ -0,0 +1,110 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import java.util.Collection; +import java.util.List; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.network.Link; +import org.matsim.freight.logistics.LSPDataObject; +import org.matsim.freight.logistics.LSPPlan; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LogisticChainElement; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; + +/** + * {@link LSPResource} bei der die geplanten Tätigkeiten NICHT am Verkehr teilnehmen. + * + *

Thus, these activities are entered directly in the Schedule of the LSPShipments that pass + * through the TranshipmentHub. + * + *

An entry is added to the schedule of the shipments that is an instance of + * ScheduledShipmentHandle. There, the name of the Resource and the client element are entered, so + * that the way that the {@link LspShipment} takes is + * specified. In addition, the planned start and end time of the handling (i.e. cross-docking) of + * the shipment is entered. In the example, cross-docking starts as soon as the considered + * LSPShipment arrives at the {@link TransshipmentHubResource} and ends after a fixed and a size + * dependent amount of time. + * + *

I (KMT, oct'22) have done this temporally public - including a "do not instantiate" + * constructor , because I need it the class for an instanceOf check for a quick scoring of hubs. + * This can be reverted, once hubs will appear in the MATSim events stream. + */ +public class TransshipmentHubResource extends LSPDataObject implements LSPResource { + + private final Id locationLinkId; + private final TransshipmentHubScheduler transshipmentHubScheduler; + private final List clientElements; + + private + TransshipmentHubResource() { // Do not instantiate. (removable once this class is package-private + // again) KMT oct'22 + super(null); + this.locationLinkId = null; + this.transshipmentHubScheduler = null; + this.clientElements = null; + throw new RuntimeException( + "This should have never been called, because it is not planed for getting instantiated."); + } + + TransshipmentHubResource( + TransshipmentHubBuilder builder, Scenario scenario) { + super(builder.getId()); + this.locationLinkId = builder.getLocationLinkId(); + this.transshipmentHubScheduler = builder.getTransshipmentHubScheduler(); + transshipmentHubScheduler.setTranshipmentHub(this); + TransshipmentHubTourEndEventHandler eventHandler = + new TransshipmentHubTourEndEventHandler(this, scenario); + transshipmentHubScheduler.setTransshipmentHubTourEndEventHandler(eventHandler); + this.clientElements = builder.getClientElements(); + } + + @Override + public Id getStartLinkId() { + return locationLinkId; + } + + @Override + public Id getEndLinkId() { + return locationLinkId; + } + + @Override + public Collection getClientElements() { + return clientElements; + } + + @Override + public void schedule(int bufferTime, LSPPlan lspPlan) { + transshipmentHubScheduler.scheduleShipments(lspPlan, this, bufferTime); + } + + public double getCapacityNeedFixed() { + return transshipmentHubScheduler.getCapacityNeedFixed(); + } + + public double getCapacityNeedLinear() { + return transshipmentHubScheduler.getCapacityNeedLinear(); + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/TransshipmentHubScheduler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/TransshipmentHubScheduler.java new file mode 100644 index 00000000000..6c6081c81bf --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/TransshipmentHubScheduler.java @@ -0,0 +1,123 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import java.util.ArrayList; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Id; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LSPResourceScheduler; +import org.matsim.freight.logistics.LogisticChainElement; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlan; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; + +/*package-private*/ class TransshipmentHubScheduler extends LSPResourceScheduler { + + final Logger log = LogManager.getLogger(TransshipmentHubScheduler.class); + private final double capacityNeedLinear; + private final double capacityNeedFixed; + private TransshipmentHubResource transshipmentHubResource; + private TransshipmentHubTourEndEventHandler eventHandler; + + TransshipmentHubScheduler(TranshipmentHubSchedulerBuilder builder) { + this.lspShipmentsToSchedule = new ArrayList<>(); + this.capacityNeedLinear = builder.getCapacityNeedLinear(); + this.capacityNeedFixed = builder.getCapacityNeedFixed(); + } + + @Override + protected void initializeValues(LSPResource resource) { + this.transshipmentHubResource = (TransshipmentHubResource) resource; + } + + @Override + protected void scheduleResource() { + for (LspShipment lspShipmentToBeAssigned : lspShipmentsToSchedule) { + updateSchedule(lspShipmentToBeAssigned); + } + } + + @Override + @Deprecated + protected void updateShipments() { + log.error("This method is not implemented. Nothing will happen here. "); + } + + private void updateSchedule(LspShipment lspShipment) { + addShipmentHandleElement(lspShipment); + addShipmentToEventHandler(lspShipment); + } + + private void addShipmentHandleElement(LspShipment lspShipment) { + LspShipmentUtils.ScheduledShipmentHandleBuilder builder = + LspShipmentUtils.ScheduledShipmentHandleBuilder.newInstance(); + builder.setStartTime(LspShipmentUtils.getTimeOfLspShipment(lspShipment)); + builder.setEndTime(LspShipmentUtils.getTimeOfLspShipment(lspShipment) + capacityNeedFixed + capacityNeedLinear * lspShipment.getSize()); + builder.setResourceId(transshipmentHubResource.getId()); + for (LogisticChainElement element : transshipmentHubResource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipment)) { + builder.setLogisticsChainElement(element); + } + } + LspShipmentPlanElement handle = builder.build(); + + String idString = + handle.getResourceId() + + String.valueOf(handle.getLogisticChainElement().getId()) + + handle.getElementType(); + Id id = Id.create(idString, LspShipmentPlanElement.class); + LspShipmentUtils.getOrCreateShipmentPlan(super.lspPlan, lspShipment.getId()) + .addPlanElement(id, handle); + } + + private void addShipmentToEventHandler(LspShipment lspShipment) { + for (LogisticChainElement element : transshipmentHubResource.getClientElements()) { + if (element.getIncomingShipments().getLspShipmentsWTime().contains(lspShipment)) { + LspShipmentPlan lspShipmentPlan = + LspShipmentUtils.getOrCreateShipmentPlan(lspPlan, lspShipment.getId()); + eventHandler.addShipment(lspShipment, element, lspShipmentPlan); + break; + } + } + } + + public double getCapacityNeedLinear() { + return capacityNeedLinear; + } + + public double getCapacityNeedFixed() { + return capacityNeedFixed; + } + + public void setTranshipmentHub(TransshipmentHubResource transshipmentHubResource) { + this.transshipmentHubResource = transshipmentHubResource; + } + + public void setTransshipmentHubTourEndEventHandler( + TransshipmentHubTourEndEventHandler eventHandler) { + this.eventHandler = eventHandler; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/TransshipmentHubTourEndEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/TransshipmentHubTourEndEventHandler.java new file mode 100644 index 00000000000..bd476a54954 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/resourceImplementations/TransshipmentHubTourEndEventHandler.java @@ -0,0 +1,278 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.api.experimental.events.EventsManager; +import org.matsim.core.controler.events.AfterMobsimEvent; +import org.matsim.core.controler.listener.AfterMobsimListener; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.Tour.ServiceActivity; +import org.matsim.freight.carriers.Tour.TourElement; +import org.matsim.freight.carriers.events.CarrierTourEndEvent; +import org.matsim.freight.carriers.events.eventhandler.CarrierTourEndEventHandler; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LSPSimulationTracker; +import org.matsim.freight.logistics.LogisticChainElement; +import org.matsim.freight.logistics.events.HandlingInHubStartsEvent; +import org.matsim.freight.logistics.shipment.*; + +/*package-private*/ class TransshipmentHubTourEndEventHandler + implements AfterMobsimListener, LSPSimulationTracker, CarrierTourEndEventHandler { + + //This class *should* also get merged into {@link LSPTourEndEventHandler}. + //Currently, this is not possible very easily, because of missing injection (of the scenario.) + //KMT, KN (Jan'24) + + private final Scenario scenario; + private final HashMap servicesWaitedFor; + private final TransshipmentHubResource transshipmentHubResource; + private final Id resourceId; + private final Id linkId; + private EventsManager eventsManager; + + /** + * This is a TourEndEvent-Handler, doing some stuff regarding the {@link + * TransshipmentHubResource}. + * + * @param transshipmentHubResource hub + * @param scenario The scenario. Is used to get the Carrier(s). + */ + TransshipmentHubTourEndEventHandler( + TransshipmentHubResource transshipmentHubResource, Scenario scenario) { + this.transshipmentHubResource = transshipmentHubResource; + this.linkId = transshipmentHubResource.getEndLinkId(); + this.resourceId = transshipmentHubResource.getId(); + this.scenario = scenario; + this.servicesWaitedFor = new HashMap<>(); + this.transshipmentHubResource.addSimulationTracker(this); + } + + @Override + public void setEmbeddingContainer(LSPResource pointer) {} + + @Override + public void setEventsManager(EventsManager eventsManager) { + this.eventsManager = eventsManager; + } + + @Override + public void notifyAfterMobsim(AfterMobsimEvent event) { + servicesWaitedFor + .clear(); // cleanup after Mobsim ends (instead of doing it in reset() = before Mobsim + // starts.) kmt oct'22 + } + + @Override + public void reset(int iteration) { + // not implemented; cleanup is done after Mobsim ends, because the internal state is (re)set + // before Mobsim starts. + // --> cleaning up here is too late. + // This is maybe not ideal, but works; kmt oct'22 + } + + public void addShipment( + LspShipment lspShipment, LogisticChainElement logisticChainElement, LspShipmentPlan lspShipmentPlan) { + TransshipmentHubEventHandlerPair pair = + new TransshipmentHubEventHandlerPair(lspShipment, logisticChainElement); + + for (LspShipmentPlanElement planElement : lspShipmentPlan.getPlanElements().values()) { + if (planElement instanceof LspShipmentLeg transport) { + if (transport.getLogisticChainElement().getNextElement() == logisticChainElement) { + servicesWaitedFor.put(transport.getCarrierService(), pair); + } + } + } + } + + @Override + public void handleEvent(CarrierTourEndEvent event) { + Tour tour = null; + Carrier carrier = CarriersUtils.getCarriers(scenario).getCarriers().get(event.getCarrierId()); + Collection scheduledTours = carrier.getSelectedPlan().getScheduledTours(); + for (ScheduledTour scheduledTour : scheduledTours) { + if (scheduledTour.getTour().getId() == event.getTourId()) { + tour = scheduledTour.getTour(); + break; + } + } + if ((event.getLinkId() == this.linkId)) { + assert tour != null; + + if (ResourceImplementationUtils.getCarrierType(carrier) + == ResourceImplementationUtils.CARRIER_TYPE.mainRunCarrier) { + if (allShipmentsOfTourEndInOnePoint(tour)) { + for (TourElement tourElement : tour.getTourElements()) { + if (tourElement instanceof ServiceActivity serviceActivity) { + if (serviceActivity.getLocation() == transshipmentHubResource.getStartLinkId() + && allServicesAreInOnePoint(tour) + && (tour.getStartLinkId() != transshipmentHubResource.getStartLinkId())) { + + final CarrierService carrierService = serviceActivity.getService(); + final LspShipment lspShipment = servicesWaitedFor.get(carrierService).lspShipment; + // NOTE: Do NOT add time vor unloading all goods, because they are included for the + // main run (Service activity at end of tour) + final double expHandlingDuration = + transshipmentHubResource.getCapacityNeedFixed() + + (transshipmentHubResource.getCapacityNeedLinear() + * lspShipment.getSize()); + final double startTime = event.getTime(); + final double endTime = startTime + expHandlingDuration; + + logHandlingInHub(serviceActivity.getService(), startTime, endTime); + throwHandlingEvent(event, lspShipment, expHandlingDuration); + } + } + } + } + } else if ((ResourceImplementationUtils.getCarrierType(carrier) + == ResourceImplementationUtils.CARRIER_TYPE.collectionCarrier)) { + for (TourElement tourElement : tour.getTourElements()) { + if (tourElement instanceof ServiceActivity serviceActivity) { + if (tour.getEndLinkId() == transshipmentHubResource.getStartLinkId()) { + + final CarrierService carrierService = serviceActivity.getService(); + final LspShipment lspShipment = servicesWaitedFor.get(carrierService).lspShipment; + + // TODO: Adding this here to be more in line with the schedule and have the shipment + // log fitting to it. + // This does NOT mean, that it really makes sense, because we decided for some + // reasons, that the handlingEvent start once the vehicle has arrived. + // It may change again, once we have unloading events available. + final double expUnloadingTime = getTotalUnloadingTime(tour); + final double expHandlingDuration = + transshipmentHubResource.getCapacityNeedFixed() + + (transshipmentHubResource.getCapacityNeedLinear() * lspShipment.getSize()); + final double startTime = event.getTime() + expUnloadingTime; + final double endTime = startTime + expHandlingDuration; + + logHandlingInHub(carrierService, startTime, endTime); + throwHandlingEvent(event, lspShipment, expHandlingDuration); + } + } + } + } + } + } + + private boolean allShipmentsOfTourEndInOnePoint(Tour tour) { + boolean allShipmentsOfTourEndInOnePoint = true; + for (TourElement tourElement : tour.getTourElements()) { + if (tourElement instanceof ServiceActivity serviceActivity) { + if (!servicesWaitedFor.containsKey(serviceActivity.getService())) { + return false; + } + } + } + return allShipmentsOfTourEndInOnePoint; + } + + private double getTotalUnloadingTime(Tour tour) { + double totalTime = 0; + for (TourElement element : tour.getTourElements()) { + if (element instanceof ServiceActivity serviceActivity) { + totalTime = totalTime + serviceActivity.getDuration(); + } + } + return totalTime; + } + + private void logHandlingInHub( + CarrierService carrierService, double startTime, double endTime) { + + LspShipment lspShipment = servicesWaitedFor.get(carrierService).lspShipment; + + { // Old logging approach - will be removed at some point in time + LspShipmentPlanElement handle = + LspShipmentUtils.LoggedShipmentHandleBuilder.newInstance() + .setLinkId(linkId) + .setResourceId(resourceId) + .setStartTime(startTime) + .setEndTime(endTime) + .setLogisticsChainElement(servicesWaitedFor.get(carrierService).logisticChainElement) + .build(); + Id loadId = + Id.create( + handle.getResourceId() + + String.valueOf(handle.getLogisticChainElement().getId()) + + handle.getElementType(), + LspShipmentPlanElement.class); + if (!lspShipment.getShipmentLog().getPlanElements().containsKey(loadId)) { + lspShipment.getShipmentLog().addPlanElement(loadId, handle); + } + } + } + + private void throwHandlingEvent( + CarrierTourEndEvent event, LspShipment lspShipment, double expHandlingDuration) { + // New event-based approach + // Todo: We need to decide what we write into the exp. handling duration: See #175 for + // discussion. + // The start time, must start at the same time as the triggering event. -> keep events stream + // ordered. + eventsManager.processEvent( + new HandlingInHubStartsEvent( + event.getTime(), linkId, lspShipment.getId(), resourceId, expHandlingDuration)); + } + + private boolean allServicesAreInOnePoint(Tour tour) { + for (TourElement element : tour.getTourElements()) { + if (element instanceof ServiceActivity activity) { + if (activity.getLocation() != tour.getEndLinkId()) { + return false; + } + } + } + return true; + } + + public Map getServicesWaitedFor() { + return servicesWaitedFor; + } + + public TransshipmentHubResource getTranshipmentHub() { + return transshipmentHubResource; + } + + public Id getResourceId() { + return resourceId; + } + + public Id getLinkId() { + return linkId; + } + + public static class TransshipmentHubEventHandlerPair { + public final LspShipment lspShipment; + public final LogisticChainElement logisticChainElement; + + public TransshipmentHubEventHandlerPair(LspShipment lspShipment, LogisticChainElement element) { + this.lspShipment = lspShipment; + this.logisticChainElement = element; + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LoggedLspShipmentHandle.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LoggedLspShipmentHandle.java new file mode 100644 index 00000000000..a9970d4bc67 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LoggedLspShipmentHandle.java @@ -0,0 +1,65 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.shipment; + +import org.matsim.api.core.v01.Id; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LogisticChainElement; + +/*package*/ class LoggedLspShipmentHandle implements LspShipmentPlanElement { + + private final double startTime; + private final double endTime; + private final LogisticChainElement element; + private final Id resourceId; + + LoggedLspShipmentHandle(LspShipmentUtils.LoggedShipmentHandleBuilder builder) { + this.startTime = builder.startTime; + this.endTime = builder.endTime; + this.element = builder.element; + this.resourceId = builder.resourceId; + } + + @Override + public LogisticChainElement getLogisticChainElement() { + return element; + } + + @Override + public Id getResourceId() { + return resourceId; + } + + @Override + public String getElementType() { + return "HANDLE"; + } + + @Override + public double getStartTime() { + return startTime; + } + + @Override + public double getEndTime() { + return endTime; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LoggedLspShipmentLoad.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LoggedLspShipmentLoad.java new file mode 100644 index 00000000000..ac0941162cb --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LoggedLspShipmentLoad.java @@ -0,0 +1,65 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.shipment; + +import org.matsim.api.core.v01.Id; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LogisticChainElement; + +/*package-private*/ class LoggedLspShipmentLoad implements LspShipmentPlanElement { + + private final double startTime; + private final double endTime; + private final LogisticChainElement element; + private final Id resourceId; + + LoggedLspShipmentLoad(LspShipmentUtils.LoggedShipmentLoadBuilder builder) { + this.startTime = builder.getStartTime(); + this.endTime = builder.getEndTime(); + this.element = builder.getElement(); + this.resourceId = builder.getResourceId(); + } + + @Override + public String getElementType() { + return "LOAD"; + } + + @Override + public double getStartTime() { + return startTime; + } + + @Override + public double getEndTime() { + return endTime; + } + + @Override + public LogisticChainElement getLogisticChainElement() { + return element; + } + + @Override + public Id getResourceId() { + return resourceId; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LoggedLspShipmentTransport.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LoggedLspShipmentTransport.java new file mode 100644 index 00000000000..6ab1650ccfe --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LoggedLspShipmentTransport.java @@ -0,0 +1,97 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.shipment; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.CarrierService; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LogisticChainElement; + +final class LoggedLspShipmentTransport implements LspShipmentLeg { + + private final double startTime; + private final LogisticChainElement element; + private final Id resourceId; + private final Id fromLinkId; + private double endTime; + private Id toLinkId; + + LoggedLspShipmentTransport(LspShipmentUtils.LoggedShipmentTransportBuilder builder) { + this.startTime = builder.getStartTime(); + this.element = builder.getElement(); + this.resourceId = builder.getResourceId(); + this.fromLinkId = builder.getFromLinkId(); + this.toLinkId = builder.getToLinkId(); + } + + @Override + public LogisticChainElement getLogisticChainElement() { + return element; + } + + @Override + public Id getResourceId() { + return resourceId; + } + + @Override + public String getElementType() { + return "TRANSPORT"; + } + + @Override + public double getStartTime() { + return startTime; + } + + @Override + public double getEndTime() { + return endTime; + } + + public void setEndTime(double endTime) { + this.endTime = endTime; + } + + public Id getFromLinkId() { + return fromLinkId; + } + + @Override + public CarrierService getCarrierService() { + throw new RuntimeException("not implemented"); + } + + public Id getToLinkId() { + return toLinkId; + } + + public void setToLinkId(Id toLinkId) { + this.toLinkId = toLinkId; + } + + @Override + public Id getCarrierId() { + throw new RuntimeException("not implemented"); + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LoggedLspShipmentUnload.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LoggedLspShipmentUnload.java new file mode 100644 index 00000000000..20d88e7032e --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LoggedLspShipmentUnload.java @@ -0,0 +1,65 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.shipment; + +import org.matsim.api.core.v01.Id; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LogisticChainElement; + +class LoggedLspShipmentUnload implements LspShipmentPlanElement { + + private final double startTime; + private final double endTime; + private final LogisticChainElement element; + private final Id resourceId; + + LoggedLspShipmentUnload(LspShipmentUtils.LoggedShipmentUnloadBuilder builder) { + this.startTime = builder.startTime; + this.endTime = builder.endTime; + this.element = builder.element; + this.resourceId = builder.resourceId; + } + + @Override + public LogisticChainElement getLogisticChainElement() { + return element; + } + + @Override + public Id getResourceId() { + return resourceId; + } + + @Override + public String getElementType() { + return "UNLOAD"; + } + + @Override + public double getStartTime() { + return startTime; + } + + @Override + public double getEndTime() { + return endTime; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipment.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipment.java new file mode 100644 index 00000000000..700f969d7ab --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipment.java @@ -0,0 +1,63 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.shipment; + +import java.util.Collection; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Identifiable; +import org.matsim.api.core.v01.network.Link; +import org.matsim.freight.carriers.TimeWindow; +import org.matsim.freight.logistics.HasSimulationTrackers; +import org.matsim.utils.objectattributes.attributable.Attributable; + +/** + * This is, for example, a shipment that DHL moves from A to B. It may use multiple carriers to + * achieve that. + * + *

Questions/comments: + * + *

    + *
  • Within more modern MATSim, we would probably prefer to have from and to in coordinates, not + * link IDs. + *
+ */ +public interface LspShipment + extends Identifiable, Attributable, HasSimulationTrackers { + + Id getFrom(); // same as in CarrierShipment + + Id getTo(); // same as in CarrierShipment + + TimeWindow getPickupTimeWindow(); // same as in CarrierShipment + + TimeWindow getDeliveryTimeWindow(); // same as in CarrierShipment + + int getSize(); // same as in CarrierShipment + + double getDeliveryServiceTime(); // same as in CarrierShipment + + double getPickupServiceTime(); // same as in CarrierShipment + + LspShipmentPlan getShipmentLog(); + + Collection getRequirements(); + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentImpl.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentImpl.java new file mode 100644 index 00000000000..8ff44b2aa79 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentImpl.java @@ -0,0 +1,137 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.shipment; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.freight.carriers.TimeWindow; +import org.matsim.freight.logistics.LSPDataObject; + +class LspShipmentImpl extends LSPDataObject implements LspShipment { + + private final Id fromLinkId; + private final Id toLinkId; + private final TimeWindow startTimeWindow; + private final TimeWindow endTimeWindow; + private final int capacityDemand; + private final double deliveryServiceTime; + private final double pickupServiceTime; + // private final ShipmentPlan shipmentPlan; + @Deprecated // This will be removed in the future and replaced by using the events. KMT, Mai'23 + private final LspShipmentPlan shipmentLog; + private final List lspShipmentRequirements; + + // private Id lspId; + + LspShipmentImpl(LspShipmentUtils.LspShipmentBuilder builder) { + super(builder.id); + this.fromLinkId = builder.fromLinkId; + this.toLinkId = builder.toLinkId; + this.startTimeWindow = builder.startTimeWindow; + this.endTimeWindow = builder.endTimeWindow; + this.capacityDemand = builder.capacityDemand; + this.deliveryServiceTime = builder.deliveryServiceTime; + this.pickupServiceTime = builder.pickupServiceTime; + // this.shipmentPlan = new ShipmentPlanImpl(this.getId()); + this.shipmentLog = new LspShipmentPlanImpl(this.getId()); + this.lspShipmentRequirements = new ArrayList<>(); + this.lspShipmentRequirements.addAll(builder.lspShipmentRequirements); + } + + @Override + public Id getFrom() { + return fromLinkId; + } + + @Override + public Id getTo() { + return toLinkId; + } + + @Override + public TimeWindow getPickupTimeWindow() { + return startTimeWindow; + } + + @Override + public TimeWindow getDeliveryTimeWindow() { + return endTimeWindow; + } + + @Deprecated // This will be removed in the future and replaced by using the events. KMT, Mai'23 + @Override + public LspShipmentPlan getShipmentLog() { + return shipmentLog; + } + + @Override + public int getSize() { + return capacityDemand; + } + + @Override + public double getDeliveryServiceTime() { + return deliveryServiceTime; + } + + @Override + public Collection getRequirements() { + return lspShipmentRequirements; + } + + @Override + public double getPickupServiceTime() { + return pickupServiceTime; + } + + + + @Override + public String toString() { + return "LSPShipmentImpl{" + + "Id=" + + getId() + + "\t fromLinkId=" + + fromLinkId + + "\t toLinkId=" + + toLinkId + + "\t capacityDemand=" + + capacityDemand + + "\t startTimeWindow=" + + startTimeWindow + + "\t endTimeWindow=" + + endTimeWindow + + "\t capacityDemand=" + + capacityDemand + + "\t deliveryServiceTime=" + + deliveryServiceTime + + "\t pickupServiceTime=" + + pickupServiceTime + + + // "\t schedule=" + schedule + + // "\t log=" + log + + // "\t requirements=" + requirements + + '}'; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentLeg.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentLeg.java new file mode 100644 index 00000000000..3b5d4c00904 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentLeg.java @@ -0,0 +1,20 @@ +package org.matsim.freight.logistics.shipment; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.CarrierService; + +public interface LspShipmentLeg extends LspShipmentPlanElement { + Id getToLinkId(); + + void setToLinkId(Id endLinkId); + + Id getCarrierId(); + + Id getFromLinkId(); + + CarrierService getCarrierService(); + + void setEndTime(double time); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentPlan.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentPlan.java new file mode 100644 index 00000000000..03cb42d0dca --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentPlan.java @@ -0,0 +1,38 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.shipment; + +import java.util.Map; +import org.matsim.api.core.v01.Id; +import org.matsim.freight.logistics.HasBackpointer; + +public interface LspShipmentPlan extends HasBackpointer> { + + Id getLspShipmentId(); + + Map, LspShipmentPlanElement> getPlanElements(); + + void addPlanElement(Id id, LspShipmentPlanElement element); + + LspShipmentPlanElement getMostRecentEntry(); + + void clear(); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentPlanElement.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentPlanElement.java new file mode 100644 index 00000000000..5809ddfad28 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentPlanElement.java @@ -0,0 +1,41 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.shipment; + +import org.matsim.api.core.v01.Id; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LogisticChainElement; + +public interface LspShipmentPlanElement { + + LogisticChainElement getLogisticChainElement(); + + Id getResourceId(); + + // yyyy "type" feels like this makes it a tagged class. These should be avoided (Effective Java + // 2018, Item 23). It is, however, probably not + // used as a type, but rather as a description. Rename? + String getElementType(); + + double getStartTime(); + + double getEndTime(); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentPlanImpl.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentPlanImpl.java new file mode 100644 index 00000000000..89f1abcd52f --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentPlanImpl.java @@ -0,0 +1,98 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.shipment; + +import java.util.*; +import org.matsim.api.core.v01.Id; + +/*package-private*/ class LspShipmentPlanImpl implements LspShipmentPlan { + + private final Id lspShipmentId; + private final LinkedHashMap, LspShipmentPlanElement> planElements; + + LspShipmentPlanImpl(Id lspShipmentId) { + this.lspShipmentId = lspShipmentId; + this.planElements = new LinkedHashMap<>(); + } + + // TODO: Ist kein embedding container! + @Override + public void setEmbeddingContainer(Id pointer) { + throw new RuntimeException("not implemented"); + } + + @Override + public Id getLspShipmentId() { + return lspShipmentId; + } + + @Override + public void addPlanElement(Id id, LspShipmentPlanElement element) { + planElements.put(id, element); + } + + @Override + public Map, LspShipmentPlanElement> getPlanElements() { + return Collections.unmodifiableMap(planElements); + } + + @Override + public LspShipmentPlanElement getMostRecentEntry() { + + // there is no method to remove entries. in consequence, the only way to change the result of + // this method is to "add" additional material into the plan. Possibly, + // the method here is indeed there to find the plan element that was added most recently, to + // figure out how the next one can be added. However, this then + // should be sorted by sequence of addition, not by timing. ??? kai/kai, apr'21 + + ArrayList logList = new ArrayList<>(planElements.values()); + logList.sort(new LogElementComparator()); + Collections.reverse(logList); + return logList.getFirst(); + } + + @Override + public void clear() { + planElements.clear(); + } + + static class LogElementComparator implements Comparator { + + @Override + public int compare(LspShipmentPlanElement o1, LspShipmentPlanElement o2) { + if (o1.getStartTime() > o2.getStartTime()) { + return 1; + } + if (o1.getStartTime() < o2.getStartTime()) { + return -1; + } + if (o1.getStartTime() == o2.getStartTime()) { + if (o1.getEndTime() > o2.getEndTime()) { + return 1; + } + if (o1.getEndTime() < o2.getEndTime()) { + return -1; + } + } + return 0; + } + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentRequirement.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentRequirement.java new file mode 100644 index 00000000000..1bbd0f323dd --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentRequirement.java @@ -0,0 +1,28 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.shipment; + +import org.matsim.freight.logistics.LogisticChain; + +public interface LspShipmentRequirement { + + boolean checkRequirement(LogisticChain solution); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentUtils.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentUtils.java new file mode 100644 index 00000000000..3b2c46e8a98 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/LspShipmentUtils.java @@ -0,0 +1,541 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.shipment; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.CarrierService; +import org.matsim.freight.carriers.CarrierShipment; +import org.matsim.freight.carriers.TimeWindow; +import org.matsim.freight.logistics.LSPPlan; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LogisticChainElement; + +public final class LspShipmentUtils { + private LspShipmentUtils() {} // do not instantiate + + public static Comparator createShipmentPlanElementComparator() { + return new ShipmentPlanElementComparator(); + } + + /** + * Gives back the {@link LspShipmentPlan} object of the {@link LSPPlan}, which matches to the id of + * the {@link LspShipment} + * + * @param lspPlan The lspPlan in which this method tries to find the shipmentPlan. + * @param shipmentId Id of the shipment for which the Plan should be found. + * @return the ShipmentPlan object or null, if it is not found. + */ + public static LspShipmentPlan getOrCreateShipmentPlan(LSPPlan lspPlan, Id shipmentId) { + // Return shipmentPlan if already existing in LspPlan + for (LspShipmentPlan lspShipmentPlan : lspPlan.getShipmentPlans()) { + if (lspShipmentPlan.getLspShipmentId().equals(shipmentId)) { + return lspShipmentPlan; + } + } + // ShipmentPlan does not exist in LspPlan. Will create one, add it to the LspPlan. + LspShipmentPlan newLspShipmentPlan = new LspShipmentPlanImpl(shipmentId); + lspPlan.addShipmentPlan(newLspShipmentPlan); + return newLspShipmentPlan; + } + + /** + * Stores a time as Attribute in the LspShipment. + * This is needed for some kind of tracking the shipment. + *

+ * This will replace the LSPShipmentWithTime class and thus reduce the complexity of the code. + * KMT Jul'24 + * @param lspShipment the LspShipment to store the time in + * @param time the time to store + */ + public static void setTimeOfLspShipment(LspShipment lspShipment, double time){ + lspShipment.getAttributes().putAttribute("time", time); + } + + /** + * Returns the time stored in the LspShipment. + *

+ * This will replace the LSPShipmentWithTime class and thus reduce the complexity of the code. KMT Jul'24 + * @param lspShipment the LspShipment to get the time from + * @return the time as double + */ + public static double getTimeOfLspShipment(LspShipment lspShipment) { + return (double) lspShipment.getAttributes().getAttribute("time"); + } + + public static final class LspShipmentBuilder { + final Id id; + final List lspShipmentRequirements; + Id fromLinkId; + Id toLinkId; + TimeWindow startTimeWindow; + TimeWindow endTimeWindow; + int capacityDemand; + double deliveryServiceTime; + double pickupServiceTime; + + private LspShipmentBuilder(Id id) { + this.lspShipmentRequirements = new ArrayList<>(); + this.id = id; + } + + public static LspShipmentBuilder newInstance(Id id) { + return new LspShipmentBuilder(id); + } + + public void setFromLinkId(Id fromLinkId) { + this.fromLinkId = fromLinkId; + } + + public void setToLinkId(Id toLinkId) { + this.toLinkId = toLinkId; + } + + public void setStartTimeWindow(TimeWindow startTimeWindow) { + this.startTimeWindow = startTimeWindow; + } + + public void setEndTimeWindow(TimeWindow endTimeWindow) { + this.endTimeWindow = endTimeWindow; + } + + public void setCapacityDemand(int capacityDemand) { + this.capacityDemand = capacityDemand; + } + + public void setDeliveryServiceTime(double serviceTime) { + this.deliveryServiceTime = serviceTime; + } + + public LspShipmentBuilder setPickupServiceTime(double serviceTime) { + this.pickupServiceTime = serviceTime; + return this; + } + + public void addRequirement(LspShipmentRequirement requirement) { + lspShipmentRequirements.add(requirement); + } + + public LspShipment build() { + return new LspShipmentImpl(this); + } + } + + //----------------------------- + // LoggedShipment<..> builders + //----------------------------- + + @SuppressWarnings("ClassEscapesDefinedScope") + public static final class LoggedShipmentLoadBuilder { + private double startTime; + private double endTime; + private LogisticChainElement element; + private Id resourceId; + private Id carrierId; + private Id linkId; + + private LoggedShipmentLoadBuilder() {} + + public static LoggedShipmentLoadBuilder newInstance() { + return new LoggedShipmentLoadBuilder(); + } + + public void setLogisticsChainElement(LogisticChainElement element) { + this.element = element; + } + + public LoggedLspShipmentLoad build() { + return new LoggedLspShipmentLoad(this); + } + + public double getStartTime() { + return startTime; + } + + public void setStartTime(double startTime) { + this.startTime = startTime; + } + + public double getEndTime() { + return endTime; + } + + public void setEndTime(double endTime) { + this.endTime = endTime; + } + + public LogisticChainElement getElement() { + return element; + } + + // --- Getters --- // + + public Id getResourceId() { + return resourceId; + } + + public void setResourceId(Id resourceId) { + this.resourceId = resourceId; + } + + public Id getCarrierId() { + return carrierId; + } + + public void setCarrierId(Id carrierId) { + this.carrierId = carrierId; + } + + public Id getLinkId() { + return linkId; + } + + public void setLinkId(Id linkId) { + this.linkId = linkId; + } + } + + @SuppressWarnings("ClassEscapesDefinedScope") + public static final class LoggedShipmentTransportBuilder { + private double startTime; + private LogisticChainElement element; + private Id resourceId; + private Id fromLinkId; + private Id toLinkId; + private Id carrierId; + + private LoggedShipmentTransportBuilder() {} + + public static LoggedShipmentTransportBuilder newInstance() { + return new LoggedShipmentTransportBuilder(); + } + + public void setLogisticChainElement(LogisticChainElement element) { + this.element = element; + } + + public LoggedLspShipmentTransport build() { + return new LoggedLspShipmentTransport(this); + } + + // --- Getters --- // + public double getStartTime() { + return startTime; + } + + public void setStartTime(double startTime) { + this.startTime = startTime; + } + + public LogisticChainElement getElement() { + return element; + } + + public Id getResourceId() { + return resourceId; + } + + public void setResourceId(Id resourceId) { + this.resourceId = resourceId; + } + + public Id getFromLinkId() { + return fromLinkId; + } + + public void setFromLinkId(Id fromLinkId) { + this.fromLinkId = fromLinkId; + } + + public Id getToLinkId() { + return toLinkId; + } + + public void setToLinkId(Id toLinkId) { + this.toLinkId = toLinkId; + } + + public Id getCarrierId() { + return carrierId; + } + + public void setCarrierId(Id carrierId) { + this.carrierId = carrierId; + } + } + + @SuppressWarnings("ClassEscapesDefinedScope") + public static final class LoggedShipmentUnloadBuilder { + double startTime; + double endTime; + LogisticChainElement element; + Id resourceId; + Id carrierId; + Id linkId; + + private LoggedShipmentUnloadBuilder() {} + + public static LoggedShipmentUnloadBuilder newInstance() { + return new LoggedShipmentUnloadBuilder(); + } + + public void setStartTime(double startTime) { + this.startTime = startTime; + } + + public void setEndTime(double endTime) { + this.endTime = endTime; + } + + public void setLogisticChainElement(LogisticChainElement element) { + this.element = element; + } + + public void setResourceId(Id resourceId) { + this.resourceId = resourceId; + } + + public void setLinkId(Id linkId) { + this.linkId = linkId; + } + + public void setCarrierId(Id carrierId) { + this.carrierId = carrierId; + } + + public LoggedLspShipmentUnload build() { + return new LoggedLspShipmentUnload(this); + } + } + + public static final class LoggedShipmentHandleBuilder { + double startTime; + double endTime; + LogisticChainElement element; + Id resourceId; + Id linkId; + + private LoggedShipmentHandleBuilder() {} + + public static LoggedShipmentHandleBuilder newInstance() { + return new LoggedShipmentHandleBuilder(); + } + + public LoggedShipmentHandleBuilder setStartTime(double startTime) { + this.startTime = startTime; + return this; + } + + public LoggedShipmentHandleBuilder setEndTime(double endTime) { + this.endTime = endTime; + return this; + } + + public LoggedShipmentHandleBuilder setLogisticsChainElement(LogisticChainElement element) { + this.element = element; + return this; + } + + public LoggedShipmentHandleBuilder setResourceId(Id resourceId) { + this.resourceId = resourceId; + return this; + } + + public LoggedShipmentHandleBuilder setLinkId(Id linkId) { + this.linkId = linkId; + return this; + } + + public LspShipmentPlanElement build() { + return new LoggedLspShipmentHandle(this); + } + } + + //----------------------------- + // ScheduledShipment<..> builders + //----------------------------- + + @SuppressWarnings("ClassEscapesDefinedScope") + public static final class ScheduledShipmentLoadBuilder { + double startTime; + double endTime; + LogisticChainElement element; + Id resourceId; + + private ScheduledShipmentLoadBuilder() {} + + public static ScheduledShipmentLoadBuilder newInstance() { + return new ScheduledShipmentLoadBuilder(); + } + + public void setStartTime(double startTime) { + this.startTime = startTime; + } + + public void setEndTime(double endTime) { + this.endTime = endTime; + } + + public void setLogisticChainElement(LogisticChainElement element) { + this.element = element; + } + + public void setResourceId(Id resourceId) { + this.resourceId = resourceId; + } + + public ScheduledLspShipmentLoad build() { + return new ScheduledLspShipmentLoad(this); + } + } + + @SuppressWarnings("ClassEscapesDefinedScope") + public static final class ScheduledShipmentTransportBuilder { + double startTime; + double endTime; + LogisticChainElement element; + Id resourceId; + Id carrierId; + Id fromLinkId; + Id toLinkId; + CarrierService carrierService; + CarrierShipment carrierShipment; //TODO: Put CarrierShipment and CarrieTask behind one interface and use that here (CarrierTask...) + + private ScheduledShipmentTransportBuilder() {} + + public static ScheduledShipmentTransportBuilder newInstance() { + return new ScheduledShipmentTransportBuilder(); + } + + public void setStartTime(double startTime) { + this.startTime = startTime; + } + + public void setEndTime(double endTime) { + this.endTime = endTime; + } + + public void setLogisticChainElement(LogisticChainElement element) { + this.element = element; + } + + public void setResourceId(Id resourceId) { + this.resourceId = resourceId; + } + + public void setCarrierId(Id carrierId) { + this.carrierId = carrierId; + } + + public void setFromLinkId(Id fromLinkId) { + this.fromLinkId = fromLinkId; + } + + public void setToLinkId(Id toLinkId) { + this.toLinkId = toLinkId; + } + + public void setCarrierService(CarrierService carrierService) { + this.carrierService = carrierService; + } + + public void setCarrierShipment(CarrierShipment carrierShipment) { + this.carrierShipment = carrierShipment; + } + + public ScheduledLspShipmentTransport build() { + return new ScheduledLspShipmentTransport(this); + } + } + + @SuppressWarnings("ClassEscapesDefinedScope") + public static final class ScheduledShipmentUnloadBuilder { + double startTime; + double endTime; + LogisticChainElement element; + Id resourceId; + + private ScheduledShipmentUnloadBuilder() {} + + public static ScheduledShipmentUnloadBuilder newInstance() { + return new ScheduledShipmentUnloadBuilder(); + } + + public void setStartTime(double startTime) { + this.startTime = startTime; + } + + public void setEndTime(double endTime) { + this.endTime = endTime; + } + + public void setLogisticsChainElement(LogisticChainElement element) { + this.element = element; + } + + public void setResourceId(Id resourceId) { + this.resourceId = resourceId; + } + + public ScheduledLspShipmentUnload build() { + return new ScheduledLspShipmentUnload(this); + } + } + + @SuppressWarnings("ClassEscapesDefinedScope") + public static final class ScheduledShipmentHandleBuilder { + double startTime; + double endTime; + LogisticChainElement element; + Id resourceId; + + private ScheduledShipmentHandleBuilder() {} + + public static ScheduledShipmentHandleBuilder newInstance() { + return new ScheduledShipmentHandleBuilder(); + } + + public void setStartTime(double startTime) { + this.startTime = startTime; + } + + public void setEndTime(double endTime) { + this.endTime = endTime; + } + + public void setLogisticsChainElement(LogisticChainElement element) { + this.element = element; + } + + public void setResourceId(Id resourceId) { + this.resourceId = resourceId; + } + + public ScheduledLspShipmentHandle build() { + return new ScheduledLspShipmentHandle(this); + } + } + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/ScheduledLspShipmentHandle.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/ScheduledLspShipmentHandle.java new file mode 100644 index 00000000000..54e6bef95a4 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/ScheduledLspShipmentHandle.java @@ -0,0 +1,65 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.shipment; + +import org.matsim.api.core.v01.Id; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LogisticChainElement; + +class ScheduledLspShipmentHandle implements LspShipmentPlanElement { + + private final double startTime; + private final double endTime; + private final LogisticChainElement element; + private final Id resourceId; + + ScheduledLspShipmentHandle(LspShipmentUtils.ScheduledShipmentHandleBuilder builder) { + this.startTime = builder.startTime; + this.endTime = builder.endTime; + this.element = builder.element; + this.resourceId = builder.resourceId; + } + + @Override + public String getElementType() { + return "HANDLE"; + } + + @Override + public double getStartTime() { + return startTime; + } + + @Override + public double getEndTime() { + return endTime; + } + + @Override + public LogisticChainElement getLogisticChainElement() { + return element; + } + + @Override + public Id getResourceId() { + return resourceId; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/ScheduledLspShipmentLoad.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/ScheduledLspShipmentLoad.java new file mode 100644 index 00000000000..df709de193d --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/ScheduledLspShipmentLoad.java @@ -0,0 +1,66 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.shipment; + +import org.matsim.api.core.v01.Id; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LogisticChainElement; + +class ScheduledLspShipmentLoad implements LspShipmentPlanElement { + + private final double startTime; + private final double endTime; + private final LogisticChainElement element; + private final Id resourceId; + + ScheduledLspShipmentLoad(LspShipmentUtils.ScheduledShipmentLoadBuilder builder) { + this.startTime = builder.startTime; + this.endTime = builder.endTime; + this.element = builder.element; + this.resourceId = builder.resourceId; + } + + @Override + public String getElementType() { + return "LOAD"; + } + + @Override + public double getStartTime() { + return startTime; + } + + @Override + public double getEndTime() { + return endTime; + } + + @Override + public LogisticChainElement getLogisticChainElement() { + return element; + } + + @Override + public Id getResourceId() { + return resourceId; + } + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/ScheduledLspShipmentTransport.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/ScheduledLspShipmentTransport.java new file mode 100644 index 00000000000..71b084e2843 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/ScheduledLspShipmentTransport.java @@ -0,0 +1,113 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.shipment; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.CarrierService; +import org.matsim.freight.carriers.CarrierShipment; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LogisticChainElement; + +final class ScheduledLspShipmentTransport implements LspShipmentLeg { + + private final double startTime; + private final double endTime; + private final LogisticChainElement element; + private final Id resourceId; + private final Id carrierId; + private final Id fromLinkId; + private final Id toLinkId; + private final CarrierService carrierService; + private final CarrierShipment carrierShipment; //TODO: Put CarrierShipment and CarrieTask behind one interface and use that here (CarrierTask...) + + ScheduledLspShipmentTransport(LspShipmentUtils.ScheduledShipmentTransportBuilder builder) { + this.startTime = builder.startTime; + this.endTime = builder.endTime; + this.element = builder.element; + this.resourceId = builder.resourceId; + this.carrierId = builder.carrierId; + this.fromLinkId = builder.fromLinkId; + this.toLinkId = builder.toLinkId; + this.carrierService = builder.carrierService; + this.carrierShipment = builder.carrierShipment; + } + + @Override + public String getElementType() { + return "TRANSPORT"; + } + + @Override + public double getStartTime() { + return startTime; + } + + @Override + public double getEndTime() { + return endTime; + } + + @Override + public void setEndTime(double time) { + throw new RuntimeException("not implemented"); + } + + @Override + public LogisticChainElement getLogisticChainElement() { + return element; + } + + @Override + public Id getResourceId() { + return resourceId; + } + + @Override + public Id getToLinkId() { + return toLinkId; + } + + @Override + public void setToLinkId(Id endLinkId) { + throw new RuntimeException("not implemented"); + } + + @Override + public Id getCarrierId() { + return carrierId; + } + + @Override + public Id getFromLinkId() { + return fromLinkId; + } + + @Override + public CarrierService getCarrierService() { + return carrierService; + } + + public CarrierShipment getCarrierShipment() { + return carrierShipment; + } +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/ScheduledLspShipmentUnload.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/ScheduledLspShipmentUnload.java new file mode 100644 index 00000000000..1746e854ffe --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/ScheduledLspShipmentUnload.java @@ -0,0 +1,66 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.shipment; + +import org.matsim.api.core.v01.Id; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LogisticChainElement; + +class ScheduledLspShipmentUnload implements LspShipmentPlanElement { + + private final double startTime; + private final double endTime; + private final LogisticChainElement element; + private final Id resourceId; + + ScheduledLspShipmentUnload(LspShipmentUtils.ScheduledShipmentUnloadBuilder builder) { + this.startTime = builder.startTime; + this.endTime = builder.endTime; + this.element = builder.element; + this.resourceId = builder.resourceId; + } + + @Override + public String getElementType() { + return "UNLOAD"; + } + + @Override + public double getStartTime() { + return startTime; + } + + @Override + public double getEndTime() { + return endTime; + } + + @Override + public LogisticChainElement getLogisticChainElement() { + return element; + } + + @Override + public Id getResourceId() { + return resourceId; + } + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/ShipmentPlanElementComparator.java b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/ShipmentPlanElementComparator.java new file mode 100644 index 00000000000..39eec06637e --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/logistics/shipment/ShipmentPlanElementComparator.java @@ -0,0 +1,46 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.shipment; + +import java.util.Comparator; + +final class ShipmentPlanElementComparator implements Comparator { + + ShipmentPlanElementComparator() {} + + public int compare(LspShipmentPlanElement o1, LspShipmentPlanElement o2) { + if (o1.getStartTime() > o2.getStartTime()) { + return 1; + } + if (o1.getStartTime() < o2.getStartTime()) { + return -1; + } + if (o1.getStartTime() == o2.getStartTime()) { + if (o1.getEndTime() > o2.getEndTime()) { + return 1; + } + if (o1.getEndTime() < o2.getEndTime()) { + return -1; + } + } + return 0; + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierEventsReadersTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierEventsReadersTest.java index bf1cb7be9a6..2b1c2ead062 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierEventsReadersTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierEventsReadersTest.java @@ -20,6 +20,10 @@ package org.matsim.freight.carriers; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -36,12 +40,6 @@ import org.matsim.testcases.utils.EventsCollector; import org.matsim.vehicles.Vehicle; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.util.ArrayList; -import java.util.List; - - /** * @author Kai Martins-Turner (kturner) * @author Niclas Richter (nixlaos) 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 49dc173dd05..e80f24075be 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 @@ -33,11 +33,9 @@ import org.matsim.core.controler.Controler; import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.core.scenario.ScenarioUtils; -import org.matsim.freight.carriers.CarriersUtils; -import org.matsim.freight.carriers.FreightCarriersConfigGroup; -import org.matsim.freight.carriers.controler.CarrierModule; -import org.matsim.freight.carriers.controler.CarrierScoringFunctionFactory; -import org.matsim.freight.carriers.controler.CarrierStrategyManager; +import org.matsim.freight.carriers.controller.CarrierModule; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; import org.matsim.freight.carriers.mobsim.DistanceScoringFunctionFactoryForTests; import org.matsim.freight.carriers.mobsim.StrategyManagerFactoryForTests; import org.matsim.testcases.MatsimTestUtils; @@ -69,10 +67,10 @@ public void setUp(){ config.plans().setInputFile( testUtils.getClassInputDirectory() + "plans100.xml" ); config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.overwriteExistingFiles); config.controller().setWritePlansInterval(1); - config.controller().setCreateGraphs(false); + config.controller().setCreateGraphsInterval(0); freightCarriersConfigGroup = ConfigUtils.addOrGetModule( config, FreightCarriersConfigGroup.class ) ; freightCarriersConfigGroup.setCarriersFile( testUtils.getClassInputDirectory() + "carrierPlansEquils.xml"); - freightCarriersConfigGroup.setCarriersVehicleTypesFile( testUtils.getClassInputDirectory() + "vehicleTypes.xml"); + freightCarriersConfigGroup.setCarriersVehicleTypesFile( testUtils.getPackageInputDirectory() + "vehicleTypes_v2.xml"); Scenario scenario = ScenarioUtils.loadScenario( config ); diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanReaderV1Test.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanReaderV1Test.java index 38749fbabdf..8092ccfd02d 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanReaderV1Test.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanReaderV1Test.java @@ -26,7 +26,6 @@ import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Id; import org.matsim.core.population.routes.NetworkRoute; -import org.matsim.freight.carriers.*; import org.matsim.freight.carriers.Tour.Leg; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.VehicleType; diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlReaderV2Test.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlReaderV2Test.java index 0deffa73889..07b0a547f3e 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlReaderV2Test.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlReaderV2Test.java @@ -21,8 +21,12 @@ package org.matsim.freight.carriers; -import org.junit.jupiter.api.BeforeEach; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.*; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Id; @@ -32,16 +36,10 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.core.gbl.Gbl; import org.matsim.core.scenario.ScenarioUtils; -import org.matsim.freight.carriers.*; import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.Vehicle; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.*; - public class CarrierPlanXmlReaderV2Test { @RegisterExtension @@ -192,7 +190,7 @@ void test_readStream() { - + diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlReaderV2WithDtdTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlReaderV2WithDtdTest.java index fb12a37ff82..db3141cf8cb 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlReaderV2WithDtdTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlReaderV2WithDtdTest.java @@ -21,20 +21,18 @@ package org.matsim.freight.carriers; +import java.util.*; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; -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.Id; import org.matsim.core.gbl.Gbl; -import org.matsim.freight.carriers.*; import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.Vehicle; -import java.util.*; - public class CarrierPlanXmlReaderV2WithDtdTest { @RegisterExtension diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2Test.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2Test.java deleted file mode 100644 index 46444ed07d3..00000000000 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2Test.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * *********************************************************************** * - * project: org.matsim.* - * *********************************************************************** * - * * - * copyright : (C) 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.freight.carriers; - -import org.junit.jupiter.api.BeforeEach; -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.TransportMode; -import org.matsim.freight.carriers.*; -import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; -import org.matsim.testcases.MatsimTestUtils; -import org.matsim.vehicles.Vehicle; - -import java.util.*; - -import static org.junit.jupiter.api.Assertions.*; - -public class CarrierPlanXmlWriterV2Test { - - @RegisterExtension - private MatsimTestUtils testUtils = new MatsimTestUtils(); - - private Carrier testCarrier; - - @BeforeEach - public void setUp() { - - CarrierVehicleTypes carrierVehicleTypes = new CarrierVehicleTypes(); - new CarrierVehicleTypeReader( carrierVehicleTypes ).readFile( this.testUtils.getPackageInputDirectory() + "vehicleTypes_v2.xml" ); - - Carriers carriers = new Carriers(); - new CarrierPlanXmlReader(carriers, carrierVehicleTypes ).readFile(this.testUtils.getClassInputDirectory() + "carrierPlansEquils.xml" ); - new CarrierPlanXmlWriterV2(carriers).write(this.testUtils.getClassInputDirectory() + "carrierPlansEquilsWritten.xml"); - carriers.getCarriers().clear(); - new CarrierPlanXmlReader(carriers, carrierVehicleTypes ).readFile(this.testUtils.getClassInputDirectory() + "carrierPlansEquilsWritten.xml" ); - testCarrier = carriers.getCarriers().get(Id.create("testCarrier", Carrier.class)); - } - - @Test - void test_whenReadingServices_nuOfServicesIsCorrect(){ - assertEquals(3,testCarrier.getServices().size()); - } - - @Test - void test_whenReadingCarrier_itReadsTypeIdsCorrectly(){ - - CarrierVehicle light = CarriersUtils.getCarrierVehicle(testCarrier, Id.createVehicleId("lightVehicle")); - assertEquals("light",light.getVehicleTypeId().toString()); - - CarrierVehicle medium = CarriersUtils.getCarrierVehicle(testCarrier, Id.createVehicleId("mediumVehicle")); - assertEquals("medium",medium.getVehicleTypeId().toString()); - - CarrierVehicle heavy = CarriersUtils.getCarrierVehicle(testCarrier, Id.createVehicleId("heavyVehicle")); - assertEquals("heavy",heavy.getVehicleTypeId().toString()); - } - - @Test - void test_whenReadingCarrier_itReadsVehiclesCorrectly(){ - Map, CarrierVehicle> carrierVehicles = testCarrier.getCarrierCapabilities().getCarrierVehicles(); - assertEquals(3,carrierVehicles.size()); - assertTrue(exactlyTheseVehiclesAreInVehicleCollection(Arrays.asList(Id.create("lightVehicle", Vehicle.class), - Id.create("mediumVehicle", Vehicle.class),Id.create("heavyVehicle", Vehicle.class)),carrierVehicles.values())); - } - - @Test - void test_whenReadingCarrier_itReadsFleetSizeCorrectly(){ - assertEquals(FleetSize.INFINITE, testCarrier.getCarrierCapabilities().getFleetSize()); - } - - @Test - void test_whenReadingCarrier_itReadsShipmentsCorrectly(){ - assertEquals(2, testCarrier.getShipments().size()); - } - - @Test - void test_whenReadingCarrier_itReadsPlansCorrectly(){ - assertEquals(3, testCarrier.getPlans().size()); - } - - @Test - void test_whenReadingCarrier_itSelectsPlansCorrectly(){ - assertNotNull(testCarrier.getSelectedPlan()); - } - - @Test - void test_whenReadingPlans_nuOfToursIsCorrect(){ - List plans = new ArrayList<>(testCarrier.getPlans()); - assertEquals(1, plans.get(0).getScheduledTours().size()); - assertEquals(1, plans.get(1).getScheduledTours().size()); - assertEquals(1, plans.get(2).getScheduledTours().size()); - } - - @Test - void test_whenReadingToursOfPlan1_nuOfActivitiesIsCorrect(){ - List plans = new ArrayList<>(testCarrier.getPlans()); - CarrierPlan plan1 = plans.getFirst(); - ScheduledTour tour1 = plan1.getScheduledTours().iterator().next(); - assertEquals(5,tour1.getTour().getTourElements().size()); - } - - @Test - void test_whenReadingToursOfPlan2_nuOfActivitiesIsCorrect(){ - List plans = new ArrayList<>(testCarrier.getPlans()); - CarrierPlan plan2 = plans.get(1); - ScheduledTour tour1 = plan2.getScheduledTours().iterator().next(); - assertEquals(9,tour1.getTour().getTourElements().size()); - } - - @Test - void test_whenReadingToursOfPlan3_nuOfActivitiesIsCorrect(){ - List plans = new ArrayList<>(testCarrier.getPlans()); - CarrierPlan plan3 = plans.get(2); - ScheduledTour tour1 = plan3.getScheduledTours().iterator().next(); - assertEquals(9,tour1.getTour().getTourElements().size()); - } - - - private boolean exactlyTheseVehiclesAreInVehicleCollection(List> asList, Collection carrierVehicles) { - List vehicles = new ArrayList<>(carrierVehicles); - for(CarrierVehicle type : carrierVehicles) if(asList.contains(type.getId() )) vehicles.remove(type ); - return vehicles.isEmpty(); - } - - @Test - void test_CarrierHasAttributes(){ - assertEquals((TransportMode.drt), CarriersUtils.getCarrierMode(testCarrier)); - assertEquals(50, CarriersUtils.getJspritIterations(testCarrier)); - } - - @Test - void test_ServicesAndShipmentsHaveAttributes(){ - Object serviceCustomerAtt = testCarrier.getServices().get(Id.create("serv1",CarrierService.class)).getAttributes().getAttribute("customer"); - assertNotNull(serviceCustomerAtt); - assertEquals("someRandomCustomer", serviceCustomerAtt); - Object shipmentCustomerAtt = testCarrier.getShipments().get(Id.create("s1",CarrierShipment.class)).getAttributes().getAttribute("customer"); - assertNotNull(shipmentCustomerAtt); - assertEquals("someRandomCustomer", shipmentCustomerAtt); - } - -} diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2_1Test.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2_1Test.java index b3a12fdb60f..f331ff0b671 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2_1Test.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierPlanXmlWriterV2_1Test.java @@ -21,6 +21,9 @@ package org.matsim.freight.carriers; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -30,10 +33,6 @@ import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.Vehicle; -import java.util.*; - -import static org.junit.jupiter.api.Assertions.*; - public class CarrierPlanXmlWriterV2_1Test { @RegisterExtension diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierReadWriteV2_1Test.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierReadWriteV2_1Test.java index 71d69e6d216..5da6137dcd8 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierReadWriteV2_1Test.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierReadWriteV2_1Test.java @@ -21,13 +21,11 @@ package org.matsim.freight.carriers; +import java.util.Collections; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import org.matsim.freight.carriers.*; import org.matsim.testcases.MatsimTestUtils; -import java.util.Collections; - public class CarrierReadWriteV2_1Test { @RegisterExtension @@ -43,7 +41,7 @@ void readWriteTest() { String outputFilename = utils.getOutputDirectory() + "outputCarriers.xml"; CarrierVehicleTypeReader vehicleTypeReader = new CarrierVehicleTypeReader(carrierVehicleTypes); - vehicleTypeReader.readFile(utils.getClassInputDirectory() + "vehicles.xml"); + vehicleTypeReader.readFile(utils.getPackageInputDirectory() + "vehicleTypes_v2.xml"); CarrierPlanXmlReader carrierReader = new CarrierPlanXmlReader(carriers, carrierVehicleTypes); carrierReader.readFile(inputFilename); @@ -65,7 +63,7 @@ void readWriteReadTest() { String outputFilename2 = utils.getOutputDirectory() + "/outputCarriers2.xml"; CarrierVehicleTypeReader vehicleTypeReader = new CarrierVehicleTypeReader(carrierVehicleTypes); - vehicleTypeReader.readFile(utils.getClassInputDirectory() + "vehicles.xml"); + vehicleTypeReader.readFile(utils.getPackageInputDirectory() + "vehicleTypes_v2.xml"); CarrierPlanXmlReader reader1 = new CarrierPlanXmlReader(carriers, carrierVehicleTypes); reader1.readFile(utils.getClassInputDirectory() + "carriers.xml"); diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeLoaderTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeLoaderTest.java index 97954bb151d..7d221c171fb 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeLoaderTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeLoaderTest.java @@ -21,16 +21,17 @@ package org.matsim.freight.carriers; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Id; -import org.matsim.freight.carriers.*; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.VehicleType; import org.matsim.vehicles.VehicleUtils; +import java.nio.file.Path; + public class CarrierVehicleTypeLoaderTest { @RegisterExtension @@ -42,14 +43,14 @@ public class CarrierVehicleTypeLoaderTest { @BeforeEach public void setUp() { types = new CarrierVehicleTypes(); - new CarrierVehicleTypeReader(types).readFile(utils.getClassInputDirectory() + "vehicleTypes.xml"); + new CarrierVehicleTypeReader(types).readFile(Path.of(utils.getClassInputDirectory()).getParent().resolve("vehicleTypes_v2.xml").toString()); carriers = new Carriers(); new CarrierPlanXmlReader(carriers, types ).readFile(utils.getClassInputDirectory() + "carrierPlansEquils.xml" ); } @Test void test_whenLoadingTypes_allAssignmentsInLightVehicleAreCorrectly(){ - new CarrierVehicleTypeLoader(carriers).loadVehicleTypes(types); +// new CarrierVehicleTypeLoader(carriers).loadVehicleTypes(types); Carrier testCarrier = carriers.getCarriers().get(Id.create("testCarrier", Carrier.class)); CarrierVehicle v = CarriersUtils.getCarrierVehicle(testCarrier,Id.createVehicleId("lightVehicle")); @@ -62,13 +63,13 @@ void test_whenLoadingTypes_allAssignmentsInLightVehicleAreCorrectly(){ Assertions.assertEquals(0.35, vehicleTypeLoaded.getCostInformation().getCostsPerMeter(), MatsimTestUtils.EPSILON); Assertions.assertEquals(30, vehicleTypeLoaded.getCostInformation().getCostsPerSecond(), MatsimTestUtils.EPSILON); - Assertions.assertEquals("gasoline", vehicleTypeLoaded.getEngineInformation().getFuelType().toString()); - Assertions.assertEquals(0.02, VehicleUtils.getFuelConsumption(vehicleTypeLoaded), MatsimTestUtils.EPSILON); + Assertions.assertEquals("gasoline", VehicleUtils.getHbefaTechnology(vehicleTypeLoaded.getEngineInformation())); + Assertions.assertEquals(0.02, VehicleUtils.getFuelConsumptionLitersPerMeter(vehicleTypeLoaded.getEngineInformation()), MatsimTestUtils.EPSILON); } @Test void test_whenLoadingTypes_allAssignmentsInMediumVehicleAreCorrectly(){ - new CarrierVehicleTypeLoader(carriers).loadVehicleTypes(types); +// new CarrierVehicleTypeLoader(carriers).loadVehicleTypes(types); Carrier testCarrier = carriers.getCarriers().get(Id.create("testCarrier", Carrier.class)); CarrierVehicle v = CarriersUtils.getCarrierVehicle(testCarrier,Id.createVehicleId("mediumVehicle")); @@ -81,8 +82,8 @@ void test_whenLoadingTypes_allAssignmentsInMediumVehicleAreCorrectly(){ Assertions.assertEquals(0.4, vehicleTypeLoaded.getCostInformation().getCostsPerMeter(), MatsimTestUtils.EPSILON); Assertions.assertEquals(30, vehicleTypeLoaded.getCostInformation().getCostsPerSecond(), MatsimTestUtils.EPSILON); - Assertions.assertEquals("gasoline", vehicleTypeLoaded.getEngineInformation().getFuelType().toString()); - Assertions.assertEquals(0.02, VehicleUtils.getFuelConsumption(vehicleTypeLoaded), MatsimTestUtils.EPSILON); + Assertions.assertEquals("gasoline", VehicleUtils.getHbefaTechnology(vehicleTypeLoaded.getEngineInformation())); + Assertions.assertEquals(0.02, VehicleUtils.getFuelConsumptionLitersPerMeter(vehicleTypeLoaded.getEngineInformation()), MatsimTestUtils.EPSILON); } diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeReaderTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeReaderTest.java index 3a2f5a5648e..1dbfcf0b096 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeReaderTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeReaderTest.java @@ -21,6 +21,9 @@ package org.matsim.freight.carriers; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.BeforeEach; @@ -29,9 +32,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.VehicleType; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import org.matsim.vehicles.VehicleUtils; public class CarrierVehicleTypeReaderTest { @RegisterExtension private MatsimTestUtils utils = new MatsimTestUtils() ; @@ -44,20 +45,21 @@ public class CarrierVehicleTypeReaderTest { @BeforeEach public void setUp() { types = new CarrierVehicleTypes(); - inFilename = utils.getClassInputDirectory() + "vehicleTypes.xml"; + inFilename = utils.getClassInputDirectory() + "vehicleTypes_deprecated_v1.xml"; new CarrierVehicleTypeReader(types).readFile( inFilename ); } @Test void test_whenReadingTypes_nuOfTypesIsReadCorrectly(){ - assertEquals(2, types.getVehicleTypes().size()); + assertEquals(3, types.getVehicleTypes().size()); } @Test void test_whenReadingTypes_itReadyExactlyTheTypesFromFile(){ assertTrue(types.getVehicleTypes().containsKey(Id.create("medium", org.matsim.vehicles.VehicleType.class ) ) ); assertTrue(types.getVehicleTypes().containsKey(Id.create("light", org.matsim.vehicles.VehicleType.class ) ) ); - assertEquals(2, types.getVehicleTypes().size()); + assertTrue(types.getVehicleTypes().containsKey(Id.create("heavy", org.matsim.vehicles.VehicleType.class ) ) ); + assertEquals(3, types.getVehicleTypes().size()); } @Test @@ -83,15 +85,15 @@ void test_whenReadingTypeMedium_itReadsCostInfoCorrectly(){ @Test void test_whenReadingTypeMedium_itReadsEngineInfoCorrectly(){ VehicleType medium = types.getVehicleTypes().get(Id.create("medium", org.matsim.vehicles.VehicleType.class ) ); - assertEquals(0.02, medium.getEngineInformation().getFuelConsumption(),0.01); - assertEquals("gasoline", medium.getEngineInformation().getFuelType().toString()); + assertEquals(0.02, VehicleUtils.getFuelConsumptionLitersPerMeter(medium.getEngineInformation()), 0.01); + assertEquals("gasoline", VehicleUtils.getHbefaTechnology(medium.getEngineInformation())); } @Test void readV1andWriteV2(){ final String outFilename = utils.getOutputDirectory() + "/vehicleTypes_v2.xml"; new CarrierVehicleTypeWriter( types ).write( outFilename ) ; - final String referenceFilename = utils.getClassInputDirectory() + "/vehicleTypes_v2.xml" ; + final String referenceFilename = utils.getPackageInputDirectory() + "/vehicleTypes_v2.xml" ; MatsimTestUtils.assertEqualFilesLineByLine( referenceFilename, outFilename ); } @@ -104,7 +106,7 @@ void readV2andWriteV2() { log.info("") ; log.info("now starting for real") ; log.info("") ; - String inFilename1 = utils.getClassInputDirectory() + "vehicleTypes_v2.xml"; + String inFilename1 = utils.getPackageInputDirectory() + "vehicleTypes_v2.xml"; CarrierVehicleTypes types1 = new CarrierVehicleTypes(); new CarrierVehicleTypeReader( types1 ).readFile( inFilename1 ); diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeTest.java index 24328872de2..653c3972aad 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeTest.java @@ -21,12 +21,12 @@ package org.matsim.freight.carriers; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Id; -import org.matsim.freight.carriers.CarrierVehicleTypes; +import org.matsim.api.core.v01.TransportMode; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.*; import org.matsim.vehicles.EngineInformation.FuelType; @@ -48,11 +48,12 @@ public void setUp() { costInformation1.setCostsPerMeter( 1.0 ); costInformation1.setCostsPerSecond( 0.5 ); EngineInformation engineInformation1 = mediumType.getEngineInformation(); - engineInformation1.setFuelType( FuelType.diesel ); - engineInformation1.setFuelConsumption( 0.02 ); + VehicleUtils.setHbefaTechnology( engineInformation1, "diesel" ); + VehicleUtils.setFuelConsumptionLitersPerMeter( engineInformation1, 0.02 ); VehicleCapacity vehicleCapacity = mediumType.getCapacity(); vehicleCapacity.setWeightInTons( 30 ); mediumType.setDescription( "Medium Vehicle" ).setMaximumVelocity( 13.89 ); + mediumType.setNetworkMode(TransportMode.truck); types = new CarrierVehicleTypes(); types.getVehicleTypes().put( mediumType.getId(), mediumType ); } @@ -71,12 +72,13 @@ public void setUp() { costInformation.setCostsPerMeter( 0.75 ); costInformation.setCostsPerSecond( 0.25 ); EngineInformation engineInformation = smallType.getEngineInformation() ; - engineInformation.setFuelType( FuelType.gasoline ); - engineInformation.setFuelConsumption( 0.015 ); + VehicleUtils.setHbefaTechnology( engineInformation, "gasoline" ); + VehicleUtils.setFuelConsumptionLitersPerMeter( engineInformation, 0.015 ); VehicleCapacity capacity = smallType.getCapacity() ; capacity.setWeightInTons( 16 ) ; // VehicleType smallType = CarriersUtils.CarrierVehicleTypeBuilder.newInstance( smallTypeId, mediumType ) smallType.setDescription( "Small Vehicle" ).setMaximumVelocity( 10.0 ) ; + smallType.setNetworkMode(TransportMode.car); types.getVehicleTypes().put( smallType.getId(), smallType); } } @@ -104,8 +106,8 @@ void test_whenCreatingTypeMedium_itCreatesCostInfoCorrectly(){ @Test void test_whenCreatingTypeMedium_itCreatesEngineInfoCorrectly(){ VehicleType medium = types.getVehicleTypes().get(Id.create("medium", org.matsim.vehicles.VehicleType.class ) ); - Assertions.assertEquals(0.02, medium.getEngineInformation().getFuelConsumption(),0.001); - Assertions.assertEquals(FuelType.diesel, medium.getEngineInformation().getFuelType()); + Assertions.assertEquals(0.02, VehicleUtils.getFuelConsumptionLitersPerMeter(medium.getEngineInformation())); + Assertions.assertEquals("diesel", VehicleUtils.getHbefaTechnology(medium.getEngineInformation())); } @Test @@ -138,8 +140,8 @@ void test_whenCopyingTypeMedium_itCopiesCostInfoCorrectly(){ @Test void test_whenCopyingTypeMedium_itCopiesEngineInfoCorrectly(){ VehicleType medium2 = types.getVehicleTypes().get(Id.create("medium2", org.matsim.vehicles.VehicleType.class ) ); - Assertions.assertEquals(0.02, medium2.getEngineInformation().getFuelConsumption(),0.001); - Assertions.assertEquals(FuelType.diesel, medium2.getEngineInformation().getFuelType()); + Assertions.assertEquals(0.02, VehicleUtils.getFuelConsumptionLitersPerMeter(medium2.getEngineInformation())); + Assertions.assertEquals("diesel", VehicleUtils.getHbefaTechnology(medium2.getEngineInformation())); } @Test @@ -172,8 +174,8 @@ void test_whenModifyingTypeSmall_itModifiesCostInfoCorrectly(){ @Test void test_whenModifyingTypeSmall_itModifiesEngineInfoCorrectly(){ VehicleType small = types.getVehicleTypes().get(Id.create("small", org.matsim.vehicles.VehicleType.class ) ); - Assertions.assertEquals(0.015, small.getEngineInformation().getFuelConsumption(),0.001); - Assertions.assertEquals(FuelType.gasoline, small.getEngineInformation().getFuelType()); + Assertions.assertEquals(0.015, VehicleUtils.getFuelConsumptionLitersPerMeter(small.getEngineInformation())); + Assertions.assertEquals("gasoline", VehicleUtils.getHbefaTechnology(small.getEngineInformation())); } @Test diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeWriterTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeWriterTest.java index 307408885a6..89228f26c4e 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeWriterTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierVehicleTypeWriterTest.java @@ -23,9 +23,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import org.matsim.freight.carriers.CarrierVehicleTypeReader; -import org.matsim.freight.carriers.CarrierVehicleTypeWriter; -import org.matsim.freight.carriers.CarrierVehicleTypes; import org.matsim.testcases.MatsimTestUtils; public class CarrierVehicleTypeWriterTest { @@ -36,7 +33,7 @@ public class CarrierVehicleTypeWriterTest { @Test void testTypeWriter(){ CarrierVehicleTypes types = new CarrierVehicleTypes(); - new CarrierVehicleTypeReader(types).readFile(utils.getClassInputDirectory()+ "vehicleTypes.xml"); + new CarrierVehicleTypeReader(types).readFile(utils.getPackageInputDirectory()+ "vehicleTypes_v2.xml"); final String outputVehTypeFile = utils.getOutputDirectory()+ "vehicleTypesWritten.xml"; new CarrierVehicleTypeWriter(types).write(outputVehTypeFile); types.getVehicleTypes().clear(); diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarriersUtilsTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarriersUtilsTest.java index 04772ee65a2..70892f49e51 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarriersUtilsTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarriersUtilsTest.java @@ -21,18 +21,17 @@ package org.matsim.freight.carriers; +import static org.matsim.testcases.MatsimTestUtils.EPSILON; + 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.Id; -import org.matsim.freight.carriers.*; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.VehicleType; import org.matsim.vehicles.VehicleUtils; -import static org.matsim.testcases.MatsimTestUtils.EPSILON; - /** */ public class CarriersUtilsTest { @@ -43,7 +42,7 @@ public class CarriersUtilsTest { @Test void testAddAndGetVehicleToCarrier() { VehicleType vehicleType = VehicleUtils.createDefaultVehicleType(); - + Carrier carrier = new CarrierImpl(Id.create("carrier", Carrier.class)); Id testVehicleId = Id.createVehicleId("testVehicle"); CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(testVehicleId, Id.createLinkId("link0"),vehicleType); diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/FreightCarriersConfigGroupTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/FreightCarriersConfigGroupTest.java index 33a4d6736e8..5c3d053190b 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/FreightCarriersConfigGroupTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/FreightCarriersConfigGroupTest.java @@ -21,6 +21,10 @@ package org.matsim.freight.carriers; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Map; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.matsim.core.config.Config; @@ -28,11 +32,6 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.freight.carriers.FreightCarriersConfigGroup.UseDistanceConstraintForTourPlanning; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.Map; - /** * @author mrieser / Simunto */ diff --git a/contribs/vsp/src/test/java/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest.java similarity index 50% rename from contribs/vsp/src/test/java/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest.java rename to contribs/freight/src/test/java/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest.java index 75986b3e94c..58587ab5248 100644 --- a/contribs/vsp/src/test/java/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest.java @@ -21,22 +21,52 @@ package org.matsim.freight.carriers.analysis; +import java.io.IOException; +import java.net.URL; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; -import java.io.IOException; - public class FreightAnalysisEventBasedTest { @RegisterExtension private MatsimTestUtils testUtils = new MatsimTestUtils(); + final static URL SCENARIO_URL = ExamplesUtils.getTestScenarioURL("freight-chessboard-9x9"); @Test - void runFreightAnalysisEventBasedTest() throws IOException { + void runServiceEventTest() throws IOException { + // Note: I had to manually change the files for this test to run, as I did not have access to the original input file of the events-file + // This results in the carrier-plans not being related to the actual events. This is however no problem for testing the core functionality, + // as those are two disjunct analysis outputs, which do not depend on each other. (aleks Sep'24) + RunFreightAnalysisEventBased analysisEventBased = new RunFreightAnalysisEventBased( + IOUtils.extendUrl(SCENARIO_URL, "grid9x9.xml" ).toString(), + testUtils.getInputDirectory() + "in/output_allVehicles.xml", + IOUtils.extendUrl(SCENARIO_URL, "singleCarrierFiveActivities.xml" ).toString(), + IOUtils.extendUrl(SCENARIO_URL, "vehicleTypes.xml" ).toString(), + testUtils.getInputDirectory() + "in/serviceBasedEvents.xml", + testUtils.getOutputDirectory(), + null); + analysisEventBased.runCompleteAnalysis(); + + MatsimTestUtils.assertEqualFilesLineByLine(testUtils.getInputDirectory() + "Carrier_stats.tsv", testUtils.getOutputDirectory() + "Carrier_stats.tsv"); + MatsimTestUtils.assertEqualFilesLineByLine(testUtils.getInputDirectory() + "Load_perVehicle.tsv", testUtils.getOutputDirectory() + "Load_perVehicle.tsv"); + MatsimTestUtils.assertEqualFilesLineByLine(testUtils.getInputDirectory() + "TimeDistance_perVehicle.tsv", testUtils.getOutputDirectory() + "TimeDistance_perVehicle.tsv"); + MatsimTestUtils.assertEqualFilesLineByLine(testUtils.getInputDirectory() + "TimeDistance_perVehicleType.tsv", testUtils.getOutputDirectory() + "TimeDistance_perVehicleType.tsv"); + } - RunFreightAnalysisEventBased analysisEventBased = new RunFreightAnalysisEventBased(testUtils.getClassInputDirectory(), testUtils.getOutputDirectory(),null); - analysisEventBased.runAnalysis(); + @Test + void runShipmentEventTest() throws IOException { + RunFreightAnalysisEventBased analysisEventBased = new RunFreightAnalysisEventBased( + IOUtils.extendUrl(SCENARIO_URL, "grid9x9.xml" ).toString(), + testUtils.getInputDirectory() + "in/carrierVehicles.xml", + IOUtils.extendUrl(SCENARIO_URL, "singleCarrierFiveActivities_Shipments.xml" ).toString(), + IOUtils.extendUrl(SCENARIO_URL, "vehicleTypes.xml" ).toString(), + testUtils.getInputDirectory() + "in/shipmentBasedEvents.xml", + testUtils.getOutputDirectory(), + null); + analysisEventBased.runCompleteAnalysis(); MatsimTestUtils.assertEqualFilesLineByLine(testUtils.getInputDirectory() + "Carrier_stats.tsv", testUtils.getOutputDirectory() + "Carrier_stats.tsv"); MatsimTestUtils.assertEqualFilesLineByLine(testUtils.getInputDirectory() + "Load_perVehicle.tsv", testUtils.getOutputDirectory() + "Load_perVehicle.tsv"); 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/controller/EquilWithCarrierWithPersonsIT.java similarity index 95% rename from contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT.java rename to contribs/freight/src/test/java/org/matsim/freight/carriers/controller/EquilWithCarrierWithPersonsIT.java index 75800bfd34d..d18c15840a4 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/controller/EquilWithCarrierWithPersonsIT.java @@ -19,10 +19,10 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Id; @@ -40,6 +40,8 @@ import org.matsim.freight.carriers.mobsim.StrategyManagerFactoryForTests; import org.matsim.testcases.MatsimTestUtils; +import java.nio.file.Path; + public class EquilWithCarrierWithPersonsIT { private Controler controler; @@ -81,7 +83,7 @@ static Scenario commonScenario( Config config, MatsimTestUtils testUtils ){ Scenario scenario = ScenarioUtils.loadScenario( config ); CarrierVehicleTypes carrierVehicleTypes = new CarrierVehicleTypes(); - new CarrierVehicleTypeReader( carrierVehicleTypes ).readFile( testUtils.getPackageInputDirectory() + "vehicleTypes_v2.xml" ); + new CarrierVehicleTypeReader( carrierVehicleTypes ).readFile(Path.of(testUtils.getPackageInputDirectory()).getParent().resolve("vehicleTypes_v2.xml").toString()); Carriers carriers = CarriersUtils.addOrGetCarriers(scenario ); new CarrierPlanXmlReader( carriers, carrierVehicleTypes ).readFile( testUtils.getClassInputDirectory() + "carrierPlansEquils.xml" ); 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/controller/EquilWithCarrierWithoutPersonsIT.java similarity index 99% rename from contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT.java rename to contribs/freight/src/test/java/org/matsim/freight/carriers/controller/EquilWithCarrierWithoutPersonsIT.java index 70b01111b10..d106530ef27 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/controller/EquilWithCarrierWithoutPersonsIT.java @@ -19,7 +19,7 @@ * */ -package org.matsim.freight.carriers.controler; +package org.matsim.freight.carriers.controller; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -33,9 +33,9 @@ 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; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.CarriersUtils; +import org.matsim.freight.carriers.FreightCarriersConfigGroup; import org.matsim.freight.carriers.ScheduledTour; import org.matsim.freight.carriers.Tour; import org.matsim.freight.carriers.mobsim.DistanceScoringFunctionFactoryForTests; diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/DistanceConstraintFromVehiclesFileTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/DistanceConstraintFromVehiclesFileTest.java index 43abc654497..b9c2cbaa909 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/DistanceConstraintFromVehiclesFileTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/DistanceConstraintFromVehiclesFileTest.java @@ -21,6 +21,10 @@ package org.matsim.freight.carriers.jsprit; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.Assertions; @@ -39,18 +43,13 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.freight.carriers.*; -import org.matsim.freight.carriers.FreightCarriersConfigGroup.UseDistanceConstraintForTourPlanning; import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.carriers.FreightCarriersConfigGroup.UseDistanceConstraintForTourPlanning; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.VehicleType; import org.matsim.vehicles.VehicleUtils; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutionException; - /** * * @author rewert, kturner diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/DistanceConstraintTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/DistanceConstraintTest.java index 50b8505cb70..6df599915f9 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/DistanceConstraintTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/DistanceConstraintTest.java @@ -21,6 +21,10 @@ package org.matsim.freight.carriers.jsprit; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.Assertions; @@ -39,18 +43,13 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.freight.carriers.*; -import org.matsim.freight.carriers.FreightCarriersConfigGroup.UseDistanceConstraintForTourPlanning; import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.carriers.FreightCarriersConfigGroup.UseDistanceConstraintForTourPlanning; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.VehicleType; import org.matsim.vehicles.VehicleUtils; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutionException; - /** * * @author rewert, kturner @@ -372,7 +371,7 @@ final void CarrierWithAdditionalDieselVehicleTest_Version4() throws ExecutionExc VehicleType vehicleType_Diesel = VehicleUtils.createVehicleType(Id.create("DieselVehicle", VehicleType.class)); vehicleType_Diesel.getCostInformation().setCostsPerMeter(0.00055).setCostsPerSecond(0.008).setFixedCost(400.); VehicleUtils.setHbefaTechnology(vehicleType_Diesel.getEngineInformation(), "diesel"); - VehicleUtils.setFuelConsumption(vehicleType_Diesel, 0.0001625); + VehicleUtils.setFuelConsumptionLitersPerMeter(vehicleType_Diesel.getEngineInformation(), 0.0001625); vehicleType_Diesel.setDescription("Carrier_Version4"); vehicleType_Diesel.getCapacity().setOther(40.); @@ -711,7 +710,5 @@ private static void defineCarriers(Carriers carriers, FleetSize fleetSize, Carri CarriersUtils.addCarrierVehicle(singleCarrier, carrierVehicle); } singleCarrier.getCarrierCapabilities().getVehicleTypes().addAll(vehicleTypes.getVehicleTypes().values()); - - new CarrierVehicleTypeLoader(carriers).loadVehicleTypes(vehicleTypes); } } diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/FixedCostsTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/FixedCostsTest.java index 7e0e4bbe12e..cf5060bf772 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/FixedCostsTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/FixedCostsTest.java @@ -27,10 +27,12 @@ import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem; import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution; import com.graphhopper.jsprit.core.util.Solutions; +import java.net.URL; +import java.util.Collection; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Id; @@ -46,10 +48,6 @@ import org.matsim.vehicles.VehicleType; import org.matsim.vehicles.VehicleUtils; -import java.net.URL; -import java.util.Collection; - - /** * @author kturner * @@ -91,8 +89,8 @@ public void setUp() { VehicleType carrierVehType_A = VehicleUtils.getFactory().createVehicleType( vehicleTypeId ); { EngineInformation engineInformation1 = carrierVehType_A.getEngineInformation(); - engineInformation1.setFuelType( EngineInformation.FuelType.diesel ); - engineInformation1.setFuelConsumption( 0.015 ); + VehicleUtils.setFuelConsumptionLitersPerMeter(carrierVehType_A.getEngineInformation(), 0.015); + VehicleUtils.setHbefaTechnology(engineInformation1, "diesel"); carrierVehType_A.getCapacity().setOther( 1. ); carrierVehType_A.getCostInformation().setFixedCost( 0. ).setCostsPerMeter( 0.001 ).setCostsPerSecond( 0.0 ); carrierVehType_A.setMaximumVelocity( 10 ); @@ -106,8 +104,8 @@ public void setUp() { VehicleType carrierVehType_B = VehicleUtils.getFactory().createVehicleType( vehicleTypeId1 ); { EngineInformation engineInformation = carrierVehType_B.getEngineInformation(); - engineInformation.setFuelType( EngineInformation.FuelType.diesel ); - engineInformation.setFuelConsumption( 0.015 ); + VehicleUtils.setFuelConsumptionLitersPerMeter(carrierVehType_A.getEngineInformation(), 0.015); + VehicleUtils.setHbefaTechnology(engineInformation, "diesel"); carrierVehType_B.getCapacity().setOther( 1. ); carrierVehType_B.getCostInformation().setFixedCost( 10. ).setCostsPerMeter( 0.00001 ).setCostsPerSecond( 0. ) ; carrierVehType_B.setMaximumVelocity( 10. ); @@ -118,7 +116,6 @@ public void setUp() { //carrier1: only vehicles of Type A (no fixed costs, variable costs: 1 EUR/km) CarrierCapabilities cc1 = CarrierCapabilities.Builder.newInstance() - .addType(carrierVehType_A) .addVehicle(carrierVehicle_A) .setFleetSize(CarrierCapabilities.FleetSize.INFINITE) .build(); @@ -127,7 +124,6 @@ public void setUp() { //carrier2: only vehicles of Type B (fixed costs of 10 EUR/vehicle, no variable costs) CarrierCapabilities cc2 = CarrierCapabilities.Builder.newInstance() - .addType(carrierVehType_B) .addVehicle(carrierVehicle_B) .setFleetSize(CarrierCapabilities.FleetSize.INFINITE) .build(); @@ -136,8 +132,6 @@ public void setUp() { //carrier3: has both vehicles of Type A (no fixed costs, variable costs: 1 EUR/km) and Type B (fixed costs of 10 EUR/vehicle, no variable costs) CarrierCapabilities cc3 = CarrierCapabilities.Builder.newInstance() - .addType(carrierVehType_A) - .addType(carrierVehType_B) .addVehicle(carrierVehicle_A) .addVehicle(carrierVehicle_B) .setFleetSize(CarrierCapabilities.FleetSize.INFINITE) @@ -145,10 +139,6 @@ public void setUp() { carrier3.setCarrierCapabilities(cc3); carriers.addCarrier(carrier3); - - // assign vehicle types to the carriers - new CarrierVehicleTypeLoader(carriers).loadVehicleTypes(vehicleTypes) ; - //load Network and build netbasedCosts for jsprit URL context = org.matsim.examples.ExamplesUtils.getTestScenarioURL( "freight-chessboard-9x9" ); diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/IntegrationIT.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/IntegrationIT.java index 762a2efe08a..6c61511a480 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/IntegrationIT.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/IntegrationIT.java @@ -27,6 +27,8 @@ import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution; import com.graphhopper.jsprit.core.reporting.SolutionPrinter; import com.graphhopper.jsprit.core.util.Solutions; +import java.nio.file.Path; +import java.util.concurrent.ExecutionException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -41,8 +43,6 @@ import org.matsim.freight.carriers.jsprit.NetworkBasedTransportCosts.Builder; import org.matsim.testcases.MatsimTestUtils; -import java.util.concurrent.ExecutionException; - public class IntegrationIT { @RegisterExtension @@ -51,7 +51,7 @@ public class IntegrationIT { @Test void testJsprit() throws ExecutionException, InterruptedException { final String networkFilename = utils.getClassInputDirectory() + "/merged-network-simplified.xml.gz"; - final String vehicleTypeFilename = utils.getClassInputDirectory() + "/vehicleTypes.xml"; + final String vehicleTypeFilename = Path.of(utils.getPackageInputDirectory()).getParent().resolve("vehicleTypes_v2.xml").toString(); final String carrierFilename = utils.getClassInputDirectory() + "/carrier.xml"; Config config = ConfigUtils.createConfig(); @@ -99,7 +99,7 @@ void testJsprit() throws ExecutionException, InterruptedException { @Test void testJspritWithDefaultSolutionOption() throws ExecutionException, InterruptedException { final String networkFilename = utils.getClassInputDirectory() + "/merged-network-simplified.xml.gz"; - final String vehicleTypeFilename = utils.getClassInputDirectory() + "/vehicleTypes.xml"; + final String vehicleTypeFilename = Path.of(utils.getPackageInputDirectory()).getParent().resolve("vehicleTypes_v2.xml").toString(); final String carrierFilename = utils.getClassInputDirectory() + "/carrier.xml"; Config config = ConfigUtils.createConfig(); diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/MatsimTransformerTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/MatsimTransformerTest.java index 15f7a1a7c86..5025334cc5e 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/MatsimTransformerTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/MatsimTransformerTest.java @@ -21,6 +21,8 @@ package org.matsim.freight.carriers.jsprit; +import static org.junit.jupiter.api.Assertions.*; + import com.graphhopper.jsprit.core.problem.Location; import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem; import com.graphhopper.jsprit.core.problem.job.Job; @@ -31,6 +33,9 @@ import com.graphhopper.jsprit.core.problem.vehicle.Vehicle; import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl; import com.graphhopper.jsprit.core.problem.vehicle.VehicleTypeImpl; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Id; @@ -44,12 +49,6 @@ import org.matsim.vehicles.VehicleType; import org.matsim.vehicles.VehicleUtils; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - public class MatsimTransformerTest { @RegisterExtension @@ -340,7 +339,7 @@ private ScheduledTour getMatsimServiceTour() { .setCapacityDemand(10).build(); CarrierVehicle matsimVehicle = getMatsimVehicle("matsimVehicle", "loc", getMatsimVehicleType()); double startTime = 15.0; - Tour.Builder sTourBuilder = Tour.Builder.newInstance(); + Tour.Builder sTourBuilder = Tour.Builder.newInstance(Id.create("testTour", Tour.class)); sTourBuilder.scheduleStart(matsimVehicle.getLinkId() ); sTourBuilder.addLeg(sTourBuilder.createLeg(null, 15.0, 0.0)); sTourBuilder.scheduleService(s1); @@ -356,7 +355,7 @@ private ScheduledTour getMatsimTour(String vehicleId) { CarrierShipment s2 = getMatsimShipment("s2", "from", "to2", 20); CarrierVehicle matsimVehicle = getMatsimVehicle(vehicleId, "loc", getMatsimVehicleType()); double startTime = 15.0; - Tour.Builder sTourBuilder = Tour.Builder.newInstance(); + Tour.Builder sTourBuilder = Tour.Builder.newInstance(Id.create("testTour", Tour.class)); sTourBuilder.scheduleStart(matsimVehicle.getLinkId() ); sTourBuilder.addLeg(sTourBuilder.createLeg(null, 15.0, 0.0)); sTourBuilder.schedulePickup(s1); @@ -378,18 +377,13 @@ private CarrierVehicle getMatsimVehicle(String VehicleId, String locationId, Veh } private VehicleType getMatsimVehicleType() { -// EngineInformation engineInformation = new EngineInformation(); -// engineInformation.setFuelType( FuelType.diesel ); -// engineInformation.setFuelConsumption( (double) 15 ); -// CarriersUtils.CarrierVehicleTypeBuilder builder = CarriersUtils.CarrierVehicleTypeBuilder.newInstance( Id.create( "matsimType", VehicleType.class ) ) VehicleType vehicleType = VehicleUtils.getFactory() .createVehicleType(Id.create("matsimType", VehicleType.class)).setMaximumVelocity(13.8); vehicleType.getCapacity().setOther(50); vehicleType.getCostInformation().setCostsPerMeter(10.0).setCostsPerSecond(5.0).setFixedCost(100.); VehicleUtils.setHbefaTechnology(vehicleType.getEngineInformation(), "diesel"); - VehicleUtils.setFuelConsumption(vehicleType, 15.); -// vehicleType.getEngineInformation().setFuelType( FuelType.diesel ) ; -// vehicleType.getEngineInformation().setFuelConsumption( 15. ); + VehicleUtils.setFuelConsumptionLitersPerMeter(vehicleType.getEngineInformation(), 0.015); + return vehicleType; } @@ -422,8 +416,8 @@ void createVehicleRoutingProblemBuilderWithServices_isMadeCorrectly() { assertEquals(10.0, vehicle.getType().getVehicleCostParams().perDistanceUnit, 0.0); assertEquals(5.0, vehicle.getType().getVehicleCostParams().perTransportTimeUnit, 0.0); assertEquals(100.0, vehicle.getType().getVehicleCostParams().fix, 0.0); - // assertEquals(FuelType.diesel, vehicle. ...); //TODO - // assertEquals(15, FuelConsumption ...); //TODO + assertEquals("diesel", VehicleUtils.getHbefaTechnology(((VehicleType)vehicle.getType().getUserData()).getEngineInformation())); + assertEquals(0.015, VehicleUtils.getFuelConsumptionLitersPerMeter(((VehicleType)vehicle.getType().getUserData()).getEngineInformation())); assertEquals(13.8, vehicle.getType().getMaxVelocity(), 0.0); // check service data 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 64e7eeba641..d58cadf388a 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 @@ -21,9 +21,13 @@ package org.matsim.freight.carriers.jsprit; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import com.graphhopper.jsprit.core.problem.Location; import com.graphhopper.jsprit.core.problem.driver.Driver; import com.graphhopper.jsprit.core.problem.vehicle.Vehicle; +import java.util.Arrays; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -43,12 +47,6 @@ import org.matsim.vehicles.VehicleUtils; import org.matsim.vehicles.VehiclesFactory; -import java.util.Arrays; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - - public class NetworkBasedTransportCostsTest { diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/SkillsIT.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/SkillsIT.java index 8886010e74b..7da556872c2 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/SkillsIT.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/SkillsIT.java @@ -127,7 +127,6 @@ private Scenario setupTestScenario() { // typeOne.setCapacity(vehicleCapacity); typeOne.getCapacity().setOther( 2.0 ); CarriersUtils.addSkill(typeOne, "skill 1"); - capabilitiesBuilder.addType(typeOne); CarrierVehicle vehicleOne = CarrierVehicle.Builder.newInstance(Id.createVehicleId("1"), carrierLocation, typeOne ) .setEarliestStart(0.0) .setLatestEnd(Time.parseTime("24:00:00")) @@ -141,7 +140,6 @@ private Scenario setupTestScenario() { // typeTwo.setCapacity(vehicleCapacity); typeTwo.getCapacity().setOther( 2.0 ); CarriersUtils.addSkill(typeTwo, "skill 2"); - capabilitiesBuilder.addType(typeTwo); CarrierVehicle vehicleTwo = CarrierVehicle.Builder.newInstance(Id.createVehicleId("2"), carrierLocation, typeTwo ) .setEarliestStart(0.0) .setLatestEnd(Time.parseTime("24:00:00")) diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/mobsim/DistanceScoringFunctionFactoryForTests.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/mobsim/DistanceScoringFunctionFactoryForTests.java index 81ad7c6e577..89bec08003a 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/mobsim/DistanceScoringFunctionFactoryForTests.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/mobsim/DistanceScoringFunctionFactoryForTests.java @@ -22,6 +22,8 @@ package org.matsim.freight.carriers.mobsim; import jakarta.inject.Inject; +import java.util.HashSet; +import java.util.Set; import org.junit.jupiter.api.Disabled; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; @@ -38,14 +40,11 @@ import org.matsim.deprecated.scoring.ScoringFunctionAccumulator.LegScoring; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.CarrierConstants; -import org.matsim.freight.carriers.CarriersUtils; import org.matsim.freight.carriers.CarrierVehicle; -import org.matsim.freight.carriers.controler.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.CarriersUtils; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; import org.matsim.vehicles.Vehicle; -import java.util.HashSet; -import java.util.Set; - @Disabled public class DistanceScoringFunctionFactoryForTests implements CarrierScoringFunctionFactory{ diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/mobsim/ScoringFunctionFactoryForTests.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/mobsim/ScoringFunctionFactoryForTests.java index 68dbf0bc7ab..87e50dacbe5 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/mobsim/ScoringFunctionFactoryForTests.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/mobsim/ScoringFunctionFactoryForTests.java @@ -21,6 +21,8 @@ package org.matsim.freight.carriers.mobsim; +import java.util.HashSet; +import java.util.Set; import org.junit.jupiter.api.Disabled; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; @@ -37,14 +39,11 @@ import org.matsim.deprecated.scoring.ScoringFunctionAccumulator.LegScoring; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.CarrierConstants; -import org.matsim.freight.carriers.CarriersUtils; import org.matsim.freight.carriers.CarrierVehicle; -import org.matsim.freight.carriers.controler.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.CarriersUtils; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; import org.matsim.vehicles.Vehicle; -import java.util.HashSet; -import java.util.Set; - @Disabled public class ScoringFunctionFactoryForTests implements CarrierScoringFunctionFactory{ diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/mobsim/StrategyManagerFactoryForTests.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/mobsim/StrategyManagerFactoryForTests.java index 680ef4e1953..c61519ea613 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/mobsim/StrategyManagerFactoryForTests.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/mobsim/StrategyManagerFactoryForTests.java @@ -23,6 +23,7 @@ import com.google.inject.Provider; import jakarta.inject.Inject; +import java.util.Map; import org.junit.jupiter.api.Disabled; import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.network.Link; @@ -36,13 +37,11 @@ import org.matsim.core.router.util.TravelTime; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.CarrierPlan; -import org.matsim.freight.carriers.controler.CarrierReRouteVehicles; -import org.matsim.freight.carriers.controler.CarrierStrategyManager; -import org.matsim.freight.carriers.controler.CarrierControlerUtils; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierReRouteVehicles; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; import org.matsim.vehicles.Vehicle; -import java.util.Map; - @Disabled public class StrategyManagerFactoryForTests implements Provider{ @@ -83,7 +82,7 @@ public CarrierStrategyManager get() { GenericPlanStrategyImpl planStrat_reRoutePlan = new GenericPlanStrategyImpl<>( new BestPlanSelector<>() ); planStrat_reRoutePlan.addStrategyModule(new CarrierReRouteVehicles.Factory(router, network, travelTimes.get(TransportMode.car )).build() ); - CarrierStrategyManager stratManager = CarrierControlerUtils.createDefaultCarrierStrategyManager(); + CarrierStrategyManager stratManager = CarrierControllerUtils.createDefaultCarrierStrategyManager(); stratManager.addStrategy(planStrat_reRoutePlan, null, 1.0); diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/mobsim/TimeScoringFunctionFactoryForTests.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/mobsim/TimeScoringFunctionFactoryForTests.java index a8cc127ba93..3b3f8965acf 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/mobsim/TimeScoringFunctionFactoryForTests.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/mobsim/TimeScoringFunctionFactoryForTests.java @@ -22,6 +22,8 @@ package org.matsim.freight.carriers.mobsim; import jakarta.inject.Inject; +import java.util.HashSet; +import java.util.Set; import org.junit.jupiter.api.Disabled; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; @@ -38,14 +40,11 @@ import org.matsim.deprecated.scoring.ScoringFunctionAccumulator.LegScoring; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.CarrierConstants; -import org.matsim.freight.carriers.CarriersUtils; import org.matsim.freight.carriers.CarrierVehicle; -import org.matsim.freight.carriers.controler.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.CarriersUtils; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; import org.matsim.vehicles.Vehicle; -import java.util.HashSet; -import java.util.Set; - @Disabled public class TimeScoringFunctionFactoryForTests implements CarrierScoringFunctionFactory{ diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/utils/CarrierControlerUtilsIT.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/utils/CarrierControllerUtilsIT.java similarity index 97% rename from contribs/freight/src/test/java/org/matsim/freight/carriers/utils/CarrierControlerUtilsIT.java rename to contribs/freight/src/test/java/org/matsim/freight/carriers/utils/CarrierControllerUtilsIT.java index 19b550dda95..28314c1a817 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/utils/CarrierControlerUtilsIT.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/utils/CarrierControllerUtilsIT.java @@ -26,8 +26,9 @@ import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem; import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution; import com.graphhopper.jsprit.core.util.Solutions; -import org.junit.jupiter.api.BeforeEach; +import java.util.Collection; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Id; @@ -45,15 +46,12 @@ import org.matsim.vehicles.*; import org.matsim.vehicles.EngineInformation.FuelType; -import java.util.Collection; - - //TODO: length of routes (legs) AND end time of route are missing. /** * @author kturner * */ -public class CarrierControlerUtilsIT { +public class CarrierControllerUtilsIT{ private final Id CARRIER_SERVICES_ID = Id.create("CarrierWServices", Carrier.class); private final Id CARRIER_SHIPMENTS_ID = Id.create("CarrierWShipments", Carrier.class); @@ -89,8 +87,8 @@ public void setUp() { final Id vehTypeId = Id.create( "gridType", VehicleType.class ); VehicleType carrierVehType = VehicleUtils.getFactory().createVehicleType( vehTypeId ); EngineInformation engineInformation = carrierVehType.getEngineInformation() ; - engineInformation.setFuelType( FuelType.diesel ); - engineInformation.setFuelConsumption( 0.015 ); + VehicleUtils.setHbefaTechnology(engineInformation, "diesel"); + VehicleUtils.setFuelConsumptionLitersPerMeter(engineInformation, 0.015); VehicleCapacity capacity = carrierVehType.getCapacity() ; capacity.setOther( 3. ) ; CostInformation costInfo = carrierVehType.getCostInformation(); @@ -106,7 +104,6 @@ public void setUp() { CarrierVehicle carrierVehicle = CarrierVehicle.Builder.newInstance(Id.create("gridVehicle", org.matsim.vehicles.Vehicle.class), Id.createLinkId("i(6,0)"), carrierVehType ).setEarliestStart(0.0 ).setLatestEnd(36000.0 ).build(); CarrierCapabilities.Builder ccBuilder = CarrierCapabilities.Builder.newInstance() - .addType(carrierVehType) .addVehicle(carrierVehicle) .setFleetSize(FleetSize.INFINITE); carrierWServices.setCarrierCapabilities(ccBuilder.build()); @@ -116,9 +113,6 @@ public void setUp() { carriersWithServicesAndShpiments.addCarrier(carrierWServices); carriersWithServicesAndShpiments.addCarrier(carrierWShipments); - // assign vehicle types to the carriers - new CarrierVehicleTypeLoader(carriersWithServicesAndShpiments).loadVehicleTypes(vehicleTypes) ; - //load Network and build netbasedCosts for jsprit Network network = NetworkUtils.createNetwork(); new MatsimNetworkReader(network).readFile(testUtils.getPackageInputDirectory() + "grid-network.xml"); @@ -151,9 +145,6 @@ public void setUp() { Carriers carriersWithShipmentsOnly = CarriersUtils.createShipmentVRPCarrierFromServiceVRPSolution( carriersWithServicesAndShpiments ); - // assign vehicle types to the carriers - new CarrierVehicleTypeLoader(carriersWithShipmentsOnly).loadVehicleTypes(vehicleTypes) ; - for (Carrier carrier : carriersWithShipmentsOnly.getCarriers().values()) { //Build VRP VehicleRoutingProblem.Builder vrpBuilder = MatsimJspritFactory.createRoutingProblemBuilder(carrier, network); diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/utils/CarrierControlerUtilsTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/utils/CarrierControllerUtilsTest.java similarity index 97% rename from contribs/freight/src/test/java/org/matsim/freight/carriers/utils/CarrierControlerUtilsTest.java rename to contribs/freight/src/test/java/org/matsim/freight/carriers/utils/CarrierControllerUtilsTest.java index a494355934c..f4c95c5bd13 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/utils/CarrierControlerUtilsTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/utils/CarrierControllerUtilsTest.java @@ -28,10 +28,12 @@ import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem; import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution; import com.graphhopper.jsprit.core.util.Solutions; +import java.net.URL; +import java.util.Collection; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Id; @@ -41,7 +43,8 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.PlansConfigGroup; -import org.matsim.core.controler.Controler; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; import org.matsim.core.network.NetworkUtils; import org.matsim.core.network.io.MatsimNetworkReader; import org.matsim.core.scenario.ScenarioUtils; @@ -56,15 +59,12 @@ import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.*; -import java.net.URL; -import java.util.Collection; - -public class CarrierControlerUtilsTest { +public class CarrierControllerUtilsTest{ @RegisterExtension private MatsimTestUtils utils = new MatsimTestUtils(); - private static final Logger log = LogManager.getLogger(CarrierControlerUtilsTest.class); + private static final Logger log = LogManager.getLogger( CarrierControllerUtilsTest.class ); private final Id CARRIER_SERVICES_ID = Id.create("CarrierWServices", Carrier.class); private final Id CARRIER_SHIPMENTS_ID = Id.create("CarrierWShipments", Carrier.class); @@ -100,7 +100,7 @@ public void setUp() { final Id vehicleTypeId = Id.create( "gridType", VehicleType.class ); VehicleType carrierVehType = VehicleUtils.getFactory().createVehicleType( vehicleTypeId ); VehicleUtils.setHbefaTechnology(carrierVehType.getEngineInformation(), "diesel"); - VehicleUtils.setFuelConsumption(carrierVehType, 0.015); + VehicleUtils.setFuelConsumptionLitersPerMeter(carrierVehType.getEngineInformation(), 0.015); VehicleCapacity vehicleCapacity = carrierVehType.getCapacity(); vehicleCapacity.setOther( 3 ); CostInformation costInfo = carrierVehType.getCostInformation(); @@ -115,7 +115,6 @@ public void setUp() { CarrierVehicle carrierVehicle = CarrierVehicle.Builder.newInstance(Id.create("gridVehicle", org.matsim.vehicles.Vehicle.class), Id.createLinkId("i(6,0)"), carrierVehType ).setEarliestStart(0.0 ).setLatestEnd(36000.0 ).build(); CarrierCapabilities.Builder ccBuilder = CarrierCapabilities.Builder.newInstance() - .addType(carrierVehType) .addVehicle(carrierVehicle) .setFleetSize(FleetSize.INFINITE); carrierWServices.setCarrierCapabilities(ccBuilder.build()); @@ -125,9 +124,6 @@ public void setUp() { carriersWithServicesAndShpiments.addCarrier(carrierWServices); carriersWithServicesAndShpiments.addCarrier(carrierWShipments); - // assign vehicle types to the carriers - new CarrierVehicleTypeLoader(carriersWithServicesAndShpiments).loadVehicleTypes(vehicleTypes) ; - //load Network and build netbasedCosts for jsprit Network network = NetworkUtils.createNetwork(); new MatsimNetworkReader(network).readFile(testUtils.getPackageInputDirectory() + "grid-network.xml"); @@ -159,9 +155,6 @@ public void setUp() { Carriers carriersWithShipmentsOnly = CarriersUtils.createShipmentVRPCarrierFromServiceVRPSolution(carriersWithServicesAndShpiments); carrierWShipmentsOnlyFromCarrierWServices = carriersWithShipmentsOnly.getCarriers().get(CARRIER_SERVICES_ID); //with converted Service carrierWShipmentsOnlyFromCarrierWShipments = carriersWithShipmentsOnly.getCarriers().get(CARRIER_SHIPMENTS_ID); //with copied Shipments - - // assign vehicle types to the carriers - new CarrierVehicleTypeLoader(carriersWithShipmentsOnly).loadVehicleTypes(vehicleTypes) ; } @@ -227,7 +220,7 @@ void fleetAvailableAfterConvertingIsCorrect() { Assertions.assertEquals(0.001, carrierVehicleType.getCostInformation().getCostsPerSecond(), 0.0 ); Assertions.assertEquals(10, carrierVehicleType.getMaximumVelocity(), 0.0); Assertions.assertEquals("diesel", VehicleUtils.getHbefaTechnology(carrierVehicleType.getEngineInformation())); - Assertions.assertEquals(0.015, VehicleUtils.getFuelConsumption(carrierVehicleType), 0.0); + Assertions.assertEquals(0.015, VehicleUtils.getFuelConsumptionLitersPerMeter(carrierVehicleType.getEngineInformation()), 0.0); } Assertions.assertEquals(FleetSize.INFINITE, carrierWShipmentsOnlyFromCarrierWShipments.getCarrierCapabilities().getFleetSize()); @@ -239,7 +232,7 @@ void fleetAvailableAfterConvertingIsCorrect() { Assertions.assertEquals(0.001, carrierVehicleType.getCostInformation().getCostsPerSecond(), 0.0 ); Assertions.assertEquals(10, carrierVehicleType.getMaximumVelocity(), 0.0); Assertions.assertEquals("diesel", VehicleUtils.getHbefaTechnology(carrierVehicleType.getEngineInformation())); - Assertions.assertEquals(0.015, VehicleUtils.getFuelConsumption(carrierVehicleType), 0.0); } + Assertions.assertEquals(0.015, VehicleUtils.getFuelConsumptionLitersPerMeter(carrierVehicleType.getEngineInformation()), 0.0); } } @Test @@ -426,7 +419,7 @@ void testRunJsprit_allInformationGiven(){ Scenario scenario = ScenarioUtils.loadScenario(config); CarriersUtils.loadCarriersAccordingToFreightConfig(scenario ); - Controler controler = new Controler(scenario); + Controller controller = ControllerUtils.createController(scenario); try { CarriersUtils.runJsprit(scenario); @@ -435,7 +428,7 @@ void testRunJsprit_allInformationGiven(){ Assertions.fail(); } - Assertions.assertEquals(vraFile, ConfigUtils.addOrGetModule( controler.getConfig(), FreightCarriersConfigGroup.class ).getVehicleRoutingAlgorithmFile()); + Assertions.assertEquals(vraFile, ConfigUtils.addOrGetModule( controller.getConfig(), FreightCarriersConfigGroup.class ).getVehicleRoutingAlgorithmFile()); } /** diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/Doxyfile b/contribs/freight/src/test/java/org/matsim/freight/logistics/Doxyfile new file mode 100644 index 00000000000..1b91b479d8e --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/Doxyfile @@ -0,0 +1,2526 @@ +# Doxyfile 1.8.18 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = dfg-freight + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = /Users/kainagel/doxygen-html/dfg-freight + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = YES + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = org/matsim + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = YES + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 0 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = YES + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# declarations. If set to NO, these declarations will be included in the +# documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# (including Cygwin) ands Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = YES + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = YES + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = NO + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = NO + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = lsp + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), +# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen +# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, +# *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.java + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = */jaxb/* + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = /Users/kainagel/git/all-matsim/freight-dfg17/src/main/java/doxyfilter.sh + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = YES + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = YES + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files +# were built. This is equivalent to specifying the "-p" option to a clang tool, +# such as clang-check. These options will then be passed to the parser. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 1 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = /Users/nagel/doxygen-html/matsim + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: https://developer.apple.com/xcode/), introduced with OSX +# 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 400 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png The default and svg Looks nicer but requires the +# pdf2svg tool. +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /

+ * This class here is in contrast used as a Replanning strategy. This behavior is not wanted anymore. + *

+ * Please use the new Approach as shown in + * org.matsim.freight.logistics.example.lsp.multipleChains.ExampleMultipleOneEchelonChainsReplanning instead. + *

+ * * KMT, Jul'24 + */ +@Deprecated +public class CollectionLSPReplanningTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + + private LSP collectionLSP; + + @BeforeEach + public void initialize() { + + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + Id carrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50/3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Link collectionLink = network.getLinks().get(collectionLinkId); + if (collectionLink == null) { + System.exit(1); + } + CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(Id.createVehicleId("CollectionVehicle"), collectionLink.getId(), collectionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(carrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities capabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + + Id.create("CollectionCarrierResource", LSPResource.class); + CollectionCarrierResourceBuilder adapterBuilder = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(carrier); + adapterBuilder.setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)); + adapterBuilder.setLocationLinkId(collectionLinkId); + LSPResource collectionResource = adapterBuilder.build(); + + Id elementId = Id.create("CollectionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder collectionElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(elementId); + collectionElementBuilder.setResource(collectionResource); + LogisticChainElement collectionElement = collectionElementBuilder.build(); + + Id collectionSolutionId = Id.create("CollectionSolution", LogisticChain.class); + LSPUtils.LogisticChainBuilder collectionSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(collectionSolutionId); + collectionSolutionBuilder.addLogisticChainElement(collectionElement); + LogisticChain collectionSolution = collectionSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan collectionPlan = LSPUtils.createLSPPlan(); + collectionPlan.setInitialShipmentAssigner(assigner); + collectionPlan.addLogisticChain(collectionSolution); + + LSPUtils.LSPBuilder collectionLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + collectionLSPBuilder.setInitialPlan(collectionPlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + collectionLSPBuilder.setLogisticChainScheduler(simpleScheduler); + collectionLSP = collectionLSPBuilder.build(); + + + List linkList = new LinkedList<>(network.getLinks().values()); + + + for (int i = 1; i < 21; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + Random random = new Random(1); + int capacityDemand = random.nextInt(10); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, random); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + builder.setToLinkId(collectionLinkId); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + collectionLSP.assignShipmentToLSP(shipment); + } + collectionLSP.scheduleLogisticChains(); + + +// ShipmentAssigner maybeTodayAssigner = new MaybeTodayAssigner(); +// maybeTodayAssigner.setLSP(collectionLSP); +// final GenericPlanStrategy strategy = new TomorrowShipmentAssignerStrategyFactory(maybeTodayAssigner).createStrategy(); +// +// GenericStrategyManager strategyManager = new GenericStrategyManagerImpl<>(); +// strategyManager.addStrategy(strategy, null, 1); +// +// LSPReplanner replanner = LSPReplanningUtils.createDefaultLSPReplanner(strategyManager); +// +// +// collectionLSP.setReplanner(replanner); + + + LSPUtils.addLSPs(scenario, new LSPs(Collections.singletonList(collectionLSP))); + + Controller controller = ControllerUtils.createController(scenario); + + controller.addOverridingModule(new LSPModule() ); + + controller.addOverridingModule(new AbstractModule(){ + @Override public void install(){ + bind( LSPStrategyManager.class ).toProvider(() -> { + LSPStrategyManager manager = new LSPStrategyManagerImpl(); + { + final GenericPlanStrategy strategy = new TomorrowShipmentAssignerStrategyFactory(new MaybeTodayAssigner()).createStrategy(); + // (a factory makes sense if it is passed around; in this case it feels like overkill. kai, jul'22) + manager.addStrategy( strategy, null, 1 ); + } + return manager; + }); + + bind( CarrierStrategyManager.class ).toProvider(() -> { + CarrierStrategyManager strategyManager = CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new RandomPlanSelector<>()), null, 1); + return strategyManager; + }); + } + } ); + + config.controller().setFirstIteration(0); + config.controller().setLastIteration(1); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } + + + + @Test + public void testCollectionLSPReplanning() { + System.out.println(collectionLSP.getSelectedPlan().getLogisticChains().iterator().next().getLspShipmentIds().size()); + assertTrue(collectionLSP.getSelectedPlan().getLogisticChains().iterator().next().getLspShipmentIds().size() < 20); + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/lspScoring/CollectionLSPScoringTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/lspScoring/CollectionLSPScoringTest.java new file mode 100644 index 00000000000..acfb73567df --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/lspScoring/CollectionLSPScoringTest.java @@ -0,0 +1,198 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.lspScoring; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler; +import static org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner; + +import java.util.*; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class CollectionLSPScoringTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private final int numberOfShipments = 25; + private LSP collectionLSP; + + @BeforeEach + public void initialize() { + Config config = ConfigUtils.createConfig(); + config.network().setInputFile("scenarios/2regions/2regions-network.xml"); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.loadScenario(config); + Network network = scenario.getNetwork(); + + + VehicleType collectionVehType = VehicleUtils.createVehicleType(Id.create("CollectionCarrierVehicleType", VehicleType.class), TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + collectionVehType.setNetworkMode(TransportMode.car); + + + Link collectionLink = network.getLinks().get(Id.createLinkId("(4 2) (4 3)")); // (make sure that the link exists) + + CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(Id.createVehicleId("CollectionVehicle"), collectionLink.getId(), collectionVehType); + + Carrier carrier = CarriersUtils.createCarrier(Id.create("CollectionCarrier", Carrier.class)); + carrier.setCarrierCapabilities(CarrierCapabilities.Builder.newInstance() + .addVehicle(carrierVehicle) + .setFleetSize(FleetSize.INFINITE) + .build()); + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(carrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)).setLocationLinkId(collectionLink.getId()).build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder + .newInstance(Id.create("CollectionElement", LogisticChainElement.class)).setResource(collectionResource).build(); + + LogisticChain collectionSolution = LSPUtils.LogisticChainBuilder.newInstance(Id.create("CollectionSolution", LogisticChain.class)) + .addLogisticChainElement(collectionElement).build(); + + collectionLSP = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)) + .setInitialPlan(LSPUtils.createLSPPlan().setInitialShipmentAssigner(createSingleLogisticChainShipmentAssigner()).addLogisticChain(collectionSolution)) + .setLogisticChainScheduler(createDefaultSimpleForwardLogisticChainScheduler(Collections.singletonList(collectionResource))) +// .setSolutionScorer(new ExampleLSPScoring.TipScorer()) + .build(); + +// TipEventHandler handler = new TipEventHandler(); +// LSPAttribute value = LSPInfoFunctionUtils.createInfoFunctionValue("TIP IN EUR" ); +// LSPAttributes function = LSPInfoFunctionUtils.createDefaultInfoFunction(); +// function.getAttributes().add(value ); +// TipInfo info = new TipInfo(); +// TipScorer.TipSimulationTracker tipTracker = new TipScorer.TipSimulationTracker(); +// collectionResource.addSimulationTracker(tipTracker); +// TipScorer tipScorer = new TipScorer(); +// collectionLSP.addSimulationTracker( tipScorer ); +// collectionLSP.setScorer(tipScorer); + + List linkList = new LinkedList<>(network.getLinks().values()); + + for (int i = 1; i < (numberOfShipments + 1); i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + Random random = new Random(1); + int capacityDemand = random.nextInt(10); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, random); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 + && pendingFromLink.getFromNode().getCoord().getY() <= 4000 + && pendingFromLink.getToNode().getCoord().getX() <= 4000 + && pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + builder.setToLinkId(collectionLink.getId()); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + collectionLSP.assignShipmentToLSP(shipment); + } + + collectionLSP.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(collectionLSP); + LSPs lsps = new LSPs(lspList); + + LSPUtils.addLSPs(scenario, lsps); + + Controller controller = ControllerUtils.createController(scenario); + + controller.addOverridingModule( new LSPModule() ); + controller.addOverridingModule( new AbstractModule(){ + @Override public void install(){ + bind( LSPScorerFactory.class ).toInstance(ExampleLSPScoring.TipScorer::new); + } + }); + + config.controller().setFirstIteration(0); + config.controller().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } + + @Test + public void testCollectionLSPScoring() { + System.out.println(collectionLSP.getSelectedPlan().getScore()); + assertEquals(numberOfShipments, collectionLSP.getLspShipments().size()); + assertEquals(numberOfShipments, collectionLSP.getSelectedPlan().getLogisticChains().iterator().next().getLspShipmentIds() + .size()); + assertTrue(collectionLSP.getSelectedPlan().getScore() > 0); + assertTrue(collectionLSP.getSelectedPlan().getScore() <= (numberOfShipments * 5)); + /*noch zu testen + * tipTracker + * InfoFunction + * Info + * Scorer + */ + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/lspScoring/ExampleLSPScoringTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/lspScoring/ExampleLSPScoringTest.java new file mode 100644 index 00000000000..c6634e58239 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/lspScoring/ExampleLSPScoringTest.java @@ -0,0 +1,58 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.lspScoring; +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.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.Controller; +import org.matsim.freight.logistics.LSP; +import org.matsim.freight.logistics.LSPUtils; +import org.matsim.testcases.MatsimTestUtils; + +public class ExampleLSPScoringTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + + @Test + public void testMain() { + + Config config = ExampleLSPScoring.prepareConfig(); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + + Scenario scenario = ExampleLSPScoring.prepareScenario(config); + + Controller controller = ExampleLSPScoring.prepareController(scenario); + + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + for (LSP lsp : LSPUtils.getLSPs(scenario).getLSPs().values()) { + Assertions.assertEquals(13.245734044444207, lsp.getSelectedPlan().getScore(), Double.MIN_VALUE); + } + + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/lspScoring/MultipleIterationsCollectionLSPScoringTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/lspScoring/MultipleIterationsCollectionLSPScoringTest.java new file mode 100644 index 00000000000..e18204c2f99 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/lspScoring/MultipleIterationsCollectionLSPScoringTest.java @@ -0,0 +1,210 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.lspScoring; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.*; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.RandomPlanSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MultipleIterationsCollectionLSPScoringTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + + private final int numberOfShipments = 25; + private LSP collectionLSP; + + @BeforeEach + public void initialize() { + + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + Id carrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Link collectionLink = network.getLinks().get(collectionLinkId); + if (collectionLink == null) { + System.exit(1); + } + CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(Id.createVehicleId("CollectionVehicle"), collectionLink.getId(), collectionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(carrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities capabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(carrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + Id elementId = Id.create("CollectionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder collectionElementBuilder = LSPUtils.LogisticChainElementBuilder + .newInstance(elementId); + collectionElementBuilder.setResource(collectionResource); + LogisticChainElement collectionElement = collectionElementBuilder.build(); + + Id collectionSolutionId = Id.create("CollectionSolution", LogisticChain.class); + LSPUtils.LogisticChainBuilder collectionSolutionBuilder = LSPUtils.LogisticChainBuilder + .newInstance(collectionSolutionId); + collectionSolutionBuilder.addLogisticChainElement(collectionElement); + LogisticChain collectionSolution = collectionSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan collectionPlan = LSPUtils.createLSPPlan(); + collectionPlan.setInitialShipmentAssigner(assigner); + collectionPlan.addLogisticChain(collectionSolution); + + LSPUtils.LSPBuilder collectionLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + collectionLSPBuilder.setInitialPlan(collectionPlan); + List resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + collectionLSPBuilder.setLogisticChainScheduler(simpleScheduler); +// collectionLSPBuilder.setSolutionScorer(new ExampleLSPScoring.TipScorer()); + collectionLSP = collectionLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + + for (int i = 1; i < (numberOfShipments + 1); i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + Random random = new Random(1); + int capacityDemand = random.nextInt(10); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, random); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 + && pendingFromLink.getFromNode().getCoord().getY() <= 4000 + && pendingFromLink.getToNode().getCoord().getX() <= 4000 + && pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + builder.setToLinkId(collectionLinkId); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + collectionLSP.assignShipmentToLSP(shipment); + } + + collectionLSP.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(collectionLSP); + LSPs lsps = new LSPs(lspList); + + Controller controller = ControllerUtils.createController(scenario); + + LSPUtils.addLSPs(scenario, lsps); + controller.addOverridingModule( new LSPModule() ); + controller.addOverridingModule( new AbstractModule(){ + @Override public void install(){ + bind( LSPScorerFactory.class ).toInstance(ExampleLSPScoring.TipScorer::new); + bind( LSPStrategyManager.class ).toInstance( new LSPModule.LSPStrategyManagerEmptyImpl() ); + bind( CarrierStrategyManager.class ).toProvider(() -> { + CarrierStrategyManager strategyManager = CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new RandomPlanSelector<>()), null, 1); + return strategyManager; + }); + } + }); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(10); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } + + @Test + public void testCollectionLSPScoring() { + System.out.println("score=" + collectionLSP.getSelectedPlan().getScore()); + assertEquals(numberOfShipments, collectionLSP.getLspShipments().size()); + assertEquals(numberOfShipments, collectionLSP.getSelectedPlan().getLogisticChains().iterator().next().getLspShipmentIds().size()); + assertTrue(collectionLSP.getSelectedPlan().getScore() > 0); + assertTrue(collectionLSP.getSelectedPlan().getScore() <= (numberOfShipments * 5)); + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/mobsimExamples/ExampleMobsimOfSimpleLSPTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/mobsimExamples/ExampleMobsimOfSimpleLSPTest.java new file mode 100644 index 00000000000..8c50a3b20b3 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/mobsimExamples/ExampleMobsimOfSimpleLSPTest.java @@ -0,0 +1,55 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.mobsimExamples; + +import static org.junit.jupiter.api.Assertions.fail; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.testcases.MatsimTestUtils; + +/** + * @author Kai Martins-Turner (kturner) + */ +public class ExampleMobsimOfSimpleLSPTest { + private static final Logger log = LogManager.getLogger(ExampleMobsimOfSimpleLSPTest.class); + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + + @Test + public void testForRuntimeExceptionsAndCompareEvents() { + try { + ExampleMobsimOfSimpleLSP.main(new String[]{ + "--config:controller.outputDirectory=" + utils.getOutputDirectory() + }); + + } catch (Exception ee) { + log.fatal(ee); + fail(); + } + + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/multipleChains/ExampleTwoLspsGroceryDeliveryMultipleChainsTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/multipleChains/ExampleTwoLspsGroceryDeliveryMultipleChainsTest.java new file mode 100644 index 00000000000..5f9d04aa959 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/multipleChains/ExampleTwoLspsGroceryDeliveryMultipleChainsTest.java @@ -0,0 +1,64 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.multipleChains; + +import static org.junit.jupiter.api.Assertions.fail; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.testcases.MatsimTestUtils; + +public class ExampleTwoLspsGroceryDeliveryMultipleChainsTest { + private static final Logger log = LogManager.getLogger(ExampleTwoLspsGroceryDeliveryMultipleChainsTest.class); + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + + +/** + * This Test should ensure that the results are stable by checking for LSP File and events File to be equal to a previous run. + * It is **not** meat to get never chanced. In contrast, it will prevent me from unintended changes. + * I assume that with ongoing work, I will adapt the test input regularly. + */ + @Test + public void testOutputIsEqual() { + + try { + ExampleTwoLspsGroceryDeliveryMultipleChains.main(new String[]{ + "--config:controller.outputDirectory=" + utils.getOutputDirectory() + , "--config:controller.lastIteration=1" + }); + + } catch (Exception ee) { + log.fatal(ee); + fail(); + } + + //Compare LSP files + MatsimTestUtils.assertEqualFilesLineByLine(utils.getClassInputDirectory() + "output_lsps.xml.gz", utils.getOutputDirectory() + "output_lsps.xml.gz" ); + + //Compare events files + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/multipleChains/MultipleChainsReplanningTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/multipleChains/MultipleChainsReplanningTest.java new file mode 100644 index 00000000000..b98dd24e4ca --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/multipleChains/MultipleChainsReplanningTest.java @@ -0,0 +1,310 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.*; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.BestPlanSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlan; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MultipleChainsReplanningTest { + + private static final Id DEPOT_LINK_ID = Id.createLinkId("i(5,0)"); + private static final VehicleType VEH_TYPE_LARGE_50 = createVehTypeLarge50(); + + private static VehicleType createVehTypeLarge50() { + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create("large50", VehicleType.class), TransportMode.car); + vehicleType.getCapacity().setOther(50); + vehicleType.getCostInformation().setCostsPerMeter(0.01); + vehicleType.getCostInformation().setCostsPerSecond(0.01); + vehicleType.getCostInformation().setFixedCost(150.); + vehicleType.setMaximumVelocity(10); + vehicleType.setNetworkMode(TransportMode.car); + + return vehicleType; + } + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + int initialPlanCount; + int initialPlanShipmentPlanCount; + + int updatedPlanCount; + int innovatedPlanShipmentPlanCount; + int innovatedPlanFirstLogisticChainShipmentCount; + boolean innovatedPlanHasEmptyShipmentPlanElements = false; + + private static Scenario prepareScenario(Config config) { + Scenario scenario = ScenarioUtils.loadScenario(config); + + for (Link link : scenario.getNetwork().getLinks().values()) { + link.setFreespeed(30 / 3.6); + link.setCapacity(1000); + } + + LSPUtils.addLSPs(scenario, new LSPs(Collections.singletonList(createLSP(scenario)))); + + return scenario; + } + + private static LSP createLSP(Scenario scenario) { + scenario.getNetwork(); + + // A plan with two different logistic chains on the left and right, with respective carriers is created + LSPPlan multipleOneEchelonChainsPlan; + { + LogisticChainElement leftCarrierElement; + { + Carrier carrierLeft = CarriersUtils.createCarrier(Id.create("carrierLeft", Carrier.class)); + carrierLeft.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle(carrierLeft, CarrierVehicle.newInstance(Id.createVehicleId("veh_small"), DEPOT_LINK_ID, VEH_TYPE_LARGE_50)); + LSPResource carrierLeftResource = ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(carrierLeft) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + leftCarrierElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("leftCarrierElement", LogisticChainElement.class)) + .setResource(carrierLeftResource) + .build(); + } + + LogisticChainElement rightCarrierElement; + { + Carrier carrierRight = CarriersUtils.createCarrier(Id.create("carrierRight", Carrier.class)); + carrierRight.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle(carrierRight, CarrierVehicle.newInstance(Id.createVehicleId("veh_small"), DEPOT_LINK_ID, VEH_TYPE_LARGE_50)); + LSPResource carrierRightResource = ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(carrierRight) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + rightCarrierElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("rightCarrierElement", LogisticChainElement.class)) + .setResource(carrierRightResource) + .build(); + } + + LogisticChain leftChain = LSPUtils.LogisticChainBuilder.newInstance(Id.create("leftChain", LogisticChain.class)) + .addLogisticChainElement(leftCarrierElement) + .build(); + + LogisticChain rightChain = LSPUtils.LogisticChainBuilder.newInstance(Id.create("rightChain", LogisticChain.class)) + .addLogisticChainElement(rightCarrierElement) + .build(); + + final InitialShipmentAssigner shipmentAssigner = MultipleChainsUtils.createRoundRobinLogisticChainShipmentAssigner(); + multipleOneEchelonChainsPlan = LSPUtils.createLSPPlan() + .addLogisticChain(leftChain) + .addLogisticChain(rightChain) + .setInitialShipmentAssigner(shipmentAssigner); + + multipleOneEchelonChainsPlan.setType(MultipleChainsUtils.LspPlanTypes.MULTIPLE_ONE_ECHELON_CHAINS.toString()); + } + + List lspPlans = new ArrayList<>(); + lspPlans.add(multipleOneEchelonChainsPlan); + + LSP lsp = LSPUtils.LSPBuilder.getInstance(Id.create("myLSP", LSP.class)) + .setInitialPlan(multipleOneEchelonChainsPlan) + .setLogisticChainScheduler(ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(createResourcesListFromLSPPlans(lspPlans))) + .build(); + + for (LspShipment shipment : createInitialLSPShipments()) { + lsp.assignShipmentToLSP(shipment); + } + + lsp.scheduleLogisticChains(); + + return lsp; + } + + private static Collection createInitialLSPShipments() { + List shipmentList = new ArrayList<>(); + int capacityDemand = 1; + + for (int i = 1; i <= 10; i++) { + if (i % 2 != 0) { + Id id = Id.create("ShipmentLeft_" + i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + + builder.setCapacityDemand(capacityDemand); + builder.setFromLinkId(DEPOT_LINK_ID); + final Id shipmentLeftLinkId = Id.createLinkId("i(1,9)R"); + builder.setToLinkId(shipmentLeftLinkId); + + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + shipmentList.add(builder.build()); + } else { + Id id = Id.create("ShipmentRight_" + i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + + builder.setCapacityDemand(capacityDemand); + builder.setFromLinkId(DEPOT_LINK_ID); + final Id shipmentRightLinkId = Id.createLinkId("j(9,9)"); + builder.setToLinkId(shipmentRightLinkId); + + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + shipmentList.add(builder.build()); + } + } + return shipmentList; + } + + private static List createResourcesListFromLSPPlans(List lspPlans) { + List resourceList = new ArrayList<>(); + for (LSPPlan lspPlan : lspPlans) { + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + for (LogisticChainElement logisticChainElement : logisticChain.getLogisticChainElements()) { + resourceList.add(logisticChainElement.getResource()); + } + } + } + return resourceList; + } + + @BeforeEach + public void initialize() { + + Config config = prepareConfig(); + + Scenario scenario = prepareScenario(config); + + Controller controller = ControllerUtils.createController(scenario); + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + final EventBasedCarrierScorer4MultipleChains carrierScorer = new EventBasedCarrierScorer4MultipleChains(); + bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); + bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); + bind(CarrierStrategyManager.class).toProvider(() -> { + CarrierStrategyManager strategyManager = CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + return strategyManager; + }); + bind(LSPStrategyManager.class).toProvider(() -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy( RandomShiftingStrategyFactory.createStrategy(), null, 1); + return strategyManager; + }); + } + }); + + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + + LSP lsp = LSPUtils.getLSPs(controller.getScenario()).getLSPs().values().iterator().next(); + + initialPlanCount = lsp.getPlans().size(); + initialPlanShipmentPlanCount = lsp.getPlans().getFirst().getShipmentPlans().size(); + + controller.run(); + + updatedPlanCount = lsp.getPlans().size(); + innovatedPlanShipmentPlanCount = lsp.getPlans().get(1).getShipmentPlans().size(); + + innovatedPlanFirstLogisticChainShipmentCount = lsp.getPlans().get(1).getLogisticChains().iterator().next().getLspShipmentIds().size(); + for (LspShipmentPlan lspShipmentPlan : lsp.getPlans().get(1).getShipmentPlans()) { + if (lspShipmentPlan.getPlanElements().isEmpty()) { + innovatedPlanHasEmptyShipmentPlanElements = true; + } + } + + + } + + private Config prepareConfig() { + Config config = ConfigUtils.createConfig(); + + config.controller().setOutputDirectory(utils.getOutputDirectory()); + config.controller().setLastIteration(1); + + config.network().setInputFile(String.valueOf(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("freight-chessboard-9x9"), "grid9x9.xml"))); + config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setWriteEventsInterval(1); + + FreightCarriersConfigGroup freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + return config; + } + + @Test + public void testGeneratedInnovatedPlan() { + // a new innovative plan should have been added + assertEquals(initialPlanCount + 1, updatedPlanCount); + + // number of shipmentPlans should remain the same + assertEquals(initialPlanShipmentPlanCount, innovatedPlanShipmentPlanCount); + } + + @Test + public void testShipmentDistributionChanged() { + // starting from 5 shipments, exactly one shipment should have shifted the logistic chain + assertTrue(innovatedPlanFirstLogisticChainShipmentCount == 4 || innovatedPlanFirstLogisticChainShipmentCount == 6); + } + + @Test + public void testScheduledLogisticChains() { + assertFalse(innovatedPlanHasEmptyShipmentPlanElements); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/multipleChains/WorstPlanSelectorTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/multipleChains/WorstPlanSelectorTest.java new file mode 100644 index 00000000000..7556c24f8c6 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/multipleChains/WorstPlanSelectorTest.java @@ -0,0 +1,317 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2024 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.freight.logistics.examples.multipleChains; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.*; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.*; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.BestPlanSelector; +import org.matsim.core.replanning.selectors.ExpBetaPlanSelector; +import org.matsim.core.replanning.selectors.GenericWorstPlanForRemovalSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class WorstPlanSelectorTest { + + private static final Id DEPOT_SOUTH_LINK_ID = Id.createLinkId("i(1,0)"); + private static final Id DEPOT_NORTH_LINK_ID = Id.createLinkId("i(1,8)"); + private static final VehicleType VEH_TYPE_CHEAP = createVehType("cheap", 1., 0.001, 0.001); + private static final VehicleType VEH_TYPE_EXPENSIVE = createVehType("expensive", 100., 0.01, 0.01); + + private static VehicleType createVehType(String vehicleTypeId, double fix, double perDistanceUnit, double perTimeUnit) { + VehicleType vehicleType = VehicleUtils.createVehicleType(Id.create(vehicleTypeId, VehicleType.class), TransportMode.car); + vehicleType.getCapacity().setOther(50); + vehicleType.getCostInformation().setCostsPerMeter(perDistanceUnit); + vehicleType.getCostInformation().setCostsPerSecond(perTimeUnit); + vehicleType.getCostInformation().setFixedCost(fix); + vehicleType.setMaximumVelocity(10); + + return vehicleType; + } + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private LSP lsp; + + private static Scenario prepareScenario(Config config) { + Scenario scenario = ScenarioUtils.loadScenario(config); + + for (Link link : scenario.getNetwork().getLinks().values()) { + link.setFreespeed(30 / 3.6); + link.setCapacity(1000); + } + + LSPUtils.addLSPs(scenario, new LSPs(Collections.singletonList(createLSP(scenario)))); + + return scenario; + } + + private static LSP createLSP(Scenario scenario) { + Network network = scenario.getNetwork(); + + // A plan with one logistic chain, containing a single carrier is created + LSPPlan lspPlan_singleChain; + { + Carrier singleCarrier = CarriersUtils.createCarrier(Id.create("singleCarrier", Carrier.class)); + singleCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle(singleCarrier, CarrierVehicle.newInstance(Id.createVehicleId("directTruck"), DEPOT_SOUTH_LINK_ID, VEH_TYPE_EXPENSIVE)); + LSPResource singleCarrierResource = ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(singleCarrier) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + LogisticChainElement singleCarrierElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("singleCarrierElement", LogisticChainElement.class)) + .setResource(singleCarrierResource) + .build(); + + LogisticChain singleChain = LSPUtils.LogisticChainBuilder.newInstance(Id.create("singleChain", LogisticChain.class)) + .addLogisticChainElement(singleCarrierElement) + .build(); + + final InitialShipmentAssigner singleSolutionShipmentAssigner = MultipleChainsUtils.createPrimaryLogisticChainShipmentAssigner(); + lspPlan_singleChain = LSPUtils.createLSPPlan() + .addLogisticChain(singleChain) + .setInitialShipmentAssigner(singleSolutionShipmentAssigner); + + lspPlan_singleChain.setType(MultipleChainsUtils.LspPlanTypes.SINGLE_ONE_ECHELON_CHAIN.toString()); + } + + // A plan with two different logistic chains in the south and north, with respective carriers is created + LSPPlan lspPlan_twoChains; + { + LogisticChainElement southCarrierElement; + { + Carrier carrierSouth = CarriersUtils.createCarrier(Id.create("carrierSouth", Carrier.class)); + carrierSouth.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle(carrierSouth, CarrierVehicle.newInstance(Id.createVehicleId("directTruck"), DEPOT_SOUTH_LINK_ID, VEH_TYPE_CHEAP)); + LSPResource carrierSouthResource = ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(carrierSouth) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + southCarrierElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("southCarrierElement", LogisticChainElement.class)) + .setResource(carrierSouthResource) + .build(); + } + + LogisticChainElement northCarrierElement; + { + Carrier carrierNorth = CarriersUtils.createCarrier(Id.create("CarrierNorth", Carrier.class)); + carrierNorth.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarriersUtils.addCarrierVehicle(carrierNorth, CarrierVehicle.newInstance(Id.createVehicleId("directTruck"), DEPOT_NORTH_LINK_ID, VEH_TYPE_CHEAP)); + LSPResource carrierNorthResource = ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(carrierNorth) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .build(); + + northCarrierElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("northCarrierElement", LogisticChainElement.class)) + .setResource(carrierNorthResource) + .build(); + } + + LogisticChain southChain = LSPUtils.LogisticChainBuilder.newInstance(Id.create("southChain", LogisticChain.class)) + .addLogisticChainElement(southCarrierElement) + .build(); + + LogisticChain northChain = LSPUtils.LogisticChainBuilder.newInstance(Id.create("northChain", LogisticChain.class)) + .addLogisticChainElement(northCarrierElement) + .build(); + + final InitialShipmentAssigner shipmentAssigner = MultipleChainsUtils.createPrimaryLogisticChainShipmentAssigner(); + lspPlan_twoChains = LSPUtils.createLSPPlan() + .addLogisticChain(southChain) + .addLogisticChain(northChain) + .setInitialShipmentAssigner(shipmentAssigner); + + lspPlan_twoChains.setType(MultipleChainsUtils.LspPlanTypes.MULTIPLE_ONE_ECHELON_CHAINS.toString()); + } + + List lspPlans = new ArrayList<>(); + lspPlans.add(lspPlan_singleChain); + lspPlans.add(lspPlan_twoChains); + + LSP lsp = LSPUtils.LSPBuilder.getInstance(Id.create("org/matsim/freight/logistics/lsp", LSP.class)) + .setInitialPlan(lspPlan_singleChain) + .setLogisticChainScheduler(ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(createResourcesListFromLSPPlans(lspPlans))) + .build(); + lsp.addPlan(lspPlan_twoChains); + + for (LspShipment shipment : createInitialLSPShipments(network)) { + lsp.assignShipmentToLSP(shipment); + } + + lsp.scheduleLogisticChains(); + + return lsp; + } + + private static Collection createInitialLSPShipments(Network network) { + List shipmentList = new ArrayList<>(); + + Random rand2 = MatsimRandom.getLocalInstance(); + + + List zoneLinkList = Arrays.asList("i(4,4)", "i(5,4)", "i(6,4)", "i(4,6)", "i(5,6)", "i(6,6)", + "j(3,5)", "j(3,6)", "j(3,7)", "j(5,5)", "j(5,6)", "j(5,7)", + "i(4,5)R", "i(5,5)R", "i(6,5)R", "i(4,7)R", "i(5,7)R", "i(6,7)R", + "j(4,5)R", "j(4,6)R", "j(4,7)R", "j(6,5)R", "j(6,6)R", "j(6,7)R"); + for (String linkIdString : zoneLinkList) { + if (!network.getLinks().containsKey( Id.createLinkId(linkIdString))) { + throw new RuntimeException("Link is not in Network!"); + } + } + + for(int i = 1; i <= 10; i++) { + Id id = Id.create("Shipment_" + i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + + int capacityDemand = 1; + builder.setCapacityDemand(capacityDemand); + + builder.setFromLinkId(DEPOT_SOUTH_LINK_ID); + final Id toLinkId = Id.createLinkId(zoneLinkList.get(rand2.nextInt(zoneLinkList.size()-1))); + builder.setToLinkId(toLinkId); + + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + shipmentList.add(builder.build()); + } + return shipmentList; + } + + private static List createResourcesListFromLSPPlans(List lspPlans) { + List resourceList = new ArrayList<>(); + for (LSPPlan lspPlan : lspPlans) { + for (LogisticChain solution : lspPlan.getLogisticChains()) { + for (LogisticChainElement solutionElement : solution.getLogisticChainElements()) { + resourceList.add(solutionElement.getResource()); + } + } + } + return resourceList; + } + + @BeforeEach + public void initialize() { + + Config config = prepareConfig(); + + Scenario scenario = prepareScenario(config); + + Controller controller = ControllerUtils.createController(scenario); + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + final EventBasedCarrierScorer4MultipleChains carrierScorer = new EventBasedCarrierScorer4MultipleChains(); + + bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); + bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); + bind(CarrierStrategyManager.class).toProvider(() -> { + CarrierStrategyManager strategyManager = CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + return strategyManager; + }); + bind(LSPStrategyManager.class).toProvider(() -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new ExpBetaPlanSelector<>(new ScoringConfigGroup())), null, 1); + strategyManager.addStrategy( RandomDistributionAllShipmentsStrategyFactory.createStrategy(), null, 1); + strategyManager.setMaxPlansPerAgent(2); + strategyManager.setPlanSelectorForRemoval(new GenericWorstPlanForRemovalSelector<>() ); + return strategyManager; + }); + } + }); + + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + this.lsp = LSPUtils.getLSPs(controller.getScenario()).getLSPs().values().iterator().next(); + } + + private Config prepareConfig() { + Config config = ConfigUtils.createConfig(); + + config.controller().setOutputDirectory(utils.getOutputDirectory()); + config.controller().setLastIteration(10); + + config.network().setInputFile(String.valueOf(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("freight-chessboard-9x9"), "grid9x9.xml"))); + config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setWriteEventsInterval(1); + + FreightCarriersConfigGroup freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + return config; + } + + @Test + public void testPreserveLastPlanOfType() { + Set planTypes = new HashSet<>(); + + for (LSPPlan lspPlan : lsp.getPlans()) { + planTypes.add(lspPlan.getType()); + + if (planTypes.size() > 1) { + break; + } + } + + assertTrue(planTypes.size() > 1); + } + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/requirementsChecking/AssignerRequirementsTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/requirementsChecking/AssignerRequirementsTest.java new file mode 100644 index 00000000000..37588adb752 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/requirementsChecking/AssignerRequirementsTest.java @@ -0,0 +1,195 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.requirementsChecking; + +import static org.junit.jupiter.api.Assertions.assertInstanceOf; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Random; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class AssignerRequirementsTest { + + private LogisticChain blueChain; + private LogisticChain redChain; + + @BeforeEach + public void initialize() { + + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + Id redCarrierId = Id.create("RedCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + collectionVehType.setNetworkMode(TransportMode.car); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id redVehicleId = Id.createVehicleId("RedVehicle"); + CarrierVehicle redVehicle = CarrierVehicle.newInstance(redVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities redCapabilities = CarrierCapabilities.Builder.newInstance() + .addVehicle(redVehicle) + .setFleetSize(FleetSize.INFINITE) + .build(); + Carrier redCarrier = CarriersUtils.createCarrier(redCarrierId); + redCarrier.setCarrierCapabilities(redCapabilities); + + LSPResource redCollectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(redCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + Id redElementId = Id.create("RedCollectionElement", LogisticChainElement.class); + LogisticChainElement redCollectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(redElementId) + .setResource(redCollectionResource) + .build(); + + redChain = LSPUtils.LogisticChainBuilder.newInstance(Id.create("RedCollectionSolution", LogisticChain.class)) + .addLogisticChainElement(redCollectionElement) + .build(); + redChain.getAttributes().putAttribute("color", "red"); + + InitialShipmentAssigner assigner = new RequirementsAssigner(); + LSPPlan collectionPlan = LSPUtils.createLSPPlan(); + collectionPlan.setInitialShipmentAssigner(assigner); + collectionPlan.addLogisticChain(redChain); + + Id blueCarrierId = Id.create("BlueCarrier", Carrier.class); + Id blueVehicleId = Id.createVehicleId("BlueVehicle"); + CarrierVehicle blueVehicle = CarrierVehicle.newInstance(blueVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities blueCapabilities = CarrierCapabilities.Builder.newInstance() + .addVehicle(blueVehicle) + .setFleetSize(FleetSize.INFINITE) + .build(); + Carrier blueCarrier = CarriersUtils.createCarrier(blueCarrierId); + blueCarrier.setCarrierCapabilities(blueCapabilities); + + LSPResource blueCollectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(blueCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + Id blueElementId = Id.create("BlueCollectionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder blueCollectionElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(blueElementId); + blueCollectionElementBuilder.setResource(blueCollectionResource); + LogisticChainElement blueCollectionElement = blueCollectionElementBuilder.build(); + + blueChain = LSPUtils.LogisticChainBuilder.newInstance(Id.create("BlueCollectionSolution", LogisticChain.class)) + .addLogisticChainElement(blueCollectionElement) + .build(); + blueChain.getAttributes().putAttribute("color", "blue"); + collectionPlan.addLogisticChain(blueChain); + + LSPUtils.LSPBuilder collectionLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + collectionLSPBuilder.setInitialPlan(collectionPlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(redCollectionResource); + resourcesList.add(blueCollectionResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + collectionLSPBuilder.setLogisticChainScheduler(simpleScheduler); + LSP collectionLSP = collectionLSPBuilder.build(); + + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + + Random rand = new Random(1); + + for (int i = 1; i < 11; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = rand.nextInt(10); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + builder.setToLinkId(collectionLinkId); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + boolean blue = rand.nextBoolean(); + if (blue) { + builder.addRequirement(new BlueRequirement()); + } else { + builder.addRequirement(new RedRequirement()); + } + + LspShipment shipment = builder.build(); + collectionLSP.assignShipmentToLSP(shipment); + } + } + + @Test + public void testAssignerRequirements() { + for (Id shipmentId : blueChain.getLspShipmentIds()) { + LspShipment shipment = LSPUtils.findLspShipment(blueChain.getLSP(), shipmentId); + assert shipment != null; + assertInstanceOf(BlueRequirement.class, shipment.getRequirements().iterator().next()); + } + for (Id shipmentId : redChain.getLspShipmentIds()) { + LspShipment shipment = LSPUtils.findLspShipment(redChain.getLSP(), shipmentId); + assert shipment != null; + assertInstanceOf(RedRequirement.class, shipment.getRequirements().iterator().next()); + } + } + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/simulationTrackers/CollectionTrackerTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/simulationTrackers/CollectionTrackerTest.java new file mode 100644 index 00000000000..47dac541f34 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/examples/simulationTrackers/CollectionTrackerTest.java @@ -0,0 +1,324 @@ +/* + *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2022 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.freight.logistics.examples.simulationTrackers; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.*; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.events.handler.EventHandler; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.population.routes.NetworkRoute; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.carriers.Tour.Leg; +import org.matsim.freight.carriers.Tour.ServiceActivity; +import org.matsim.freight.carriers.Tour.TourElement; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.CollectionCarrierResourceBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class CollectionTrackerTest { + private static final Logger log = LogManager.getLogger(CollectionTrackerTest.class); + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private Network network; + private Carrier carrier; + private LogisticChain logisticChain; + private double shareOfFixedCosts; + + @BeforeEach + public void initialize() { + + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + this.network = scenario.getNetwork(); + + Id carrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Link collectionLink = network.getLinks().get(collectionLinkId); + + CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(Id.createVehicleId("CollectionVehicle"), collectionLink.getId(), collectionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(carrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities capabilities = capabilitiesBuilder.build(); + carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + + Id.create("CollectionCarrierResource", LSPResource.class); + CollectionCarrierResourceBuilder adapterBuilder = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(carrier); + adapterBuilder.setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)); + adapterBuilder.setLocationLinkId(collectionLinkId); + LSPResource collectionResource = adapterBuilder.build(); + + Id elementId = Id.create("CollectionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder collectionElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(elementId); + collectionElementBuilder.setResource(collectionResource); + LogisticChainElement collectionElement = collectionElementBuilder.build(); + + Id collectionSolutionId = Id.create("CollectionSolution", LogisticChain.class); + LSPUtils.LogisticChainBuilder collectionSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(collectionSolutionId); + collectionSolutionBuilder.addLogisticChainElement(collectionElement); + logisticChain = collectionSolutionBuilder.build(); + + { + shareOfFixedCosts = 0.2; + LinearCostTracker tracker = new LinearCostTracker(shareOfFixedCosts); + tracker.getEventHandlers().add(new TourStartHandler(scenario)); + tracker.getEventHandlers().add(new CollectionServiceHandler(scenario)); + tracker.getEventHandlers().add(new DistanceAndTimeHandler(scenario)); + // I think that it would be better to use delegation inside LinearCostTracker, i.e. to not expose getEventHandlers(). kai, jun'22 + + logisticChain.addSimulationTracker(tracker); + } + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan collectionPlan = LSPUtils.createLSPPlan(); + collectionPlan.setInitialShipmentAssigner(assigner); + collectionPlan.addLogisticChain(logisticChain); + + LSPUtils.LSPBuilder collectionLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + collectionLSPBuilder.setInitialPlan(collectionPlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + collectionLSPBuilder.setLogisticChainScheduler(simpleScheduler); + LSP collectionLSP = collectionLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + + + for (int i = 1; i < 2; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + Random random = new Random(1); + int capacityDemand = random.nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, random); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + builder.setToLinkId(collectionLinkId); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + collectionLSP.assignShipmentToLSP(shipment); + } + collectionLSP.scheduleLogisticChains(); + + + ArrayList lspList = new ArrayList<>(); + lspList.add(collectionLSP); + LSPs lsps = new LSPs(lspList); + + LSPUtils.addLSPs(scenario, lsps); + + Controller controller = ControllerUtils.createController(scenario); + + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); +// config.network().setInputFile("scenarios/2regions/2regions-network.xml"); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } + + @Test + public void testCollectionTracker() { + + assertEquals(1, logisticChain.getSimulationTrackers().size()); + LSPSimulationTracker tracker = logisticChain.getSimulationTrackers().iterator().next(); + assertInstanceOf(LinearCostTracker.class, tracker); + LinearCostTracker linearTracker = (LinearCostTracker) tracker; + double totalScheduledCosts = 0; + double totalTrackedCosts = 0; + double totalScheduledWeight = 0; + double totalTrackedWeight = 0; + int totalNumberOfScheduledShipments = 0; + int totalNumberOfTrackedShipments = 0; + for (EventHandler handler : linearTracker.getEventHandlers()) { + if (handler instanceof TourStartHandler startHandler) { + double scheduledCosts = 0; + for (ScheduledTour scheduledTour : carrier.getSelectedPlan().getScheduledTours()) { + scheduledCosts += ((Vehicle) scheduledTour.getVehicle()).getType().getCostInformation().getFixedCosts(); + totalScheduledCosts += scheduledCosts; + } + double trackedCosts = startHandler.getVehicleFixedCosts(); + totalTrackedCosts += trackedCosts; + assertEquals(trackedCosts, scheduledCosts, 0.1); + } + if (handler instanceof CollectionServiceHandler serviceHandler) { + totalTrackedWeight = serviceHandler.getTotalWeightOfShipments(); + totalNumberOfTrackedShipments = serviceHandler.getTotalNumberOfShipments(); + double scheduledCosts = 0; + for (ScheduledTour scheduledTour : carrier.getSelectedPlan().getScheduledTours()) { + Tour tour = scheduledTour.getTour(); + for (TourElement element : tour.getTourElements()) { + if (element instanceof ServiceActivity activity) { + scheduledCosts += activity.getService().getServiceDuration() * ((Vehicle) scheduledTour.getVehicle()).getType().getCostInformation().getCostsPerSecond(); + totalScheduledCosts += scheduledCosts; + totalScheduledWeight += activity.getService().getCapacityDemand(); + totalNumberOfScheduledShipments++; + } + } + } + double trackedCosts = serviceHandler.getTotalLoadingCosts(); + totalTrackedCosts += trackedCosts; + assertEquals(trackedCosts, scheduledCosts, 0.1); + } + if (handler instanceof DistanceAndTimeHandler distanceHandler) { + double trackedTimeCosts = distanceHandler.getTimeCosts(); + totalTrackedCosts += trackedTimeCosts; + double scheduledTimeCosts = 0; + for (ScheduledTour scheduledTour : carrier.getSelectedPlan().getScheduledTours()) { + Tour tour = scheduledTour.getTour(); + for (TourElement element : tour.getTourElements()) { + if (element instanceof Leg leg) { + scheduledTimeCosts += leg.getExpectedTransportTime() * ((Vehicle) scheduledTour.getVehicle()).getType().getCostInformation().getCostsPerSecond(); + } + } + } + totalScheduledCosts += scheduledTimeCosts; + assertEquals(scheduledTimeCosts, trackedTimeCosts, Math.max(scheduledTimeCosts, trackedTimeCosts) * 0.01); + + double scheduledDistanceCosts = 0; + double trackedDistanceCosts = distanceHandler.getDistanceCosts(); + totalTrackedCosts += trackedDistanceCosts; + for (ScheduledTour scheduledTour : carrier.getSelectedPlan().getScheduledTours()) { + scheduledDistanceCosts += network.getLinks().get(scheduledTour.getTour().getEndLinkId()).getLength() * ((Vehicle) scheduledTour.getVehicle()).getType().getCostInformation().getCostsPerMeter(); + for (TourElement element : scheduledTour.getTour().getTourElements()) { + System.out.println(element); + if (element instanceof Leg leg) { + NetworkRoute linkRoute = (NetworkRoute) leg.getRoute(); + for (Id linkId : linkRoute.getLinkIds()) { + scheduledDistanceCosts += network.getLinks().get(linkId).getLength() * ((Vehicle) scheduledTour.getVehicle()).getType().getCostInformation().getCostsPerMeter(); + } + } + if (element instanceof ServiceActivity activity) { + scheduledDistanceCosts += network.getLinks().get(activity.getLocation()).getLength() * ((Vehicle) scheduledTour.getVehicle()).getType().getCostInformation().getCostsPerMeter(); + // (I think that we need this since the last link is not in the route. Or is it? kai, jul'22) + // (yy I do not understand why we do not need to do this for the end activity of the tour.) + } + } + log.warn("scheduledDistanceCosts={}", scheduledDistanceCosts); + } + totalScheduledCosts += scheduledDistanceCosts; + assertEquals(scheduledDistanceCosts, trackedDistanceCosts, Math.max(scheduledDistanceCosts, trackedDistanceCosts) * 0.01); + } + } + + double linearTrackedCostsPerShipment = (totalTrackedCosts * (1 - shareOfFixedCosts)) / totalTrackedWeight; + double linearScheduledCostsPerShipment = (totalScheduledCosts * (1 - shareOfFixedCosts)) / totalScheduledWeight; + double fixedTrackedCostsPerShipment = (totalTrackedCosts * shareOfFixedCosts) / totalNumberOfTrackedShipments; + double fixedScheduledCostsPerShipment = (totalScheduledCosts * shareOfFixedCosts) / totalNumberOfScheduledShipments; + + assertEquals(totalTrackedWeight, totalScheduledWeight, 0); + assertEquals(totalNumberOfTrackedShipments, totalNumberOfScheduledShipments, 0); + assertEquals(totalTrackedCosts, totalScheduledCosts, Math.max(totalScheduledCosts, totalTrackedCosts) * 0.01); + assertEquals(linearTrackedCostsPerShipment, linearScheduledCostsPerShipment, Math.max(linearTrackedCostsPerShipment, linearScheduledCostsPerShipment) * 0.01); + assertEquals(fixedScheduledCostsPerShipment, fixedTrackedCostsPerShipment, Math.max(fixedTrackedCostsPerShipment, fixedScheduledCostsPerShipment) * 0.01); + +// LSPInfo info = collectionSolution.getAttributes().iterator().next(); +// assertTrue(info instanceof CostInfo ); +// CostInfo costInfo = (CostInfo) info; + +// assertEquals(costInfo.getVariableCost() ,linearTrackedCostsPerShipment , Math.max(linearTrackedCostsPerShipment,costInfo.getVariableCost() ) * 0.01 ); +// assertEquals(costInfo.getVariableCost() , linearScheduledCostsPerShipment, Math.max(linearScheduledCostsPerShipment,costInfo.getVariableCost() ) * 0.01 ); +// assertEquals(costInfo.getFixedCost() ,fixedTrackedCostsPerShipment, Math.max(fixedTrackedCostsPerShipment,costInfo.getFixedCost()) * 0.01 ); +// assertEquals(costInfo.getFixedCost(),fixedScheduledCostsPerShipment, Math.max(fixedScheduledCostsPerShipment,costInfo.getFixedCost()) * 0.01 ); + + // I cannot say how the above was supposed to work, since costInfo.getVariableCost() was the same in both cases. kai, may'22 + + assertEquals(2, logisticChain.getAttributes().size()); + assertEquals(LSPUtils.getVariableCost(logisticChain), linearTrackedCostsPerShipment, Math.max(linearTrackedCostsPerShipment, LSPUtils.getVariableCost(logisticChain)) * 0.01); + assertEquals(LSPUtils.getVariableCost(logisticChain), linearScheduledCostsPerShipment, Math.max(linearScheduledCostsPerShipment, LSPUtils.getVariableCost(logisticChain)) * 0.01); + assertEquals(LSPUtils.getFixedCost(logisticChain), fixedTrackedCostsPerShipment, Math.max(fixedTrackedCostsPerShipment, LSPUtils.getFixedCost(logisticChain)) * 0.01); + assertEquals(LSPUtils.getFixedCost(logisticChain), fixedScheduledCostsPerShipment, Math.max(fixedScheduledCostsPerShipment, LSPUtils.getFixedCost(logisticChain)) * 0.01); + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/io/LSPReadWriteTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/io/LSPReadWriteTest.java new file mode 100644 index 00000000000..82a2d86a835 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/io/LSPReadWriteTest.java @@ -0,0 +1,78 @@ +package org.matsim.freight.logistics.io; + +import java.util.Collections; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.freight.carriers.CarrierPlanXmlReader; +import org.matsim.freight.carriers.CarrierVehicleTypeReader; +import org.matsim.freight.carriers.CarrierVehicleTypes; +import org.matsim.freight.carriers.Carriers; +import org.matsim.freight.logistics.LSPs; +import org.matsim.testcases.MatsimTestUtils; + +public class LSPReadWriteTest { + + @RegisterExtension + public MatsimTestUtils utils = new MatsimTestUtils(); + + @Test + public void readWriteTest() { + + LSPs lsPs = new LSPs(Collections.emptyList()); + Carriers carriers = new Carriers(); + CarrierVehicleTypes carrierVehicleTypes = new CarrierVehicleTypes(); + + String inputFilename = utils.getPackageInputDirectory() + "lsps.xml"; + String outputFilename = utils.getOutputDirectory() + "/outputLsps.xml"; + + CarrierVehicleTypeReader vehicleTypeReader = new CarrierVehicleTypeReader(carrierVehicleTypes); + vehicleTypeReader.readFile(utils.getPackageInputDirectory() + "vehicles.xml"); + + CarrierPlanXmlReader carrierReader = new CarrierPlanXmlReader(carriers, carrierVehicleTypes); + carrierReader.readFile(utils.getPackageInputDirectory() + "carriers.xml"); + + LSPPlanXmlReader reader = new LSPPlanXmlReader(lsPs, carriers); + reader.readFile(inputFilename); + + new LSPPlanXmlWriter(lsPs).write(outputFilename); + + MatsimTestUtils.assertEqualFilesLineByLine(inputFilename, outputFilename); + } + + @Test + public void readWriteReadTest() { + + LSPs lsps = new LSPs(Collections.emptyList()); + Carriers carriers = new Carriers(); + CarrierVehicleTypes carrierVehicleTypes = new CarrierVehicleTypes(); + + String inputFilename = utils.getPackageInputDirectory() + "lsps.xml"; + String outputFilename = utils.getOutputDirectory() + "/outputLsps.xml"; + String outputFilename2 = utils.getOutputDirectory() + "/outputLsps2.xml"; + + CarrierVehicleTypeReader vehicleTypeReader = new CarrierVehicleTypeReader(carrierVehicleTypes); + vehicleTypeReader.readFile(utils.getPackageInputDirectory() + "vehicles.xml"); + + CarrierPlanXmlReader carrierReader = new CarrierPlanXmlReader(carriers, carrierVehicleTypes); + carrierReader.readFile(utils.getPackageInputDirectory() + "carriers.xml"); + + LSPPlanXmlReader reader = new LSPPlanXmlReader(lsps, carriers); + reader.readFile(inputFilename); + + new LSPPlanXmlWriter(lsps).write(outputFilename); + + //clear and 2nd read - based on written file. + lsps.getLSPs().clear(); + + LSPPlanXmlReader reader2 = new LSPPlanXmlReader(lsps, carriers); + reader2.readFile(outputFilename); + + new LSPPlanXmlWriter(lsps).write(outputFilename2); + + MatsimTestUtils.assertEqualFilesLineByLine(inputFilename, outputFilename2); + } + + + + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainElementTests/CollectionElementTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainElementTests/CollectionElementTest.java new file mode 100644 index 00000000000..40ab28dbce5 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainElementTests/CollectionElementTest.java @@ -0,0 +1,103 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.logisticChainElementTests; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.core.config.Config; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.LSPCarrierResource; +import org.matsim.freight.logistics.LSPUtils; +import org.matsim.freight.logistics.LogisticChainElement; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class CollectionElementTest { + + private LogisticChainElement collectionElement; + private LSPCarrierResource carrierResource; + + @BeforeEach + public void initialize() { + + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + scenario.getNetwork(); + + Id carrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(Id.createVehicleId("CollectionVehicle"), collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(carrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities capabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + carrierResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(carrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(carrierResource) + .build(); + } + + @Test + public void testCollectionElement() { + assertNotNull(collectionElement.getIncomingShipments()); + assertNotNull(collectionElement.getIncomingShipments().getLspShipmentsWTime()); + assertTrue(collectionElement.getIncomingShipments().getSortedLspShipments().isEmpty()); + assertNotNull(collectionElement.getAttributes()); + assertTrue(collectionElement.getAttributes().isEmpty()); +// assertNull(collectionElement.getEmbeddingContainer() ); + assertNull(collectionElement.getNextElement()); + assertNotNull(collectionElement.getOutgoingShipments()); + assertNotNull(collectionElement.getOutgoingShipments().getLspShipmentsWTime()); + assertTrue(collectionElement.getOutgoingShipments().getSortedLspShipments().isEmpty()); + assertNull(collectionElement.getPreviousElement()); + assertSame(collectionElement.getResource(), carrierResource); + assertSame(collectionElement.getResource().getClientElements().iterator().next(), collectionElement); + } + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainElementTests/DistributionElementTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainElementTests/DistributionElementTest.java new file mode 100644 index 00000000000..ca387a1056b --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainElementTests/DistributionElementTest.java @@ -0,0 +1,109 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.logisticChainElementTests; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.core.config.Config; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.LSPCarrierResource; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LSPUtils; +import org.matsim.freight.logistics.LogisticChainElement; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class DistributionElementTest { + + private LSPCarrierResource adapter; + private LogisticChainElement distributionElement; + + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + scenario.getNetwork(); + + Id carrierId = Id.create("DistributionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("DistributionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType distributionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + distributionVehType.getCapacity().setOther(10); + distributionVehType.getCostInformation().setCostsPerMeter(0.0004); + distributionVehType.getCostInformation().setCostsPerSecond(0.38); + distributionVehType.getCostInformation().setFixedCost(49.); + distributionVehType.setMaximumVelocity(50 / 3.6); + + Id distributionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id distributionVehicleId = Id.createVehicleId("DistributionVehicle"); + CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(distributionVehicleId, distributionLinkId, distributionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(carrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities capabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + + Id.create("DistributionCarrierResource", LSPResource.class); + adapter = ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(carrier) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .setLocationLinkId(distributionLinkId) + .build(); + + Id elementId = Id.create("DistributionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder distributionBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(elementId); + distributionBuilder.setResource(adapter); + distributionElement = distributionBuilder.build(); + + } + + @Test + public void testDistributionElement() { + assertNotNull(distributionElement.getIncomingShipments()); + assertNotNull(distributionElement.getIncomingShipments().getLspShipmentsWTime()); + assertTrue(distributionElement.getIncomingShipments().getSortedLspShipments().isEmpty()); + assertNotNull(distributionElement.getAttributes()); + assertTrue(distributionElement.getAttributes().isEmpty()); +// assertNull(distributionElement.getEmbeddingContainer() ); + assertNull(distributionElement.getNextElement()); + assertNotNull(distributionElement.getOutgoingShipments()); + assertNotNull(distributionElement.getOutgoingShipments().getLspShipmentsWTime()); + assertTrue(distributionElement.getOutgoingShipments().getSortedLspShipments().isEmpty()); + assertNull(distributionElement.getPreviousElement()); + assertSame(distributionElement.getResource(), adapter); + assertSame(distributionElement.getResource().getClientElements().iterator().next(), distributionElement); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainElementTests/MainRunElementTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainElementTests/MainRunElementTest.java new file mode 100644 index 00000000000..26694caceb0 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainElementTests/MainRunElementTest.java @@ -0,0 +1,109 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.logisticChainElementTests; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.core.config.Config; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LSPUtils; +import org.matsim.freight.logistics.LogisticChainElement; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MainRunElementTest { + + private LSPResource mainRunResource; + private LogisticChainElement mainRunElement; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + scenario.getNetwork(); + + + Id carrierId = Id.create("MainRunCarrier", Carrier.class); + Id vehicleTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50 / 3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id vollectionVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(vollectionVehicleId, fromLinkId, mainRunVehType); + + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(carrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities capabilities = capabilitiesBuilder.build(); + Carrier mainRunCarrierResourceBuilder = CarriersUtils.createCarrier(carrierId); + mainRunCarrierResourceBuilder.setCarrierCapabilities(capabilities); + + mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrierResourceBuilder) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .build(); + + mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + } + + @Test + public void testDistributionElement() { + assertNotNull(mainRunElement.getIncomingShipments()); + assertNotNull(mainRunElement.getIncomingShipments().getLspShipmentsWTime()); + assertTrue(mainRunElement.getIncomingShipments().getSortedLspShipments().isEmpty()); + assertNotNull(mainRunElement.getAttributes()); + assertTrue(mainRunElement.getAttributes().isEmpty()); +// assertNull(mainRunElement.getEmbeddingContainer() ); + assertNull(mainRunElement.getNextElement()); + assertNotNull(mainRunElement.getOutgoingShipments()); + assertNotNull(mainRunElement.getOutgoingShipments().getLspShipmentsWTime()); + assertTrue(mainRunElement.getOutgoingShipments().getSortedLspShipments().isEmpty()); + assertNull(mainRunElement.getPreviousElement()); + assertSame(mainRunElement.getResource(), mainRunResource); + assertSame(mainRunElement.getResource().getClientElements().iterator().next(), mainRunElement); + } + + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainElementTests/SecondHubElementTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainElementTests/SecondHubElementTest.java new file mode 100644 index 00000000000..3b60dc7d00d --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainElementTests/SecondHubElementTest.java @@ -0,0 +1,73 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.logisticChainElementTests; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Id; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LSPUtils; +import org.matsim.freight.logistics.LogisticChainElement; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; + +public class SecondHubElementTest { + + private LSPResource point; + private LogisticChainElement hubElement; + + @BeforeEach + public void initialize() { + TranshipmentHubSchedulerBuilder schedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + schedulerBuilder.setCapacityNeedFixed(10); + schedulerBuilder.setCapacityNeedLinear(1); + + + point = ResourceImplementationUtils.TransshipmentHubBuilder + .newInstance(Id.create("TranshipmentHub2", LSPResource.class), Id.createLinkId("(14 2) (14 3)"), null) + .setTransshipmentHubScheduler(schedulerBuilder.build()) + .build(); + + hubElement = LSPUtils.LogisticChainElementBuilder + .newInstance(Id.create("SecondHubElement", LogisticChainElement.class)) + .setResource(point) + .build(); + } + + @Test + public void testDistributionElement() { + assertNotNull(hubElement.getIncomingShipments()); + assertNotNull(hubElement.getIncomingShipments().getLspShipmentsWTime()); + assertTrue(hubElement.getIncomingShipments().getSortedLspShipments().isEmpty()); + assertNotNull(hubElement.getAttributes()); + assertTrue(hubElement.getAttributes().isEmpty()); +// assertNull(hubElement.getEmbeddingContainer() ); + assertNull(hubElement.getNextElement()); + assertNotNull(hubElement.getOutgoingShipments()); + assertNotNull(hubElement.getOutgoingShipments().getLspShipmentsWTime()); + assertTrue(hubElement.getOutgoingShipments().getSortedLspShipments().isEmpty()); + assertNull(hubElement.getPreviousElement()); + assertSame(hubElement.getResource(), point); + assertSame(hubElement.getResource().getClientElements().iterator().next(), hubElement); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainTests/CollectionChainTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainTests/CollectionChainTest.java new file mode 100644 index 00000000000..2d0a981f7d5 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainTests/CollectionChainTest.java @@ -0,0 +1,118 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.logisticChainTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.core.config.Config; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.LSPCarrierResource; +import org.matsim.freight.logistics.LSPUtils; +import org.matsim.freight.logistics.LogisticChain; +import org.matsim.freight.logistics.LogisticChainElement; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class CollectionChainTest { + + private LogisticChain logisticChain; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + scenario.getNetwork(); + + Id carrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(Id.createVehicleId("CollectionVehicle"), collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(carrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities capabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + LSPCarrierResource carrierResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder + .newInstance(carrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + Id elementId = Id.create("CollectionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder collectionElementBuilder = LSPUtils.LogisticChainElementBuilder + .newInstance(elementId); + collectionElementBuilder.setResource(carrierResource); + LogisticChainElement collectionElement = collectionElementBuilder.build(); + + Id collectionSolutionId = Id.create("CollectionSolution", LogisticChain.class); + LSPUtils.LogisticChainBuilder collectionSolutionBuilder = LSPUtils.LogisticChainBuilder + .newInstance(collectionSolutionId); + collectionSolutionBuilder.addLogisticChainElement(collectionElement); + logisticChain = collectionSolutionBuilder.build(); + + } + + @Test + public void testCollectionChain() { + assertNotNull(logisticChain.getSimulationTrackers()); + assertTrue(logisticChain.getSimulationTrackers().isEmpty()); + assertNotNull(logisticChain.getAttributes()); + assertTrue(logisticChain.getAttributes().isEmpty()); + assertNull(logisticChain.getLSP()); + assertNotNull(logisticChain.getLspShipmentIds()); + assertTrue(logisticChain.getLspShipmentIds().isEmpty()); + assertEquals(1, logisticChain.getLogisticChainElements().size()); + ArrayList elements = new ArrayList<>(logisticChain.getLogisticChainElements()); + for (LogisticChainElement element : elements) { + if (elements.indexOf(element) == 0) { + assertNull(element.getPreviousElement()); + } + if (elements.indexOf(element) == (elements.size() - 1)) { + assertNull(element.getNextElement()); + } +// assertSame(element.getEmbeddingContainer(), collectionSolution ); + } + } + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainTests/CompleteLogisticChainTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainTests/CompleteLogisticChainTest.java new file mode 100644 index 00000000000..a3f61d2f872 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/logisticChainTests/CompleteLogisticChainTest.java @@ -0,0 +1,246 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.logisticChainTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.core.config.Config; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LSPUtils; +import org.matsim.freight.logistics.LogisticChain; +import org.matsim.freight.logistics.LogisticChainElement; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.CollectionCarrierResourceBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class CompleteLogisticChainTest { + + private LogisticChainElement collectionElement; + private LogisticChainElement firstHubElement; + private LogisticChainElement mainRunElement; + private LogisticChainElement secondHubElement; + private LogisticChainElement distributionElement; + private LogisticChain logisticChain; + + @BeforeEach + public void initialize() { + + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + scenario.getNetwork(); + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + CollectionCarrierResourceBuilder collectionResourceBuilder = ResourceImplementationUtils.CollectionCarrierResourceBuilder + .newInstance(collectionCarrier); + collectionResourceBuilder.setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)); + collectionResourceBuilder.setLocationLinkId(collectionLinkId); + + Id collectionElementId = Id.create("CollectionElement", + LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder collectionBuilder = LSPUtils.LogisticChainElementBuilder + .newInstance(collectionElementId); + collectionBuilder.setResource(collectionResourceBuilder.build()); + collectionElement = collectionBuilder.build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, + firstTransshipmentHub_LinkId, scenario) + .setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + firstHubElement = LSPUtils.LogisticChainElementBuilder + .newInstance(firstHubElementId) + .setResource(firstTransshipmentHubBuilder.build()) + .build(); + + + final VehicleType mainRunType = VehicleUtils.createVehicleType(Id.create("small05", VehicleType.class), TransportMode.car); + mainRunType.getCapacity().setOther(30); + mainRunType.getCostInformation().setCostsPerMeter(0.0002); + mainRunType.getCostInformation().setCostsPerSecond(0.38); + mainRunType.getCostInformation().setFixedCost(120.); + mainRunType.setMaximumVelocity(50 / 3.6); + mainRunType.setNetworkMode(TransportMode.car); + + final Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(Id.createVehicleId("MainRunVehicle"), fromLinkId, mainRunType); + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = collectionCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(collectionCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + LSPResource mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .build(); + + Id mainRunElementId = Id.create("MainRunElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder mainRunBuilder = LSPUtils.LogisticChainElementBuilder + .newInstance(mainRunElementId); + mainRunBuilder.setResource(mainRunResource); + mainRunElement = mainRunBuilder.build(); + + TranshipmentHubSchedulerBuilder secondSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + secondSchedulerBuilder.setCapacityNeedFixed(10); + secondSchedulerBuilder.setCapacityNeedLinear(1); + + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + + TransshipmentHubBuilder secondTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(secondTransshipmentHubId, + secondTransshipmentHub_LinkId, scenario); + secondTransshipmentHubBuilder.setTransshipmentHubScheduler(secondSchedulerBuilder.build()); + + Id secondHubElementId = Id.create("SecondHubElement", + LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = LSPUtils.LogisticChainElementBuilder + .newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTransshipmentHubBuilder.build()); + secondHubElement = secondHubElementBuilder.build(); + + Id distributionCarrierId = Id.create("DistributionCarrier", Carrier.class); + Id distributionVehTypeId = Id.create("DistributionCarrierVehicleType", VehicleType.class); + VehicleType distributionVehType = VehicleUtils.createVehicleType(distributionVehTypeId, TransportMode.car); + distributionVehType.getCapacity().setOther(10); + distributionVehType.getCostInformation().setCostsPerMeter(0.0004); + distributionVehType.getCostInformation().setCostsPerSecond(0.38); + distributionVehType.getCostInformation().setFixedCost(49.); + distributionVehType.setMaximumVelocity(50 / 3.6); + + Id distributionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id distributionVehicleId = Id.createVehicleId("DistributionVehicle"); + CarrierVehicle distributionCarrierVehicle = CarrierVehicle.newInstance(distributionVehicleId, distributionLinkId, distributionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(distributionCarrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities distributionCapabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(distributionCarrierId); + carrier.setCarrierCapabilities(distributionCapabilities); + + final LSPResource distributionCarrierResource = ResourceImplementationUtils.DistributionCarrierResourceBuilder + .newInstance(carrier) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .setLocationLinkId(distributionLinkId) + .build(); + + Id distributionElementId = Id.create("DistributionElement", LogisticChainElement.class); + distributionElement = LSPUtils.LogisticChainElementBuilder + .newInstance(distributionElementId) + .setResource(distributionCarrierResource) + .build(); + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + secondHubElement.connectWithNextElement(distributionElement); + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + completeSolutionBuilder.addLogisticChainElement(mainRunElement); + completeSolutionBuilder.addLogisticChainElement(secondHubElement); + completeSolutionBuilder.addLogisticChainElement(distributionElement); + logisticChain = completeSolutionBuilder.build(); + + } + + @Test + public void testCompleteLogisticChain() { + assertNotNull(logisticChain.getSimulationTrackers()); + assertTrue(logisticChain.getSimulationTrackers().isEmpty()); + assertNotNull(logisticChain.getAttributes()); + assertTrue(logisticChain.getAttributes().isEmpty()); + assertNull(logisticChain.getLSP()); + assertNotNull(logisticChain.getLspShipmentIds()); + assertTrue(logisticChain.getLspShipmentIds().isEmpty()); + assertEquals(5, logisticChain.getLogisticChainElements().size()); + ArrayList elements = new ArrayList<>(logisticChain.getLogisticChainElements()); + for (LogisticChainElement element : elements) { + if (elements.indexOf(element) == 0) { + assertNull(element.getPreviousElement()); + } + if (elements.indexOf(element) == (elements.size() - 1)) { + assertNull(element.getNextElement()); + } +// assertSame(element.getEmbeddingContainer(), solution ); + } + assertNull(collectionElement.getPreviousElement()); + assertSame(collectionElement.getNextElement(), firstHubElement); + assertSame(firstHubElement.getPreviousElement(), collectionElement); + assertSame(firstHubElement.getNextElement(), mainRunElement); + assertSame(mainRunElement.getPreviousElement(), firstHubElement); + assertSame(mainRunElement.getNextElement(), secondHubElement); + assertSame(secondHubElement.getPreviousElement(), mainRunElement); + assertSame(secondHubElement.getNextElement(), distributionElement); + assertSame(distributionElement.getPreviousElement(), secondHubElement); + assertNull(distributionElement.getNextElement()); + } + + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspCreationTests/CollectionLSPCreationTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspCreationTests/CollectionLSPCreationTest.java new file mode 100644 index 00000000000..7272fa366fa --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspCreationTests/CollectionLSPCreationTest.java @@ -0,0 +1,124 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspCreationTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.core.config.Config; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.CollectionCarrierResourceBuilder; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class CollectionLSPCreationTest { + + private LogisticChain logisticChain; + private InitialShipmentAssigner assigner; + private LSP collectionLSP; + + @BeforeEach + public void initialize() { + + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + scenario.getNetwork(); + + Id carrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(Id.createVehicleId("CollectionVehicle"), collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(carrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities capabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + + Id.create("CollectionCarrierResource", LSPResource.class); + CollectionCarrierResourceBuilder adapterBuilder = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(carrier); + adapterBuilder.setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)); + adapterBuilder.setLocationLinkId(collectionLinkId); + LSPResource collectionResource = adapterBuilder.build(); + + Id elementId = Id.create("CollectionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder collectionElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(elementId); + collectionElementBuilder.setResource(collectionResource); + LogisticChainElement collectionElement = collectionElementBuilder.build(); + + Id collectionSolutionId = Id.create("CollectionSolution", LogisticChain.class); + LSPUtils.LogisticChainBuilder collectionSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(collectionSolutionId); + collectionSolutionBuilder.addLogisticChainElement(collectionElement); + logisticChain = collectionSolutionBuilder.build(); + + assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan collectionPlan = LSPUtils.createLSPPlan(); + collectionPlan.setInitialShipmentAssigner(assigner); + collectionPlan.addLogisticChain(logisticChain); + + LSPUtils.LSPBuilder collectionLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + collectionLSPBuilder.setInitialPlan(collectionPlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + collectionLSPBuilder.setLogisticChainScheduler(simpleScheduler); + collectionLSP = collectionLSPBuilder.build(); + } + + @Test + public void testCollectionLSPCreation() { + assertNotNull(collectionLSP.getPlans()); + assertFalse(collectionLSP.getPlans().isEmpty()); + assertNotNull(collectionLSP.getResources()); + LSPPlan selectedPlan = collectionLSP.getSelectedPlan(); + assertNull(selectedPlan.getScore()); + assertSame(selectedPlan.getLSP(), collectionLSP); + assertSame(selectedPlan.getInitialShipmentAssigner(), assigner); + assertSame(selectedPlan.getLogisticChains().iterator().next(), logisticChain); + assertSame(selectedPlan.getLogisticChains().iterator().next().getLSP(), collectionLSP); +// assertTrue(selectedPlan.getAssigner().getLSP()== collectionLSP); + assertSame(selectedPlan.getLSP(), collectionLSP); + } + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspCreationTests/CompleteLSPCreationTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspCreationTests/CompleteLSPCreationTest.java new file mode 100644 index 00000000000..9b347e5055b --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspCreationTests/CompleteLSPCreationTest.java @@ -0,0 +1,232 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspCreationTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.core.config.Config; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class CompleteLSPCreationTest { + private LSP completeLSP; + private InitialShipmentAssigner assigner; + private LogisticChain logisticChain; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50/3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50/3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = collectionCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(collectionCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + LSPResource mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .build(); + + LogisticChainElement mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + TranshipmentHubSchedulerBuilder secondSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + secondSchedulerBuilder.setCapacityNeedFixed(10); + secondSchedulerBuilder.setCapacityNeedLinear(1); + + + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + + TransshipmentHubBuilder secondTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(secondTransshipmentHubId, secondTransshipmentHub_LinkId, scenario); + secondTransshipmentHubBuilder.setTransshipmentHubScheduler(secondSchedulerBuilder.build()); + LSPResource secondTranshipmentHubResource = secondTransshipmentHubBuilder.build(); + + Id secondHubElementId = Id.create("SecondHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTranshipmentHubResource); + LogisticChainElement secondHubElement = secondHubElementBuilder.build(); + + Id distributionCarrierId = Id.create("DistributionCarrier", Carrier.class); + Id distributionVehTypeId = Id.create("DistributionCarrierVehicleType", VehicleType.class); + VehicleType distributionVehType = VehicleUtils.createVehicleType(distributionVehTypeId, TransportMode.car); + distributionVehType.getCapacity().setOther(10); + distributionVehType.getCostInformation().setCostsPerMeter(0.0004); + distributionVehType.getCostInformation().setCostsPerSecond(0.38); + distributionVehType.getCostInformation().setFixedCost(49.); + distributionVehType.setMaximumVelocity(50 / 3.6); + distributionVehType.setNetworkMode(TransportMode.car); + + Id distributionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id distributionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle distributionCarrierVehicle = CarrierVehicle.newInstance(distributionVehicleId, distributionLinkId, distributionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(distributionCarrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities distributionCapabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(distributionCarrierId); + carrier.setCarrierCapabilities(distributionCapabilities); + + + LSPResource distributionResource = ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(carrier) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .setLocationLinkId(distributionLinkId) + .build(); + + Id distributionElementId = Id.create("DistributionElement", LogisticChainElement.class); + LogisticChainElement distributionElement= LSPUtils.LogisticChainElementBuilder.newInstance(distributionElementId) + .setResource(distributionResource) + .build(); + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + secondHubElement.connectWithNextElement(distributionElement); + + final Id chainId = Id.create("SolutionId", LogisticChain.class); + logisticChain = LSPUtils.LogisticChainBuilder.newInstance(chainId).addLogisticChainElement(collectionElement) + .addLogisticChainElement(firstHubElement) + .addLogisticChainElement(mainRunElement) + .addLogisticChainElement(secondHubElement) + .addLogisticChainElement(distributionElement) + .build(); + + assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(logisticChain); + + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + resourcesList.add(secondTranshipmentHubResource); + resourcesList.add(distributionResource); + + completeLSP = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)) + .setInitialPlan(completePlan) + .setLogisticChainScheduler(ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList)) + .build(); + } + + @Test + public void testCollectionLSPCreation() { + assertNotNull(completeLSP.getPlans()); + assertFalse(completeLSP.getPlans().isEmpty()); + assertNotNull(completeLSP.getResources()); + LSPPlan selectedPlan = completeLSP.getSelectedPlan(); + assertNull(selectedPlan.getScore()); + assertSame(selectedPlan.getLSP(), completeLSP); + assertSame(selectedPlan.getInitialShipmentAssigner(), assigner); + assertSame(selectedPlan.getLogisticChains().iterator().next(), logisticChain); + assertSame(selectedPlan.getLogisticChains().iterator().next().getLSP(), completeLSP); +// assertTrue(selectedPlan.getAssigner().getLSP()== completeLSP); + assertSame(selectedPlan.getLSP(), completeLSP); + } + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/CollectionLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/CollectionLSPMobsimTest.java new file mode 100644 index 00000000000..df196d86233 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/CollectionLSPMobsimTest.java @@ -0,0 +1,245 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; +import static org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler; +import static org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.events.handler.BasicEventHandler; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class CollectionLSPMobsimTest { + + private static final Logger log = LogManager.getLogger(CollectionLSPMobsimTest.class); + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private LSP collectionLSP; + private Carrier carrier; + private LSPResource collectionResource; + + @BeforeEach + public void initialize() { + + // create config: + Config config = ConfigUtils.createConfig(); + config.network().setInputFile("scenarios/2regions/2regions-network.xml"); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(0); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + // load scenario: + Scenario scenario = ScenarioUtils.loadScenario(config); + + // define vehicle type: + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50/3.6); + + // define starting link (?): + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Link collectionLink = scenario.getNetwork().getLinks().get(collectionLinkId); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLink.getId(), collectionVehType); + + // define carrier: + Id carrierId = Id.create("CollectionCarrier", Carrier.class); + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(carrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities capabilities = capabilitiesBuilder.build(); + carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + + + collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(carrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)).setLocationLinkId(collectionLinkId) + .build(); + + final LogisticChainElement collectionElement; + { + Id elementId = Id.create("CollectionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder collectionElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(elementId); + collectionElementBuilder.setResource(collectionResource); + collectionElement = collectionElementBuilder.build(); + } + final LogisticChain collectionSolution; + { + Id collectionSolutionId = Id.create("CollectionSolution", LogisticChain.class); + LSPUtils.LogisticChainBuilder collectionSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(collectionSolutionId); + collectionSolutionBuilder.addLogisticChainElement(collectionElement); + collectionSolution = collectionSolutionBuilder.build(); + } + final LSPPlan collectionPlan; + { + InitialShipmentAssigner assigner = createSingleLogisticChainShipmentAssigner(); + collectionPlan = LSPUtils.createLSPPlan(); + collectionPlan.setInitialShipmentAssigner(assigner); + collectionPlan.addLogisticChain(collectionSolution); + } + { + final LSPUtils.LSPBuilder collectionLSPBuilder; + ArrayList resourcesList = new ArrayList<>(); + collectionLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + collectionLSPBuilder.setInitialPlan(collectionPlan); + resourcesList.add(collectionResource); + LogisticChainScheduler simpleScheduler = createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + collectionLSPBuilder.setLogisticChainScheduler(simpleScheduler); + collectionLSP = collectionLSPBuilder.build(); + } + { + List linkList = new LinkedList<>(scenario.getNetwork().getLinks().values()); + for (int i = 1; i < 2; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = 1 + MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + builder.setToLinkId(collectionLinkId); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + collectionLSP.assignShipmentToLSP(shipment); + } + collectionLSP.scheduleLogisticChains(); + } + final LSPs lsps; + { + ArrayList lspList = new ArrayList<>(); + lspList.add(collectionLSP); + lsps = new LSPs(lspList); + } + Controller controller = ControllerUtils.createController(scenario); + controller.getEvents().addHandler((BasicEventHandler) event -> log.warn(event)); + + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + + LSPUtils.addLSPs(scenario, lsps); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } + + @Test + public void testCollectionLSPMobsim() { + for (LspShipment shipment : collectionLSP.getLspShipments()) { + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + + log.warn(""); + log.warn("shipment schedule plan elements:"); + for (LspShipmentPlanElement planElement : LspShipmentUtils.getOrCreateShipmentPlan(collectionLSP.getSelectedPlan(), shipment.getId()).getPlanElements().values()) { + log.warn(planElement); + } + log.warn(""); + log.warn("shipment log plan elements:"); + for (LspShipmentPlanElement planElement : shipment.getShipmentLog().getPlanElements().values()) { + log.warn(planElement); + } + log.warn(""); + + assertEquals(LspShipmentUtils.getOrCreateShipmentPlan(collectionLSP.getSelectedPlan(), shipment.getId()).getPlanElements().size(), shipment.getShipmentLog().getPlanElements().size()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(collectionLSP.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + //Das muss besser in den SchedulingTest rein + assertSame(collectionLSP.getResources().iterator().next(), collectionResource); + LSPCarrierResource carrierResource = (LSPCarrierResource) collectionResource; + assertSame(carrierResource.getCarrier(), carrier); + assertEquals(1, carrier.getServices().size()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/CompleteLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/CompleteLSPMobsimTest.java new file mode 100644 index 00000000000..4a17e1dbc4d --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/CompleteLSPMobsimTest.java @@ -0,0 +1,332 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.*; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class CompleteLSPMobsimTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private LSP completeLSP; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50 / 3.6); + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + LSPResource mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .build(); + + LogisticChainElement mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + TranshipmentHubSchedulerBuilder secondSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + secondSchedulerBuilder.setCapacityNeedFixed(10); + secondSchedulerBuilder.setCapacityNeedLinear(1); + + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + + TransshipmentHubBuilder secondTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(secondTransshipmentHubId, secondTransshipmentHub_LinkId, scenario); + + secondTransshipmentHubBuilder.setTransshipmentHubScheduler(secondSchedulerBuilder.build()); + LSPResource secondTranshipmentHubResource = secondTransshipmentHubBuilder.build(); + + Id secondHubElementId = Id.create("SecondHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTranshipmentHubResource); + LogisticChainElement secondHubElement = secondHubElementBuilder.build(); + + Id distributionCarrierId = Id.create("DistributionCarrier", Carrier.class); + Id distributionVehTypeId = Id.create("DistributionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType distributionVehType = VehicleUtils.createVehicleType(distributionVehTypeId, TransportMode.car); + distributionVehType.getCapacity().setOther(10); + distributionVehType.getCostInformation().setCostsPerMeter(0.0004); + distributionVehType.getCostInformation().setCostsPerSecond(0.38); + distributionVehType.getCostInformation().setFixedCost(49.); + distributionVehType.setMaximumVelocity(50 / 3.6); + + Id distributionLinkId = Id.createLinkId("(14 2) (14 3)"); + Id distributionVehicleId = Id.createVehicleId("DistributionVehicle"); + CarrierVehicle distributionCarrierVehicle = CarrierVehicle.newInstance(distributionVehicleId, distributionLinkId, distributionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(distributionCarrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities distributionCapabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(distributionCarrierId); + carrier.setCarrierCapabilities(distributionCapabilities); + + LSPResource distributionResource = ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(carrier) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .setLocationLinkId(distributionLinkId) + .build(); + + Id distributionElementId = Id.create("DistributionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder distributionBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(distributionElementId); + distributionBuilder.setResource(distributionResource); + LogisticChainElement distributionElement = distributionBuilder.build(); + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + secondHubElement.connectWithNextElement(distributionElement); + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + completeSolutionBuilder.addLogisticChainElement(mainRunElement); + completeSolutionBuilder.addLogisticChainElement(secondHubElement); + completeSolutionBuilder.addLogisticChainElement(distributionElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + resourcesList.add(secondTranshipmentHubResource); + resourcesList.add(distributionResource); + + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + completeLSP = completeLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + Random rand = new Random(1); + for (int i = 1; i < 2; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = 1 + rand.nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, rand); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList, rand); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + completeLSP.assignShipmentToLSP(shipment); + } + completeLSP.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(completeLSP); + LSPs lsps = new LSPs(lspList); + + LSPUtils.addLSPs(scenario, lsps); + + Controller controller = ControllerUtils.createController(scenario); + + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + + + config.controller().setFirstIteration(0); + config.controller().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } + + @Test + public void testFirstReloadLSPMobsim() { + for (LspShipment shipment : completeLSP.getLspShipments()) { + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(completeLSP.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} + diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/FirstAndSecondReloadLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/FirstAndSecondReloadLSPMobsimTest.java new file mode 100644 index 00000000000..3294ed1b7c2 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/FirstAndSecondReloadLSPMobsimTest.java @@ -0,0 +1,303 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class FirstAndSecondReloadLSPMobsimTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private LSP lsp; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50 / 3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + LSPResource mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .build(); + + LogisticChainElement mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + TranshipmentHubSchedulerBuilder secondSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + secondSchedulerBuilder.setCapacityNeedFixed(10); + secondSchedulerBuilder.setCapacityNeedLinear(1); + + + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + + TransshipmentHubBuilder secondTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(secondTransshipmentHubId, secondTransshipmentHub_LinkId, scenario); + secondTransshipmentHubBuilder.setTransshipmentHubScheduler(secondSchedulerBuilder.build()); + LSPResource secondTranshipmentHubResource = secondTransshipmentHubBuilder.build(); + + Id secondHubElementId = Id.create("SecondHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTranshipmentHubResource); + LogisticChainElement secondHubElement = secondHubElementBuilder.build(); + + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + completeSolutionBuilder.addLogisticChainElement(mainRunElement); + completeSolutionBuilder.addLogisticChainElement(secondHubElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + resourcesList.add(secondTranshipmentHubResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + + for (int i = 1; i < 2; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = 1 + MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(lsp); + LSPs lsps = new LSPs(lspList); + + LSPUtils.addLSPs(scenario, lsps); + + Controller controller = ControllerUtils.createController(scenario); + + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } + + @Test + public void testFirstReloadLSPMobsim() { + for (LspShipment shipment : lsp.getLspShipments()) { + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + assertEquals(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size(), shipment.getShipmentLog().getPlanElements().size()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/FirstReloadLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/FirstReloadLSPMobsimTest.java new file mode 100644 index 00000000000..d5ba96be6d0 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/FirstReloadLSPMobsimTest.java @@ -0,0 +1,249 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class FirstReloadLSPMobsimTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + + private LSP lsp; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + collectionElement.connectWithNextElement(firstHubElement); + + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + LinkedList resourcesList = new LinkedList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + + for (int i = 1; i < 2; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + //Random random = new Random(1); + int capacityDemand = 1 + MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(lsp); + LSPs lsps = new LSPs(lspList); + LSPUtils.addLSPs(scenario, lsps); + + Controller controller = ControllerUtils.createController(scenario); + + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } + + @Test + public void testFirstReloadLSPMobsim() { + + for (LspShipment shipment : lsp.getLspShipments()) { + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + assertEquals(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size(), shipment.getShipmentLog().getPlanElements().size()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MainRunLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MainRunLSPMobsimTest.java new file mode 100644 index 00000000000..aac62ebf43a --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MainRunLSPMobsimTest.java @@ -0,0 +1,279 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MainRunLSPMobsimTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private LSP lsp; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50 / 3.6); + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + LSPResource mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .build(); + + LogisticChainElement mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + completeSolutionBuilder.addLogisticChainElement(mainRunElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + + for (int i = 1; i < 2; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = 1 + MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(lsp); + LSPs lsps = new LSPs(lspList); + + LSPUtils.addLSPs(scenario, lsps); + + Controller controller = ControllerUtils.createController(scenario); + + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } + + @Test + public void testFirstReloadLSPMobsim() { + for (LspShipment shipment : lsp.getLspShipments()) { + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + assertEquals(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size(), shipment.getShipmentLog().getPlanElements().size()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MainRunOnlyLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MainRunOnlyLSPMobsimTest.java new file mode 100644 index 00000000000..57a4886fba3 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MainRunOnlyLSPMobsimTest.java @@ -0,0 +1,227 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MainRunOnlyLSPMobsimTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private LSP lsp; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50 / 3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + LSPResource mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .build(); + + LogisticChainElement mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + + completeSolutionBuilder.addLogisticChainElement(mainRunElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + + resourcesList.add(mainRunResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + + for (int i = 1; i < 2; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = 1 + MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(lsp); + LSPs lsps = new LSPs(lspList); + + LSPUtils.addLSPs(scenario, lsps); + + Controller controller = ControllerUtils.createController(scenario); + + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } + + @Test + public void testFirstReloadLSPMobsim() { + for (LspShipment shipment : lsp.getLspShipments()) { + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + assertEquals(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size(), shipment.getShipmentLog().getPlanElements().size()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsCollectionLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsCollectionLSPMobsimTest.java new file mode 100644 index 00000000000..910cd4ce3ea --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsCollectionLSPMobsimTest.java @@ -0,0 +1,226 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.RandomPlanSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.CollectionCarrierResourceBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MultipleIterationsCollectionLSPMobsimTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + + private LSP collectionLSP; + + @BeforeEach + public void initialize() { + + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + Id carrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Link collectionLink = network.getLinks().get(collectionLinkId); + CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(Id.createVehicleId("CollectionVehicle"), collectionLink.getId(), collectionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(carrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities capabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + + Id.create("CollectionCarrierResource", LSPResource.class); + CollectionCarrierResourceBuilder adapterBuilder = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(carrier); + adapterBuilder.setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)); + adapterBuilder.setLocationLinkId(collectionLinkId); + LSPResource collectionResource = adapterBuilder.build(); + + Id elementId = Id.create("CollectionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder collectionElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(elementId); + collectionElementBuilder.setResource(collectionResource); + LogisticChainElement collectionElement = collectionElementBuilder.build(); + + Id collectionSolutionId = Id.create("CollectionSolution", LogisticChain.class); + LSPUtils.LogisticChainBuilder collectionSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(collectionSolutionId); + collectionSolutionBuilder.addLogisticChainElement(collectionElement); + LogisticChain collectionSolution = collectionSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan collectionPlan = LSPUtils.createLSPPlan(); + collectionPlan.setInitialShipmentAssigner(assigner); + collectionPlan.addLogisticChain(collectionSolution); + + LSPUtils.LSPBuilder collectionLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + collectionLSPBuilder.setInitialPlan(collectionPlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + collectionLSPBuilder.setLogisticChainScheduler(simpleScheduler); + collectionLSP = collectionLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + + int numberOfShipments = 1 + MatsimRandom.getRandom().nextInt(50); + for (int i = 1; i < 1 + numberOfShipments; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + //Random random = new Random(1); + int capacityDemand = 1 + MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + builder.setToLinkId(collectionLinkId); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + collectionLSP.assignShipmentToLSP(shipment); + } + collectionLSP.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(collectionLSP); + LSPs lsps = new LSPs(lspList); + + Controller controller = ControllerUtils.createController(scenario); + + LSPUtils.addLSPs(scenario, lsps); + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + controller.addOverridingModule( new AbstractModule(){ + @Override public void install(){ + bind( LSPStrategyManager.class ).toInstance( new LSPModule.LSPStrategyManagerEmptyImpl() ); + bind( CarrierStrategyManager.class ).toProvider(() -> { + CarrierStrategyManager strategyManager = CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new RandomPlanSelector<>()), null, 1); + return strategyManager; + }); + } + } ); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(1 + MatsimRandom.getRandom().nextInt(10)); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } + + @Test + public void testCollectionLSPMobsim() { + + for (LspShipment shipment : collectionLSP.getLspShipments()) { + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + assertEquals(LspShipmentUtils.getOrCreateShipmentPlan(collectionLSP.getSelectedPlan(), shipment.getId()).getPlanElements().size(), shipment.getShipmentLog().getPlanElements().size()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(collectionLSP.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsCompleteLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsCompleteLSPMobsimTest.java new file mode 100644 index 00000000000..8b2a05157c6 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsCompleteLSPMobsimTest.java @@ -0,0 +1,359 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.RandomPlanSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.examples.lspReplanning.AssignmentStrategyFactory; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MultipleIterationsCompleteLSPMobsimTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private LSP completeLSP; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50 / 3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + LSPResource mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .build(); + + LogisticChainElement mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + TranshipmentHubSchedulerBuilder secondSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + secondSchedulerBuilder.setCapacityNeedFixed(10); + secondSchedulerBuilder.setCapacityNeedLinear(1); + + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + + TransshipmentHubBuilder secondTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(secondTransshipmentHubId, secondTransshipmentHub_LinkId, scenario); + + secondTransshipmentHubBuilder.setTransshipmentHubScheduler(secondSchedulerBuilder.build()); + LSPResource secondTranshipmentHubResource = secondTransshipmentHubBuilder.build(); + + Id secondHubElementId = Id.create("SecondHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTranshipmentHubResource); + LogisticChainElement secondHubElement = secondHubElementBuilder.build(); + + Id distributionCarrierId = Id.create("DistributionCarrier", Carrier.class); + Id distributionVehTypeId = Id.create("DistributionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType distributionVehType = VehicleUtils.createVehicleType(distributionVehTypeId, TransportMode.car); + distributionVehType.getCapacity().setOther(10); + distributionVehType.getCostInformation().setCostsPerMeter(0.0004); + distributionVehType.getCostInformation().setCostsPerSecond(0.38); + distributionVehType.getCostInformation().setFixedCost(49.); + distributionVehType.setMaximumVelocity(50 / 3.6); + + Id distributionLinkId = Id.createLinkId("(14 2) (14 3)"); + Id distributionVehicleId = Id.createVehicleId("DistributionVehicle"); + CarrierVehicle distributionCarrierVehicle = CarrierVehicle.newInstance(distributionVehicleId, distributionLinkId, distributionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(distributionCarrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities distributionCapabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(distributionCarrierId); + carrier.setCarrierCapabilities(distributionCapabilities); + + LSPResource distributionResource = ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(carrier) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .setLocationLinkId(distributionLinkId) + .build(); + + Id distributionElementId = Id.create("DistributionElement", LogisticChainElement.class); + LogisticChainElement distributionElement = LSPUtils.LogisticChainElementBuilder.newInstance(distributionElementId) + .setResource(distributionResource) + .build(); + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + secondHubElement.connectWithNextElement(distributionElement); + + final Id chainId = Id.create("SolutionId", LogisticChain.class); + LogisticChain completeSolution = LSPUtils.LogisticChainBuilder.newInstance(chainId) + .addLogisticChainElement(collectionElement) + .addLogisticChainElement(firstHubElement) + .addLogisticChainElement(mainRunElement) + .addLogisticChainElement(secondHubElement) + .addLogisticChainElement(distributionElement) + .build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + resourcesList.add(secondTranshipmentHubResource); + resourcesList.add(distributionResource); + + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + completeLSP = completeLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + //Random rand = new Random(1); + int numberOfShipments = MatsimRandom.getRandom().nextInt(50); + + for (int i = 1; i < 1 + numberOfShipments; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = 1 + MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + completeLSP.assignShipmentToLSP(shipment); + } + completeLSP.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(completeLSP); + LSPs lsps = new LSPs(lspList); + + Controller controller = ControllerUtils.createController(scenario); + + LSPUtils.addLSPs(scenario, lsps); + controller.addOverridingModule(new LSPModule()); + controller.addOverridingModule( new AbstractModule(){ + @Override public void install(){ + bind( LSPStrategyManager.class ).toProvider(() -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy(new AssignmentStrategyFactory().createStrategy(), null, 1); + return strategyManager; + }); + bind( CarrierStrategyManager.class ).toProvider(() -> { + CarrierStrategyManager strategyManager = CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new RandomPlanSelector<>()), null, 1); + return strategyManager; + }); + } + } ); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(1 + MatsimRandom.getRandom().nextInt(10)); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + for (LSP lsp : LSPUtils.getLSPs(controller.getScenario()).getLSPs().values()) { + ResourceImplementationUtils.printResults_shipmentPlan(controller.getControlerIO().getOutputPath(), lsp); + ResourceImplementationUtils.printResults_shipmentLog(controller.getControlerIO().getOutputPath(), lsp); + } + } + + @Test + public void testCompleteLSPMobsim() { + for (LspShipment shipment : completeLSP.getLspShipments()) { + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(completeLSP.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } + +} + + + diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsFirstAndSecondReloadLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsFirstAndSecondReloadLSPMobsimTest.java new file mode 100644 index 00000000000..14d2f7a263f --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsFirstAndSecondReloadLSPMobsimTest.java @@ -0,0 +1,318 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.RandomPlanSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.examples.lspReplanning.AssignmentStrategyFactory; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MultipleIterationsFirstAndSecondReloadLSPMobsimTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private LSP lsp; + + @BeforeEach + public void initialize() { + //Todo/Fixme: In the result there only the second hub is used. -- see Issue #170. KMT Nov'23 + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50 / 3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + LSPResource mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .build(); + + LogisticChainElement mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + TranshipmentHubSchedulerBuilder secondSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + secondSchedulerBuilder.setCapacityNeedFixed(10); + secondSchedulerBuilder.setCapacityNeedLinear(1); + + + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + + TransshipmentHubBuilder secondTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(secondTransshipmentHubId, secondTransshipmentHub_LinkId, scenario); + secondTransshipmentHubBuilder.setTransshipmentHubScheduler(secondSchedulerBuilder.build()); + LSPResource secondTranshipmentHubResource = secondTransshipmentHubBuilder.build(); + + Id secondHubElementId = Id.create("SecondHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTranshipmentHubResource); + LogisticChainElement secondHubElement = secondHubElementBuilder.build(); + + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + completeSolutionBuilder.addLogisticChainElement(mainRunElement); + completeSolutionBuilder.addLogisticChainElement(secondHubElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + resourcesList.add(secondTranshipmentHubResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + int numberOfShipments = 1 + MatsimRandom.getRandom().nextInt(50); + for (int i = 1; i < 1 + numberOfShipments; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = 1 + MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(lsp); + LSPs lsps = new LSPs(lspList); + + Controller controller = ControllerUtils.createController(scenario); + + LSPUtils.addLSPs(scenario, lsps); + controller.addOverridingModule(new LSPModule()); + controller.addOverridingModule( new AbstractModule(){ + @Override public void install(){ + bind( LSPStrategyManager.class ).toProvider(() -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy(new AssignmentStrategyFactory().createStrategy(), null, 1); + return strategyManager; + }); + bind( CarrierStrategyManager.class ).toProvider(() -> { + CarrierStrategyManager strategyManager = CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new RandomPlanSelector<>()), null, 1); + return strategyManager; + }); + } + } ); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(1 + MatsimRandom.getRandom().nextInt(10)); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } + + @Test + public void testFirstReloadLSPMobsim() { + for (LspShipment shipment : lsp.getLspShipments()) { + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + assertEquals(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size(), shipment.getShipmentLog().getPlanElements().size()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + //Please note, that this result contains also reloading / hubHandlingStarts after the main run (even if there is no further distribution carrier) + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsFirstReloadLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsFirstReloadLSPMobsimTest.java new file mode 100644 index 00000000000..fb6fb93f516 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsFirstReloadLSPMobsimTest.java @@ -0,0 +1,262 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.RandomPlanSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.examples.lspReplanning.AssignmentStrategyFactory; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MultipleIterationsFirstReloadLSPMobsimTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + + private LSP lsp; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(Id.createVehicleId("CollectionVehicle"), collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + collectionElement.connectWithNextElement(firstHubElement); + + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + int numberOfShipments = 1 + MatsimRandom.getRandom().nextInt(50); + + for (int i = 1; i < 1 + numberOfShipments; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + //Random random = new Random(1); + int capacityDemand = 1 + MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(lsp); + LSPs lsps = new LSPs(lspList); + + Controller controller = ControllerUtils.createController(scenario); + + LSPUtils.addLSPs(scenario, lsps); + controller.addOverridingModule(new LSPModule()); + controller.addOverridingModule( new AbstractModule(){ + @Override public void install(){ + bind( LSPStrategyManager.class ).toProvider(() -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy(new AssignmentStrategyFactory().createStrategy(), null, 1); + return strategyManager; + }); + bind( CarrierStrategyManager.class ).toProvider(() -> { + CarrierStrategyManager strategyManager = CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new RandomPlanSelector<>()), null, 1); + return strategyManager; + }); + } + } ); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(1 + MatsimRandom.getRandom().nextInt(10)); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } + + @Test + public void testFirstReloadLSPMobsim() { + + for (LspShipment shipment : lsp.getLspShipments()) { + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + assertEquals(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size(), shipment.getShipmentLog().getPlanElements().size()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsMainRunLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsMainRunLSPMobsimTest.java new file mode 100644 index 00000000000..8dac1d91417 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsMainRunLSPMobsimTest.java @@ -0,0 +1,302 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.RandomPlanSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.examples.lspReplanning.AssignmentStrategyFactory; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +@SuppressWarnings("ALL") +public class MultipleIterationsMainRunLSPMobsimTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private LSP lsp; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50/3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + LSPResource mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .build(); + + LogisticChainElement mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + completeSolutionBuilder.addLogisticChainElement(mainRunElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + + int numberOfShipments = 1 + MatsimRandom.getRandom().nextInt(50); + for (int i = 1; i < 1 + numberOfShipments; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = 1 + MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(lsp); + LSPs lsps = new LSPs(lspList); + + Controller controller = ControllerUtils.createController(scenario); + + LSPUtils.addLSPs(scenario, lsps); + controller.addOverridingModule(new LSPModule()); + controller.addOverridingModule( new AbstractModule(){ + @Override public void install(){ + bind( LSPStrategyManager.class ).toProvider(() -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy(new AssignmentStrategyFactory().createStrategy(), null, 1); + return strategyManager; + }); + bind( CarrierStrategyManager.class ).toProvider(() -> { + CarrierStrategyManager strategyManager = CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new RandomPlanSelector<>()), null, 1); + return strategyManager; + }); + } + } ); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(1 + MatsimRandom.getRandom().nextInt(10)); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + for (LSP lsp : LSPUtils.getLSPs(controller.getScenario()).getLSPs().values()) { + ResourceImplementationUtils.printResults_shipmentPlan(controller.getControlerIO().getOutputPath(), lsp); + ResourceImplementationUtils.printResults_shipmentLog(controller.getControlerIO().getOutputPath(), lsp); + } + + } + + @Test + public void testFirstReloadLSPMobsim() { + for (LspShipment shipment : lsp.getLspShipments()) { + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + assertEquals(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size(), shipment.getShipmentLog().getPlanElements().size()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsCollectionLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsCollectionLSPMobsimTest.java new file mode 100644 index 00000000000..6a6c4aafdb6 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsCollectionLSPMobsimTest.java @@ -0,0 +1,211 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.CollectionCarrierResourceBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MultipleShipmentsCollectionLSPMobsimTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private LSP collectionLSP; + + @BeforeEach + public void initialize() { + + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + Id carrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType vehicleType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + vehicleType.getCapacity().setOther(10); + vehicleType.getCostInformation().setCostsPerMeter(0.0004); + vehicleType.getCostInformation().setCostsPerSecond(0.38); + vehicleType.getCostInformation().setFixedCost(49.); + vehicleType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Link collectionLink = network.getLinks().get(collectionLinkId); + CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(Id.createVehicleId("CollectionVehicle"), collectionLink.getId(), vehicleType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(carrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities capabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + + Id.create("CollectionCarrierResource", LSPResource.class); + CollectionCarrierResourceBuilder adapterBuilder = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(carrier); + adapterBuilder.setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)); + adapterBuilder.setLocationLinkId(collectionLinkId); + LSPResource collectionResource = adapterBuilder.build(); + + Id elementId = Id.create("CollectionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder collectionElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(elementId); + collectionElementBuilder.setResource(collectionResource); + LogisticChainElement collectionElement = collectionElementBuilder.build(); + + Id collectionSolutionId = Id.create("CollectionSolution", LogisticChain.class); + LSPUtils.LogisticChainBuilder collectionSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(collectionSolutionId); + collectionSolutionBuilder.addLogisticChainElement(collectionElement); + LogisticChain collectionSolution = collectionSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan collectionPlan = LSPUtils.createLSPPlan(); + collectionPlan.setInitialShipmentAssigner(assigner); + collectionPlan.addLogisticChain(collectionSolution); + + LSPUtils.LSPBuilder collectionLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + collectionLSPBuilder.setInitialPlan(collectionPlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + collectionLSPBuilder.setLogisticChainScheduler(simpleScheduler); + collectionLSP = collectionLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + + int numberOfShipments = 1 + MatsimRandom.getRandom().nextInt(50); + for (int i = 1; i < 1 + numberOfShipments; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + //Random random = new Random(1); + int capacityDemand = 1 + MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + builder.setToLinkId(collectionLinkId); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + collectionLSP.assignShipmentToLSP(shipment); + } + collectionLSP.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(collectionLSP); + LSPs lsps = new LSPs(lspList); + + Controller controller = ControllerUtils.createController(scenario); + + LSPUtils.addLSPs(scenario, lsps); + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } + + @Test + public void testCollectionLSPMobsim() { + + for (LspShipment shipment : collectionLSP.getLspShipments()) { + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + assertEquals(LspShipmentUtils.getOrCreateShipmentPlan(collectionLSP.getSelectedPlan(), shipment.getId()).getPlanElements().size(), shipment.getShipmentLog().getPlanElements().size()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(collectionLSP.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsCompleteLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsCompleteLSPMobsimTest.java new file mode 100644 index 00000000000..984027f50d9 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsCompleteLSPMobsimTest.java @@ -0,0 +1,360 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.RandomPlanSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.examples.lspReplanning.AssignmentStrategyFactory; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MultipleShipmentsCompleteLSPMobsimTest { + + private static final Logger log = LogManager.getLogger(MultipleShipmentsCompleteLSPMobsimTest.class); + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private LSP completeLSP; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50 / 3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + LSPResource mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .build(); + + LogisticChainElement mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + TranshipmentHubSchedulerBuilder secondSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + secondSchedulerBuilder.setCapacityNeedFixed(10); + secondSchedulerBuilder.setCapacityNeedLinear(1); + + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + + TransshipmentHubBuilder secondTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(secondTransshipmentHubId, secondTransshipmentHub_LinkId, scenario); + + secondTransshipmentHubBuilder.setTransshipmentHubScheduler(secondSchedulerBuilder.build()); + LSPResource secondTranshipmentHubResource = secondTransshipmentHubBuilder.build(); + + Id secondHubElementId = Id.create("SecondHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTranshipmentHubResource); + LogisticChainElement secondHubElement = secondHubElementBuilder.build(); + + Id distributionCarrierId = Id.create("DistributionCarrier", Carrier.class); + Id distributionVehTypeId = Id.create("DistributionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType distributionVehType = VehicleUtils.createVehicleType(distributionVehTypeId, TransportMode.car); + distributionVehType.getCapacity().setOther(10); + distributionVehType.getCostInformation().setCostsPerMeter(0.0004); + distributionVehType.getCostInformation().setCostsPerSecond(0.38); + distributionVehType.getCostInformation().setFixedCost(49.); + distributionVehType.setMaximumVelocity(50 / 3.6); + + Id distributionLinkId = Id.createLinkId("(14 2) (14 3)"); + Id distributionVehicleId = Id.createVehicleId("DistributionVehicle"); + CarrierVehicle distributionCarrierVehicle = CarrierVehicle.newInstance(distributionVehicleId, distributionLinkId, distributionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(distributionCarrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities distributionCapabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(distributionCarrierId); + carrier.setCarrierCapabilities(distributionCapabilities); + + + LSPResource distributionResource = ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(carrier) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .setLocationLinkId(distributionLinkId) + .build(); + + Id distributionElementId = Id.create("DistributionElement", LogisticChainElement.class); + LogisticChainElement distributionElement= LSPUtils.LogisticChainElementBuilder.newInstance(distributionElementId) + .setResource(distributionResource) + .build(); + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + secondHubElement.connectWithNextElement(distributionElement); + + final Id chainId = Id.create("SolutionId", LogisticChain.class); + LogisticChain completeSolution = LSPUtils.LogisticChainBuilder.newInstance(chainId) + .addLogisticChainElement(collectionElement) + .addLogisticChainElement(firstHubElement) + .addLogisticChainElement(mainRunElement) + .addLogisticChainElement(secondHubElement) + .addLogisticChainElement(distributionElement) + .build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + resourcesList.add(secondTranshipmentHubResource); + resourcesList.add(distributionResource); + + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + completeLSP = completeLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + //Random rand = new Random(1); + int numberOfShipments = MatsimRandom.getRandom().nextInt(50); + + for (int i = 1; i < 1 + numberOfShipments; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = 1 + MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + completeLSP.assignShipmentToLSP(shipment); + } + completeLSP.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(completeLSP); + LSPs lsps = new LSPs(lspList); + + Controller controller = ControllerUtils.createController(scenario); + + LSPUtils.addLSPs(scenario, lsps); + controller.addOverridingModule(new LSPModule()); + controller.addOverridingModule( new AbstractModule(){ + @Override public void install(){ + bind( LSPStrategyManager.class ).toProvider(() -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy(new AssignmentStrategyFactory().createStrategy(), null, 1); + return strategyManager; + }); + bind( CarrierStrategyManager.class ).toProvider(() -> { + CarrierStrategyManager strategyManager = CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new RandomPlanSelector<>()), null, 1); + return strategyManager; + }); + } + } ); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(1 + MatsimRandom.getRandom().nextInt(10)); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + for (LSP lsp : LSPUtils.getLSPs(controller.getScenario()).getLSPs().values()) { + ResourceImplementationUtils.printResults_shipmentPlan(controller.getControlerIO().getOutputPath(), lsp); + ResourceImplementationUtils.printResults_shipmentLog(controller.getControlerIO().getOutputPath(), lsp); + } + } + + @Test + public void testCompleteLSPMobsim() { + for (LspShipment shipment : completeLSP.getLspShipments()) { + log.info("comparing shipment: {}", shipment.getId()); + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(completeLSP.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} + diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsFirstAndSecondReloadLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsFirstAndSecondReloadLSPMobsimTest.java new file mode 100644 index 00000000000..37d260c2f28 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsFirstAndSecondReloadLSPMobsimTest.java @@ -0,0 +1,316 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.RandomPlanSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.carriers.controller.CarrierControllerUtils; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.examples.lspReplanning.AssignmentStrategyFactory; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MultipleShipmentsFirstAndSecondReloadLSPMobsimTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private LSP lsp; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50 / 3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + LSPResource mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .build(); + + LogisticChainElement mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + TranshipmentHubSchedulerBuilder secondSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + secondSchedulerBuilder.setCapacityNeedFixed(10); + secondSchedulerBuilder.setCapacityNeedLinear(1); + + + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + + TransshipmentHubBuilder secondTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(secondTransshipmentHubId, secondTransshipmentHub_LinkId, scenario); + secondTransshipmentHubBuilder.setTransshipmentHubScheduler(secondSchedulerBuilder.build()); + LSPResource secondTranshipmentHubResource = secondTransshipmentHubBuilder.build(); + + Id secondHubElementId = Id.create("SecondHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTranshipmentHubResource); + LogisticChainElement secondHubElement = secondHubElementBuilder.build(); + + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + completeSolutionBuilder.addLogisticChainElement(mainRunElement); + completeSolutionBuilder.addLogisticChainElement(secondHubElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + resourcesList.add(secondTranshipmentHubResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + int numberOfShipments = 1 + MatsimRandom.getRandom().nextInt(50); + for (int i = 1; i < 1 + numberOfShipments; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = 1 + MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(lsp); + LSPs lsps = new LSPs(lspList); + + Controller controller = ControllerUtils.createController(scenario); + + LSPUtils.addLSPs(scenario, lsps); + controller.addOverridingModule(new LSPModule()); + controller.addOverridingModule( new AbstractModule(){ + @Override public void install(){ + bind( LSPStrategyManager.class ).toProvider(() -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy(new AssignmentStrategyFactory().createStrategy(), null, 1); + return strategyManager; + }); + bind( CarrierStrategyManager.class ).toProvider(() -> { + CarrierStrategyManager strategyManager = CarrierControllerUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new RandomPlanSelector<>()), null, 1); + return strategyManager; + }); + } + } ); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(4); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } + + @Test + public void testFirstReloadLSPMobsim() { + for (LspShipment shipment : lsp.getLspShipments()) { + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + assertEquals(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size(), shipment.getShipmentLog().getPlanElements().size()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsFirstReloadLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsFirstReloadLSPMobsimTest.java new file mode 100644 index 00000000000..7b75f3a8fd7 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsFirstReloadLSPMobsimTest.java @@ -0,0 +1,254 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MultipleShipmentsFirstReloadLSPMobsimTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private LSP lsp; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + collectionElement.connectWithNextElement(firstHubElement); + + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + int numberOfShipments = 1 + MatsimRandom.getRandom().nextInt(50); + + for (int i = 1; i < 1 + numberOfShipments; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + //Random random = new Random(1); + int capacityDemand = 1 + MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(lsp); + LSPs lsps = new LSPs(lspList); + + Controller controller = ControllerUtils.createController(scenario); + + LSPUtils.addLSPs(scenario, lsps); + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + for (LSP lsp : LSPUtils.getLSPs(controller.getScenario()).getLSPs().values()) { + ResourceImplementationUtils.printResults_shipmentPlan(controller.getControlerIO().getOutputPath(), lsp); + ResourceImplementationUtils.printResults_shipmentLog(controller.getControlerIO().getOutputPath(), lsp); + } + } + + @Test + public void testFirstReloadLSPMobsim() { + + for (LspShipment shipment : lsp.getLspShipments()) { + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + assertEquals(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size(), shipment.getShipmentLog().getPlanElements().size()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsMainRunLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsMainRunLSPMobsimTest.java new file mode 100644 index 00000000000..d0119ec03a2 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsMainRunLSPMobsimTest.java @@ -0,0 +1,287 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MultipleShipmentsMainRunLSPMobsimTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private LSP lsp; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + collectionVehType.setNetworkMode(TransportMode.car); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50 / 3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + LSPResource mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .build(); + + LogisticChainElement mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + completeSolutionBuilder.addLogisticChainElement(mainRunElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + + int numberOfShipments = 1 + MatsimRandom.getRandom().nextInt(50); + for (int i = 1; i < 1 + numberOfShipments; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = 1 + MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(lsp); + LSPs lsps = new LSPs(lspList); + + Controller controller = ControllerUtils.createController(scenario); + + LSPUtils.addLSPs(scenario, lsps); + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + + for (LSP lsp : LSPUtils.getLSPs(controller.getScenario()).getLSPs().values()) { + ResourceImplementationUtils.printResults_shipmentPlan(controller.getControlerIO().getOutputPath(), lsp); + ResourceImplementationUtils.printResults_shipmentLog(controller.getControlerIO().getOutputPath(), lsp); + } + } + + @Test + public void testFirstReloadLSPMobsim() { + for (LspShipment shipment : lsp.getLspShipments()) { + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + assertEquals(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size(), shipment.getShipmentLog().getPlanElements().size()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/RepeatedMultipleShipmentsCompleteLSPMobsimTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/RepeatedMultipleShipmentsCompleteLSPMobsimTest.java new file mode 100644 index 00000000000..f14a75d3802 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspMobsimTests/RepeatedMultipleShipmentsCompleteLSPMobsimTest.java @@ -0,0 +1,353 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspMobsimTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +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.Scenario; +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.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controller; +import org.matsim.core.controler.ControllerUtils; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class RepeatedMultipleShipmentsCompleteLSPMobsimTest { + + @RegisterExtension + public final MatsimTestUtils utils = new MatsimTestUtils(); + private LSP completeLSP; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + + var freightConfig = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightCarriersConfigGroup.TimeWindowHandling.ignore); + + + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50 / 3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + LSPResource mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .build(); + + LogisticChainElement mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + TranshipmentHubSchedulerBuilder secondSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + secondSchedulerBuilder.setCapacityNeedFixed(10); + secondSchedulerBuilder.setCapacityNeedLinear(1); + + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + + TransshipmentHubBuilder secondTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(secondTransshipmentHubId, secondTransshipmentHub_LinkId, scenario); + + secondTransshipmentHubBuilder.setTransshipmentHubScheduler(secondSchedulerBuilder.build()); + LSPResource secondTranshipmentHubResource = secondTransshipmentHubBuilder.build(); + + Id secondHubElementId = Id.create("SecondHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTranshipmentHubResource); + LogisticChainElement secondHubElement = secondHubElementBuilder.build(); + + Id distributionCarrierId = Id.create("DistributionCarrier", Carrier.class); + Id distributionVehTypeId = Id.create("DistributionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType distributionVehType = VehicleUtils.createVehicleType(distributionVehTypeId, TransportMode.car); + distributionVehType.getCapacity().setOther(10); + distributionVehType.getCostInformation().setCostsPerMeter(0.0004); + distributionVehType.getCostInformation().setCostsPerSecond(0.38); + distributionVehType.getCostInformation().setFixedCost(49.); + distributionVehType.setMaximumVelocity(50 / 3.6); + + Id distributionLinkId = Id.createLinkId("(14 2) (14 3)"); + Id distributionVehicleId = Id.createVehicleId("DistributionVehicle"); + CarrierVehicle distributionCarrierVehicle = CarrierVehicle.newInstance(distributionVehicleId, distributionLinkId, distributionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(distributionCarrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities distributionCapabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(distributionCarrierId); + carrier.setCarrierCapabilities(distributionCapabilities); + + LSPResource distributionResource = ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(carrier) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .setLocationLinkId(distributionLinkId) + .build(); + + Id distributionElementId = Id.create("DistributionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder distributionBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(distributionElementId); + distributionBuilder.setResource(distributionResource); + LogisticChainElement distributionElement = distributionBuilder.build(); + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + secondHubElement.connectWithNextElement(distributionElement); + + final Id chainId = Id.create("SolutionId", LogisticChain.class); + LogisticChain completeSolution = LSPUtils.LogisticChainBuilder.newInstance(chainId) + .addLogisticChainElement(collectionElement) + .addLogisticChainElement(firstHubElement) + .addLogisticChainElement(mainRunElement) + .addLogisticChainElement(secondHubElement) + .addLogisticChainElement(distributionElement) + .build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + resourcesList.add(secondTranshipmentHubResource); + resourcesList.add(distributionResource); + + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + completeLSP = completeLSPBuilder.build(); + + List linkList = new LinkedList<>(network.getLinks().values()); + //Random rand = new Random(1); + int numberOfShipments = MatsimRandom.getRandom().nextInt(50); + + for (int i = 1; i < 1 + numberOfShipments; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = 1 + MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList, MatsimRandom.getRandom()); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + completeLSP.assignShipmentToLSP(shipment); + } + completeLSP.scheduleLogisticChains(); + + ArrayList lspList = new ArrayList<>(); + lspList.add(completeLSP); + LSPs lsps = new LSPs(lspList); + + Controller controller = ControllerUtils.createController(scenario); + + LSPUtils.addLSPs(scenario, lsps); + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + config.controller().setFirstIteration(0); + config.controller().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controller.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controller.run(); + } + + @Test + public void testCompleteLSPMobsim() { + int numberOfIterations = 1 + MatsimRandom.getRandom().nextInt(10); + for (int i = 0; i < numberOfIterations; i++) { + initialize(); + for (LspShipment shipment : completeLSP.getLspShipments()) { + assertFalse(shipment.getShipmentLog().getPlanElements().isEmpty()); + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(completeLSP.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList logElements = new ArrayList<>(shipment.getShipmentLog().getPlanElements().values()); + logElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + for (LspShipmentPlanElement scheduleElement : scheduleElements) { + LspShipmentPlanElement logElement = logElements.get(scheduleElements.indexOf(scheduleElement)); + if (!scheduleElement.getElementType().equals(logElement.getElementType())) { + System.out.println(scheduleElement.getElementType()); + System.out.println(logElement.getElementType()); + for (int j = 0; j < LspShipmentUtils.getOrCreateShipmentPlan(completeLSP.getSelectedPlan(), shipment.getId()).getPlanElements().size(); j++) { + System.out.println("Scheduled: " + scheduleElements.get(j).getLogisticChainElement().getId() + " " + scheduleElements.get(j).getResourceId() + " " + scheduleElements.get(j).getElementType() + " Start: " + scheduleElements.get(j).getStartTime() + " End: " + scheduleElements.get(j).getEndTime()); + } + System.out.println(); + for (int j = 0; j < shipment.getShipmentLog().getPlanElements().size(); j++) { + System.out.println("Logged: " + logElements.get(j).getLogisticChainElement().getId() + " " + logElements.get(j).getResourceId() + " " + logElements.get(j).getElementType() + " Start: " + logElements.get(j).getStartTime() + " End: " + logElements.get(j).getEndTime()); + } + System.out.println(); + } + + assertEquals(scheduleElement.getElementType(), logElement.getElementType()); + assertSame(scheduleElement.getResourceId(), logElement.getResourceId()); + assertSame(scheduleElement.getLogisticChainElement(), logElement.getLogisticChainElement()); + assertEquals(scheduleElement.getStartTime(), logElement.getStartTime(), 300); + } + } + } + } + + @Test + public void compareEvents(){ + MatsimTestUtils.assertEqualEventsFiles(utils.getClassInputDirectory() + "output_events.xml.gz", utils.getOutputDirectory() + "output_events.xml.gz" ); + } +} + diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspPlanTests/CollectionLSPPlanTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspPlanTests/CollectionLSPPlanTest.java new file mode 100644 index 00000000000..06e9f39b5d1 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspPlanTests/CollectionLSPPlanTest.java @@ -0,0 +1,107 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspPlanTests; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.core.config.Config; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.CollectionCarrierResourceBuilder; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class CollectionLSPPlanTest { + + private LogisticChain logisticChain; + private InitialShipmentAssigner assigner; + private LSPPlan collectionPlan; + + @BeforeEach + public void initialize() { + + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + scenario.getNetwork(); + + Id carrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(Id.createVehicleId("CollectionVehicle"), collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(carrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities capabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + + CollectionCarrierResourceBuilder adapterBuilder = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(carrier); + adapterBuilder.setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)); + adapterBuilder.setLocationLinkId(collectionLinkId); + + + Id elementId = Id.create("CollectionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder collectionElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(elementId); + collectionElementBuilder.setResource(adapterBuilder.build()); + LogisticChainElement collectionElement = collectionElementBuilder.build(); + + Id collectionSolutionId = Id.create("CollectionSolution", LogisticChain.class); + LSPUtils.LogisticChainBuilder collectionSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(collectionSolutionId); + collectionSolutionBuilder.addLogisticChainElement(collectionElement); + logisticChain = collectionSolutionBuilder.build(); + + assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + collectionPlan = LSPUtils.createLSPPlan(); + collectionPlan.setInitialShipmentAssigner(assigner); + collectionPlan.addLogisticChain(logisticChain); + } + + @Test + public void collectionLSPPlanTest() { + assertSame(collectionPlan.getInitialShipmentAssigner(), assigner); + assertNull(collectionPlan.getScore()); + assertNull(collectionPlan.getLSP()); + assertEquals(1, collectionPlan.getLogisticChains().size()); + assertSame(collectionPlan.getLogisticChains().iterator().next(), logisticChain); + } + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspPlanTests/CompleteLSPPlanTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspPlanTests/CompleteLSPPlanTest.java new file mode 100644 index 00000000000..58f82a24ebb --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspPlanTests/CompleteLSPPlanTest.java @@ -0,0 +1,216 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspPlanTests; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.core.config.Config; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class CompleteLSPPlanTest { + + private InitialShipmentAssigner assigner; + private LSPPlan completePlan; + private LogisticChain logisticChain; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + Id.create("CollectionCarrierResource", LSPResource.class); + final LSPResource collectionCarrierResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionCarrierResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTransshipmentHubBuilder.build()); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50 / 3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = collectionCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(collectionCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + LSPResource mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .build(); + + LogisticChainElement mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + TranshipmentHubSchedulerBuilder secondSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + secondSchedulerBuilder.setCapacityNeedFixed(10); + secondSchedulerBuilder.setCapacityNeedLinear(1); + + + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + + TransshipmentHubBuilder secondTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(secondTransshipmentHubId, secondTransshipmentHub_LinkId, scenario ); + secondTransshipmentHubBuilder.setTransshipmentHubScheduler(secondSchedulerBuilder.build()); + + + Id secondHubElementId = Id.create("SecondHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTransshipmentHubBuilder.build()); + LogisticChainElement secondHubElement = secondHubElementBuilder.build(); + + Id distributionCarrierId = Id.create("DistributionCarrier", Carrier.class); + Id distributionVehTypeId = Id.create("DistributionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType distributionVehType = VehicleUtils.createVehicleType(distributionVehTypeId, TransportMode.car); + distributionVehType.getCapacity().setOther(10); + distributionVehType.getCostInformation().setCostsPerMeter(0.0004); + distributionVehType.getCostInformation().setCostsPerSecond(0.38); + distributionVehType.getCostInformation().setFixedCost(49.); + distributionVehType.setMaximumVelocity(50 / 3.6); + + Id distributionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id distributionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle distributionCarrierVehicle = CarrierVehicle.newInstance(distributionVehicleId, distributionLinkId, distributionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(distributionCarrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities distributionCapabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(distributionCarrierId); + carrier.setCarrierCapabilities(distributionCapabilities); + + + final LSPResource distributionCarrierResource = ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(carrier) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .setLocationLinkId(distributionLinkId) + .build(); + + + Id distributionElementId = Id.create("DistributionElement", LogisticChainElement.class); + LogisticChainElement distributionElement = LSPUtils.LogisticChainElementBuilder.newInstance(distributionElementId) + .setResource(distributionCarrierResource) + .build(); + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + secondHubElement.connectWithNextElement(distributionElement); + + final Id chainId = Id.create("SolutionId", LogisticChain.class); + logisticChain = LSPUtils.LogisticChainBuilder.newInstance(chainId) + .addLogisticChainElement(collectionElement) + .addLogisticChainElement(firstHubElement) + .addLogisticChainElement(mainRunElement) + .addLogisticChainElement(secondHubElement) + .addLogisticChainElement(distributionElement) + .build(); + + assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(logisticChain); + } + + @Test + public void testCompleteLSPPlan() { + assertSame(completePlan.getInitialShipmentAssigner(), assigner); + assertNull(completePlan.getLSP()); + assertNull(completePlan.getScore()); + assertEquals(1, completePlan.getLogisticChains().size()); + assertSame(completePlan.getLogisticChains().iterator().next(), logisticChain); + } + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspShipmentAssignmentTests/CollectionLspShipmentAssigmentTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspShipmentAssignmentTests/CollectionLspShipmentAssigmentTest.java new file mode 100644 index 00000000000..c7f627638bb --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspShipmentAssignmentTests/CollectionLspShipmentAssigmentTest.java @@ -0,0 +1,165 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspShipmentAssignmentTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.CollectionCarrierResourceBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class CollectionLspShipmentAssigmentTest { + + private LSPPlan collectionPlan; + private LSP collectionLSP; + + @BeforeEach + public void initialize() { + + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + Id carrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(Id.createVehicleId("CollectionVehicle"), collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(carrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities capabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + + Id.create("CollectionCarrierResource", LSPResource.class); + CollectionCarrierResourceBuilder adapterBuilder = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(carrier); + adapterBuilder.setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)); + adapterBuilder.setLocationLinkId(collectionLinkId); + LSPResource collectionResource = adapterBuilder.build(); + + Id elementId = Id.create("CollectionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder collectionElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(elementId); + collectionElementBuilder.setResource(collectionResource); + LogisticChainElement collectionElement = collectionElementBuilder.build(); + + Id collectionSolutionId = Id.create("CollectionSolution", LogisticChain.class); + LSPUtils.LogisticChainBuilder collectionSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(collectionSolutionId); + collectionSolutionBuilder.addLogisticChainElement(collectionElement); + LogisticChain collectionSolution = collectionSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + collectionPlan = LSPUtils.createLSPPlan(); + collectionPlan.setInitialShipmentAssigner(assigner); + collectionPlan.addLogisticChain(collectionSolution); + + LSPUtils.LSPBuilder collectionLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + collectionLSPBuilder.setInitialPlan(collectionPlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + collectionLSPBuilder.setLogisticChainScheduler(simpleScheduler); + collectionLSP = collectionLSPBuilder.build(); + + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + + + for (int i = 1; i < 11; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = MatsimRandom.getRandom().nextInt(10); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + builder.setToLinkId(collectionLinkId); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + collectionLSP.assignShipmentToLSP(shipment); + } + } + + @Test + public void testCollectionLSPShipmentAssignment() { + assertSame(collectionLSP.getSelectedPlan(), collectionPlan); + assertFalse(collectionLSP.getLspShipments().isEmpty()); + ArrayList solutions = new ArrayList<>(collectionLSP.getSelectedPlan().getLogisticChains()); + + for (LogisticChain solution : solutions) { + if (solutions.indexOf(solution) == 0) { + assertEquals(10, solution.getLspShipmentIds().size()); + for (LogisticChainElement element : solution.getLogisticChainElements()) { + if (element.getPreviousElement() == null) { + assertTrue(element.getIncomingShipments().getLspShipmentsWTime().isEmpty()); + assertTrue(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } + } + } else { + assertTrue(solution.getLspShipmentIds().isEmpty()); + } + } + + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspShipmentAssignmentTests/CompleteLspShipmentAssignerTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspShipmentAssignmentTests/CompleteLspShipmentAssignerTest.java new file mode 100644 index 00000000000..5e2348ae67e --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspShipmentAssignmentTests/CompleteLspShipmentAssignerTest.java @@ -0,0 +1,287 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspShipmentAssignmentTests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class CompleteLspShipmentAssignerTest { + + private LSPPlan completePlan; + private LSP completeLSP; + + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + LSPResource collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + LogisticChainElement collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + LSPResource firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + LogisticChainElement firstHubElement = firstHubElementBuilder.build(); + + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50 / 3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = collectionCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(collectionCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + LSPResource mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(Id.createLinkId("(4 2) (4 3)")) + .setToLinkId(Id.createLinkId("(14 2) (14 3)")) + .build(); + + LogisticChainElement mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + TranshipmentHubSchedulerBuilder secondSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + secondSchedulerBuilder.setCapacityNeedFixed(10); + secondSchedulerBuilder.setCapacityNeedLinear(1); + + + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + + TransshipmentHubBuilder secondTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(secondTransshipmentHubId, secondTransshipmentHub_LinkId, scenario); + secondTransshipmentHubBuilder.setTransshipmentHubScheduler(secondSchedulerBuilder.build()); + LSPResource secondTranshipmentHubResource = secondTransshipmentHubBuilder.build(); + + Id secondHubElementId = Id.create("SecondHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTranshipmentHubResource); + LogisticChainElement secondHubElement = secondHubElementBuilder.build(); + + Id distributionCarrierId = Id.create("DistributionCarrier", Carrier.class); + Id distributionVehTypeId = Id.create("DistributionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType distributionVehType = VehicleUtils.createVehicleType(distributionVehTypeId, TransportMode.car); + distributionVehType.getCapacity().setOther(10); + distributionVehType.getCostInformation().setCostsPerMeter(0.0004); + distributionVehType.getCostInformation().setCostsPerSecond(0.38); + distributionVehType.getCostInformation().setFixedCost(49.); + distributionVehType.setMaximumVelocity(50 / 3.6); + + Id distributionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id distributionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle distributionCarrierVehicle = CarrierVehicle.newInstance(distributionVehicleId, distributionLinkId, distributionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(distributionCarrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities distributionCapabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(distributionCarrierId); + carrier.setCarrierCapabilities(distributionCapabilities); + + LSPResource distributionResource = ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(carrier) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .setLocationLinkId(distributionLinkId) + .build(); + + Id distributionElementId = Id.create("DistributionElement", LogisticChainElement.class); + LogisticChainElement distributionElement= LSPUtils.LogisticChainElementBuilder.newInstance(distributionElementId) + .setResource(distributionResource) + .build(); + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + secondHubElement.connectWithNextElement(distributionElement); + + LogisticChain completeSolution = LSPUtils.LogisticChainBuilder.newInstance(Id.create("SolutionId", LogisticChain.class)) + .addLogisticChainElement(collectionElement) + .addLogisticChainElement(firstHubElement) + .addLogisticChainElement(mainRunElement) + .addLogisticChainElement(secondHubElement) + .addLogisticChainElement(distributionElement) + .build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + resourcesList.add(secondTranshipmentHubResource); + resourcesList.add(distributionResource); + + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + completeLSP = completeLSPBuilder.build(); + + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + + for (int i = 1; i < 11; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = MatsimRandom.getRandom().nextInt(10); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + completeLSP.assignShipmentToLSP(builder.build()); + } + } + + @Test + public void testCollectionLSPShipmentAssignment() { + assertSame(completeLSP.getSelectedPlan(), completePlan); + ArrayList solutions = new ArrayList<>(completeLSP.getSelectedPlan().getLogisticChains()); + + for (LogisticChain solution : solutions) { + if (solutions.indexOf(solution) == 0) { + assertEquals(10, solution.getLspShipmentIds().size()); + for (LogisticChainElement element : solution.getLogisticChainElements()) { + if (element.getPreviousElement() == null) { + assertTrue(element.getIncomingShipments().getLspShipmentsWTime().isEmpty()); + assertTrue(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } + } + } else { + assertTrue(solution.getLspShipmentIds().isEmpty()); + } + } + + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspShipmentTest/CollectionShipmentBuilderTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspShipmentTest/CollectionShipmentBuilderTest.java new file mode 100644 index 00000000000..11957dbfac6 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspShipmentTest/CollectionShipmentBuilderTest.java @@ -0,0 +1,117 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspShipmentTest; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.TimeWindow; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; + +public class CollectionShipmentBuilderTest { + + private Network network; + private ArrayList shipments; + + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + this.network = scenario.getNetwork(); + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id toLinkId = network.getLinks().get(collectionLinkId).getId(); + this.shipments = new ArrayList<>(); + + for (int i = 1; i < 11; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = MatsimRandom.getRandom().nextInt(10); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + builder.setToLinkId(toLinkId); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + shipments.add(builder.build()); + } + } + + @Test + public void testShipments() { + assertEquals(10, shipments.size()); + for (LspShipment shipment : shipments) { + assertNotNull(shipment.getId()); + assertNotNull(shipment.getSize()); + assertNotNull(shipment.getDeliveryTimeWindow()); + assertNotNull(shipment.getFrom()); + assertNotNull(shipment.getDeliveryServiceTime()); + assertNotNull(shipment.getTo()); + assertNotNull(shipment.getPickupTimeWindow()); +// assertNotNull(shipment.getShipmentPlan()); + assertNotNull(shipment.getShipmentLog()); + assertNotNull(shipment.getSimulationTrackers()); + + assertTrue(shipment.getSimulationTrackers().isEmpty()); + assertEquals(shipment.getShipmentLog().getLspShipmentId(), shipment.getId()); + assertTrue(shipment.getShipmentLog().getPlanElements().isEmpty()); + +// assertEquals(shipment.getShipmentPlan().getEmbeddingContainer(), shipment.getId()); +// assertTrue(shipment.getShipmentPlan().getPlanElements().isEmpty()); + + Link link = network.getLinks().get(shipment.getFrom()); + assertTrue(link.getFromNode().getCoord().getX() <= 4000); + assertTrue(link.getFromNode().getCoord().getY() <= 4000); + + } + } + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspShipmentTest/CompleteShipmentBuilderTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspShipmentTest/CompleteShipmentBuilderTest.java new file mode 100644 index 00000000000..cb3ea748e39 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspShipmentTest/CompleteShipmentBuilderTest.java @@ -0,0 +1,132 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspShipmentTest; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.TimeWindow; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; + +public class CompleteShipmentBuilderTest { + + private Network network; + private ArrayList shipments; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + this.network = scenario.getNetwork(); + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + this.shipments = new ArrayList<>(); + + for (int i = 1; i < 11; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = MatsimRandom.getRandom().nextInt(10); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + shipments.add(builder.build()); + } + } + + + @Test + public void testShipments() { + assertEquals(10, shipments.size()); + for (LspShipment shipment : shipments) { + assertNotNull(shipment.getId()); + assertNotNull(shipment.getSize()); + assertNotNull(shipment.getDeliveryTimeWindow()); + assertNotNull(shipment.getFrom()); + assertNotNull(shipment.getDeliveryServiceTime()); + assertNotNull(shipment.getTo()); + assertNotNull(shipment.getPickupTimeWindow()); +// assertNotNull(shipment.getShipmentPlan()); + assertNotNull(shipment.getShipmentLog()); + assertNotNull(shipment.getSimulationTrackers()); + + assertTrue(shipment.getSimulationTrackers().isEmpty()); + assertEquals(shipment.getShipmentLog().getLspShipmentId(), shipment.getId()); + assertTrue(shipment.getShipmentLog().getPlanElements().isEmpty()); + +// assertEquals(shipment.getShipmentPlan().getEmbeddingContainer(), shipment.getId()); +// assertTrue(shipment.getShipmentPlan().getPlanElements().isEmpty()); + Link link = network.getLinks().get(shipment.getTo()); + assertTrue(link.getFromNode().getCoord().getX() <= 18000); + assertTrue(link.getFromNode().getCoord().getX() >= 14000); + assertTrue(link.getToNode().getCoord().getX() <= 18000); + assertTrue(link.getToNode().getCoord().getX() >= 14000); + + link = network.getLinks().get(shipment.getFrom()); + assertTrue(link.getFromNode().getCoord().getX() <= 4000); + assertTrue(link.getFromNode().getCoord().getY() <= 4000); + } + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/lspShipmentTest/DistributionShipmentBuilderTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspShipmentTest/DistributionShipmentBuilderTest.java new file mode 100644 index 00000000000..380a86b98a4 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/lspShipmentTest/DistributionShipmentBuilderTest.java @@ -0,0 +1,118 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.lspShipmentTest; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.TimeWindow; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; + +public class DistributionShipmentBuilderTest { + + private Network network; + private ArrayList shipments; + + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + this.network = scenario.getNetwork(); + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + Id distributionLinkId = Id.createLinkId("(14 2) (14 3)"); + Id fromLinkId = network.getLinks().get(distributionLinkId).getId(); + this.shipments = new ArrayList<>(); + + for (int i = 1; i < 11; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = MatsimRandom.getRandom().nextInt(10); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + builder.setFromLinkId(fromLinkId); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + shipments.add(builder.build()); + } + } + + @Test + public void testShipments() { + assertEquals(10, shipments.size()); + for (LspShipment shipment : shipments) { + assertNotNull(shipment.getId()); + assertNotNull(shipment.getSize()); + assertNotNull(shipment.getDeliveryTimeWindow()); + assertNotNull(shipment.getFrom()); + assertNotNull(shipment.getDeliveryServiceTime()); + assertNotNull(shipment.getTo()); + assertNotNull(shipment.getPickupTimeWindow()); +// assertNotNull(shipment.getShipmentPlan()); + assertNotNull(shipment.getShipmentLog()); + assertNotNull(shipment.getSimulationTrackers()); + + assertTrue(shipment.getSimulationTrackers().isEmpty()); + assertEquals(shipment.getShipmentLog().getLspShipmentId(), shipment.getId()); + assertTrue(shipment.getShipmentLog().getPlanElements().isEmpty()); + +// assertEquals(shipment.getShipmentPlan().getEmbeddingContainer(), shipment.getId()); +// assertTrue(shipment.getShipmentPlan().getPlanElements().isEmpty()); + Link link = network.getLinks().get(shipment.getTo()); + assertTrue(link.getFromNode().getCoord().getX() <= 18000); + assertTrue(link.getFromNode().getCoord().getX() >= 14000); + assertTrue(link.getToNode().getCoord().getX() <= 18000); + assertTrue(link.getToNode().getCoord().getX() >= 14000); + } + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/CollectionLSPSchedulingTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/CollectionLSPSchedulingTest.java new file mode 100644 index 00000000000..5e071b894d4 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/CollectionLSPSchedulingTest.java @@ -0,0 +1,240 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Random; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.events.handler.EventHandler; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.CollectionCarrierResourceBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class CollectionLSPSchedulingTest { + + private LSP collectionLSP; + private LSPResource collectionResource; + private LogisticChainElement collectionElement; + + @BeforeEach + public void initialize() { + + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + Id carrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50 / 3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(Id.createVehicleId("CollectionVehicle"), collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(carrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities capabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + + Id.create("CollectionCarrierResource", LSPResource.class); + CollectionCarrierResourceBuilder adapterBuilder = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(carrier); + adapterBuilder.setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)); + adapterBuilder.setLocationLinkId(collectionLinkId); + collectionResource = adapterBuilder.build(); + + Id elementId = Id.create("CollectionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder collectionElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(elementId); + collectionElementBuilder.setResource(collectionResource); + collectionElement = collectionElementBuilder.build(); + + Id collectionSolutionId = Id.create("CollectionSolution", LogisticChain.class); + LSPUtils.LogisticChainBuilder collectionSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(collectionSolutionId); + collectionSolutionBuilder.addLogisticChainElement(collectionElement); + LogisticChain collectionSolution = collectionSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan collectionPlan = LSPUtils.createLSPPlan(); + collectionPlan.setInitialShipmentAssigner(assigner); + collectionPlan.addLogisticChain(collectionSolution); + + LSPUtils.LSPBuilder collectionLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + collectionLSPBuilder.setInitialPlan(collectionPlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + collectionLSPBuilder.setLogisticChainScheduler(simpleScheduler); + collectionLSP = collectionLSPBuilder.build(); + + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + + + for (int i = 1; i < 2; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + Random random = new Random(1); + int capacityDemand = random.nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, random); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + builder.setToLinkId(collectionLinkId); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + collectionLSP.assignShipmentToLSP(shipment); + } + collectionLSP.scheduleLogisticChains(); + + } + + @Test + public void testCollectionLSPScheduling() { + + for (LspShipment shipment : collectionLSP.getLspShipments()) { + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(collectionLSP.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + System.out.println(); + for (int i = 0; i < LspShipmentUtils.getOrCreateShipmentPlan(collectionLSP.getSelectedPlan(), shipment.getId()).getPlanElements().size(); i++) { + System.out.println("Scheduled: " + scheduleElements.get(i).getLogisticChainElement().getId() + " " + scheduleElements.get(i).getResourceId() + " " + scheduleElements.get(i).getElementType() + " Start: " + scheduleElements.get(i).getStartTime() + " End: " + scheduleElements.get(i).getEndTime()); + } + System.out.println(); + } + + for (LspShipment shipment : collectionLSP.getLspShipments()) { + assertEquals(3, LspShipmentUtils.getOrCreateShipmentPlan(collectionLSP.getSelectedPlan(), shipment.getId()).getPlanElements().size()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(collectionLSP.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + assertEquals("UNLOAD", planElements.get(2).getElementType()); + assertTrue(planElements.get(2).getEndTime() >= (0)); + assertTrue(planElements.get(2).getEndTime() <= (24*3600)); + assertTrue(planElements.get(2).getStartTime() <= planElements.get(2).getEndTime()); + assertTrue(planElements.get(2).getStartTime() >= (0)); + assertTrue(planElements.get(2).getStartTime() <= (24*3600)); + assertSame(planElements.get(2).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(2).getLogisticChainElement(), collectionElement); + assertEquals("TRANSPORT", planElements.get(1).getElementType()); + assertTrue(planElements.get(1).getEndTime() >= (0)); + assertTrue(planElements.get(1).getEndTime() <= (24*3600)); + assertEquals(planElements.get(2).getStartTime(), planElements.get(1).getEndTime(), 0.0); + assertTrue(planElements.get(1).getStartTime() <= planElements.get(1).getEndTime()); + assertTrue(planElements.get(1).getStartTime() >= (0)); + assertTrue(planElements.get(1).getStartTime() <= (24*3600)); + assertSame(planElements.get(1).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(1).getLogisticChainElement(), collectionElement); + assertEquals("LOAD", planElements.get(0).getElementType()); + assertTrue(planElements.get(0).getEndTime() >= (0)); + assertTrue(planElements.get(0).getEndTime() <= (24*3600)); + assertEquals(planElements.get(1).getStartTime(), planElements.get(0).getEndTime(), 0.0); + assertTrue(planElements.get(0).getStartTime() <= planElements.get(0).getEndTime()); + assertTrue(planElements.get(0).getStartTime() >= (0)); + assertTrue(planElements.getFirst().getStartTime() <= (24*3600)); + assertSame(planElements.getFirst().getResourceId(), collectionResource.getId()); + assertSame(planElements.getFirst().getLogisticChainElement(), collectionElement); + + assertEquals(2, shipment.getSimulationTrackers().size()); + ArrayList eventHandlers = new ArrayList<>(shipment.getSimulationTrackers()); + + { + assertInstanceOf(LSPTourEndEventHandler.class, eventHandlers.getFirst()); + LSPTourEndEventHandler endHandler = (LSPTourEndEventHandler) eventHandlers.getFirst(); + assertSame(endHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(endHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(endHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(endHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(endHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(endHandler.getLogisticChainElement(), planElements.get(2).getLogisticChainElement()); + assertSame(endHandler.getLogisticChainElement(), collectionLSP.getSelectedPlan().getLogisticChains().iterator().next().getLogisticChainElements().iterator().next()); + assertSame(endHandler.getLspShipment(), shipment); + assertSame(endHandler.getResourceId(), planElements.get(2).getResourceId()); + assertSame(endHandler.getResourceId(), collectionLSP.getResources().iterator().next().getId()); + } + + { + assertInstanceOf(CollectionServiceEndEventHandler.class, eventHandlers.get(1)); + CollectionServiceEndEventHandler serviceHandler = (CollectionServiceEndEventHandler) eventHandlers.get(1); + assertSame(serviceHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(serviceHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(serviceHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(serviceHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(serviceHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(serviceHandler.getElement(), planElements.get(1).getLogisticChainElement()); + assertSame(serviceHandler.getElement(), collectionLSP.getSelectedPlan().getLogisticChains().iterator().next().getLogisticChainElements().iterator().next()); + assertSame(serviceHandler.getLspShipment(), shipment); + assertSame(serviceHandler.getResourceId(), planElements.get(1).getResourceId()); + assertSame(serviceHandler.getResourceId(), collectionLSP.getResources().iterator().next().getId()); + } + } + + for (LogisticChain solution : collectionLSP.getSelectedPlan().getLogisticChains()) { + assertEquals(1, solution.getLspShipmentIds().size()); + for (LogisticChainElement element : solution.getLogisticChainElements()) { + assertTrue(element.getIncomingShipments().getLspShipmentsWTime().isEmpty()); + if (element.getNextElement() != null) { + assertTrue(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } else { + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } + } + } + + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/CompleteLSPSchedulingTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/CompleteLSPSchedulingTest.java new file mode 100644 index 00000000000..c4fd34c0fd3 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/CompleteLSPSchedulingTest.java @@ -0,0 +1,608 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.Random; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.events.handler.EventHandler; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class CompleteLSPSchedulingTest { + + private LSP lsp; + private LSPResource collectionResource; + private LogisticChainElement collectionElement; + private LSPResource firstTranshipmentHubResource; + private LogisticChainElement firstHubElement; + private LSPResource mainRunResource; + private LogisticChainElement mainRunElement; + private LSPResource secondTranshipmentHubResource; + private LogisticChainElement secondHubElement; + private LSPResource distributionResource; + private LogisticChainElement distributionElement; + private Id toLinkId; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50/3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + firstHubElement = firstHubElementBuilder.build(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50/3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + toLinkId = Id.createLinkId("(14 2) (14 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(fromLinkId) + .setToLinkId(toLinkId) + .build(); + + mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + TranshipmentHubSchedulerBuilder secondSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + secondSchedulerBuilder.setCapacityNeedFixed(10); + secondSchedulerBuilder.setCapacityNeedLinear(1); + + + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + + TransshipmentHubBuilder secondTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(secondTransshipmentHubId, secondTransshipmentHub_LinkId, scenario); + secondTransshipmentHubBuilder.setTransshipmentHubScheduler(secondSchedulerBuilder.build()); + secondTranshipmentHubResource = secondTransshipmentHubBuilder.build(); + + Id secondHubElementId = Id.create("SecondHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTranshipmentHubResource); + secondHubElement = secondHubElementBuilder.build(); + + Id distributionCarrierId = Id.create("DistributionCarrier", Carrier.class); + Id distributionVehTypeId = Id.create("DistributionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType distributionVehType = VehicleUtils.createVehicleType(distributionVehTypeId, TransportMode.car); + distributionVehType.getCapacity().setOther(10); + distributionVehType.getCostInformation().setCostsPerMeter(0.0004); + distributionVehType.getCostInformation().setCostsPerSecond(0.38); + distributionVehType.getCostInformation().setFixedCost(49.); + distributionVehType.setMaximumVelocity(50/3.6); + + Id distributionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id distributionVehicleId = Id.createVehicleId("DistributionVehicle"); + CarrierVehicle distributionCarrierVehicle = CarrierVehicle.newInstance(distributionVehicleId, distributionLinkId, distributionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(distributionCarrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities distributionCapabilities = capabilitiesBuilder.build(); + Carrier distributionCarrier = CarriersUtils.createCarrier(distributionCarrierId); + distributionCarrier.setCarrierCapabilities(distributionCapabilities); + + distributionResource = ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(distributionCarrier) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .setLocationLinkId(distributionLinkId) + .build(); + + Id distributionElementId = Id.create("DistributionElement", LogisticChainElement.class); + distributionElement = LSPUtils.LogisticChainElementBuilder.newInstance(distributionElementId) + .setResource(distributionResource) + .build(); + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + secondHubElement.connectWithNextElement(distributionElement); + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + completeSolutionBuilder.addLogisticChainElement(mainRunElement); + completeSolutionBuilder.addLogisticChainElement(secondHubElement); + completeSolutionBuilder.addLogisticChainElement(distributionElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + resourcesList.add(secondTranshipmentHubResource); + resourcesList.add(distributionResource); + + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + Random rand = new Random(1); + for (int i = 1; i < 2; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = rand.nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, rand); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList, rand); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + } + + @Test + public void testCompletedLSPScheduling() { + + for (LspShipment shipment : lsp.getLspShipments()) { + ArrayList elementList = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + elementList.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + System.out.println(); + for (LspShipmentPlanElement element : elementList) { + System.out.println(element.getLogisticChainElement().getId() + "\t\t" + element.getResourceId() + "\t\t" + element.getElementType() + "\t\t" + element.getStartTime() + "\t\t" + element.getEndTime()); + } + System.out.println(); + } + + ArrayList solutionElements = new ArrayList<>(lsp.getSelectedPlan().getLogisticChains().iterator().next().getLogisticChainElements()); + ArrayList resources = new ArrayList<>(lsp.getResources()); + + for (LspShipment shipment : lsp.getLspShipments()) { + assertEquals(11, LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + planElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + assertEquals("UNLOAD", planElements.get(10).getElementType()); + assertTrue(planElements.get(10).getEndTime() >= (0)); + assertTrue(planElements.get(10).getEndTime() <= (24*3600)); + assertTrue(planElements.get(10).getStartTime() <= planElements.get(10).getEndTime()); + assertTrue(planElements.get(10).getStartTime() >= (0)); + assertTrue(planElements.get(10).getStartTime() <= (24*3600)); + assertSame(planElements.get(10).getResourceId(), distributionResource.getId()); + assertSame(planElements.get(10).getLogisticChainElement(), distributionElement); + + assertEquals(planElements.get(10).getStartTime(), planElements.get(9).getEndTime(), 0.0); + + assertEquals("TRANSPORT", planElements.get(9).getElementType()); + assertTrue(planElements.get(9).getEndTime() >= (0)); + assertTrue(planElements.get(9).getEndTime() <= (24*3600)); + assertTrue(planElements.get(9).getStartTime() <= planElements.get(9).getEndTime()); + assertTrue(planElements.get(9).getStartTime() >= (0)); + assertTrue(planElements.get(9).getStartTime() <= (24*3600)); + assertSame(planElements.get(9).getResourceId(), distributionResource.getId()); + assertSame(planElements.get(9).getLogisticChainElement(), distributionElement); + + assertEquals(planElements.get(9).getStartTime(), planElements.get(8).getEndTime(), 0.0); + + assertEquals("LOAD", planElements.get(8).getElementType()); + assertTrue(planElements.get(8).getEndTime() >= (0)); + assertTrue(planElements.get(8).getEndTime() <= (24*3600)); + assertTrue(planElements.get(8).getStartTime() <= planElements.get(8).getEndTime()); + assertTrue(planElements.get(8).getStartTime() >= (0)); + assertTrue(planElements.get(8).getStartTime() <= (24*3600)); + assertSame(planElements.get(8).getResourceId(), distributionResource.getId()); + assertSame(planElements.get(8).getLogisticChainElement(), distributionElement); + + assertTrue(planElements.get(8).getStartTime() >= (planElements.get(7).getEndTime() / 1.0001) + 300); + + assertEquals("HANDLE", planElements.get(7).getElementType()); + assertTrue(planElements.get(7).getEndTime() >= (0)); + assertTrue(planElements.get(7).getEndTime() <= (24*3600)); + assertTrue(planElements.get(7).getStartTime() <= planElements.get(7).getEndTime()); + assertTrue(planElements.get(7).getStartTime() >= (0)); + assertTrue(planElements.get(7).getStartTime() <= (24*3600)); + assertSame(planElements.get(7).getResourceId(), secondTranshipmentHubResource.getId()); + assertSame(planElements.get(7).getLogisticChainElement(), secondHubElement); + + assertEquals(planElements.get(7).getStartTime(), (planElements.get(6).getEndTime() + 300), 0.0); + + assertEquals("UNLOAD", planElements.get(6).getElementType()); + assertTrue(planElements.get(6).getEndTime() >= (0)); + assertTrue(planElements.get(6).getEndTime() <= (24*3600)); + assertTrue(planElements.get(6).getStartTime() <= planElements.get(6).getEndTime()); + assertTrue(planElements.get(6).getStartTime() >= (0)); + assertTrue(planElements.get(6).getStartTime() <= (24*3600)); + assertSame(planElements.get(6).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(6).getLogisticChainElement(), mainRunElement); + + assertEquals(planElements.get(6).getStartTime(), planElements.get(5).getEndTime(), 0.0); + + assertEquals("TRANSPORT", planElements.get(5).getElementType()); + assertTrue(planElements.get(5).getEndTime() >= (0)); + assertTrue(planElements.get(5).getEndTime() <= (24*3600)); + assertTrue(planElements.get(5).getStartTime() <= planElements.get(5).getEndTime()); + assertTrue(planElements.get(5).getStartTime() >= (0)); + assertTrue(planElements.get(5).getStartTime() <= (24*3600)); + assertSame(planElements.get(5).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(5).getLogisticChainElement(), mainRunElement); + + assertEquals(planElements.get(5).getStartTime(), planElements.get(4).getEndTime(), 0.0); + + assertEquals("LOAD", planElements.get(4).getElementType()); + assertTrue(planElements.get(4).getEndTime() >= (0)); + assertTrue(planElements.get(4).getEndTime() <= (24*3600)); + assertTrue(planElements.get(4).getStartTime() <= planElements.get(4).getEndTime()); + assertTrue(planElements.get(4).getStartTime() >= (0)); + assertTrue(planElements.get(4).getStartTime() <= (24*3600)); + assertSame(planElements.get(4).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(4).getLogisticChainElement(), mainRunElement); + + assertTrue(planElements.get(4).getStartTime() >= (planElements.get(3).getEndTime() / (1.0001)) + 300); + + assertEquals("HANDLE", planElements.get(3).getElementType()); + assertTrue(planElements.get(3).getEndTime() >= (0)); + assertTrue(planElements.get(3).getEndTime() <= (24*3600)); + assertTrue(planElements.get(3).getStartTime() <= planElements.get(3).getEndTime()); + assertTrue(planElements.get(3).getStartTime() >= (0)); + assertTrue(planElements.get(3).getStartTime() <= (24*3600)); + assertSame(planElements.get(3).getResourceId(), firstTranshipmentHubResource.getId()); + assertSame(planElements.get(3).getLogisticChainElement(), firstHubElement); + + assertEquals(planElements.get(3).getStartTime(), (planElements.get(2).getEndTime() + 300), 0.0); + + assertEquals("UNLOAD", planElements.get(2).getElementType()); + assertTrue(planElements.get(2).getEndTime() >= (0)); + assertTrue(planElements.get(2).getEndTime() <= (24*3600)); + assertTrue(planElements.get(2).getStartTime() <= planElements.get(2).getEndTime()); + assertTrue(planElements.get(2).getStartTime() >= (0)); + assertTrue(planElements.get(2).getStartTime() <= (24*3600)); + assertSame(planElements.get(2).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(2).getLogisticChainElement(), collectionElement); + + assertEquals(planElements.get(2).getStartTime(), planElements.get(1).getEndTime(), 0.0); + + assertEquals("TRANSPORT", planElements.get(1).getElementType()); + assertTrue(planElements.get(1).getEndTime() >= (0)); + assertTrue(planElements.get(1).getEndTime() <= (24*3600)); + assertTrue(planElements.get(1).getStartTime() <= planElements.get(1).getEndTime()); + assertTrue(planElements.get(1).getStartTime() >= (0)); + assertTrue(planElements.get(1).getStartTime() <= (24*3600)); + assertSame(planElements.get(1).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(1).getLogisticChainElement(), collectionElement); + + assertEquals(planElements.get(1).getStartTime(), planElements.get(0).getEndTime(), 0.0); + + assertEquals("LOAD", planElements.get(0).getElementType()); + assertTrue(planElements.get(0).getEndTime() >= (0)); + assertTrue(planElements.getFirst().getEndTime() <= (24*3600)); + assertTrue(planElements.getFirst().getStartTime() <= planElements.getFirst().getEndTime()); + assertTrue(planElements.getFirst().getStartTime() >= (0)); + assertTrue(planElements.getFirst().getStartTime() <= (24*3600)); + assertSame(planElements.getFirst().getResourceId(), collectionResource.getId()); + assertSame(planElements.getFirst().getLogisticChainElement(), collectionElement); + } + + assertEquals(1, firstTranshipmentHubResource.getSimulationTrackers().size()); + ArrayList eventHandlers = new ArrayList<>(firstTranshipmentHubResource.getSimulationTrackers()); + assertInstanceOf(TransshipmentHubTourEndEventHandler.class, eventHandlers.getFirst()); + TransshipmentHubTourEndEventHandler reloadEventHandler = (TransshipmentHubTourEndEventHandler) eventHandlers.getFirst(); + Iterator> iter = reloadEventHandler.getServicesWaitedFor().entrySet().iterator(); + + while (iter.hasNext()) { + Entry entry = iter.next(); + CarrierService service = entry.getKey(); + LspShipment shipment = entry.getValue().lspShipment; + LogisticChainElement element = entry.getValue().logisticChainElement; + assertSame(service.getLocationLinkId(), shipment.getFrom()); + assertEquals(service.getCapacityDemand(), shipment.getSize()); + assertEquals(service.getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + boolean handledByTranshipmentHub = false; + for (LogisticChainElement clientElement : reloadEventHandler.getTranshipmentHub().getClientElements()) { + if (clientElement == element) { + handledByTranshipmentHub = true; + break; + } + } + assertTrue(handledByTranshipmentHub); + + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().contains(shipment)); + assertFalse(element.getIncomingShipments().getLspShipmentsWTime().contains(shipment)); + } + + assertEquals(1, secondTranshipmentHubResource.getSimulationTrackers().size()); + eventHandlers = new ArrayList<>(secondTranshipmentHubResource.getSimulationTrackers()); + assertInstanceOf(TransshipmentHubTourEndEventHandler.class, eventHandlers.getFirst()); + reloadEventHandler = (TransshipmentHubTourEndEventHandler) eventHandlers.getFirst(); + iter = reloadEventHandler.getServicesWaitedFor().entrySet().iterator(); + + while (iter.hasNext()) { + Entry entry = iter.next(); + CarrierService service = entry.getKey(); + LspShipment shipment = entry.getValue().lspShipment; + LogisticChainElement element = entry.getValue().logisticChainElement; + assertSame(service.getLocationLinkId(), toLinkId); + assertEquals(service.getCapacityDemand(), shipment.getSize()); + assertEquals(service.getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + boolean handledByTranshipmentHub = false; + for (LogisticChainElement clientElement : reloadEventHandler.getTranshipmentHub().getClientElements()) { + if (clientElement == element) { + handledByTranshipmentHub = true; + break; + } + } + assertTrue(handledByTranshipmentHub); + + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().contains(shipment)); + assertFalse(element.getIncomingShipments().getLspShipmentsWTime().contains(shipment)); + } + + for (LspShipment shipment : lsp.getLspShipments()) { + assertEquals(6, shipment.getSimulationTrackers().size()); + eventHandlers = new ArrayList<>(shipment.getSimulationTrackers()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + planElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + assertInstanceOf(LSPTourEndEventHandler.class, eventHandlers.getFirst()); + LSPTourEndEventHandler endHandler = (LSPTourEndEventHandler) eventHandlers.getFirst(); + assertSame(endHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(endHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(endHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(endHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(endHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(endHandler.getLogisticChainElement(), planElements.get(0).getLogisticChainElement()); + assertSame(endHandler.getLogisticChainElement(), planElements.get(1).getLogisticChainElement()); + assertSame(endHandler.getLogisticChainElement(), planElements.get(2).getLogisticChainElement()); + assertSame(endHandler.getLogisticChainElement(), solutionElements.getFirst()); + assertSame(endHandler.getLspShipment(), shipment); + assertSame(endHandler.getResourceId(), planElements.get(0).getResourceId()); + assertSame(endHandler.getResourceId(), planElements.get(1).getResourceId()); + assertSame(endHandler.getResourceId(), planElements.get(2).getResourceId()); + assertSame(endHandler.getResourceId(), resources.getFirst().getId()); + + //CollectionServiceEnd + assertInstanceOf(CollectionServiceEndEventHandler.class, eventHandlers.get(1)); + CollectionServiceEndEventHandler serviceHandler = (CollectionServiceEndEventHandler) eventHandlers.get(1); + assertSame(serviceHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(serviceHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(serviceHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(serviceHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(serviceHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(serviceHandler.getElement(), planElements.get(0).getLogisticChainElement()); + assertSame(serviceHandler.getElement(), planElements.get(1).getLogisticChainElement()); + assertSame(serviceHandler.getElement(), planElements.get(2).getLogisticChainElement()); + assertSame(serviceHandler.getElement(), solutionElements.getFirst()); + assertSame(serviceHandler.getLspShipment(), shipment); + assertSame(serviceHandler.getResourceId(), planElements.get(0).getResourceId()); + assertSame(serviceHandler.getResourceId(), planElements.get(1).getResourceId()); + assertSame(serviceHandler.getResourceId(), planElements.get(2).getResourceId()); + assertSame(serviceHandler.getResourceId(), resources.getFirst().getId()); + + //MainRunStart + assertInstanceOf(LSPTourStartEventHandler.class, eventHandlers.get(2)); + LSPTourStartEventHandler mainRunStartHandler = (LSPTourStartEventHandler) eventHandlers.get(2); + assertSame(mainRunStartHandler.getCarrierService().getLocationLinkId(), toLinkId); + assertEquals(mainRunStartHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(mainRunStartHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(0, mainRunStartHandler.getCarrierService().getServiceStartTimeWindow().getStart(), 0.0); + assertEquals(Integer.MAX_VALUE, mainRunStartHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), 0.0); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(4).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(5).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(6).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), solutionElements.get(2)); + assertSame(mainRunStartHandler.getLspShipment(), shipment); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(4).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(5).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(6).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), resources.get(2).getId()); + + //MainRunEnd + assertInstanceOf(LSPTourEndEventHandler.class, eventHandlers.get(3)); + LSPTourEndEventHandler mainRunEndHandler = (LSPTourEndEventHandler) eventHandlers.get(3); + assertSame(mainRunEndHandler.getCarrierService().getLocationLinkId(), toLinkId); + assertEquals(mainRunEndHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(mainRunEndHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(0, mainRunEndHandler.getCarrierService().getServiceStartTimeWindow().getStart(), 0.0); + assertEquals(Integer.MAX_VALUE, mainRunEndHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), 0.0); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(4).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(5).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(6).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), solutionElements.get(2)); + assertSame(mainRunEndHandler.getLspShipment(), shipment); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(4).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(5).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(6).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), resources.get(2).getId()); + + //DistributionRunStart + assertInstanceOf(LSPTourStartEventHandler.class, eventHandlers.get(4)); + LSPTourStartEventHandler lspTourStartEventHandler = (LSPTourStartEventHandler) eventHandlers.get(4); + assertSame(lspTourStartEventHandler.getCarrierService().getLocationLinkId(), shipment.getTo()); + assertEquals(lspTourStartEventHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(lspTourStartEventHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(0, lspTourStartEventHandler.getCarrierService().getServiceStartTimeWindow().getStart(), 0.0); + assertEquals(Integer.MAX_VALUE, lspTourStartEventHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), 0.0); + assertSame(lspTourStartEventHandler.getLogisticChainElement(), planElements.get(8).getLogisticChainElement()); + assertSame(lspTourStartEventHandler.getLogisticChainElement(), planElements.get(9).getLogisticChainElement()); + assertSame(lspTourStartEventHandler.getLogisticChainElement(), planElements.get(10).getLogisticChainElement()); + assertSame(lspTourStartEventHandler.getLogisticChainElement(), solutionElements.get(4)); + assertSame(lspTourStartEventHandler.getLspShipment(), shipment); + assertSame(lspTourStartEventHandler.getResourceId(), planElements.get(8).getResourceId()); + assertSame(lspTourStartEventHandler.getResourceId(), planElements.get(9).getResourceId()); + assertSame(lspTourStartEventHandler.getResourceId(), planElements.get(10).getResourceId()); + assertSame(lspTourStartEventHandler.getResourceId(), resources.get(4).getId()); + + //DistributionServiceStart + assertInstanceOf(DistributionServiceStartEventHandler.class, eventHandlers.get(5)); + DistributionServiceStartEventHandler distributionServiceHandler = (DistributionServiceStartEventHandler) eventHandlers.get(5); + assertSame(distributionServiceHandler.getCarrierService().getLocationLinkId(), shipment.getTo()); + assertEquals(distributionServiceHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(distributionServiceHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(0, distributionServiceHandler.getCarrierService().getServiceStartTimeWindow().getStart(), 0.0); + assertEquals(Integer.MAX_VALUE, distributionServiceHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), 0.0); + assertSame(distributionServiceHandler.getLogisticChainElement(), planElements.get(8).getLogisticChainElement()); + assertSame(distributionServiceHandler.getLogisticChainElement(), planElements.get(9).getLogisticChainElement()); + assertSame(distributionServiceHandler.getLogisticChainElement(), planElements.get(10).getLogisticChainElement()); + assertSame(distributionServiceHandler.getLogisticChainElement(), solutionElements.get(4)); + assertSame(distributionServiceHandler.getLspShipment(), shipment); + assertSame(distributionServiceHandler.getResource().getId(), planElements.get(8).getResourceId()); + assertSame(distributionServiceHandler.getResource().getId(), planElements.get(9).getResourceId()); + assertSame(distributionServiceHandler.getResource().getId(), planElements.get(10).getResourceId()); + assertSame(distributionServiceHandler.getResource().getId(), resources.get(4).getId()); + + } + + for (LogisticChain solution : lsp.getSelectedPlan().getLogisticChains()) { + assertEquals(1, solution.getLspShipmentIds().size()); + for (LogisticChainElement element : solution.getLogisticChainElements()) { + assertTrue(element.getIncomingShipments().getLspShipmentsWTime().isEmpty()); + if (element.getNextElement() != null) { + assertTrue(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } else { + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } + } + } + + } + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/FirstHubElementTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/FirstHubElementTest.java new file mode 100644 index 00000000000..6e9db008a4b --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/FirstHubElementTest.java @@ -0,0 +1,73 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Id; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.LSPUtils; +import org.matsim.freight.logistics.LogisticChainElement; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; + +public class FirstHubElementTest { + + private TransshipmentHubResource point; + private LogisticChainElement reloadingElement; + + @BeforeEach + public void initialize() { + TranshipmentHubSchedulerBuilder schedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + schedulerBuilder.setCapacityNeedFixed(10); + schedulerBuilder.setCapacityNeedLinear(1); + + + point = ResourceImplementationUtils.TransshipmentHubBuilder + .newInstance(Id.create("TranshipmentHub1", LSPResource.class), Id.createLinkId("(4 2) (4 3)"), null) + .setTransshipmentHubScheduler(schedulerBuilder.build()) + .build(); + + reloadingElement = LSPUtils.LogisticChainElementBuilder + .newInstance(Id.create("FirstHubElement", LogisticChainElement.class)) + .setResource(point) + .build(); + } + + @Test + public void testDistributionElement() { + assertNotNull(reloadingElement.getIncomingShipments()); + assertNotNull(reloadingElement.getIncomingShipments().getLspShipmentsWTime()); + assertTrue(reloadingElement.getIncomingShipments().getSortedLspShipments().isEmpty()); + assertNotNull(reloadingElement.getAttributes()); + assertTrue(reloadingElement.getAttributes().isEmpty()); +// assertNull(reloadingElement.getEmbeddingContainer() ); + assertNull(reloadingElement.getNextElement()); + assertNotNull(reloadingElement.getOutgoingShipments()); + assertNotNull(reloadingElement.getOutgoingShipments().getLspShipmentsWTime()); + assertTrue(reloadingElement.getOutgoingShipments().getSortedLspShipments().isEmpty()); + assertNull(reloadingElement.getPreviousElement()); + assertSame(reloadingElement.getResource(), point); + assertSame(reloadingElement.getResource().getClientElements().iterator().next(), reloadingElement); + } + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/FirstReloadLSPSchedulingTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/FirstReloadLSPSchedulingTest.java new file mode 100644 index 00000000000..3cead4c873c --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/FirstReloadLSPSchedulingTest.java @@ -0,0 +1,324 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Map.Entry; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.events.handler.EventHandler; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class FirstReloadLSPSchedulingTest { + private LSP lsp; + private LSPResource firstTranshipmentHubResource; + private LogisticChainElement firstHubElement; + private LogisticChainElement collectionElement; + private LSPResource collectionResource; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50/3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + firstHubElement = firstHubElementBuilder.build(); + + collectionElement.connectWithNextElement(firstHubElement); + + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + + for (int i = 1; i < 2; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + //Random random = new Random(1); + int capacityDemand = MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + } + + @Test + public void testFirstReloadLSPScheduling() { + + for (LspShipment shipment : lsp.getLspShipments()) { + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + System.out.println(); + for (int i = 0; i < LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size(); i++) { + System.out.println("Scheduled: " + scheduleElements.get(i).getLogisticChainElement().getId() + " " + scheduleElements.get(i).getResourceId() + " " + scheduleElements.get(i).getElementType() + " Start: " + scheduleElements.get(i).getStartTime() + " End: " + scheduleElements.get(i).getEndTime()); + } + System.out.println(); + } + + + for (LspShipment shipment : lsp.getLspShipments()) { + assertEquals(4, LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + planElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + assertEquals("HANDLE", planElements.get(3).getElementType()); + assertTrue(planElements.get(3).getEndTime() >= (0)); + assertTrue(planElements.get(3).getEndTime() <= (24*3600)); + assertTrue(planElements.get(3).getStartTime() <= planElements.get(3).getEndTime()); + assertTrue(planElements.get(3).getStartTime() >= (0)); + assertTrue(planElements.get(3).getStartTime() <= (24*3600)); + assertSame(planElements.get(3).getResourceId(), firstTranshipmentHubResource.getId()); + assertSame(planElements.get(3).getLogisticChainElement(), firstHubElement); + + assertEquals(planElements.get(3).getStartTime(), (planElements.get(2).getEndTime() + 300), 0.0); + + assertEquals("UNLOAD", planElements.get(2).getElementType()); + assertTrue(planElements.get(2).getEndTime() >= (0)); + assertTrue(planElements.get(2).getEndTime() <= (24*3600)); + assertTrue(planElements.get(2).getStartTime() <= planElements.get(2).getEndTime()); + assertTrue(planElements.get(2).getStartTime() >= (0)); + assertTrue(planElements.get(2).getStartTime() <= (24*3600)); + assertSame(planElements.get(2).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(2).getLogisticChainElement(), collectionElement); + + assertEquals(planElements.get(2).getStartTime(), planElements.get(1).getEndTime(), 0.0); + + assertEquals("TRANSPORT", planElements.get(1).getElementType()); + assertTrue(planElements.get(1).getEndTime() >= (0)); + assertTrue(planElements.get(1).getEndTime() <= (24*3600)); + assertTrue(planElements.get(1).getStartTime() <= planElements.get(1).getEndTime()); + assertTrue(planElements.get(1).getStartTime() >= (0)); + assertTrue(planElements.get(1).getStartTime() <= (24*3600)); + assertSame(planElements.get(1).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(1).getLogisticChainElement(), collectionElement); + + assertEquals(planElements.get(1).getStartTime(), planElements.get(0).getEndTime(), 0.0); + + assertEquals("LOAD", planElements.get(0).getElementType()); + assertTrue(planElements.get(0).getEndTime() >= (0)); + assertTrue(planElements.getFirst().getEndTime() <= (24*3600)); + assertTrue(planElements.getFirst().getStartTime() <= planElements.getFirst().getEndTime()); + assertTrue(planElements.getFirst().getStartTime() >= (0)); + assertTrue(planElements.getFirst().getStartTime() <= (24*3600)); + assertSame(planElements.getFirst().getResourceId(), collectionResource.getId()); + assertSame(planElements.getFirst().getLogisticChainElement(), collectionElement); + + } + + assertEquals(1, firstTranshipmentHubResource.getSimulationTrackers().size()); + ArrayList eventHandlers = new ArrayList<>(firstTranshipmentHubResource.getSimulationTrackers()); + assertInstanceOf(TransshipmentHubTourEndEventHandler.class, eventHandlers.getFirst()); + TransshipmentHubTourEndEventHandler reloadEventHandler = (TransshipmentHubTourEndEventHandler) eventHandlers.getFirst(); + + for (Entry entry : reloadEventHandler.getServicesWaitedFor().entrySet()) { + CarrierService service = entry.getKey(); + LspShipment shipment = entry.getValue().lspShipment; + LogisticChainElement element = entry.getValue().logisticChainElement; + assertSame(service.getLocationLinkId(), shipment.getFrom()); + assertEquals(service.getCapacityDemand(), shipment.getSize()); + assertEquals(service.getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + boolean handledByTranshipmentHub = false; + for (LogisticChainElement clientElement : reloadEventHandler.getTranshipmentHub().getClientElements()) { + if (clientElement == element) { + handledByTranshipmentHub = true; + break; + } + } + assertTrue(handledByTranshipmentHub); + + assertTrue(element.getOutgoingShipments().getLspShipmentsWTime().contains(shipment)); + assertFalse(element.getIncomingShipments().getLspShipmentsWTime().contains(shipment)); + } + + + for (LspShipment shipment : lsp.getLspShipments()) { + assertEquals(2, shipment.getSimulationTrackers().size()); + eventHandlers = new ArrayList<>(shipment.getSimulationTrackers()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + + assertInstanceOf(LSPTourEndEventHandler.class, eventHandlers.getFirst()); + LSPTourEndEventHandler endHandler = (LSPTourEndEventHandler) eventHandlers.getFirst(); + assertSame(endHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(endHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(endHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(endHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(endHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(endHandler.getLogisticChainElement(), planElements.get(2).getLogisticChainElement()); + assertSame(endHandler.getLogisticChainElement(), lsp.getSelectedPlan().getLogisticChains().iterator().next().getLogisticChainElements().iterator().next()); + assertSame(endHandler.getLspShipment(), shipment); + assertSame(endHandler.getResourceId(), planElements.get(2).getResourceId()); + assertSame(endHandler.getResourceId(), lsp.getResources().iterator().next().getId()); + + assertInstanceOf(CollectionServiceEndEventHandler.class, eventHandlers.get(1)); + CollectionServiceEndEventHandler serviceHandler = (CollectionServiceEndEventHandler) eventHandlers.get(1); + assertSame(serviceHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(serviceHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(serviceHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(serviceHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(serviceHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(serviceHandler.getElement(), planElements.getFirst().getLogisticChainElement()); + assertSame(serviceHandler.getElement(), lsp.getSelectedPlan().getLogisticChains().iterator().next().getLogisticChainElements().iterator().next()); + assertSame(serviceHandler.getLspShipment(), shipment); + assertSame(serviceHandler.getResourceId(), planElements.getFirst().getResourceId()); + assertSame(serviceHandler.getResourceId(), lsp.getResources().iterator().next().getId()); + } + + for (LogisticChain solution : lsp.getSelectedPlan().getLogisticChains()) { + assertEquals(1, solution.getLspShipmentIds().size()); + for (LogisticChainElement element : solution.getLogisticChainElements()) { + assertTrue(element.getIncomingShipments().getLspShipmentsWTime().isEmpty()); + if (element.getNextElement() != null) { + assertTrue(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } else { + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } + } + } + + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/FirstReloadResourceTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/FirstReloadResourceTest.java new file mode 100644 index 00000000000..d69105472f6 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/FirstReloadResourceTest.java @@ -0,0 +1,67 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.freight.logistics.LSPCarrierResource; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; + +public class FirstReloadResourceTest { + + private static final Id hubLinkId = Id.createLinkId("(4 2) (4 3)"); + private TransshipmentHubResource transshipmentHubResource; + + @BeforeEach + public void initialize() { + + + TranshipmentHubSchedulerBuilder schedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + schedulerBuilder.setCapacityNeedFixed(10); + schedulerBuilder.setCapacityNeedLinear(1); + + transshipmentHubResource = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(Id.create("TranshipmentHub1", LSPResource.class), hubLinkId, null) + .setTransshipmentHubScheduler(schedulerBuilder.build()) + .build(); + } + + @Test + public void TranshipmentHubTest() { + assertEquals(10, transshipmentHubResource.getCapacityNeedFixed(), 0.0); + assertEquals(1, transshipmentHubResource.getCapacityNeedLinear(), 0.0); + assertFalse(LSPCarrierResource.class.isAssignableFrom(transshipmentHubResource.getClass())); +// assertSame(TranshipmentHub.getClassOfResource(), TranshipmentHub.class); + assertNotNull(transshipmentHubResource.getClientElements()); + assertTrue(transshipmentHubResource.getClientElements().isEmpty()); + assertSame(transshipmentHubResource.getEndLinkId(), hubLinkId); + assertSame(transshipmentHubResource.getStartLinkId(), hubLinkId); + assertNotNull(transshipmentHubResource.getSimulationTrackers()); + assertFalse(transshipmentHubResource.getSimulationTrackers().isEmpty()); + assertEquals(1, transshipmentHubResource.getSimulationTrackers().size()); + assertNotNull(transshipmentHubResource.getAttributes()); + assertTrue(transshipmentHubResource.getAttributes().isEmpty()); + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MainRunLSPSchedulingTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MainRunLSPSchedulingTest.java new file mode 100644 index 00000000000..4a39f6c6170 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MainRunLSPSchedulingTest.java @@ -0,0 +1,436 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Map.Entry; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.events.handler.EventHandler; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MainRunLSPSchedulingTest { + private LSP lsp; + private LSPResource collectionResource; + private LogisticChainElement collectionElement; + private LSPResource firstTranshipmentHubResource; + private LogisticChainElement firstHubElement; + private LSPResource mainRunResource; + private LogisticChainElement mainRunElement; + private Id toLinkId; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50/3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + firstHubElement = firstHubElementBuilder.build(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50/3.6); + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + toLinkId = Id.createLinkId("(14 2) (14 3)"); + + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(fromLinkId) + .setToLinkId(toLinkId) + .build(); + + mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + completeSolutionBuilder.addLogisticChainElement(mainRunElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + + for (int i = 1; i < 2; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + //Random random = new Random(1); + int capacityDemand = MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + } + + @Test + public void testMainRunLSPScheduling() { + + for (LspShipment shipment : lsp.getLspShipments()) { + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + System.out.println(); + for (int i = 0; i < LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size(); i++) { + System.out.println("Scheduled: " + scheduleElements.get(i).getLogisticChainElement().getId() + " " + scheduleElements.get(i).getResourceId() + " " + scheduleElements.get(i).getElementType() + " Start: " + scheduleElements.get(i).getStartTime() + " End: " + scheduleElements.get(i).getEndTime()); + } + System.out.println(); + } + + + for (LspShipment shipment : lsp.getLspShipments()) { + assertEquals(7, LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + planElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + assertEquals("UNLOAD", planElements.get(6).getElementType()); + assertTrue(planElements.get(6).getEndTime() >= (0)); + assertTrue(planElements.get(6).getEndTime() <= (24*3600)); + assertTrue(planElements.get(6).getStartTime() <= planElements.get(6).getEndTime()); + assertTrue(planElements.get(6).getStartTime() >= (0)); + assertTrue(planElements.get(6).getStartTime() <= (24*3600)); + assertSame(planElements.get(6).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(6).getLogisticChainElement(), mainRunElement); + + assertEquals(planElements.get(6).getStartTime(), planElements.get(5).getEndTime(), 0.0); + + assertEquals("TRANSPORT", planElements.get(5).getElementType()); + assertTrue(planElements.get(5).getEndTime() >= (0)); + assertTrue(planElements.get(5).getEndTime() <= (24*3600)); + assertTrue(planElements.get(5).getStartTime() <= planElements.get(5).getEndTime()); + assertTrue(planElements.get(5).getStartTime() >= (0)); + assertTrue(planElements.get(5).getStartTime() <= (24*3600)); + assertSame(planElements.get(5).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(5).getLogisticChainElement(), mainRunElement); + + assertEquals(planElements.get(5).getStartTime(), planElements.get(4).getEndTime(), 0.0); + + assertEquals("LOAD", planElements.get(4).getElementType()); + assertTrue(planElements.get(4).getEndTime() >= (0)); + assertTrue(planElements.get(4).getEndTime() <= (24*3600)); + assertTrue(planElements.get(4).getStartTime() <= planElements.get(4).getEndTime()); + assertTrue(planElements.get(4).getStartTime() >= (0)); + assertTrue(planElements.get(4).getStartTime() <= (24*3600)); + assertSame(planElements.get(4).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(4).getLogisticChainElement(), mainRunElement); + + assertTrue(planElements.get(4).getStartTime() >= (planElements.get(3).getEndTime() / (1.0001)) + 300); + + assertEquals("HANDLE", planElements.get(3).getElementType()); + assertTrue(planElements.get(3).getEndTime() >= (0)); + assertTrue(planElements.get(3).getEndTime() <= (24*3600)); + assertTrue(planElements.get(3).getStartTime() <= planElements.get(3).getEndTime()); + assertTrue(planElements.get(3).getStartTime() >= (0)); + assertTrue(planElements.get(3).getStartTime() <= (24*3600)); + assertSame(planElements.get(3).getResourceId(), firstTranshipmentHubResource.getId()); + assertSame(planElements.get(3).getLogisticChainElement(), firstHubElement); + + assertEquals(planElements.get(3).getStartTime(), (planElements.get(2).getEndTime() + 300), 0.0); + + assertEquals("UNLOAD", planElements.get(2).getElementType()); + assertTrue(planElements.get(2).getEndTime() >= (0)); + assertTrue(planElements.get(2).getEndTime() <= (24*3600)); + assertTrue(planElements.get(2).getStartTime() <= planElements.get(2).getEndTime()); + assertTrue(planElements.get(2).getStartTime() >= (0)); + assertTrue(planElements.get(2).getStartTime() <= (24*3600)); + assertSame(planElements.get(2).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(2).getLogisticChainElement(), collectionElement); + + assertEquals(planElements.get(2).getStartTime(), planElements.get(1).getEndTime(), 0.0); + + assertEquals("TRANSPORT", planElements.get(1).getElementType()); + assertTrue(planElements.get(1).getEndTime() >= (0)); + assertTrue(planElements.get(1).getEndTime() <= (24*3600)); + assertTrue(planElements.get(1).getStartTime() <= planElements.get(1).getEndTime()); + assertTrue(planElements.get(1).getStartTime() >= (0)); + assertTrue(planElements.get(1).getStartTime() <= (24*3600)); + assertSame(planElements.get(1).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(1).getLogisticChainElement(), collectionElement); + + assertEquals(planElements.get(1).getStartTime(), planElements.get(0).getEndTime(), 0.0); + + assertEquals("LOAD", planElements.get(0).getElementType()); + assertTrue(planElements.get(0).getEndTime() >= (0)); + assertTrue(planElements.getFirst().getEndTime() <= (24*3600)); + assertTrue(planElements.getFirst().getStartTime() <= planElements.getFirst().getEndTime()); + assertTrue(planElements.getFirst().getStartTime() >= (0)); + assertTrue(planElements.getFirst().getStartTime() <= (24*3600)); + assertSame(planElements.getFirst().getResourceId(), collectionResource.getId()); + assertSame(planElements.getFirst().getLogisticChainElement(), collectionElement); + } + + assertEquals(1, firstTranshipmentHubResource.getSimulationTrackers().size()); + ArrayList eventHandlers = new ArrayList<>(firstTranshipmentHubResource.getSimulationTrackers()); + assertInstanceOf(TransshipmentHubTourEndEventHandler.class, eventHandlers.getFirst()); + TransshipmentHubTourEndEventHandler reloadEventHandler = (TransshipmentHubTourEndEventHandler) eventHandlers.getFirst(); + + for (Entry entry : reloadEventHandler.getServicesWaitedFor().entrySet()) { + CarrierService service = entry.getKey(); + LspShipment shipment = entry.getValue().lspShipment; + LogisticChainElement element = entry.getValue().logisticChainElement; + assertSame(service.getLocationLinkId(), shipment.getFrom()); + assertEquals(service.getCapacityDemand(), shipment.getSize()); + assertEquals(service.getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + boolean handledByTranshipmentHub = false; + for (LogisticChainElement clientElement : reloadEventHandler.getTranshipmentHub().getClientElements()) { + if (clientElement == element) { + handledByTranshipmentHub = true; + break; + } + } + assertTrue(handledByTranshipmentHub); + + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().contains(shipment)); + assertFalse(element.getIncomingShipments().getLspShipmentsWTime().contains(shipment)); + } + + for (LspShipment shipment : lsp.getLspShipments()) { + assertEquals(4, shipment.getSimulationTrackers().size()); + eventHandlers = new ArrayList<>(shipment.getSimulationTrackers()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + planElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList solutionElements = new ArrayList<>(lsp.getSelectedPlan().getLogisticChains().iterator().next().getLogisticChainElements()); + ArrayList resources = new ArrayList<>(lsp.getResources()); + + assertInstanceOf(LSPTourEndEventHandler.class, eventHandlers.getFirst()); + LSPTourEndEventHandler endHandler = (LSPTourEndEventHandler) eventHandlers.getFirst(); + assertSame(endHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(endHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(endHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(endHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(endHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(endHandler.getLogisticChainElement(), planElements.get(0).getLogisticChainElement()); + assertSame(endHandler.getLogisticChainElement(), planElements.get(1).getLogisticChainElement()); + assertSame(endHandler.getLogisticChainElement(), planElements.get(2).getLogisticChainElement()); + assertSame(endHandler.getLogisticChainElement(), solutionElements.getFirst()); + assertSame(endHandler.getLspShipment(), shipment); + assertSame(endHandler.getResourceId(), planElements.get(0).getResourceId()); + assertSame(endHandler.getResourceId(), planElements.get(1).getResourceId()); + assertSame(endHandler.getResourceId(), planElements.get(2).getResourceId()); + assertSame(endHandler.getResourceId(), resources.getFirst().getId()); + + //CollectionServiceEnd + assertInstanceOf(CollectionServiceEndEventHandler.class, eventHandlers.get(1)); + CollectionServiceEndEventHandler serviceHandler = (CollectionServiceEndEventHandler) eventHandlers.get(1); + assertSame(serviceHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(serviceHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(serviceHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(serviceHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(serviceHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(serviceHandler.getElement(), planElements.get(0).getLogisticChainElement()); + assertSame(serviceHandler.getElement(), planElements.get(1).getLogisticChainElement()); + assertSame(serviceHandler.getElement(), planElements.get(2).getLogisticChainElement()); + assertSame(serviceHandler.getElement(), solutionElements.getFirst()); + assertSame(serviceHandler.getLspShipment(), shipment); + assertSame(serviceHandler.getResourceId(), planElements.get(0).getResourceId()); + assertSame(serviceHandler.getResourceId(), planElements.get(1).getResourceId()); + assertSame(serviceHandler.getResourceId(), planElements.get(2).getResourceId()); + assertSame(serviceHandler.getResourceId(), resources.getFirst().getId()); + + //MainRunTourStart + assertInstanceOf(LSPTourStartEventHandler.class, eventHandlers.get(2)); + LSPTourStartEventHandler mainRunStartHandler = (LSPTourStartEventHandler) eventHandlers.get(2); + assertSame(mainRunStartHandler.getCarrierService().getLocationLinkId(), toLinkId); + assertEquals(mainRunStartHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(mainRunStartHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(0, mainRunStartHandler.getCarrierService().getServiceStartTimeWindow().getStart(), 0.0); + assertEquals(Integer.MAX_VALUE, mainRunStartHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), 0.0); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(4).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(5).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(6).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), solutionElements.get(2)); + assertSame(mainRunStartHandler.getLspShipment(), shipment); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(4).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(5).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(6).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), resources.get(2).getId()); + + //MainRunTourEnd + assertInstanceOf(LSPTourEndEventHandler.class, eventHandlers.get(3)); + LSPTourEndEventHandler mainRunEndHandler = (LSPTourEndEventHandler) eventHandlers.get(3); + assertSame(mainRunEndHandler.getCarrierService().getLocationLinkId(), toLinkId); + assertEquals(mainRunEndHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(mainRunEndHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(0, mainRunEndHandler.getCarrierService().getServiceStartTimeWindow().getStart(), 0.0); + assertEquals(Integer.MAX_VALUE, mainRunEndHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), 0.0); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(4).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(5).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(6).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), solutionElements.get(2)); + assertSame(mainRunEndHandler.getLspShipment(), shipment); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(4).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(5).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(6).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), resources.get(2).getId()); + } + + for (LogisticChain solution : lsp.getSelectedPlan().getLogisticChains()) { + assertEquals(1, solution.getLspShipmentIds().size()); + for (LogisticChainElement element : solution.getLogisticChainElements()) { + assertTrue(element.getIncomingShipments().getLspShipmentsWTime().isEmpty()); + if (element.getNextElement() != null) { + assertTrue(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } else { + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } + } + } + + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MultipleShipmentsCollectionLSPSchedulingTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MultipleShipmentsCollectionLSPSchedulingTest.java new file mode 100644 index 00000000000..d30d608f985 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MultipleShipmentsCollectionLSPSchedulingTest.java @@ -0,0 +1,237 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Random; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.events.handler.EventHandler; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.CollectionCarrierResourceBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MultipleShipmentsCollectionLSPSchedulingTest { + + private LSP collectionLSP; + private LSPResource collectionResource; + private LogisticChainElement collectionElement; + + @BeforeEach + public void initialize() { + + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + Id carrierId = Id.create("CollectionCarrier", Carrier.class); + Id vehicleTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(vehicleTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50/3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id vollectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle carrierVehicle = CarrierVehicle.newInstance(vollectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(carrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities capabilities = capabilitiesBuilder.build(); + Carrier carrier = CarriersUtils.createCarrier(carrierId); + carrier.setCarrierCapabilities(capabilities); + + + Id.create("CollectionCarrierResource", LSPResource.class); + CollectionCarrierResourceBuilder adapterBuilder = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(carrier); + adapterBuilder.setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)); + adapterBuilder.setLocationLinkId(collectionLinkId); + collectionResource = adapterBuilder.build(); + + Id elementId = Id.create("CollectionElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder collectionElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(elementId); + collectionElementBuilder.setResource(collectionResource); + collectionElement = collectionElementBuilder.build(); + + Id collectionSolutionId = Id.create("CollectionSolution", LogisticChain.class); + LSPUtils.LogisticChainBuilder collectionSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(collectionSolutionId); + collectionSolutionBuilder.addLogisticChainElement(collectionElement); + LogisticChain collectionSolution = collectionSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan collectionPlan = LSPUtils.createLSPPlan(); + collectionPlan.setInitialShipmentAssigner(assigner); + collectionPlan.addLogisticChain(collectionSolution); + + LSPUtils.LSPBuilder collectionLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + collectionLSPBuilder.setInitialPlan(collectionPlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + collectionLSPBuilder.setLogisticChainScheduler(simpleScheduler); + collectionLSP = collectionLSPBuilder.build(); + + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + + + for (int i = 1; i < 100; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + Random random = new Random(1); + int capacityDemand = random.nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, random); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + } + + builder.setToLinkId(collectionLinkId); + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + collectionLSP.assignShipmentToLSP(shipment); + } + collectionLSP.scheduleLogisticChains(); + + } + + @Test + public void testCollectionLSPScheduling() { + + for (LspShipment shipment : collectionLSP.getLspShipments()) { + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(collectionLSP.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + System.out.println(); + for (int i = 0; i < LspShipmentUtils.getOrCreateShipmentPlan(collectionLSP.getSelectedPlan(), shipment.getId()).getPlanElements().size(); i++) { + System.out.println("Scheduled: " + scheduleElements.get(i).getLogisticChainElement().getId() + " " + scheduleElements.get(i).getResourceId() + " " + scheduleElements.get(i).getElementType() + " Start: " + scheduleElements.get(i).getStartTime() + " End: " + scheduleElements.get(i).getEndTime()); + } + System.out.println(); + } + + for (LspShipment shipment : collectionLSP.getLspShipments()) { + assertEquals(3, LspShipmentUtils.getOrCreateShipmentPlan(collectionLSP.getSelectedPlan(), shipment.getId()).getPlanElements().size()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(collectionLSP.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + assertEquals("UNLOAD", planElements.get(2).getElementType()); + assertTrue(planElements.get(2).getEndTime() >= (0)); + assertTrue(planElements.get(2).getEndTime() <= (24*3600)); + assertTrue(planElements.get(2).getStartTime() <= planElements.get(2).getEndTime()); + assertTrue(planElements.get(2).getStartTime() >= (0)); + assertTrue(planElements.get(2).getStartTime() <= (24*3600)); + assertSame(planElements.get(2).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(2).getLogisticChainElement(), collectionElement); + assertEquals("TRANSPORT", planElements.get(1).getElementType()); + assertTrue(planElements.get(1).getEndTime() >= (0)); + assertTrue(planElements.get(1).getEndTime() <= (24*3600)); + assertEquals(planElements.get(2).getStartTime(), planElements.get(1).getEndTime(), 0.0); + assertTrue(planElements.get(1).getStartTime() <= planElements.get(1).getEndTime()); + assertTrue(planElements.get(1).getStartTime() >= (0)); + assertTrue(planElements.get(1).getStartTime() <= (24*3600)); + assertSame(planElements.get(1).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(1).getLogisticChainElement(), collectionElement); + assertEquals("LOAD", planElements.get(0).getElementType()); + assertTrue(planElements.get(0).getEndTime() >= (0)); + assertTrue(planElements.get(0).getEndTime() <= (24*3600)); + assertEquals(planElements.get(1).getStartTime(), planElements.get(0).getEndTime(), 0.0); + assertTrue(planElements.get(0).getStartTime() <= planElements.get(0).getEndTime()); + assertTrue(planElements.get(0).getStartTime() >= (0)); + assertTrue(planElements.getFirst().getStartTime() <= (24*3600)); + assertSame(planElements.getFirst().getResourceId(), collectionResource.getId()); + assertSame(planElements.getFirst().getLogisticChainElement(), collectionElement); + + assertEquals(2, shipment.getSimulationTrackers().size()); + ArrayList eventHandlers = new ArrayList<>(shipment.getSimulationTrackers()); + + assertInstanceOf(LSPTourEndEventHandler.class, eventHandlers.getFirst()); + LSPTourEndEventHandler endHandler = (LSPTourEndEventHandler) eventHandlers.getFirst(); + assertSame(endHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(endHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(endHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(endHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(endHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(endHandler.getLogisticChainElement(), planElements.get(2).getLogisticChainElement()); + assertSame(endHandler.getLogisticChainElement(), collectionLSP.getSelectedPlan().getLogisticChains().iterator().next().getLogisticChainElements().iterator().next()); + assertSame(endHandler.getLspShipment(), shipment); + assertSame(endHandler.getResourceId(), planElements.get(2).getResourceId()); + assertSame(endHandler.getResourceId(), collectionLSP.getResources().iterator().next().getId()); + + assertInstanceOf(CollectionServiceEndEventHandler.class, eventHandlers.get(1)); + CollectionServiceEndEventHandler serviceHandler = (CollectionServiceEndEventHandler) eventHandlers.get(1); + assertSame(serviceHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(serviceHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(serviceHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(serviceHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(serviceHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(serviceHandler.getElement(), planElements.get(1).getLogisticChainElement()); + assertSame(serviceHandler.getElement(), collectionLSP.getSelectedPlan().getLogisticChains().iterator().next().getLogisticChainElements().iterator().next()); + assertSame(serviceHandler.getLspShipment(), shipment); + assertSame(serviceHandler.getResourceId(), planElements.get(1).getResourceId()); + assertSame(serviceHandler.getResourceId(), collectionLSP.getResources().iterator().next().getId()); + } + + for (LogisticChain solution : collectionLSP.getSelectedPlan().getLogisticChains()) { + for (LogisticChainElement element : solution.getLogisticChainElements()) { + assertTrue(element.getIncomingShipments().getLspShipmentsWTime().isEmpty()); + if (element.getNextElement() != null) { + assertTrue(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } else { + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } + } + } + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MultipleShipmentsCompleteLSPSchedulingTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MultipleShipmentsCompleteLSPSchedulingTest.java new file mode 100644 index 00000000000..f27a1e08219 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MultipleShipmentsCompleteLSPSchedulingTest.java @@ -0,0 +1,610 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.Random; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.events.handler.EventHandler; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MultipleShipmentsCompleteLSPSchedulingTest { + + private LSP lsp; + private LSPResource collectionResource; + private LogisticChainElement collectionElement; + private LSPResource firstTranshipmentHubResource; + private LogisticChainElement firstHubElement; + private LSPResource mainRunResource; + private LogisticChainElement mainRunElement; + private LSPResource secondTranshipmentHubResource; + private LogisticChainElement secondHubElement; + private LSPResource distributionResource; + private LogisticChainElement distributionElement; + private Id toLinkId; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50/3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + firstHubElement = firstHubElementBuilder.build(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50/3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + toLinkId = Id.createLinkId("(14 2) (14 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(fromLinkId) + .setToLinkId(toLinkId) + .build(); + + mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + TranshipmentHubSchedulerBuilder secondSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + secondSchedulerBuilder.setCapacityNeedFixed(10); + secondSchedulerBuilder.setCapacityNeedLinear(1); + + + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + + TransshipmentHubBuilder secondTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(secondTransshipmentHubId, secondTransshipmentHub_LinkId, scenario); + secondTransshipmentHubBuilder.setTransshipmentHubScheduler(secondSchedulerBuilder.build()); + secondTranshipmentHubResource = secondTransshipmentHubBuilder.build(); + + Id secondHubElementId = Id.create("SecondHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTranshipmentHubResource); + secondHubElement = secondHubElementBuilder.build(); + + Id distributionCarrierId = Id.create("DistributionCarrier", Carrier.class); + Id distributionVehTypeId = Id.create("DistributionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType distributionVehType = VehicleUtils.createVehicleType(distributionVehTypeId, TransportMode.car); + distributionVehType.getCapacity().setOther(10); + distributionVehType.getCostInformation().setCostsPerMeter(0.0004); + distributionVehType.getCostInformation().setCostsPerSecond(0.38); + distributionVehType.getCostInformation().setFixedCost(49.); + distributionVehType.setMaximumVelocity(50/3.6); + + Id distributionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id distributionVehicleId = Id.createVehicleId("DistributionVehicle"); + CarrierVehicle distributionCarrierVehicle = CarrierVehicle.newInstance(distributionVehicleId, distributionLinkId, distributionVehType); + + CarrierCapabilities.Builder capabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + capabilitiesBuilder.addVehicle(distributionCarrierVehicle); + capabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities distributionCapabilities = capabilitiesBuilder.build(); + Carrier distributionCarrier = CarriersUtils.createCarrier(distributionCarrierId); + distributionCarrier.setCarrierCapabilities(distributionCapabilities); + + + distributionResource = ResourceImplementationUtils.DistributionCarrierResourceBuilder.newInstance(distributionCarrier) + .setDistributionScheduler(ResourceImplementationUtils.createDefaultDistributionCarrierScheduler(scenario)) + .setLocationLinkId(distributionLinkId) + .build(); + + Id distributionElementId = Id.create("DistributionElement", LogisticChainElement.class); + distributionElement = LSPUtils.LogisticChainElementBuilder.newInstance(distributionElementId) + .setResource(distributionResource) + .build(); + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + secondHubElement.connectWithNextElement(distributionElement); + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LogisticChain completeSolution = LSPUtils.LogisticChainBuilder.newInstance(solutionId) + .addLogisticChainElement(collectionElement) + .addLogisticChainElement(firstHubElement) + .addLogisticChainElement(mainRunElement) + .addLogisticChainElement(secondHubElement) + .addLogisticChainElement(distributionElement) + .build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + resourcesList.add(secondTranshipmentHubResource); + resourcesList.add(distributionResource); + + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + Random rand = new Random(1); + for (int i = 1; i < 100; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = rand.nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList, rand); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList, rand); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + } + + @Test + public void testCompletedLSPScheduling() { + + for (LspShipment shipment : lsp.getLspShipments()) { + ArrayList elementList = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + elementList.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + System.out.println(); + for (LspShipmentPlanElement element : elementList) { + System.out.println(element.getLogisticChainElement().getId() + "\t\t" + element.getResourceId() + "\t\t" + element.getElementType() + "\t\t" + element.getStartTime() + "\t\t" + element.getEndTime()); + } + System.out.println(); + } + + ArrayList solutionElements = new ArrayList<>(lsp.getSelectedPlan().getLogisticChains().iterator().next().getLogisticChainElements()); + ArrayList resources = new ArrayList<>(lsp.getResources()); + + for (LspShipment shipment : lsp.getLspShipments()) { + assertEquals(11, LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + planElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + assertEquals("UNLOAD", planElements.get(10).getElementType()); + assertTrue(planElements.get(10).getEndTime() >= (0)); + assertTrue(planElements.get(10).getEndTime() <= (24*3600)); + assertTrue(planElements.get(10).getStartTime() <= planElements.get(10).getEndTime()); + assertTrue(planElements.get(10).getStartTime() >= (0)); + assertTrue(planElements.get(10).getStartTime() <= (24*3600)); + assertSame(planElements.get(10).getResourceId(), distributionResource.getId()); + assertSame(planElements.get(10).getLogisticChainElement(), distributionElement); + + assertEquals(planElements.get(10).getStartTime(), planElements.get(9).getEndTime(), 0.0); + + assertEquals("TRANSPORT", planElements.get(9).getElementType()); + assertTrue(planElements.get(9).getEndTime() >= (0)); + assertTrue(planElements.get(9).getEndTime() <= (24*3600)); + assertTrue(planElements.get(9).getStartTime() <= planElements.get(9).getEndTime()); + assertTrue(planElements.get(9).getStartTime() >= (0)); + assertTrue(planElements.get(9).getStartTime() <= (24*3600)); + assertSame(planElements.get(9).getResourceId(), distributionResource.getId()); + assertSame(planElements.get(9).getLogisticChainElement(), distributionElement); + + assertEquals(planElements.get(9).getStartTime(), planElements.get(8).getEndTime(), 0.0); + + assertEquals("LOAD", planElements.get(8).getElementType()); + assertTrue(planElements.get(8).getEndTime() >= (0)); + assertTrue(planElements.get(8).getEndTime() <= (24*3600)); + assertTrue(planElements.get(8).getStartTime() <= planElements.get(8).getEndTime()); + assertTrue(planElements.get(8).getStartTime() >= (0)); + assertTrue(planElements.get(8).getStartTime() <= (24*3600)); + assertSame(planElements.get(8).getResourceId(), distributionResource.getId()); + assertSame(planElements.get(8).getLogisticChainElement(), distributionElement); + + assertTrue(planElements.get(8).getStartTime() >= planElements.get(7).getEndTime() / 1.0001 + 300); + + assertEquals("HANDLE", planElements.get(7).getElementType()); + assertTrue(planElements.get(7).getEndTime() >= (0)); + assertTrue(planElements.get(7).getEndTime() <= (24*3600)); + assertTrue(planElements.get(7).getStartTime() <= planElements.get(7).getEndTime()); + assertTrue(planElements.get(7).getStartTime() >= (0)); + assertTrue(planElements.get(7).getStartTime() <= (24*3600)); + assertSame(planElements.get(7).getResourceId(), secondTranshipmentHubResource.getId()); + assertSame(planElements.get(7).getLogisticChainElement(), secondHubElement); + + assertEquals(planElements.get(7).getStartTime(), planElements.get(6).getEndTime() + 300, 0.0); + + assertEquals("UNLOAD", planElements.get(6).getElementType()); + assertTrue(planElements.get(6).getEndTime() >= (0)); + assertTrue(planElements.get(6).getEndTime() <= (24*3600)); + assertTrue(planElements.get(6).getStartTime() <= planElements.get(6).getEndTime()); + assertTrue(planElements.get(6).getStartTime() >= (0)); + assertTrue(planElements.get(6).getStartTime() <= (24*3600)); + assertSame(planElements.get(6).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(6).getLogisticChainElement(), mainRunElement); + + assertEquals(planElements.get(6).getStartTime(), planElements.get(5).getEndTime(), 0.0); + + assertEquals("TRANSPORT", planElements.get(5).getElementType()); + assertTrue(planElements.get(5).getEndTime() >= (0)); + assertTrue(planElements.get(5).getEndTime() <= (24*3600)); + assertTrue(planElements.get(5).getStartTime() <= planElements.get(5).getEndTime()); + assertTrue(planElements.get(5).getStartTime() >= (0)); + assertTrue(planElements.get(5).getStartTime() <= (24*3600)); + assertSame(planElements.get(5).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(5).getLogisticChainElement(), mainRunElement); + + assertEquals(planElements.get(5).getStartTime(), planElements.get(4).getEndTime(), 0.0); + + assertEquals("LOAD", planElements.get(4).getElementType()); + assertTrue(planElements.get(4).getEndTime() >= (0)); + assertTrue(planElements.get(4).getEndTime() <= (24*3600)); + assertTrue(planElements.get(4).getStartTime() <= planElements.get(4).getEndTime()); + assertTrue(planElements.get(4).getStartTime() >= (0)); + assertTrue(planElements.get(4).getStartTime() <= (24*3600)); + assertSame(planElements.get(4).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(4).getLogisticChainElement(), mainRunElement); + + assertTrue(planElements.get(4).getStartTime() >= planElements.get(3).getEndTime() / (1.0001) + 300); + + assertEquals("HANDLE", planElements.get(3).getElementType()); + assertTrue(planElements.get(3).getEndTime() >= (0)); + assertTrue(planElements.get(3).getEndTime() <= (24*3600)); + assertTrue(planElements.get(3).getStartTime() <= planElements.get(3).getEndTime()); + assertTrue(planElements.get(3).getStartTime() >= (0)); + assertTrue(planElements.get(3).getStartTime() <= (24*3600)); + assertSame(planElements.get(3).getResourceId(), firstTranshipmentHubResource.getId()); + assertSame(planElements.get(3).getLogisticChainElement(), firstHubElement); + + assertEquals(planElements.get(3).getStartTime(), planElements.get(2).getEndTime() + 300, 0.0); + + assertEquals("UNLOAD", planElements.get(2).getElementType()); + assertTrue(planElements.get(2).getEndTime() >= (0)); + assertTrue(planElements.get(2).getEndTime() <= (24*3600)); + assertTrue(planElements.get(2).getStartTime() <= planElements.get(2).getEndTime()); + assertTrue(planElements.get(2).getStartTime() >= (0)); + assertTrue(planElements.get(2).getStartTime() <= (24*3600)); + assertSame(planElements.get(2).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(2).getLogisticChainElement(), collectionElement); + + assertEquals(planElements.get(2).getStartTime(), planElements.get(1).getEndTime(), 0.0); + + assertEquals("TRANSPORT", planElements.get(1).getElementType()); + assertTrue(planElements.get(1).getEndTime() >= (0)); + assertTrue(planElements.get(1).getEndTime() <= (24*3600)); + assertTrue(planElements.get(1).getStartTime() <= planElements.get(1).getEndTime()); + assertTrue(planElements.get(1).getStartTime() >= (0)); + assertTrue(planElements.get(1).getStartTime() <= (24*3600)); + assertSame(planElements.get(1).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(1).getLogisticChainElement(), collectionElement); + + assertEquals(planElements.get(1).getStartTime(), planElements.get(0).getEndTime(), 0.0); + + assertEquals("LOAD", planElements.get(0).getElementType()); + assertTrue(planElements.get(0).getEndTime() >= (0)); + assertTrue(planElements.getFirst().getEndTime() <= (24*3600)); + assertTrue(planElements.getFirst().getStartTime() <= planElements.getFirst().getEndTime()); + assertTrue(planElements.getFirst().getStartTime() >= (0)); + assertTrue(planElements.getFirst().getStartTime() <= (24*3600)); + assertSame(planElements.getFirst().getResourceId(), collectionResource.getId()); + assertSame(planElements.getFirst().getLogisticChainElement(), collectionElement); + } + + assertEquals(1, firstTranshipmentHubResource.getSimulationTrackers().size()); + ArrayList eventHandlers = new ArrayList<>(firstTranshipmentHubResource.getSimulationTrackers()); + assertInstanceOf(TransshipmentHubTourEndEventHandler.class, eventHandlers.getFirst()); + TransshipmentHubTourEndEventHandler reloadEventHandler = (TransshipmentHubTourEndEventHandler) eventHandlers.getFirst(); + Iterator> iter = reloadEventHandler.getServicesWaitedFor().entrySet().iterator(); + + while (iter.hasNext()) { + Entry entry = iter.next(); + CarrierService service = entry.getKey(); + LspShipment shipment = entry.getValue().lspShipment; + LogisticChainElement element = entry.getValue().logisticChainElement; + assertSame(service.getLocationLinkId(), shipment.getFrom()); + assertEquals(service.getCapacityDemand(), shipment.getSize()); + assertEquals(service.getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + boolean handledByTranshipmentHub = false; + for (LogisticChainElement clientElement : reloadEventHandler.getTranshipmentHub().getClientElements()) { + if (clientElement == element) { + handledByTranshipmentHub = true; + break; + } + } + assertTrue(handledByTranshipmentHub); + + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().contains(shipment)); + assertFalse(element.getIncomingShipments().getLspShipmentsWTime().contains(shipment)); + } + + assertEquals(1, secondTranshipmentHubResource.getSimulationTrackers().size()); + eventHandlers = new ArrayList<>(secondTranshipmentHubResource.getSimulationTrackers()); + assertInstanceOf(TransshipmentHubTourEndEventHandler.class, eventHandlers.getFirst()); + reloadEventHandler = (TransshipmentHubTourEndEventHandler) eventHandlers.getFirst(); + iter = reloadEventHandler.getServicesWaitedFor().entrySet().iterator(); + + while (iter.hasNext()) { + Entry entry = iter.next(); + CarrierService service = entry.getKey(); + LspShipment shipment = entry.getValue().lspShipment; + LogisticChainElement element = entry.getValue().logisticChainElement; + assertSame(service.getLocationLinkId(), toLinkId); + assertEquals(service.getCapacityDemand(), shipment.getSize()); + assertEquals(service.getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + boolean handledByTranshipmentHub = false; + for (LogisticChainElement clientElement : reloadEventHandler.getTranshipmentHub().getClientElements()) { + if (clientElement == element) { + handledByTranshipmentHub = true; + break; + } + } + assertTrue(handledByTranshipmentHub); + + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().contains(shipment)); + assertFalse(element.getIncomingShipments().getLspShipmentsWTime().contains(shipment)); + } + + for (LspShipment shipment : lsp.getLspShipments()) { + assertEquals(6, shipment.getSimulationTrackers().size()); + eventHandlers = new ArrayList<>(shipment.getSimulationTrackers()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + planElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + assertInstanceOf(LSPTourEndEventHandler.class, eventHandlers.getFirst()); + LSPTourEndEventHandler endHandler = (LSPTourEndEventHandler) eventHandlers.getFirst(); + assertSame(endHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(endHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(endHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(endHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(endHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(endHandler.getLogisticChainElement(), planElements.get(0).getLogisticChainElement()); + assertSame(endHandler.getLogisticChainElement(), planElements.get(1).getLogisticChainElement()); + assertSame(endHandler.getLogisticChainElement(), planElements.get(2).getLogisticChainElement()); + assertSame(endHandler.getLogisticChainElement(), solutionElements.getFirst()); + assertSame(endHandler.getLspShipment(), shipment); + assertSame(endHandler.getResourceId(), planElements.get(0).getResourceId()); + assertSame(endHandler.getResourceId(), planElements.get(1).getResourceId()); + assertSame(endHandler.getResourceId(), planElements.get(2).getResourceId()); + assertSame(endHandler.getResourceId(), resources.getFirst().getId()); + + //CollectionServiceEnd + assertInstanceOf(CollectionServiceEndEventHandler.class, eventHandlers.get(1)); + CollectionServiceEndEventHandler serviceHandler = (CollectionServiceEndEventHandler) eventHandlers.get(1); + assertSame(serviceHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(serviceHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(serviceHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(serviceHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(serviceHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(serviceHandler.getElement(), planElements.get(0).getLogisticChainElement()); + assertSame(serviceHandler.getElement(), planElements.get(1).getLogisticChainElement()); + assertSame(serviceHandler.getElement(), planElements.get(2).getLogisticChainElement()); + assertSame(serviceHandler.getElement(), solutionElements.getFirst()); + assertSame(serviceHandler.getLspShipment(), shipment); + assertSame(serviceHandler.getResourceId(), planElements.get(0).getResourceId()); + assertSame(serviceHandler.getResourceId(), planElements.get(1).getResourceId()); + assertSame(serviceHandler.getResourceId(), planElements.get(2).getResourceId()); + assertSame(serviceHandler.getResourceId(), resources.getFirst().getId()); + + //MainRunTourStart + assertInstanceOf(LSPTourStartEventHandler.class, eventHandlers.get(2)); + LSPTourStartEventHandler mainRunStartHandler = (LSPTourStartEventHandler) eventHandlers.get(2); + assertSame(mainRunStartHandler.getCarrierService().getLocationLinkId(), toLinkId); + assertEquals(mainRunStartHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(mainRunStartHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(0, mainRunStartHandler.getCarrierService().getServiceStartTimeWindow().getStart(), 0.0); + assertEquals(Integer.MAX_VALUE, mainRunStartHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), 0.0); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(4).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(5).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(6).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), solutionElements.get(2)); + assertSame(mainRunStartHandler.getLspShipment(), shipment); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(4).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(5).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(6).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), resources.get(2).getId()); + + //MainRunTourEnd + assertInstanceOf(LSPTourEndEventHandler.class, eventHandlers.get(3)); + LSPTourEndEventHandler mainRunEndHandler = (LSPTourEndEventHandler) eventHandlers.get(3); + assertSame(mainRunEndHandler.getCarrierService().getLocationLinkId(), toLinkId); + assertEquals(mainRunEndHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(mainRunEndHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(0, mainRunEndHandler.getCarrierService().getServiceStartTimeWindow().getStart(), 0.0); + assertEquals(Integer.MAX_VALUE, mainRunEndHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), 0.0); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(4).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(5).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(6).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), solutionElements.get(2)); + assertSame(mainRunEndHandler.getLspShipment(), shipment); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(4).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(5).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(6).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), resources.get(2).getId()); + + //DistributionTourStart + assertInstanceOf(LSPTourStartEventHandler.class, eventHandlers.get(4)); + LSPTourStartEventHandler lspTourStartEventHandler = (LSPTourStartEventHandler) eventHandlers.get(4); + assertSame(lspTourStartEventHandler.getCarrierService().getLocationLinkId(), shipment.getTo()); + assertEquals(lspTourStartEventHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(lspTourStartEventHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(0, lspTourStartEventHandler.getCarrierService().getServiceStartTimeWindow().getStart(), 0.0); + assertEquals(Integer.MAX_VALUE, lspTourStartEventHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), 0.0); + assertSame(lspTourStartEventHandler.getLogisticChainElement(), planElements.get(8).getLogisticChainElement()); + assertSame(lspTourStartEventHandler.getLogisticChainElement(), planElements.get(9).getLogisticChainElement()); + assertSame(lspTourStartEventHandler.getLogisticChainElement(), planElements.get(10).getLogisticChainElement()); + assertSame(lspTourStartEventHandler.getLogisticChainElement(), solutionElements.get(4)); + assertSame(lspTourStartEventHandler.getLspShipment(), shipment); + assertSame(lspTourStartEventHandler.getResourceId(), planElements.get(8).getResourceId()); + assertSame(lspTourStartEventHandler.getResourceId(), planElements.get(9).getResourceId()); + assertSame(lspTourStartEventHandler.getResourceId(), planElements.get(10).getResourceId()); + assertSame(lspTourStartEventHandler.getResourceId(), resources.get(4).getId()); + + //DistributionServiceStart + assertInstanceOf(DistributionServiceStartEventHandler.class, eventHandlers.get(5)); + DistributionServiceStartEventHandler distributionServiceHandler = (DistributionServiceStartEventHandler) eventHandlers.get(5); + assertSame(distributionServiceHandler.getCarrierService().getLocationLinkId(), shipment.getTo()); + assertEquals(distributionServiceHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(distributionServiceHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(0, distributionServiceHandler.getCarrierService().getServiceStartTimeWindow().getStart(), 0.0); + assertEquals(Integer.MAX_VALUE, distributionServiceHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), 0.0); + assertSame(distributionServiceHandler.getLogisticChainElement(), planElements.get(8).getLogisticChainElement()); + assertSame(distributionServiceHandler.getLogisticChainElement(), planElements.get(9).getLogisticChainElement()); + assertSame(distributionServiceHandler.getLogisticChainElement(), planElements.get(10).getLogisticChainElement()); + assertSame(distributionServiceHandler.getLogisticChainElement(), solutionElements.get(4)); + assertSame(distributionServiceHandler.getLspShipment(), shipment); + assertSame(distributionServiceHandler.getResource().getId(), planElements.get(8).getResourceId()); + assertSame(distributionServiceHandler.getResource().getId(), planElements.get(9).getResourceId()); + assertSame(distributionServiceHandler.getResource().getId(), planElements.get(10).getResourceId()); + assertSame(distributionServiceHandler.getResource().getId(), resources.get(4).getId()); + + } + + for (LogisticChain solution : lsp.getSelectedPlan().getLogisticChains()) { + for (LogisticChainElement element : solution.getLogisticChainElements()) { + assertTrue(element.getIncomingShipments().getLspShipmentsWTime().isEmpty()); + if (element.getNextElement() != null) { + assertTrue(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } else { + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } + } + } + + } + +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MultipleShipmentsFirstReloadLSPSchedulingTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MultipleShipmentsFirstReloadLSPSchedulingTest.java new file mode 100644 index 00000000000..e1661887039 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MultipleShipmentsFirstReloadLSPSchedulingTest.java @@ -0,0 +1,321 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Map.Entry; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.events.handler.EventHandler; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MultipleShipmentsFirstReloadLSPSchedulingTest { + private LSP lsp; + private LSPResource firstTranshipmentHubResource; + private LogisticChainElement firstHubElement; + private LogisticChainElement collectionElement; + private LSPResource collectionResource; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50/3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + firstHubElement = firstHubElementBuilder.build(); + + collectionElement.connectWithNextElement(firstHubElement); + + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + + for (int i = 1; i < 100; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + //Random random = new Random(1); + int capacityDemand = MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + } + + @Test + public void testFirstReloadLSPScheduling() { + + for (LspShipment shipment : lsp.getLspShipments()) { + ArrayList scheduleElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + scheduleElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + System.out.println(); + for (int i = 0; i < LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size(); i++) { + System.out.println("Scheduled: " + scheduleElements.get(i).getLogisticChainElement().getId() + " " + scheduleElements.get(i).getResourceId() + " " + scheduleElements.get(i).getElementType() + " Start: " + scheduleElements.get(i).getStartTime() + " End: " + scheduleElements.get(i).getEndTime()); + } + System.out.println(); + } + + + for (LspShipment shipment : lsp.getLspShipments()) { + assertEquals(4, LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + planElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + assertEquals("HANDLE", planElements.get(3).getElementType()); + assertTrue(planElements.get(3).getEndTime() >= (0)); + assertTrue(planElements.get(3).getEndTime() <= (24*3600)); + assertTrue(planElements.get(3).getStartTime() <= planElements.get(3).getEndTime()); + assertTrue(planElements.get(3).getStartTime() >= (0)); + assertTrue(planElements.get(3).getStartTime() <= (24*3600)); + assertSame(planElements.get(3).getResourceId(), firstTranshipmentHubResource.getId()); + assertSame(planElements.get(3).getLogisticChainElement(), firstHubElement); + + assertEquals(planElements.get(3).getStartTime(), planElements.get(2).getEndTime() + 300, 0.0); + + assertEquals("UNLOAD", planElements.get(2).getElementType()); + assertTrue(planElements.get(2).getEndTime() >= (0)); + assertTrue(planElements.get(2).getEndTime() <= (24*3600)); + assertTrue(planElements.get(2).getStartTime() <= planElements.get(2).getEndTime()); + assertTrue(planElements.get(2).getStartTime() >= (0)); + assertTrue(planElements.get(2).getStartTime() <= (24*3600)); + assertSame(planElements.get(2).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(2).getLogisticChainElement(), collectionElement); + + assertEquals(planElements.get(2).getStartTime(), planElements.get(1).getEndTime(), 0.0); + + assertEquals("TRANSPORT", planElements.get(1).getElementType()); + assertTrue(planElements.get(1).getEndTime() >= (0)); + assertTrue(planElements.get(1).getEndTime() <= (24*3600)); + assertTrue(planElements.get(1).getStartTime() <= planElements.get(1).getEndTime()); + assertTrue(planElements.get(1).getStartTime() >= (0)); + assertTrue(planElements.get(1).getStartTime() <= (24*3600)); + assertSame(planElements.get(1).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(1).getLogisticChainElement(), collectionElement); + + assertEquals(planElements.get(1).getStartTime(), planElements.get(0).getEndTime(), 0.0); + + assertEquals("LOAD", planElements.get(0).getElementType()); + assertTrue(planElements.get(0).getEndTime() >= (0)); + assertTrue(planElements.getFirst().getEndTime() <= (24*3600)); + assertTrue(planElements.getFirst().getStartTime() <= planElements.getFirst().getEndTime()); + assertTrue(planElements.getFirst().getStartTime() >= (0)); + assertTrue(planElements.getFirst().getStartTime() <= (24*3600)); + assertSame(planElements.getFirst().getResourceId(), collectionResource.getId()); + assertSame(planElements.getFirst().getLogisticChainElement(), collectionElement); + + } + + assertEquals(1, firstTranshipmentHubResource.getSimulationTrackers().size()); + ArrayList eventHandlers = new ArrayList<>(firstTranshipmentHubResource.getSimulationTrackers()); + assertInstanceOf(TransshipmentHubTourEndEventHandler.class, eventHandlers.getFirst()); + TransshipmentHubTourEndEventHandler reloadEventHandler = (TransshipmentHubTourEndEventHandler) eventHandlers.getFirst(); + + for (Entry entry : reloadEventHandler.getServicesWaitedFor().entrySet()) { + CarrierService service = entry.getKey(); + LspShipment shipment = entry.getValue().lspShipment; + LogisticChainElement element = entry.getValue().logisticChainElement; + assertSame(service.getLocationLinkId(), shipment.getFrom()); + assertEquals(service.getCapacityDemand(), shipment.getSize()); + assertEquals(service.getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + boolean handledByTranshipmentHub = false; + for (LogisticChainElement clientElement : reloadEventHandler.getTranshipmentHub().getClientElements()) { + if (clientElement == element) { + handledByTranshipmentHub = true; + break; + } + } + assertTrue(handledByTranshipmentHub); + + assertTrue(element.getOutgoingShipments().getLspShipmentsWTime().contains(shipment)); + assertFalse(element.getIncomingShipments().getLspShipmentsWTime().contains(shipment)); + } + + + for (LspShipment shipment : lsp.getLspShipments()) { + assertEquals(2, shipment.getSimulationTrackers().size()); + eventHandlers = new ArrayList<>(shipment.getSimulationTrackers()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + + assertInstanceOf(LSPTourEndEventHandler.class, eventHandlers.getFirst()); + LSPTourEndEventHandler endHandler = (LSPTourEndEventHandler) eventHandlers.getFirst(); + assertSame(endHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(endHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(endHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(endHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(endHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(endHandler.getLogisticChainElement(), planElements.get(2).getLogisticChainElement()); + assertSame(endHandler.getLogisticChainElement(), lsp.getSelectedPlan().getLogisticChains().iterator().next().getLogisticChainElements().iterator().next()); + assertSame(endHandler.getLspShipment(), shipment); + assertSame(endHandler.getResourceId(), planElements.get(2).getResourceId()); + assertSame(endHandler.getResourceId(), lsp.getResources().iterator().next().getId()); + + assertInstanceOf(CollectionServiceEndEventHandler.class, eventHandlers.get(1)); + CollectionServiceEndEventHandler serviceHandler = (CollectionServiceEndEventHandler) eventHandlers.get(1); + assertSame(serviceHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(serviceHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(serviceHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(serviceHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(serviceHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(serviceHandler.getElement(), planElements.getFirst().getLogisticChainElement()); + assertSame(serviceHandler.getElement(), lsp.getSelectedPlan().getLogisticChains().iterator().next().getLogisticChainElements().iterator().next()); + assertSame(serviceHandler.getLspShipment(), shipment); + assertSame(serviceHandler.getResourceId(), planElements.getFirst().getResourceId()); + assertSame(serviceHandler.getResourceId(), lsp.getResources().iterator().next().getId()); + } + + for (LogisticChain solution : lsp.getSelectedPlan().getLogisticChains()) { + for (LogisticChainElement element : solution.getLogisticChainElements()) { + assertTrue(element.getIncomingShipments().getLspShipmentsWTime().isEmpty()); + if (element.getNextElement() != null) { + assertTrue(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } else { + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } + } + } + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MultipleShipmentsMainRunLSPSchedulingTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MultipleShipmentsMainRunLSPSchedulingTest.java new file mode 100644 index 00000000000..c9811f9e03d --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MultipleShipmentsMainRunLSPSchedulingTest.java @@ -0,0 +1,434 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Map.Entry; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.events.handler.EventHandler; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MultipleShipmentsMainRunLSPSchedulingTest { + private LSP lsp; + private LSPResource collectionResource; + private LogisticChainElement collectionElement; + private LSPResource firstTranshipmentHubResource; + private LogisticChainElement firstHubElement; + private LSPResource mainRunResource; + private LogisticChainElement mainRunElement; + private Id toLinkId; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50/3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + firstHubElement = firstHubElementBuilder.build(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50/3.6); + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + toLinkId = Id.createLinkId("(14 2) (14 3)"); + + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(fromLinkId) + .setToLinkId(toLinkId) + .build(); + + mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + completeSolutionBuilder.addLogisticChainElement(mainRunElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + + for (int i = 1; i < 100; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + //Random random = new Random(1); + int capacityDemand = MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + } + + @Test + public void testMainRunLSPScheduling() { + + /*for(LSPShipment shipment : lsp.getShipments()) { + ArrayList scheduleElements = new ArrayList(shipment.getSchedule().getPlanElements().values()); + Collections.sort(scheduleElements, new AbstractShipmentPlanElementComparator()); + + System.out.println(); + for(int i = 0; i < shipment.getSchedule().getPlanElements().size(); i++) { + System.out.println("Scheduled: " + scheduleElements.get(i).getSolutionElement().getId() + " " + scheduleElements.get(i).getResourceId() +" "+ scheduleElements.get(i).getElementType() + " Start: " + scheduleElements.get(i).getStartTime() + " End: " + scheduleElements.get(i).getEndTime()); + } + System.out.println(); + }*/ + + + for (LspShipment shipment : lsp.getLspShipments()) { + assertEquals(7, LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + planElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + assertEquals("UNLOAD", planElements.get(6).getElementType()); + assertTrue(planElements.get(6).getEndTime() >= (0)); + assertTrue(planElements.get(6).getEndTime() <= (24*3600)); + assertTrue(planElements.get(6).getStartTime() <= planElements.get(6).getEndTime()); + assertTrue(planElements.get(6).getStartTime() >= (0)); + assertTrue(planElements.get(6).getStartTime() <= (24*3600)); + assertSame(planElements.get(6).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(6).getLogisticChainElement(), mainRunElement); + + assertEquals(planElements.get(6).getStartTime(), planElements.get(5).getEndTime(), 0.0); + + assertEquals("TRANSPORT", planElements.get(5).getElementType()); + assertTrue(planElements.get(5).getEndTime() >= (0)); + assertTrue(planElements.get(5).getEndTime() <= (24*3600)); + assertTrue(planElements.get(5).getStartTime() <= planElements.get(5).getEndTime()); + assertTrue(planElements.get(5).getStartTime() >= (0)); + assertTrue(planElements.get(5).getStartTime() <= (24*3600)); + assertSame(planElements.get(5).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(5).getLogisticChainElement(), mainRunElement); + + assertEquals(planElements.get(5).getStartTime(), planElements.get(4).getEndTime(), 0.0); + + assertEquals("LOAD", planElements.get(4).getElementType()); + assertTrue(planElements.get(4).getEndTime() >= (0)); + assertTrue(planElements.get(4).getEndTime() <= (24*3600)); + assertTrue(planElements.get(4).getStartTime() <= planElements.get(4).getEndTime()); + assertTrue(planElements.get(4).getStartTime() >= (0)); + assertTrue(planElements.get(4).getStartTime() <= (24*3600)); + assertSame(planElements.get(4).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(4).getLogisticChainElement(), mainRunElement); + + assertTrue(planElements.get(4).getStartTime() >= planElements.get(3).getEndTime() / (1.0001) + 300); + + assertEquals("HANDLE", planElements.get(3).getElementType()); + assertTrue(planElements.get(3).getEndTime() >= (0)); + assertTrue(planElements.get(3).getEndTime() <= (24*3600)); + assertTrue(planElements.get(3).getStartTime() <= planElements.get(3).getEndTime()); + assertTrue(planElements.get(3).getStartTime() >= (0)); + assertTrue(planElements.get(3).getStartTime() <= (24*3600)); + assertSame(planElements.get(3).getResourceId(), firstTranshipmentHubResource.getId()); + assertSame(planElements.get(3).getLogisticChainElement(), firstHubElement); + + assertEquals(planElements.get(3).getStartTime(), (planElements.get(2).getEndTime() + 300), 0.0); + + assertEquals("UNLOAD", planElements.get(2).getElementType()); + assertTrue(planElements.get(2).getEndTime() >= (0)); + assertTrue(planElements.get(2).getEndTime() <= (24*3600)); + assertTrue(planElements.get(2).getStartTime() <= planElements.get(2).getEndTime()); + assertTrue(planElements.get(2).getStartTime() >= (0)); + assertTrue(planElements.get(2).getStartTime() <= (24*3600)); + assertSame(planElements.get(2).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(2).getLogisticChainElement(), collectionElement); + + assertEquals(planElements.get(2).getStartTime(), planElements.get(1).getEndTime(), 0.0); + + assertEquals("TRANSPORT", planElements.get(1).getElementType()); + assertTrue(planElements.get(1).getEndTime() >= (0)); + assertTrue(planElements.get(1).getEndTime() <= (24*3600)); + assertTrue(planElements.get(1).getStartTime() <= planElements.get(1).getEndTime()); + assertTrue(planElements.get(1).getStartTime() >= (0)); + assertTrue(planElements.get(1).getStartTime() <= (24*3600)); + assertSame(planElements.get(1).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(1).getLogisticChainElement(), collectionElement); + + assertEquals(planElements.get(1).getStartTime(), planElements.get(0).getEndTime(), 0.0); + + assertEquals("LOAD", planElements.get(0).getElementType()); + assertTrue(planElements.get(0).getEndTime() >= (0)); + assertTrue(planElements.getFirst().getEndTime() <= (24*3600)); + assertTrue(planElements.getFirst().getStartTime() <= planElements.getFirst().getEndTime()); + assertTrue(planElements.getFirst().getStartTime() >= (0)); + assertTrue(planElements.getFirst().getStartTime() <= (24*3600)); + assertSame(planElements.getFirst().getResourceId(), collectionResource.getId()); + assertSame(planElements.getFirst().getLogisticChainElement(), collectionElement); + } + + assertEquals(1, firstTranshipmentHubResource.getSimulationTrackers().size()); + ArrayList eventHandlers = new ArrayList<>(firstTranshipmentHubResource.getSimulationTrackers()); + assertInstanceOf(TransshipmentHubTourEndEventHandler.class, eventHandlers.getFirst()); + TransshipmentHubTourEndEventHandler reloadEventHandler = (TransshipmentHubTourEndEventHandler) eventHandlers.getFirst(); + + for (Entry entry : reloadEventHandler.getServicesWaitedFor().entrySet()) { + CarrierService service = entry.getKey(); + LspShipment shipment = entry.getValue().lspShipment; + LogisticChainElement element = entry.getValue().logisticChainElement; + assertSame(service.getLocationLinkId(), shipment.getFrom()); + assertEquals(service.getCapacityDemand(), shipment.getSize()); + assertEquals(service.getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + boolean handledByTranshipmentHub = false; + for (LogisticChainElement clientElement : reloadEventHandler.getTranshipmentHub().getClientElements()) { + if (clientElement == element) { + handledByTranshipmentHub = true; + break; + } + } + assertTrue(handledByTranshipmentHub); + + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().contains(shipment)); + assertFalse(element.getIncomingShipments().getLspShipmentsWTime().contains(shipment)); + } + + for (LspShipment shipment : lsp.getLspShipments()) { + assertEquals(4, shipment.getSimulationTrackers().size()); + eventHandlers = new ArrayList<>(shipment.getSimulationTrackers()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + planElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList solutionElements = new ArrayList<>(lsp.getSelectedPlan().getLogisticChains().iterator().next().getLogisticChainElements()); + ArrayList resources = new ArrayList<>(lsp.getResources()); + + assertInstanceOf(LSPTourEndEventHandler.class, eventHandlers.getFirst()); + LSPTourEndEventHandler endHandler = (LSPTourEndEventHandler) eventHandlers.getFirst(); + assertSame(endHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(endHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(endHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(endHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(endHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(endHandler.getLogisticChainElement(), planElements.get(0).getLogisticChainElement()); + assertSame(endHandler.getLogisticChainElement(), planElements.get(1).getLogisticChainElement()); + assertSame(endHandler.getLogisticChainElement(), planElements.get(2).getLogisticChainElement()); + assertSame(endHandler.getLogisticChainElement(), solutionElements.getFirst()); + assertSame(endHandler.getLspShipment(), shipment); + assertSame(endHandler.getResourceId(), planElements.get(0).getResourceId()); + assertSame(endHandler.getResourceId(), planElements.get(1).getResourceId()); + assertSame(endHandler.getResourceId(), planElements.get(2).getResourceId()); + assertSame(endHandler.getResourceId(), resources.getFirst().getId()); + + //CollectionServiceEnd + assertInstanceOf(CollectionServiceEndEventHandler.class, eventHandlers.get(1)); + CollectionServiceEndEventHandler serviceHandler = (CollectionServiceEndEventHandler) eventHandlers.get(1); + assertSame(serviceHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(serviceHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(serviceHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(serviceHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(serviceHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(serviceHandler.getElement(), planElements.get(0).getLogisticChainElement()); + assertSame(serviceHandler.getElement(), planElements.get(1).getLogisticChainElement()); + assertSame(serviceHandler.getElement(), planElements.get(2).getLogisticChainElement()); + assertSame(serviceHandler.getElement(), solutionElements.getFirst()); + assertSame(serviceHandler.getLspShipment(), shipment); + assertSame(serviceHandler.getResourceId(), planElements.get(0).getResourceId()); + assertSame(serviceHandler.getResourceId(), planElements.get(1).getResourceId()); + assertSame(serviceHandler.getResourceId(), planElements.get(2).getResourceId()); + assertSame(serviceHandler.getResourceId(), resources.getFirst().getId()); + + //MainRunTourStart + assertInstanceOf(LSPTourStartEventHandler.class, eventHandlers.get(2)); + LSPTourStartEventHandler mainRunStartHandler = (LSPTourStartEventHandler) eventHandlers.get(2); + assertSame(mainRunStartHandler.getCarrierService().getLocationLinkId(), toLinkId); + assertEquals(mainRunStartHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(mainRunStartHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(0, mainRunStartHandler.getCarrierService().getServiceStartTimeWindow().getStart(), 0.0); + assertEquals(Integer.MAX_VALUE, mainRunStartHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), 0.0); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(4).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(5).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(6).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), solutionElements.get(2)); + assertSame(mainRunStartHandler.getLspShipment(), shipment); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(4).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(5).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(6).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), resources.get(2).getId()); + + //MainRunEnd + assertInstanceOf(LSPTourEndEventHandler.class, eventHandlers.get(3)); + LSPTourEndEventHandler mainRunEndHandler = (LSPTourEndEventHandler) eventHandlers.get(3); + assertSame(mainRunEndHandler.getCarrierService().getLocationLinkId(), toLinkId); + assertEquals(mainRunEndHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(mainRunEndHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(0, mainRunEndHandler.getCarrierService().getServiceStartTimeWindow().getStart(), 0.0); + assertEquals(Integer.MAX_VALUE, mainRunEndHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), 0.0); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(4).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(5).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(6).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), solutionElements.get(2)); + assertSame(mainRunEndHandler.getLspShipment(), shipment); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(4).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(5).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(6).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), resources.get(2).getId()); + } + + for (LogisticChain solution : lsp.getSelectedPlan().getLogisticChains()) { + for (LogisticChainElement element : solution.getLogisticChainElements()) { + assertTrue(element.getIncomingShipments().getLspShipmentsWTime().isEmpty()); + if (element.getNextElement() != null) { + assertTrue(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } else { + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } + } + } + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MultipleShipmentsSecondReloadLSPSchedulingTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MultipleShipmentsSecondReloadLSPSchedulingTest.java new file mode 100644 index 00000000000..23ee9f61e86 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/MultipleShipmentsSecondReloadLSPSchedulingTest.java @@ -0,0 +1,518 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map.Entry; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.events.handler.EventHandler; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MultipleShipmentsSecondReloadLSPSchedulingTest { + private LSP lsp; + private LSPResource collectionResource; + private LogisticChainElement collectionElement; + private LSPResource firstTranshipmentHubResource; + private LogisticChainElement firstHubElement; + private LSPResource mainRunResource; + private LogisticChainElement mainRunElement; + private LSPResource secondTranshipmentHubResource; + private LogisticChainElement secondHubElement; + private Id toLinkId; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50/3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + firstHubElement = firstHubElementBuilder.build(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50/3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + toLinkId = Id.createLinkId("(14 2) (14 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(fromLinkId) + .setToLinkId(Id.createLinkId(toLinkId)) + .build(); + + mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + TranshipmentHubSchedulerBuilder secondSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + secondSchedulerBuilder.setCapacityNeedFixed(10); + secondSchedulerBuilder.setCapacityNeedLinear(1); + + + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + + TransshipmentHubBuilder secondTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(secondTransshipmentHubId, secondTransshipmentHub_LinkId, scenario); + secondTransshipmentHubBuilder.setTransshipmentHubScheduler(secondSchedulerBuilder.build()); + secondTranshipmentHubResource = secondTransshipmentHubBuilder.build(); + + Id secondHubElementId = Id.create("SecondHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTranshipmentHubResource); + secondHubElement = secondHubElementBuilder.build(); + + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + completeSolutionBuilder.addLogisticChainElement(mainRunElement); + completeSolutionBuilder.addLogisticChainElement(secondHubElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + resourcesList.add(secondTranshipmentHubResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + + for (int i = 1; i < 100; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = MatsimRandom.getRandom().nextInt(4); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + } + + @Test + public void testSecondReloadLSPScheduling() { + + /*for(LSPShipment shipment : lsp.getShipments()) { + ArrayList elementList = new ArrayList(shipment.getSchedule().getPlanElements().values()); + Collections.sort(elementList, new AbstractShipmentPlanElementComparator()); + System.out.println(); + for(AbstractShipmentPlanElement element : elementList) { + System.out.println(element.getSolutionElement().getId() + " " + element.getResourceId() + " " + element.getElementType() + " " + element.getStartTime() + " " + element.getEndTime()); + } + System.out.println(); + }*/ + + for (LspShipment shipment : lsp.getLspShipments()) { + assertEquals(8, LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + planElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + assertEquals("HANDLE", planElements.get(7).getElementType()); + assertTrue(planElements.get(7).getEndTime() >= (0)); + assertTrue(planElements.get(7).getEndTime() <= (24*3600)); + assertTrue(planElements.get(7).getStartTime() <= planElements.get(7).getEndTime()); + assertTrue(planElements.get(7).getStartTime() >= (0)); + assertTrue(planElements.get(7).getStartTime() <= (24*3600)); + assertSame(planElements.get(7).getResourceId(), secondTranshipmentHubResource.getId()); + assertSame(planElements.get(7).getLogisticChainElement(), secondHubElement); + + assertEquals(planElements.get(7).getStartTime(), (planElements.get(6).getEndTime() + 300), 0.0); + + assertEquals("UNLOAD", planElements.get(6).getElementType()); + assertTrue(planElements.get(6).getEndTime() >= (0)); + assertTrue(planElements.get(6).getEndTime() <= (24*3600)); + assertTrue(planElements.get(6).getStartTime() <= planElements.get(6).getEndTime()); + assertTrue(planElements.get(6).getStartTime() >= (0)); + assertTrue(planElements.get(6).getStartTime() <= (24*3600)); + assertSame(planElements.get(6).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(6).getLogisticChainElement(), mainRunElement); + + assertEquals(planElements.get(6).getStartTime(), planElements.get(5).getEndTime(), 0.0); + + assertEquals("TRANSPORT", planElements.get(5).getElementType()); + assertTrue(planElements.get(5).getEndTime() >= (0)); + assertTrue(planElements.get(5).getEndTime() <= (24*3600)); + assertTrue(planElements.get(5).getStartTime() <= planElements.get(5).getEndTime()); + assertTrue(planElements.get(5).getStartTime() >= (0)); + assertTrue(planElements.get(5).getStartTime() <= (24*3600)); + assertSame(planElements.get(5).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(5).getLogisticChainElement(), mainRunElement); + + assertEquals(planElements.get(5).getStartTime(), planElements.get(4).getEndTime(), 0.0); + + assertEquals("LOAD", planElements.get(4).getElementType()); + assertTrue(planElements.get(4).getEndTime() >= (0)); + assertTrue(planElements.get(4).getEndTime() <= (24*3600)); + assertTrue(planElements.get(4).getStartTime() <= planElements.get(4).getEndTime()); + assertTrue(planElements.get(4).getStartTime() >= (0)); + assertTrue(planElements.get(4).getStartTime() <= (24*3600)); + assertSame(planElements.get(4).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(4).getLogisticChainElement(), mainRunElement); + + assertTrue(planElements.get(4).getStartTime() >= (planElements.get(3).getEndTime() / (1.0001)) + 300); + + assertEquals("HANDLE", planElements.get(3).getElementType()); + assertTrue(planElements.get(3).getEndTime() >= (0)); + assertTrue(planElements.get(3).getEndTime() <= (24*3600)); + assertTrue(planElements.get(3).getStartTime() <= planElements.get(3).getEndTime()); + assertTrue(planElements.get(3).getStartTime() >= (0)); + assertTrue(planElements.get(3).getStartTime() <= (24*3600)); + assertSame(planElements.get(3).getResourceId(), firstTranshipmentHubResource.getId()); + assertSame(planElements.get(3).getLogisticChainElement(), firstHubElement); + + assertEquals(planElements.get(3).getStartTime(), (planElements.get(2).getEndTime() + 300), 0.0); + + assertEquals("UNLOAD", planElements.get(2).getElementType()); + assertTrue(planElements.get(2).getEndTime() >= (0)); + assertTrue(planElements.get(2).getEndTime() <= (24*3600)); + assertTrue(planElements.get(2).getStartTime() <= planElements.get(2).getEndTime()); + assertTrue(planElements.get(2).getStartTime() >= (0)); + assertTrue(planElements.get(2).getStartTime() <= (24*3600)); + assertSame(planElements.get(2).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(2).getLogisticChainElement(), collectionElement); + + assertEquals(planElements.get(2).getStartTime(), planElements.get(1).getEndTime(), 0.0); + + assertEquals("TRANSPORT", planElements.get(1).getElementType()); + assertTrue(planElements.get(1).getEndTime() >= (0)); + assertTrue(planElements.get(1).getEndTime() <= (24*3600)); + assertTrue(planElements.get(1).getStartTime() <= planElements.get(1).getEndTime()); + assertTrue(planElements.get(1).getStartTime() >= (0)); + assertTrue(planElements.get(1).getStartTime() <= (24*3600)); + assertSame(planElements.get(1).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(1).getLogisticChainElement(), collectionElement); + + assertEquals(planElements.get(1).getStartTime(), planElements.get(0).getEndTime(), 0.0); + + assertEquals("LOAD", planElements.get(0).getElementType()); + assertTrue(planElements.get(0).getEndTime() >= (0)); + assertTrue(planElements.getFirst().getEndTime() <= (24*3600)); + assertTrue(planElements.getFirst().getStartTime() <= planElements.getFirst().getEndTime()); + assertTrue(planElements.getFirst().getStartTime() >= (0)); + assertTrue(planElements.getFirst().getStartTime() <= (24*3600)); + assertSame(planElements.getFirst().getResourceId(), collectionResource.getId()); + assertSame(planElements.getFirst().getLogisticChainElement(), collectionElement); + } + + { + assertEquals(1, firstTranshipmentHubResource.getSimulationTrackers().size()); + ArrayList eventHandlers = new ArrayList<>(firstTranshipmentHubResource.getSimulationTrackers()); + assertInstanceOf(TransshipmentHubTourEndEventHandler.class, eventHandlers.getFirst()); + TransshipmentHubTourEndEventHandler reloadEventHandler = (TransshipmentHubTourEndEventHandler) eventHandlers.getFirst(); + Iterator> + iter = reloadEventHandler.getServicesWaitedFor().entrySet().iterator(); + + while (iter.hasNext()) { + Entry + entry = iter.next(); + CarrierService service = entry.getKey(); + LspShipment shipment = entry.getValue().lspShipment; + LogisticChainElement element = entry.getValue().logisticChainElement; + assertSame(service.getLocationLinkId(), shipment.getFrom()); + assertEquals(service.getCapacityDemand(), shipment.getSize()); + assertEquals(service.getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + boolean handledByTranshipmentHub = false; + for (LogisticChainElement clientElement : + reloadEventHandler.getTranshipmentHub().getClientElements()) { + if (clientElement == element) { + handledByTranshipmentHub = true; + break; + } + } + assertTrue(handledByTranshipmentHub); + + //There IS a next element following the 1st hub, so the outgoing shipments does NOT contain the shipment anymore (got handled). + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().contains(shipment)); + assertFalse(element.getIncomingShipments().getLspShipmentsWTime().contains(shipment)); + } + } + + { + assertEquals(1, secondTranshipmentHubResource.getSimulationTrackers().size()); + ArrayList eventHandlers = new ArrayList<>(secondTranshipmentHubResource.getSimulationTrackers()); + assertInstanceOf(TransshipmentHubTourEndEventHandler.class, eventHandlers.getFirst()); + TransshipmentHubTourEndEventHandler reloadEventHandler = (TransshipmentHubTourEndEventHandler) eventHandlers.getFirst(); + Iterator> + iter = reloadEventHandler.getServicesWaitedFor().entrySet().iterator(); + + while (iter.hasNext()) { + Entry entry = iter.next(); + CarrierService service = entry.getKey(); + LspShipment shipment = entry.getValue().lspShipment; + LogisticChainElement element = entry.getValue().logisticChainElement; + assertSame(service.getLocationLinkId(), toLinkId); + assertEquals(service.getCapacityDemand(), shipment.getSize()); + assertEquals(service.getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + boolean handledByTranshipmentHub = false; + for (LogisticChainElement clientElement : reloadEventHandler.getTranshipmentHub().getClientElements()) { + if (clientElement == element) { + handledByTranshipmentHub = true; + break; + } + } + assertTrue(handledByTranshipmentHub); + + //There is NO next element following the 2nd hub, so the outgoing shipments remain in the list of the 2nd hub. + assertTrue(element.getOutgoingShipments().getLspShipmentsWTime().contains(shipment)); + assertFalse(element.getIncomingShipments().getLspShipmentsWTime().contains(shipment)); + } + } + + for (LspShipment shipment : lsp.getLspShipments()) { + assertEquals(4, shipment.getSimulationTrackers().size()); + ArrayList> eventHandlers = new ArrayList<>(shipment.getSimulationTrackers()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + planElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList solutionElements = new ArrayList<>(lsp.getSelectedPlan().getLogisticChains().iterator().next().getLogisticChainElements()); + ArrayList resources = new ArrayList<>(lsp.getResources()); + + //CollectionTourEnd + { + assertInstanceOf(LSPTourEndEventHandler.class, eventHandlers.getFirst()); + LSPTourEndEventHandler collectionEndHandler = (LSPTourEndEventHandler) eventHandlers.getFirst(); + assertSame(collectionEndHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(collectionEndHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(collectionEndHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(collectionEndHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(collectionEndHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(collectionEndHandler.getLogisticChainElement(), planElements.get(0).getLogisticChainElement()); + assertSame(collectionEndHandler.getLogisticChainElement(), planElements.get(1).getLogisticChainElement()); + assertSame(collectionEndHandler.getLogisticChainElement(), planElements.get(2).getLogisticChainElement()); + assertSame(collectionEndHandler.getLogisticChainElement(), solutionElements.getFirst()); + assertSame(collectionEndHandler.getLspShipment(), shipment); + assertSame(collectionEndHandler.getResourceId(), planElements.get(0).getResourceId()); + assertSame(collectionEndHandler.getResourceId(), planElements.get(1).getResourceId()); + assertSame(collectionEndHandler.getResourceId(), planElements.get(2).getResourceId()); + assertSame(collectionEndHandler.getResourceId(), resources.getFirst().getId()); + } + + {//CollectionServiceEnd + assertInstanceOf(CollectionServiceEndEventHandler.class, eventHandlers.get(1)); + CollectionServiceEndEventHandler collectionServiceHandler = (CollectionServiceEndEventHandler) eventHandlers.get(1); + assertSame(collectionServiceHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(collectionServiceHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(collectionServiceHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(collectionServiceHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(collectionServiceHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(collectionServiceHandler.getElement(), planElements.get(0).getLogisticChainElement()); + assertSame(collectionServiceHandler.getElement(), planElements.get(1).getLogisticChainElement()); + assertSame(collectionServiceHandler.getElement(), planElements.get(2).getLogisticChainElement()); + assertSame(collectionServiceHandler.getElement(), solutionElements.getFirst()); + assertSame(collectionServiceHandler.getLspShipment(), shipment); + assertSame(collectionServiceHandler.getResourceId(), planElements.get(0).getResourceId()); + assertSame(collectionServiceHandler.getResourceId(), planElements.get(1).getResourceId()); + assertSame(collectionServiceHandler.getResourceId(), planElements.get(2).getResourceId()); + assertSame(collectionServiceHandler.getResourceId(), resources.getFirst().getId()); + } + + {//MainRunStart + assertInstanceOf(LSPTourStartEventHandler.class, eventHandlers.get(2)); + LSPTourStartEventHandler mainRunStartHandler = (LSPTourStartEventHandler) eventHandlers.get(2); + assertSame(mainRunStartHandler.getCarrierService().getLocationLinkId(), toLinkId); + assertEquals(mainRunStartHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(mainRunStartHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(0, mainRunStartHandler.getCarrierService().getServiceStartTimeWindow().getStart(), 0.0); + assertEquals(Integer.MAX_VALUE, mainRunStartHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), 0.0); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(4).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(5).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(6).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), solutionElements.get(2)); + assertSame(mainRunStartHandler.getLspShipment(), shipment); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(4).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(5).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(6).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), resources.get(2).getId()); + } + + {//MainRunEnd + assertInstanceOf(LSPTourEndEventHandler.class, eventHandlers.get(3)); + LSPTourEndEventHandler mainRunEndHandler = (LSPTourEndEventHandler) eventHandlers.get(3); + assertSame(mainRunEndHandler.getCarrierService().getLocationLinkId(), toLinkId); + assertEquals(mainRunEndHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(mainRunEndHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(0, mainRunEndHandler.getCarrierService().getServiceStartTimeWindow().getStart(), 0.0); + assertEquals(Integer.MAX_VALUE, mainRunEndHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), 0.0); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(4).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(5).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(6).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), solutionElements.get(2)); + assertSame(mainRunEndHandler.getLspShipment(), shipment); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(4).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(5).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(6).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), resources.get(2).getId()); + } + } + + for (LogisticChain solution : lsp.getSelectedPlan().getLogisticChains()) { + for (LogisticChainElement element : solution.getLogisticChainElements()) { + assertTrue(element.getIncomingShipments().getLspShipmentsWTime().isEmpty()); + if (element.getNextElement() != null) { + assertTrue(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } else { + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } + } + } + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/SecondReloadLSPSchedulingTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/SecondReloadLSPSchedulingTest.java new file mode 100644 index 00000000000..6a37cd65697 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/SecondReloadLSPSchedulingTest.java @@ -0,0 +1,525 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map.Entry; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.Config; +import org.matsim.core.events.handler.EventHandler; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.freight.carriers.*; +import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; +import org.matsim.freight.logistics.*; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; +import org.matsim.freight.logistics.shipment.LspShipment; +import org.matsim.freight.logistics.shipment.LspShipmentPlanElement; +import org.matsim.freight.logistics.shipment.LspShipmentUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class SecondReloadLSPSchedulingTest { + private LSP lsp; + private LSPResource collectionResource; + private LogisticChainElement collectionElement; + private LSPResource firstTranshipmentHubResource; + private LogisticChainElement firstHubElement; + private LSPResource mainRunResource; + private LogisticChainElement mainRunElement; + private LSPResource secondTranshipmentHubResource; + private LogisticChainElement secondHubElement; + private Id toLinkId; + + @BeforeEach + public void initialize() { + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile("scenarios/2regions/2regions-network.xml"); + Network network = scenario.getNetwork(); + + + Id collectionCarrierId = Id.create("CollectionCarrier", Carrier.class); + Id collectionVehTypeId = Id.create("CollectionCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType collectionVehType = VehicleUtils.createVehicleType(collectionVehTypeId, TransportMode.car); + collectionVehType.getCapacity().setOther(10); + collectionVehType.getCostInformation().setCostsPerMeter(0.0004); + collectionVehType.getCostInformation().setCostsPerSecond(0.38); + collectionVehType.getCostInformation().setFixedCost(49.); + collectionVehType.setMaximumVelocity(50/3.6); + + Id collectionLinkId = Id.createLinkId("(4 2) (4 3)"); + Id collectionVehicleId = Id.createVehicleId("CollectionVehicle"); + CarrierVehicle collectionCarrierVehicle = CarrierVehicle.newInstance(collectionVehicleId, collectionLinkId, collectionVehType); + + CarrierCapabilities.Builder collectionCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + collectionCapabilitiesBuilder.addVehicle(collectionCarrierVehicle); + collectionCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities collectionCapabilities = collectionCapabilitiesBuilder.build(); + Carrier collectionCarrier = CarriersUtils.createCarrier(collectionCarrierId); + collectionCarrier.setCarrierCapabilities(collectionCapabilities); + + + collectionResource = ResourceImplementationUtils.CollectionCarrierResourceBuilder.newInstance(collectionCarrier) + .setCollectionScheduler(ResourceImplementationUtils.createDefaultCollectionCarrierScheduler(scenario)) + .setLocationLinkId(collectionLinkId) + .build(); + + collectionElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("CollectionElement", LogisticChainElement.class)) + .setResource(collectionResource) + .build(); + + TranshipmentHubSchedulerBuilder firstReloadingSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + firstReloadingSchedulerBuilder.setCapacityNeedFixed(10); + firstReloadingSchedulerBuilder.setCapacityNeedLinear(1); + + + Id firstTransshipmentHubId = Id.create("TranshipmentHub1", LSPResource.class); + Id firstTransshipmentHub_LinkId = Id.createLinkId("(4 2) (4 3)"); + + TransshipmentHubBuilder firstTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(firstTransshipmentHubId, firstTransshipmentHub_LinkId, scenario); + firstTransshipmentHubBuilder.setTransshipmentHubScheduler(firstReloadingSchedulerBuilder.build()); + firstTranshipmentHubResource = firstTransshipmentHubBuilder.build(); + + Id firstHubElementId = Id.create("FirstHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder firstHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(firstHubElementId); + firstHubElementBuilder.setResource(firstTranshipmentHubResource); + firstHubElement = firstHubElementBuilder.build(); + + Id mainRunCarrierId = Id.create("MainRunCarrier", Carrier.class); + Id mainRunVehTypeId = Id.create("MainRunCarrierVehicleType", VehicleType.class); + org.matsim.vehicles.VehicleType mainRunVehType = VehicleUtils.createVehicleType(mainRunVehTypeId, TransportMode.car); + mainRunVehType.getCapacity().setOther(30); + mainRunVehType.getCostInformation().setCostsPerMeter(0.0002); + mainRunVehType.getCostInformation().setCostsPerSecond(0.38); + mainRunVehType.getCostInformation().setFixedCost(120.); + mainRunVehType.setMaximumVelocity(50/3.6); + + + Id fromLinkId = Id.createLinkId("(4 2) (4 3)"); + toLinkId = Id.createLinkId("(14 2) (14 3)"); + Id mainRunVehicleId = Id.createVehicleId("MainRunVehicle"); + CarrierVehicle mainRunCarrierVehicle = CarrierVehicle.newInstance(mainRunVehicleId, fromLinkId, mainRunVehType); + + + CarrierCapabilities.Builder mainRunCapabilitiesBuilder = CarrierCapabilities.Builder.newInstance(); + mainRunCapabilitiesBuilder.addVehicle(mainRunCarrierVehicle); + mainRunCapabilitiesBuilder.setFleetSize(FleetSize.INFINITE); + CarrierCapabilities mainRunCapabilities = mainRunCapabilitiesBuilder.build(); + Carrier mainRunCarrier = CarriersUtils.createCarrier(mainRunCarrierId); + mainRunCarrier.setCarrierCapabilities(mainRunCapabilities); + + + mainRunResource = ResourceImplementationUtils.MainRunCarrierResourceBuilder.newInstance(mainRunCarrier) + .setMainRunCarrierScheduler(ResourceImplementationUtils.createDefaultMainRunCarrierScheduler(scenario)) + .setFromLinkId(fromLinkId) + .setToLinkId(Id.createLinkId(toLinkId)) + .build(); + + mainRunElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("MainRunElement", LogisticChainElement.class)) + .setResource(mainRunResource) + .build(); + + TranshipmentHubSchedulerBuilder secondSchedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + secondSchedulerBuilder.setCapacityNeedFixed(10); + secondSchedulerBuilder.setCapacityNeedLinear(1); + + + Id secondTransshipmentHubId = Id.create("TranshipmentHub2", LSPResource.class); + Id secondTransshipmentHub_LinkId = Id.createLinkId("(14 2) (14 3)"); + + TransshipmentHubBuilder secondTransshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(secondTransshipmentHubId, secondTransshipmentHub_LinkId, scenario); + secondTransshipmentHubBuilder.setTransshipmentHubScheduler(secondSchedulerBuilder.build()); + secondTranshipmentHubResource = secondTransshipmentHubBuilder.build(); + + Id secondHubElementId = Id.create("SecondHubElement", LogisticChainElement.class); + LSPUtils.LogisticChainElementBuilder secondHubElementBuilder = LSPUtils.LogisticChainElementBuilder.newInstance(secondHubElementId); + secondHubElementBuilder.setResource(secondTranshipmentHubResource); + secondHubElement = secondHubElementBuilder.build(); + + + collectionElement.connectWithNextElement(firstHubElement); + firstHubElement.connectWithNextElement(mainRunElement); + mainRunElement.connectWithNextElement(secondHubElement); + + + Id solutionId = Id.create("SolutionId", LogisticChain.class); + LSPUtils.LogisticChainBuilder completeSolutionBuilder = LSPUtils.LogisticChainBuilder.newInstance(solutionId); + completeSolutionBuilder.addLogisticChainElement(collectionElement); + completeSolutionBuilder.addLogisticChainElement(firstHubElement); + completeSolutionBuilder.addLogisticChainElement(mainRunElement); + completeSolutionBuilder.addLogisticChainElement(secondHubElement); + LogisticChain completeSolution = completeSolutionBuilder.build(); + + InitialShipmentAssigner assigner = ResourceImplementationUtils.createSingleLogisticChainShipmentAssigner(); + LSPPlan completePlan = LSPUtils.createLSPPlan(); + completePlan.setInitialShipmentAssigner(assigner); + completePlan.addLogisticChain(completeSolution); + + LSPUtils.LSPBuilder completeLSPBuilder = LSPUtils.LSPBuilder.getInstance(Id.create("CollectionLSP", LSP.class)); + completeLSPBuilder.setInitialPlan(completePlan); + ArrayList resourcesList = new ArrayList<>(); + resourcesList.add(collectionResource); + resourcesList.add(firstTranshipmentHubResource); + resourcesList.add(mainRunResource); + resourcesList.add(secondTranshipmentHubResource); + + LogisticChainScheduler simpleScheduler = ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(resourcesList); + simpleScheduler.setBufferTime(300); + completeLSPBuilder.setLogisticChainScheduler(simpleScheduler); + lsp = completeLSPBuilder.build(); + + ArrayList linkList = new ArrayList<>(network.getLinks().values()); + + for (int i = 1; i < 2; i++) { + Id id = Id.create(i, LspShipment.class); + LspShipmentUtils.LspShipmentBuilder builder = LspShipmentUtils.LspShipmentBuilder.newInstance(id); + int capacityDemand = MatsimRandom.getRandom().nextInt(10); + builder.setCapacityDemand(capacityDemand); + + while (true) { + Collections.shuffle(linkList); + Link pendingToLink = linkList.getFirst(); + if ((pendingToLink.getFromNode().getCoord().getX() <= 18000 && + pendingToLink.getFromNode().getCoord().getY() <= 4000 && + pendingToLink.getFromNode().getCoord().getX() >= 14000 && + pendingToLink.getToNode().getCoord().getX() <= 18000 && + pendingToLink.getToNode().getCoord().getY() <= 4000 && + pendingToLink.getToNode().getCoord().getX() >= 14000)) { + builder.setToLinkId(pendingToLink.getId()); + break; + } + + } + + while (true) { + Collections.shuffle(linkList); + Link pendingFromLink = linkList.getFirst(); + if (pendingFromLink.getFromNode().getCoord().getX() <= 4000 && + pendingFromLink.getFromNode().getCoord().getY() <= 4000 && + pendingFromLink.getToNode().getCoord().getX() <= 4000 && + pendingFromLink.getToNode().getCoord().getY() <= 4000) { + builder.setFromLinkId(pendingFromLink.getId()); + break; + } + + } + + TimeWindow endTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setEndTimeWindow(endTimeWindow); + TimeWindow startTimeWindow = TimeWindow.newInstance(0, (24 * 3600)); + builder.setStartTimeWindow(startTimeWindow); + builder.setDeliveryServiceTime(capacityDemand * 60); + LspShipment shipment = builder.build(); + lsp.assignShipmentToLSP(shipment); + } + lsp.scheduleLogisticChains(); + + } + + @Test + public void testSecondReloadLSPScheduling() { + + for (LspShipment shipment : lsp.getLspShipments()) { + ArrayList elementList = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + elementList.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + System.out.println(); + for (LspShipmentPlanElement element : elementList) { + System.out.println(element.getLogisticChainElement().getId() + " " + element.getResourceId() + " " + element.getElementType() + " " + element.getStartTime() + " " + element.getEndTime()); + } + System.out.println(); + } + + for (LspShipment shipment : lsp.getLspShipments()) { + assertEquals(8, LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().size()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + planElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + + assertEquals("HANDLE", planElements.get(7).getElementType()); + assertTrue(planElements.get(7).getEndTime() >= (0)); + assertTrue(planElements.get(7).getEndTime() <= (24*3600)); + assertTrue(planElements.get(7).getStartTime() <= planElements.get(7).getEndTime()); + assertTrue(planElements.get(7).getStartTime() >= (0)); + assertTrue(planElements.get(7).getStartTime() <= (24*3600)); + assertSame(planElements.get(7).getResourceId(), secondTranshipmentHubResource.getId()); + assertSame(planElements.get(7).getLogisticChainElement(), secondHubElement); + + assertEquals(planElements.get(7).getStartTime(), (planElements.get(6).getEndTime() + 300), 0.0); + + assertEquals("UNLOAD", planElements.get(6).getElementType()); + assertTrue(planElements.get(6).getEndTime() >= (0)); + assertTrue(planElements.get(6).getEndTime() <= (24*3600)); + assertTrue(planElements.get(6).getStartTime() <= planElements.get(6).getEndTime()); + assertTrue(planElements.get(6).getStartTime() >= (0)); + assertTrue(planElements.get(6).getStartTime() <= (24*3600)); + assertSame(planElements.get(6).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(6).getLogisticChainElement(), mainRunElement); + + assertEquals(planElements.get(6).getStartTime(), planElements.get(5).getEndTime(), 0.0); + + assertEquals("TRANSPORT", planElements.get(5).getElementType()); + assertTrue(planElements.get(5).getEndTime() >= (0)); + assertTrue(planElements.get(5).getEndTime() <= (24*3600)); + assertTrue(planElements.get(5).getStartTime() <= planElements.get(5).getEndTime()); + assertTrue(planElements.get(5).getStartTime() >= (0)); + assertTrue(planElements.get(5).getStartTime() <= (24*3600)); + assertSame(planElements.get(5).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(5).getLogisticChainElement(), mainRunElement); + + assertEquals(planElements.get(5).getStartTime(), planElements.get(4).getEndTime(), 0.0); + + assertEquals("LOAD", planElements.get(4).getElementType()); + assertTrue(planElements.get(4).getEndTime() >= (0)); + assertTrue(planElements.get(4).getEndTime() <= (24*3600)); + assertTrue(planElements.get(4).getStartTime() <= planElements.get(4).getEndTime()); + assertTrue(planElements.get(4).getStartTime() >= (0)); + assertTrue(planElements.get(4).getStartTime() <= (24*3600)); + assertSame(planElements.get(4).getResourceId(), mainRunResource.getId()); + assertSame(planElements.get(4).getLogisticChainElement(), mainRunElement); + + assertTrue(planElements.get(4).getStartTime() >= (planElements.get(3).getEndTime() / (1.0001)) + 300); + + assertEquals("HANDLE", planElements.get(3).getElementType()); + assertTrue(planElements.get(3).getEndTime() >= (0)); + assertTrue(planElements.get(3).getEndTime() <= (24*3600)); + assertTrue(planElements.get(3).getStartTime() <= planElements.get(3).getEndTime()); + assertTrue(planElements.get(3).getStartTime() >= (0)); + assertTrue(planElements.get(3).getStartTime() <= (24*3600)); + assertSame(planElements.get(3).getResourceId(), firstTranshipmentHubResource.getId()); + assertSame(planElements.get(3).getLogisticChainElement(), firstHubElement); + + assertEquals(planElements.get(3).getStartTime(), (planElements.get(2).getEndTime() + 300), 0.0); + + assertEquals("UNLOAD", planElements.get(2).getElementType()); + assertTrue(planElements.get(2).getEndTime() >= (0)); + assertTrue(planElements.get(2).getEndTime() <= (24*3600)); + assertTrue(planElements.get(2).getStartTime() <= planElements.get(2).getEndTime()); + assertTrue(planElements.get(2).getStartTime() >= (0)); + assertTrue(planElements.get(2).getStartTime() <= (24*3600)); + assertSame(planElements.get(2).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(2).getLogisticChainElement(), collectionElement); + + assertEquals(planElements.get(2).getStartTime(), planElements.get(1).getEndTime(), 0.0); + + assertEquals("TRANSPORT", planElements.get(1).getElementType()); + assertTrue(planElements.get(1).getEndTime() >= (0)); + assertTrue(planElements.get(1).getEndTime() <= (24*3600)); + assertTrue(planElements.get(1).getStartTime() <= planElements.get(1).getEndTime()); + assertTrue(planElements.get(1).getStartTime() >= (0)); + assertTrue(planElements.get(1).getStartTime() <= (24*3600)); + assertSame(planElements.get(1).getResourceId(), collectionResource.getId()); + assertSame(planElements.get(1).getLogisticChainElement(), collectionElement); + + assertEquals(planElements.get(1).getStartTime(), planElements.get(0).getEndTime(), 0.0); + + assertEquals("LOAD", planElements.get(0).getElementType()); + assertTrue(planElements.get(0).getEndTime() >= (0)); + assertTrue(planElements.getFirst().getEndTime() <= (24*3600)); + assertTrue(planElements.getFirst().getStartTime() <= planElements.getFirst().getEndTime()); + assertTrue(planElements.getFirst().getStartTime() >= (0)); + assertTrue(planElements.getFirst().getStartTime() <= (24*3600)); + assertSame(planElements.getFirst().getResourceId(), collectionResource.getId()); + assertSame(planElements.getFirst().getLogisticChainElement(), collectionElement); + } + + { + assertEquals(1, firstTranshipmentHubResource.getSimulationTrackers().size()); + ArrayList eventHandlers = new ArrayList<>(firstTranshipmentHubResource.getSimulationTrackers()); + assertInstanceOf(TransshipmentHubTourEndEventHandler.class, eventHandlers.getFirst()); + TransshipmentHubTourEndEventHandler reloadEventHandler = (TransshipmentHubTourEndEventHandler) eventHandlers.getFirst(); + Iterator> + iter = reloadEventHandler.getServicesWaitedFor().entrySet().iterator(); + + while (iter.hasNext()) { + Entry + entry = iter.next(); + CarrierService service = entry.getKey(); + LspShipment shipment = entry.getValue().lspShipment; + LogisticChainElement element = entry.getValue().logisticChainElement; + assertSame(service.getLocationLinkId(), shipment.getFrom()); + assertEquals(service.getCapacityDemand(), shipment.getSize()); + assertEquals(service.getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + boolean handledByTranshipmentHub = false; + for (LogisticChainElement clientElement : + reloadEventHandler.getTranshipmentHub().getClientElements()) { + if (clientElement == element) { + handledByTranshipmentHub = true; + break; + } + } + assertTrue(handledByTranshipmentHub); + + //There IS a next element following the 1st hub, so the outgoing shipments does NOT contain the shipment anymore (got handled). + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().contains(shipment)); + assertFalse(element.getIncomingShipments().getLspShipmentsWTime().contains(shipment)); + } + } + + { + assertEquals(1, secondTranshipmentHubResource.getSimulationTrackers().size()); + ArrayList eventHandlers = + new ArrayList<>(secondTranshipmentHubResource.getSimulationTrackers()); + assertInstanceOf(TransshipmentHubTourEndEventHandler.class, eventHandlers.getFirst()); + TransshipmentHubTourEndEventHandler reloadEventHandler = + (TransshipmentHubTourEndEventHandler) eventHandlers.getFirst(); + Iterator< + Entry< + CarrierService, + TransshipmentHubTourEndEventHandler.TransshipmentHubEventHandlerPair>> + iter = reloadEventHandler.getServicesWaitedFor().entrySet().iterator(); + + while (iter.hasNext()) { + Entry + entry = iter.next(); + CarrierService service = entry.getKey(); + LspShipment shipment = entry.getValue().lspShipment; + LogisticChainElement element = entry.getValue().logisticChainElement; + assertSame(service.getLocationLinkId(), toLinkId); + assertEquals(service.getCapacityDemand(), shipment.getSize()); + assertEquals(service.getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + boolean handledByTranshipmentHub = false; + for (LogisticChainElement clientElement : + reloadEventHandler.getTranshipmentHub().getClientElements()) { + if (clientElement == element) { + handledByTranshipmentHub = true; + break; + } + } + assertTrue(handledByTranshipmentHub); + + //There is NO next element following the 2nd hub, so the outgoing shipments remain in the list of the 2nd hub. + assertTrue(element.getOutgoingShipments().getLspShipmentsWTime().contains(shipment)); + assertFalse(element.getIncomingShipments().getLspShipmentsWTime().contains(shipment)); + } + } + + + for (LspShipment shipment : lsp.getLspShipments()) { + assertEquals(4, shipment.getSimulationTrackers().size()); + ArrayList eventHandlers = new ArrayList<>(shipment.getSimulationTrackers()); + ArrayList planElements = new ArrayList<>(LspShipmentUtils.getOrCreateShipmentPlan(lsp.getSelectedPlan(), shipment.getId()).getPlanElements().values()); + planElements.sort(LspShipmentUtils.createShipmentPlanElementComparator()); + ArrayList solutionElements = new ArrayList<>(lsp.getSelectedPlan().getLogisticChains().iterator().next().getLogisticChainElements()); + ArrayList resources = new ArrayList<>(lsp.getResources()); + + {//CollectionTourEnd + assertInstanceOf(LSPTourEndEventHandler.class, eventHandlers.getFirst()); + LSPTourEndEventHandler collectionEndHandler = (LSPTourEndEventHandler) eventHandlers.getFirst(); + assertSame(collectionEndHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(collectionEndHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(collectionEndHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(collectionEndHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(collectionEndHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(collectionEndHandler.getLogisticChainElement(), planElements.get(0).getLogisticChainElement()); + assertSame(collectionEndHandler.getLogisticChainElement(), planElements.get(1).getLogisticChainElement()); + assertSame(collectionEndHandler.getLogisticChainElement(), planElements.get(2).getLogisticChainElement()); + assertSame(collectionEndHandler.getLogisticChainElement(), solutionElements.getFirst()); + assertSame(collectionEndHandler.getLspShipment(), shipment); + assertSame(collectionEndHandler.getResourceId(), planElements.get(0).getResourceId()); + assertSame(collectionEndHandler.getResourceId(), planElements.get(1).getResourceId()); + assertSame(collectionEndHandler.getResourceId(), planElements.get(2).getResourceId()); + assertSame(collectionEndHandler.getResourceId(), resources.getFirst().getId()); + } + + {//CollectionServiceEnd + assertInstanceOf(CollectionServiceEndEventHandler.class, eventHandlers.get(1)); + CollectionServiceEndEventHandler collectionServiceHandler = (CollectionServiceEndEventHandler) eventHandlers.get(1); + assertSame(collectionServiceHandler.getCarrierService().getLocationLinkId(), shipment.getFrom()); + assertEquals(collectionServiceHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(collectionServiceHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(collectionServiceHandler.getCarrierService().getServiceStartTimeWindow().getStart(), shipment.getPickupTimeWindow().getStart(), 0.0); + assertEquals(collectionServiceHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), shipment.getPickupTimeWindow().getEnd(), 0.0); + assertSame(collectionServiceHandler.getElement(), planElements.get(0).getLogisticChainElement()); + assertSame(collectionServiceHandler.getElement(), planElements.get(1).getLogisticChainElement()); + assertSame(collectionServiceHandler.getElement(), planElements.get(2).getLogisticChainElement()); + assertSame(collectionServiceHandler.getElement(), solutionElements.getFirst()); + assertSame(collectionServiceHandler.getLspShipment(), shipment); + assertSame(collectionServiceHandler.getResourceId(), planElements.get(0).getResourceId()); + assertSame(collectionServiceHandler.getResourceId(), planElements.get(1).getResourceId()); + assertSame(collectionServiceHandler.getResourceId(), planElements.get(2).getResourceId()); + assertSame(collectionServiceHandler.getResourceId(), resources.getFirst().getId()); + } + + {//MainRunStart + assertInstanceOf(LSPTourStartEventHandler.class, eventHandlers.get(2)); + LSPTourStartEventHandler mainRunStartHandler = (LSPTourStartEventHandler) eventHandlers.get(2); + assertSame(mainRunStartHandler.getCarrierService().getLocationLinkId(), toLinkId); + assertEquals(mainRunStartHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(mainRunStartHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(0, mainRunStartHandler.getCarrierService().getServiceStartTimeWindow().getStart(), 0.0); + assertEquals(Integer.MAX_VALUE, mainRunStartHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), 0.0); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(4).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(5).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), planElements.get(6).getLogisticChainElement()); + assertSame(mainRunStartHandler.getLogisticChainElement(), solutionElements.get(2)); + assertSame(mainRunStartHandler.getLspShipment(), shipment); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(4).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(5).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), planElements.get(6).getResourceId()); + assertSame(mainRunStartHandler.getResourceId(), resources.get(2).getId()); + } + + {//MainRunEnd + assertInstanceOf(LSPTourEndEventHandler.class, eventHandlers.get(3)); + LSPTourEndEventHandler mainRunEndHandler = (LSPTourEndEventHandler) eventHandlers.get(3); + assertSame(mainRunEndHandler.getCarrierService().getLocationLinkId(), toLinkId); + assertEquals(mainRunEndHandler.getCarrierService().getServiceDuration(), shipment.getDeliveryServiceTime(), 0.0); + assertEquals(mainRunEndHandler.getCarrierService().getCapacityDemand(), shipment.getSize()); + assertEquals(0, mainRunEndHandler.getCarrierService().getServiceStartTimeWindow().getStart(), 0.0); + assertEquals(Integer.MAX_VALUE, mainRunEndHandler.getCarrierService().getServiceStartTimeWindow().getEnd(), 0.0); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(4).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(5).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), planElements.get(6).getLogisticChainElement()); + assertSame(mainRunEndHandler.getLogisticChainElement(), solutionElements.get(2)); + assertSame(mainRunEndHandler.getLspShipment(), shipment); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(4).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(5).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), planElements.get(6).getResourceId()); + assertSame(mainRunEndHandler.getResourceId(), resources.get(2).getId()); + } + } + + for (LogisticChain solution : lsp.getSelectedPlan().getLogisticChains()) { + for (LogisticChainElement element : solution.getLogisticChainElements()) { + assertTrue(element.getIncomingShipments().getLspShipmentsWTime().isEmpty()); + if (element.getNextElement() != null) { + assertTrue(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } else { + assertFalse(element.getOutgoingShipments().getLspShipmentsWTime().isEmpty()); + } + } + } + } +} diff --git a/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/SecondReloadResourceTest.java b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/SecondReloadResourceTest.java new file mode 100644 index 00000000000..d76ad918254 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/logistics/resourceImplementations/SecondReloadResourceTest.java @@ -0,0 +1,71 @@ +/* + * *********************************************************************** * + * * project: org.matsim.* + * * *********************************************************************** * + * * * + * * copyright : (C) 2022 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.freight.logistics.resourceImplementations; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.freight.logistics.LSPCarrierResource; +import org.matsim.freight.logistics.LSPResource; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TranshipmentHubSchedulerBuilder; +import org.matsim.freight.logistics.resourceImplementations.ResourceImplementationUtils.TransshipmentHubBuilder; + +public class SecondReloadResourceTest { + + private TransshipmentHubResource transshipmentHubResource; + private Id reloadingLinkId; + + @BeforeEach + public void initialize() { + TranshipmentHubSchedulerBuilder schedulerBuilder = ResourceImplementationUtils.TranshipmentHubSchedulerBuilder.newInstance(); + schedulerBuilder.setCapacityNeedFixed(10); + schedulerBuilder.setCapacityNeedLinear(1); + + Id reloadingId = Id.create("TranshipmentHub2", LSPResource.class); + reloadingLinkId = Id.createLinkId("(14 2) (14 3)"); + + TransshipmentHubBuilder transshipmentHubBuilder = ResourceImplementationUtils.TransshipmentHubBuilder.newInstance(reloadingId, reloadingLinkId, null); + transshipmentHubBuilder.setTransshipmentHubScheduler(schedulerBuilder.build()); + transshipmentHubResource = transshipmentHubBuilder.build(); + + } + + @Test + public void TranshipmentHubTest() { + assertEquals(10, transshipmentHubResource.getCapacityNeedFixed(), 0.0); + assertEquals(1, transshipmentHubResource.getCapacityNeedLinear(), 0.0); + assertFalse(LSPCarrierResource.class.isAssignableFrom(transshipmentHubResource.getClass())); +// assertSame(TranshipmentHub.getClassOfResource(), TranshipmentHub.class); + assertNotNull(transshipmentHubResource.getClientElements()); + assertTrue(transshipmentHubResource.getClientElements().isEmpty()); + assertSame(transshipmentHubResource.getEndLinkId(), reloadingLinkId); + assertSame(transshipmentHubResource.getStartLinkId(), reloadingLinkId); + assertNotNull(transshipmentHubResource.getSimulationTrackers()); + assertFalse(transshipmentHubResource.getSimulationTrackers().isEmpty()); + assertEquals(1, transshipmentHubResource.getSimulationTrackers().size()); + assertNotNull(transshipmentHubResource.getAttributes()); + assertTrue(transshipmentHubResource.getAttributes().isEmpty()); + } + +} diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierModuleTest/vehicleTypes.xml b/contribs/freight/test/input/org/matsim/freight/carriers/CarrierModuleTest/vehicleTypes.xml deleted file mode 100644 index 1ad295354d8..00000000000 --- a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierModuleTest/vehicleTypes.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - Light Vehicle - - - - - - - - - - - - - - - - Medium Vehicle - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierPlanXmlWriterV1Test/carrierPlansEquils.xml b/contribs/freight/test/input/org/matsim/freight/carriers/CarrierPlanXmlWriterV1Test/carrierPlansEquils.xml deleted file mode 100644 index 9c6165af57d..00000000000 --- a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierPlanXmlWriterV1Test/carrierPlansEquils.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - 2 3 4 - - - - - - - - - - - - - - - - - - - - - - - - - - 2 3 4 - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierPlanXmlWriterV2Test/carrierPlansEquils.xml b/contribs/freight/test/input/org/matsim/freight/carriers/CarrierPlanXmlWriterV2Test/carrierPlansEquils.xml deleted file mode 100644 index 68337d77b88..00000000000 --- a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierPlanXmlWriterV2Test/carrierPlansEquils.xml +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - drt - 50 - - - - - - - - - - - - - - someRandomCustomer - - - - - - - - - someRandomCustomer - - - - - - - - - - - - 2 3 4 - - - - - - - - - - - - - - - - - - 2 3 4 - - - - - - - - - - - - - - - - - - - - - - - - - - 2 3 4 - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierPlanXmlWriterV2Test/carrierPlansEquilsWritten.xml b/contribs/freight/test/input/org/matsim/freight/carriers/CarrierPlanXmlWriterV2Test/carrierPlansEquilsWritten.xml deleted file mode 100644 index 5c122507f56..00000000000 --- a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierPlanXmlWriterV2Test/carrierPlansEquilsWritten.xml +++ /dev/null @@ -1,108 +0,0 @@ - - - - - drt - 50 - - - - - - - - - - - - - - someRandomCustomer - - - - - - - - - someRandomCustomer - - - - - - - - - - - 2 3 4 - - - - - - - - - - - - - - - - - - 2 3 4 - - - - - - - - - - - - - - - - - - - - - - - - - - 2 3 4 - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierReadWriteV2_1Test/carriers.xml b/contribs/freight/test/input/org/matsim/freight/carriers/CarrierReadWriteV2_1Test/carriers.xml index 88124972eec..3d2ae8952c2 100644 --- a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierReadWriteV2_1Test/carriers.xml +++ b/contribs/freight/test/input/org/matsim/freight/carriers/CarrierReadWriteV2_1Test/carriers.xml @@ -8,8 +8,8 @@ - - + + @@ -115,8 +115,8 @@ - - + + diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierVehicleTypeReaderTest/vehicleTypes.xml b/contribs/freight/test/input/org/matsim/freight/carriers/CarrierVehicleTypeReaderTest/vehicleTypes.xml deleted file mode 100644 index f4087007a6d..00000000000 --- a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierVehicleTypeReaderTest/vehicleTypes.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - Medium Vehicle - - 30 - - - - - Light Vehicle - 15 - - - - diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierVehicleTypeLoaderTest/vehicleTypes.xml b/contribs/freight/test/input/org/matsim/freight/carriers/CarrierVehicleTypeReaderTest/vehicleTypes_deprecated_v1.xml similarity index 76% rename from contribs/freight/test/input/org/matsim/freight/carriers/CarrierVehicleTypeLoaderTest/vehicleTypes.xml rename to contribs/freight/test/input/org/matsim/freight/carriers/CarrierVehicleTypeReaderTest/vehicleTypes_deprecated_v1.xml index 4913dba6c79..703e60cd498 100644 --- a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierVehicleTypeLoaderTest/vehicleTypes.xml +++ b/contribs/freight/test/input/org/matsim/freight/carriers/CarrierVehicleTypeReaderTest/vehicleTypes_deprecated_v1.xml @@ -14,9 +14,9 @@ - Heavy Vehicle - 15 - - + Medium Vehicle + 30 + + diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierVehicleTypeReaderTest/vehicleTypes_v2.xml b/contribs/freight/test/input/org/matsim/freight/carriers/CarrierVehicleTypeReaderTest/vehicleTypes_v2.xml deleted file mode 100644 index 8568206c736..00000000000 --- a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierVehicleTypeReaderTest/vehicleTypes_v2.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - Light Vehicle - - - - - - - - 0.02 - gasoline - - - - - - - - - - - - - Medium Vehicle - - - - - - - - 0.02 - gasoline - - - - - - - - - - - - - \ No newline at end of file diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierVehicleTypeWriterTest/vehicleTypes.xml b/contribs/freight/test/input/org/matsim/freight/carriers/CarrierVehicleTypeWriterTest/vehicleTypes.xml deleted file mode 100644 index 9ac37fd0dfe..00000000000 --- a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierVehicleTypeWriterTest/vehicleTypes.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - Medium Vehicle - - 30 - - - - - Light Vehicle - 15 - - - - diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/Carrier_stats.tsv b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/Carrier_stats.tsv new file mode 100644 index 00000000000..8a1b8ff7b0e --- /dev/null +++ b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/Carrier_stats.tsv @@ -0,0 +1,2 @@ +carrierId MATSimScoreSelectedPlan jSpritScoreSelectedPlan nuOfTours nuOfShipments(input) nuOfShipments(handled) nuOfServices(input) nuOfServices(handled) noOfNotHandledJobs nuOfPlanedDemandSize nuOfHandledDemandSize jspritComputationTime[HH:mm:ss] +carrier1 -210.81333333333333 null 1 0 0 7 7 0 7 7 null diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/Load_perVehicle.tsv b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/Load_perVehicle.tsv new file mode 100644 index 00000000000..a1e0058ce5b --- /dev/null +++ b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/Load_perVehicle.tsv @@ -0,0 +1 @@ +vehicleId vehicleTypeId capacity maxLoad load state during tour diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/TimeDistance_perVehicle.tsv b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/TimeDistance_perVehicle.tsv new file mode 100644 index 00000000000..9ed73be9e24 --- /dev/null +++ b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/TimeDistance_perVehicle.tsv @@ -0,0 +1,2 @@ +vehicleId carrierId vehicleTypeId tourId tourDuration[s] tourDuration[h] travelDistance[m] travelDistance[km] travelTime[s] travelTime[h] costPerSecond[EUR/s] costPerMeter[EUR/m] fixedCosts[EUR] varCostsTime[EUR] varCostsDist[EUR] totalCosts[EUR] +freight_carrier1_veh_carrier_19_heavyVehicle_1 carrier1 heavy unknown 8003.0 2.2230555555555553 44000.0 44.0 5896.0 1.6377777777777778 0.008 7.7E-4 130.0 64.024 33.879999999999995 227.904 diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/TimeDistance_perVehicleType.tsv b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/TimeDistance_perVehicleType.tsv new file mode 100644 index 00000000000..962761fc7b1 --- /dev/null +++ b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/TimeDistance_perVehicleType.tsv @@ -0,0 +1,3 @@ +vehicleTypeId nuOfVehicles SumOfTourDuration[s] SumOfTourDuration[h] SumOfTravelDistances[m] SumOfTravelDistances[km] SumOfTravelTime[s] SumOfTravelTime[h] costPerSecond[EUR/s] costPerMeter[EUR/m] fixedCosts[EUR/veh] varCostsTime[EUR] varCostsDist[EUR] fixedCosts[EUR] totalCosts[EUR] +heavy 1 8003.0 2.2230555555555553 44000.0 44.0 5896.0 1.6377777777777778 0.008 7.7E-4 130.0 64.024 33.879999999999995 130.0 227.904 +light 0 0.0 0.0 0.0 0.0 0.0 0.0 0.008 4.7E-4 84.0 0.0 0.0 0.0 0.0 diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/in/output_allVehicles.xml b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/in/output_allVehicles.xml new file mode 100644 index 00000000000..ee644f0e30f --- /dev/null +++ b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/in/output_allVehicles.xml @@ -0,0 +1,24 @@ + + + + + + + A heavy truck + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/in/serviceBasedEvents.xml b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/in/serviceBasedEvents.xml new file mode 100644 index 00000000000..8da18029836 --- /dev/null +++ b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runServiceEventTest/in/serviceBasedEvents.xml @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/Carrier_stats.tsv b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/Carrier_stats.tsv new file mode 100644 index 00000000000..f08676856fb --- /dev/null +++ b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/Carrier_stats.tsv @@ -0,0 +1,2 @@ +carrierId MATSimScoreSelectedPlan jSpritScoreSelectedPlan nuOfTours nuOfShipments(input) nuOfShipments(handled) nuOfServices(input) nuOfServices(handled) noOfNotHandledJobs nuOfPlanedDemandSize nuOfHandledDemandSize jspritComputationTime[HH:mm:ss] +carrier1 -Infinity -215.4666666666667 1 5 5 0 0 0 26 26 00:00:00 diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/Load_perVehicle.tsv b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/Load_perVehicle.tsv new file mode 100644 index 00000000000..d61ddd36308 --- /dev/null +++ b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/Load_perVehicle.tsv @@ -0,0 +1,2 @@ +vehicleId vehicleTypeId capacity maxLoad load state during tour +freight_carrier1_veh_freight_carrier1_veh_heavyVehicle_1_1 heavy 50.0 26 [3, 8, 18, 25, 26, 23, 13, 12, 7, 0] diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/TimeDistance_perVehicle.tsv b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/TimeDistance_perVehicle.tsv new file mode 100644 index 00000000000..24a90a81255 --- /dev/null +++ b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/TimeDistance_perVehicle.tsv @@ -0,0 +1,2 @@ +vehicleId carrierId vehicleTypeId tourId tourDuration[s] tourDuration[h] travelDistance[m] travelDistance[km] travelTime[s] travelTime[h] costPerSecond[EUR/s] costPerMeter[EUR/m] fixedCosts[EUR] varCostsTime[EUR] varCostsDist[EUR] totalCosts[EUR] +freight_carrier1_veh_freight_carrier1_veh_heavyVehicle_1_1 carrier1 heavy 1 6870.0 1.9083333333333334 40000.0 40.0 5360.0 1.488888888888889 0.008 7.7E-4 130.0 54.96 30.799999999999997 215.76 diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/TimeDistance_perVehicleType.tsv b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/TimeDistance_perVehicleType.tsv new file mode 100644 index 00000000000..f2090c11206 --- /dev/null +++ b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/TimeDistance_perVehicleType.tsv @@ -0,0 +1,3 @@ +vehicleTypeId nuOfVehicles SumOfTourDuration[s] SumOfTourDuration[h] SumOfTravelDistances[m] SumOfTravelDistances[km] SumOfTravelTime[s] SumOfTravelTime[h] costPerSecond[EUR/s] costPerMeter[EUR/m] fixedCosts[EUR/veh] varCostsTime[EUR] varCostsDist[EUR] fixedCosts[EUR] totalCosts[EUR] +heavy 1 6870.0 1.9083333333333334 40000.0 40.0 5360.0 1.488888888888889 0.008 7.7E-4 130.0 54.96 30.799999999999997 130.0 215.76 +light 0 0.0 0.0 0.0 0.0 0.0 0.0 0.008 4.7E-4 84.0 0.0 0.0 0.0 0.0 diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/in/carrierVehicles.xml b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/in/carrierVehicles.xml new file mode 100644 index 00000000000..dbb3af477a7 --- /dev/null +++ b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/in/carrierVehicles.xml @@ -0,0 +1,24 @@ + + + + + + + A heavy truck + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/in/shipmentBasedEvents.xml b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/in/shipmentBasedEvents.xml new file mode 100644 index 00000000000..5dd11c5616b --- /dev/null +++ b/contribs/freight/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runShipmentEventTest/in/shipmentBasedEvents.xml @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/controler/vehicleTypes_v2.xml b/contribs/freight/test/input/org/matsim/freight/carriers/controler/vehicleTypes_v2.xml deleted file mode 100644 index d29386a7a2a..00000000000 --- a/contribs/freight/test/input/org/matsim/freight/carriers/controler/vehicleTypes_v2.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - Light Vehicle - - - - - - - - 0.02 - gasoline - - - - - - - - - - - - - Medium Vehicle - - - - - - - - 0.02 - gasoline - - - - - - - - - - - - - Medium Vehicle - - - - - - - - 0.03 - gasoline - - - - - - - - - - - - - Medium Vehicle - - - - - - - - 0.03 - gasoline - - - - - - - - - - - - - diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT/carrierPlansEquils.xml b/contribs/freight/test/input/org/matsim/freight/carriers/controller/EquilWithCarrierWithPersonsIT/carrierPlansEquils.xml similarity index 91% rename from contribs/freight/test/input/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT/carrierPlansEquils.xml rename to contribs/freight/test/input/org/matsim/freight/carriers/controller/EquilWithCarrierWithPersonsIT/carrierPlansEquils.xml index 1a7369f8abf..0971f759480 100644 --- a/contribs/freight/test/input/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT/carrierPlansEquils.xml +++ b/contribs/freight/test/input/org/matsim/freight/carriers/controller/EquilWithCarrierWithPersonsIT/carrierPlansEquils.xml @@ -31,17 +31,17 @@ - - + + - + - + @@ -58,7 +58,7 @@ - + @@ -76,18 +76,18 @@ - + - + - + - + @@ -106,18 +106,18 @@ - + - + - + - + @@ -136,7 +136,6 @@ - + - - \ No newline at end of file + diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT/network.xml b/contribs/freight/test/input/org/matsim/freight/carriers/controller/EquilWithCarrierWithPersonsIT/network.xml old mode 100755 new mode 100644 similarity index 100% rename from contribs/freight/test/input/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT/network.xml rename to contribs/freight/test/input/org/matsim/freight/carriers/controller/EquilWithCarrierWithPersonsIT/network.xml diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT/plans100.xml b/contribs/freight/test/input/org/matsim/freight/carriers/controller/EquilWithCarrierWithPersonsIT/plans100.xml similarity index 100% rename from contribs/freight/test/input/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT/plans100.xml rename to contribs/freight/test/input/org/matsim/freight/carriers/controller/EquilWithCarrierWithPersonsIT/plans100.xml diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT/carrierPlansEquils.xml b/contribs/freight/test/input/org/matsim/freight/carriers/controller/EquilWithCarrierWithoutPersonsIT/carrierPlansEquils.xml similarity index 91% rename from contribs/freight/test/input/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT/carrierPlansEquils.xml rename to contribs/freight/test/input/org/matsim/freight/carriers/controller/EquilWithCarrierWithoutPersonsIT/carrierPlansEquils.xml index 4fd1e13d09d..e7374870fc3 100644 --- a/contribs/freight/test/input/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT/carrierPlansEquils.xml +++ b/contribs/freight/test/input/org/matsim/freight/carriers/controller/EquilWithCarrierWithoutPersonsIT/carrierPlansEquils.xml @@ -31,17 +31,17 @@ - - + + - + - + @@ -58,7 +58,7 @@ - + @@ -76,18 +76,18 @@ - + - + - + - + @@ -106,18 +106,18 @@ - + - + - + - + @@ -136,6 +136,6 @@ - + - + diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT/network.xml b/contribs/freight/test/input/org/matsim/freight/carriers/controller/EquilWithCarrierWithoutPersonsIT/network.xml old mode 100755 new mode 100644 similarity index 100% rename from contribs/freight/test/input/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT/network.xml rename to contribs/freight/test/input/org/matsim/freight/carriers/controller/EquilWithCarrierWithoutPersonsIT/network.xml diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/carriers/controller/EquilWithCarrierWithoutPersonsIT/output_events.xml.gz similarity index 100% rename from contribs/freight/test/input/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT/output_events.xml.gz rename to contribs/freight/test/input/org/matsim/freight/carriers/controller/EquilWithCarrierWithoutPersonsIT/output_events.xml.gz diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/jsprit/IntegrationIT/carrier.xml b/contribs/freight/test/input/org/matsim/freight/carriers/jsprit/IntegrationIT/carrier.xml index e14845dfaff..3f7eaf626e1 100644 --- a/contribs/freight/test/input/org/matsim/freight/carriers/jsprit/IntegrationIT/carrier.xml +++ b/contribs/freight/test/input/org/matsim/freight/carriers/jsprit/IntegrationIT/carrier.xml @@ -3,19 +3,19 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -197,8 +197,8 @@ - - + + diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/jsprit/IntegrationIT/vehicleTypes.xml b/contribs/freight/test/input/org/matsim/freight/carriers/jsprit/IntegrationIT/vehicleTypes.xml deleted file mode 100644 index 5f3ad64ff22..00000000000 --- a/contribs/freight/test/input/org/matsim/freight/carriers/jsprit/IntegrationIT/vehicleTypes.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - null - 6000 - - - - null - 7000 - - - - null - 12000 - - - - null - 3000 - - - - null - 15000 - - - - diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT/runChessboard/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT/runChessboard/output_events.xml.gz index 8057a55fbcc..bf5ebee32b8 100644 Binary files a/contribs/freight/test/input/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT/runChessboard/output_events.xml.gz and b/contribs/freight/test/input/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT/runChessboard/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/vehicleTypes_v2.xml b/contribs/freight/test/input/org/matsim/freight/carriers/vehicleTypes_v2.xml index c9b487b48b9..f78dccd883c 100644 --- a/contribs/freight/test/input/org/matsim/freight/carriers/vehicleTypes_v2.xml +++ b/contribs/freight/test/input/org/matsim/freight/carriers/vehicleTypes_v2.xml @@ -2,29 +2,7 @@ - - - Light Vehicle - - - - - - - - 0.02 - gasoline - - - - - - - - - - - + Medium Vehicle @@ -34,11 +12,11 @@ - 0.02 - gasoline + gasoline + 0.03 - + @@ -46,21 +24,21 @@ - + - Medium Vehicle - + Light Vehicle + - 0.03 - gasoline + gasoline + 0.02 - + @@ -68,7 +46,7 @@ - + Medium Vehicle @@ -78,11 +56,11 @@ - 0.03 - gasoline + gasoline + 0.02 - + diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/examples/initialPlans/ExampleSchedulingOfTransportChainHubsVsDirectTest/testMain1/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/examples/initialPlans/ExampleSchedulingOfTransportChainHubsVsDirectTest/testMain1/output_events.xml.gz new file mode 100644 index 00000000000..c7bb86ba149 Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/examples/initialPlans/ExampleSchedulingOfTransportChainHubsVsDirectTest/testMain1/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/examples/initialPlans/ExampleSchedulingOfTransportChainHubsVsDirectTest/testMain2_direct/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/examples/initialPlans/ExampleSchedulingOfTransportChainHubsVsDirectTest/testMain2_direct/output_events.xml.gz new file mode 100644 index 00000000000..da9f8fe99ef Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/examples/initialPlans/ExampleSchedulingOfTransportChainHubsVsDirectTest/testMain2_direct/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/examples/lspReplanning/CollectionLSPReplanningTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/examples/lspReplanning/CollectionLSPReplanningTest/output_events.xml.gz new file mode 100644 index 00000000000..953044d825c Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/examples/lspReplanning/CollectionLSPReplanningTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/examples/lspScoring/CollectionLSPScoringTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/examples/lspScoring/CollectionLSPScoringTest/output_events.xml.gz new file mode 100644 index 00000000000..e03c47b6e73 Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/examples/lspScoring/CollectionLSPScoringTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/examples/lspScoring/MultipleIterationsCollectionLSPScoringTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/examples/lspScoring/MultipleIterationsCollectionLSPScoringTest/output_events.xml.gz new file mode 100644 index 00000000000..55b637c1592 Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/examples/lspScoring/MultipleIterationsCollectionLSPScoringTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/examples/mobsimExamples/ExampleMobsimOfSimpleLSPTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/examples/mobsimExamples/ExampleMobsimOfSimpleLSPTest/output_events.xml.gz new file mode 100644 index 00000000000..11deb8015c0 Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/examples/mobsimExamples/ExampleMobsimOfSimpleLSPTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/examples/multipleChains/ExampleTwoLspsGroceryDeliveryMultipleChainsTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/examples/multipleChains/ExampleTwoLspsGroceryDeliveryMultipleChainsTest/output_events.xml.gz new file mode 100644 index 00000000000..6da265f5157 Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/examples/multipleChains/ExampleTwoLspsGroceryDeliveryMultipleChainsTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/examples/multipleChains/ExampleTwoLspsGroceryDeliveryMultipleChainsTest/output_lsps.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/examples/multipleChains/ExampleTwoLspsGroceryDeliveryMultipleChainsTest/output_lsps.xml.gz new file mode 100644 index 00000000000..a81a27f6410 Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/examples/multipleChains/ExampleTwoLspsGroceryDeliveryMultipleChainsTest/output_lsps.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/examples/simulationTrackers/CollectionTrackerTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/examples/simulationTrackers/CollectionTrackerTest/output_events.xml.gz new file mode 100644 index 00000000000..8a42fcbf5b5 Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/examples/simulationTrackers/CollectionTrackerTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/io/carriers.xml b/contribs/freight/test/input/org/matsim/freight/logistics/io/carriers.xml new file mode 100644 index 00000000000..6e6493a0ff7 --- /dev/null +++ b/contribs/freight/test/input/org/matsim/freight/logistics/io/carriers.xml @@ -0,0 +1,291 @@ + + + + + + distributionCarrier + + + + + + + + + + + + + + + + j(1,1) j(1,2) j(1,3) j(1,4) j(1,5) j(1,6) j(1,7) j(1,8) i(2,8) i(3,8) i(4,8) i(5,8) i(6,8) i(7,8) i(8,8) + + + + j(9,9) i(9,9)R j(8,9)R j(8,8)R j(8,7)R j(8,6)R j(8,5)R j(8,4)R j(8,3)R j(8,2)R j(8,1)R + + + + j(9,1) i(9,1)R i(8,1)R i(7,1)R i(6,1)R i(5,1)R i(4,1)R i(3,1)R i(2,1)R i(1,1)R j(0,1)R + + + + + + + + + distributionCarrier + + + + + + + + + + + + + + distributionCarrier + + + + + + + + + + + + + + mainRunCarrier + + + + + + + + + + + + + + + + + + + + + + + + j(1,1) j(1,2) j(1,3) j(1,4) j(1,5) j(1,6) j(1,7) j(1,8) i(2,8) i(3,8) i(4,8) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + i(6,8) j(6,8)R j(6,7)R j(6,6)R j(6,5)R j(6,4)R j(6,3)R j(6,2)R i(6,1)R i(5,1)R i(4,1)R i(3,1)R i(2,1)R i(1,1)R j(0,1)R + + + + + + + + + distributionCarrier + + + + + + + + + + + + + + + + + + + + + + + + i(6,8) j(6,8)R i(6,7)R + + + + + + + + + + + + j(5,7) i(5,7)R i(4,7)R i(3,7)R j(2,7)R i(3,6) + + + + j(4,6)R i(4,5)R j(3,6) + + + + j(3,8) i(4,8) + + + + + + + i(6,8) j(6,8)R i(6,7)R i(5,7)R j(4,7)R i(5,6) + + + + + + + + i(6,5)R j(5,6) + + + + i(5,7)R i(4,7)R i(3,7)R j(2,7)R i(3,6) + + + + j(4,6)R i(4,5)R j(3,6) + + + + j(3,8) i(4,8) + + + + + + + + + distributionCarrier + + + + + + + + + + + + + + + + + + + + + + + + j(1,1) j(1,2) j(1,3) j(1,4) j(1,5) j(1,6) i(2,6) i(3,6) + + + + + + + + i(3,7)R j(2,7)R i(3,6) + + + + + + + + i(5,6) j(5,7) i(5,7)R + + + + + + + + + + + + + + + + i(6,5)R j(5,6) + + + + + + + + j(4,7)R j(4,6)R j(4,5)R j(4,4)R j(4,3)R j(4,2)R i(4,1)R i(3,1)R i(2,1)R i(1,1)R j(0,1)R + + + + + + + \ No newline at end of file diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/io/lsps.xml b/contribs/freight/test/input/org/matsim/freight/logistics/io/lsps.xml new file mode 100644 index 00000000000..556ef25c6c6 --- /dev/null +++ b/contribs/freight/test/input/org/matsim/freight/logistics/io/lsps.xml @@ -0,0 +1,243 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierReadWriteV2_1Test/vehicles.xml b/contribs/freight/test/input/org/matsim/freight/logistics/io/vehicles.xml similarity index 71% rename from contribs/freight/test/input/org/matsim/freight/carriers/CarrierReadWriteV2_1Test/vehicles.xml rename to contribs/freight/test/input/org/matsim/freight/logistics/io/vehicles.xml index 3ff84f751a1..a98419ac59d 100644 --- a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierReadWriteV2_1Test/vehicles.xml +++ b/contribs/freight/test/input/org/matsim/freight/logistics/io/vehicles.xml @@ -17,22 +17,6 @@ - - - - - - - - - - - - - - - - @@ -48,6 +32,6 @@ + - - + \ No newline at end of file diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/CollectionLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/CollectionLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..7a3a269cd78 Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/CollectionLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/CompleteLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/CompleteLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..d7897531de3 Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/CompleteLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/FirstAndSecondReloadLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/FirstAndSecondReloadLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..6def492ec5d Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/FirstAndSecondReloadLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/FirstReloadLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/FirstReloadLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..4e8cc4957a1 Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/FirstReloadLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MainRunLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MainRunLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..9da5513322e Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MainRunLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MainRunOnlyLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MainRunOnlyLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..8cd33ffda2b Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MainRunOnlyLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsCollectionLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsCollectionLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..45e527febdf Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsCollectionLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsCompleteLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsCompleteLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..d36cdc25b87 Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsCompleteLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsFirstAndSecondReloadLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsFirstAndSecondReloadLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..0bab600b81b Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsFirstAndSecondReloadLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsFirstReloadLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsFirstReloadLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..39eeab60be2 Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsFirstReloadLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsMainRunLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsMainRunLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..99f6e933591 Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleIterationsMainRunLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsCollectionLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsCollectionLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..af5f5b3cecf Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsCollectionLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsCompleteLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsCompleteLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..ab288426f05 Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsCompleteLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsFirstAndSecondReloadLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsFirstAndSecondReloadLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..298d349f4a0 Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsFirstAndSecondReloadLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsFirstReloadLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsFirstReloadLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..fbb89f77428 Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsFirstReloadLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsMainRunLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsMainRunLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..ca605ab9f9e Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/MultipleShipmentsMainRunLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/RepeatedMultipleShipmentsCompleteLSPMobsimTest/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/RepeatedMultipleShipmentsCompleteLSPMobsimTest/output_events.xml.gz new file mode 100644 index 00000000000..8cc1ea40edb Binary files /dev/null and b/contribs/freight/test/input/org/matsim/freight/logistics/lspMobsimTests/RepeatedMultipleShipmentsCompleteLSPMobsimTest/output_events.xml.gz differ diff --git a/contribs/freightreceiver/pom.xml b/contribs/freightreceiver/pom.xml index 9b9a8fdc2c9..1e69c51d40d 100644 --- a/contribs/freightreceiver/pom.xml +++ b/contribs/freightreceiver/pom.xml @@ -28,13 +28,13 @@ org.matsim.contrib freight - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim matsim-examples - 2025.0-SNAPSHOT + ${project.parent.version} diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/Order.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/Order.java similarity index 99% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/Order.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/Order.java index 6060e7ba4ee..d2cd76201eb 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/Order.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/Order.java @@ -16,7 +16,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ProductType.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ProductType.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ProductType.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ProductType.java index 4589cd7b3b9..6c7b6f84f97 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ProductType.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ProductType.java @@ -16,7 +16,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Identifiable; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/Receiver.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/Receiver.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/Receiver.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/Receiver.java index 631130ba87a..3faee4fc53b 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/Receiver.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/Receiver.java @@ -16,7 +16,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverAgent.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverAgent.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverAgent.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverAgent.java index df29bc43a71..df4c6d6f948 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverAgent.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverAgent.java @@ -16,7 +16,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverConfigGroup.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverConfigGroup.java similarity index 99% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverConfigGroup.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverConfigGroup.java index dfbc6cbe4a5..e42150f9b8f 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverConfigGroup.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverConfigGroup.java @@ -15,7 +15,7 @@ * See also COPYING, LICENSE and WARRANTY file * * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverControlerListener.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverControlerListener.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverControlerListener.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverControlerListener.java index 10fe1be6bdd..852452663a6 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverControlerListener.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverControlerListener.java @@ -16,7 +16,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import com.google.inject.Inject; import org.apache.logging.log4j.LogManager; @@ -29,8 +29,8 @@ import org.matsim.freight.carriers.CarriersUtils; import org.matsim.freight.carriers.ScheduledTour; import org.matsim.freight.carriers.Tour; -import org.matsim.contrib.freightreceiver.collaboration.CollaborationUtils; -import org.matsim.contrib.freightreceiver.replanning.ReceiverStrategyManager; +import org.matsim.freight.receiver.collaboration.CollaborationUtils; +import org.matsim.freight.receiver.replanning.ReceiverStrategyManager; import org.matsim.core.config.ConfigUtils; import org.matsim.core.controler.events.*; import org.matsim.core.controler.listener.*; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverCostAllocation.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverCostAllocation.java similarity index 96% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverCostAllocation.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverCostAllocation.java index 72ccdeb68fa..c01f7425f9b 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverCostAllocation.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverCostAllocation.java @@ -18,7 +18,7 @@ * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.matsim.freight.carriers.Carrier; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverCostAllocationEqualProportion.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverCostAllocationEqualProportion.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverCostAllocationEqualProportion.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverCostAllocationEqualProportion.java index 6f85efcd2f1..ae79d2db6c5 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverCostAllocationEqualProportion.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverCostAllocationEqualProportion.java @@ -18,7 +18,7 @@ * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import com.google.inject.Inject; import org.matsim.api.core.v01.Id; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverCostAllocationFixed.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverCostAllocationFixed.java similarity index 97% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverCostAllocationFixed.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverCostAllocationFixed.java index 5f3a6a2dea2..fed9d76f609 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverCostAllocationFixed.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverCostAllocationFixed.java @@ -17,7 +17,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.apache.logging.log4j.LogManager; import org.matsim.freight.carriers.Carrier; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverCostAllocationType.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverCostAllocationType.java similarity index 96% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverCostAllocationType.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverCostAllocationType.java index 9ad1862b9c9..c4b110f8266 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverCostAllocationType.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverCostAllocationType.java @@ -18,7 +18,7 @@ * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; /** * The supported ways in which the carrier's cost is spread among the receivers. diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverImpl.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverImpl.java similarity index 99% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverImpl.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverImpl.java index 1f29889a0a6..59b70767176 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverImpl.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverImpl.java @@ -16,7 +16,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverModule.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverModule.java similarity index 96% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverModule.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverModule.java index aac11b5e7b2..a108dbf87f4 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverModule.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverModule.java @@ -16,14 +16,15 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.matsim.freight.carriers.Carrier; -import org.matsim.contrib.freightreceiver.replanning.*; import org.matsim.core.config.ConfigUtils; import org.matsim.core.controler.AbstractModule; +import org.matsim.freight.receiver.replanning.ReceiverReplanningUtils; +import org.matsim.freight.receiver.replanning.ReceiverStrategyManager; public final class ReceiverModule extends AbstractModule { final private static Logger LOG = LogManager.getLogger(ReceiverModule.class); diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverOrder.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverOrder.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverOrder.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverOrder.java index 081004dcb71..cad5c103842 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverOrder.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverOrder.java @@ -16,7 +16,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverPlan.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverPlan.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverPlan.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverPlan.java index 0497d364b3d..88a8fe76268 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverPlan.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverPlan.java @@ -16,7 +16,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -25,7 +25,7 @@ import org.matsim.api.core.v01.population.Person; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.TimeWindow; -import org.matsim.contrib.freightreceiver.collaboration.CollaborationUtils; +import org.matsim.freight.receiver.collaboration.CollaborationUtils; import org.matsim.utils.objectattributes.attributable.Attributable; import org.matsim.utils.objectattributes.attributable.Attributes; import org.matsim.utils.objectattributes.attributable.AttributesImpl; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverProduct.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverProduct.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverProduct.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverProduct.java index 40489f44c23..5e734d77247 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverProduct.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverProduct.java @@ -16,7 +16,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; /** * Returns a new instance of a receiver product with associated information, diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverReplanningType.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverReplanningType.java similarity index 96% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverReplanningType.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverReplanningType.java index d8bd5df43dc..f1845f3d2cb 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverReplanningType.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverReplanningType.java @@ -15,7 +15,7 @@ * See also COPYING, LICENSE and WARRANTY file * * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; public enum ReceiverReplanningType { serviceTime, timeWindow, orderFrequency, afterHoursTimeWindow diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverScoreStats.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverScoreStats.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverScoreStats.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverScoreStats.java index a9a63491a07..a6b260fc449 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverScoreStats.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverScoreStats.java @@ -1,11 +1,11 @@ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import com.google.inject.Inject; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Scenario; import org.matsim.freight.carriers.CarriersUtils; -import org.matsim.contrib.freightreceiver.collaboration.CollaborationUtils; +import org.matsim.freight.receiver.collaboration.CollaborationUtils; import org.matsim.core.config.ConfigUtils; import org.matsim.core.controler.events.IterationEndsEvent; import org.matsim.core.controler.events.ShutdownEvent; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverScoringFunctionFactory.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverScoringFunctionFactory.java similarity index 97% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverScoringFunctionFactory.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverScoringFunctionFactory.java index 81e60676e02..ade37d5354e 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverScoringFunctionFactory.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverScoringFunctionFactory.java @@ -16,7 +16,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.matsim.core.scoring.ScoringFunction; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverScoringFunctionFactoryMoneyOnly.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverScoringFunctionFactoryMoneyOnly.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverScoringFunctionFactoryMoneyOnly.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverScoringFunctionFactoryMoneyOnly.java index 57357050ebb..e937074d616 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverScoringFunctionFactoryMoneyOnly.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverScoringFunctionFactoryMoneyOnly.java @@ -16,7 +16,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.apache.logging.log4j.LogManager; import org.matsim.core.scoring.ScoringFunction; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverTracker.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverTracker.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverTracker.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverTracker.java index a03dc19cf06..e1fd6bc7ef5 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverTracker.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverTracker.java @@ -16,7 +16,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverTriggersCarrierReplanningListener.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverTriggersCarrierReplanningListener.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverTriggersCarrierReplanningListener.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverTriggersCarrierReplanningListener.java index 62a2a507aa2..2b8c4a6dfb9 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverTriggersCarrierReplanningListener.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverTriggersCarrierReplanningListener.java @@ -15,7 +15,7 @@ * See also COPYING, LICENSE and WARRANTY file * * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm; import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem; @@ -29,7 +29,7 @@ import org.matsim.freight.carriers.jsprit.MatsimJspritFactory; import org.matsim.freight.carriers.jsprit.NetworkBasedTransportCosts; import org.matsim.freight.carriers.jsprit.NetworkRouter; -import org.matsim.contrib.freightreceiver.collaboration.CollaborationUtils; +import org.matsim.freight.receiver.collaboration.CollaborationUtils; import org.matsim.core.config.ConfigUtils; import org.matsim.core.controler.events.IterationStartsEvent; import org.matsim.core.controler.listener.IterationStartsListener; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverUtils.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverUtils.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverUtils.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverUtils.java index dcd2861daed..e9b1b293368 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiverUtils.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiverUtils.java @@ -1,4 +1,4 @@ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/Receivers.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/Receivers.java similarity index 99% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/Receivers.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/Receivers.java index 3d042480928..640aa31d6b8 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/Receivers.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/Receivers.java @@ -16,7 +16,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversReader.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversReader.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversReader.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversReader.java index 63afdf1c4cd..1c68dd3dbfe 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversReader.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversReader.java @@ -18,7 +18,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.matsim.core.utils.io.MatsimXmlParser; import org.xml.sax.Attributes; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversReaderV2.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversReaderV2.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversReaderV2.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversReaderV2.java index 2036326c078..b886be795f8 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversReaderV2.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversReaderV2.java @@ -18,13 +18,13 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.TimeWindow; -import org.matsim.contrib.freightreceiver.collaboration.CollaborationUtils; +import org.matsim.freight.receiver.collaboration.CollaborationUtils; import org.matsim.core.api.internal.MatsimReader; import org.matsim.core.utils.io.MatsimXmlParser; import org.matsim.core.utils.misc.Counter; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversWriter.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversWriter.java similarity index 99% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversWriter.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversWriter.java index cd9e2f33a06..68b37813398 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversWriter.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversWriter.java @@ -18,7 +18,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversWriterHandler.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversWriterHandler.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversWriterHandler.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversWriterHandler.java index 09172159e06..1ceacde5d4b 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversWriterHandler.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversWriterHandler.java @@ -18,7 +18,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.matsim.freight.carriers.TimeWindow; import java.io.BufferedWriter; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversWriterHandlerImplV1.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversWriterHandlerImplV1.java similarity index 99% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversWriterHandlerImplV1.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversWriterHandlerImplV1.java index ecc7b58f43e..4e5a4b2e262 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversWriterHandlerImplV1.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversWriterHandlerImplV1.java @@ -18,7 +18,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.matsim.freight.carriers.TimeWindow; import org.matsim.core.utils.misc.Time; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversWriterHandlerImplV2.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversWriterHandlerImplV2.java similarity index 99% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversWriterHandlerImplV2.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversWriterHandlerImplV2.java index c2b8fe50f1b..b9091c62111 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReceiversWriterHandlerImplV2.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReceiversWriterHandlerImplV2.java @@ -18,7 +18,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.matsim.freight.carriers.TimeWindow; import org.matsim.core.utils.misc.Time; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReorderPolicy.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReorderPolicy.java similarity index 97% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReorderPolicy.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReorderPolicy.java index e04152e5e30..9447bb3b8bc 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/ReorderPolicy.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/ReorderPolicy.java @@ -18,7 +18,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.matsim.utils.objectattributes.attributable.Attributable; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/SSReorderPolicy.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/SSReorderPolicy.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/SSReorderPolicy.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/SSReorderPolicy.java index 9928bbc6191..f9620ef58b2 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/SSReorderPolicy.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/SSReorderPolicy.java @@ -18,7 +18,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.matsim.utils.objectattributes.attributable.Attributes; import org.matsim.utils.objectattributes.attributable.AttributesImpl; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/UsecasesCarrierScoringFunctionFactory.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/UsecasesCarrierScoringFunctionFactory.java similarity index 97% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/UsecasesCarrierScoringFunctionFactory.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/UsecasesCarrierScoringFunctionFactory.java index 5cc872f2b50..ba49d350c14 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/UsecasesCarrierScoringFunctionFactory.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/UsecasesCarrierScoringFunctionFactory.java @@ -1,4 +1,4 @@ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; @@ -8,8 +8,8 @@ import org.matsim.api.core.v01.population.Activity; import org.matsim.api.core.v01.population.Leg; import org.matsim.freight.carriers.*; -import org.matsim.freight.carriers.controler.CarrierScoringFunctionFactory; -import org.matsim.freight.carriers.controler.FreightActivity; +import org.matsim.freight.carriers.controller.CarrierScoringFunctionFactory; +import org.matsim.freight.carriers.controller.FreightActivity; import org.matsim.core.population.routes.NetworkRoute; import org.matsim.core.scoring.ScoringFunction; import org.matsim.core.scoring.SumScoringFunction; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/Coalition.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/Coalition.java similarity index 86% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/Coalition.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/Coalition.java index 9afea8cdc9e..77e28d853e6 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/Coalition.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/Coalition.java @@ -1,7 +1,7 @@ -package org.matsim.contrib.freightreceiver.collaboration; +package org.matsim.freight.receiver.collaboration; import org.matsim.freight.carriers.Carrier; -import org.matsim.contrib.freightreceiver.Receiver; +import org.matsim.freight.receiver.Receiver; import org.matsim.utils.objectattributes.attributable.Attributable; import java.util.Collection; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/CollaborationUtils.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/CollaborationUtils.java similarity index 97% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/CollaborationUtils.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/CollaborationUtils.java index 25e73445613..3775eec413b 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/CollaborationUtils.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/CollaborationUtils.java @@ -1,4 +1,4 @@ -package org.matsim.contrib.freightreceiver.collaboration; +package org.matsim.freight.receiver.collaboration; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -7,7 +7,7 @@ import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.CarriersUtils; import org.matsim.freight.carriers.Carriers; -import org.matsim.contrib.freightreceiver.*; +import org.matsim.freight.receiver.*; public class CollaborationUtils{ private CollaborationUtils(){} // do not instantiate diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/CollaborationUtilsNew.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/CollaborationUtilsNew.java similarity index 70% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/CollaborationUtilsNew.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/CollaborationUtilsNew.java index c3c3d3d544e..68576dc0ea3 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/CollaborationUtilsNew.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/CollaborationUtilsNew.java @@ -1,7 +1,7 @@ -package org.matsim.contrib.freightreceiver.collaboration; +package org.matsim.freight.receiver.collaboration; import org.matsim.freight.carriers.Carriers; -import org.matsim.contrib.freightreceiver.*; +import org.matsim.freight.receiver.Receivers; /** * Class with utilities to handle the collaboration between {@link Carriers} diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/MutableCoalition.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/MutableCoalition.java similarity index 93% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/MutableCoalition.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/MutableCoalition.java index 4799f493912..c6597ff695d 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/MutableCoalition.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/MutableCoalition.java @@ -1,8 +1,8 @@ -package org.matsim.contrib.freightreceiver.collaboration; +package org.matsim.freight.receiver.collaboration; import org.matsim.freight.carriers.Carrier; -import org.matsim.contrib.freightreceiver.Receiver; +import org.matsim.freight.receiver.Receiver; import org.matsim.utils.objectattributes.attributable.Attributes; import org.matsim.utils.objectattributes.attributable.AttributesImpl; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/OrderSizeMutator.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/OrderSizeMutator.java similarity index 93% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/OrderSizeMutator.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/OrderSizeMutator.java index 99b91c04395..118f6ed3b84 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/OrderSizeMutator.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/OrderSizeMutator.java @@ -16,11 +16,11 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver.collaboration; +package org.matsim.freight.receiver.collaboration; -import org.matsim.contrib.freightreceiver.Order; -import org.matsim.contrib.freightreceiver.ReceiverOrder; -import org.matsim.contrib.freightreceiver.ReceiverPlan; +import org.matsim.freight.receiver.Order; +import org.matsim.freight.receiver.ReceiverOrder; +import org.matsim.freight.receiver.ReceiverPlan; import org.matsim.core.gbl.MatsimRandom; import org.matsim.core.replanning.ReplanningContext; import org.matsim.core.replanning.modules.GenericPlanStrategyModule; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/TimeWindowMutator.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/TimeWindowMutator.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/TimeWindowMutator.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/TimeWindowMutator.java index bf972b057fe..abd734db026 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/collaboration/TimeWindowMutator.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/collaboration/TimeWindowMutator.java @@ -19,10 +19,10 @@ /** * */ -package org.matsim.contrib.freightreceiver.collaboration; +package org.matsim.freight.receiver.collaboration; import org.matsim.freight.carriers.TimeWindow; -import org.matsim.contrib.freightreceiver.ReceiverPlan; +import org.matsim.freight.receiver.ReceiverPlan; import org.matsim.core.gbl.MatsimRandom; import org.matsim.core.replanning.ReplanningContext; import org.matsim.core.replanning.modules.GenericPlanStrategyModule; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/multiday/MultidayUtils.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/multiday/MultidayUtils.java similarity index 89% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/multiday/MultidayUtils.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/multiday/MultidayUtils.java index 46fad091944..b5aad6ea53a 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/multiday/MultidayUtils.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/multiday/MultidayUtils.java @@ -1,4 +1,4 @@ -package org.matsim.contrib.freightreceiver.multiday; +package org.matsim.freight.receiver.multiday; import org.matsim.core.utils.misc.OptionalTime; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/CollaborationStatusMutator.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/CollaborationStatusMutator.java similarity index 88% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/CollaborationStatusMutator.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/CollaborationStatusMutator.java index 018a8f64c87..caa840d48c1 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/CollaborationStatusMutator.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/CollaborationStatusMutator.java @@ -1,9 +1,9 @@ -package org.matsim.contrib.freightreceiver.replanning; +package org.matsim.freight.receiver.replanning; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; -import org.matsim.contrib.freightreceiver.ReceiverPlan; -import org.matsim.contrib.freightreceiver.collaboration.CollaborationUtils; +import org.matsim.freight.receiver.ReceiverPlan; +import org.matsim.freight.receiver.collaboration.CollaborationUtils; import org.matsim.core.replanning.ReplanningContext; import org.matsim.core.replanning.modules.GenericPlanStrategyModule; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/OrderFrequencyStrategyManager.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/OrderFrequencyStrategyManager.java similarity index 91% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/OrderFrequencyStrategyManager.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/OrderFrequencyStrategyManager.java index f74750d9924..eb14b8eeb22 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/OrderFrequencyStrategyManager.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/OrderFrequencyStrategyManager.java @@ -1,11 +1,11 @@ -package org.matsim.contrib.freightreceiver.replanning; +package org.matsim.freight.receiver.replanning; import com.google.inject.Inject; import com.google.inject.Provider; import org.matsim.api.core.v01.Scenario; -import org.matsim.contrib.freightreceiver.Receiver; -import org.matsim.contrib.freightreceiver.ReceiverPlan; -import org.matsim.contrib.freightreceiver.collaboration.OrderSizeMutator; +import org.matsim.freight.receiver.Receiver; +import org.matsim.freight.receiver.ReceiverPlan; +import org.matsim.freight.receiver.collaboration.OrderSizeMutator; import org.matsim.core.replanning.GenericPlanStrategyImpl; import org.matsim.core.replanning.selectors.ExpBetaPlanChanger; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/ReceiverReplanningUtils.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/ReceiverReplanningUtils.java similarity index 81% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/ReceiverReplanningUtils.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/ReceiverReplanningUtils.java index 2bdc4eadbb7..71309261c26 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/ReceiverReplanningUtils.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/ReceiverReplanningUtils.java @@ -1,7 +1,7 @@ -package org.matsim.contrib.freightreceiver.replanning; +package org.matsim.freight.receiver.replanning; import com.google.inject.Provider; -import org.matsim.contrib.freightreceiver.ReceiverReplanningType; +import org.matsim.freight.receiver.ReceiverReplanningType; /** * A single entry point for receiver replanning. diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/ReceiverStrategyManager.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/ReceiverStrategyManager.java similarity index 83% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/ReceiverStrategyManager.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/ReceiverStrategyManager.java index 0ef128e441a..f697154a305 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/ReceiverStrategyManager.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/ReceiverStrategyManager.java @@ -18,11 +18,11 @@ * *********************************************************************** */ -package org.matsim.contrib.freightreceiver.replanning; +package org.matsim.freight.receiver.replanning; -import org.matsim.freight.carriers.controler.CarrierStrategyManager; -import org.matsim.contrib.freightreceiver.Receiver; -import org.matsim.contrib.freightreceiver.ReceiverPlan; +import org.matsim.freight.carriers.controller.CarrierStrategyManager; +import org.matsim.freight.receiver.Receiver; +import org.matsim.freight.receiver.ReceiverPlan; import org.matsim.core.replanning.GenericStrategyManager; /** diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/ReceiverStrategyManagerImpl.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/ReceiverStrategyManagerImpl.java similarity index 94% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/ReceiverStrategyManagerImpl.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/ReceiverStrategyManagerImpl.java index 4b56bee4470..c164c64a039 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/ReceiverStrategyManagerImpl.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/ReceiverStrategyManagerImpl.java @@ -18,11 +18,11 @@ * *********************************************************************** */ -package org.matsim.contrib.freightreceiver.replanning; +package org.matsim.freight.receiver.replanning; import org.matsim.api.core.v01.population.HasPlansAndId; -import org.matsim.contrib.freightreceiver.Receiver; -import org.matsim.contrib.freightreceiver.ReceiverPlan; +import org.matsim.freight.receiver.Receiver; +import org.matsim.freight.receiver.ReceiverPlan; import org.matsim.core.replanning.GenericPlanStrategy; import org.matsim.core.replanning.GenericStrategyManager; import org.matsim.core.replanning.GenericStrategyManagerImpl; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/ServiceTimeMutator.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/ServiceTimeMutator.java similarity index 93% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/ServiceTimeMutator.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/ServiceTimeMutator.java index 842ad6c5584..7488cc3e748 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/ServiceTimeMutator.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/ServiceTimeMutator.java @@ -16,13 +16,13 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver.replanning; +package org.matsim.freight.receiver.replanning; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; -import org.matsim.contrib.freightreceiver.Order; -import org.matsim.contrib.freightreceiver.ReceiverOrder; -import org.matsim.contrib.freightreceiver.ReceiverPlan; +import org.matsim.freight.receiver.Order; +import org.matsim.freight.receiver.ReceiverOrder; +import org.matsim.freight.receiver.ReceiverPlan; import org.matsim.core.replanning.ReplanningContext; import org.matsim.core.replanning.modules.GenericPlanStrategyModule; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/ServiceTimeStrategyManagerProvider.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/ServiceTimeStrategyManagerProvider.java similarity index 95% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/ServiceTimeStrategyManagerProvider.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/ServiceTimeStrategyManagerProvider.java index 6271e402b57..c88b09a261d 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/ServiceTimeStrategyManagerProvider.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/ServiceTimeStrategyManagerProvider.java @@ -1,10 +1,10 @@ -package org.matsim.contrib.freightreceiver.replanning; +package org.matsim.freight.receiver.replanning; import com.google.inject.Inject; import com.google.inject.Provider; import org.matsim.api.core.v01.Scenario; -import org.matsim.contrib.freightreceiver.Receiver; -import org.matsim.contrib.freightreceiver.ReceiverPlan; +import org.matsim.freight.receiver.Receiver; +import org.matsim.freight.receiver.ReceiverPlan; import org.matsim.core.replanning.GenericPlanStrategy; import org.matsim.core.replanning.GenericPlanStrategyImpl; import org.matsim.core.replanning.selectors.ExpBetaPlanChanger; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/TimeWindowStrategyManagerFactory.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/TimeWindowStrategyManagerFactory.java similarity index 92% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/TimeWindowStrategyManagerFactory.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/TimeWindowStrategyManagerFactory.java index e19d1437dc0..87926d796a2 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/TimeWindowStrategyManagerFactory.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/TimeWindowStrategyManagerFactory.java @@ -1,13 +1,13 @@ /** * */ -package org.matsim.contrib.freightreceiver.replanning; +package org.matsim.freight.receiver.replanning; import com.google.inject.Inject; import com.google.inject.Provider; import org.matsim.api.core.v01.Scenario; -import org.matsim.contrib.freightreceiver.Receiver; -import org.matsim.contrib.freightreceiver.ReceiverPlan; +import org.matsim.freight.receiver.Receiver; +import org.matsim.freight.receiver.ReceiverPlan; import org.matsim.core.replanning.GenericPlanStrategyImpl; import org.matsim.core.replanning.selectors.ExpBetaPlanChanger; import org.matsim.core.utils.misc.Time; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/TimeWindowUpperBoundMutator.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/TimeWindowUpperBoundMutator.java similarity index 97% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/TimeWindowUpperBoundMutator.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/TimeWindowUpperBoundMutator.java index 97ea20b2e20..553504a7862 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/replanning/TimeWindowUpperBoundMutator.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/replanning/TimeWindowUpperBoundMutator.java @@ -16,10 +16,10 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver.replanning; +package org.matsim.freight.receiver.replanning; import org.matsim.freight.carriers.TimeWindow; -import org.matsim.contrib.freightreceiver.ReceiverPlan; +import org.matsim.freight.receiver.ReceiverPlan; import org.matsim.core.gbl.MatsimRandom; import org.matsim.core.replanning.ReplanningContext; import org.matsim.core.replanning.modules.GenericPlanStrategyModule; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/run/chessboard/ReceiverChessboardParameters.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/run/chessboard/ReceiverChessboardParameters.java similarity index 94% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/run/chessboard/ReceiverChessboardParameters.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/run/chessboard/ReceiverChessboardParameters.java index b5b946942b0..327c65716d6 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/run/chessboard/ReceiverChessboardParameters.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/run/chessboard/ReceiverChessboardParameters.java @@ -16,9 +16,9 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver.run.chessboard; +package org.matsim.freight.receiver.run.chessboard; -import org.matsim.contrib.freightreceiver.ReceiverReplanningType; +import org.matsim.freight.receiver.ReceiverReplanningType; /** * Class to help with setting experimental parameters. These parameters are diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/run/chessboard/ReceiverChessboardScenario.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/run/chessboard/ReceiverChessboardScenario.java similarity index 98% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/run/chessboard/ReceiverChessboardScenario.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/run/chessboard/ReceiverChessboardScenario.java index b5b2f535b45..fd036695370 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/run/chessboard/ReceiverChessboardScenario.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/run/chessboard/ReceiverChessboardScenario.java @@ -18,7 +18,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver.run.chessboard; +package org.matsim.freight.receiver.run.chessboard; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -29,8 +29,8 @@ import org.matsim.api.core.v01.network.NetworkWriter; import org.matsim.freight.carriers.*; import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; -import org.matsim.contrib.freightreceiver.*; -import org.matsim.contrib.freightreceiver.collaboration.CollaborationUtils; +import org.matsim.freight.receiver.*; +import org.matsim.freight.receiver.collaboration.CollaborationUtils; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.ConfigWriter; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/run/chessboard/RunReceiverChessboardWithEqualProportionCost.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/run/chessboard/RunReceiverChessboardWithEqualProportionCost.java similarity index 93% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/run/chessboard/RunReceiverChessboardWithEqualProportionCost.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/run/chessboard/RunReceiverChessboardWithEqualProportionCost.java index 469f45574ee..4e7b9b2607a 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/run/chessboard/RunReceiverChessboardWithEqualProportionCost.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/run/chessboard/RunReceiverChessboardWithEqualProportionCost.java @@ -18,7 +18,7 @@ * *********************************************************************** */ -package org.matsim.contrib.freightreceiver.run.chessboard; +package org.matsim.freight.receiver.run.chessboard; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -26,9 +26,9 @@ import org.matsim.freight.carriers.CarriersUtils; import org.matsim.freight.carriers.Carriers; import org.matsim.freight.carriers.usecases.analysis.CarrierScoreStats; -import org.matsim.contrib.freightreceiver.ReceiverModule; -import org.matsim.contrib.freightreceiver.ReceiverReplanningType; -import org.matsim.contrib.freightreceiver.ReceiverUtils; +import org.matsim.freight.receiver.ReceiverModule; +import org.matsim.freight.receiver.ReceiverReplanningType; +import org.matsim.freight.receiver.ReceiverUtils; import org.matsim.core.controler.Controler; import org.matsim.core.controler.MatsimServices; diff --git a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/run/chessboard/RunReceiverChessboardWithFixedCarrierCost.java b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/run/chessboard/RunReceiverChessboardWithFixedCarrierCost.java similarity index 93% rename from contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/run/chessboard/RunReceiverChessboardWithFixedCarrierCost.java rename to contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/run/chessboard/RunReceiverChessboardWithFixedCarrierCost.java index 112785c45b8..2570eb80c16 100644 --- a/contribs/freightreceiver/src/main/java/org/matsim/contrib/freightreceiver/run/chessboard/RunReceiverChessboardWithFixedCarrierCost.java +++ b/contribs/freightreceiver/src/main/java/org/matsim/freight/receiver/run/chessboard/RunReceiverChessboardWithFixedCarrierCost.java @@ -18,7 +18,7 @@ * *********************************************************************** */ -package org.matsim.contrib.freightreceiver.run.chessboard; +package org.matsim.freight.receiver.run.chessboard; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -26,9 +26,9 @@ import org.matsim.freight.carriers.CarriersUtils; import org.matsim.freight.carriers.Carriers; import org.matsim.freight.carriers.usecases.analysis.CarrierScoreStats; -import org.matsim.contrib.freightreceiver.ReceiverModule; -import org.matsim.contrib.freightreceiver.ReceiverReplanningType; -import org.matsim.contrib.freightreceiver.ReceiverUtils; +import org.matsim.freight.receiver.ReceiverModule; +import org.matsim.freight.receiver.ReceiverReplanningType; +import org.matsim.freight.receiver.ReceiverUtils; import org.matsim.core.controler.Controler; import org.matsim.core.controler.MatsimServices; diff --git a/contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/ReceiverCostAllocationFixedTest.java b/contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/ReceiverCostAllocationFixedTest.java similarity index 88% rename from contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/ReceiverCostAllocationFixedTest.java rename to contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/ReceiverCostAllocationFixedTest.java index 8faf02fd1c0..4189a6e9779 100644 --- a/contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/ReceiverCostAllocationFixedTest.java +++ b/contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/ReceiverCostAllocationFixedTest.java @@ -1,4 +1,4 @@ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/ReceiverPlanTest.java b/contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/ReceiverPlanTest.java similarity index 97% rename from contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/ReceiverPlanTest.java rename to contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/ReceiverPlanTest.java index 9933bda39d7..ea784499f81 100644 --- a/contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/ReceiverPlanTest.java +++ b/contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/ReceiverPlanTest.java @@ -16,7 +16,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.matsim.api.core.v01.Id; diff --git a/contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/ReceiversReaderTest.java b/contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/ReceiversReaderTest.java similarity index 98% rename from contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/ReceiversReaderTest.java rename to contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/ReceiversReaderTest.java index 970641df24e..6a893a9409f 100644 --- a/contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/ReceiversReaderTest.java +++ b/contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/ReceiversReaderTest.java @@ -18,7 +18,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -26,7 +26,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.TimeWindow; -import org.matsim.contrib.freightreceiver.collaboration.CollaborationUtils; +import org.matsim.freight.receiver.collaboration.CollaborationUtils; import org.matsim.core.utils.misc.Time; import org.matsim.testcases.MatsimTestUtils; diff --git a/contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/ReceiversTest.java b/contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/ReceiversTest.java similarity index 97% rename from contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/ReceiversTest.java rename to contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/ReceiversTest.java index 35dbed33c31..8ca84ad87f8 100644 --- a/contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/ReceiversTest.java +++ b/contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/ReceiversTest.java @@ -1,11 +1,11 @@ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; 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.Id; import org.matsim.api.core.v01.Scenario; -import org.matsim.contrib.freightreceiver.run.chessboard.ReceiverChessboardScenario; +import org.matsim.freight.receiver.run.chessboard.ReceiverChessboardScenario; import org.matsim.testcases.MatsimTestUtils; import java.util.Collection; diff --git a/contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/ReceiversWriterTest.java b/contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/ReceiversWriterTest.java similarity index 96% rename from contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/ReceiversWriterTest.java rename to contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/ReceiversWriterTest.java index 34a66898d68..1f9a453ce08 100644 --- a/contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/ReceiversWriterTest.java +++ b/contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/ReceiversWriterTest.java @@ -18,13 +18,13 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; 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.contrib.freightreceiver.run.chessboard.ReceiverChessboardScenario; +import org.matsim.freight.receiver.run.chessboard.ReceiverChessboardScenario; import org.matsim.testcases.MatsimTestUtils; import java.io.File; diff --git a/contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/SSReorderPolicyTest.java b/contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/SSReorderPolicyTest.java similarity index 97% rename from contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/SSReorderPolicyTest.java rename to contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/SSReorderPolicyTest.java index 1841ae963fc..c22aea6a54b 100644 --- a/contribs/freightreceiver/src/test/java/org/matsim/contrib/freightreceiver/SSReorderPolicyTest.java +++ b/contribs/freightreceiver/src/test/java/org/matsim/freight/receiver/SSReorderPolicyTest.java @@ -18,7 +18,7 @@ * * * *********************************************************************** */ -package org.matsim.contrib.freightreceiver; +package org.matsim.freight.receiver; import org.junit.jupiter.api.Assertions; diff --git a/contribs/freightreceiver/test/input/org/matsim/contrib/freightreceiver/ReceiversReaderTest/receivers_v2_basic.xml b/contribs/freightreceiver/test/input/org/matsim/freight/receiver/ReceiversReaderTest/receivers_v2_basic.xml similarity index 100% rename from contribs/freightreceiver/test/input/org/matsim/contrib/freightreceiver/ReceiversReaderTest/receivers_v2_basic.xml rename to contribs/freightreceiver/test/input/org/matsim/freight/receiver/ReceiversReaderTest/receivers_v2_basic.xml diff --git a/contribs/freightreceiver/test/input/org/matsim/contrib/freightreceiver/ReceiversReaderTest/receivers_v2_full.xml b/contribs/freightreceiver/test/input/org/matsim/freight/receiver/ReceiversReaderTest/receivers_v2_full.xml similarity index 100% rename from contribs/freightreceiver/test/input/org/matsim/contrib/freightreceiver/ReceiversReaderTest/receivers_v2_full.xml rename to contribs/freightreceiver/test/input/org/matsim/freight/receiver/ReceiversReaderTest/receivers_v2_full.xml diff --git a/contribs/freightreceiver/test/input/org/matsim/contrib/freightreceiver/ReceiversTest/receivers_v2.xml b/contribs/freightreceiver/test/input/org/matsim/freight/receiver/ReceiversTest/receivers_v2.xml similarity index 100% rename from contribs/freightreceiver/test/input/org/matsim/contrib/freightreceiver/ReceiversTest/receivers_v2.xml rename to contribs/freightreceiver/test/input/org/matsim/freight/receiver/ReceiversTest/receivers_v2.xml diff --git a/contribs/hybridsim/pom.xml b/contribs/hybridsim/pom.xml index bed620d598d..7bb94a4feff 100644 --- a/contribs/hybridsim/pom.xml +++ b/contribs/hybridsim/pom.xml @@ -10,8 +10,8 @@ hybridsim - 4.28.0 - 1.66.0 + 4.28.3 + 1.68.1 diff --git a/contribs/informed-mode-choice/pom.xml b/contribs/informed-mode-choice/pom.xml index 04b54d402cb..d28005db983 100644 --- a/contribs/informed-mode-choice/pom.xml +++ b/contribs/informed-mode-choice/pom.xml @@ -16,7 +16,7 @@ org.matsim.contrib application - 2025.0-SNAPSHOT + ${project.parent.version} xerces diff --git a/contribs/integration/pom.xml b/contribs/integration/pom.xml index 05bc09e61a9..95a7a2dfd5c 100644 --- a/contribs/integration/pom.xml +++ b/contribs/integration/pom.xml @@ -80,7 +80,7 @@ org.matsim.contrib accessibility - 2025.0-SNAPSHOT + ${project.parent.version} org.geotools.jdbc @@ -90,18 +90,18 @@ org.matsim.contrib analysis - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib dvrp - 2025.0-SNAPSHOT + ${project.parent.version} test org.matsim.contrib drt - 2025.0-SNAPSHOT + ${project.parent.version} test diff --git a/contribs/locationchoice/pom.xml b/contribs/locationchoice/pom.xml index 955d0dd364c..33de35d8866 100644 --- a/contribs/locationchoice/pom.xml +++ b/contribs/locationchoice/pom.xml @@ -24,12 +24,12 @@ org.matsim.contrib otfvis - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib analysis - 2025.0-SNAPSHOT + ${project.parent.version} test diff --git a/contribs/minibus/pom.xml b/contribs/minibus/pom.xml index c9b6f4eb0fb..374288785e9 100644 --- a/contribs/minibus/pom.xml +++ b/contribs/minibus/pom.xml @@ -45,7 +45,7 @@ org.matsim matsim - 2025.0-SNAPSHOT + ${project.parent.version} diff --git a/contribs/minibus/src/main/java/org/matsim/contrib/minibus/hook/PVehiclesFactory.java b/contribs/minibus/src/main/java/org/matsim/contrib/minibus/hook/PVehiclesFactory.java index cca689ac56c..7069b4c3b0a 100644 --- a/contribs/minibus/src/main/java/org/matsim/contrib/minibus/hook/PVehiclesFactory.java +++ b/contribs/minibus/src/main/java/org/matsim/contrib/minibus/hook/PVehiclesFactory.java @@ -22,6 +22,7 @@ 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.TransportMode; import org.matsim.contrib.minibus.PConfigGroup; import org.matsim.pt.transitSchedule.api.Departure; import org.matsim.pt.transitSchedule.api.TransitLine; @@ -31,15 +32,15 @@ /** * Generates vehicles for a whole transit schedule - * + * * @author aneumann * */ class PVehiclesFactory { - + @SuppressWarnings("unused") private final static Logger log = LogManager.getLogger(PVehiclesFactory.class); - + private final PConfigGroup pConfig; public PVehiclesFactory(PConfigGroup pConfig) { @@ -48,11 +49,11 @@ public PVehiclesFactory(PConfigGroup pConfig) { /** * Create vehicles for each departure of the given transit schedule. - * + * * @return Vehicles used by paratranit lines */ - public Vehicles createVehicles(TransitSchedule pTransitSchedule){ - Vehicles vehicles = VehicleUtils.createVehiclesContainer(); + public Vehicles createVehicles(TransitSchedule pTransitSchedule){ + Vehicles vehicles = VehicleUtils.createVehiclesContainer(); VehiclesFactory vehFactory = vehicles.getFactory(); VehicleType vehType = vehFactory.createVehicleType(Id.create(this.pConfig.getPIdentifier(), VehicleType.class)); // VehicleCapacity capacity = new VehicleCapacity(); @@ -61,11 +62,12 @@ public Vehicles createVehicles(TransitSchedule pTransitSchedule){ // vehType.setCapacity(capacity); vehType.setPcuEquivalents(this.pConfig.getPassengerCarEquivalents()); vehType.setMaximumVelocity(this.pConfig.getVehicleMaximumVelocity()); + vehType.setNetworkMode(TransportMode.car); VehicleUtils.setAccessTime(vehType, this.pConfig.getDelayPerBoardingPassenger()); VehicleUtils.setEgressTime(vehType, this.pConfig.getDelayPerAlightingPassenger()); VehicleUtils.setDoorOperationMode(vehType, this.pConfig.getDoorOperationMode()) ; vehicles.addVehicleType( vehType); - + for (TransitLine line : pTransitSchedule.getTransitLines().values()) { for (TransitRoute route : line.getRoutes().values()) { for (Departure departure : route.getDepartures().values()) { @@ -76,7 +78,7 @@ public Vehicles createVehicles(TransitSchedule pTransitSchedule){ } } } - + return vehicles; } } diff --git a/contribs/multimodal/src/main/java/org/matsim/contrib/multimodal/RunMultimodalExample.java b/contribs/multimodal/src/main/java/org/matsim/contrib/multimodal/RunMultimodalExample.java index 6f1d5b48b0c..879c3d9dca5 100644 --- a/contribs/multimodal/src/main/java/org/matsim/contrib/multimodal/RunMultimodalExample.java +++ b/contribs/multimodal/src/main/java/org/matsim/contrib/multimodal/RunMultimodalExample.java @@ -26,8 +26,6 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.controler.Controler; -import org.matsim.core.controler.ControlerUtils; -import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.core.scenario.ScenarioUtils; /** diff --git a/contribs/noise/pom.xml b/contribs/noise/pom.xml index ac1c5fbd32b..920c9b58606 100644 --- a/contribs/noise/pom.xml +++ b/contribs/noise/pom.xml @@ -13,7 +13,7 @@ org.matsim.contrib analysis - 2025.0-SNAPSHOT + ${project.parent.version} diff --git a/contribs/noise/src/main/java/org/matsim/contrib/noise/Grid.java b/contribs/noise/src/main/java/org/matsim/contrib/noise/Grid.java index 6815899be8a..48eb2951430 100644 --- a/contribs/noise/src/main/java/org/matsim/contrib/noise/Grid.java +++ b/contribs/noise/src/main/java/org/matsim/contrib/noise/Grid.java @@ -268,19 +268,32 @@ private void setActivityCoord2NearestReceiverPointId () { counter.printCounter(); counter = new Counter("compute nearest receiver-points #"); + Counter otherCounter = new Counter("activities outside grid #"); for (Coord coord : consideredActivityCoordsForSpatialFunctionality) { // TODO maybe add a check here so we consider only the rp in the 9 surrounding cells? - ReceiverPoint rp = qTree.getClosest(coord.getX(), coord.getY()); - if(rp != null) { - if(activityCoord2receiverPointId.put(coord, rp.getId()) != null){ - log.warn("this must not happen"); + // ts, nov' 24: ---> might be done by the following filtering (by grid) ?? + + // Filter activity coords that are within the quadTree. + // I do not know, why whe put a buffer around the grid when instantiating the QuadTree, above, but I'll keep it for now + // tschlenther, nov '24 + if (coord.getX() >= xCoordMin && coord.getX() <= xCoordMax && + coord.getY() >= yCoordMin && coord.getY() <= yCoordMax){ + + ReceiverPoint rp = qTree.getClosest(coord.getX(), coord.getY()); + if(rp != null) { + if(activityCoord2receiverPointId.put(coord, rp.getId()) != null){ + log.warn("this must not happen"); + } } - } - counter.incCounter(); + counter.incCounter(); + } else { + otherCounter.incCounter(); + } } counter.printCounter(); + otherCounter.printCounter(); } private void readReceiverPoints(String file, CoordinateTransformation ct) throws IOException { 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 06e793c85d9..c2c9bc8d039 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 @@ -26,6 +26,7 @@ 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.TransportMode; import org.matsim.api.core.v01.network.Link; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigGroup; @@ -134,9 +135,9 @@ public enum NoiseAllocationApproach { private NoiseAllocationApproach noiseAllocationApproach = NoiseAllocationApproach.AverageCost; private String[] hgvIdPrefixes = {"lkw", "truck", "freight"}; + private Set networkModesToIgnore = CollectionUtils.stringArrayToSet( new String[]{TransportMode.bike, TransportMode.walk, TransportMode.transit_walk, TransportMode.non_network_walk} ); private Set busIdIdentifier = new HashSet<>(); private Set> tunnelLinkIDs = new HashSet<>(); - private Set networkModesToIgnore = new HashSet<>(); private double noiseTollFactor = 1.0; @@ -209,7 +210,7 @@ public Map getComments() { comments.put(USE_DEM, "Set to 'true' if a DEM (digital elevation model) should be used for road gradients. Otherwise set to 'false'."); comments.put(DEM_FILE, "Path to the geoTiff file of the DEM."); - comments.put(NETWORK_MODES_TO_IGNORE, "Specifies the network modes to be excluded from the noise computation, e.g. 'bike'."); + comments.put(NETWORK_MODES_TO_IGNORE, "Specifies the network modes to be excluded from the noise computation. By default, the following modes are excluded: [bike, walk, transit_walk, non_network_walk]."); comments.put(NOISE_COMPUTATION_METHOD, "Specifies the computation method of different guidelines: " + Arrays.toString(NoiseComputationMethod.values())); @@ -313,6 +314,37 @@ private void checkNoiseParametersForConsistency(Config config) { this.considerNoiseBarriers = false; } } + + List walkAndBikeModes = List.of(TransportMode.bike, TransportMode.walk, TransportMode.transit_walk, TransportMode.non_network_walk); + String exclude = "["; + for (String mode : walkAndBikeModes){ + exclude += mode + ","; + } + exclude = exclude.substring(0, exclude.lastIndexOf(',')) + "]"; + String warning = "You should set networkModesToIgnore such that all of the standard walk and bike modes are included!" + + " These are " + exclude + "."; + if (this.networkModesToIgnore.isEmpty() || + ! this.networkModesToIgnore.containsAll(walkAndBikeModes)){ + boolean bikeOrWalkIsNetworkMode = config.routing().getNetworkModes().stream() + .filter(networkMode -> networkModesToIgnore.contains(networkMode)) + .findAny() + .isPresent(); + if (bikeOrWalkIsNetworkMode){ + //TODO: use enum for consistencyCheckLevel and replace all RunTimeExceptions thrown within this class. + throw new RuntimeException(warning + " You configured one of these modes as networkMode in config().routing.getNetworkModes()! This will lead to wrong results!" + + "Make sure ignore all network modes that do not model a car, a heavy-goods-vehicle (HGV) or a transit vehicle to be considered by the noise analysis!!! Will abort now..."); + } else { + log.warn( warning + + " Otherwise, your results will turn wrong as soon as you are routing these modes on the network (which luckily appears not to be the case in your current setup)."); + } + } + + Set defaultHGVIdPrefixes = Set.of("lkw", "truck", "freight"); + + if (! defaultHGVIdPrefixes.stream().allMatch(defaultPrefix -> + Arrays.stream(this.hgvIdPrefixes).anyMatch(prefix -> defaultPrefix.equals(prefix)))){ + log.warn("You are not considering all of [lkw, truck, freight] as HGV prefixes, which you should! Especially when you use scenarios created by VSP!!"); + } } // ######################################################################################################## diff --git a/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseContextImpl.java b/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseContextImpl.java index d941615320a..bad61d3696c 100644 --- a/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseContextImpl.java +++ b/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseContextImpl.java @@ -201,9 +201,9 @@ private void checkConsistency() { || this.grid.getGridParams().getReceiverPointsGridMinX() != 0. || this.grid.getGridParams().getReceiverPointsGridMaxY() != 0. || this.grid.getGridParams().getReceiverPointsGridMinY() != 0.) { - log.warn("In order to keep track of the agent activities, the grid of receiver points should not be limited to a set of predefined coordinates." + log.warn("In order to keep track of ALL the agent activities, the grid of receiver points should not be limited to a set of predefined coordinates." + "For a grid covering all activity locations, set the minimum and maximum x/y parameters to 0.0. " - + "There will be more agents mapped to the receiver points at the edges. Only the inner receiver points should be used for analysis."); + + "Damages will be computed only for activities that are performed within the receiver point grid."); } if (this.grid.getGridParams().getReceiverPointsGridMinX() == 0. && this.grid.getGridParams().getReceiverPointsGridMinY() == 0. && this.grid.getGridParams().getReceiverPointsGridMaxX() == 0. && this.grid.getGridParams().getReceiverPointsGridMaxY() == 0.) { diff --git a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/LinkProperties.java b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/LinkProperties.java index 41d2b302d37..6d8ddbac9c8 100644 --- a/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/LinkProperties.java +++ b/contribs/osm/src/main/java/org/matsim/contrib/osm/networkReader/LinkProperties.java @@ -18,6 +18,7 @@ public class LinkProperties { public static final int LEVEL_UNCLASSIFIED = 6; public static final int LEVEL_RESIDENTIAL = 7; public static final int LEVEL_LIVING_STREET = 8; + public static final int LEVEL_PATH = 9; /** * Assume for links with max speed lower than 51km/h to be in urban areas. diff --git a/contribs/parking/pom.xml b/contribs/parking/pom.xml index f6d4bbf3c76..8dd4d6c1af9 100644 --- a/contribs/parking/pom.xml +++ b/contribs/parking/pom.xml @@ -12,17 +12,17 @@ org.matsim.contrib multimodal - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib otfvis - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib dvrp - 2025.0-SNAPSHOT + ${project.parent.version} diff --git a/contribs/pom.xml b/contribs/pom.xml index c8b2dd3620c..ae36adaea70 100644 --- a/contribs/pom.xml +++ b/contribs/pom.xml @@ -115,14 +115,14 @@ org.matsim matsim - ${project.version} + ${project.parent.version} jar compile org.matsim matsim - ${project.version} + ${project.parent.version} test-jar test @@ -133,7 +133,7 @@ org.matsim matsim-examples test - ${project.version} + ${project.parent.version} diff --git a/contribs/protobuf/pom.xml b/contribs/protobuf/pom.xml index 1a56905386a..53542aa2494 100644 --- a/contribs/protobuf/pom.xml +++ b/contribs/protobuf/pom.xml @@ -11,7 +11,7 @@ protobuf - 4.28.2 + 4.28.3 diff --git a/contribs/pseudosimulation/pom.xml b/contribs/pseudosimulation/pom.xml index 9d9ec4449f2..dbb6f00a75e 100644 --- a/contribs/pseudosimulation/pom.xml +++ b/contribs/pseudosimulation/pom.xml @@ -13,7 +13,7 @@ org.matsim.contrib common - 2025.0-SNAPSHOT + ${project.parent.version} commons-cli diff --git a/contribs/shared_mobility/pom.xml b/contribs/shared_mobility/pom.xml index d97630a3c64..24edfc4a3ce 100644 --- a/contribs/shared_mobility/pom.xml +++ b/contribs/shared_mobility/pom.xml @@ -16,12 +16,12 @@ org.matsim matsim-examples - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib common - 2025.0-SNAPSHOT + ${project.parent.version} diff --git a/contribs/signals/pom.xml b/contribs/signals/pom.xml index 15dc9962de4..23d03270960 100644 --- a/contribs/signals/pom.xml +++ b/contribs/signals/pom.xml @@ -22,12 +22,12 @@ org.matsim matsim-examples - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib otfvis - 2025.0-SNAPSHOT + ${project.parent.version} compile diff --git a/contribs/simulatedannealing/pom.xml b/contribs/simulatedannealing/pom.xml index fbe7ed06b54..a3a2688d16e 100644 --- a/contribs/simulatedannealing/pom.xml +++ b/contribs/simulatedannealing/pom.xml @@ -16,7 +16,7 @@ org.matsim.contrib common - 2025.0-SNAPSHOT + ${project.parent.version} diff --git a/contribs/simwrapper/pom.xml b/contribs/simwrapper/pom.xml index 499bf95af87..cf59db1d70d 100644 --- a/contribs/simwrapper/pom.xml +++ b/contribs/simwrapper/pom.xml @@ -16,7 +16,7 @@ org.matsim.contrib application - 2025.0-SNAPSHOT + ${project.parent.version} @@ -55,7 +55,7 @@ org.matsim.contrib vsp - 2025.0-SNAPSHOT + ${project.parent.version} test diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/DefaultDashboardProvider.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/DefaultDashboardProvider.java index a01674f4856..5cb80fec839 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/DefaultDashboardProvider.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/DefaultDashboardProvider.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Set; /** * Default dashboards suited for every run. @@ -19,7 +20,7 @@ public List getDashboards(Config config, SimWrapper simWrapper) { List result = new ArrayList<>(List.of( new OverviewDashboard(), new TripDashboard(), - new TrafficDashboard() + new TrafficDashboard(Set.copyOf(config.qsim().getMainModes())) )); if (config.transit().isUseTransit()) { diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/OverviewDashboard.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/OverviewDashboard.java index ef29484258b..0d5f54ca8e9 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/OverviewDashboard.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/OverviewDashboard.java @@ -58,7 +58,7 @@ public void configure(Header header, Layout layout) { }); layout.row("config").el(XML.class, (viz, data) -> { - viz.file = data.output("*.output_config.xml"); + viz.file = data.output("(*.)?output_config.xml"); viz.height = 6d; viz.width = 2d; viz.unfoldLevel = 1; @@ -66,7 +66,7 @@ public void configure(Header header, Layout layout) { }).el(PieChart.class, (viz, data) -> { viz.title = "Mode Share"; viz.description = "at final Iteration"; - viz.dataset = data.output("*.modestats.csv"); + viz.dataset = data.output("(*.)?modestats.csv"); viz.ignoreColumns = List.of("iteration"); viz.useLastRow = true; }); @@ -75,7 +75,7 @@ public void configure(Header header, Layout layout) { layout.row("second").el(Line.class, (viz, data) -> { viz.title = "Score"; - viz.dataset = data.output("*.scorestats.csv"); + viz.dataset = data.output("(*.)?scorestats.csv"); viz.description = "per Iteration"; viz.x = "iteration"; viz.columns = List.of("avg_executed", "avg_worst", "avg_best"); @@ -88,7 +88,7 @@ public void configure(Header header, Layout layout) { .el(Area.class, (viz, data) -> { viz.title = "Mode Share Progression"; viz.description = "per Iteration"; - viz.dataset = data.output("*.modestats.csv"); + viz.dataset = data.output("(*.)?modestats.csv"); viz.x = "iteration"; viz.xAxisName = "Iteration"; viz.yAxisName = "Share"; diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/PublicTransitDashboard.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/PublicTransitDashboard.java index 6903902d098..50960fbaffe 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/PublicTransitDashboard.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/PublicTransitDashboard.java @@ -1,28 +1,51 @@ package org.matsim.simwrapper.dashboard; +import org.matsim.application.analysis.pt.PublicTransitAnalysis; +import org.matsim.application.prepare.network.CreateAvroNetwork; import org.matsim.simwrapper.Dashboard; import org.matsim.simwrapper.Header; import org.matsim.simwrapper.Layout; import org.matsim.simwrapper.viz.TransitViewer; +import java.util.ArrayList; +import java.util.List; + /** * Standard dashboard for public transit. */ public class PublicTransitDashboard implements Dashboard { + private List customRouteTypes = new ArrayList<>(); + + /** + * Add custom route types to the transit viewer. + */ + public PublicTransitDashboard withCustomRouteTypes(TransitViewer.CustomRouteType... custom) { + customRouteTypes.addAll(List.of(custom)); + return this; + } + @Override public void configure(Header header, Layout layout) { header.title = "Public Transit"; header.tab = "PT"; - header.triggerPattern = "*output_transitSchedule*xml*"; + header.triggerPattern = "(*.)?output_transitSchedule*xml*"; layout.row("viewer").el(TransitViewer.class, (viz, data) -> { viz.title = "Transit Viewer"; viz.height = 12d; viz.description = "Visualize the transit schedule."; - viz.network = "*output_network.xml.gz"; - viz.transitSchedule = data.output("*output_transitSchedule.xml.gz"); + + // Include a network that has not been filtered + viz.network = data.withContext("all").compute(CreateAvroNetwork.class, "network.avro", + "--mode-filter", "", "--shp", "none"); + + viz.transitSchedule = data.output("(*.)?output_transitSchedule.xml.gz"); + viz.ptStop2stopFile = data.compute(PublicTransitAnalysis.class, "pt_pax_volumes.csv.gz"); + + if (!customRouteTypes.isEmpty()) + viz.customRouteTypes = customRouteTypes; }); } } diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/TripDashboard.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/TripDashboard.java index 7603da2b791..34c5f1ba1c3 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/TripDashboard.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/TripDashboard.java @@ -247,7 +247,7 @@ public void configure(Header header, Layout layout) { .el(Plotly.class, (viz, data) -> { viz.title = "Mode usage"; - viz.description = "Share of persons using a main mode at least once per day."; + viz.description = "Share of persons using a main mode at least once per day"; viz.width = 2d; Plotly.DataSet ds = viz.addDataset(data.compute(TripAnalysis.class, "mode_users.csv")); @@ -267,6 +267,11 @@ public void configure(Header header, Layout layout) { viz.mergeDatasets = true; } + }).el(Sankey.class, (viz, data) -> { + viz.title = "Mode shift"; + viz.width = 1.5d; + viz.description = "by main mode. Compares initial input with output after the last iteration"; + viz.csv = data.compute(TripAnalysis.class, "mode_shift.csv", args); }); createDistancePlot(layout, args, tab); diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/viz/TransitViewer.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/viz/TransitViewer.java index ff9e8176b60..bf32176b9ab 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/viz/TransitViewer.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/viz/TransitViewer.java @@ -2,6 +2,8 @@ import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + /** * Transit viewer for pt schedules. */ @@ -13,7 +15,58 @@ public class TransitViewer extends Viz { @JsonProperty(required = true) public String transitSchedule; + @JsonProperty + public String ptStop2stopFile; + + public List customRouteTypes; + public TransitViewer() { super("transit"); } + + public static CustomRouteType customRouteType(String label, String color) { + return new CustomRouteType(label, color); + } + + public static class CustomRouteType { + public String label; + public String color; + public Boolean hide; + Match match; + + private CustomRouteType(String label, String color) { + this.label = label; + this.color = color; + } + + public CustomRouteType addMatchTransportMode(String... transportMode) { + if (match == null) + match = new Match(); + + match.transportMode = transportMode; + return this; + } + + public CustomRouteType addMatchId(String... id) { + if (match == null) + match = new Match(); + + match.id = id; + return this; + } + + public CustomRouteType addMatchGtfsRouteType(Integer... gtfsRouteType) { + if (match == null) + match = new Match(); + + match.gtfsRouteType = gtfsRouteType; + return this; + } + } + + private static class Match { + Object transportMode; + Object id; + Object gtfsRouteType; + } } diff --git a/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/DashboardTests.java b/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/DashboardTests.java index 7818cd4c190..e3e92fa87a7 100644 --- a/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/DashboardTests.java +++ b/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/DashboardTests.java @@ -13,6 +13,7 @@ import org.matsim.simwrapper.SimWrapper; import org.matsim.simwrapper.SimWrapperConfigGroup; import org.matsim.simwrapper.TestScenario; +import org.matsim.simwrapper.viz.TransitViewer; import org.matsim.testcases.MatsimTestUtils; import tech.tablesaw.api.Table; import tech.tablesaw.io.csv.CsvReadOptions; @@ -28,7 +29,7 @@ public class DashboardTests { private void run(Dashboard... dashboards) { Config config = TestScenario.loadConfig(utils); - config.controller().setLastIteration(2); + config.controller().setLastIteration(1); SimWrapperConfigGroup group = ConfigUtils.addOrGetModule(config, SimWrapperConfigGroup.class); group.sampleSize = 0.001; @@ -42,39 +43,29 @@ private void run(Dashboard... dashboards) { controler.run(); } + @Test void defaults() { - Path out = Path.of(utils.getOutputDirectory(), "analysis", "population"); + Path out = Path.of(utils.getOutputDirectory(), "analysis"); run(); // Ensure default dashboards have been added Assertions.assertThat(out) - .isDirectoryContaining("glob:**stuck_agents.csv"); - } - - @Test - void stuckAgents() { - - Path out = Path.of(utils.getOutputDirectory(), "analysis", "population"); - - run(new StuckAgentDashboard()); - - Assertions.assertThat(out) - .isDirectoryContaining("glob:**stuck_agents.csv"); - - } - - @Test - void trip() { - - Path out = Path.of(utils.getOutputDirectory(), "analysis", "population"); - - run(new TripDashboard()); - Assertions.assertThat(out) - .isDirectoryContaining("glob:**trip_stats.csv") - .isDirectoryContaining("glob:**mode_share.csv"); + // Stuck agents + .isDirectoryRecursivelyContaining("glob:**stuck_agents.csv") + // Trip stats + .isDirectoryRecursivelyContaining("glob:**trip_stats.csv") + .isDirectoryRecursivelyContaining("glob:**mode_share.csv") + .isDirectoryRecursivelyContaining("glob:**mode_share_per_purpose.csv") + .isDirectoryRecursivelyContaining("glob:**mode_shift.csv") + // Traffic stats + .isDirectoryRecursivelyContaining("glob:**traffic_stats_by_link_daily.csv") + .isDirectoryRecursivelyContaining("glob:**traffic_stats_by_road_type_and_hour.csv") + .isDirectoryRecursivelyContaining("glob:**traffic_stats_by_road_type_daily.csv") + // PT + .isDirectoryRecursivelyContaining("glob:**pt_pax_volumes.csv.gz"); } @Test @@ -126,21 +117,6 @@ void populationAttribute() { .isDirectoryContaining("glob:**total_agents.csv"); - } - - @Test - void traffic() { - - Path out = Path.of(utils.getOutputDirectory(), "analysis", "traffic"); - - run(new TrafficDashboard()); - - Assertions.assertThat(out) - .isDirectoryContaining("glob:**traffic_stats_by_link_daily.csv") - .isDirectoryContaining("glob:**traffic_stats_by_road_type_and_hour.csv") - .isDirectoryContaining("glob:**traffic_stats_by_road_type_daily.csv"); - - } @Test @@ -156,4 +132,25 @@ void odTrips() { } + @Test + void ptCustom() { + PublicTransitDashboard pt = new PublicTransitDashboard(); + + // bus + TransitViewer.CustomRouteType crt = TransitViewer.customRouteType("Bus", "#109192"); + crt.addMatchGtfsRouteType(3); + + // rail + TransitViewer.CustomRouteType crtRail = TransitViewer.customRouteType("Rail", "#EC0016"); + crtRail.addMatchGtfsRouteType(2); + + pt.withCustomRouteTypes(crt, crtRail); + + run(pt); + + Path out = Path.of(utils.getOutputDirectory(), "analysis", "pt"); + + Assertions.assertThat(out) + .isDirectoryContaining("glob:**pt_pax_volumes.csv.gz"); + } } 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 a4ce705e001..178bfa9109f 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 @@ -1,5 +1,6 @@ package org.matsim.simwrapper.dashboard; +import com.opencsv.CSVReader; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -15,6 +16,7 @@ import org.matsim.testcases.MatsimTestUtils; +import java.io.FileReader; import java.net.URL; import java.nio.file.Path; @@ -51,6 +53,19 @@ void generate() { .isDirectoryContaining("glob:**damages_receiverPoint_per_day.avro") .isDirectoryContaining("glob:**noise_stats.csv"); - //TODO check content / values of the files + double totalDamages; + double totalImmissions; + try { + CSVReader reader = new CSVReader(new FileReader(utils.getOutputDirectory() + "analysis/noise/noise_stats.csv")); + reader.skip(1); + totalDamages = Double.parseDouble(reader.readNext()[1]); + totalImmissions = Double.parseDouble(reader.readNext()[1]); + } catch (Exception e) { + throw new RuntimeException(e); + } + + Assertions.assertThat(totalDamages == 3573114.25); + Assertions.assertThat( totalImmissions == 2.688); + } } diff --git a/contribs/small-scale-traffic-generation/pom.xml b/contribs/small-scale-traffic-generation/pom.xml index 46ea6a80936..07314d16da1 100644 --- a/contribs/small-scale-traffic-generation/pom.xml +++ b/contribs/small-scale-traffic-generation/pom.xml @@ -15,13 +15,13 @@ org.matsim.contrib application - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib freight - 2025.0-SNAPSHOT + ${project.parent.version} diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/DefaultUnhandledServicesSolution.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/DefaultUnhandledServicesSolution.java new file mode 100644 index 00000000000..735a2d8f44a --- /dev/null +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/DefaultUnhandledServicesSolution.java @@ -0,0 +1,143 @@ +package org.matsim.smallScaleCommercialTrafficGeneration; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Scenario; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.CarrierService; +import org.matsim.freight.carriers.CarrierVehicle; +import org.matsim.freight.carriers.CarriersUtils; + +import java.util.*; +import java.util.concurrent.ExecutionException; + +public class DefaultUnhandledServicesSolution implements UnhandledServicesSolution { + private static final Logger log = LogManager.getLogger(DefaultUnhandledServicesSolution.class); + + // Generation data + Random rnd; + private final GenerateSmallScaleCommercialTrafficDemand generator; + + DefaultUnhandledServicesSolution(GenerateSmallScaleCommercialTrafficDemand generator){ + rnd = MatsimRandom.getRandom(); + this.generator = generator; + } + + public List createListOfCarrierWithUnhandledJobs(Scenario scenario){ + List carriersWithUnhandledJobs = new LinkedList<>(); + for (Carrier carrier : CarriersUtils.getCarriers(scenario).getCarriers().values()) { + if (!CarriersUtils.allJobsHandledBySelectedPlan(carrier)) + carriersWithUnhandledJobs.add(carrier); + } + + return carriersWithUnhandledJobs; + } + + /** + * Redraws the service-durations of all {@link CarrierService}s of the given {@link Carrier}. + */ + private void redrawAllServiceDurations(Carrier carrier, GenerateSmallScaleCommercialTrafficDemand.CarrierAttributes carrierAttributes, int additionalTravelBufferPerIterationInMinutes) { + for (CarrierService service : carrier.getServices().values()) { + double newServiceDuration = generator.getServiceTimePerStop(carrier, carrierAttributes, additionalTravelBufferPerIterationInMinutes); + CarrierService redrawnService = CarrierService.Builder.newInstance(service.getId(), service.getLocationLinkId()) + .setServiceDuration(newServiceDuration).setServiceStartTimeWindow(service.getServiceStartTimeWindow()).build(); + carrier.getServices().put(redrawnService.getId(), redrawnService); + } + } + + @Override + public void tryToSolveAllCarriersCompletely(Scenario scenario, List nonCompleteSolvedCarriers) { + int startNumberOfCarriersWithUnhandledJobs = nonCompleteSolvedCarriers.size(); + log.info("Starting with carrier-replanning loop."); + for (int i = 0; i < generator.getMaxReplanningIterations(); i++) { + log.info("carrier-replanning loop iteration: {}", i); + int numberOfCarriersWithUnhandledJobs = nonCompleteSolvedCarriers.size(); + for (Carrier nonCompleteSolvedCarrier : nonCompleteSolvedCarriers) { + //Delete old plan of carrier + nonCompleteSolvedCarrier.clearPlans(); + GenerateSmallScaleCommercialTrafficDemand.CarrierAttributes carrierAttributes = generator.getCarrierId2carrierAttributes().get(nonCompleteSolvedCarrier.getId()); + + // Generate new services. The new service batch should have a smaller sum of serviceDurations than before (or otherwise it will not change anything) + redrawAllServiceDurations(nonCompleteSolvedCarrier, carrierAttributes, (i + 1) * generator.getAdditionalTravelBufferPerIterationInMinutes()); + log.info("Carrier should be changed..."); + } + try { + CarriersUtils.runJsprit(scenario, CarriersUtils.CarrierSelectionForSolution.solveOnlyForCarrierWithoutPlans); + } catch (ExecutionException | InterruptedException e) { + throw new RuntimeException(e); + } + + + nonCompleteSolvedCarriers = createListOfCarrierWithUnhandledJobs(scenario); + log.info( + "End of carrier-replanning loop iteration: {}. From the {} carriers with unhandled jobs ({} already solved), {} were solved in this iteration with an additionalBuffer of {} minutes.", + i, startNumberOfCarriersWithUnhandledJobs, startNumberOfCarriersWithUnhandledJobs - numberOfCarriersWithUnhandledJobs, + numberOfCarriersWithUnhandledJobs - nonCompleteSolvedCarriers.size(), (i + 1) * generator.getAdditionalTravelBufferPerIterationInMinutes()); + if (nonCompleteSolvedCarriers.isEmpty()) break; + } + + // Final check + if (!nonCompleteSolvedCarriers.isEmpty()) { + log.warn("Not all services were handled!"); + } + } + + /** + * Change the service duration for a given carrier, because the service could not be handled in the last solution. + * + * @param carrier The carrier for which we generate the serviceTime + * @param carrierAttributes attributes of the carrier to generate the service time for. + * @param key key for the service duration + * @param additionalTravelBufferPerIterationInMinutes additional buffer for the travel time + * @return new service duration + */ + @Override + public int changeServiceTimePerStop(Carrier carrier, GenerateSmallScaleCommercialTrafficDemand.CarrierAttributes carrierAttributes, + GenerateSmallScaleCommercialTrafficDemand.ServiceDurationPerCategoryKey key, + int additionalTravelBufferPerIterationInMinutes) { + + double maxVehicleAvailability = carrier.getCarrierCapabilities().getCarrierVehicles().values().stream().mapToDouble(vehicle -> vehicle.getLatestEndTime() - vehicle.getEarliestStartTime()).max().orElse(0); + int usedTravelTimeBuffer = additionalTravelBufferPerIterationInMinutes * 60; // buffer for the driving time; for unsolved carriers the buffer will be increased over time + for (int j = 0; j < 200; j++) { + if (generator.getServiceDurationTimeSelector().get(key) == null) { + System.out.println("key: " + key); + System.out.println(generator.getServiceDurationTimeSelector().keySet()); + throw new RuntimeException("No service duration found for employee category '" + carrierAttributes.selectedStartCategory() + "' and mode '" + + carrierAttributes.modeORvehType() + "' in traffic type '" + carrierAttributes.smallScaleCommercialTrafficType() + "'"); + } + GenerateSmallScaleCommercialTrafficDemand.DurationsBounds serviceDurationBounds = generator.getServiceDurationTimeSelector().get(key).sample(); + + for (int i = 0; i < 10; i++) { + int serviceDurationLowerBound = serviceDurationBounds.minDuration(); + int serviceDurationUpperBound = serviceDurationBounds.maxDuration(); + int possibleValue = rnd.nextInt(serviceDurationLowerBound * 60, serviceDurationUpperBound * 60); + // checks if the service duration will not exceed the vehicle availability including the buffer + if (possibleValue + usedTravelTimeBuffer <= maxVehicleAvailability) + return possibleValue; + } + if (j > 100){ + CarrierVehicle carrierVehicleToChange = carrier.getCarrierCapabilities().getCarrierVehicles().values().stream().sorted(Comparator.comparingDouble(vehicle -> vehicle.getLatestEndTime() - vehicle.getEarliestStartTime())).toList().getFirst(); + log.info("Changing vehicle availability for carrier {}. Old maxVehicleAvailability: {}", carrier.getId(), maxVehicleAvailability); + int tourDuration = 0; + int vehicleStartTime = 0; + int vehicleEndTime = 0; + while (tourDuration < maxVehicleAvailability) { + GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration t = generator.getTourDistribution().get(carrierAttributes.smallScaleCommercialTrafficType()).sample(); + vehicleStartTime = t.getVehicleStartTime(); + tourDuration = t.getVehicleTourDuration(); + vehicleEndTime = vehicleStartTime + tourDuration; + } + CarrierVehicle newCarrierVehicle = CarrierVehicle.Builder.newInstance(carrierVehicleToChange.getId(), carrierVehicleToChange.getLinkId(), + carrierVehicleToChange.getType()).setEarliestStart(vehicleStartTime).setLatestEnd(vehicleEndTime).build(); + carrier.getCarrierCapabilities().getCarrierVehicles().remove(carrierVehicleToChange.getId()); + carrier.getCarrierCapabilities().getCarrierVehicles().put(newCarrierVehicle.getId(), newCarrierVehicle); + maxVehicleAvailability = carrier.getCarrierCapabilities().getCarrierVehicles().values().stream().mapToDouble(vehicle -> vehicle.getLatestEndTime() - vehicle.getEarliestStartTime()).max().orElse(0); + log.info("New maxVehicleAvailability: {}", maxVehicleAvailability); + } + } + + throw new RuntimeException("No possible service duration found for employee category '" + carrierAttributes.selectedStartCategory() + "' and mode '" + + carrierAttributes.modeORvehType() + "' in traffic type '" + carrierAttributes.smallScaleCommercialTrafficType() + "'"); + } +} diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/DefaultVehicleSelection.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/DefaultVehicleSelection.java new file mode 100644 index 00000000000..c6221d61515 --- /dev/null +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/DefaultVehicleSelection.java @@ -0,0 +1,82 @@ +package org.matsim.smallScaleCommercialTrafficGeneration; + +import java.util.ArrayList; +import java.util.List; + +public class DefaultVehicleSelection implements VehicleSelection{ + @Override + public List getAllCategories() { + ArrayList categories = new ArrayList<>(7); + categories.add("Employee Primary Sector"); + categories.add("Employee Construction"); + categories.add("Employee Secondary Sector Rest"); + categories.add("Employee Retail"); + categories.add("Employee Traffic/Parcels"); + categories.add("Employee Tertiary Sector Rest"); + categories.add("Inhabitants"); + return categories; + } + + + @Override + public OdMatrixEntryInformation getOdMatrixEntryInformation(int purpose, String modeORvehType, String smallScaleCommercialTrafficType) { + VehicleSelection.OdMatrixEntryInformation information = new OdMatrixEntryInformation(); + information.occupancyRate = 0; + information.possibleVehicleTypes = null; + information.possibleStartCategories = new ArrayList<>(); + information.possibleStopCategories = new ArrayList<>(getAllCategories()); + + if (purpose == 1) { + if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic")) { + information.possibleVehicleTypes = new String[]{"vwCaddy", "e_SpaceTourer"}; + information.occupancyRate = 1.5; + } + information.possibleStartCategories.add("Employee Secondary Sector Rest"); + information.possibleStopCategories.clear(); + information.possibleStopCategories.add("Employee Secondary Sector Rest"); + } else if (purpose == 2) { + if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic")) { + information.possibleVehicleTypes = new String[]{"vwCaddy", "e_SpaceTourer"}; + information.occupancyRate = 1.6; + } + information.possibleStartCategories.add("Employee Secondary Sector Rest"); + } else if (purpose == 3) { + if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic")) { + information.possibleVehicleTypes = new String[]{"golf1.4", "c_zero"}; + information.occupancyRate = 1.2; + } + information.possibleStartCategories.add("Employee Retail"); + information.possibleStartCategories.add("Employee Tertiary Sector Rest"); + } else if (purpose == 4) { + if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic")) { + information.possibleVehicleTypes = new String[]{"golf1.4", "c_zero"}; + information.occupancyRate = 1.2; + } + information.possibleStartCategories.add("Employee Traffic/Parcels"); + } else if (purpose == 5) { + if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic")) { + information.possibleVehicleTypes = new String[]{"mercedes313", "e_SpaceTourer"}; + information.occupancyRate = 1.7; + } + information.possibleStartCategories.add("Employee Construction"); + } else if (purpose == 6) { + information.possibleStartCategories.add("Inhabitants"); + } + + if (smallScaleCommercialTrafficType.equals("goodsTraffic")) { + information.occupancyRate = 1.; + switch (modeORvehType) { + case "vehTyp1" -> + information.possibleVehicleTypes = new String[]{"vwCaddy", "e_SpaceTourer"}; // possible to add more types, see source + case "vehTyp2" -> + information.possibleVehicleTypes = new String[]{"mercedes313", "e_SpaceTourer"}; + case "vehTyp3", "vehTyp4" -> + information.possibleVehicleTypes = new String[]{"light8t", "light8t_electro"}; + case "vehTyp5" -> + information.possibleVehicleTypes = new String[]{"medium18t", "medium18t_electro", "heavy40t", "heavy40t_electro"}; + } + } + + return information; + } +} 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 af8fbacf479..c3aa017dc39 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 @@ -17,6 +17,7 @@ * See also COPYING, LICENSE and WARRANTY file * * * * *********************************************************************** */ + package org.matsim.smallScaleCommercialTrafficGeneration; import com.google.inject.Inject; @@ -68,11 +69,11 @@ import org.matsim.core.utils.geometry.CoordinateTransformation; import org.matsim.facilities.ActivityFacility; import org.matsim.freight.carriers.*; -import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; -import org.matsim.freight.carriers.controler.*; +import org.matsim.freight.carriers.analysis.RunFreightAnalysisEventBased; +import org.matsim.freight.carriers.controller.*; import org.matsim.freight.carriers.usecases.chessboard.CarrierTravelDisutilities; +import org.matsim.smallScaleCommercialTrafficGeneration.data.CommercialTourSpecifications; 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; @@ -94,7 +95,6 @@ * * @author Ricardo Ewert */ -//TODO: use EnumeratedDistribution for distributions with probabilities @CommandLine.Command(name = "generate-small-scale-commercial-traffic", description = "Generates plans for a small scale commercial traffic model", showDefaultValues = true) public class GenerateSmallScaleCommercialTrafficDemand implements MATSimAppCommand { // freight traffic from extern: @@ -108,7 +108,9 @@ public class GenerateSmallScaleCommercialTrafficDemand implements MATSimAppComma private static final Logger log = LogManager.getLogger(GenerateSmallScaleCommercialTrafficDemand.class); private final IntegrateExistingTrafficToSmallScaleCommercial integrateExistingTrafficToSmallScaleCommercial; - private final GetCommercialTourSpecifications getCommercialTourSpecifications; + private final CommercialTourSpecifications commercialTourSpecifications; + private final VehicleSelection vehicleSelection; + private final UnhandledServicesSolution unhandledServicesSolution; private enum CreationOption { useExistingCarrierFileWithSolution, createNewCarrierFile, useExistingCarrierFileWithoutSolution @@ -136,6 +138,12 @@ public enum SmallScaleCommercialTrafficType { @CommandLine.Option(names = "--jspritIterations", description = "Set number of jsprit iterations", required = true) private int jspritIterations; + @CommandLine.Option(names = "--additionalTravelBufferPerIterationInMinutes", description = "This buffer/driving time is used for service-route-planning. If set too low, carriers may not serve all their services.", defaultValue = "10") + private int additionalTravelBufferPerIterationInMinutes; + + @CommandLine.Option(names = "--maxReplanningIterations", description = "Limit of carrier replanning iterations, where carriers with unhandled services get new plans. If your carrier-plans are still not fully served, increase this limit.", defaultValue = "100") + private int maxReplanningIterations; + @CommandLine.Option(names = "--creationOption", description = "Set option of mode differentiation: useExistingCarrierFileWithSolution, createNewCarrierFile, useExistingCarrierFileWithoutSolution") private CreationOption usedCreationOption; @@ -169,19 +177,32 @@ public enum SmallScaleCommercialTrafficType { @CommandLine.Option(names = "--pathOutput", description = "Path for the output") private Path output; - private Random rnd; + private static Random rnd; private RandomGenerator rng; private final Map>> facilitiesPerZone = new HashMap<>(); + private final Map, CarrierAttributes> carrierId2carrierAttributes = new HashMap<>(); + + private Map> tourDistribution = null; + private Map> serviceDurationTimeSelector = null; + + private TripDistributionMatrix odMatrix; + private Map> resultingDataPerZone; + private Map, Link>> linksPerZone; private Index indexZones; public GenerateSmallScaleCommercialTrafficDemand() { this.integrateExistingTrafficToSmallScaleCommercial = new DefaultIntegrateExistingTrafficToSmallScaleCommercialImpl(); log.info("Using default {} if existing models are integrated!", DefaultIntegrateExistingTrafficToSmallScaleCommercialImpl.class.getSimpleName()); - this.getCommercialTourSpecifications = new DefaultTourSpecificationsByUsingKID2002(); + this.commercialTourSpecifications = new DefaultTourSpecificationsByUsingKID2002(); log.info("Using default {} for tour specifications!", DefaultTourSpecificationsByUsingKID2002.class.getSimpleName()); + this.vehicleSelection = new DefaultVehicleSelection(); + log.info("Using default {} for tour vehicle-selection!", DefaultVehicleSelection.class.getSimpleName()); + this.unhandledServicesSolution = new DefaultUnhandledServicesSolution(this); + log.info("Using default {} for tour unhandled-services-solution!", DefaultUnhandledServicesSolution.class.getSimpleName()); } - public GenerateSmallScaleCommercialTrafficDemand(IntegrateExistingTrafficToSmallScaleCommercial integrateExistingTrafficToSmallScaleCommercial, GetCommercialTourSpecifications getCommercialTourSpecifications) { + + public GenerateSmallScaleCommercialTrafficDemand(IntegrateExistingTrafficToSmallScaleCommercial integrateExistingTrafficToSmallScaleCommercial, CommercialTourSpecifications getCommercialTourSpecifications, VehicleSelection vehicleSelection, UnhandledServicesSolution unhandledServicesSolution) { if (integrateExistingTrafficToSmallScaleCommercial == null){ this.integrateExistingTrafficToSmallScaleCommercial = new DefaultIntegrateExistingTrafficToSmallScaleCommercialImpl(); log.info("Using default {} if existing models are integrated!", DefaultIntegrateExistingTrafficToSmallScaleCommercialImpl.class.getSimpleName()); @@ -190,12 +211,26 @@ public GenerateSmallScaleCommercialTrafficDemand(IntegrateExistingTrafficToSmall log.info("Using {} if existing models are integrated!", integrateExistingTrafficToSmallScaleCommercial.getClass().getSimpleName()); } if (getCommercialTourSpecifications == null){ - this.getCommercialTourSpecifications = new DefaultTourSpecificationsByUsingKID2002(); + this.commercialTourSpecifications = new DefaultTourSpecificationsByUsingKID2002(); log.info("Using default {} for tour specifications!", DefaultTourSpecificationsByUsingKID2002.class.getSimpleName()); } else { - this.getCommercialTourSpecifications = getCommercialTourSpecifications; + this.commercialTourSpecifications = getCommercialTourSpecifications; log.info("Using {} for tour specifications!", getCommercialTourSpecifications.getClass().getSimpleName()); } + if (vehicleSelection == null){ + this.vehicleSelection = new DefaultVehicleSelection(); + log.info("Using default {} for tour vehicle-selection!", DefaultVehicleSelection.class.getSimpleName()); + } else { + this.vehicleSelection = vehicleSelection; + log.info("Using {} for tour vehicle-selection!", vehicleSelection.getClass().getSimpleName()); + } + if (unhandledServicesSolution == null){ + this.unhandledServicesSolution = new DefaultUnhandledServicesSolution(this); + log.info("Using default {} for unhandled-services-solution", DefaultUnhandledServicesSolution.class.getSimpleName()); + } else { + this.unhandledServicesSolution = unhandledServicesSolution; + log.info("Using {} for unhandled-services-solution!", unhandledServicesSolution.getClass().getSimpleName()); + } } public static void main(String[] args) { @@ -243,7 +278,7 @@ public Integer call() throws Exception { readVehicleTypes.keySet().removeIf(vehicleType -> !usedCarrierVehicleTypes.contains(vehicleType)); if (Objects.requireNonNull(usedCreationOption) == CreationOption.useExistingCarrierFileWithoutSolution) { - solveSeparatedVRPs(scenario, null); + solveSeparatedVRPs(scenario); } } default -> { @@ -252,20 +287,20 @@ public Integer call() throws Exception { } indexZones = SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, shapeCRS, shapeFileZoneNameColumn); - Map> resultingDataPerZone = readDataDistribution(pathToDataDistributionToZones); + resultingDataPerZone = readDataDistribution(pathToDataDistributionToZones); filterFacilitiesForZones(scenario, facilitiesPerZone); - Map, Link>> linksPerZone = filterLinksForZones(scenario, indexZones, facilitiesPerZone, shapeFileZoneNameColumn); + linksPerZone = filterLinksForZones(scenario, indexZones, facilitiesPerZone, shapeFileZoneNameColumn); switch (usedSmallScaleCommercialTrafficType) { case commercialPersonTraffic, goodsTraffic -> - createCarriersAndDemand(output, scenario, resultingDataPerZone, linksPerZone, + createCarriersAndDemand(output, scenario, usedSmallScaleCommercialTrafficType.toString(), includeExistingModels); case completeSmallScaleCommercialTraffic -> { - createCarriersAndDemand(output, scenario, resultingDataPerZone, linksPerZone, "commercialPersonTraffic", + createCarriersAndDemand(output, scenario, "commercialPersonTraffic", includeExistingModels); includeExistingModels = false; // because already included in the step before - createCarriersAndDemand(output, scenario, resultingDataPerZone, linksPerZone, "goodsTraffic", + createCarriersAndDemand(output, scenario, "goodsTraffic", includeExistingModels); } default -> throw new RuntimeException("No traffic type selected."); @@ -277,7 +312,7 @@ public Integer call() throws Exception { new CarrierPlanWriter(CarriersUtils.addOrGetCarriers(scenario)) .write(scenario.getConfig().controller().getOutputDirectory() + "/" + scenario.getConfig().controller().getRunId() + ".output_CarrierDemand.xml"); - solveSeparatedVRPs(scenario, linksPerZone); + solveSeparatedVRPs(scenario); } } if (config.controller().getRunId() == null) @@ -298,13 +333,21 @@ public Integer call() throws Exception { controler.run(); + //Analysis + System.out.println("Starting Analysis for Carriers of small scale commercial traffic."); + //TODO perhaps change to complete carrier analysis + RunFreightAnalysisEventBased freightAnalysis = new RunFreightAnalysisEventBased(CarriersUtils.addOrGetCarriers(scenario), output.resolve("CarrierAnalysis").toString()); + freightAnalysis.runCarriersAnalysis(); + System.out.println("Finishing Analysis of Carrier."); + SmallScaleCommercialTrafficUtils.createPlansBasedOnCarrierPlans(controler.getScenario(), usedSmallScaleCommercialTrafficType.toString(), output, modelName, sampleName, nameOutputPopulation, numberOfPlanVariantsPerAgent); return 0; } - /** Creates a map with the different facility types per building. + /** + * Creates a map with the different facility types per building. * @param scenario complete Scenario * @param facilitiesPerZone Map with facilities per zone */ @@ -318,11 +361,13 @@ private void filterFacilitiesForZones(Scenario scenario, Map, Link>> linksPerZone) throws Exception { - + private void solveSeparatedVRPs(Scenario originalScenario) throws Exception { boolean splitCarrier = true; boolean splitVRPs = false; int maxServicesPerCarrier = 100; @@ -330,6 +375,7 @@ private void solveSeparatedVRPs(Scenario originalScenario, Map, Carrier> solvedCarriers = new HashMap<>(); List> keyList = new ArrayList<>(allCarriers.keySet()); + Map, List>> carrierId2subCarrierIds = new HashMap<>(); CarriersUtils.getCarriers(originalScenario).getCarriers().values().forEach(carrier -> { if (CarriersUtils.getJspritIterations(carrier) == 0) { allCarriers.remove(carrier.getId()); @@ -389,6 +435,9 @@ private void solveSeparatedVRPs(Scenario originalScenario, Map newCarrier.getAttributes() .putAttribute(attribute, carrier.getAttributes().getAttribute(attribute))); + carrierId2subCarrierIds.putIfAbsent(carrier.getId(), new LinkedList<>()); + carrierId2subCarrierIds.get(carrier.getId()).add(newCarrier.getId()); + List> vehiclesForNewCarrier = new ArrayList<>( carrier.getCarrierCapabilities().getCarrierVehicles().keySet()); List> servicesForNewCarrier = new ArrayList<>( @@ -428,9 +477,21 @@ private void solveSeparatedVRPs(Scenario originalScenario, Map oldCarrierId : carrierId2subCarrierIds.keySet()) { + for (Id newCarrierId : carrierId2subCarrierIds.get(oldCarrierId)) { + if (carrierId2carrierAttributes.putIfAbsent(newCarrierId, carrierId2carrierAttributes.get(oldCarrierId)) != null) + throw new Exception("CarrierAttributes already exist for the carrier " + newCarrierId.toString()); + } + } + log.info("Solving carriers {}-{} of all {} carriers. This are {} VRP to solve.", fromIndex + 1, toIndex, allCarriers.size(), subCarriers.size()); CarriersUtils.runJsprit(originalScenario); + List nonCompleteSolvedCarriers = unhandledServicesSolution.createListOfCarrierWithUnhandledJobs(originalScenario); + if (!nonCompleteSolvedCarriers.isEmpty()) + unhandledServicesSolution.tryToSolveAllCarriersCompletely(originalScenario, nonCompleteSolvedCarriers); solvedCarriers.putAll(CarriersUtils.getCarriers(originalScenario).getCarriers()); CarriersUtils.getCarriers(originalScenario).getCarriers().clear(); if (!splitVRPs) @@ -453,10 +514,8 @@ private void solveSeparatedVRPs(Scenario originalScenario, Map> resultingDataPerZone, - Map, Link>> linksPerZone, String smallScaleCommercialTrafficType, + String smallScaleCommercialTrafficType, boolean includeExistingModels) throws Exception { - ArrayList modesORvehTypes; if (smallScaleCommercialTrafficType.equals("goodsTraffic")) modesORvehTypes = new ArrayList<>( @@ -478,16 +537,15 @@ else if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic")) integrateExistingTrafficToSmallScaleCommercial.reduceDemandBasedOnExistingCarriers(scenario, linksPerZone, smallScaleCommercialTrafficType, trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop); } - final TripDistributionMatrix odMatrix = createTripDistribution(trafficVolumePerTypeAndZone_start, - trafficVolumePerTypeAndZone_stop, smallScaleCommercialTrafficType, scenario, output, linksPerZone); - createCarriers(scenario, odMatrix, resultingDataPerZone, smallScaleCommercialTrafficType, linksPerZone); + odMatrix = createTripDistribution(trafficVolumePerTypeAndZone_start, + trafficVolumePerTypeAndZone_stop, smallScaleCommercialTrafficType, scenario, output); + createCarriers(scenario, smallScaleCommercialTrafficType); } /** * Reads and checks config if all necessary parameters are set. */ private Config readAndCheckConfig(Path configPath, String modelName, String sampleName, Path output) throws Exception { - Config config = ConfigUtils.loadConfig(configPath.toString()); if (output == null || output.toString().isEmpty()) config.controller().setOutputDirectory(Path.of(config.controller().getOutputDirectory()).resolve(modelName) @@ -559,18 +617,22 @@ public void install() { /** * Creates the carriers and the related demand, based on the generated * TripDistributionMatrix. + * @param scenario Scenario (loaded from your config), where the carriers will be put into + * @param smallScaleCommercialTrafficType Selected traffic types. Options: commercialPersonTraffic, goodsTraffic */ - private void createCarriers(Scenario scenario, TripDistributionMatrix odMatrix, - Map> resultingDataPerZone, String smallScaleCommercialTrafficType, - Map, Link>> linksPerZone) { + public void createCarriers(Scenario scenario, + String smallScaleCommercialTrafficType) { + //Save the given data + RandomGenerator rng = new MersenneTwister(scenario.getConfig().global().getRandomSeed()); + int maxNumberOfCarrier = odMatrix.getListOfPurposes().size() * odMatrix.getListOfZones().size() * odMatrix.getListOfModesOrVehTypes().size(); int createdCarrier = 0; int fixedNumberOfVehiclePerTypeAndLocation = 1; //TODO possible improvement, perhaps check KiD - EnumeratedDistribution tourDistribution = getCommercialTourSpecifications.createTourDistribution(smallScaleCommercialTrafficType, rng); + tourDistribution = commercialTourSpecifications.createTourDistribution(rng); - Map> stopDurationTimeSelector = getCommercialTourSpecifications.createStopDurationDistributionPerCategory(smallScaleCommercialTrafficType, rng); + serviceDurationTimeSelector = commercialTourSpecifications.createStopDurationDistributionPerCategory(rng); CarrierVehicleTypes carrierVehicleTypes = CarriersUtils.getCarrierVehicleTypes(scenario); Map, VehicleType> additionalCarrierVehicleTypes = scenario.getVehicles().getVehicleTypes(); @@ -589,6 +651,8 @@ private void createCarriers(Scenario scenario, TripDistributionMatrix odMatrix, for (Integer purpose : odMatrix.getListOfPurposes()) { for (String startZone : odMatrix.getListOfZones()) { for (String modeORvehType : odMatrix.getListOfModesOrVehTypes()) { + + // Check if this purpose, startZone, modeORvehType combination is a possiblr starting location (by looking if it has a trip-distribution-entry) boolean isStartingLocation = false; checkIfIsStartingPosition: { @@ -601,87 +665,44 @@ private void createCarriers(Scenario scenario, TripDistributionMatrix odMatrix, } } } - //TODO make vehcile selection configurable + if (isStartingLocation) { - double occupancyRate = 0; - String[] possibleVehicleTypes = null; - ArrayList startCategory = new ArrayList<>(); - ArrayList stopCategory = new ArrayList<>(); - stopCategory.add("Employee Primary Sector"); - stopCategory.add("Employee Construction"); - stopCategory.add("Employee Secondary Sector Rest"); - stopCategory.add("Employee Retail"); - stopCategory.add("Employee Traffic/Parcels"); - stopCategory.add("Employee Tertiary Sector Rest"); - stopCategory.add("Inhabitants"); - if (purpose == 1) { - if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic")) { - possibleVehicleTypes = new String[]{"vwCaddy", "e_SpaceTourer"}; - occupancyRate = 1.5; - } - startCategory.add("Employee Secondary Sector Rest"); - stopCategory.clear(); - stopCategory.add("Employee Secondary Sector Rest"); - } else if (purpose == 2) { - if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic")) { - possibleVehicleTypes = new String[]{"vwCaddy", "e_SpaceTourer"}; - occupancyRate = 1.6; - } - startCategory.add("Employee Secondary Sector Rest"); - } else if (purpose == 3) { - if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic")) { - possibleVehicleTypes = new String[]{"golf1.4", "c_zero"}; - occupancyRate = 1.2; - } - startCategory.add("Employee Retail"); - startCategory.add("Employee Tertiary Sector Rest"); - } else if (purpose == 4) { - if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic")) { - possibleVehicleTypes = new String[]{"golf1.4", "c_zero"}; - occupancyRate = 1.2; - } - startCategory.add("Employee Traffic/Parcels"); - } else if (purpose == 5) { - if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic")) { - possibleVehicleTypes = new String[]{"mercedes313", "e_SpaceTourer"}; - occupancyRate = 1.7; - } - startCategory.add("Employee Construction"); - } else if (purpose == 6) { - startCategory.add("Inhabitants"); - } - if (smallScaleCommercialTrafficType.equals("goodsTraffic")) { - occupancyRate = 1.; - switch (modeORvehType) { - case "vehTyp1" -> - possibleVehicleTypes = new String[]{"vwCaddy", "e_SpaceTourer"}; // possible to add more types, see source - case "vehTyp2" -> - possibleVehicleTypes = new String[]{"mercedes313", "e_SpaceTourer"}; - case "vehTyp3", "vehTyp4" -> - possibleVehicleTypes = new String[]{"light8t", "light8t_electro"}; - case "vehTyp5" -> - possibleVehicleTypes = new String[]{"medium18t", "medium18t_electro", "heavy40t", "heavy40t_electro"}; - } - } + // Get the vehicle-types and start/stop-categories + VehicleSelection.OdMatrixEntryInformation odMatrixEntry = vehicleSelection.getOdMatrixEntryInformation(purpose, modeORvehType, smallScaleCommercialTrafficType); // use only types of the possibleTypes which are in the given types file List vehicleTypes = new ArrayList<>(); - assert possibleVehicleTypes != null; + assert odMatrixEntry.possibleVehicleTypes != null; - for (String possibleVehicleType : possibleVehicleTypes) { + for (String possibleVehicleType : odMatrixEntry.possibleVehicleTypes) { if (CarriersUtils.getCarrierVehicleTypes(scenario).getVehicleTypes().containsKey( Id.create(possibleVehicleType, VehicleType.class))) vehicleTypes.add(possibleVehicleType); } - // find a start category with existing employees in this zone - Collections.shuffle(startCategory, rnd); - String selectedStartCategory = startCategory.getFirst(); + + Collections.shuffle(odMatrixEntry.possibleStartCategories, rnd); + String selectedStartCategory = odMatrixEntry.possibleStartCategories.getFirst(); + // Find a (random) start category with existing employees in this zone + // we start with count = 1 because the first category is already selected, and if this category has employees, we can use it. + // Otherwise, we have to find another category. for (int count = 1; resultingDataPerZone.get(startZone).getDouble(selectedStartCategory) == 0; count++) { - if (count <= startCategory.size()) - selectedStartCategory = startCategory.get(rnd.nextInt(startCategory.size())); - else - selectedStartCategory = stopCategory.get(rnd.nextInt(stopCategory.size())); + if (count < odMatrixEntry.possibleStartCategories.size()) + selectedStartCategory = odMatrixEntry.possibleStartCategories.get(count); + else { + // if no possible start category with employees is found, take a random category of the stop categories, + // the reason that no start category with employees is found is that traffic volume for employees in general is created, + // so that it is possible that we have traffic, although we have no employees in the given start category. + // That's why we exclude Inhabitants as a possible start category. + selectedStartCategory = odMatrixEntry.possibleStopCategories.get(rnd.nextInt(odMatrixEntry.possibleStopCategories.size())); + if (selectedStartCategory.equals("Inhabitants")) + selectedStartCategory = odMatrixEntry.possibleStopCategories.get(rnd.nextInt(odMatrixEntry.possibleStopCategories.size())); + if (resultingDataPerZone.get(startZone).getDouble(selectedStartCategory) > 0) + log.warn("No possible start category with employees found for zone {}. Take a random category of the stop categories: {}. The possible start categories are: {}", + startZone, selectedStartCategory, odMatrixEntry.possibleStartCategories); + } } + + // Generate carrierName String carrierName = null; if (smallScaleCommercialTrafficType.equals("goodsTraffic")) { carrierName = "Carrier_Goods_" + startZone + "_purpose_" + purpose + "_" + modeORvehType; @@ -689,94 +710,123 @@ private void createCarriers(Scenario scenario, TripDistributionMatrix odMatrix, carrierName = "Carrier_Business_" + startZone + "_purpose_" + purpose; int numberOfDepots = odMatrix.getSumOfServicesForStartZone(startZone, modeORvehType, purpose, smallScaleCommercialTrafficType); - FleetSize fleetSize = FleetSize.FINITE; + + // Create the Carrier + CarrierCapabilities.FleetSize fleetSize = CarrierCapabilities.FleetSize.FINITE; ArrayList vehicleDepots = new ArrayList<>(); createdCarrier++; log.info("Create carrier number {} of a maximum Number of {} carriers.", createdCarrier, maxNumberOfCarrier); log.info("Carrier: {}; depots: {}; services: {}", carrierName, numberOfDepots, (int) Math.ceil(odMatrix.getSumOfServicesForStartZone(startZone, modeORvehType, - purpose, smallScaleCommercialTrafficType) / occupancyRate)); - createNewCarrierAndAddVehicleTypes(scenario, purpose, startZone, - selectedStartCategory, carrierName, vehicleTypes, numberOfDepots, fleetSize, - fixedNumberOfVehiclePerTypeAndLocation, vehicleDepots, linksPerZone, smallScaleCommercialTrafficType, - tourDistribution); - log.info("Create services for carrier: {}", carrierName); - for (String stopZone : odMatrix.getListOfZones()) { - int trafficVolumeForOD = Math.round((float)odMatrix.getTripDistributionValue(startZone, - stopZone, modeORvehType, purpose, smallScaleCommercialTrafficType)); - int numberOfJobs = (int) Math.ceil(trafficVolumeForOD / occupancyRate); - if (numberOfJobs == 0) - continue; - // find a category for the tour stop with existing employees in this zone - String selectedStopCategory = stopCategory.get(rnd.nextInt(stopCategory.size())); - while (resultingDataPerZone.get(stopZone).getDouble(selectedStopCategory) == 0) - selectedStopCategory = stopCategory.get(rnd.nextInt(stopCategory.size())); - String[] serviceArea = new String[]{stopZone}; - int serviceTimePerStop; - if (selectedStartCategory.equals("Inhabitants")) - serviceTimePerStop = getServiceTimePerStop(stopDurationTimeSelector, startCategory.getFirst(), modeORvehType, smallScaleCommercialTrafficType); - else - serviceTimePerStop = getServiceTimePerStop(stopDurationTimeSelector, selectedStartCategory, modeORvehType, smallScaleCommercialTrafficType); - - TimeWindow serviceTimeWindow = TimeWindow.newInstance(0, - 24 * 3600); //TODO eventuell anpassen wegen veränderter Tourzeiten - createServices(scenario, vehicleDepots, selectedStopCategory, carrierName, - numberOfJobs, serviceArea, serviceTimePerStop, serviceTimeWindow, linksPerZone); - } - } - } - } - } + purpose, smallScaleCommercialTrafficType) / odMatrixEntry.occupancyRate)); -// System.out.println("Final results for the start time distribution"); -// tourStartTimeSelector.writeResults(); + CarrierAttributes carrierAttributes = new CarrierAttributes(purpose, startZone, selectedStartCategory, modeORvehType, + smallScaleCommercialTrafficType, vehicleDepots, odMatrixEntry); + if(carrierId2carrierAttributes.putIfAbsent(Id.create(carrierName, Carrier.class), carrierAttributes) != null) + throw new RuntimeException("CarrierAttributes already exist for the carrier " + carrierName); -// System.out.println("Final results for the tour duration distribution"); -// tourDurationTimeSelector.writeResults(); + createNewCarrierAndAddVehicleTypes(scenario, carrierName, carrierAttributes, vehicleTypes, numberOfDepots, fleetSize, + fixedNumberOfVehiclePerTypeAndLocation); -// for (StopDurationGoodTrafficKey sector : stopDurationTimeSelector.keySet()) { -// System.out.println("Final results for the stop duration distribution in sector " + sector); -// stopDurationTimeSelector.get(sector); -// } + // Now Create services for this carrier + Carrier newCarrier = CarriersUtils.getCarriers(scenario).getCarriers().get(Id.create(carrierName, Carrier.class)); + createServices(newCarrier, carrierAttributes); + } + } + } + } log.warn("The jspritIterations are now set to {} in this simulation!", jspritIterations); log.info("Finished creating {} carriers including related services.", createdCarrier); } /** - * Creates the services for one carrier. + * Generates and adds the services for the given carrier. */ - private void createServices(Scenario scenario, ArrayList noPossibleLinks, - String selectedStopCategory, String carrierName, int numberOfJobs, String[] serviceArea, - Integer serviceTimePerStop, TimeWindow serviceTimeWindow, - Map, Link>> linksPerZone) { + private void createServices(Carrier newCarrier, CarrierAttributes carrierAttributes) { + log.info("Create services for carrier: {}", newCarrier.getId()); + for (String stopZone : odMatrix.getListOfZones()) { + int trafficVolumeForOD = Math.round((float)odMatrix.getTripDistributionValue(carrierAttributes.startZone, + stopZone, carrierAttributes.modeORvehType, carrierAttributes.purpose, carrierAttributes.smallScaleCommercialTrafficType)); + int numberOfJobs = (int) Math.ceil(trafficVolumeForOD / carrierAttributes.odMatrixEntry.occupancyRate); + if (numberOfJobs == 0) + continue; + // find a category for the tour stop with existing employees in this zone + String selectedStopCategory = carrierAttributes.odMatrixEntry.possibleStopCategories.get(rnd.nextInt(carrierAttributes.odMatrixEntry.possibleStopCategories.size())); + while (resultingDataPerZone.get(stopZone).getDouble(selectedStopCategory) == 0) + selectedStopCategory = carrierAttributes.odMatrixEntry.possibleStopCategories.get(rnd.nextInt(carrierAttributes.odMatrixEntry.possibleStopCategories.size())); + for (int i = 0; i < numberOfJobs; i++) { + // additionalTravelBufferPerIterationInMinutes is only used for recalculation of the service time if a carrier solution could not handle all services + int serviceTimePerStop = getServiceTimePerStop(newCarrier, carrierAttributes, 0); + + TimeWindow serviceTimeWindow = TimeWindow.newInstance(0, 36 * 3600); // extended time window, so that late tours can handle it + createService(newCarrier, carrierAttributes.vehicleDepots, selectedStopCategory, stopZone, serviceTimePerStop, serviceTimeWindow); + } + } + } - String stopZone = serviceArea[0]; + /** + * Give a service duration based on the purpose and the trafficType under a given probability + * + * @param carrier The carrier for which the service time should be calculated + * @param carrierAttributes The attributes of the carrier + * @param additionalTravelBufferPerIterationInMinutes Additional travel buffer per recalculation iteration for a carrier in minutes + * @return The service time in seconds + */ + public Integer getServiceTimePerStop(Carrier carrier, GenerateSmallScaleCommercialTrafficDemand.CarrierAttributes carrierAttributes, + int additionalTravelBufferPerIterationInMinutes) { + GenerateSmallScaleCommercialTrafficDemand.ServiceDurationPerCategoryKey key; + // we use the start category for the service time selection because the start category represents the employees + if (carrierAttributes.smallScaleCommercialTrafficType().equals( + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { + if (!carrierAttributes.odMatrixEntry().possibleStartCategories.contains(carrierAttributes.selectedStartCategory())) + key = GenerateSmallScaleCommercialTrafficDemand.makeServiceDurationPerCategoryKey(carrierAttributes.odMatrixEntry().possibleStartCategories.get(rnd.nextInt(carrierAttributes.odMatrixEntry().possibleStartCategories.size())), null, carrierAttributes.smallScaleCommercialTrafficType()); + else + key = GenerateSmallScaleCommercialTrafficDemand.makeServiceDurationPerCategoryKey(carrierAttributes.selectedStartCategory(), null, + carrierAttributes.smallScaleCommercialTrafficType()); + } + else if (carrierAttributes.smallScaleCommercialTrafficType().equals( + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString())) { + key = GenerateSmallScaleCommercialTrafficDemand.makeServiceDurationPerCategoryKey(carrierAttributes.selectedStartCategory(), + carrierAttributes.modeORvehType(), carrierAttributes.smallScaleCommercialTrafficType()); + } else { + throw new RuntimeException("Unknown traffic type: " + carrierAttributes.smallScaleCommercialTrafficType()); + } + // additionalTravelBufferPerIterationInMinutes is only used for recalculation of the service time if a carrier solution could not handle all services + if (additionalTravelBufferPerIterationInMinutes == 0) { + GenerateSmallScaleCommercialTrafficDemand.DurationsBounds serviceDurationBounds = serviceDurationTimeSelector.get(key).sample(); - for (int i = 0; i < numberOfJobs; i++) { + int serviceDurationLowerBound = serviceDurationBounds.minDuration(); + int serviceDurationUpperBound = serviceDurationBounds.maxDuration(); + return rnd.nextInt(serviceDurationLowerBound * 60, serviceDurationUpperBound * 60); + } else { + return unhandledServicesSolution.changeServiceTimePerStop(carrier, carrierAttributes, key, additionalTravelBufferPerIterationInMinutes); + } + } - Id linkId = findPossibleLink(stopZone, selectedStopCategory, noPossibleLinks, linksPerZone); - Id idNewService = Id.create(carrierName + "_" + linkId + "_" + rnd.nextInt(10000), - CarrierService.class); + /** + * Adds a service with the given attributes to the carrier. + */ + private void createService(Carrier newCarrier, ArrayList noPossibleLinks, String selectedStopCategory, String stopZone, + Integer serviceTimePerStop, TimeWindow serviceTimeWindow) { - CarrierService thisService = CarrierService.Builder.newInstance(idNewService, linkId) - .setServiceDuration(serviceTimePerStop).setServiceStartTimeWindow(serviceTimeWindow).build(); - CarriersUtils.getCarriers(scenario).getCarriers().get(Id.create(carrierName, Carrier.class)).getServices() - .put(thisService.getId(), thisService); - } + Id linkId = findPossibleLink(stopZone, selectedStopCategory, noPossibleLinks); + Id idNewService = Id.create(newCarrier.getId().toString() + "_" + linkId + "_" + rnd.nextInt(10000), + CarrierService.class); + CarrierService thisService = CarrierService.Builder.newInstance(idNewService, linkId) + .setServiceDuration(serviceTimePerStop).setServiceStartTimeWindow(serviceTimeWindow).build(); + newCarrier.getServices().put(thisService.getId(), thisService); } + + /** * Creates the carrier and the related vehicles. */ - private void createNewCarrierAndAddVehicleTypes(Scenario scenario, Integer purpose, String startZone, - String selectedStartCategory, String carrierName, - List vehicleTypes, int numberOfDepots, FleetSize fleetSize, - int fixedNumberOfVehiclePerTypeAndLocation, - List vehicleDepots, Map, Link>> linksPerZone, - String smallScaleCommercialTrafficType, - EnumeratedDistribution tourStartTimeSelector) { + private void createNewCarrierAndAddVehicleTypes(Scenario scenario, String carrierName, CarrierAttributes carrierAttributes, + List vehicleTypes, int numberOfDepots, CarrierCapabilities.FleetSize fleetSize, + int fixedNumberOfVehiclePerTypeAndLocation) { Carriers carriers = CarriersUtils.addOrGetCarriers(scenario); CarrierVehicleTypes carrierVehicleTypes = CarriersUtils.getCarrierVehicleTypes(scenario); @@ -784,28 +834,28 @@ private void createNewCarrierAndAddVehicleTypes(Scenario scenario, Integer purpo CarrierCapabilities carrierCapabilities; Carrier thisCarrier = CarriersUtils.createCarrier(Id.create(carrierName, Carrier.class)); - if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic") && purpose == 3) - thisCarrier.getAttributes().putAttribute("subpopulation", smallScaleCommercialTrafficType + "_service"); + if (carrierAttributes.smallScaleCommercialTrafficType.equals("commercialPersonTraffic") && carrierAttributes.purpose == 3) + thisCarrier.getAttributes().putAttribute("subpopulation", carrierAttributes.smallScaleCommercialTrafficType + "_service"); else - thisCarrier.getAttributes().putAttribute("subpopulation", smallScaleCommercialTrafficType); + thisCarrier.getAttributes().putAttribute("subpopulation", carrierAttributes.smallScaleCommercialTrafficType); - thisCarrier.getAttributes().putAttribute("purpose", purpose); - thisCarrier.getAttributes().putAttribute("tourStartArea", startZone); + thisCarrier.getAttributes().putAttribute("purpose", carrierAttributes.purpose); + thisCarrier.getAttributes().putAttribute("tourStartArea", carrierAttributes.startZone); if (jspritIterations > 0) CarriersUtils.setJspritIterations(thisCarrier, jspritIterations); carrierCapabilities = CarrierCapabilities.Builder.newInstance().setFleetSize(fleetSize).build(); + carriers.addCarrier(thisCarrier); - while (vehicleDepots.size() < numberOfDepots) { - Id linkId = findPossibleLink(startZone, selectedStartCategory, null, linksPerZone); - vehicleDepots.add(linkId.toString()); + while (carrierAttributes.vehicleDepots.size() < numberOfDepots) { + Id linkId = findPossibleLink(carrierAttributes.startZone, carrierAttributes.selectedStartCategory, null); + carrierAttributes.vehicleDepots.add(linkId.toString()); } - for (String singleDepot : vehicleDepots) { - TourStartAndDuration t = tourStartTimeSelector.sample(); - - int vehicleStartTime = getVehicleStartTime(t); - int tourDuration = getVehicleTourDuration(t); + for (String singleDepot : carrierAttributes.vehicleDepots) { + GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration t = tourDistribution.get(carrierAttributes.smallScaleCommercialTrafficType).sample(); + int vehicleStartTime = t.getVehicleStartTime(); + int tourDuration = t.getVehicleTourDuration(); int vehicleEndTime = vehicleStartTime + tourDuration; for (String thisVehicleType : vehicleTypes) { //TODO Flottenzusammensetzung anpassen. Momentan pro Depot alle Fahrzeugtypen 1x erzeugen VehicleType thisType = carrierVehicleTypes.getVehicleTypes() @@ -831,52 +881,10 @@ private void createNewCarrierAndAddVehicleTypes(Scenario scenario, Integer purpo } } - /** - * Gives a duration for the created tour under the given probability. - * - */ - private int getVehicleTourDuration(TourStartAndDuration t) { - return (int) rnd.nextDouble(t.minDuration * 60, t.maxDuration * 60); - } - - /** - * Gives a tour start time for the created tour under the given probability. - */ - private int getVehicleStartTime(TourStartAndDuration t) { - return rnd.nextInt(t.hourLower * 3600, t.hourUpper * 3600); - } - - - /** - * Give a service duration based on the purpose and the trafficType under a given probability - * - * @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, - String employeeCategory, - String modeORvehType, String smallScaleCommercialTrafficType) { - StopDurationGoodTrafficKey key = null; - if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) - key = makeStopDurationGoodTrafficKey(employeeCategory, null); - else if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.goodsTraffic.toString())) { - key = makeStopDurationGoodTrafficKey(employeeCategory, modeORvehType); - } - DurationsBounds serviceDurationBounds = serviceDurationTimeSelector.get(key).sample(); - int serviceDurationLowerBound = serviceDurationBounds.minDuration(); - int serviceDurationUpperBound = serviceDurationBounds.maxDuration(); - return rnd.nextInt(serviceDurationLowerBound * 60, serviceDurationUpperBound * 60); - } - /** * Finds a possible link for a service or the vehicle location. */ - private Id findPossibleLink(String zone, String selectedCategory, List noPossibleLinks, - Map, Link>> linksPerZone) { - + private Id findPossibleLink(String zone, String selectedCategory, List noPossibleLinks) { Id newLink = null; for (int a = 0; newLink == null && a < facilitiesPerZone.get(zone).get(selectedCategory).size() * 2; a++) { @@ -958,7 +966,7 @@ private static void findNearestLinkForZonesWithoutLinks(Network networkToChange, private TripDistributionMatrix createTripDistribution( Map> trafficVolume_start, Map> trafficVolume_stop, - String smallScaleCommercialTrafficType, Scenario scenario, Path output, Map, Link>> linksPerZone) + String smallScaleCommercialTrafficType, Scenario scenario, Path output) throws Exception { ArrayList listOfZones = new ArrayList<>(); @@ -991,6 +999,26 @@ private TripDistributionMatrix createTripDistribution( return odMatrix; } + public Map> getTourDistribution() { + return tourDistribution; + } + + public Map> getServiceDurationTimeSelector() { + return serviceDurationTimeSelector; + } + + public Map, CarrierAttributes> getCarrierId2carrierAttributes() { + return carrierId2carrierAttributes; + } + + public int getMaxReplanningIterations(){ + return maxReplanningIterations; + } + + public int getAdditionalTravelBufferPerIterationInMinutes(){ + return additionalTravelBufferPerIterationInMinutes; + } + private static class MyCarrierScoringFunctionFactory implements CarrierScoringFunctionFactory { @Inject @@ -1035,7 +1063,7 @@ public CarrierStrategyManager get() { travelDisutility, modeTravelTimes.get(TransportMode.car)); // final GenericStrategyManager strategyManager = new GenericStrategyManager<>(); - final CarrierStrategyManager strategyManager = CarrierControlerUtils.createDefaultCarrierStrategyManager(); + final CarrierStrategyManager strategyManager = CarrierControllerUtils.createDefaultCarrierStrategyManager(); strategyManager.setMaxPlansPerAgent(5); { GenericPlanStrategyImpl strategy = new GenericPlanStrategyImpl<>( @@ -1203,33 +1231,68 @@ public double getScore() { } - public record StopDurationGoodTrafficKey(String employeeCategory, String vehicleType) { + public record ServiceDurationPerCategoryKey(String employeeCategory, String vehicleType, String smallScaleCommercialTrafficType) { @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ServiceDurationPerCategoryKey other = (ServiceDurationPerCategoryKey) obj; + if (employeeCategory == null) { + if (other.employeeCategory != null) return false; - if (getClass() != obj.getClass()) + } else if (!employeeCategory.equals(other.employeeCategory)) + return false; + if (vehicleType == null) { + if (other.vehicleType != null) return false; - StopDurationGoodTrafficKey other = (StopDurationGoodTrafficKey) obj; - if (employeeCategory == null) { - if (other.employeeCategory != null) - return false; - } else if (!employeeCategory.equals(other.employeeCategory)) - return false; - if (vehicleType == null) { - return other.vehicleType == null; - } else return vehicleType.equals(other.vehicleType); - } + } else if (!vehicleType.equals(other.vehicleType)) + return false; + if (smallScaleCommercialTrafficType == null) { + return other.smallScaleCommercialTrafficType == null; + } else return smallScaleCommercialTrafficType.equals(other.smallScaleCommercialTrafficType); } - public static StopDurationGoodTrafficKey makeStopDurationGoodTrafficKey(String employeeCategory, String vehicleType) { - return new StopDurationGoodTrafficKey(employeeCategory, vehicleType); + } + public static ServiceDurationPerCategoryKey makeServiceDurationPerCategoryKey(String employeeCategory, String vehicleType, String smallScaleCommercialTrafficType) { + return new ServiceDurationPerCategoryKey(employeeCategory, vehicleType, smallScaleCommercialTrafficType); } - public record TourStartAndDuration(int hourLower, int hourUpper, double minDuration, double maxDuration) {} + public record TourStartAndDuration(int hourLower, int hourUpper, double minDuration, double maxDuration) { + /** + * Gives a duration for the created tour under the given probability. + */ + public int getVehicleTourDuration() { + if (minDuration == 0.) + return (int) maxDuration() * 60; + else + return (int) rnd.nextDouble(minDuration * 60, maxDuration * 60); + } + + /** + * Gives a tour start time for the created tour under the given probability. + */ + public int getVehicleStartTime() { + return rnd.nextInt(hourLower * 3600, hourUpper * 3600); + } + } public record DurationsBounds(int minDuration, int maxDuration) {} + /** + * The attributes of a carrier, used during the generation + * @param purpose purpose of this carrier denoted as an index. Can be used in {@link VehicleSelection} to get more information about this carrier. + * @param startZone start zone of this carrier, entry from {@link TripDistributionMatrix#getListOfZones()} + * @param selectedStartCategory start category of this carrier, selected randomly from {@link VehicleSelection.OdMatrixEntryInformation#possibleStartCategories} + * @param modeORvehType entry from {@link TripDistributionMatrix#getListOfModesOrVehTypes()} + * @param smallScaleCommercialTrafficType Entry from {@link SmallScaleCommercialTrafficType} for this carrier + * (NOTE: This value only differs between carriers if {@link SmallScaleCommercialTrafficType#completeSmallScaleCommercialTraffic is selected) + * @param vehicleDepots Containing the depots of this carrier with linkIds as strings + */ + public record CarrierAttributes(int purpose, String startZone, String selectedStartCategory, String modeORvehType, + String smallScaleCommercialTrafficType, ArrayList vehicleDepots, + VehicleSelection.OdMatrixEntryInformation odMatrixEntry) {} } diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java index a536f751552..34af805ee00 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java @@ -25,6 +25,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.core.utils.io.IOUtils; +import org.matsim.smallScaleCommercialTrafficGeneration.data.GetGenerationRates; import java.io.BufferedWriter; import java.io.IOException; @@ -246,865 +247,16 @@ private static void writeCSVTrafficVolume(Map> setGenerationRates(String smallScaleCommercialTrafficType, - String generationType) { - - Map> generationRates = new HashMap<>(); - Map ratesPerPurpose1 = new HashMap<>(); - Map ratesPerPurpose2 = new HashMap<>(); - Map ratesPerPurpose3 = new HashMap<>(); - Map ratesPerPurpose4 = new HashMap<>(); - Map ratesPerPurpose5 = new HashMap<>(); - Map ratesPerPurpose6 = new HashMap<>(); - if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic")) { - if (generationType.equals("start")) { - ratesPerPurpose1.put("Inhabitants", 0.0); - ratesPerPurpose1.put("Employee", 0.0); - ratesPerPurpose1.put("Employee Primary Sector", 0.0); - ratesPerPurpose1.put("Employee Construction", 0.0); - ratesPerPurpose1.put("Employee Secondary Sector Rest", 0.059); - ratesPerPurpose1.put("Employee Retail", 0.0); - ratesPerPurpose1.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose1.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose2.put("Inhabitants", 0.0); - ratesPerPurpose2.put("Employee", 0.029); - ratesPerPurpose2.put("Employee Primary Sector", 0.0); - ratesPerPurpose2.put("Employee Construction", 0.0); - ratesPerPurpose2.put("Employee Secondary Sector Rest", 0.045); - ratesPerPurpose2.put("Employee Retail", 0.0); - ratesPerPurpose2.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose2.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose3.put("Inhabitants", 0.0); - ratesPerPurpose3.put("Employee", 0.021); - ratesPerPurpose3.put("Employee Primary Sector", 0.0); - ratesPerPurpose3.put("Employee Construction", 0.0); - ratesPerPurpose3.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose3.put("Employee Retail", 0.0192); - ratesPerPurpose3.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose3.put("Employee Tertiary Sector Rest", 0.184); - - ratesPerPurpose4.put("Inhabitants", 0.0); - ratesPerPurpose4.put("Employee", 0.021); - ratesPerPurpose4.put("Employee Primary Sector", 0.0); - ratesPerPurpose4.put("Employee Construction", 0.0); - ratesPerPurpose4.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose4.put("Employee Retail", 0.0); - ratesPerPurpose4.put("Employee Traffic/Parcels", 0.203); - ratesPerPurpose4.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose5.put("Inhabitants", 0.0); - ratesPerPurpose5.put("Employee", 0.03); - ratesPerPurpose5.put("Employee Primary Sector", 0.0); - ratesPerPurpose5.put("Employee Construction", 0.29); - ratesPerPurpose5.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose5.put("Employee Retail", 0.0); - ratesPerPurpose5.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose5.put("Employee Tertiary Sector Rest", 0.0); - } else if (generationType.equals("stop")) { - ratesPerPurpose1.put("Inhabitants", 0.0); - ratesPerPurpose1.put("Employee", 0.0); - ratesPerPurpose1.put("Employee Primary Sector", 0.0); - ratesPerPurpose1.put("Employee Construction", 0.0); - ratesPerPurpose1.put("Employee Secondary Sector Rest", 0.02); - ratesPerPurpose1.put("Employee Retail", 0.0); - ratesPerPurpose1.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose1.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose2.put("Inhabitants", 0.002); - ratesPerPurpose2.put("Employee", 0.0); - ratesPerPurpose2.put("Employee Primary Sector", 0.029); - ratesPerPurpose2.put("Employee Construction", 0.029); - ratesPerPurpose2.put("Employee Secondary Sector Rest", 0.009); - ratesPerPurpose2.put("Employee Retail", 0.029); - ratesPerPurpose2.put("Employee Traffic/Parcels", 0.039); - ratesPerPurpose2.put("Employee Tertiary Sector Rest", 0.029); - - ratesPerPurpose3.put("Inhabitants", 0.025); - ratesPerPurpose3.put("Employee", 0.0); - ratesPerPurpose3.put("Employee Primary Sector", 0.0168); - ratesPerPurpose3.put("Employee Construction", 0.168); - ratesPerPurpose3.put("Employee Secondary Sector Rest", 0.0168); - ratesPerPurpose3.put("Employee Retail", 0.0168); - ratesPerPurpose3.put("Employee Traffic/Parcels", 0.097); - ratesPerPurpose3.put("Employee Tertiary Sector Rest", 0.168); - - ratesPerPurpose4.put("Inhabitants", 0.002); - ratesPerPurpose4.put("Employee", 0.0); - ratesPerPurpose4.put("Employee Primary Sector", 0.025); - ratesPerPurpose4.put("Employee Construction", 0.025); - ratesPerPurpose4.put("Employee Secondary Sector Rest", 0.025); - ratesPerPurpose4.put("Employee Retail", 0.025); - ratesPerPurpose4.put("Employee Traffic/Parcels", 0.075); - ratesPerPurpose4.put("Employee Tertiary Sector Rest", 0.025); - - ratesPerPurpose5.put("Inhabitants", 0.004); - ratesPerPurpose5.put("Employee", 0.0); - ratesPerPurpose5.put("Employee Primary Sector", 0.015); - ratesPerPurpose5.put("Employee Construction", 0.002); - ratesPerPurpose5.put("Employee Secondary Sector Rest", 0.015); - ratesPerPurpose5.put("Employee Retail", 0.015); - ratesPerPurpose5.put("Employee Traffic/Parcels", 0.02); - ratesPerPurpose5.put("Employee Tertiary Sector Rest", 0.015); - - } - } else if (smallScaleCommercialTrafficType.equals("goodsTraffic")) { - if (generationType.equals("start")) { - ratesPerPurpose1.put("Inhabitants", 0.0); - ratesPerPurpose1.put("Employee", 0.0); - ratesPerPurpose1.put("Employee Primary Sector", 0.0); - ratesPerPurpose1.put("Employee Construction", 0.0); - ratesPerPurpose1.put("Employee Secondary Sector Rest", 0.023); - ratesPerPurpose1.put("Employee Retail", 0.0); - ratesPerPurpose1.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose1.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose2.put("Inhabitants", 0.0); - ratesPerPurpose2.put("Employee", 0.002); - ratesPerPurpose2.put("Employee Primary Sector", 0.0); - ratesPerPurpose2.put("Employee Construction", 0.0); - ratesPerPurpose2.put("Employee Secondary Sector Rest", 0.049); - ratesPerPurpose2.put("Employee Retail", 0.0); - ratesPerPurpose2.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose2.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose3.put("Inhabitants", 0.0); - ratesPerPurpose3.put("Employee", 0.002); - ratesPerPurpose3.put("Employee Primary Sector", 0.0); - ratesPerPurpose3.put("Employee Construction", 0.0); - ratesPerPurpose3.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose3.put("Employee Retail", 0.139); - ratesPerPurpose3.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose3.put("Employee Tertiary Sector Rest", 0.059); - - ratesPerPurpose4.put("Inhabitants", 0.0); - ratesPerPurpose4.put("Employee", 0.002); - ratesPerPurpose4.put("Employee Primary Sector", 0.0); - ratesPerPurpose4.put("Employee Construction", 0.0); - ratesPerPurpose4.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose4.put("Employee Retail", 0.0); - ratesPerPurpose4.put("Employee Traffic/Parcels", 0.333); - ratesPerPurpose4.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose5.put("Inhabitants", 0.0); - ratesPerPurpose5.put("Employee", 0.002); - ratesPerPurpose5.put("Employee Primary Sector", 0.0); - ratesPerPurpose5.put("Employee Construction", 0.220); - ratesPerPurpose5.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose5.put("Employee Retail", 0.0); - ratesPerPurpose5.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose5.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose6.put("Inhabitants", 0.009); - ratesPerPurpose6.put("Employee", 0.0); - ratesPerPurpose6.put("Employee Primary Sector", 0.0); - ratesPerPurpose6.put("Employee Construction", 0.0); - ratesPerPurpose6.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose6.put("Employee Retail", 0.0); - ratesPerPurpose6.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose6.put("Employee Tertiary Sector Rest", 0.0); - - } else if (generationType.equals("stop")) { - ratesPerPurpose1.put("Inhabitants", 0.0); - ratesPerPurpose1.put("Employee", 0.0); - ratesPerPurpose1.put("Employee Primary Sector", 0.0); - ratesPerPurpose1.put("Employee Construction", 0.0); - ratesPerPurpose1.put("Employee Secondary Sector Rest", 0.031); - ratesPerPurpose1.put("Employee Retail", 0.0); - ratesPerPurpose1.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose1.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose2.put("Inhabitants", 0.001); - ratesPerPurpose2.put("Employee", 0.0); - ratesPerPurpose2.put("Employee Primary Sector", 0.001); - ratesPerPurpose2.put("Employee Construction", 0.01); - ratesPerPurpose2.put("Employee Secondary Sector Rest", 0.011); - ratesPerPurpose2.put("Employee Retail", 0.021); - ratesPerPurpose2.put("Employee Traffic/Parcels", 0.001); - ratesPerPurpose2.put("Employee Tertiary Sector Rest", 0.001); - - ratesPerPurpose3.put("Inhabitants", 0.009); - ratesPerPurpose3.put("Employee", 0.0); - ratesPerPurpose3.put("Employee Primary Sector", 0.02); - ratesPerPurpose3.put("Employee Construction", 0.005); - ratesPerPurpose3.put("Employee Secondary Sector Rest", 0.029); - ratesPerPurpose3.put("Employee Retail", 0.055); - ratesPerPurpose3.put("Employee Traffic/Parcels", 0.02); - ratesPerPurpose3.put("Employee Tertiary Sector Rest", 0.02); - - ratesPerPurpose4.put("Inhabitants", 0.014); - ratesPerPurpose4.put("Employee", 0.0); - ratesPerPurpose4.put("Employee Primary Sector", 0.02); - ratesPerPurpose4.put("Employee Construction", 0.002); - ratesPerPurpose4.put("Employee Secondary Sector Rest", 0.11); - ratesPerPurpose4.put("Employee Retail", 0.154); - ratesPerPurpose4.put("Employee Traffic/Parcels", 0.02); - ratesPerPurpose4.put("Employee Tertiary Sector Rest", 0.02); - - ratesPerPurpose5.put("Inhabitants", 0.002); - ratesPerPurpose5.put("Employee", 0.0); - ratesPerPurpose5.put("Employee Primary Sector", 0.005); - ratesPerPurpose5.put("Employee Construction", 0.002); - ratesPerPurpose5.put("Employee Secondary Sector Rest", 0.01); - ratesPerPurpose5.put("Employee Retail", 0.01); - ratesPerPurpose5.put("Employee Traffic/Parcels", 0.005); - ratesPerPurpose5.put("Employee Tertiary Sector Rest", 0.005); - - ratesPerPurpose6.put("Inhabitants", 0.002); - ratesPerPurpose6.put("Employee", 0.0); - ratesPerPurpose6.put("Employee Primary Sector", 0.005); - ratesPerPurpose6.put("Employee Construction", 0.002); - ratesPerPurpose6.put("Employee Secondary Sector Rest", 0.01); - ratesPerPurpose6.put("Employee Retail", 0.01); - ratesPerPurpose6.put("Employee Traffic/Parcels", 0.005); - ratesPerPurpose6.put("Employee Tertiary Sector Rest", 0.005); - } - generationRates.put(6, ratesPerPurpose6); - } - generationRates.put(1, ratesPerPurpose1); - generationRates.put(2, ratesPerPurpose2); - generationRates.put(3, ratesPerPurpose3); - generationRates.put(4, ratesPerPurpose4); - generationRates.put(5, ratesPerPurpose5); - return generationRates; - } - - /** - * Sets the commitment rates based on the IVV 2005 for the goodsTraffic. The - * commitment rate for the commercialPersonTraffic is 1, because mode choice will be - * done in MATSim. - * - * @param smallScaleCommercialTrafficType used trafficType (freight or business traffic) - * @param commitmentType start or stop parameter - */ - private static Map> setCommitmentRates(String smallScaleCommercialTrafficType, - String commitmentType) { - Map> commitmentRates = new HashMap<>(); - - if (smallScaleCommercialTrafficType.equals("goodsTraffic")) { - - // the first number is the purpose; second number the vehicle type - Map ratesPerPurpose1_1 = new HashMap<>(); - Map ratesPerPurpose1_2 = new HashMap<>(); - Map ratesPerPurpose1_3 = new HashMap<>(); - Map ratesPerPurpose1_4 = new HashMap<>(); - Map ratesPerPurpose1_5 = new HashMap<>(); - Map ratesPerPurpose2_1 = new HashMap<>(); - Map ratesPerPurpose2_2 = new HashMap<>(); - Map ratesPerPurpose2_3 = new HashMap<>(); - Map ratesPerPurpose2_4 = new HashMap<>(); - Map ratesPerPurpose2_5 = new HashMap<>(); - Map ratesPerPurpose3_1 = new HashMap<>(); - Map ratesPerPurpose3_2 = new HashMap<>(); - Map ratesPerPurpose3_3 = new HashMap<>(); - Map ratesPerPurpose3_4 = new HashMap<>(); - Map ratesPerPurpose3_5 = new HashMap<>(); - Map ratesPerPurpose4_1 = new HashMap<>(); - Map ratesPerPurpose4_2 = new HashMap<>(); - Map ratesPerPurpose4_3 = new HashMap<>(); - Map ratesPerPurpose4_4 = new HashMap<>(); - Map ratesPerPurpose4_5 = new HashMap<>(); - Map ratesPerPurpose5_1 = new HashMap<>(); - Map ratesPerPurpose5_2 = new HashMap<>(); - Map ratesPerPurpose5_3 = new HashMap<>(); - Map ratesPerPurpose5_4 = new HashMap<>(); - Map ratesPerPurpose5_5 = new HashMap<>(); - Map ratesPerPurpose6_1 = new HashMap<>(); - Map ratesPerPurpose6_2 = new HashMap<>(); - Map ratesPerPurpose6_3 = new HashMap<>(); - Map ratesPerPurpose6_4 = new HashMap<>(); - Map ratesPerPurpose6_5 = new HashMap<>(); - if (commitmentType.equals("start")) { - ratesPerPurpose1_1.put("Inhabitants", 0.0); - ratesPerPurpose1_1.put("Employee", 0.8); - ratesPerPurpose1_1.put("Employee Primary Sector", 0.0); - ratesPerPurpose1_1.put("Employee Construction", 0.0); - ratesPerPurpose1_1.put("Employee Secondary Sector Rest", 0.44); - ratesPerPurpose1_1.put("Employee Retail", 0.0); - ratesPerPurpose1_1.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose1_1.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose1_2.put("Inhabitants", 0.0); - ratesPerPurpose1_2.put("Employee", 0.1); - ratesPerPurpose1_2.put("Employee Primary Sector", 0.0); - ratesPerPurpose1_2.put("Employee Construction", 0.0); - ratesPerPurpose1_2.put("Employee Secondary Sector Rest", 0.11); - ratesPerPurpose1_2.put("Employee Retail", 0.0); - ratesPerPurpose1_2.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose1_2.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose1_3.put("Inhabitants", 0.0); - ratesPerPurpose1_3.put("Employee", 0.1); - ratesPerPurpose1_3.put("Employee Primary Sector", 0.0); - ratesPerPurpose1_3.put("Employee Construction", 0.0); - ratesPerPurpose1_3.put("Employee Secondary Sector Rest", 0.22); - ratesPerPurpose1_3.put("Employee Retail", 0.0); - ratesPerPurpose1_3.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose1_3.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose1_4.put("Inhabitants", 0.0); - ratesPerPurpose1_4.put("Employee", 0.0); - ratesPerPurpose1_4.put("Employee Primary Sector", 0.0); - ratesPerPurpose1_4.put("Employee Construction", 0.0); - ratesPerPurpose1_4.put("Employee Secondary Sector Rest", 0.06); - ratesPerPurpose1_4.put("Employee Retail", 0.0); - ratesPerPurpose1_4.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose1_4.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose1_5.put("Inhabitants", 0.0); - ratesPerPurpose1_5.put("Employee", 0.0); - ratesPerPurpose1_5.put("Employee Primary Sector", 0.0); - ratesPerPurpose1_5.put("Employee Construction", 0.0); - ratesPerPurpose1_5.put("Employee Secondary Sector Rest", 0.16); - ratesPerPurpose1_5.put("Employee Retail", 0.0); - ratesPerPurpose1_5.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose1_5.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose2_1.put("Inhabitants", 0.0); - ratesPerPurpose2_1.put("Employee", 0.8); - ratesPerPurpose2_1.put("Employee Primary Sector", 0.0); - ratesPerPurpose2_1.put("Employee Construction", 0.0); - ratesPerPurpose2_1.put("Employee Secondary Sector Rest", 0.44); - ratesPerPurpose2_1.put("Employee Retail", 0.0); - ratesPerPurpose2_1.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose2_1.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose2_2.put("Inhabitants", 0.0); - ratesPerPurpose2_2.put("Employee", 0.1); - ratesPerPurpose2_2.put("Employee Primary Sector", 0.0); - ratesPerPurpose2_2.put("Employee Construction", 0.0); - ratesPerPurpose2_2.put("Employee Secondary Sector Rest", 0.11); - ratesPerPurpose2_2.put("Employee Retail", 0.0); - ratesPerPurpose2_2.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose2_2.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose2_3.put("Inhabitants", 0.0); - ratesPerPurpose2_3.put("Employee", 0.1); - ratesPerPurpose2_3.put("Employee Primary Sector", 0.0); - ratesPerPurpose2_3.put("Employee Construction", 0.0); - ratesPerPurpose2_3.put("Employee Secondary Sector Rest", 0.22); - ratesPerPurpose2_3.put("Employee Retail", 0.0); - ratesPerPurpose2_3.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose2_3.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose2_4.put("Inhabitants", 0.0); - ratesPerPurpose2_4.put("Employee", 0.0); - ratesPerPurpose2_4.put("Employee Primary Sector", 0.0); - ratesPerPurpose2_4.put("Employee Construction", 0.0); - ratesPerPurpose2_4.put("Employee Secondary Sector Rest", 0.06); - ratesPerPurpose2_4.put("Employee Retail", 0.0); - ratesPerPurpose2_4.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose2_4.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose2_5.put("Inhabitants", 0.0); - ratesPerPurpose2_5.put("Employee", 0.0); - ratesPerPurpose2_5.put("Employee Primary Sector", 0.0); - ratesPerPurpose2_5.put("Employee Construction", 0.0); - ratesPerPurpose2_5.put("Employee Secondary Sector Rest", 0.16); - ratesPerPurpose2_5.put("Employee Retail", 0.0); - ratesPerPurpose2_5.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose2_5.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose3_1.put("Inhabitants", 0.0); - ratesPerPurpose3_1.put("Employee", 0.8); - ratesPerPurpose3_1.put("Employee Primary Sector", 0.0); - ratesPerPurpose3_1.put("Employee Construction", 0.0); - ratesPerPurpose3_1.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose3_1.put("Employee Retail", 0.46); - ratesPerPurpose3_1.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose3_1.put("Employee Tertiary Sector Rest", 0.54); - - ratesPerPurpose3_2.put("Inhabitants", 0.0); - ratesPerPurpose3_2.put("Employee", 0.1); - ratesPerPurpose3_2.put("Employee Primary Sector", 0.0); - ratesPerPurpose3_2.put("Employee Construction", 0.0); - ratesPerPurpose3_2.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose3_2.put("Employee Retail", 0.1); - ratesPerPurpose3_2.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose3_2.put("Employee Tertiary Sector Rest", 0.1); - - ratesPerPurpose3_3.put("Inhabitants", 0.0); - ratesPerPurpose3_3.put("Employee", 0.1); - ratesPerPurpose3_3.put("Employee Primary Sector", 0.0); - ratesPerPurpose3_3.put("Employee Construction", 0.0); - ratesPerPurpose3_3.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose3_3.put("Employee Retail", 0.23); - ratesPerPurpose3_3.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose3_3.put("Employee Tertiary Sector Rest", 0.2); - - ratesPerPurpose3_4.put("Inhabitants", 0.0); - ratesPerPurpose3_4.put("Employee", 0.0); - ratesPerPurpose3_4.put("Employee Primary Sector", 0.0); - ratesPerPurpose3_4.put("Employee Construction", 0.0); - ratesPerPurpose3_4.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose3_4.put("Employee Retail", 0.06); - ratesPerPurpose3_4.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose3_4.put("Employee Tertiary Sector Rest", 0.02); - - ratesPerPurpose3_5.put("Inhabitants", 0.0); - ratesPerPurpose3_5.put("Employee", 0.0); - ratesPerPurpose3_5.put("Employee Primary Sector", 0.0); - ratesPerPurpose3_5.put("Employee Construction", 0.0); - ratesPerPurpose3_5.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose3_5.put("Employee Retail", 0.15); - ratesPerPurpose3_5.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose3_5.put("Employee Tertiary Sector Rest", 0.14); - - ratesPerPurpose4_1.put("Inhabitants", 0.009); - ratesPerPurpose4_1.put("Employee", 0.8); - ratesPerPurpose4_1.put("Employee Primary Sector", 0.0); - ratesPerPurpose4_1.put("Employee Construction", 0.0); - ratesPerPurpose4_1.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose4_1.put("Employee Retail", 0.0); - ratesPerPurpose4_1.put("Employee Traffic/Parcels", 0.18); - ratesPerPurpose4_1.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose4_2.put("Inhabitants", 0.0); - ratesPerPurpose4_2.put("Employee", 0.1); - ratesPerPurpose4_2.put("Employee Primary Sector", 0.0); - ratesPerPurpose4_2.put("Employee Construction", 0.0); - ratesPerPurpose4_2.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose4_2.put("Employee Retail", 0.0); - ratesPerPurpose4_2.put("Employee Traffic/Parcels", 0.06); - ratesPerPurpose4_2.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose4_3.put("Inhabitants", 0.0); - ratesPerPurpose4_3.put("Employee", 0.1); - ratesPerPurpose4_3.put("Employee Primary Sector", 0.0); - ratesPerPurpose4_3.put("Employee Construction", 0.0); - ratesPerPurpose4_3.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose4_3.put("Employee Retail", 0.0); - ratesPerPurpose4_3.put("Employee Traffic/Parcels", 0.25); - ratesPerPurpose4_3.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose4_4.put("Inhabitants", 0.0); - ratesPerPurpose4_4.put("Employee", 0.0); - ratesPerPurpose4_4.put("Employee Primary Sector", 0.0); - ratesPerPurpose4_4.put("Employee Construction", 0.0); - ratesPerPurpose4_4.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose4_4.put("Employee Retail", 0.0); - ratesPerPurpose4_4.put("Employee Traffic/Parcels", 0.08); - ratesPerPurpose4_4.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose4_5.put("Inhabitants", 0.0); - ratesPerPurpose4_5.put("Employee", 0.0); - ratesPerPurpose4_5.put("Employee Primary Sector", 0.0); - ratesPerPurpose4_5.put("Employee Construction", 0.0); - ratesPerPurpose4_5.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose4_5.put("Employee Retail", 0.0); - ratesPerPurpose4_5.put("Employee Traffic/Parcels", 0.43); - ratesPerPurpose4_5.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose5_1.put("Inhabitants", 0.0); - ratesPerPurpose5_1.put("Employee", 0.8); - ratesPerPurpose5_1.put("Employee Primary Sector", 0.0); - ratesPerPurpose5_1.put("Employee Construction", 0.25); - ratesPerPurpose5_1.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose5_1.put("Employee Retail", 0.0); - ratesPerPurpose5_1.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose5_1.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose5_2.put("Inhabitants", 0.0); - ratesPerPurpose5_2.put("Employee", 0.1); - ratesPerPurpose5_2.put("Employee Primary Sector", 0.0); - ratesPerPurpose5_2.put("Employee Construction", 0.2); - ratesPerPurpose5_2.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose5_2.put("Employee Retail", 0.0); - ratesPerPurpose5_2.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose5_2.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose5_3.put("Inhabitants", 0.0); - ratesPerPurpose5_3.put("Employee", 0.1); - ratesPerPurpose5_3.put("Employee Primary Sector", 0.0); - ratesPerPurpose5_3.put("Employee Construction", 0.25); - ratesPerPurpose5_3.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose5_3.put("Employee Retail", 0.139); - ratesPerPurpose5_3.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose5_3.put("Employee Tertiary Sector Rest", 0.059); - - ratesPerPurpose5_4.put("Inhabitants", 0.0); - ratesPerPurpose5_4.put("Employee", 0.0); - ratesPerPurpose5_4.put("Employee Primary Sector", 0.0); - ratesPerPurpose5_4.put("Employee Construction", 0.02); - ratesPerPurpose5_4.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose5_4.put("Employee Retail", 0.0); - ratesPerPurpose5_4.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose5_4.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose5_5.put("Inhabitants", 0.0); - ratesPerPurpose5_5.put("Employee", 0.0); - ratesPerPurpose5_5.put("Employee Primary Sector", 0.0); - ratesPerPurpose5_5.put("Employee Construction", 0.28); - ratesPerPurpose5_5.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose5_5.put("Employee Retail", 0.0); - ratesPerPurpose5_5.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose5_5.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose6_1.put("Inhabitants", 0.0); - ratesPerPurpose6_1.put("Employee", 0.0); - ratesPerPurpose6_1.put("Employee Primary Sector", 0.0); - ratesPerPurpose6_1.put("Employee Construction", 0.0); - ratesPerPurpose6_1.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose6_1.put("Employee Retail", 0.0); - ratesPerPurpose6_1.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose6_1.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose6_2.put("Inhabitants", 0.29); - ratesPerPurpose6_2.put("Employee", 0.0); - ratesPerPurpose6_2.put("Employee Primary Sector", 0.0); - ratesPerPurpose6_2.put("Employee Construction", 0.0); - ratesPerPurpose6_2.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose6_2.put("Employee Retail", 0.0); - ratesPerPurpose6_2.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose6_2.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose6_3.put("Inhabitants", 0.63); - ratesPerPurpose6_3.put("Employee", 0.0); - ratesPerPurpose6_3.put("Employee Primary Sector", 0.0); - ratesPerPurpose6_3.put("Employee Construction", 0.0); - ratesPerPurpose6_3.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose6_3.put("Employee Retail", 0.0); - ratesPerPurpose6_3.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose6_3.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose6_4.put("Inhabitants", 0.07); - ratesPerPurpose6_4.put("Employee", 0.0); - ratesPerPurpose6_4.put("Employee Primary Sector", 0.0); - ratesPerPurpose6_4.put("Employee Construction", 0.0); - ratesPerPurpose6_4.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose6_4.put("Employee Retail", 0.0); - ratesPerPurpose6_4.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose6_4.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose6_5.put("Inhabitants", 0.001); - ratesPerPurpose6_5.put("Employee", 0.0); - ratesPerPurpose6_5.put("Employee Primary Sector", 0.0); - ratesPerPurpose6_5.put("Employee Construction", 0.2); - ratesPerPurpose6_5.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose6_5.put("Employee Retail", 0.0); - ratesPerPurpose6_5.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose6_5.put("Employee Tertiary Sector Rest", 0.0); - } else if (commitmentType.equals("stop")) { - ratesPerPurpose1_1.put("Inhabitants", 0.0); - ratesPerPurpose1_1.put("Employee", 0.0); - ratesPerPurpose1_1.put("Employee Primary Sector", 0.0); - ratesPerPurpose1_1.put("Employee Construction", 0.0); - ratesPerPurpose1_1.put("Employee Secondary Sector Rest", 0.35); - ratesPerPurpose1_1.put("Employee Retail", 0.0); - ratesPerPurpose1_1.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose1_1.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose1_2.put("Inhabitants", 0.0); - ratesPerPurpose1_2.put("Employee", 0.0); - ratesPerPurpose1_2.put("Employee Primary Sector", 0.0); - ratesPerPurpose1_2.put("Employee Construction", 0.0); - ratesPerPurpose1_2.put("Employee Secondary Sector Rest", 0.1); - ratesPerPurpose1_2.put("Employee Retail", 0.0); - ratesPerPurpose1_2.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose1_2.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose1_3.put("Inhabitants", 0.0); - ratesPerPurpose1_3.put("Employee", 0.0); - ratesPerPurpose1_3.put("Employee Primary Sector", 0.0); - ratesPerPurpose1_3.put("Employee Construction", 0.0); - ratesPerPurpose1_3.put("Employee Secondary Sector Rest", 0.27); - ratesPerPurpose1_3.put("Employee Retail", 0.0); - ratesPerPurpose1_3.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose1_3.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose1_4.put("Inhabitants", 0.0); - ratesPerPurpose1_4.put("Employee", 0.0); - ratesPerPurpose1_4.put("Employee Primary Sector", 0.0); - ratesPerPurpose1_4.put("Employee Construction", 0.0); - ratesPerPurpose1_4.put("Employee Secondary Sector Rest", 0.01); - ratesPerPurpose1_4.put("Employee Retail", 0.0); - ratesPerPurpose1_4.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose1_4.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose1_5.put("Inhabitants", 0.0); - ratesPerPurpose1_5.put("Employee", 0.0); - ratesPerPurpose1_5.put("Employee Primary Sector", 0.0); - ratesPerPurpose1_5.put("Employee Construction", 0.0); - ratesPerPurpose1_5.put("Employee Secondary Sector Rest", 0.27); - ratesPerPurpose1_5.put("Employee Retail", 0.0); - ratesPerPurpose1_5.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose1_5.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose2_1.put("Inhabitants", 0.55); - ratesPerPurpose2_1.put("Employee", 0.0); - ratesPerPurpose2_1.put("Employee Primary Sector", 0.46); - ratesPerPurpose2_1.put("Employee Construction", 0.46); - ratesPerPurpose2_1.put("Employee Secondary Sector Rest", 0.46); - ratesPerPurpose2_1.put("Employee Retail", 0.46); - ratesPerPurpose2_1.put("Employee Traffic/Parcels", 0.34); - ratesPerPurpose2_1.put("Employee Tertiary Sector Rest", 0.46); - - ratesPerPurpose2_2.put("Inhabitants", 0.09); - ratesPerPurpose2_2.put("Employee", 0.0); - ratesPerPurpose2_2.put("Employee Primary Sector", 0.09); - ratesPerPurpose2_2.put("Employee Construction", 0.09); - ratesPerPurpose2_2.put("Employee Secondary Sector Rest", 0.09); - ratesPerPurpose2_2.put("Employee Retail", 0.09); - ratesPerPurpose2_2.put("Employee Traffic/Parcels", 0.1); - ratesPerPurpose2_2.put("Employee Tertiary Sector Rest", 0.09); - - ratesPerPurpose2_3.put("Inhabitants", 0.21); - ratesPerPurpose2_3.put("Employee", 0.0); - ratesPerPurpose2_3.put("Employee Primary Sector", 0.22); - ratesPerPurpose2_3.put("Employee Construction", 0.22); - ratesPerPurpose2_3.put("Employee Secondary Sector Rest", 0.22); - ratesPerPurpose2_3.put("Employee Retail", 0.22); - ratesPerPurpose2_3.put("Employee Traffic/Parcels", 0.29); - ratesPerPurpose2_3.put("Employee Tertiary Sector Rest", 0.22); - - ratesPerPurpose2_4.put("Inhabitants", 0.06); - ratesPerPurpose2_4.put("Employee", 0.0); - ratesPerPurpose2_4.put("Employee Primary Sector", 0.06); - ratesPerPurpose2_4.put("Employee Construction", 0.06); - ratesPerPurpose2_4.put("Employee Secondary Sector Rest", 0.06); - ratesPerPurpose2_4.put("Employee Retail", 0.06); - ratesPerPurpose2_4.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose2_4.put("Employee Tertiary Sector Rest", 0.06); - - ratesPerPurpose2_5.put("Inhabitants", 0.1); - ratesPerPurpose2_5.put("Employee", 0.0); - ratesPerPurpose2_5.put("Employee Primary Sector", 0.17); - ratesPerPurpose2_5.put("Employee Construction", 0.17); - ratesPerPurpose2_5.put("Employee Secondary Sector Rest", 0.17); - ratesPerPurpose2_5.put("Employee Retail", 0.17); - ratesPerPurpose2_5.put("Employee Traffic/Parcels", 0.27); - ratesPerPurpose2_5.put("Employee Tertiary Sector Rest", 0.17); - - ratesPerPurpose3_1.put("Inhabitants", 0.489); - ratesPerPurpose3_1.put("Employee", 0.0); - ratesPerPurpose3_1.put("Employee Primary Sector", 0.538); - ratesPerPurpose3_1.put("Employee Construction", 0.538); - ratesPerPurpose3_1.put("Employee Secondary Sector Rest", 0.538); - ratesPerPurpose3_1.put("Employee Retail", 0.538); - ratesPerPurpose3_1.put("Employee Traffic/Parcels", 0.59); - ratesPerPurpose3_1.put("Employee Tertiary Sector Rest", 0.538); - - ratesPerPurpose3_2.put("Inhabitants", 0.106); - ratesPerPurpose3_2.put("Employee", 0.0); - ratesPerPurpose3_2.put("Employee Primary Sector", 0.092); - ratesPerPurpose3_2.put("Employee Construction", 0.092); - ratesPerPurpose3_2.put("Employee Secondary Sector Rest", 0.092); - ratesPerPurpose3_2.put("Employee Retail", 0.092); - ratesPerPurpose3_2.put("Employee Traffic/Parcels", 0.03); - ratesPerPurpose3_2.put("Employee Tertiary Sector Rest", 0.092); - - ratesPerPurpose3_3.put("Inhabitants", 0.26); - ratesPerPurpose3_3.put("Employee", 0.0); - ratesPerPurpose3_3.put("Employee Primary Sector", 0.19); - ratesPerPurpose3_3.put("Employee Construction", 0.19); - ratesPerPurpose3_3.put("Employee Secondary Sector Rest", 0.19); - ratesPerPurpose3_3.put("Employee Retail", 0.19); - ratesPerPurpose3_3.put("Employee Traffic/Parcels", 0.102); - ratesPerPurpose3_3.put("Employee Tertiary Sector Rest", 0.19); - - ratesPerPurpose3_4.put("Inhabitants", 0.033); - ratesPerPurpose3_4.put("Employee", 0.0); - ratesPerPurpose3_4.put("Employee Primary Sector", 0.032); - ratesPerPurpose3_4.put("Employee Construction", 0.032); - ratesPerPurpose3_4.put("Employee Secondary Sector Rest", 0.032); - ratesPerPurpose3_4.put("Employee Retail", 0.032); - ratesPerPurpose3_4.put("Employee Traffic/Parcels", 0.058); - ratesPerPurpose3_4.put("Employee Tertiary Sector Rest", 0.032); - - ratesPerPurpose3_5.put("Inhabitants", 0.112); - ratesPerPurpose3_5.put("Employee", 0.0); - ratesPerPurpose3_5.put("Employee Primary Sector", 0.147); - ratesPerPurpose3_5.put("Employee Construction", 0.147); - ratesPerPurpose3_5.put("Employee Secondary Sector Rest", 0.147); - ratesPerPurpose3_5.put("Employee Retail", 0.147); - ratesPerPurpose3_5.put("Employee Traffic/Parcels", 0.219); - ratesPerPurpose3_5.put("Employee Tertiary Sector Rest", 0.147); - - ratesPerPurpose4_1.put("Inhabitants", 0.37); - ratesPerPurpose4_1.put("Employee", 0.0); - ratesPerPurpose4_1.put("Employee Primary Sector", 0.14); - ratesPerPurpose4_1.put("Employee Construction", 0.14); - ratesPerPurpose4_1.put("Employee Secondary Sector Rest", 0.14); - ratesPerPurpose4_1.put("Employee Retail", 0.14); - ratesPerPurpose4_1.put("Employee Traffic/Parcels", 0.06); - ratesPerPurpose4_1.put("Employee Tertiary Sector Rest", 0.14); - - ratesPerPurpose4_2.put("Inhabitants", 0.05); - ratesPerPurpose4_2.put("Employee", 0.0); - ratesPerPurpose4_2.put("Employee Primary Sector", 0.07); - ratesPerPurpose4_2.put("Employee Construction", 0.07); - ratesPerPurpose4_2.put("Employee Secondary Sector Rest", 0.07); - ratesPerPurpose4_2.put("Employee Retail", 0.07); - ratesPerPurpose4_2.put("Employee Traffic/Parcels", 0.07); - ratesPerPurpose4_2.put("Employee Tertiary Sector Rest", 0.07); - - ratesPerPurpose4_3.put("Inhabitants", 0.4); - ratesPerPurpose4_3.put("Employee", 0.0); - ratesPerPurpose4_3.put("Employee Primary Sector", 0.21); - ratesPerPurpose4_3.put("Employee Construction", 0.21); - ratesPerPurpose4_3.put("Employee Secondary Sector Rest", 0.21); - ratesPerPurpose4_3.put("Employee Retail", 0.21); - ratesPerPurpose4_3.put("Employee Traffic/Parcels", 0.19); - ratesPerPurpose4_3.put("Employee Tertiary Sector Rest", 0.21); - - ratesPerPurpose4_4.put("Inhabitants", 0.13); - ratesPerPurpose4_4.put("Employee", 0.0); - ratesPerPurpose4_4.put("Employee Primary Sector", 0.05); - ratesPerPurpose4_4.put("Employee Construction", 0.05); - ratesPerPurpose4_4.put("Employee Secondary Sector Rest", 0.05); - ratesPerPurpose4_4.put("Employee Retail", 0.05); - ratesPerPurpose4_4.put("Employee Traffic/Parcels", 0.08); - ratesPerPurpose4_4.put("Employee Tertiary Sector Rest", 0.05); - - ratesPerPurpose4_5.put("Inhabitants", 0.05); - ratesPerPurpose4_5.put("Employee", 0.0); - ratesPerPurpose4_5.put("Employee Primary Sector", 0.54); - ratesPerPurpose4_5.put("Employee Construction", 0.54); - ratesPerPurpose4_5.put("Employee Secondary Sector Rest", 0.54); - ratesPerPurpose4_5.put("Employee Retail", 0.54); - ratesPerPurpose4_5.put("Employee Traffic/Parcels", 0.61); - ratesPerPurpose4_5.put("Employee Tertiary Sector Rest", 0.54); - - ratesPerPurpose5_1.put("Inhabitants", 0.16); - ratesPerPurpose5_1.put("Employee", 0.0); - ratesPerPurpose5_1.put("Employee Primary Sector", 0.4); - ratesPerPurpose5_1.put("Employee Construction", 0.4); - ratesPerPurpose5_1.put("Employee Secondary Sector Rest", 0.4); - ratesPerPurpose5_1.put("Employee Retail", 0.4); - ratesPerPurpose5_1.put("Employee Traffic/Parcels", 0.14); - ratesPerPurpose5_1.put("Employee Tertiary Sector Rest", 0.4); - - ratesPerPurpose5_2.put("Inhabitants", 0.55); - ratesPerPurpose5_2.put("Employee", 0.11); - ratesPerPurpose5_2.put("Employee Primary Sector", 0.11); - ratesPerPurpose5_2.put("Employee Construction", 0.11); - ratesPerPurpose5_2.put("Employee Secondary Sector Rest", 0.11); - ratesPerPurpose5_2.put("Employee Retail", 0.11); - ratesPerPurpose5_2.put("Employee Traffic/Parcels", 0.06); - ratesPerPurpose5_2.put("Employee Tertiary Sector Rest", 0.11); - - ratesPerPurpose5_3.put("Inhabitants", 0.22); - ratesPerPurpose5_3.put("Employee", 0.0); - ratesPerPurpose5_3.put("Employee Primary Sector", 0.17); - ratesPerPurpose5_3.put("Employee Construction", 0.17); - ratesPerPurpose5_3.put("Employee Secondary Sector Rest", 0.17); - ratesPerPurpose5_3.put("Employee Retail", 0.17); - ratesPerPurpose5_3.put("Employee Traffic/Parcels", 0.21); - ratesPerPurpose5_3.put("Employee Tertiary Sector Rest", 0.17); - - ratesPerPurpose5_4.put("Inhabitants", 0.0); - ratesPerPurpose5_4.put("Employee", 0.0); - ratesPerPurpose5_4.put("Employee Primary Sector", 0.04); - ratesPerPurpose5_4.put("Employee Construction", 0.04); - ratesPerPurpose5_4.put("Employee Secondary Sector Rest", 0.04); - ratesPerPurpose5_4.put("Employee Retail", 0.04); - ratesPerPurpose5_4.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose5_4.put("Employee Tertiary Sector Rest", 0.04); - - ratesPerPurpose5_5.put("Inhabitants", 0.06); - ratesPerPurpose5_5.put("Employee", 0.0); - ratesPerPurpose5_5.put("Employee Primary Sector", 0.28); - ratesPerPurpose5_5.put("Employee Construction", 0.28); - ratesPerPurpose5_5.put("Employee Secondary Sector Rest", 0.28); - ratesPerPurpose5_5.put("Employee Retail", 0.28); - ratesPerPurpose5_5.put("Employee Traffic/Parcels", 0.58); - ratesPerPurpose5_5.put("Employee Tertiary Sector Rest", 0.28); - - ratesPerPurpose6_1.put("Inhabitants", 0.0); - ratesPerPurpose6_1.put("Employee", 0.0); - ratesPerPurpose6_1.put("Employee Primary Sector", 0.0); - ratesPerPurpose6_1.put("Employee Construction", 0.0); - ratesPerPurpose6_1.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose6_1.put("Employee Retail", 0.0); - ratesPerPurpose6_1.put("Employee Traffic/Parcels", 0.0); - ratesPerPurpose6_1.put("Employee Tertiary Sector Rest", 0.0); - - ratesPerPurpose6_2.put("Inhabitants", 0.85); - ratesPerPurpose6_2.put("Employee", 0.0); - ratesPerPurpose6_2.put("Employee Primary Sector", 0.21); - ratesPerPurpose6_2.put("Employee Construction", 0.21); - ratesPerPurpose6_2.put("Employee Secondary Sector Rest", 0.21); - ratesPerPurpose6_2.put("Employee Retail", 0.21); - ratesPerPurpose6_2.put("Employee Traffic/Parcels", 0.09); - ratesPerPurpose6_2.put("Employee Tertiary Sector Rest", 0.21); - - ratesPerPurpose6_3.put("Inhabitants", 0.15); - ratesPerPurpose6_3.put("Employee", 0.0); - ratesPerPurpose6_3.put("Employee Primary Sector", 0.58); - ratesPerPurpose6_3.put("Employee Construction", 0.58); - ratesPerPurpose6_3.put("Employee Secondary Sector Rest", 0.58); - ratesPerPurpose6_3.put("Employee Retail", 0.58); - ratesPerPurpose6_3.put("Employee Traffic/Parcels", 0.55); - ratesPerPurpose6_3.put("Employee Tertiary Sector Rest", 0.58); - - ratesPerPurpose6_4.put("Inhabitants", 0.0); - ratesPerPurpose6_4.put("Employee", 0.0); - ratesPerPurpose6_4.put("Employee Primary Sector", 0.21); - ratesPerPurpose6_4.put("Employee Construction", 0.21); - ratesPerPurpose6_4.put("Employee Secondary Sector Rest", 0.21); - ratesPerPurpose6_4.put("Employee Retail", 0.21); - ratesPerPurpose6_4.put("Employee Traffic/Parcels", 0.25); - ratesPerPurpose6_4.put("Employee Tertiary Sector Rest", 0.21); - - ratesPerPurpose6_5.put("Inhabitants", 0.0); - ratesPerPurpose6_5.put("Employee", 0.0); - ratesPerPurpose6_5.put("Employee Primary Sector", 0.0); - ratesPerPurpose6_5.put("Employee Construction", 0.0); - ratesPerPurpose6_5.put("Employee Secondary Sector Rest", 0.0); - ratesPerPurpose6_5.put("Employee Retail", 0.0); - ratesPerPurpose6_5.put("Employee Traffic/Parcels", 0.11); - ratesPerPurpose6_5.put("Employee Tertiary Sector Rest", 0.0); - } - commitmentRates.put("1_1", ratesPerPurpose1_1); - commitmentRates.put("1_2", ratesPerPurpose1_2); - commitmentRates.put("1_3", ratesPerPurpose1_3); - commitmentRates.put("1_4", ratesPerPurpose1_4); - commitmentRates.put("1_5", ratesPerPurpose1_5); - commitmentRates.put("2_1", ratesPerPurpose2_1); - commitmentRates.put("2_2", ratesPerPurpose2_2); - commitmentRates.put("2_3", ratesPerPurpose2_3); - commitmentRates.put("2_4", ratesPerPurpose2_4); - commitmentRates.put("2_5", ratesPerPurpose2_5); - commitmentRates.put("3_1", ratesPerPurpose3_1); - commitmentRates.put("3_2", ratesPerPurpose3_2); - commitmentRates.put("3_3", ratesPerPurpose3_3); - commitmentRates.put("3_4", ratesPerPurpose3_4); - commitmentRates.put("3_5", ratesPerPurpose3_5); - commitmentRates.put("4_1", ratesPerPurpose4_1); - commitmentRates.put("4_2", ratesPerPurpose4_2); - commitmentRates.put("4_3", ratesPerPurpose4_3); - commitmentRates.put("4_4", ratesPerPurpose4_4); - commitmentRates.put("4_5", ratesPerPurpose4_5); - commitmentRates.put("5_1", ratesPerPurpose5_1); - commitmentRates.put("5_2", ratesPerPurpose5_2); - commitmentRates.put("5_3", ratesPerPurpose5_3); - commitmentRates.put("5_4", ratesPerPurpose5_4); - commitmentRates.put("5_5", ratesPerPurpose5_5); - commitmentRates.put("6_1", ratesPerPurpose6_1); - commitmentRates.put("6_2", ratesPerPurpose6_2); - commitmentRates.put("6_3", ratesPerPurpose6_3); - commitmentRates.put("6_4", ratesPerPurpose6_4); - commitmentRates.put("6_5", ratesPerPurpose6_5); - } - return commitmentRates; - } } diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/UnhandledServicesSolution.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/UnhandledServicesSolution.java new file mode 100644 index 00000000000..c65c75deee7 --- /dev/null +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/UnhandledServicesSolution.java @@ -0,0 +1,39 @@ +package org.matsim.smallScaleCommercialTrafficGeneration; + +import org.matsim.api.core.v01.Scenario; +import org.matsim.freight.carriers.Carrier; + +import java.util.List; + +/** + * When generating service-durations for {@link Carrier}s it may happen service durations of their plans + * are too long to be fully handled. This implementation solves this problem. + */ +public interface UnhandledServicesSolution { + + /** + * @param scenario Scenario to search for carriers with unhandled jobs + * @return List with the found carriers + */ + List createListOfCarrierWithUnhandledJobs(Scenario scenario); + + /** + * + * Checks and recalculates plans of carriers, which did not serve all services. + * This step may take a few minutes. + * @param scenario Scenario to handle the carriers for. Needed to execute {@link org.matsim.freight.carriers.CarriersUtils#runJsprit(Scenario)} and {@link UnhandledServicesSolution#createListOfCarrierWithUnhandledJobs(Scenario)} + * @param nonCompleteSolvedCarriers List of carriers, that are not solved. Can be obtained by {@link UnhandledServicesSolution#createListOfCarrierWithUnhandledJobs(Scenario)} + */ + void tryToSolveAllCarriersCompletely(Scenario scenario, List nonCompleteSolvedCarriers); + + /** + * Change the service duration for a given carrier, because the service could not be handled in the last solution. + * + * @param carrier The carrier for which we generate the serviceTime + * @param carrierAttributes attributes of the carrier to generate the service time for. + * @param key key for the service duration + * @param additionalTravelBufferPerIterationInMinutes additional buffer for the travel time + * @return new service duration + */ + int changeServiceTimePerStop(Carrier carrier, GenerateSmallScaleCommercialTrafficDemand.CarrierAttributes carrierAttributes, GenerateSmallScaleCommercialTrafficDemand.ServiceDurationPerCategoryKey key, int additionalTravelBufferPerIterationInMinutes); +} diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/VehicleAvailabilityAllocator.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/VehicleAvailabilityAllocator.java new file mode 100644 index 00000000000..e13cce7efcf --- /dev/null +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/VehicleAvailabilityAllocator.java @@ -0,0 +1,106 @@ +package org.matsim.smallScaleCommercialTrafficGeneration; + +import java.util.*; + +/** + * A small allocator to solve the time-window problems in the Vehicle and Service generation using a Best-Fit Allocator.
+ * NOTE: This class does not actually change anything in the scenario. It is just a tool to check if Service and Vehicle TimeWindows are + * compatible. + */ +public class VehicleAvailabilityAllocator { + private List availableVehicleTime; + + /** + * Prepares the allocator for a vehicle fleet. + * @param availableVehicleTime This Collection should contain the duration of available-time-frames of the vehicles. + * For example: 4x vehicles are available from 1:00 to 4:00 (3 hours), then the {@code availableVehicles} Collection should + * contain 4 entries with value: 3*3600=10800. If a vehicle has a non-coherent availability-time-frame, add it as two + * separate entries. + */ + public VehicleAvailabilityAllocator(List availableVehicleTime){ + this.availableVehicleTime = availableVehicleTime; + } + + /** + * Prepares the allocator for one vehicle. + * @param availableVehicleTime This Collection should contain the duration of available-time-frames of the vehicle. + */ + public VehicleAvailabilityAllocator(double availableVehicleTime){ + this.availableVehicleTime = new ArrayList<>(1); + this.availableVehicleTime.add(availableVehicleTime); + } + + /** + * Checks if a vehicle is available for the given amount of time. If not, then the time is set to the largest possible duration, + * which can be allocated. + * @return the reduced serviceDuration (unchanged, if a vehicle was found, that was available for the full duration) + */ + public double makeServiceDurationViable(double serviceDuration){ + for(Double vehicleTime : availableVehicleTime){ + if(vehicleTime >= serviceDuration) return serviceDuration; + } + return availableVehicleTime.stream().mapToDouble(v -> v).max().orElseThrow(); + } + + /** + * Tries to allocate a single vehicle to the service and reduces the allocated vehicle available time by the serviceDuration. + * If no vehicle is available nothing happens. You should then consider to reduce the duration with {@link VehicleAvailabilityAllocator#makeServiceDurationViable} + * @return true if a vehicle was allocated, false if no vehicle is available for the given duration + */ + public boolean allocateServiceDuration(double serviceDuration){ + //Best-Fit Allocation + int bestFit = -1; + double bestRemaining = Double.MAX_VALUE; + for(int i = 0; i < availableVehicleTime.size(); i++){ + double remaining = availableVehicleTime.get(i) - serviceDuration; + if(remaining >= 0 && remaining < bestRemaining){ + bestFit = i; + bestRemaining = remaining; + } + } + if(bestFit == -1) return false; + //Allocate + availableVehicleTime.set(bestFit, availableVehicleTime.get(bestFit) - serviceDuration); + return true; + } + + /** + * This method checks for a given amount of same serviceDurations, whether you can allocate a vehicle to all of them or not. + * If not, the Allocator reduces the serviceDurations in a balanced way, so that the duration-cutoff is distributed across all given services. + * If you do not care if some services get much more time than others, you can use the {@link VehicleAvailabilityAllocator#makeServiceDurationViable} method. + * @param serviceDuration The duration of the services. + * @return An array which contains the maximum possible service durations (reverse order) + */ + public double makeMultipleServiceDurationsBalancedViable(int serviceAmount, double serviceDuration){ + //Check for serviceDuration first + int allocatedServices = 0; + for (Double d : availableVehicleTime) { + allocatedServices += (int) Math.floor(d / serviceDuration); + } + + if(allocatedServices >= serviceAmount){ + return serviceDuration; + } + + //If not found yet, get the best next value + double lastValue = Double.POSITIVE_INFINITY; + while(true){ + //Get largest value below lastValue + double thisValue = 0; + for(double d : availableVehicleTime){ + if(d > thisValue && d < lastValue) thisValue = d; + } + + allocatedServices = 0; + for (Double d : availableVehicleTime) { + allocatedServices += (int) Math.floor(d / thisValue); + } + + if(allocatedServices >= serviceAmount){ + return thisValue; + } + + lastValue = thisValue; + } + } +} diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/VehicleSelection.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/VehicleSelection.java new file mode 100644 index 00000000000..fdcf721a98d --- /dev/null +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/VehicleSelection.java @@ -0,0 +1,31 @@ +package org.matsim.smallScaleCommercialTrafficGeneration; + +import java.util.ArrayList; +import java.util.List; +/** + * Interface to set the categories needed by {@link GenerateSmallScaleCommercialTrafficDemand}. + * Standard implementation is {@link DefaultVehicleSelection}. + * Any configuration settings and external data-sources should be saved as attributes during initialization in the constructor of the class. + */ +public interface VehicleSelection{ + + class OdMatrixEntryInformation { + double occupancyRate; + String[] possibleVehicleTypes; + List possibleStartCategories = new ArrayList<>(); + List possibleStopCategories = new ArrayList<>(); + } + + /** + * @return all possible stop/start-categories. + */ + List getAllCategories(); + + /** + * @param purpose entry from {@link TripDistributionMatrix#getListOfPurposes()} + * @param modeORvehType entry from {@link TripDistributionMatrix#getListOfModesOrVehTypes()} + * @param smallScaleCommercialTrafficType Selected traffic types. Options: commercialPersonTraffic, goodsTraffic + * @return class holding the information that is specified by the given entry. + */ + OdMatrixEntryInformation getOdMatrixEntryInformation(int purpose, String modeORvehType, String smallScaleCommercialTrafficType); +} 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/CommercialTourSpecifications.java similarity index 71% rename from contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/GetCommercialTourSpecifications.java rename to contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/CommercialTourSpecifications.java index ce6bce3c04c..5cd6256c1ea 100644 --- 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/CommercialTourSpecifications.java @@ -6,25 +6,23 @@ import java.util.Map; -public interface GetCommercialTourSpecifications { +public interface CommercialTourSpecifications { /** * 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); + Map> createStopDurationDistributionPerCategory( + 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); + Map> createTourDistribution(RandomGenerator rng); /** * Creates the probability distribution for the tour start times for the day. 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 index ec4bd9640ab..46f6887f0cd 100644 --- 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 @@ -10,1279 +10,1787 @@ import java.util.List; import java.util.Map; -import static org.matsim.smallScaleCommercialTrafficGeneration.GenerateSmallScaleCommercialTrafficDemand.makeStopDurationGoodTrafficKey; +import static org.matsim.smallScaleCommercialTrafficGeneration.GenerateSmallScaleCommercialTrafficDemand.makeServiceDurationPerCategoryKey; -public class DefaultTourSpecificationsByUsingKID2002 implements GetCommercialTourSpecifications { +public class DefaultTourSpecificationsByUsingKID2002 implements CommercialTourSpecifications { @Override - public Map> createStopDurationDistributionPerCategory(String smallScaleCommercialTrafficType, RandomGenerator rng) { - Map> stopDurationProbabilityDistribution = new HashMap<>(); + public Map> createStopDurationDistributionPerCategory( + 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(); + 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(makeServiceDurationPerCategoryKey("Employee Primary Sector", null, + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Construction", null, + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Secondary Sector Rest", null, + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Retail", null, + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Traffic/Parcels", null, + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString()), + 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)); + 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(makeServiceDurationPerCategoryKey("Employee Tertiary Sector Rest", null, + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString()), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); - } 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.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(makeServiceDurationPerCategoryKey("Employee Primary Sector", "vehTyp1", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Primary Sector", "vehTyp2", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Primary Sector", "vehTyp3", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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(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(makeServiceDurationPerCategoryKey("Employee Primary Sector", "vehTyp4", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Primary Sector", "vehTyp5", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Construction", "vehTyp1", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Construction", "vehTyp2", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Construction", "vehTyp3", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Construction", "vehTyp4", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Construction", "vehTyp5", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Secondary Sector Rest", "vehTyp1", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Secondary Sector Rest", "vehTyp2", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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(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(makeServiceDurationPerCategoryKey("Employee Secondary Sector Rest", "vehTyp3", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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(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(makeServiceDurationPerCategoryKey("Employee Secondary Sector Rest", "vehTyp4", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Secondary Sector Rest", "vehTyp5", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Retail", "vehTyp1", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Retail", "vehTyp2", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Retail", "vehTyp3", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Retail", "vehTyp4", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Retail", "vehTyp5", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Traffic/Parcels", "vehTyp1", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Traffic/Parcels", "vehTyp2", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Traffic/Parcels", "vehTyp3", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Traffic/Parcels", "vehTyp4", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Traffic/Parcels", "vehTyp5", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Tertiary Sector Rest", "vehTyp1", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Employee Tertiary Sector Rest", "vehTyp2", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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(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(makeServiceDurationPerCategoryKey("Employee Tertiary Sector Rest", "vehTyp3", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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(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(makeServiceDurationPerCategoryKey("Employee Tertiary Sector Rest", "vehTyp4", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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(); + 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(makeServiceDurationPerCategoryKey("Employee Tertiary Sector Rest", "vehTyp5", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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(); + // 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(makeServiceDurationPerCategoryKey("Inhabitants", "vehTyp1", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Inhabitants", "vehTyp2", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Inhabitants", "vehTyp3", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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.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(makeServiceDurationPerCategoryKey("Inhabitants", "vehTyp4", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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(makeServiceDurationPerCategoryKey("Inhabitants", "vehTyp5", + GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString()), + 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) { + public Map> createTourDistribution( + RandomGenerator rng) { + Map> tourDistribution = new HashMap<>(); 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)); - 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())) { + tourDistribution.put(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString(), + new EnumeratedDistribution<>(rng, tourDurationProbabilityDistribution)); + tourDurationProbabilityDistribution.clear(); - 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); + 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)); - return new EnumeratedDistribution<>(rng, tourDurationProbabilityDistribution); + tourDistribution.put(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString(), + new EnumeratedDistribution<>(rng, tourDurationProbabilityDistribution)); + return tourDistribution; } @Override diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/GetGenerationRates.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/GetGenerationRates.java new file mode 100644 index 00000000000..5ed6ab36660 --- /dev/null +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/GetGenerationRates.java @@ -0,0 +1,856 @@ +package org.matsim.smallScaleCommercialTrafficGeneration.data; + +import java.util.HashMap; +import java.util.Map; + +public interface GetGenerationRates { + /** + * Sets the generation rates based on the IVV 2005 + * + * @param smallScaleCommercialTrafficType used trafficType (freight or business traffic) + * @param generationType start or stop rates + */ + static Map> setGenerationRates(String smallScaleCommercialTrafficType, + String generationType) { + + Map> generationRates = new HashMap<>(); + Map ratesPerPurpose1 = new HashMap<>(); + Map ratesPerPurpose2 = new HashMap<>(); + Map ratesPerPurpose3 = new HashMap<>(); + Map ratesPerPurpose4 = new HashMap<>(); + Map ratesPerPurpose5 = new HashMap<>(); + Map ratesPerPurpose6 = new HashMap<>(); + if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic")) { + if (generationType.equals("start")) { + ratesPerPurpose1.put("Inhabitants", 0.0); + ratesPerPurpose1.put("Employee", 0.0); + ratesPerPurpose1.put("Employee Primary Sector", 0.0); + ratesPerPurpose1.put("Employee Construction", 0.0); + ratesPerPurpose1.put("Employee Secondary Sector Rest", 0.059); + ratesPerPurpose1.put("Employee Retail", 0.0); + ratesPerPurpose1.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose1.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose2.put("Inhabitants", 0.0); + ratesPerPurpose2.put("Employee", 0.029); + ratesPerPurpose2.put("Employee Primary Sector", 0.0); + ratesPerPurpose2.put("Employee Construction", 0.0); + ratesPerPurpose2.put("Employee Secondary Sector Rest", 0.045); + ratesPerPurpose2.put("Employee Retail", 0.0); + ratesPerPurpose2.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose2.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose3.put("Inhabitants", 0.0); + ratesPerPurpose3.put("Employee", 0.021); + ratesPerPurpose3.put("Employee Primary Sector", 0.0); + ratesPerPurpose3.put("Employee Construction", 0.0); + ratesPerPurpose3.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose3.put("Employee Retail", 0.0192); + ratesPerPurpose3.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose3.put("Employee Tertiary Sector Rest", 0.184); + + ratesPerPurpose4.put("Inhabitants", 0.0); + ratesPerPurpose4.put("Employee", 0.021); + ratesPerPurpose4.put("Employee Primary Sector", 0.0); + ratesPerPurpose4.put("Employee Construction", 0.0); + ratesPerPurpose4.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose4.put("Employee Retail", 0.0); + ratesPerPurpose4.put("Employee Traffic/Parcels", 0.203); + ratesPerPurpose4.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose5.put("Inhabitants", 0.0); + ratesPerPurpose5.put("Employee", 0.03); + ratesPerPurpose5.put("Employee Primary Sector", 0.0); + ratesPerPurpose5.put("Employee Construction", 0.29); + ratesPerPurpose5.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose5.put("Employee Retail", 0.0); + ratesPerPurpose5.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose5.put("Employee Tertiary Sector Rest", 0.0); + } else if (generationType.equals("stop")) { + ratesPerPurpose1.put("Inhabitants", 0.0); + ratesPerPurpose1.put("Employee", 0.0); + ratesPerPurpose1.put("Employee Primary Sector", 0.0); + ratesPerPurpose1.put("Employee Construction", 0.0); + ratesPerPurpose1.put("Employee Secondary Sector Rest", 0.02); + ratesPerPurpose1.put("Employee Retail", 0.0); + ratesPerPurpose1.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose1.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose2.put("Inhabitants", 0.002); + ratesPerPurpose2.put("Employee", 0.0); + ratesPerPurpose2.put("Employee Primary Sector", 0.029); + ratesPerPurpose2.put("Employee Construction", 0.029); + ratesPerPurpose2.put("Employee Secondary Sector Rest", 0.009); + ratesPerPurpose2.put("Employee Retail", 0.029); + ratesPerPurpose2.put("Employee Traffic/Parcels", 0.039); + ratesPerPurpose2.put("Employee Tertiary Sector Rest", 0.029); + + ratesPerPurpose3.put("Inhabitants", 0.025); + ratesPerPurpose3.put("Employee", 0.0); + ratesPerPurpose3.put("Employee Primary Sector", 0.0168); + ratesPerPurpose3.put("Employee Construction", 0.168); + ratesPerPurpose3.put("Employee Secondary Sector Rest", 0.0168); + ratesPerPurpose3.put("Employee Retail", 0.0168); + ratesPerPurpose3.put("Employee Traffic/Parcels", 0.097); + ratesPerPurpose3.put("Employee Tertiary Sector Rest", 0.168); + + ratesPerPurpose4.put("Inhabitants", 0.002); + ratesPerPurpose4.put("Employee", 0.0); + ratesPerPurpose4.put("Employee Primary Sector", 0.025); + ratesPerPurpose4.put("Employee Construction", 0.025); + ratesPerPurpose4.put("Employee Secondary Sector Rest", 0.025); + ratesPerPurpose4.put("Employee Retail", 0.025); + ratesPerPurpose4.put("Employee Traffic/Parcels", 0.075); + ratesPerPurpose4.put("Employee Tertiary Sector Rest", 0.025); + + ratesPerPurpose5.put("Inhabitants", 0.004); + ratesPerPurpose5.put("Employee", 0.0); + ratesPerPurpose5.put("Employee Primary Sector", 0.015); + ratesPerPurpose5.put("Employee Construction", 0.002); + ratesPerPurpose5.put("Employee Secondary Sector Rest", 0.015); + ratesPerPurpose5.put("Employee Retail", 0.015); + ratesPerPurpose5.put("Employee Traffic/Parcels", 0.02); + ratesPerPurpose5.put("Employee Tertiary Sector Rest", 0.015); + + } + } else if (smallScaleCommercialTrafficType.equals("goodsTraffic")) { + if (generationType.equals("start")) { + ratesPerPurpose1.put("Inhabitants", 0.0); + ratesPerPurpose1.put("Employee", 0.0); + ratesPerPurpose1.put("Employee Primary Sector", 0.0); + ratesPerPurpose1.put("Employee Construction", 0.0); + ratesPerPurpose1.put("Employee Secondary Sector Rest", 0.023); + ratesPerPurpose1.put("Employee Retail", 0.0); + ratesPerPurpose1.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose1.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose2.put("Inhabitants", 0.0); + ratesPerPurpose2.put("Employee", 0.002); + ratesPerPurpose2.put("Employee Primary Sector", 0.0); + ratesPerPurpose2.put("Employee Construction", 0.0); + ratesPerPurpose2.put("Employee Secondary Sector Rest", 0.049); + ratesPerPurpose2.put("Employee Retail", 0.0); + ratesPerPurpose2.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose2.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose3.put("Inhabitants", 0.0); + ratesPerPurpose3.put("Employee", 0.002); + ratesPerPurpose3.put("Employee Primary Sector", 0.0); + ratesPerPurpose3.put("Employee Construction", 0.0); + ratesPerPurpose3.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose3.put("Employee Retail", 0.139); + ratesPerPurpose3.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose3.put("Employee Tertiary Sector Rest", 0.059); + + ratesPerPurpose4.put("Inhabitants", 0.0); + ratesPerPurpose4.put("Employee", 0.002); + ratesPerPurpose4.put("Employee Primary Sector", 0.0); + ratesPerPurpose4.put("Employee Construction", 0.0); + ratesPerPurpose4.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose4.put("Employee Retail", 0.0); + ratesPerPurpose4.put("Employee Traffic/Parcels", 0.333); + ratesPerPurpose4.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose5.put("Inhabitants", 0.0); + ratesPerPurpose5.put("Employee", 0.002); + ratesPerPurpose5.put("Employee Primary Sector", 0.0); + ratesPerPurpose5.put("Employee Construction", 0.220); + ratesPerPurpose5.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose5.put("Employee Retail", 0.0); + ratesPerPurpose5.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose5.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose6.put("Inhabitants", 0.009); + ratesPerPurpose6.put("Employee", 0.0); + ratesPerPurpose6.put("Employee Primary Sector", 0.0); + ratesPerPurpose6.put("Employee Construction", 0.0); + ratesPerPurpose6.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose6.put("Employee Retail", 0.0); + ratesPerPurpose6.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose6.put("Employee Tertiary Sector Rest", 0.0); + + } else if (generationType.equals("stop")) { + ratesPerPurpose1.put("Inhabitants", 0.0); + ratesPerPurpose1.put("Employee", 0.0); + ratesPerPurpose1.put("Employee Primary Sector", 0.0); + ratesPerPurpose1.put("Employee Construction", 0.0); + ratesPerPurpose1.put("Employee Secondary Sector Rest", 0.031); + ratesPerPurpose1.put("Employee Retail", 0.0); + ratesPerPurpose1.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose1.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose2.put("Inhabitants", 0.001); + ratesPerPurpose2.put("Employee", 0.0); + ratesPerPurpose2.put("Employee Primary Sector", 0.001); + ratesPerPurpose2.put("Employee Construction", 0.01); + ratesPerPurpose2.put("Employee Secondary Sector Rest", 0.011); + ratesPerPurpose2.put("Employee Retail", 0.021); + ratesPerPurpose2.put("Employee Traffic/Parcels", 0.001); + ratesPerPurpose2.put("Employee Tertiary Sector Rest", 0.001); + + ratesPerPurpose3.put("Inhabitants", 0.009); + ratesPerPurpose3.put("Employee", 0.0); + ratesPerPurpose3.put("Employee Primary Sector", 0.02); + ratesPerPurpose3.put("Employee Construction", 0.005); + ratesPerPurpose3.put("Employee Secondary Sector Rest", 0.029); + ratesPerPurpose3.put("Employee Retail", 0.055); + ratesPerPurpose3.put("Employee Traffic/Parcels", 0.02); + ratesPerPurpose3.put("Employee Tertiary Sector Rest", 0.02); + + ratesPerPurpose4.put("Inhabitants", 0.014); + ratesPerPurpose4.put("Employee", 0.0); + ratesPerPurpose4.put("Employee Primary Sector", 0.02); + ratesPerPurpose4.put("Employee Construction", 0.002); + ratesPerPurpose4.put("Employee Secondary Sector Rest", 0.11); + ratesPerPurpose4.put("Employee Retail", 0.154); + ratesPerPurpose4.put("Employee Traffic/Parcels", 0.02); + ratesPerPurpose4.put("Employee Tertiary Sector Rest", 0.02); + + ratesPerPurpose5.put("Inhabitants", 0.002); + ratesPerPurpose5.put("Employee", 0.0); + ratesPerPurpose5.put("Employee Primary Sector", 0.005); + ratesPerPurpose5.put("Employee Construction", 0.002); + ratesPerPurpose5.put("Employee Secondary Sector Rest", 0.01); + ratesPerPurpose5.put("Employee Retail", 0.01); + ratesPerPurpose5.put("Employee Traffic/Parcels", 0.005); + ratesPerPurpose5.put("Employee Tertiary Sector Rest", 0.005); + + ratesPerPurpose6.put("Inhabitants", 0.002); + ratesPerPurpose6.put("Employee", 0.0); + ratesPerPurpose6.put("Employee Primary Sector", 0.005); + ratesPerPurpose6.put("Employee Construction", 0.002); + ratesPerPurpose6.put("Employee Secondary Sector Rest", 0.01); + ratesPerPurpose6.put("Employee Retail", 0.01); + ratesPerPurpose6.put("Employee Traffic/Parcels", 0.005); + ratesPerPurpose6.put("Employee Tertiary Sector Rest", 0.005); + } + generationRates.put(6, ratesPerPurpose6); + } + generationRates.put(1, ratesPerPurpose1); + generationRates.put(2, ratesPerPurpose2); + generationRates.put(3, ratesPerPurpose3); + generationRates.put(4, ratesPerPurpose4); + generationRates.put(5, ratesPerPurpose5); + return generationRates; + } + + /** + * Sets the commitment rates based on the IVV 2005 for the goodsTraffic. The + * commitment rate for the commercialPersonTraffic is 1, because mode choice will be + * done in MATSim. + * + * @param smallScaleCommercialTrafficType used trafficType (freight or business traffic) + * @param commitmentType start or stop parameter + */ + static Map> setCommitmentRates(String smallScaleCommercialTrafficType, + String commitmentType) { + Map> commitmentRates = new HashMap<>(); + + if (smallScaleCommercialTrafficType.equals("goodsTraffic")) { + + // the first number is the purpose; second number the vehicle type + Map ratesPerPurpose1_1 = new HashMap<>(); + Map ratesPerPurpose1_2 = new HashMap<>(); + Map ratesPerPurpose1_3 = new HashMap<>(); + Map ratesPerPurpose1_4 = new HashMap<>(); + Map ratesPerPurpose1_5 = new HashMap<>(); + Map ratesPerPurpose2_1 = new HashMap<>(); + Map ratesPerPurpose2_2 = new HashMap<>(); + Map ratesPerPurpose2_3 = new HashMap<>(); + Map ratesPerPurpose2_4 = new HashMap<>(); + Map ratesPerPurpose2_5 = new HashMap<>(); + Map ratesPerPurpose3_1 = new HashMap<>(); + Map ratesPerPurpose3_2 = new HashMap<>(); + Map ratesPerPurpose3_3 = new HashMap<>(); + Map ratesPerPurpose3_4 = new HashMap<>(); + Map ratesPerPurpose3_5 = new HashMap<>(); + Map ratesPerPurpose4_1 = new HashMap<>(); + Map ratesPerPurpose4_2 = new HashMap<>(); + Map ratesPerPurpose4_3 = new HashMap<>(); + Map ratesPerPurpose4_4 = new HashMap<>(); + Map ratesPerPurpose4_5 = new HashMap<>(); + Map ratesPerPurpose5_1 = new HashMap<>(); + Map ratesPerPurpose5_2 = new HashMap<>(); + Map ratesPerPurpose5_3 = new HashMap<>(); + Map ratesPerPurpose5_4 = new HashMap<>(); + Map ratesPerPurpose5_5 = new HashMap<>(); + Map ratesPerPurpose6_1 = new HashMap<>(); + Map ratesPerPurpose6_2 = new HashMap<>(); + Map ratesPerPurpose6_3 = new HashMap<>(); + Map ratesPerPurpose6_4 = new HashMap<>(); + Map ratesPerPurpose6_5 = new HashMap<>(); + if (commitmentType.equals("start")) { + ratesPerPurpose1_1.put("Inhabitants", 0.0); + ratesPerPurpose1_1.put("Employee", 0.8); + ratesPerPurpose1_1.put("Employee Primary Sector", 0.0); + ratesPerPurpose1_1.put("Employee Construction", 0.0); + ratesPerPurpose1_1.put("Employee Secondary Sector Rest", 0.44); + ratesPerPurpose1_1.put("Employee Retail", 0.0); + ratesPerPurpose1_1.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose1_1.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose1_2.put("Inhabitants", 0.0); + ratesPerPurpose1_2.put("Employee", 0.1); + ratesPerPurpose1_2.put("Employee Primary Sector", 0.0); + ratesPerPurpose1_2.put("Employee Construction", 0.0); + ratesPerPurpose1_2.put("Employee Secondary Sector Rest", 0.11); + ratesPerPurpose1_2.put("Employee Retail", 0.0); + ratesPerPurpose1_2.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose1_2.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose1_3.put("Inhabitants", 0.0); + ratesPerPurpose1_3.put("Employee", 0.1); + ratesPerPurpose1_3.put("Employee Primary Sector", 0.0); + ratesPerPurpose1_3.put("Employee Construction", 0.0); + ratesPerPurpose1_3.put("Employee Secondary Sector Rest", 0.22); + ratesPerPurpose1_3.put("Employee Retail", 0.0); + ratesPerPurpose1_3.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose1_3.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose1_4.put("Inhabitants", 0.0); + ratesPerPurpose1_4.put("Employee", 0.0); + ratesPerPurpose1_4.put("Employee Primary Sector", 0.0); + ratesPerPurpose1_4.put("Employee Construction", 0.0); + ratesPerPurpose1_4.put("Employee Secondary Sector Rest", 0.06); + ratesPerPurpose1_4.put("Employee Retail", 0.0); + ratesPerPurpose1_4.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose1_4.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose1_5.put("Inhabitants", 0.0); + ratesPerPurpose1_5.put("Employee", 0.0); + ratesPerPurpose1_5.put("Employee Primary Sector", 0.0); + ratesPerPurpose1_5.put("Employee Construction", 0.0); + ratesPerPurpose1_5.put("Employee Secondary Sector Rest", 0.16); + ratesPerPurpose1_5.put("Employee Retail", 0.0); + ratesPerPurpose1_5.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose1_5.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose2_1.put("Inhabitants", 0.0); + ratesPerPurpose2_1.put("Employee", 0.8); + ratesPerPurpose2_1.put("Employee Primary Sector", 0.0); + ratesPerPurpose2_1.put("Employee Construction", 0.0); + ratesPerPurpose2_1.put("Employee Secondary Sector Rest", 0.44); + ratesPerPurpose2_1.put("Employee Retail", 0.0); + ratesPerPurpose2_1.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose2_1.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose2_2.put("Inhabitants", 0.0); + ratesPerPurpose2_2.put("Employee", 0.1); + ratesPerPurpose2_2.put("Employee Primary Sector", 0.0); + ratesPerPurpose2_2.put("Employee Construction", 0.0); + ratesPerPurpose2_2.put("Employee Secondary Sector Rest", 0.11); + ratesPerPurpose2_2.put("Employee Retail", 0.0); + ratesPerPurpose2_2.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose2_2.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose2_3.put("Inhabitants", 0.0); + ratesPerPurpose2_3.put("Employee", 0.1); + ratesPerPurpose2_3.put("Employee Primary Sector", 0.0); + ratesPerPurpose2_3.put("Employee Construction", 0.0); + ratesPerPurpose2_3.put("Employee Secondary Sector Rest", 0.22); + ratesPerPurpose2_3.put("Employee Retail", 0.0); + ratesPerPurpose2_3.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose2_3.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose2_4.put("Inhabitants", 0.0); + ratesPerPurpose2_4.put("Employee", 0.0); + ratesPerPurpose2_4.put("Employee Primary Sector", 0.0); + ratesPerPurpose2_4.put("Employee Construction", 0.0); + ratesPerPurpose2_4.put("Employee Secondary Sector Rest", 0.06); + ratesPerPurpose2_4.put("Employee Retail", 0.0); + ratesPerPurpose2_4.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose2_4.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose2_5.put("Inhabitants", 0.0); + ratesPerPurpose2_5.put("Employee", 0.0); + ratesPerPurpose2_5.put("Employee Primary Sector", 0.0); + ratesPerPurpose2_5.put("Employee Construction", 0.0); + ratesPerPurpose2_5.put("Employee Secondary Sector Rest", 0.16); + ratesPerPurpose2_5.put("Employee Retail", 0.0); + ratesPerPurpose2_5.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose2_5.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose3_1.put("Inhabitants", 0.0); + ratesPerPurpose3_1.put("Employee", 0.8); + ratesPerPurpose3_1.put("Employee Primary Sector", 0.0); + ratesPerPurpose3_1.put("Employee Construction", 0.0); + ratesPerPurpose3_1.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose3_1.put("Employee Retail", 0.46); + ratesPerPurpose3_1.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose3_1.put("Employee Tertiary Sector Rest", 0.54); + + ratesPerPurpose3_2.put("Inhabitants", 0.0); + ratesPerPurpose3_2.put("Employee", 0.1); + ratesPerPurpose3_2.put("Employee Primary Sector", 0.0); + ratesPerPurpose3_2.put("Employee Construction", 0.0); + ratesPerPurpose3_2.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose3_2.put("Employee Retail", 0.1); + ratesPerPurpose3_2.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose3_2.put("Employee Tertiary Sector Rest", 0.1); + + ratesPerPurpose3_3.put("Inhabitants", 0.0); + ratesPerPurpose3_3.put("Employee", 0.1); + ratesPerPurpose3_3.put("Employee Primary Sector", 0.0); + ratesPerPurpose3_3.put("Employee Construction", 0.0); + ratesPerPurpose3_3.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose3_3.put("Employee Retail", 0.23); + ratesPerPurpose3_3.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose3_3.put("Employee Tertiary Sector Rest", 0.2); + + ratesPerPurpose3_4.put("Inhabitants", 0.0); + ratesPerPurpose3_4.put("Employee", 0.0); + ratesPerPurpose3_4.put("Employee Primary Sector", 0.0); + ratesPerPurpose3_4.put("Employee Construction", 0.0); + ratesPerPurpose3_4.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose3_4.put("Employee Retail", 0.06); + ratesPerPurpose3_4.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose3_4.put("Employee Tertiary Sector Rest", 0.02); + + ratesPerPurpose3_5.put("Inhabitants", 0.0); + ratesPerPurpose3_5.put("Employee", 0.0); + ratesPerPurpose3_5.put("Employee Primary Sector", 0.0); + ratesPerPurpose3_5.put("Employee Construction", 0.0); + ratesPerPurpose3_5.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose3_5.put("Employee Retail", 0.15); + ratesPerPurpose3_5.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose3_5.put("Employee Tertiary Sector Rest", 0.14); + + ratesPerPurpose4_1.put("Inhabitants", 0.009); + ratesPerPurpose4_1.put("Employee", 0.8); + ratesPerPurpose4_1.put("Employee Primary Sector", 0.0); + ratesPerPurpose4_1.put("Employee Construction", 0.0); + ratesPerPurpose4_1.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose4_1.put("Employee Retail", 0.0); + ratesPerPurpose4_1.put("Employee Traffic/Parcels", 0.18); + ratesPerPurpose4_1.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose4_2.put("Inhabitants", 0.0); + ratesPerPurpose4_2.put("Employee", 0.1); + ratesPerPurpose4_2.put("Employee Primary Sector", 0.0); + ratesPerPurpose4_2.put("Employee Construction", 0.0); + ratesPerPurpose4_2.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose4_2.put("Employee Retail", 0.0); + ratesPerPurpose4_2.put("Employee Traffic/Parcels", 0.06); + ratesPerPurpose4_2.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose4_3.put("Inhabitants", 0.0); + ratesPerPurpose4_3.put("Employee", 0.1); + ratesPerPurpose4_3.put("Employee Primary Sector", 0.0); + ratesPerPurpose4_3.put("Employee Construction", 0.0); + ratesPerPurpose4_3.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose4_3.put("Employee Retail", 0.0); + ratesPerPurpose4_3.put("Employee Traffic/Parcels", 0.25); + ratesPerPurpose4_3.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose4_4.put("Inhabitants", 0.0); + ratesPerPurpose4_4.put("Employee", 0.0); + ratesPerPurpose4_4.put("Employee Primary Sector", 0.0); + ratesPerPurpose4_4.put("Employee Construction", 0.0); + ratesPerPurpose4_4.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose4_4.put("Employee Retail", 0.0); + ratesPerPurpose4_4.put("Employee Traffic/Parcels", 0.08); + ratesPerPurpose4_4.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose4_5.put("Inhabitants", 0.0); + ratesPerPurpose4_5.put("Employee", 0.0); + ratesPerPurpose4_5.put("Employee Primary Sector", 0.0); + ratesPerPurpose4_5.put("Employee Construction", 0.0); + ratesPerPurpose4_5.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose4_5.put("Employee Retail", 0.0); + ratesPerPurpose4_5.put("Employee Traffic/Parcels", 0.43); + ratesPerPurpose4_5.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose5_1.put("Inhabitants", 0.0); + ratesPerPurpose5_1.put("Employee", 0.8); + ratesPerPurpose5_1.put("Employee Primary Sector", 0.0); + ratesPerPurpose5_1.put("Employee Construction", 0.25); + ratesPerPurpose5_1.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose5_1.put("Employee Retail", 0.0); + ratesPerPurpose5_1.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose5_1.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose5_2.put("Inhabitants", 0.0); + ratesPerPurpose5_2.put("Employee", 0.1); + ratesPerPurpose5_2.put("Employee Primary Sector", 0.0); + ratesPerPurpose5_2.put("Employee Construction", 0.2); + ratesPerPurpose5_2.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose5_2.put("Employee Retail", 0.0); + ratesPerPurpose5_2.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose5_2.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose5_3.put("Inhabitants", 0.0); + ratesPerPurpose5_3.put("Employee", 0.1); + ratesPerPurpose5_3.put("Employee Primary Sector", 0.0); + ratesPerPurpose5_3.put("Employee Construction", 0.25); + ratesPerPurpose5_3.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose5_3.put("Employee Retail", 0.139); + ratesPerPurpose5_3.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose5_3.put("Employee Tertiary Sector Rest", 0.059); + + ratesPerPurpose5_4.put("Inhabitants", 0.0); + ratesPerPurpose5_4.put("Employee", 0.0); + ratesPerPurpose5_4.put("Employee Primary Sector", 0.0); + ratesPerPurpose5_4.put("Employee Construction", 0.02); + ratesPerPurpose5_4.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose5_4.put("Employee Retail", 0.0); + ratesPerPurpose5_4.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose5_4.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose5_5.put("Inhabitants", 0.0); + ratesPerPurpose5_5.put("Employee", 0.0); + ratesPerPurpose5_5.put("Employee Primary Sector", 0.0); + ratesPerPurpose5_5.put("Employee Construction", 0.28); + ratesPerPurpose5_5.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose5_5.put("Employee Retail", 0.0); + ratesPerPurpose5_5.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose5_5.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose6_1.put("Inhabitants", 0.0); + ratesPerPurpose6_1.put("Employee", 0.0); + ratesPerPurpose6_1.put("Employee Primary Sector", 0.0); + ratesPerPurpose6_1.put("Employee Construction", 0.0); + ratesPerPurpose6_1.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose6_1.put("Employee Retail", 0.0); + ratesPerPurpose6_1.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose6_1.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose6_2.put("Inhabitants", 0.29); + ratesPerPurpose6_2.put("Employee", 0.0); + ratesPerPurpose6_2.put("Employee Primary Sector", 0.0); + ratesPerPurpose6_2.put("Employee Construction", 0.0); + ratesPerPurpose6_2.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose6_2.put("Employee Retail", 0.0); + ratesPerPurpose6_2.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose6_2.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose6_3.put("Inhabitants", 0.63); + ratesPerPurpose6_3.put("Employee", 0.0); + ratesPerPurpose6_3.put("Employee Primary Sector", 0.0); + ratesPerPurpose6_3.put("Employee Construction", 0.0); + ratesPerPurpose6_3.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose6_3.put("Employee Retail", 0.0); + ratesPerPurpose6_3.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose6_3.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose6_4.put("Inhabitants", 0.07); + ratesPerPurpose6_4.put("Employee", 0.0); + ratesPerPurpose6_4.put("Employee Primary Sector", 0.0); + ratesPerPurpose6_4.put("Employee Construction", 0.0); + ratesPerPurpose6_4.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose6_4.put("Employee Retail", 0.0); + ratesPerPurpose6_4.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose6_4.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose6_5.put("Inhabitants", 0.001); + ratesPerPurpose6_5.put("Employee", 0.0); + ratesPerPurpose6_5.put("Employee Primary Sector", 0.0); + ratesPerPurpose6_5.put("Employee Construction", 0.2); + ratesPerPurpose6_5.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose6_5.put("Employee Retail", 0.0); + ratesPerPurpose6_5.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose6_5.put("Employee Tertiary Sector Rest", 0.0); + } else if (commitmentType.equals("stop")) { + ratesPerPurpose1_1.put("Inhabitants", 0.0); + ratesPerPurpose1_1.put("Employee", 0.0); + ratesPerPurpose1_1.put("Employee Primary Sector", 0.0); + ratesPerPurpose1_1.put("Employee Construction", 0.0); + ratesPerPurpose1_1.put("Employee Secondary Sector Rest", 0.35); + ratesPerPurpose1_1.put("Employee Retail", 0.0); + ratesPerPurpose1_1.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose1_1.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose1_2.put("Inhabitants", 0.0); + ratesPerPurpose1_2.put("Employee", 0.0); + ratesPerPurpose1_2.put("Employee Primary Sector", 0.0); + ratesPerPurpose1_2.put("Employee Construction", 0.0); + ratesPerPurpose1_2.put("Employee Secondary Sector Rest", 0.1); + ratesPerPurpose1_2.put("Employee Retail", 0.0); + ratesPerPurpose1_2.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose1_2.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose1_3.put("Inhabitants", 0.0); + ratesPerPurpose1_3.put("Employee", 0.0); + ratesPerPurpose1_3.put("Employee Primary Sector", 0.0); + ratesPerPurpose1_3.put("Employee Construction", 0.0); + ratesPerPurpose1_3.put("Employee Secondary Sector Rest", 0.27); + ratesPerPurpose1_3.put("Employee Retail", 0.0); + ratesPerPurpose1_3.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose1_3.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose1_4.put("Inhabitants", 0.0); + ratesPerPurpose1_4.put("Employee", 0.0); + ratesPerPurpose1_4.put("Employee Primary Sector", 0.0); + ratesPerPurpose1_4.put("Employee Construction", 0.0); + ratesPerPurpose1_4.put("Employee Secondary Sector Rest", 0.01); + ratesPerPurpose1_4.put("Employee Retail", 0.0); + ratesPerPurpose1_4.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose1_4.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose1_5.put("Inhabitants", 0.0); + ratesPerPurpose1_5.put("Employee", 0.0); + ratesPerPurpose1_5.put("Employee Primary Sector", 0.0); + ratesPerPurpose1_5.put("Employee Construction", 0.0); + ratesPerPurpose1_5.put("Employee Secondary Sector Rest", 0.27); + ratesPerPurpose1_5.put("Employee Retail", 0.0); + ratesPerPurpose1_5.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose1_5.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose2_1.put("Inhabitants", 0.55); + ratesPerPurpose2_1.put("Employee", 0.0); + ratesPerPurpose2_1.put("Employee Primary Sector", 0.46); + ratesPerPurpose2_1.put("Employee Construction", 0.46); + ratesPerPurpose2_1.put("Employee Secondary Sector Rest", 0.46); + ratesPerPurpose2_1.put("Employee Retail", 0.46); + ratesPerPurpose2_1.put("Employee Traffic/Parcels", 0.34); + ratesPerPurpose2_1.put("Employee Tertiary Sector Rest", 0.46); + + ratesPerPurpose2_2.put("Inhabitants", 0.09); + ratesPerPurpose2_2.put("Employee", 0.0); + ratesPerPurpose2_2.put("Employee Primary Sector", 0.09); + ratesPerPurpose2_2.put("Employee Construction", 0.09); + ratesPerPurpose2_2.put("Employee Secondary Sector Rest", 0.09); + ratesPerPurpose2_2.put("Employee Retail", 0.09); + ratesPerPurpose2_2.put("Employee Traffic/Parcels", 0.1); + ratesPerPurpose2_2.put("Employee Tertiary Sector Rest", 0.09); + + ratesPerPurpose2_3.put("Inhabitants", 0.21); + ratesPerPurpose2_3.put("Employee", 0.0); + ratesPerPurpose2_3.put("Employee Primary Sector", 0.22); + ratesPerPurpose2_3.put("Employee Construction", 0.22); + ratesPerPurpose2_3.put("Employee Secondary Sector Rest", 0.22); + ratesPerPurpose2_3.put("Employee Retail", 0.22); + ratesPerPurpose2_3.put("Employee Traffic/Parcels", 0.29); + ratesPerPurpose2_3.put("Employee Tertiary Sector Rest", 0.22); + + ratesPerPurpose2_4.put("Inhabitants", 0.06); + ratesPerPurpose2_4.put("Employee", 0.0); + ratesPerPurpose2_4.put("Employee Primary Sector", 0.06); + ratesPerPurpose2_4.put("Employee Construction", 0.06); + ratesPerPurpose2_4.put("Employee Secondary Sector Rest", 0.06); + ratesPerPurpose2_4.put("Employee Retail", 0.06); + ratesPerPurpose2_4.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose2_4.put("Employee Tertiary Sector Rest", 0.06); + + ratesPerPurpose2_5.put("Inhabitants", 0.1); + ratesPerPurpose2_5.put("Employee", 0.0); + ratesPerPurpose2_5.put("Employee Primary Sector", 0.17); + ratesPerPurpose2_5.put("Employee Construction", 0.17); + ratesPerPurpose2_5.put("Employee Secondary Sector Rest", 0.17); + ratesPerPurpose2_5.put("Employee Retail", 0.17); + ratesPerPurpose2_5.put("Employee Traffic/Parcels", 0.27); + ratesPerPurpose2_5.put("Employee Tertiary Sector Rest", 0.17); + + ratesPerPurpose3_1.put("Inhabitants", 0.489); + ratesPerPurpose3_1.put("Employee", 0.0); + ratesPerPurpose3_1.put("Employee Primary Sector", 0.538); + ratesPerPurpose3_1.put("Employee Construction", 0.538); + ratesPerPurpose3_1.put("Employee Secondary Sector Rest", 0.538); + ratesPerPurpose3_1.put("Employee Retail", 0.538); + ratesPerPurpose3_1.put("Employee Traffic/Parcels", 0.59); + ratesPerPurpose3_1.put("Employee Tertiary Sector Rest", 0.538); + + ratesPerPurpose3_2.put("Inhabitants", 0.106); + ratesPerPurpose3_2.put("Employee", 0.0); + ratesPerPurpose3_2.put("Employee Primary Sector", 0.092); + ratesPerPurpose3_2.put("Employee Construction", 0.092); + ratesPerPurpose3_2.put("Employee Secondary Sector Rest", 0.092); + ratesPerPurpose3_2.put("Employee Retail", 0.092); + ratesPerPurpose3_2.put("Employee Traffic/Parcels", 0.03); + ratesPerPurpose3_2.put("Employee Tertiary Sector Rest", 0.092); + + ratesPerPurpose3_3.put("Inhabitants", 0.26); + ratesPerPurpose3_3.put("Employee", 0.0); + ratesPerPurpose3_3.put("Employee Primary Sector", 0.19); + ratesPerPurpose3_3.put("Employee Construction", 0.19); + ratesPerPurpose3_3.put("Employee Secondary Sector Rest", 0.19); + ratesPerPurpose3_3.put("Employee Retail", 0.19); + ratesPerPurpose3_3.put("Employee Traffic/Parcels", 0.102); + ratesPerPurpose3_3.put("Employee Tertiary Sector Rest", 0.19); + + ratesPerPurpose3_4.put("Inhabitants", 0.033); + ratesPerPurpose3_4.put("Employee", 0.0); + ratesPerPurpose3_4.put("Employee Primary Sector", 0.032); + ratesPerPurpose3_4.put("Employee Construction", 0.032); + ratesPerPurpose3_4.put("Employee Secondary Sector Rest", 0.032); + ratesPerPurpose3_4.put("Employee Retail", 0.032); + ratesPerPurpose3_4.put("Employee Traffic/Parcels", 0.058); + ratesPerPurpose3_4.put("Employee Tertiary Sector Rest", 0.032); + + ratesPerPurpose3_5.put("Inhabitants", 0.112); + ratesPerPurpose3_5.put("Employee", 0.0); + ratesPerPurpose3_5.put("Employee Primary Sector", 0.147); + ratesPerPurpose3_5.put("Employee Construction", 0.147); + ratesPerPurpose3_5.put("Employee Secondary Sector Rest", 0.147); + ratesPerPurpose3_5.put("Employee Retail", 0.147); + ratesPerPurpose3_5.put("Employee Traffic/Parcels", 0.219); + ratesPerPurpose3_5.put("Employee Tertiary Sector Rest", 0.147); + + ratesPerPurpose4_1.put("Inhabitants", 0.37); + ratesPerPurpose4_1.put("Employee", 0.0); + ratesPerPurpose4_1.put("Employee Primary Sector", 0.14); + ratesPerPurpose4_1.put("Employee Construction", 0.14); + ratesPerPurpose4_1.put("Employee Secondary Sector Rest", 0.14); + ratesPerPurpose4_1.put("Employee Retail", 0.14); + ratesPerPurpose4_1.put("Employee Traffic/Parcels", 0.06); + ratesPerPurpose4_1.put("Employee Tertiary Sector Rest", 0.14); + + ratesPerPurpose4_2.put("Inhabitants", 0.05); + ratesPerPurpose4_2.put("Employee", 0.0); + ratesPerPurpose4_2.put("Employee Primary Sector", 0.07); + ratesPerPurpose4_2.put("Employee Construction", 0.07); + ratesPerPurpose4_2.put("Employee Secondary Sector Rest", 0.07); + ratesPerPurpose4_2.put("Employee Retail", 0.07); + ratesPerPurpose4_2.put("Employee Traffic/Parcels", 0.07); + ratesPerPurpose4_2.put("Employee Tertiary Sector Rest", 0.07); + + ratesPerPurpose4_3.put("Inhabitants", 0.4); + ratesPerPurpose4_3.put("Employee", 0.0); + ratesPerPurpose4_3.put("Employee Primary Sector", 0.21); + ratesPerPurpose4_3.put("Employee Construction", 0.21); + ratesPerPurpose4_3.put("Employee Secondary Sector Rest", 0.21); + ratesPerPurpose4_3.put("Employee Retail", 0.21); + ratesPerPurpose4_3.put("Employee Traffic/Parcels", 0.19); + ratesPerPurpose4_3.put("Employee Tertiary Sector Rest", 0.21); + + ratesPerPurpose4_4.put("Inhabitants", 0.13); + ratesPerPurpose4_4.put("Employee", 0.0); + ratesPerPurpose4_4.put("Employee Primary Sector", 0.05); + ratesPerPurpose4_4.put("Employee Construction", 0.05); + ratesPerPurpose4_4.put("Employee Secondary Sector Rest", 0.05); + ratesPerPurpose4_4.put("Employee Retail", 0.05); + ratesPerPurpose4_4.put("Employee Traffic/Parcels", 0.08); + ratesPerPurpose4_4.put("Employee Tertiary Sector Rest", 0.05); + + ratesPerPurpose4_5.put("Inhabitants", 0.05); + ratesPerPurpose4_5.put("Employee", 0.0); + ratesPerPurpose4_5.put("Employee Primary Sector", 0.54); + ratesPerPurpose4_5.put("Employee Construction", 0.54); + ratesPerPurpose4_5.put("Employee Secondary Sector Rest", 0.54); + ratesPerPurpose4_5.put("Employee Retail", 0.54); + ratesPerPurpose4_5.put("Employee Traffic/Parcels", 0.61); + ratesPerPurpose4_5.put("Employee Tertiary Sector Rest", 0.54); + + ratesPerPurpose5_1.put("Inhabitants", 0.16); + ratesPerPurpose5_1.put("Employee", 0.0); + ratesPerPurpose5_1.put("Employee Primary Sector", 0.4); + ratesPerPurpose5_1.put("Employee Construction", 0.4); + ratesPerPurpose5_1.put("Employee Secondary Sector Rest", 0.4); + ratesPerPurpose5_1.put("Employee Retail", 0.4); + ratesPerPurpose5_1.put("Employee Traffic/Parcels", 0.14); + ratesPerPurpose5_1.put("Employee Tertiary Sector Rest", 0.4); + + ratesPerPurpose5_2.put("Inhabitants", 0.55); + ratesPerPurpose5_2.put("Employee", 0.11); + ratesPerPurpose5_2.put("Employee Primary Sector", 0.11); + ratesPerPurpose5_2.put("Employee Construction", 0.11); + ratesPerPurpose5_2.put("Employee Secondary Sector Rest", 0.11); + ratesPerPurpose5_2.put("Employee Retail", 0.11); + ratesPerPurpose5_2.put("Employee Traffic/Parcels", 0.06); + ratesPerPurpose5_2.put("Employee Tertiary Sector Rest", 0.11); + + ratesPerPurpose5_3.put("Inhabitants", 0.22); + ratesPerPurpose5_3.put("Employee", 0.0); + ratesPerPurpose5_3.put("Employee Primary Sector", 0.17); + ratesPerPurpose5_3.put("Employee Construction", 0.17); + ratesPerPurpose5_3.put("Employee Secondary Sector Rest", 0.17); + ratesPerPurpose5_3.put("Employee Retail", 0.17); + ratesPerPurpose5_3.put("Employee Traffic/Parcels", 0.21); + ratesPerPurpose5_3.put("Employee Tertiary Sector Rest", 0.17); + + ratesPerPurpose5_4.put("Inhabitants", 0.0); + ratesPerPurpose5_4.put("Employee", 0.0); + ratesPerPurpose5_4.put("Employee Primary Sector", 0.04); + ratesPerPurpose5_4.put("Employee Construction", 0.04); + ratesPerPurpose5_4.put("Employee Secondary Sector Rest", 0.04); + ratesPerPurpose5_4.put("Employee Retail", 0.04); + ratesPerPurpose5_4.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose5_4.put("Employee Tertiary Sector Rest", 0.04); + + ratesPerPurpose5_5.put("Inhabitants", 0.06); + ratesPerPurpose5_5.put("Employee", 0.0); + ratesPerPurpose5_5.put("Employee Primary Sector", 0.28); + ratesPerPurpose5_5.put("Employee Construction", 0.28); + ratesPerPurpose5_5.put("Employee Secondary Sector Rest", 0.28); + ratesPerPurpose5_5.put("Employee Retail", 0.28); + ratesPerPurpose5_5.put("Employee Traffic/Parcels", 0.58); + ratesPerPurpose5_5.put("Employee Tertiary Sector Rest", 0.28); + + ratesPerPurpose6_1.put("Inhabitants", 0.0); + ratesPerPurpose6_1.put("Employee", 0.0); + ratesPerPurpose6_1.put("Employee Primary Sector", 0.0); + ratesPerPurpose6_1.put("Employee Construction", 0.0); + ratesPerPurpose6_1.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose6_1.put("Employee Retail", 0.0); + ratesPerPurpose6_1.put("Employee Traffic/Parcels", 0.0); + ratesPerPurpose6_1.put("Employee Tertiary Sector Rest", 0.0); + + ratesPerPurpose6_2.put("Inhabitants", 0.85); + ratesPerPurpose6_2.put("Employee", 0.0); + ratesPerPurpose6_2.put("Employee Primary Sector", 0.21); + ratesPerPurpose6_2.put("Employee Construction", 0.21); + ratesPerPurpose6_2.put("Employee Secondary Sector Rest", 0.21); + ratesPerPurpose6_2.put("Employee Retail", 0.21); + ratesPerPurpose6_2.put("Employee Traffic/Parcels", 0.09); + ratesPerPurpose6_2.put("Employee Tertiary Sector Rest", 0.21); + + ratesPerPurpose6_3.put("Inhabitants", 0.15); + ratesPerPurpose6_3.put("Employee", 0.0); + ratesPerPurpose6_3.put("Employee Primary Sector", 0.58); + ratesPerPurpose6_3.put("Employee Construction", 0.58); + ratesPerPurpose6_3.put("Employee Secondary Sector Rest", 0.58); + ratesPerPurpose6_3.put("Employee Retail", 0.58); + ratesPerPurpose6_3.put("Employee Traffic/Parcels", 0.55); + ratesPerPurpose6_3.put("Employee Tertiary Sector Rest", 0.58); + + ratesPerPurpose6_4.put("Inhabitants", 0.0); + ratesPerPurpose6_4.put("Employee", 0.0); + ratesPerPurpose6_4.put("Employee Primary Sector", 0.21); + ratesPerPurpose6_4.put("Employee Construction", 0.21); + ratesPerPurpose6_4.put("Employee Secondary Sector Rest", 0.21); + ratesPerPurpose6_4.put("Employee Retail", 0.21); + ratesPerPurpose6_4.put("Employee Traffic/Parcels", 0.25); + ratesPerPurpose6_4.put("Employee Tertiary Sector Rest", 0.21); + + ratesPerPurpose6_5.put("Inhabitants", 0.0); + ratesPerPurpose6_5.put("Employee", 0.0); + ratesPerPurpose6_5.put("Employee Primary Sector", 0.0); + ratesPerPurpose6_5.put("Employee Construction", 0.0); + ratesPerPurpose6_5.put("Employee Secondary Sector Rest", 0.0); + ratesPerPurpose6_5.put("Employee Retail", 0.0); + ratesPerPurpose6_5.put("Employee Traffic/Parcels", 0.11); + ratesPerPurpose6_5.put("Employee Tertiary Sector Rest", 0.0); + } + commitmentRates.put("1_1", ratesPerPurpose1_1); + commitmentRates.put("1_2", ratesPerPurpose1_2); + commitmentRates.put("1_3", ratesPerPurpose1_3); + commitmentRates.put("1_4", ratesPerPurpose1_4); + commitmentRates.put("1_5", ratesPerPurpose1_5); + commitmentRates.put("2_1", ratesPerPurpose2_1); + commitmentRates.put("2_2", ratesPerPurpose2_2); + commitmentRates.put("2_3", ratesPerPurpose2_3); + commitmentRates.put("2_4", ratesPerPurpose2_4); + commitmentRates.put("2_5", ratesPerPurpose2_5); + commitmentRates.put("3_1", ratesPerPurpose3_1); + commitmentRates.put("3_2", ratesPerPurpose3_2); + commitmentRates.put("3_3", ratesPerPurpose3_3); + commitmentRates.put("3_4", ratesPerPurpose3_4); + commitmentRates.put("3_5", ratesPerPurpose3_5); + commitmentRates.put("4_1", ratesPerPurpose4_1); + commitmentRates.put("4_2", ratesPerPurpose4_2); + commitmentRates.put("4_3", ratesPerPurpose4_3); + commitmentRates.put("4_4", ratesPerPurpose4_4); + commitmentRates.put("4_5", ratesPerPurpose4_5); + commitmentRates.put("5_1", ratesPerPurpose5_1); + commitmentRates.put("5_2", ratesPerPurpose5_2); + commitmentRates.put("5_3", ratesPerPurpose5_3); + commitmentRates.put("5_4", ratesPerPurpose5_4); + commitmentRates.put("5_5", ratesPerPurpose5_5); + commitmentRates.put("6_1", ratesPerPurpose6_1); + commitmentRates.put("6_2", ratesPerPurpose6_2); + commitmentRates.put("6_3", ratesPerPurpose6_3); + commitmentRates.put("6_4", ratesPerPurpose6_4); + commitmentRates.put("6_5", ratesPerPurpose6_5); + } + return commitmentRates; + } +} 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 7aeefbf5925..999ea549ccf 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 @@ -73,7 +73,7 @@ void testMainRunAndResults() { String sample = "0.1"; String jspritIterations = "2"; String creationOption = "createNewCarrierFile"; - String smallScaleCommercialTrafficType = "commercialPersonTraffic"; + String smallScaleCommercialTrafficType = "completeSmallScaleCommercialTraffic"; String zoneShapeFileName = utils.getPackageInputDirectory() + "/shp/testZones.shp"; String zoneShapeFileNameColumn = "name"; String shapeCRS = "EPSG:4326"; diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_goodsTraffic_startPerZone_10pt.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_goodsTraffic_startPerZone_10pt.csv new file mode 100644 index 00000000000..bb4a958810a --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_goodsTraffic_startPerZone_10pt.csv @@ -0,0 +1,16 @@ +zoneID mode/vehType 1 2 3 4 5 +area1 vehTyp3 0 1 4 4 3 +area2 vehTyp4 0 0 1 4 1 +area3 vehTyp5 0 0 1 3 1 +area1 vehTyp4 0 0 1 1 0 +area2 vehTyp5 0 0 3 21 9 +area1 vehTyp1 1 2 10 4 3 +area2 vehTyp2 0 0 2 3 7 +area3 vehTyp3 0 0 1 2 1 +area1 vehTyp2 0 0 2 1 2 +area2 vehTyp3 0 1 4 13 8 +area3 vehTyp4 0 0 0 1 0 +area3 vehTyp1 0 0 2 1 1 +area2 vehTyp1 1 2 11 10 9 +area3 vehTyp2 0 0 0 0 1 +area1 vehTyp5 0 0 3 7 3 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_goodsTraffic_stopPerZone_10pt.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_goodsTraffic_stopPerZone_10pt.csv new file mode 100644 index 00000000000..8eacf8fd4d5 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_goodsTraffic_stopPerZone_10pt.csv @@ -0,0 +1,16 @@ +zoneID mode/vehType 1 2 3 4 5 +area1 vehTyp3 0 1 3 7 1 +area2 vehTyp4 0 0 1 2 0 +area3 vehTyp5 0 0 0 3 0 +area1 vehTyp4 0 0 0 2 0 +area2 vehTyp5 0 1 3 12 1 +area1 vehTyp1 1 2 7 5 1 +area2 vehTyp2 0 0 1 2 1 +area3 vehTyp3 0 0 1 1 0 +area1 vehTyp2 0 0 1 2 1 +area2 vehTyp3 0 1 3 7 1 +area3 vehTyp4 0 0 0 0 0 +area3 vehTyp1 0 0 2 1 0 +area2 vehTyp1 1 2 9 5 1 +area3 vehTyp2 0 0 0 0 0 +area1 vehTyp5 0 1 2 13 1 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose1.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose1.csv new file mode 100644 index 00000000000..cc8a668c7b8 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose1.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 1 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose2.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose2.csv new file mode 100644 index 00000000000..de59ab8889f --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose2.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 0 0 +area2 1 2 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose3.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose3.csv new file mode 100644 index 00000000000..26a96bff6fd --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose3.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 3 3 0 +area2 4 5 1 +area3 0 1 1 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose4.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose4.csv new file mode 100644 index 00000000000..12ec403fccd --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose4.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 2 1 0 +area2 3 4 0 +area3 0 0 1 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose5.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose5.csv new file mode 100644 index 00000000000..7e6891a86a5 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose5.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 0 0 +area2 0 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose6.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose6.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp1_purpose6.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose1.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose1.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose1.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose2.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose2.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose2.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose3.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose3.csv new file mode 100644 index 00000000000..2bf59089a18 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose3.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 1 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose4.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose4.csv new file mode 100644 index 00000000000..0ae1ae162f4 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose4.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 1 0 +area2 2 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose5.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose5.csv new file mode 100644 index 00000000000..c53d46eaaae --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose5.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 1 1 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose6.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose6.csv new file mode 100644 index 00000000000..2bf59089a18 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp2_purpose6.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 1 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose1.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose1.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose1.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose2.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose2.csv new file mode 100644 index 00000000000..cc8a668c7b8 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose2.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 1 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose3.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose3.csv new file mode 100644 index 00000000000..72ffd6bb344 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose3.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 2 0 +area2 2 1 0 +area3 0 0 1 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose4.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose4.csv new file mode 100644 index 00000000000..4f435ce0431 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose4.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 1 0 +area2 5 5 1 +area3 1 1 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose5.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose5.csv new file mode 100644 index 00000000000..cc8a668c7b8 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose5.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 1 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose6.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose6.csv new file mode 100644 index 00000000000..8b670f48efc --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp3_purpose6.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 1 2 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose1.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose1.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose1.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose2.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose2.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose2.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose3.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose3.csv new file mode 100644 index 00000000000..89e40cb7518 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose3.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 1 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose4.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose4.csv new file mode 100644 index 00000000000..9a8d21f3eeb --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose4.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 1 1 0 +area3 1 1 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose5.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose5.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose5.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose6.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose6.csv new file mode 100644 index 00000000000..7e6891a86a5 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp4_purpose6.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 0 0 +area2 0 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose1.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose1.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose1.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose2.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose2.csv new file mode 100644 index 00000000000..7e6891a86a5 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose2.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 0 0 +area2 0 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose3.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose3.csv new file mode 100644 index 00000000000..dae6ecd671c --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose3.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 2 0 +area2 2 1 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose4.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose4.csv new file mode 100644 index 00000000000..ab520bdffca --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose4.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 3 3 1 +area2 9 8 2 +area3 1 1 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose5.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose5.csv new file mode 100644 index 00000000000..2bf59089a18 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose5.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 1 1 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose6.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose6.csv new file mode 100644 index 00000000000..4f394b5d502 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_goodsTraffic_vehTyp5_purpose6.csv @@ -0,0 +1,4 @@ +O/D area1 area2 area3 +area1 0 0 0 +area2 0 0 0 +area3 0 0 0 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/vehicleTypes.xml.gz b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/vehicleTypes.xml.gz index e9f770072c4..1e5c09a053f 100644 Binary files a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/vehicleTypes.xml.gz and b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleServiceCarrier/vehicleTypes.xml.gz differ diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/vehicleTypes.xml.gz b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/vehicleTypes.xml.gz index e9f770072c4..b110aa96838 100644 Binary files a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/vehicleTypes.xml.gz and b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/existingModels/exampleShipmentCarrier/vehicleTypes.xml.gz differ 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 6934ebcecc0..8feaf9c0273 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/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/vehicleTypes.xml b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/vehicleTypes.xml index efe44ed5710..2b11da8b0cb 100644 --- a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/vehicleTypes.xml +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/vehicleTypes.xml @@ -5,20 +5,22 @@ Golf 1.4 Trendline - - - + + - diesel + PASSENGER_CAR + petrol + average + average - + - 0.00948 - 0.00948 + 0.0049 + 0.0049 @@ -26,21 +28,22 @@ - - - Heavy Vehicle 26t - + - + VW Caddy 2.0 Maxi TDI + + - 0.0 - diesel + PASSENGER_CAR + diesel + average + average - + 0.0049 0.0049 @@ -51,180 +54,178 @@ - - - Light Vehicle 7.5t - + - + Mercedes 313 CDI + + + LIGHT_COMMERCIAL_VEHICLE diesel + average + average - + 0.0049 0.0049 - + + - - - Medium Vehicle 18t - - - + Mercedes 313 CDI + + + LIGHT_COMMERCIAL_VEHICLE diesel + average + average - + 0.0049 0.0049 - + - - - Mercedes 313 CDI - + - + Light Vehicle 7.5t + + + LIGHT_COMMERCIAL_VEHICLE diesel + average + average - + 0.0049 0.0049 - + + - - - VW Caddy 2.0 Maxi TDI - - - + Medium Vehicle 18t + + + HEAVY_GOODS_VEHICLE diesel + average + average - + - 0.00948 - 0.00948 + 0.0049 + 0.0049 - + - - - - Heavy Vehicle 26t - + - + Medium Vehicle 18t + + + HEAVY_GOODS_VEHICLE diesel + average + average - - + + + 0.0049 + 0.0049 + - + - Heavy Vehicle 40t - - - - + + + + HEAVY_GOODS_VEHICLE diesel + average + average - - - - - - - - - - Light Vehicle 7.5t Frozen - - - - - - - diesel + 0.00559 + 0.00559 - - - - + - - - + + Waste collection vehicle - - + + HEAVY_GOODS_VEHICLE + diesel + average + average 0.5 - 60.0 - diesel + 0.0006 - + + 0.0 + 0.0 + + - \ No newline at end of file + diff --git a/contribs/sumo/pom.xml b/contribs/sumo/pom.xml index da11bdf4865..fb52edc379c 100644 --- a/contribs/sumo/pom.xml +++ b/contribs/sumo/pom.xml @@ -16,7 +16,7 @@ org.matsim.contrib osm - ${project.version} + ${project.parent.version} diff --git a/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkConverter.java b/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkConverter.java index 378703db1eb..b384b50d8d0 100644 --- a/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkConverter.java +++ b/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkConverter.java @@ -165,7 +165,10 @@ public void writeFeatures(SumoNetworkHandler handler, String output) { SumoNetworkFeatureExtractor props = new SumoNetworkFeatureExtractor(handler); try (CSVPrinter out = new CSVPrinter(IOUtils.getBufferedWriter(output), CSVFormat.DEFAULT)) { - out.printRecord(props.getHeader()); + List header = new ArrayList<>(props.getHeader()); + header.addAll(handler.attributes); + + out.printRecord(header); props.print(out); } catch (IOException e) { @@ -243,7 +246,11 @@ public SumoNetworkHandler convert(Network network) throws ParserConfigurationExc Map linkProperties = LinkProperties.createLinkProperties(); // add additional service tag - linkProperties.put(OsmTags.SERVICE, new LinkProperties(LinkProperties.LEVEL_LIVING_STREET, 1, 15 / 3.6, 450, false)); + linkProperties.put(OsmTags.SERVICE, new LinkProperties(LinkProperties.LEVEL_PATH, 1, 15 / 3.6, 450, false)); + linkProperties.put(OsmTags.PATH, new LinkProperties(LinkProperties.LEVEL_PATH, 1, 15 / 3.6, 300, false)); + + // This is for bikes + linkProperties.put(OsmTags.CYCLEWAY, new LinkProperties(LinkProperties.LEVEL_PATH, 1, 15 / 3.6, 300, false)); for (SumoNetworkHandler.Edge edge : sumoHandler.edges.values()) { diff --git a/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractor.java b/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractor.java index ee8c9a45b87..91445ca7f33 100644 --- a/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractor.java +++ b/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkFeatureExtractor.java @@ -274,6 +274,10 @@ public void print(CSVPrinter out, String linkId, SumoNetworkHandler.Edge edge) t out.print(numConnections.getInt('r')); out.print(numConnections.getInt('s')); + for (String attribute : handler.attributes) { + out.print(edge.attributes.getOrDefault(attribute, "")); + } + out.println(); } diff --git a/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkHandler.java b/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkHandler.java index 65de2df3a94..367be8f1827 100644 --- a/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkHandler.java +++ b/contribs/sumo/src/main/java/org/matsim/contrib/sumo/SumoNetworkHandler.java @@ -47,6 +47,11 @@ public class SumoNetworkHandler extends DefaultHandler { */ final Map types = new HashMap<>(); + /** + * Attribute names that have been observed during parsing. + */ + Set attributes = new LinkedHashSet<>(); + /** * Stores current parsed edge. */ @@ -257,6 +262,14 @@ public void startElement(String uri, String localName, String qName, Attributes case "origTo": tmpEdge.origTo = value; break; + // Redundant attribute, that does not need to be stored + case "highway": + break; + default: + String attribute = attributes.getValue("key").intern(); + this.attributes.add(attribute); + tmpEdge.attributes.put(attribute, value); + break; } break; @@ -345,6 +358,8 @@ static final class Edge { @Nullable String origTo; + final Map attributes = new HashMap<>(); + public Edge(String id, String from, String to, String type, int priority, String name, String[] shape) { this.id = id; this.from = from; diff --git a/contribs/sumo/src/test/java/org/matsim/contrib/sumo/SumoNetworkConverterTest.java b/contribs/sumo/src/test/java/org/matsim/contrib/sumo/SumoNetworkConverterTest.java index 2bb89ec4caa..7a13bf4a440 100644 --- a/contribs/sumo/src/test/java/org/matsim/contrib/sumo/SumoNetworkConverterTest.java +++ b/contribs/sumo/src/test/java/org/matsim/contrib/sumo/SumoNetworkConverterTest.java @@ -1,6 +1,9 @@ package org.matsim.contrib.sumo; import com.google.common.io.Resources; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.TransportMode; @@ -8,6 +11,8 @@ import org.matsim.api.core.v01.network.Network; import org.matsim.core.network.NetworkUtils; +import java.io.File; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; @@ -42,9 +47,16 @@ void convert() throws Exception { assert Files.exists(geometry) : "Geometries must exist"; - Path fts = Path.of(output.toString().replace(".xml", "-ft.csv")); + String csv = output.toString().replace(".xml", "-ft.csv"); + Path fts = Path.of(csv); assert Files.exists(fts) : "Features must exists"; + CSVParser parser = CSVParser.parse(new File(csv), StandardCharsets.UTF_8, CSVFormat.DEFAULT.builder().setHeader().setHeader().build()); + + List header = parser.getHeaderNames(); + Assertions.assertEquals("linkId", header.get(0)); + Assertions.assertEquals("highway_type", header.get(1)); + } } diff --git a/contribs/taxi/pom.xml b/contribs/taxi/pom.xml index 33a2ceb4c42..b94a6ed2d99 100644 --- a/contribs/taxi/pom.xml +++ b/contribs/taxi/pom.xml @@ -28,17 +28,17 @@ org.matsim.contrib dvrp - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib drt - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib ev - 2025.0-SNAPSHOT + ${project.parent.version} org.assertj diff --git a/contribs/vsp/pom.xml b/contribs/vsp/pom.xml index 8f4e01bec37..29cbf1de5d6 100644 --- a/contribs/vsp/pom.xml +++ b/contribs/vsp/pom.xml @@ -22,59 +22,59 @@ org.matsim.contrib multimodal - 2025.0-SNAPSHOT + ${project.parent.version} compile org.matsim.contrib taxi - 2025.0-SNAPSHOT + ${project.parent.version} compile org.matsim.contrib dvrp - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib parking - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib freight - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib accessibility - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib emissions - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib minibus - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib common - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib analysis - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib informed-mode-choice - 2025.0-SNAPSHOT + ${project.parent.version} @@ -97,17 +97,17 @@ org.matsim.contrib otfvis - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib noise - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib signals - 2025.0-SNAPSHOT + ${project.parent.version} org.openstreetmap.osmosis @@ -145,7 +145,7 @@ org.matsim.contrib cadyts-integration - 2025.0-SNAPSHOT + ${project.parent.version} org.apache.poi @@ -174,12 +174,12 @@ org.matsim matsim-examples - 2025.0-SNAPSHOT + ${project.parent.version} org.matsim.contrib drt - 2025.0-SNAPSHOT + ${project.parent.version} org.openjfx diff --git a/contribs/vsp/src/main/java/org/matsim/core/scoring/functions/PersonScoringParametersFromPersonAttributes.java b/contribs/vsp/src/main/java/org/matsim/core/scoring/functions/PersonScoringParametersFromPersonAttributes.java index 861a51c33c4..e5a805462bd 100644 --- a/contribs/vsp/src/main/java/org/matsim/core/scoring/functions/PersonScoringParametersFromPersonAttributes.java +++ b/contribs/vsp/src/main/java/org/matsim/core/scoring/functions/PersonScoringParametersFromPersonAttributes.java @@ -45,7 +45,7 @@ * which is an adoption of {@link org.matsim.core.scoring.functions.SubpopulationScoringParameters}. * This class additionaly allows for person-specific mode scoring parameters (for now ASC only) and marginalUtilityOfMoney. * In order to use this, you need to provide the respective attributes (otherwise default values for the subpopulation - * are used). For mode scoring parameters use .... TODO + * are used). The person specific mode parameters are interpreted as offset added to the subpopulation's parameters. * For marginalUtilityOfMoney an attribute {@link org.matsim.core.population.PersonUtils#getIncome(Person)} for persons that have a specific * income is used. Persons in the population, that have no attribute {@link org.matsim.core.population.PersonUtils#getIncome(Person)} will use the * default marginal utility set in their subpopulation's scoring parameters. @@ -160,9 +160,11 @@ public ScoringParameters getScoringParameters(Person person) { Map personalScoringModeConstants = PersonUtils.getModeConstants(person); if (personalScoringModeConstants != null) { for (Map.Entry entry: personalScoringModeConstants.entrySet()) { - ModeUtilityParameters.Builder modeUtilityParamsBuilder = new ModeUtilityParameters.Builder(); + ScoringConfigGroup.ModeParams subpopulationModeParams = subpopulationScoringParams.getModes().get(entry.getKey()); + ModeUtilityParameters.Builder modeUtilityParamsBuilder = new ModeUtilityParameters.Builder(); try { - modeUtilityParamsBuilder.setConstant(Double.parseDouble(entry.getValue())); + modeUtilityParamsBuilder.setConstant(Double.parseDouble(entry.getValue()) + + subpopulationModeParams.getConstant()); } catch (NumberFormatException e) { log.error("PersonalScoringModeConstants from person attribute could not be parsed for person " + person.getId().toString() + "."); @@ -170,7 +172,6 @@ public ScoringParameters getScoringParameters(Person person) { } // copy other params from subpopulation config - ScoringConfigGroup.ModeParams subpopulationModeParams = subpopulationScoringParams.getModes().get(entry.getKey()); modeUtilityParamsBuilder.setMarginalUtilityOfTraveling_s(subpopulationModeParams.getMarginalUtilityOfTraveling()); modeUtilityParamsBuilder.setMarginalUtilityOfDistance_m(subpopulationModeParams.getMarginalUtilityOfDistance()); modeUtilityParamsBuilder.setMonetaryDistanceRate(subpopulationModeParams.getMonetaryDistanceRate()); diff --git a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/CarrierPlanAnalysis.java b/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/CarrierPlanAnalysis.java deleted file mode 100644 index 4b57935373a..00000000000 --- a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/CarrierPlanAnalysis.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * *********************************************************************** * - * project: org.matsim.* - * *********************************************************************** * - * * - * copyright : (C) 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.freight.carriers.analysis; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.matsim.api.core.v01.Id; -import org.matsim.core.utils.misc.Time; -import org.matsim.freight.carriers.Carrier; -import org.matsim.freight.carriers.Carriers; -import org.matsim.freight.carriers.CarriersUtils; - -import java.io.BufferedWriter; -import java.io.FileWriter; -import java.io.IOException; -import java.util.TreeMap; - -/** - * Some basic analysis / data collection for {@link Carriers}(files) - *

- * For all carriers it writes out the: - * - score of the selected plan - * - number of tours (= vehicles) of the selected plan - * - number of Services (input) - * - number of shipments (input) - * to a tsv-file. - * @author Kai Martins-Turner (kturner) - */ -public class CarrierPlanAnalysis { - - private static final Logger log = LogManager.getLogger(CarrierPlanAnalysis.class); - - Carriers carriers; - - public CarrierPlanAnalysis(Carriers carriers) { - this.carriers = carriers; - } - - public void runAnalysisAndWriteStats(String analysisOutputDirectory) throws IOException { - log.info("Writing out carrier analysis ..."); - //Load per vehicle - String fileName = analysisOutputDirectory + "Carrier_stats.tsv"; - - BufferedWriter bw1 = new BufferedWriter(new FileWriter(fileName)); - - //Write headline: - bw1.write("carrierId \t MATSimScoreSelectedPlan \t jSpritScoreSelectedPlan \t nuOfTours \t nuOfShipments(input) \t nuOfServices(input) \t jspritComputationTime[HH:mm:ss]"); - bw1.newLine(); - - final TreeMap, Carrier> sortedCarrierMap = new TreeMap<>(carriers.getCarriers()); - - for (Carrier carrier : sortedCarrierMap.values()) { - bw1.write(carrier.getId().toString()); - bw1.write("\t" + carrier.getSelectedPlan().getScore()); - bw1.write("\t" + carrier.getSelectedPlan().getJspritScore()); - bw1.write("\t" + carrier.getSelectedPlan().getScheduledTours().size()); - bw1.write("\t" + carrier.getShipments().size()); - bw1.write("\t" + carrier.getServices().size()); - if (CarriersUtils.getJspritComputationTime(carrier) != Integer.MIN_VALUE) - bw1.write("\t" + Time.writeTime(CarriersUtils.getJspritComputationTime(carrier), Time.TIMEFORMAT_HHMMSS)); - else - bw1.write("\t" + "null"); - - bw1.newLine(); - } - - bw1.close(); - log.info("Output written to " + fileName); - } -} diff --git a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java b/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java deleted file mode 100644 index 44374d18dd7..00000000000 --- a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/RunFreightAnalysisEventBased.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * *********************************************************************** * - * project: org.matsim.* - * *********************************************************************** * - * * - * copyright : (C) 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.freight.carriers.analysis; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.matsim.api.core.v01.Scenario; -import org.matsim.freight.carriers.FreightCarriersConfigGroup; -import org.matsim.freight.carriers.CarriersUtils; -import org.matsim.freight.carriers.events.CarrierEventsReaders; -import org.matsim.core.api.experimental.events.EventsManager; -import org.matsim.core.config.Config; -import org.matsim.core.config.ConfigUtils; -import org.matsim.core.events.EventsUtils; -import org.matsim.core.events.MatsimEventsReader; -import org.matsim.core.scenario.ScenarioUtils; - -import java.io.File; -import java.io.IOException; - - -/** - * A first approach for some analysis based on the freight events introduced in 2022/23. - * This class comes from teaching SimGV in the winter term 2022/23. - *

- * This class should get extended and prepared as a standardized analysis for freight output. - * This should also get aligned with the current development in Simwrapper. - * Todo: Add some tests. - * - * @author kturner (Kai Martins-Turner) - */ -public class RunFreightAnalysisEventBased { - - private static final Logger log = LogManager.getLogger(RunFreightAnalysisEventBased.class); - - //Were is your simulation output, that should be analysed? - private final String SIM_OUTPUT_PATH ; - private final String ANALYSIS_OUTPUT_PATH; - private final String GLOBAL_CRS; - - /** - * @param simOutputPath The output directory of the simulation run - * @param analysisOutputPath The directory where the result of the analysis should go to - * @param globalCrs - */ - public RunFreightAnalysisEventBased(String simOutputPath, String analysisOutputPath, String globalCrs) { - this.SIM_OUTPUT_PATH = simOutputPath; - this.ANALYSIS_OUTPUT_PATH = analysisOutputPath; - this.GLOBAL_CRS = globalCrs; - } - - public void runAnalysis() throws IOException { - - Config config = ConfigUtils.createConfig(); - config.vehicles().setVehiclesFile(SIM_OUTPUT_PATH + "output_allVehicles.xml.gz"); - config.network().setInputFile(SIM_OUTPUT_PATH + "output_network.xml.gz"); - config.global().setCoordinateSystem(GLOBAL_CRS); - config.plans().setInputFile(null); - config.eventsManager().setNumberOfThreads(null); - config.eventsManager().setEstimatedNumberOfEvents(null); - config.global().setNumberOfThreads(1); - //freight settings - FreightCarriersConfigGroup freightCarriersConfigGroup = ConfigUtils.addOrGetModule( config, FreightCarriersConfigGroup.class ) ; - freightCarriersConfigGroup.setCarriersFile( SIM_OUTPUT_PATH + "output_carriers.xml.gz"); - freightCarriersConfigGroup.setCarriersVehicleTypesFile(SIM_OUTPUT_PATH + "output_carriersVehicleTypes.xml.gz"); - - //Were to store the analysis output? - String analysisOutputDirectory = ANALYSIS_OUTPUT_PATH; - if (!analysisOutputDirectory.endsWith("/")) { - analysisOutputDirectory = analysisOutputDirectory + "/"; - } - File folder = new File(analysisOutputDirectory); - folder.mkdirs(); - - final String eventsFile = SIM_OUTPUT_PATH + "output_events.xml.gz"; - - Scenario scenario = ScenarioUtils.loadScenario(config); - - //load carriers according to freight config - CarriersUtils.loadCarriersAccordingToFreightConfig( scenario ); - - - // CarrierPlanAnalysis - CarrierPlanAnalysis carrierPlanAnalysis = new CarrierPlanAnalysis(CarriersUtils.getCarriers(scenario)); - carrierPlanAnalysis.runAnalysisAndWriteStats(analysisOutputDirectory); - - // Prepare eventsManager - start of event based Analysis; - EventsManager eventsManager = EventsUtils.createEventsManager(); - - FreightTimeAndDistanceAnalysisEventsHandler freightTimeAndDistanceAnalysisEventsHandler = new FreightTimeAndDistanceAnalysisEventsHandler(scenario); - eventsManager.addHandler(freightTimeAndDistanceAnalysisEventsHandler); - - CarrierLoadAnalysis carrierLoadAnalysis = new CarrierLoadAnalysis(CarriersUtils.getCarriers(scenario)); - eventsManager.addHandler(carrierLoadAnalysis); - - eventsManager.initProcessing(); - MatsimEventsReader matsimEventsReader = CarrierEventsReaders.createEventsReader(eventsManager); - - matsimEventsReader.readFile(eventsFile); - eventsManager.finishProcessing(); - - log.info("Analysis completed."); - log.info("Writing output..."); - freightTimeAndDistanceAnalysisEventsHandler.writeTravelTimeAndDistancePerVehicle(analysisOutputDirectory, scenario); - freightTimeAndDistanceAnalysisEventsHandler.writeTravelTimeAndDistancePerVehicleType(analysisOutputDirectory, scenario); - carrierLoadAnalysis.writeLoadPerVehicle(analysisOutputDirectory, scenario); - } - -} diff --git a/contribs/vsp/src/test/java/org/matsim/core/scoring/functions/PersonScoringParametersFromPersonAttributesNoSubpopulationTest.java b/contribs/vsp/src/test/java/org/matsim/core/scoring/functions/PersonScoringParametersFromPersonAttributesNoSubpopulationTest.java index 395990c6a8c..9934ec2f088 100644 --- a/contribs/vsp/src/test/java/org/matsim/core/scoring/functions/PersonScoringParametersFromPersonAttributesNoSubpopulationTest.java +++ b/contribs/vsp/src/test/java/org/matsim/core/scoring/functions/PersonScoringParametersFromPersonAttributesNoSubpopulationTest.java @@ -22,7 +22,6 @@ import org.junit.jupiter.api.BeforeEach; 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.Id; import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.population.*; @@ -50,8 +49,6 @@ */ public class PersonScoringParametersFromPersonAttributesNoSubpopulationTest { - @RegisterExtension - private MatsimTestUtils utils = new MatsimTestUtils(); private PersonScoringParametersFromPersonAttributes personScoringParams; private Population population; @@ -144,7 +141,7 @@ void testPersonWithLowIncomeLowCarAsc(){ Id id = Id.createPersonId("lowIncomeLowCarAsc"); ScoringParameters params = personScoringParams.getScoringParameters(population.getPersons().get(id)); makeAssertMarginalUtilityOfMoneyAndPtWait(params, 0.5d, 0.5d); - Assertions.assertEquals(-0.1d, params.modeParams.get(TransportMode.car).constant, MatsimTestUtils.EPSILON); + Assertions.assertEquals(-1.0d -0.1d, params.modeParams.get(TransportMode.car).constant, MatsimTestUtils.EPSILON); Assertions.assertEquals(-0.001d, params.modeParams.get(TransportMode.car).marginalUtilityOfTraveling_s, MatsimTestUtils.EPSILON); } @@ -153,7 +150,7 @@ void testPersonWithHighIncomeLowCarAsc(){ Id id = Id.createPersonId("highIncomeLowCarAsc"); ScoringParameters params = personScoringParams.getScoringParameters(population.getPersons().get(id)); makeAssertMarginalUtilityOfMoneyAndPtWait(params, 1.5d, 0.5d); - Assertions.assertEquals(-0.1d, params.modeParams.get(TransportMode.car).constant, MatsimTestUtils.EPSILON); + Assertions.assertEquals(-1.0d -0.1d, params.modeParams.get(TransportMode.car).constant, MatsimTestUtils.EPSILON); Assertions.assertEquals(-0.001d, params.modeParams.get(TransportMode.car).marginalUtilityOfTraveling_s, MatsimTestUtils.EPSILON); } @@ -162,8 +159,8 @@ void testPersonWithMediumIncomeHighCarAsc(){ Id id = Id.createPersonId("mediumIncomeHighCarAsc"); ScoringParameters params = personScoringParams.getScoringParameters(population.getPersons().get(id)); makeAssertMarginalUtilityOfMoneyAndPtWait(params, 1d, 0.5d); - Assertions.assertEquals(-2.1d, params.modeParams.get(TransportMode.car).constant, MatsimTestUtils.EPSILON); - Assertions.assertEquals(-50.0d, params.modeParams.get(TransportMode.bike).constant, MatsimTestUtils.EPSILON); + Assertions.assertEquals(-1.0d -2.1d, params.modeParams.get(TransportMode.car).constant, MatsimTestUtils.EPSILON); + Assertions.assertEquals(-0.55d -50.0d, params.modeParams.get(TransportMode.bike).constant, MatsimTestUtils.EPSILON); Assertions.assertEquals(-0.001d, params.modeParams.get(TransportMode.car).marginalUtilityOfTraveling_s, MatsimTestUtils.EPSILON); } @@ -189,12 +186,12 @@ void testPersonSpecificAscScoring(){ Leg carLegZeroDistanceTenSeconds = createLeg(TransportMode.car, 0.0d, 10.0d ); legScoringRichCarLeg.handleLeg(carLegZeroDistanceTenSeconds); - Assertions.assertEquals(-0.1d -0.001d * 10 -7.5*1./1.5 -0.3, legScoringRichCarLeg.getScore(), MatsimTestUtils.EPSILON, "for the rich person with low car asc, a 0 meter and 10s car trip should be equal to a score of "); + Assertions.assertEquals(-1.0d -0.1d -0.001d * 10 -7.5*1./1.5 -0.3, legScoringRichCarLeg.getScore(), MatsimTestUtils.EPSILON, "for the rich person with low car asc, a 0 meter and 10s car trip should be equal to a score of "); ScoringParameters paramsMediumIncomeHighCarAsc = personScoringParams.getScoringParameters(population.getPersons().get(Id.createPersonId("mediumIncomeHighCarAsc"))); CharyparNagelLegScoring legScoringMediumIncomeHighCarAsc = new CharyparNagelLegScoring(paramsMediumIncomeHighCarAsc, NetworkUtils.createNetwork(), Set.of(TransportMode.pt)); legScoringMediumIncomeHighCarAsc.handleLeg(carLegZeroDistanceTenSeconds); - Assertions.assertEquals(-2.1d -0.001d * 10 -7.5*1./1.0 -0.3, legScoringMediumIncomeHighCarAsc.getScore(), MatsimTestUtils.EPSILON, "for the medium person with high car asc, a 0 meter and 10s car trip should be equal to a score of "); + Assertions.assertEquals(-1.0d -2.1d -0.001d * 10 -7.5*1./1.0 -0.3, legScoringMediumIncomeHighCarAsc.getScore(), MatsimTestUtils.EPSILON, "for the medium person with high car asc, a 0 meter and 10s car trip should be equal to a score of "); // bike has no person specific asc for high income person and is not affected CharyparNagelLegScoring legScoringRichBikeLeg = new CharyparNagelLegScoring(paramsRich, NetworkUtils.createNetwork(), Set.of(TransportMode.pt)); @@ -205,7 +202,7 @@ void testPersonSpecificAscScoring(){ // bike has a person specific asc for the medium income person CharyparNagelLegScoring legScoringMediumIncomeBikeLeg = new CharyparNagelLegScoring(paramsMediumIncomeHighCarAsc, NetworkUtils.createNetwork(), Set.of(TransportMode.pt)); legScoringMediumIncomeBikeLeg.handleLeg(bikeLegZeroDistanceZeroSeconds); - Assertions.assertEquals(-50.0d, legScoringMediumIncomeBikeLeg.getScore(), MatsimTestUtils.EPSILON, "for the medium income person with high car asc, a 0 meter and 0s bike trip should be equal to a score of "); + Assertions.assertEquals(-0.55d -50.0d, legScoringMediumIncomeBikeLeg.getScore(), MatsimTestUtils.EPSILON, "for the medium income person with high car asc, a 0 meter and 0s bike trip should be equal to a score of "); } private static Leg createLeg(String mode, double distance, double travelTime) { diff --git a/contribs/vsp/src/test/java/org/matsim/core/scoring/functions/PersonScoringParametersFromPersonAttributesTest.java b/contribs/vsp/src/test/java/org/matsim/core/scoring/functions/PersonScoringParametersFromPersonAttributesTest.java index 72f00ce92ef..2ef25ce7dea 100644 --- a/contribs/vsp/src/test/java/org/matsim/core/scoring/functions/PersonScoringParametersFromPersonAttributesTest.java +++ b/contribs/vsp/src/test/java/org/matsim/core/scoring/functions/PersonScoringParametersFromPersonAttributesTest.java @@ -22,7 +22,6 @@ import org.junit.jupiter.api.BeforeEach; 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.Id; import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.population.*; @@ -50,8 +49,6 @@ */ public class PersonScoringParametersFromPersonAttributesTest { - @RegisterExtension - private MatsimTestUtils utils = new MatsimTestUtils(); private PersonScoringParametersFromPersonAttributes personScoringParams; private Population population; @@ -166,7 +163,7 @@ void testPersonWithLowIncomeLowCarAsc(){ Id id = Id.createPersonId("lowIncomeLowCarAsc"); ScoringParameters params = personScoringParams.getScoringParameters(population.getPersons().get(id)); makeAssertMarginalUtilityOfMoneyAndPtWait(params, 0.5d, 0.5d); - Assertions.assertEquals(-0.1d, params.modeParams.get(TransportMode.car).constant, MatsimTestUtils.EPSILON); + Assertions.assertEquals(-1.0d -0.1d, params.modeParams.get(TransportMode.car).constant, MatsimTestUtils.EPSILON); Assertions.assertEquals(-0.001d, params.modeParams.get(TransportMode.car).marginalUtilityOfTraveling_s, MatsimTestUtils.EPSILON); } @@ -175,7 +172,7 @@ void testPersonWithHighIncomeLowCarAsc(){ Id id = Id.createPersonId("highIncomeLowCarAsc"); ScoringParameters params = personScoringParams.getScoringParameters(population.getPersons().get(id)); makeAssertMarginalUtilityOfMoneyAndPtWait(params, 1.5d, 0.5d); - Assertions.assertEquals(-0.1d, params.modeParams.get(TransportMode.car).constant, MatsimTestUtils.EPSILON); + Assertions.assertEquals(-1.0d -0.1d, params.modeParams.get(TransportMode.car).constant, MatsimTestUtils.EPSILON); Assertions.assertEquals(-0.001d, params.modeParams.get(TransportMode.car).marginalUtilityOfTraveling_s, MatsimTestUtils.EPSILON); } @@ -184,8 +181,8 @@ void testPersonWithMediumIncomeHighCarAsc(){ Id id = Id.createPersonId("mediumIncomeHighCarAsc"); ScoringParameters params = personScoringParams.getScoringParameters(population.getPersons().get(id)); makeAssertMarginalUtilityOfMoneyAndPtWait(params, 1d, 0.5d); - Assertions.assertEquals(-2.1d, params.modeParams.get(TransportMode.car).constant, MatsimTestUtils.EPSILON); - Assertions.assertEquals(-50.0d, params.modeParams.get(TransportMode.bike).constant, MatsimTestUtils.EPSILON); + Assertions.assertEquals(-1.0d -2.1d, params.modeParams.get(TransportMode.car).constant, MatsimTestUtils.EPSILON); + Assertions.assertEquals(-0.55d -50.0d, params.modeParams.get(TransportMode.bike).constant, MatsimTestUtils.EPSILON); Assertions.assertEquals(-0.001d, params.modeParams.get(TransportMode.car).marginalUtilityOfTraveling_s, MatsimTestUtils.EPSILON); } @@ -229,12 +226,12 @@ void testPersonSpecificAscScoring(){ Leg carLegZeroDistanceTenSeconds = createLeg(TransportMode.car, 0.0d, 10.0d ); legScoringRichCarLeg.handleLeg(carLegZeroDistanceTenSeconds); - Assertions.assertEquals(-0.1d -0.001d * 10 -7.5*1./1.5 -0.3, legScoringRichCarLeg.getScore(), MatsimTestUtils.EPSILON, "for the rich person with low car asc, a 0 meter and 10s car trip should be equal to a score of "); + Assertions.assertEquals(-1.0d -0.1d -0.001d * 10 -7.5*1./1.5 -0.3, legScoringRichCarLeg.getScore(), MatsimTestUtils.EPSILON, "for the rich person with low car asc, a 0 meter and 10s car trip should be equal to a score of "); ScoringParameters paramsMediumIncomeHighCarAsc = personScoringParams.getScoringParameters(population.getPersons().get(Id.createPersonId("mediumIncomeHighCarAsc"))); CharyparNagelLegScoring legScoringMediumIncomeHighCarAsc = new CharyparNagelLegScoring(paramsMediumIncomeHighCarAsc, NetworkUtils.createNetwork(), Set.of(TransportMode.pt)); legScoringMediumIncomeHighCarAsc.handleLeg(carLegZeroDistanceTenSeconds); - Assertions.assertEquals(-2.1d -0.001d * 10 -7.5*1./1.0 -0.3, legScoringMediumIncomeHighCarAsc.getScore(), MatsimTestUtils.EPSILON, "for the medium person with high car asc, a 0 meter and 10s car trip should be equal to a score of "); + Assertions.assertEquals(-1.0d -2.1d -0.001d * 10 -7.5*1./1.0 -0.3, legScoringMediumIncomeHighCarAsc.getScore(), MatsimTestUtils.EPSILON, "for the medium person with high car asc, a 0 meter and 10s car trip should be equal to a score of "); // bike has no person specific asc for high income person and is not affected CharyparNagelLegScoring legScoringRichBikeLeg = new CharyparNagelLegScoring(paramsRich, NetworkUtils.createNetwork(), Set.of(TransportMode.pt)); @@ -245,7 +242,7 @@ void testPersonSpecificAscScoring(){ // bike has a person specific asc for the medium income person CharyparNagelLegScoring legScoringMediumIncomeBikeLeg = new CharyparNagelLegScoring(paramsMediumIncomeHighCarAsc, NetworkUtils.createNetwork(), Set.of(TransportMode.pt)); legScoringMediumIncomeBikeLeg.handleLeg(bikeLegZeroDistanceZeroSeconds); - Assertions.assertEquals(-50.0d, legScoringMediumIncomeBikeLeg.getScore(), MatsimTestUtils.EPSILON, "for the medium income person with high car asc, a 0 meter and 0s bike trip should be equal to a score of "); + Assertions.assertEquals(-0.55d -50.0d, legScoringMediumIncomeBikeLeg.getScore(), MatsimTestUtils.EPSILON, "for the medium income person with high car asc, a 0 meter and 0s bike trip should be equal to a score of "); } private static Leg createLeg(String mode, double distance, double travelTime) { 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 dbdb804cb9b..3f1ed342aa5 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 @@ -1,5 +1,4 @@ package playground.vsp.cadyts.marginals; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -63,13 +62,14 @@ private static DistanceDistribution createDistanceDistribution() { return result; } - private Config createConfig() { + private Config createConfig(String outputSuffix) { Config config = ConfigUtils.createConfig(); String[] modes = new String[]{TransportMode.car, TransportMode.bike}; config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); - config.controller().setOutputDirectory(this.utils.getOutputDirectory()); + String outputDirectory = this.utils.getOutputDirectory(); + config.controller().setOutputDirectory(outputDirectory.substring(0,outputDirectory.length()-1)+outputSuffix); config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setLastIteration(40); @@ -244,7 +244,7 @@ private static Plan createPlan(String mode, String endLink, Network network, Pop @MethodSource("arguments") void test(double countsWeight, double modalDistanceWeight) { - Config config = createConfig(); + Config config = createConfig(countsWeight+"_"+modalDistanceWeight); CadytsConfigGroup cadytsConfigGroup = new CadytsConfigGroup(); cadytsConfigGroup.setWriteAnalysisFile(true); config.addModule(cadytsConfigGroup); diff --git a/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/Carrier_stats.tsv b/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/Carrier_stats.tsv index d9ee80ea968..fc9ba4ea543 100644 --- a/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/Carrier_stats.tsv +++ b/contribs/vsp/test/input/org/matsim/freight/carriers/analysis/FreightAnalysisEventBasedTest/runFreightAnalysisEventBasedTest/Carrier_stats.tsv @@ -1,2 +1,2 @@ -carrierId MATSimScoreSelectedPlan jSpritScoreSelectedPlan nuOfTours nuOfShipments(input) nuOfServices(input) jspritComputationTime[HH:mm:ss] -carrier1 -263.4 null 2 0 7 null +carrierId MATSimScoreSelectedPlan jSpritScoreSelectedPlan nuOfTours nuOfShipments(input) nuOfShipments(handled) nuOfServices(input) nuOfServices(handled) nuOfPlanedDemandSize nuOfHandledDemandSize jspritComputationTime[HH:mm:ss] +carrier1 -263.4 null 2 0 0 7 7 7 7 null diff --git a/examples/scenarios/emissions-sampleScenario/testv2_Vehv2/sample_emissionVehicles_v2.xml b/examples/scenarios/emissions-sampleScenario/testv2_Vehv2/sample_emissionVehicles_v2.xml index 566a49585bd..36079e8d101 100644 --- a/examples/scenarios/emissions-sampleScenario/testv2_Vehv2/sample_emissionVehicles_v2.xml +++ b/examples/scenarios/emissions-sampleScenario/testv2_Vehv2/sample_emissionVehicles_v2.xml @@ -14,6 +14,7 @@ average + @@ -27,6 +28,7 @@ PC-P-Euro-1 + @@ -40,6 +42,7 @@ PC-D-Euro-3 + @@ -56,6 +59,7 @@ average + @@ -66,4 +70,4 @@ - \ No newline at end of file + diff --git a/examples/scenarios/freight-chessboard-9x9/singleCarrierFiveActivities_Shipments.xml b/examples/scenarios/freight-chessboard-9x9/singleCarrierFiveActivities_Shipments.xml new file mode 100644 index 00000000000..1e6b969acaf --- /dev/null +++ b/examples/scenarios/freight-chessboard-9x9/singleCarrierFiveActivities_Shipments.xml @@ -0,0 +1,76 @@ + + + + + + 0.12 + 50 + + + + + + + + + + + + + + + + + -215.4666666666667 + + + + + + + + + + + + + + + + + + + + + + + + + i(1,0) i(2,0) i(3,0) j(3,1) j(3,2) i(4,2) i(5,2) i(6,2) j(6,2)R + + + + i(7,0) i(8,0) i(9,0) j(9,1) + + + + j(9,3) j(9,4) j(9,5) j(9,6) + + + + i(9,7)R i(8,7)R i(7,7)R i(6,7)R i(5,7)R j(4,7)R + + + + i(6,6) j(6,6)R i(6,5)R i(5,5)R j(4,5)R j(4,4)R j(4,3)R + + + + i(4,1)R i(3,1)R i(2,1)R i(1,1)R + + + + + + + \ No newline at end of file diff --git a/examples/scenarios/freight-chessboard-9x9/vehicleTypes.xml b/examples/scenarios/freight-chessboard-9x9/vehicleTypes.xml index 27a7d8e1255..df4c6c7c95f 100644 --- a/examples/scenarios/freight-chessboard-9x9/vehicleTypes.xml +++ b/examples/scenarios/freight-chessboard-9x9/vehicleTypes.xml @@ -10,11 +10,13 @@ A heavy truck + A light truck + - \ No newline at end of file + diff --git a/examples/scenarios/logistics-2regions/2regions-network.xml b/examples/scenarios/logistics-2regions/2regions-network.xml new file mode 100644 index 00000000000..5e45ad6bca0 --- /dev/null +++ b/examples/scenarios/logistics-2regions/2regions-network.xml @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java index d6c059897d8..521c237d412 100644 --- a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java +++ b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java @@ -38,15 +38,7 @@ import org.matsim.pt.transitSchedule.api.TransitStopFacility; import org.matsim.vehicles.Vehicle; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; +import java.util.*; /** * The actual RAPTOR implementation, based on Delling et al, Round-Based Public Transit Routing. @@ -118,7 +110,8 @@ public RaptorRoute calcLeastCostRoute(double depTime, Facility fromFacility, Fac reset(); CachingTransferProvider transferProvider = this.data.new CachingTransferProvider(); - Map destinationStops = new HashMap<>(); + // Using a LinkedHashMap instead of a regular HashMap here is necessary to have a deterministic behaviour + Map destinationStops = new LinkedHashMap<>(); // go through all egressStops; check if already in destinationStops; if so, check if current cost is smaller; if so, then replace. This can // presumably happen when the same stop can be reached at lower cost by a different egress mode. (*) @@ -141,7 +134,8 @@ public RaptorRoute calcLeastCostRoute(double depTime, Facility fromFacility, Fac } // same as (*) for access stops: - Map initialStops = new HashMap<>(); + // Also, using a LinkedHashMap instead of a regular HashMap here is necessary to have a deterministic behaviour + Map initialStops = new LinkedHashMap<>(); for (InitialStop accessStop : accessStops) { InitialStop alternative = initialStops.get(accessStop.stop); if (alternative == null || accessStop.accessCost < alternative.accessCost) { @@ -833,7 +827,7 @@ private void handleTransfers(boolean strict, RaptorParameters raptorParams, Cach final int firstTransferIndex; final int lastTransferIndex; final RTransfer[] transfers; - + if (!useAdaptiveTransferCalculation) { // efficient lookup from the precomputed transfer candidates transfers = this.data.transfers; diff --git a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorData.java b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorData.java index a02b58c7b35..e4d4f28a1c5 100644 --- a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorData.java +++ b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorData.java @@ -20,17 +20,7 @@ package ch.sbb.matsim.routing.pt.raptor; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.function.Supplier; import javax.annotation.Nullable; @@ -148,7 +138,8 @@ public static SwissRailRaptorData create(TransitSchedule schedule, @Nullable Veh // enumerate TransitStopFacilities along their usage in transit routes to (hopefully) achieve a better memory locality // well, I'm not even sure how often we'll need the transit stop facilities, likely we'll use RouteStops more often Map stopFacilityIndices = new HashMap<>((int) (schedule.getFacilities().size() * 1.5)); - Map routeStopsPerStopFacility = new HashMap<>(); + // Using a LinkedHashMap instead of a regular HashMap here is necessary to have a deterministic behaviour + Map routeStopsPerStopFacility = new LinkedHashMap<>(); boolean useModeMapping = staticConfig.isUseModeMappingForPassengers(); for (TransitLine line : schedule.getTransitLines().values()) { diff --git a/matsim/src/main/java/org/matsim/analysis/IterationTravelStatsControlerListener.java b/matsim/src/main/java/org/matsim/analysis/IterationTravelStatsControlerListener.java index 483f282480c..f0807fbe07e 100644 --- a/matsim/src/main/java/org/matsim/analysis/IterationTravelStatsControlerListener.java +++ b/matsim/src/main/java/org/matsim/analysis/IterationTravelStatsControlerListener.java @@ -94,15 +94,17 @@ private boolean isWriteGraph(IterationEndsEvent event){ return config.controller().getCreateGraphsInterval() > 0 && event.getIteration() % config.controller().getCreateGraphsInterval() == 0; } - private boolean isWriteTripsAndLegs(IterationEndsEvent event){ - if (config.controller().getWriteTripsInterval() <= 0) { - return false; - } + private boolean isWriteTripsAndLegs(IterationEndsEvent event) { - if (event.getIteration() == 0 || event.isLastIteration()){ - return true; + // This uses the same logic as in PlansDumpingImpl + int writeTripsInterval = config.controller().getWriteTripsInterval(); + final boolean writingTripsAtAll = writeTripsInterval > 0; + final boolean earlyIteration = event.getIteration() <= config.controller().getWritePlansInterval() ; + + if (!writingTripsAtAll) { + return false; } - return event.getIteration() % config.controller().getWriteTripsInterval() == 0; + return earlyIteration || event.isLastIteration() || event.getIteration() % writeTripsInterval == 0; } } diff --git a/matsim/src/main/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysis.java b/matsim/src/main/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysis.java index 222b2d825af..370c8567348 100644 --- a/matsim/src/main/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysis.java +++ b/matsim/src/main/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysis.java @@ -42,24 +42,26 @@ import org.matsim.vehicles.Vehicles; import java.io.IOException; +import java.net.URL; +import java.nio.file.Path; import java.util.*; -import java.util.function.BinaryOperator; import java.util.stream.Collectors; /** * Processes events to create a csv file with passenger volumes, delays and similar information for each stop to stop * segment of a pt {@link org.matsim.pt.transitSchedule.api.Departure}. - * + *

* This class is entirely based on events. In case simulated pt should deviate from the * {@link org.matsim.pt.transitSchedule.api.TransitSchedule} this class provides data on what the simulation really gave * ignoring the TransitSchedule. - * - * Currently there are no integrity checks, if the sequence of events is wrong or an event is missing, this class might + *

+ * Currently, there are no integrity checks, if the sequence of events is wrong or an event is missing, this class might * silently produce invalid output. * This class was intended to be run after the last iteration and the simulation has finished and no preconditions were * taken for TransitVehicle fleets which might change over the course of iterations (e.g. minibus). So running this * class as an EventsListener during the simulation might give wrong results and might need work to get the transit - * vehicles updated before mobsim in each iteration. + * vehicles updated before mobsim in each iteration. Still it could be useful to run in each iteration in special cases, + * such as the minibus contrib. * * @author vsp-gleich */ @@ -70,10 +72,16 @@ public class PtStop2StopAnalysis implements TransitDriverStartsEventHandler, Veh private final Vehicles transitVehicles; // for vehicle capacity private final Map, PtVehicleData> transitVehicle2temporaryVehicleData = new HashMap<>(); private final List stop2StopEntriesForEachDeparture; // the output + private final double sampleUpscaleFactor; private static final Logger log = LogManager.getLogger(PtStop2StopAnalysis.class); - public PtStop2StopAnalysis(Vehicles transitVehicles) { + /** + * @param transitVehicles needed to look up vehicle capacity + * @param sampleUpscaleFactor : factor to scale up output passenger volumes to 100% + */ + public PtStop2StopAnalysis(Vehicles transitVehicles, double sampleUpscaleFactor) { this.transitVehicles = transitVehicles; + this.sampleUpscaleFactor = sampleUpscaleFactor; // set initial capacity to rough estimate of 30 entries by vehicle (should be sufficient) stop2StopEntriesForEachDeparture = new ArrayList<>(transitVehicles.getVehicles().size() * 30); } @@ -95,7 +103,7 @@ public void handleEvent(TransitDriverStartsEvent event) { public void handleEvent(VehicleArrivesAtFacilityEvent event) { PtVehicleData ptVehicleData = transitVehicle2temporaryVehicleData.get(event.getVehicleId()); if (ptVehicleData == null) { - log.error("Encountered a VehicleArrivesAtFacilityEvent without a previous TransitDriverStartsEvent for vehicle " + event.getVehicleId() + " at facility " + event.getFacilityId() + " at time " + event.getTime() + ". This should not happen, this analysis might fail subsequently."); + log.error("Encountered a VehicleArrivesAtFacilityEvent without a previous TransitDriverStartsEvent for vehicle {} at facility {} at time {}. This should not happen, this analysis might fail subsequently.", event.getVehicleId(), event.getFacilityId(), event.getTime()); } else { ptVehicleData.lastVehicleArrivesAtFacilityEvent = event; } @@ -108,16 +116,17 @@ public void handleEvent(VehicleArrivesAtFacilityEvent event) { public void handleEvent(VehicleDepartsAtFacilityEvent event) { PtVehicleData ptVehicleData = transitVehicle2temporaryVehicleData.get(event.getVehicleId()); if (ptVehicleData == null) { - log.error("Encountered a VehicleDepartsAtFacilityEvent without a previous TransitDriverStartsEvent for vehicle " + event.getVehicleId() + " at facility " + event.getFacilityId() + " at time " + event.getTime() + ". This should not happen, this analysis might fail subsequently."); + log.error("Encountered a VehicleDepartsAtFacilityEvent without a previous TransitDriverStartsEvent for vehicle {} at facility {} at time {}. This should not happen, this analysis might fail subsequently.", event.getVehicleId(), event.getFacilityId(), event.getTime()); } else { // produce output entry - stop2StopEntriesForEachDeparture.add(new Stop2StopEntry(ptVehicleData.transitLineId, - ptVehicleData.transitRouteId, ptVehicleData.departureId, event.getFacilityId(), - ptVehicleData.stopSequenceCounter, ptVehicleData.lastStopId, - ptVehicleData.lastVehicleArrivesAtFacilityEvent.getTime() - ptVehicleData.lastVehicleArrivesAtFacilityEvent.getDelay(), - ptVehicleData.lastVehicleArrivesAtFacilityEvent.getDelay(), event.getTime() - event.getDelay(), - event.getDelay(), ptVehicleData.currentPax, ptVehicleData.totalVehicleCapacity, - ptVehicleData.alightings, ptVehicleData.boardings, ptVehicleData.linksTravelledOnSincePreviousStop)); + stop2StopEntriesForEachDeparture.add(new Stop2StopEntry(ptVehicleData.transitLineId, + ptVehicleData.transitRouteId, ptVehicleData.departureId, event.getFacilityId(), + ptVehicleData.stopSequenceCounter, ptVehicleData.lastStopId, + ptVehicleData.lastVehicleArrivesAtFacilityEvent.getTime() - ptVehicleData.lastVehicleArrivesAtFacilityEvent.getDelay(), + ptVehicleData.lastVehicleArrivesAtFacilityEvent.getDelay(), event.getTime() - event.getDelay(), + event.getDelay(), ptVehicleData.currentPax * sampleUpscaleFactor, ptVehicleData.totalVehicleCapacity, + ptVehicleData.alightings * sampleUpscaleFactor, ptVehicleData.boardings * sampleUpscaleFactor, + List.copyOf(ptVehicleData.linksTravelledOnSincePreviousStop))); // calculate number of passengers at departure // (the Stop2StopEntry before needed the number of passengers at arrival so do not move this up!) ptVehicleData.currentPax = ptVehicleData.currentPax - ptVehicleData.alightings + ptVehicleData.boardings; @@ -167,8 +176,8 @@ public void handleEvent(PersonLeavesVehicleEvent event) { @Override public void reset(int iteration) { - if(transitVehicle2temporaryVehicleData.size() > 0) { - log.warn(transitVehicle2temporaryVehicleData.size() + " transit vehicles did not finish service in the last iteration."); + if(!transitVehicle2temporaryVehicleData.isEmpty()) { + log.warn("{} transit vehicles did not finish service in the last iteration.", transitVehicle2temporaryVehicleData.size()); } transitVehicle2temporaryVehicleData.clear(); stop2StopEntriesForEachDeparture.clear(); @@ -225,132 +234,48 @@ private PtVehicleData(Id transitLineId, Id transitRou } } - /** - * output data structure - */ - static final class Stop2StopEntry { - final Id transitLineId;// for aggregation -> set null or leave out and use Map lineId -> Stop2StopEntry? - final Id transitRouteId; - final Id departureId; - final Id stopId; - final int stopSequence; - final Id stopPreviousId; - final double arrivalTimeScheduled; - final double arrivalDelay; - final double departureTimeScheduled; - final double departureDelay; - final int passengersAtArrival; - final double totalVehicleCapacity; - final int passengersAlighting; - final int passengersBoarding; - final List> linkIdsSincePreviousStop; - - Stop2StopEntry(Id transitLineId, Id transitRouteId, - Id departureId, Id stopId, int stopSequence, - Id stopPreviousId, double arrivalTimeScheduled, double arrivalDelay, - double departureTimeScheduled, double departureDelay, int passengersAtArrival, - double totalVehicleCapacity, int passengersAlighting, int passengersBoarding, - List> linkIdsSincePreviousStop) { - this.transitLineId = transitLineId; - this.transitRouteId = transitRouteId; - this.departureId = departureId; - this.stopId = stopId; - this.stopSequence = stopSequence; - this.stopPreviousId = stopPreviousId; - this.arrivalTimeScheduled = arrivalTimeScheduled; - this.arrivalDelay = arrivalDelay; - this.departureTimeScheduled = departureTimeScheduled; - this.departureDelay = departureDelay; - this.passengersAtArrival = passengersAtArrival; - this.totalVehicleCapacity = totalVehicleCapacity; - this.passengersAlighting = passengersAlighting; - this.passengersBoarding = passengersBoarding; - this.linkIdsSincePreviousStop = List.copyOf(linkIdsSincePreviousStop); - } - - // getter for usage of standard Comparator implementations below and more - public Id getTransitLineId() { - return transitLineId; - } - - public Id getTransitRouteId() { - return transitRouteId; - } - - public Id getDepartureId() { - return departureId; - } - - public Id getStopId() { - return stopId; - } - - public int getStopSequence() { - return stopSequence; - } - - public Id getStopPreviousId() { - return stopPreviousId; - } - - public double getArrivalTimeScheduled() { - return arrivalTimeScheduled; - } - - public double getArrivalDelay() { - return arrivalDelay; - } - - public double getDepartureTimeScheduled() { - return departureTimeScheduled; - } - - public double getDepartureDelay() { - return departureDelay; - } - - public int getPassengersAtArrival() { - return passengersAtArrival; - } - - public double getTotalVehicleCapacity() { - return totalVehicleCapacity; - } - - public int getPassengersAlighting() { - return passengersAlighting; - } - - public int getPassengersBoarding() { - return passengersBoarding; - } - - public List> getLinkIdsSincePreviousStop() { - return linkIdsSincePreviousStop; - } - } + /** + * output data structure + * + * @param transitLineId for aggregation -> set null or leave out and use Map lineId -> Stop2StopEntry? + */ + record Stop2StopEntry(Id transitLineId, Id transitRouteId, Id departureId, Id stopId, + int stopSequence, Id stopPreviousId, double arrivalTimeScheduled, double arrivalDelay, + double departureTimeScheduled, double departureDelay, double passengersAtArrival, double totalVehicleCapacity, + double passengersAlighting, double passengersBoarding, List> linkIdsSincePreviousStop) {} static final String[] HEADER = {"transitLine", "transitRoute", "departure", "stop", "stopSequence", "stopPrevious", "arrivalTimeScheduled", "arrivalDelay", "departureTimeScheduled", "departureDelay", "passengersAtArrival", "totalVehicleCapacity", "passengersAlighting", "passengersBoarding", "linkIdsSincePreviousStop"}; - public static Comparator stop2StopEntryByTransitLineComparator = - Comparator.nullsLast(Comparator.comparing(Stop2StopEntry::getTransitLineId)); - public static Comparator stop2StopEntryByTransitRouteComparator = - Comparator.nullsLast(Comparator.comparing(Stop2StopEntry::getTransitRouteId)); - public static Comparator stop2StopEntryByDepartureComparator = - Comparator.nullsLast(Comparator.comparing(Stop2StopEntry::getDepartureId)); - public static Comparator stop2StopEntryByStopSequenceComparator = - Comparator.nullsLast(Comparator.comparing(Stop2StopEntry::getStopSequence)); + static Comparator stop2StopEntryByTransitLineComparator = + Comparator.nullsLast(Comparator.comparing(Stop2StopEntry::transitLineId)); + static Comparator stop2StopEntryByTransitRouteComparator = + Comparator.nullsLast(Comparator.comparing(Stop2StopEntry::transitRouteId)); + static Comparator stop2StopEntryByDepartureComparator = + Comparator.nullsLast(Comparator.comparing(Stop2StopEntry::departureId)); + static Comparator stop2StopEntryByStopSequenceComparator = + Comparator.nullsLast(Comparator.comparing(Stop2StopEntry::stopSequence)); + + public void writeStop2StopEntriesByDepartureCsv(String fileName, String columnSeparator, String listSeparatorInsideColumn) { + writeStop2StopEntriesByDepartureCsv(IOUtils.getFileUrl(fileName), columnSeparator, listSeparatorInsideColumn); + } + + public void writeStop2StopEntriesByDepartureCsv(Path path, String columnSeparator, String listSeparatorInsideColumn) { + writeStop2StopEntriesByDepartureCsv(IOUtils.getFileUrl(path.toString()), columnSeparator, listSeparatorInsideColumn); + } - public void writeStop2StopEntriesByDepartureCsv(String fileName, String columnSeparator, String listSeparatorInsideColumn) { + public void writeStop2StopEntriesByDepartureCsv(URL url, String columnSeparator, String listSeparatorInsideColumn) { stop2StopEntriesForEachDeparture.sort(stop2StopEntryByTransitLineComparator. thenComparing(stop2StopEntryByTransitRouteComparator). thenComparing(stop2StopEntryByDepartureComparator). thenComparing(stop2StopEntryByStopSequenceComparator)); - try (CSVPrinter printer = new CSVPrinter(IOUtils.getBufferedWriter(fileName), - CSVFormat.DEFAULT.withDelimiter(columnSeparator.charAt(0)).withHeader(HEADER)) + try (CSVPrinter printer = new CSVPrinter(IOUtils.getBufferedWriter(url), + CSVFormat.Builder.create() + .setDelimiter(columnSeparator) + .setHeader(HEADER) + .build()) ) { for (Stop2StopEntry entry : stop2StopEntriesForEachDeparture) { printer.print(entry.transitLineId); @@ -367,45 +292,15 @@ public void writeStop2StopEntriesByDepartureCsv(String fileName, String columnSe printer.print(entry.totalVehicleCapacity); printer.print(entry.passengersAlighting); printer.print(entry.passengersBoarding); - printer.print(entry.linkIdsSincePreviousStop.stream().map(id -> id.toString()).collect(Collectors.joining(listSeparatorInsideColumn))); + printer.print(entry.linkIdsSincePreviousStop.stream().map(Object::toString).collect(Collectors.joining(listSeparatorInsideColumn))); printer.println(); } } catch (IOException e) { - e.printStackTrace(); + log.error(e); } } - public List getStop2StopEntriesByDeparture () { + List getStop2StopEntriesByDeparture () { return List.copyOf(stop2StopEntriesForEachDeparture); } - - static final class Stop2StopAggregation { - - private final int departures; - private final long passengers; - private final double totalVehicleCapacity; - - Stop2StopAggregation (int departures, long passengers, double totalVehicleCapacity) { - this.departures = departures; - this.passengers = passengers; - this.totalVehicleCapacity = totalVehicleCapacity; - } - - public int getDepartures() { - return departures; - } - - public long getPassengers() { - return passengers; - } - - public double getTotalVehicleCapacity() { - return totalVehicleCapacity; - } - } - - public static BinaryOperator aggregateStop2StopAggregations() { - return (entry1, entry2) -> new PtStop2StopAnalysis.Stop2StopAggregation(entry1.getDepartures() + entry2.getDepartures(), entry1.getPassengers() + entry2.getPassengers(), - entry1.getTotalVehicleCapacity() + entry2.getTotalVehicleCapacity()); - } } diff --git a/matsim/src/main/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysis2Shp.java b/matsim/src/main/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysis2Shp.java deleted file mode 100644 index 1599a5ba979..00000000000 --- a/matsim/src/main/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysis2Shp.java +++ /dev/null @@ -1,164 +0,0 @@ -/* *********************************************************************** * - * project: org.matsim.* - * * - * *********************************************************************** * - * * - * copyright : (C) 2021 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.analysis.pt.stop2stop; - -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.geotools.api.feature.simple.SimpleFeature; -import org.geotools.feature.simple.SimpleFeatureBuilder; -import org.geotools.feature.simple.SimpleFeatureTypeBuilder; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.jts.geom.GeometryFactory; -import org.locationtech.jts.geom.LineString; -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.Scenario; -import org.matsim.api.core.v01.network.Link; -import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.core.utils.gis.GeoFileWriter; -import org.matsim.core.utils.io.IOUtils; -import org.matsim.pt.transitSchedule.api.TransitLine; - -import java.io.IOException; -import java.util.*; -import java.util.stream.Collectors; - -import static org.matsim.analysis.pt.stop2stop.PtStop2StopAnalysis.aggregateStop2StopAggregations; - -/** - * Write a shape file with passenger volumes, delays and similar information for each stop to stop - * segment of a pt {@link org.matsim.pt.transitSchedule.api.TransitLine}. - * - * @author vsp-gleich - */ -public class PtStop2StopAnalysis2Shp { - - private static final String[] headerCsv = {"link", "transitLine", "stop", "departures", "passengers", "totalVehicleCapacity"}; - private static final Logger log = LogManager.getLogger(PtStop2StopAnalysis2Shp.class); - - public static void writePtStop2StopAnalysisByTransitLine2ShpFile( - final Scenario scenario, final List stop2StopEntriesForEachDeparture, String shpFileName, String coordinateSystem) { - - // sum per link and transit line - Map, Map, PtStop2StopAnalysis.Stop2StopAggregation>> stop2stopByLinkAndTransitLineAggregates = aggregatePerLinkAndLine(stop2StopEntriesForEachDeparture); - - SimpleFeatureTypeBuilder simpleFeatureBuilder = new SimpleFeatureTypeBuilder(); - try { - simpleFeatureBuilder.setCRS(MGC.getCRS(coordinateSystem)); - } catch (IllegalArgumentException e) { - log.warn("Coordinate reference system \"" + coordinateSystem + "\" is unknown."); - } - - simpleFeatureBuilder.setName("ptLinkPerLinePaxFeature"); - // note: column names may not be longer than 10 characters. Otherwise the name is cut after the 10th character and the avalue is NULL in QGis - simpleFeatureBuilder.add("the_geom", LineString.class); - simpleFeatureBuilder.add("linkId", String.class); - simpleFeatureBuilder.add("lineId", String.class); - // simpleFeatureBuilder.add("transitStopIdPrevious", String.class); //not unique, could be multiple - // simpleFeatureBuilder.add("transitStopIdFollowing", String.class); //not unique, could be multiple - simpleFeatureBuilder.add("departures", Integer.class); - simpleFeatureBuilder.add("passengers", Double.class); - simpleFeatureBuilder.add("totVehCapa", Double.class); - simpleFeatureBuilder.add("loadFactor", Double.class); - SimpleFeatureBuilder linkFeatureBuilder = new SimpleFeatureBuilder(simpleFeatureBuilder.buildFeatureType()); - - Collection features = new ArrayList<>(); - GeometryFactory geofac = new GeometryFactory(); - - for(Map.Entry, Map, PtStop2StopAnalysis.Stop2StopAggregation>> entryLinkLevel: stop2stopByLinkAndTransitLineAggregates.entrySet()) { - for (Map.Entry, PtStop2StopAnalysis.Stop2StopAggregation> entryLineLevel : entryLinkLevel.getValue().entrySet()) { - createLinkFeatureFromStop2StopAggregation(scenario, linkFeatureBuilder, features, geofac, entryLinkLevel.getKey(), entryLineLevel.getKey().toString(), entryLineLevel.getValue()); - } - } - - // sum per link of all transit lines - Map, PtStop2StopAnalysis.Stop2StopAggregation> stop2stopByLinkAggregates = stop2StopEntriesForEachDeparture.stream() - .flatMap(stop2StopEntry -> stop2StopEntry.linkIdsSincePreviousStop.stream() - .map(linkId -> new AbstractMap.SimpleEntry<>(linkId, stop2StopEntry))) - .collect(Collectors.toMap( - entry -> entry.getKey(), - entry -> new PtStop2StopAnalysis.Stop2StopAggregation(1, entry.getValue().passengersAtArrival, entry.getValue().totalVehicleCapacity), - aggregateStop2StopAggregations(), - HashMap::new)); - - for(Map.Entry, PtStop2StopAnalysis.Stop2StopAggregation> entryLinkLevel: stop2stopByLinkAggregates.entrySet()) { - createLinkFeatureFromStop2StopAggregation(scenario, linkFeatureBuilder, features, geofac, entryLinkLevel.getKey(), "all", entryLinkLevel.getValue()); - } - - // TODO: add stops? - GeoFileWriter.writeGeometries(features, shpFileName); - } - - public static void writePtStop2StopAnalysisByTransitLine2CsvFile( - final List stop2StopEntriesForEachDeparture, String fileNameCsv, String separatorCsv) { - - // sum per link and transit line - Map, Map, PtStop2StopAnalysis.Stop2StopAggregation>> stop2stopByLinkAndTransitLineAggregates = aggregatePerLinkAndLine(stop2StopEntriesForEachDeparture); - - try (CSVPrinter printer = new CSVPrinter(IOUtils.getBufferedWriter(fileNameCsv), - CSVFormat.DEFAULT.withDelimiter(separatorCsv.charAt(0)).withHeader(headerCsv)) - ) { - for(Map.Entry, Map, PtStop2StopAnalysis.Stop2StopAggregation>> entryLinkLevel: stop2stopByLinkAndTransitLineAggregates.entrySet()) { - for (Map.Entry, PtStop2StopAnalysis.Stop2StopAggregation> entryLineLevel : entryLinkLevel.getValue().entrySet()) { - printer.print(entryLinkLevel.getKey()); - printer.print(entryLineLevel.getKey()); - printer.print(entryLineLevel.getValue().getDepartures()); - printer.print(entryLineLevel.getValue().getPassengers()); - printer.print(entryLineLevel.getValue().getTotalVehicleCapacity()); - printer.println(); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - private static Map, Map, PtStop2StopAnalysis.Stop2StopAggregation>> aggregatePerLinkAndLine(List stop2StopEntriesForEachDeparture) { - return stop2StopEntriesForEachDeparture.stream() - .flatMap(stop2StopEntry -> stop2StopEntry.linkIdsSincePreviousStop.stream() - .map(linkId -> new AbstractMap.SimpleEntry<>(linkId, stop2StopEntry))) - .collect(Collectors.groupingBy(entry -> entry.getKey(), Collectors.toMap( - entry -> entry.getValue().transitLineId, - entry -> new PtStop2StopAnalysis.Stop2StopAggregation(1, entry.getValue().passengersAtArrival, entry.getValue().totalVehicleCapacity), - aggregateStop2StopAggregations(), - TreeMap::new))); - } - - private static void createLinkFeatureFromStop2StopAggregation(Scenario scenario, SimpleFeatureBuilder linkFeatureBuilder, Collection features, GeometryFactory geofac, Id linkId, String transitLineId, PtStop2StopAnalysis.Stop2StopAggregation stop2StopAggregation) { - Link link = scenario.getNetwork().getLinks().get(linkId); - LineString ls = geofac.createLineString(new Coordinate[] {MGC.coord2Coordinate(link.getFromNode().getCoord()), - MGC.coord2Coordinate(link.getToNode().getCoord())}); - Object[] linkFeatureAttributes = new Object[7]; - linkFeatureAttributes[0] = ls; - linkFeatureAttributes[1] = linkId; - linkFeatureAttributes[2] = transitLineId; - linkFeatureAttributes[3] = stop2StopAggregation.getDepartures(); - linkFeatureAttributes[4] = stop2StopAggregation.getPassengers(); - linkFeatureAttributes[5] = stop2StopAggregation.getTotalVehicleCapacity(); - linkFeatureAttributes[6] = stop2StopAggregation.getPassengers() / stop2StopAggregation.getTotalVehicleCapacity(); - try { - features.add(linkFeatureBuilder.buildFeature(stop2StopAggregation + "_line_" + transitLineId, linkFeatureAttributes)); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } - } - -} diff --git a/matsim/src/main/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysisControlerListener.java b/matsim/src/main/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysisControlerListener.java index 8259ad38828..7047436a44e 100644 --- a/matsim/src/main/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysisControlerListener.java +++ b/matsim/src/main/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysisControlerListener.java @@ -46,7 +46,8 @@ public class PtStop2StopAnalysisControlerListener implements IterationStartsList PtStop2StopAnalysisControlerListener(Scenario scenario, EventsManager eventsManager, OutputDirectoryHierarchy controlerIO) { this.eventsManager = eventsManager; this.controlerIO = controlerIO; - ptStop2StopAnalysis = new PtStop2StopAnalysis(scenario.getTransitVehicles()); + // TODO: Sample size is only available in simwrapper config group which is not available here. Setting to 1, needs to be upscaled later. + ptStop2StopAnalysis = new PtStop2StopAnalysis(scenario.getTransitVehicles(), 1.0); sep = scenario.getConfig().global().getDefaultDelimiter(); sep2 = sep.equals(";") ? "_" : ";"; // TODO: move sep2 to global config } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/ActivityEndEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/ActivityEndEvent.java index 39e0e36bbac..76bc4427498 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/ActivityEndEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/ActivityEndEvent.java @@ -29,6 +29,8 @@ import org.matsim.api.core.v01.population.Person; import org.matsim.facilities.ActivityFacility; +import static org.matsim.core.utils.io.XmlUtils.writeEncodedAttributeKeyValue; + public final class ActivityEndEvent extends Event implements HasPersonId, HasLinkId, HasFacilityId, BasicLocation { public static final String EVENT_TYPE = "actend"; @@ -49,7 +51,7 @@ public ActivityEndEvent( final double time, final Id agentId, final Id agentId, final Id linkId, + public ActivityEndEvent(final double time, final Id agentId, final Id linkId, final Id facilityId, final String acttype, final Coord coord) { super(time); this.linkId = linkId; @@ -79,7 +81,7 @@ public String getActType() { @Override public Id getPersonId() { return this.personId; } - + @Override public Map getAttributes() { Map attr = super.getAttributes(); @@ -95,4 +97,12 @@ public void setCoord( Coord coord ) { // yy this is to retrofit the coordinate into existing events that don't have it. this.coord = coord; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes common attributes + writeXMLStart(out); + writeEncodedAttributeKeyValue(out, ATTRIBUTE_ACTTYPE, this.acttype); + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/ActivityStartEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/ActivityStartEvent.java index f58a5b9a506..b0786093572 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/ActivityStartEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/ActivityStartEvent.java @@ -20,8 +20,6 @@ package org.matsim.api.core.v01.events; -import java.util.Map; - import org.matsim.api.core.v01.BasicLocation; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; @@ -29,6 +27,10 @@ import org.matsim.api.core.v01.population.Person; import org.matsim.facilities.ActivityFacility; +import java.util.Map; + +import static org.matsim.core.utils.io.XmlUtils.writeEncodedAttributeKeyValue; + public class ActivityStartEvent extends Event implements HasFacilityId, HasPersonId, HasLinkId, BasicLocation{ public static final String EVENT_TYPE = "actstart"; @@ -91,7 +93,7 @@ public String getActType() { @Override public Id getPersonId() { return this.personId; } - + @Override public Map getAttributes() { Map attr = super.getAttributes(); @@ -109,4 +111,12 @@ public void setCoord( Coord coord ) { // yy this is to retrofit the coordinate into existing events that don't have it. :-( kai, mar'20 this.coord = coord; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes common attributes + writeXMLStart(out); + writeEncodedAttributeKeyValue(out, ATTRIBUTE_ACTTYPE, this.acttype); + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/Event.java b/matsim/src/main/java/org/matsim/api/core/v01/events/Event.java index 09852740b7a..c51a90610fe 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/Event.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/Event.java @@ -24,6 +24,9 @@ import java.util.Map; import org.matsim.api.core.v01.BasicLocation; +import org.matsim.core.utils.io.XmlUtils; + +import static org.matsim.core.utils.io.XmlUtils.writeEncodedAttributeValue; public abstract class Event { @@ -105,6 +108,69 @@ public boolean equals(Object obj) { public int hashCode() { return getAttributes().hashCode(); // Two equal events must at least have the same attributes, so they will get the same hashCode like this. } + + + /** + * Write the start of the xml representation and some common attributes. This method should be called first by {@link #writeAsXML(StringBuilder)}. + */ + protected final void writeXMLStart(StringBuilder out) { + out.append("\t\n"); + } + + /** + * Write a xml representation of this event to the given writer. + * The implementation must write the whole xml element . Starting with \t and adding a newline at the end. + * + * The provided default implementation writes the whole element based on {@link #getAttributes()}. This is slow and should be overridden. + * The overriding implementation must *not* call the super method. + */ + public void writeAsXML(StringBuilder out) { + out.append("\t attr = getAttributes(); + for (Map.Entry entry : attr.entrySet()) { + out.append(entry.getKey()); + out.append("=\""); + out.append(XmlUtils.encodeAttributeValue(entry.getValue())); + out.append("\" "); + } + out.append(" />\n"); + } + } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/LinkEnterEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/LinkEnterEvent.java index 63250efa333..310521abc11 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/LinkEnterEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/LinkEnterEvent.java @@ -73,4 +73,11 @@ public Map getAttributes() { // linkId, vehicleId handled by superclass return atts; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes all common attributes + writeXMLStart(out); + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/LinkLeaveEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/LinkLeaveEvent.java index 06018363204..0491771b110 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/LinkLeaveEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/LinkLeaveEvent.java @@ -76,4 +76,11 @@ public Map getAttributes() { // linkId, vehicleId handled by superclass return atts; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes all common attributes + writeXMLStart(out); + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonArrivalEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonArrivalEvent.java index 6e947aaff11..9e45e10e7da 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonArrivalEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonArrivalEvent.java @@ -26,6 +26,8 @@ import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.population.Person; +import static org.matsim.core.utils.io.XmlUtils.writeEncodedAttributeKeyValue; + public class PersonArrivalEvent extends Event implements HasPersonId, HasLinkId { public static final String EVENT_TYPE = "arrival"; @@ -71,4 +73,14 @@ public Map getAttributes() { } return attr; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes all common attributes + writeXMLStart(out); + if (this.legMode != null) { + writeEncodedAttributeKeyValue(out, ATTRIBUTE_LEGMODE, this.legMode); + } + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonDepartureEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonDepartureEvent.java index 425d8ad4e78..d98e05e8708 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonDepartureEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonDepartureEvent.java @@ -25,6 +25,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.population.Person; +import org.matsim.core.utils.io.XmlUtils; public class PersonDepartureEvent extends Event implements HasPersonId, HasLinkId { @@ -82,4 +83,16 @@ public Map getAttributes() { } return attr; } + + @Override + public void writeAsXML(StringBuilder out) { + writeXMLStart(out); + if (this.legMode != null) { + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_LEGMODE, this.legMode); + } + if (this.routingMode != null) { + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_ROUTING_MODE, this.routingMode); + } + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonEntersVehicleEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonEntersVehicleEvent.java index a3e051f44c4..db694dff953 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonEntersVehicleEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonEntersVehicleEvent.java @@ -68,4 +68,11 @@ public Map getAttributes() { // personId, vehicleId handled by superclass return atts; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes all common attributes + writeXMLStart(out); + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonLeavesVehicleEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonLeavesVehicleEvent.java index 27a3b5b2bdd..3a2bad23e44 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonLeavesVehicleEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonLeavesVehicleEvent.java @@ -69,4 +69,11 @@ public Map getAttributes() { // personId, vehicleId handled by superclass return attrs; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes all common attributes + writeXMLStart(out); + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonMoneyEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonMoneyEvent.java index e61a8a85b32..1b08399d47f 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonMoneyEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonMoneyEvent.java @@ -25,6 +25,8 @@ import java.util.Map; +import static org.matsim.core.utils.io.XmlUtils.writeEncodedAttributeKeyValue; + /** * This event specifies that an agent has gained (or paid) some money. * Scoring functions should handle these Events by adding the amount somehow @@ -134,4 +136,23 @@ public Map getAttributes() { } return attr; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes all common attributes + writeXMLStart(out); + + out.append("amount=\"").append(this.amount).append("\" "); + if (this.purpose != null) { + writeEncodedAttributeKeyValue(out, ATTRIBUTE_PURPOSE, this.purpose); + } + if (this.transactionPartner != null) { + writeEncodedAttributeKeyValue(out, ATTRIBUTE_TRANSACTION_PARTNER, this.transactionPartner); + } + if (this.reference != null) { + writeEncodedAttributeKeyValue(out, ATTRIBUTE_REFERENCE, this.reference); + } + + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonScoreEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonScoreEvent.java index 96019b6242f..893769df004 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonScoreEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonScoreEvent.java @@ -20,6 +20,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.population.Person; +import org.matsim.core.utils.io.XmlUtils; import java.util.Map; @@ -75,4 +76,14 @@ public Map getAttributes() { } return attr; } + + @Override + public void writeAsXML(StringBuilder out) { + writeXMLStart(out); + out.append("amount=\"").append(this.amount).append("\" "); + if (this.kind != null) { + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_KIND, this.kind); + } + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonStuckEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonStuckEvent.java index b2439dd8b96..2eca25c0eab 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/PersonStuckEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/PersonStuckEvent.java @@ -25,6 +25,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.population.Person; +import org.matsim.core.utils.io.XmlUtils; public class PersonStuckEvent extends Event implements HasPersonId, HasLinkId { @@ -71,4 +72,16 @@ public Map getAttributes() { } return attr; } + + @Override + public void writeAsXML(StringBuilder out) { + // Writes all common attributes + writeXMLStart(out); + + if (this.legMode != null) { + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_LEGMODE, this.legMode); + } + + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/TransitDriverStartsEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/TransitDriverStartsEvent.java index f58b1536fa9..801b2ec44c4 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/TransitDriverStartsEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/TransitDriverStartsEvent.java @@ -23,6 +23,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.population.Person; +import org.matsim.core.utils.io.XmlUtils; import org.matsim.pt.transitSchedule.api.Departure; import org.matsim.pt.transitSchedule.api.TransitLine; import org.matsim.pt.transitSchedule.api.TransitRoute; @@ -45,7 +46,7 @@ public class TransitDriverStartsEvent extends Event { private final Id transitLineId; private final Id departureId; - public TransitDriverStartsEvent(final double time, final Id driverId, final Id vehicleId, + public TransitDriverStartsEvent(final double time, final Id driverId, final Id vehicleId, final Id transitLineId, final Id transitRouteId, final Id departureId) { super(time); this.driverId = driverId; @@ -54,23 +55,23 @@ public TransitDriverStartsEvent(final double time, final Id driverId, fi this.transitLineId = transitLineId; this.departureId = departureId; } - + public Id getDriverId() { return driverId; } - + public Id getVehicleId() { return vehicleId; } - + public Id getTransitRouteId() { return transitRouteId; } - + public Id getTransitLineId() { return transitLineId; } - + public Id getDepartureId() { return departureId; } @@ -79,7 +80,7 @@ public Id getDepartureId() { public String getEventType() { return EVENT_TYPE; } - + @Override public Map getAttributes() { Map atts = super.getAttributes(); @@ -90,4 +91,17 @@ public Map getAttributes() { atts.put(ATTRIBUTE_DEPARTURE_ID, this.getDepartureId().toString()); return atts; } -} \ No newline at end of file + + @Override + public void writeAsXML(StringBuilder out) { + writeXMLStart(out); + + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_DRIVER_ID, this.getDriverId().toString()); + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_VEHICLE_ID, this.getVehicleId().toString()); + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_TRANSIT_LINE_ID, this.getTransitLineId().toString()); + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_TRANSIT_ROUTE_ID, this.getTransitRouteId().toString()); + XmlUtils.writeEncodedAttributeKeyValue(out, ATTRIBUTE_DEPARTURE_ID, this.getDepartureId().toString()); + + writeXMLEnd(out); + } +} diff --git a/matsim/src/main/java/org/matsim/api/core/v01/events/VehicleAbortsEvent.java b/matsim/src/main/java/org/matsim/api/core/v01/events/VehicleAbortsEvent.java index a623a758bd0..ba0ec9bbeff 100644 --- a/matsim/src/main/java/org/matsim/api/core/v01/events/VehicleAbortsEvent.java +++ b/matsim/src/main/java/org/matsim/api/core/v01/events/VehicleAbortsEvent.java @@ -61,4 +61,10 @@ public Map getAttributes() { // linkId, vehicleId handled by superclass return atts; } + + @Override + public void writeAsXML(StringBuilder out) { + writeXMLStart(out); + writeXMLEnd(out); + } } diff --git a/matsim/src/main/java/org/matsim/core/config/consistency/VspConfigConsistencyCheckerImpl.java b/matsim/src/main/java/org/matsim/core/config/consistency/VspConfigConsistencyCheckerImpl.java index 901d5da4b5c..a7dba48bdb6 100644 --- a/matsim/src/main/java/org/matsim/core/config/consistency/VspConfigConsistencyCheckerImpl.java +++ b/matsim/src/main/java/org/matsim/core/config/consistency/VspConfigConsistencyCheckerImpl.java @@ -46,13 +46,7 @@ * */ public final class VspConfigConsistencyCheckerImpl implements ConfigConsistencyChecker { - // yyyy TODOS: - // VSP now regularly uses marg utls of travelling != null to fit distance distributions. There should be a switch to switch off the warnings. - - // VSP says that people < 18J should not use car, and implements that via car availability. How to handle that? - - // private static final Logger log = LogManager.getLogger(VspConfigConsistencyCheckerImpl.class); public VspConfigConsistencyCheckerImpl() { @@ -96,10 +90,6 @@ public void checkConsistency(Config config) { problem = checkLocationChoiceConfigGroup( config, problem ); - // === mode choice: - - problem = checkModeChoiceConfigGroup( config, lvl, problem ); - // === planCalcScore: problem = checkPlanCalcScoreConfigGroup( config, lvl, problem ); @@ -116,10 +106,6 @@ public void checkConsistency(Config config) { problem = checkQsimConfigGroup( config, lvl, problem ); - // === subtour mode choice: - - problem = checkSubtourModeChoiceConfigGroup( config, lvl, problem ); - // === strategy: problem = checkStrategyConfigGroup( config, lvl, problem ); @@ -157,20 +143,20 @@ public void checkConsistency(Config config) { } } - private boolean checkSubtourModeChoiceConfigGroup( Config config, Level lvl, boolean problem ){ - if ( config.subtourModeChoice().considerCarAvailability() ) { -// problem = true; - log.log( lvl, "you are considering car abailability; vsp config is not doing that. Instead, we are using a daily monetary constant for car."); - } - return problem; - } - private boolean checkModeChoiceConfigGroup( Config config, Level lvl, boolean problem ){ - if ( !config.changeMode().getIgnoreCarAvailability() ) { -// problem = true; - log.log( lvl, "you are considering car abailability; vsp config is not doing that. Instead, we are using a daily monetary constant for car."); - } - return problem; - } +// private boolean checkSubtourModeChoiceConfigGroup( Config config, Level lvl, boolean problem ){ +// if ( config.subtourModeChoice().considerCarAvailability() ) { +//// problem = true; +// log.log( lvl, "you are considering car abailability; vsp config is not doing that. Instead, we are using a daily monetary constant for car."); +// } +// return problem; +// } +// private boolean checkModeChoiceConfigGroup( Config config, Level lvl, boolean problem ){ +// if ( !config.changeMode().getIgnoreCarAvailability() ) { +//// problem = true; +// log.log( lvl, "you are considering car abailability; vsp config is not doing that. Instead, we are using a daily monetary constant for car."); +// } +// return problem; +// } private static boolean checkGlobalConfigGroup( Config config, Level lvl, boolean problem ){ if ( config.global().isInsistingOnDeprecatedConfigVersion() ) { problem = true ; @@ -263,7 +249,7 @@ private static boolean checkQsimConfigGroup( Config config, Level lvl, boolean p if ( config.qsim().getVehiclesSource()==VehiclesSource.defaultVehicle ) { log.log( lvl, "found qsim.vehiclesSource=defaultVehicle; vsp should use one of the other settings or talk to kai"); } - if ( config.qsim().getLinkDynamics() != QSimConfigGroup.LinkDynamics.PassingQ ) { + if ( config.qsim().getLinkDynamics() != QSimConfigGroup.LinkDynamics.PassingQ && config.qsim().getMainModes().contains(TransportMode.bike) ) { log.log( lvl, "found qsim.linkDynamics=" + config.qsim().getLinkDynamics() + "; vsp should use PassingQ or talk to kai"); } @@ -428,7 +414,7 @@ private static boolean checkPlanCalcScoreConfigGroup( Config config, Level lvl, // added may'23 for ( ModeParams params : config.scoring().getModes().values() ){ if ( config.vspExperimental().getCheckingOfMarginalUtilityOfTravellng()== CheckingOfMarginalUtilityOfTravellng.allZero ){ - if( params.getMarginalUtilityOfTraveling() != 0. ){ + if( params.getMarginalUtilityOfTraveling() != 0. && !params.getMode().equals( TransportMode.ride ) && !params.getMode().equals( TransportMode.bike ) ){ log.log( lvl, "You are setting the marginal utility of traveling with mode " + params.getMode() + " to " + params.getMarginalUtilityOfTraveling() + ". VSP standard is to set this to zero. Please document carefully why you are using a value different from zero, e.g. by showing distance distributions." ); } @@ -495,6 +481,19 @@ private static boolean checkControlerConfigGroup( Config config, Level lvl, bool case SpeedyALT: break; } + + if ( config.controller().getWritePlansInterval() <= 0 ) { + problem = true ; + System.out.flush() ; + log.log( lvl, "found writePlansInterval==0. vsp default is to write plans at least once (for simwrapper).") ; + } + + if ( config.controller().getWriteTripsInterval() <= 0 ) { + problem = true ; + System.out.flush() ; + log.log( lvl, "found writeTripsInterval==0. vsp default is to write trips at least once (for simwrapper).") ; + } + return problem; } diff --git a/matsim/src/main/java/org/matsim/core/config/groups/QSimConfigGroup.java b/matsim/src/main/java/org/matsim/core/config/groups/QSimConfigGroup.java index f8d59f01e01..97c175243e0 100644 --- a/matsim/src/main/java/org/matsim/core/config/groups/QSimConfigGroup.java +++ b/matsim/src/main/java/org/matsim/core/config/groups/QSimConfigGroup.java @@ -431,8 +431,15 @@ public void setInsertingWaitingVehiclesBeforeDrivingVehicles(boolean val) { this.insertingWaitingVehiclesBeforeDrivingVehicles = val; } + /** + * This determines the traffic dynamics of a link. The default is 'queue', but the recommended setting is kinematic waves. + * + * DEPRECATION NOTE: 'withHoles' is deprecated, use 'kinematicWaves' instead, as that uses 'withHoles' and adds an inflow capacity on top. + */ public enum TrafficDynamics { - queue, withHoles, + queue, + @Deprecated + withHoles, kinematicWaves // MATSim-630; previously, the switch was InflowConstraint.maxflowFromFdiag. Amit Jan 2017. } @@ -440,11 +447,19 @@ public enum TrafficDynamics { * Defines how the qsim sets the inflow and/or how it reacts to link attributes which are inconsistent with regard to the fundamental diagram.
* *

  • Note that {@code MAX_CAP_FOR_ONE_LANE} is backwards-compatible but always sets the inflow capacity to the maximum according to the fundamental diagram for one lane, - * so it essentially sets the inflow capacity too low for multiple-lane-links.
  • - *
  • {@code INFLOW_FROM_FDIAG} sets the inflow capacity to maximum flow capacity according to the fundamental diagram, assuming the nr of lanes in the link attributes to be correct.
  • - *
  • {@code NR_OF_LANES_FROM_FDIAG} sets the number of lanes to minimum required according to the fundamental diagram, assuming the flow capacity in the link attributes to be correct.
  • + * so it essentially sets the inflow capacity too low for multiple-lane-links. DEPRECATED: This is only for backwards compatibility. Use + * INFLOW_FROM_FDIAG instead. + *
  • {@code INFLOW_FROM_FDIAG} sets the inflow capacity to maximum flow capacity according to the + * fundamental diagram, assuming the nr of lanes in the link attributes to be correct.
  • + *
  • {@code NR_OF_LANES_FROM_FDIAG} sets the number of lanes to minimum required according to the fundamental + * diagram, assuming the flow capacity in the link attributes to be correct. DEPRECATED: In practice the other setting is used most often! Use\ + * INFLOW_FROM_FDIAG instead.
  • */ - public enum InflowCapacitySetting {INFLOW_FROM_FDIAG, NR_OF_LANES_FROM_FDIAG, MAX_CAP_FOR_ONE_LANE} + public enum InflowCapacitySetting {INFLOW_FROM_FDIAG, + @Deprecated + NR_OF_LANES_FROM_FDIAG, + @Deprecated + MAX_CAP_FOR_ONE_LANE} @StringSetter(TRAFFIC_DYNAMICS) public void setTrafficDynamics(final TrafficDynamics str) { diff --git a/matsim/src/main/java/org/matsim/core/controler/AbstractController.java b/matsim/src/main/java/org/matsim/core/controler/AbstractController.java index a1c008e31ba..6775c0fc998 100644 --- a/matsim/src/main/java/org/matsim/core/controler/AbstractController.java +++ b/matsim/src/main/java/org/matsim/core/controler/AbstractController.java @@ -79,7 +79,7 @@ protected final void run(final Config config) { public void run() throws MatsimRuntimeModifications.UnexpectedShutdownException { loadCoreListeners(); controlerListenerManagerImpl.fireControlerStartupEvent(); - ControlerUtils.checkConfigConsistencyAndWriteToLog(config, "config dump before iterations start"); + ControllerUtils.checkConfigConsistencyAndWriteToLog(config, "config dump before iterations start" ); prepareForSim(); doIterations(config); } diff --git a/matsim/src/main/java/org/matsim/core/controler/Controler.java b/matsim/src/main/java/org/matsim/core/controler/Controler.java index bc7fbdc47da..22279357ada 100755 --- a/matsim/src/main/java/org/matsim/core/controler/Controler.java +++ b/matsim/src/main/java/org/matsim/core/controler/Controler.java @@ -65,7 +65,7 @@ * * @author mrieser */ -public final class Controler implements ControlerI, MatsimServices, AllowsConfiguration{ +public final class Controler implements Controller, ControlerI, MatsimServices, AllowsConfiguration{ // yyyy Design thoughts: // * Seems to me that we should try to get everything here final. Flexibility is provided by the ability to set or add factories. If this is // not sufficient, people should use AbstractController. kai, jan'13 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 293ac9ed415..0de32d9c47b 100755 --- a/matsim/src/main/java/org/matsim/core/controler/ControlerDefaultsModule.java +++ b/matsim/src/main/java/org/matsim/core/controler/ControlerDefaultsModule.java @@ -51,6 +51,7 @@ import java.io.File; public final class ControlerDefaultsModule extends AbstractModule { + @Override public void install() { install(new EventsManagerModule()); @@ -85,9 +86,10 @@ 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; - @Override public void notifyStartup(StartupEvent event) { - ImageIO.setCacheDirectory(new File(outputDirectoryHierarchy.getTempPath())); + + @Override + public void notifyStartup(StartupEvent event) { + ImageIO.setCacheDirectory(new File(event.getServices().getControlerIO().getTempPath())); } }); diff --git a/matsim/src/main/java/org/matsim/core/controler/ControlerUtils.java b/matsim/src/main/java/org/matsim/core/controler/ControlerUtils.java index 490076578e5..be978146879 100644 --- a/matsim/src/main/java/org/matsim/core/controler/ControlerUtils.java +++ b/matsim/src/main/java/org/matsim/core/controler/ControlerUtils.java @@ -1,103 +1,30 @@ -/* *********************************************************************** * - * project: org.matsim.* * - * * - * *********************************************************************** * - * * - * copyright : (C) 2008 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.core.controler; -import java.io.PrintWriter; -import java.io.StringWriter; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import com.google.inject.Injector; import org.matsim.api.core.v01.Scenario; import org.matsim.core.config.Config; -import org.matsim.core.config.ConfigWriter; -import org.matsim.core.controler.corelisteners.ControlerDefaultCoreListenersModule; -import org.matsim.core.scenario.ScenarioByInstanceModule; /** - * @author nagel - * + * @deprecated -- use class and methods with double l. */ -public final class ControlerUtils { - private static final Logger log = LogManager.getLogger( ControlerUtils.class ) ; +@Deprecated +public class ControlerUtils { + private ControlerUtils(){} // namespace only; do not instantiate + /** - * This is meant for creating the matsim injector if one does not need/want {@link Controler}. Technical reason is that {@link Controler} creates - * the injector in the run method, and then it is too late to extract material in a direct way. - * - * @param config * @param scenario * @return + * @deprecated -- use controller methods with double l */ - public static com.google.inject.Injector createAdhocInjector( Config config, Scenario scenario ){ - return Injector.createInjector( config, new AbstractModule(){ - @Override public void install(){ - install( new NewControlerModule() ); - install( new ControlerDefaultCoreListenersModule() ); - install( new ControlerDefaultsModule() ); - install( new ScenarioByInstanceModule( scenario ) ); - } - } ); - } - - private ControlerUtils() {} // namespace for static methods only should not be instantiated - - /** - * Design decisions: - *
      - *
    • I extracted this method since it is now called twice: once - * directly after reading, and once before the iterations start. The second - * call seems more important, but I wanted to leave the first one there in - * case the program fails before that config dump. Might be put into the - * "unexpected shutdown hook" instead. kai, dec'10 - * - * Removed the first call for now, because I am now also checking for - * consistency with loaded controler modules. If still desired, we can - * put it in the shutdown hook.. michaz aug'14 - * - *
    - * - * @param config TODO - * @param message the message that is written just before the config dump - */ - public static final void checkConfigConsistencyAndWriteToLog(Config config, - final String message) { - log.info(message); - String newline = System.lineSeparator();// use native line endings for logfile - StringWriter writer = new StringWriter(); - new ConfigWriter(config).writeStream(new PrintWriter(writer), newline); - log.info(newline + newline + writer.getBuffer().toString()); - log.info("Complete config dump done."); - log.info("Checking consistency of config..."); - config.checkConsistency(); - log.info("Checking consistency of config done."); - } - - @Deprecated // use OutputDirectoryLogging.catchLogEntries() directly. kai, mar'18 - public static final void initializeOutputLogging() { - OutputDirectoryLogging.catchLogEntries(); + @Deprecated + public Controler createControler( Scenario scenario ) { + return (Controler) ControllerUtils.createController( scenario ); } - public static void catchLogEntries() { - OutputDirectoryLogging.catchLogEntries(); + public Injector createAdhocInjector( Config config, Scenario scenario ) { + return ControllerUtils.createAdhocInjector( config, scenario ); } - - public Controler createControler( Scenario scenario ) { - return new Controler( scenario ); + public Injector createAdhocInjector( Scenario scenario ) { + return ControllerUtils.createAdhocInjector( scenario ); } - } diff --git a/matsim/src/main/java/org/matsim/core/controler/Controller.java b/matsim/src/main/java/org/matsim/core/controler/Controller.java new file mode 100644 index 00000000000..17dc747424f --- /dev/null +++ b/matsim/src/main/java/org/matsim/core/controler/Controller.java @@ -0,0 +1,7 @@ +package org.matsim.core.controler; + +/** + * This is an attempt to allow a syntax that spells controller with double l. + */ +public interface Controller extends MatsimServices, AllowsConfiguration, Runnable { +} diff --git a/matsim/src/main/java/org/matsim/core/controler/ControllerUtils.java b/matsim/src/main/java/org/matsim/core/controler/ControllerUtils.java new file mode 100644 index 00000000000..05665604a40 --- /dev/null +++ b/matsim/src/main/java/org/matsim/core/controler/ControllerUtils.java @@ -0,0 +1,121 @@ +/* *********************************************************************** * + * project: org.matsim.* * + * * + * *********************************************************************** * + * * + * copyright : (C) 2008 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.core.controler; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Scenario; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigWriter; +import org.matsim.core.controler.corelisteners.ControlerDefaultCoreListenersModule; +import org.matsim.core.scenario.ScenarioByInstanceModule; + +/** + * @author nagel + * + */ +public final class ControllerUtils{ + private static final Logger log = LogManager.getLogger( ControllerUtils.class ) ; + /** + * This is meant for creating the matsim injector if one does not need/want {@link Controler}. Technical reason is that {@link Controler} creates + * the injector in the run method, and then it is too late to extract material in a direct way. + * + * @param config + * @param scenario + * @return + */ + public static com.google.inject.Injector createAdhocInjector( Config config, Scenario scenario ){ + return Injector.createInjector( config, new AbstractModule(){ + @Override public void install(){ + install( new NewControlerModule() ); + install( new ControlerDefaultCoreListenersModule() ); + install( new ControlerDefaultsModule() ); + install( new ScenarioByInstanceModule( scenario ) ); + } + } ); + } + /** + * This is meant for creating the matsim injector if one does not need/want {@link Controler}. + * Technical reason is that {@link Controler} creates + * the injector in the run method, and then it is too late to extract material in a direct way. + * + * @param scenario + * @return + */ + public static com.google.inject.Injector createAdhocInjector( Scenario scenario ){ + return Injector.createInjector( scenario.getConfig(), new AbstractModule(){ + @Override public void install(){ + install( new NewControlerModule() ); + install( new ControlerDefaultCoreListenersModule() ); + install( new ControlerDefaultsModule() ); + install( new ScenarioByInstanceModule( scenario ) ); + } + } ); + } + + private ControllerUtils() {} // namespace for static methods only should not be instantiated + + /** + * Design decisions: + *
      + *
    • I extracted this method since it is now called twice: once + * directly after reading, and once before the iterations start. The second + * call seems more important, but I wanted to leave the first one there in + * case the program fails before that config dump. Might be put into the + * "unexpected shutdown hook" instead. kai, dec'10 + * + * Removed the first call for now, because I am now also checking for + * consistency with loaded controler modules. If still desired, we can + * put it in the shutdown hook.. michaz aug'14 + * + *
    + * + * @param config TODO + * @param message the message that is written just before the config dump + */ + public static final void checkConfigConsistencyAndWriteToLog(Config config, + final String message) { + log.info(message); + String newline = System.lineSeparator();// use native line endings for logfile + StringWriter writer = new StringWriter(); + new ConfigWriter(config).writeStream(new PrintWriter(writer), newline); + log.info(newline + newline + writer.getBuffer().toString()); + log.info("Complete config dump done."); + log.info("Checking consistency of config..."); + config.checkConsistency(); + log.info("Checking consistency of config done."); + } + + @Deprecated // use OutputDirectoryLogging.catchLogEntries() directly. kai, mar'18 + public static final void initializeOutputLogging() { + OutputDirectoryLogging.catchLogEntries(); + } + + public static void catchLogEntries() { + OutputDirectoryLogging.catchLogEntries(); + } + + public static Controller createController( Scenario scenario ) { + return new Controler( scenario ); + } + +} diff --git a/matsim/src/main/java/org/matsim/core/controler/OutputDirectoryHierarchy.java b/matsim/src/main/java/org/matsim/core/controler/OutputDirectoryHierarchy.java index 86272160a77..9decfe75a1a 100644 --- a/matsim/src/main/java/org/matsim/core/controler/OutputDirectoryHierarchy.java +++ b/matsim/src/main/java/org/matsim/core/controler/OutputDirectoryHierarchy.java @@ -47,6 +47,8 @@ public enum OverwriteFileSetting {failIfDirectoryExists, overwriteExistingFiles, private static final String DIRECTORY_ITERS = "ITERS"; + public static final String MATSIM_TEMP_DIR_PROPERTY = "matsim.tempDir"; + private static final Logger log = LogManager.getLogger(OutputDirectoryHierarchy.class); private String runId = null; @@ -108,7 +110,11 @@ public OutputDirectoryHierarchy(String outputPath, String runId, OverwriteFileSe * @return path to a temp-directory. */ public final String getTempPath() { - return outputPath + "/tmp"; + String matsimTempDir = System.getProperty(MATSIM_TEMP_DIR_PROPERTY); + if (matsimTempDir == null) { + matsimTempDir = outputPath + "/tmp"; + } + return matsimTempDir; } /** diff --git a/matsim/src/main/java/org/matsim/core/events/algorithms/EventWriterXML.java b/matsim/src/main/java/org/matsim/core/events/algorithms/EventWriterXML.java index 54b731771e1..4b29ae4ac55 100644 --- a/matsim/src/main/java/org/matsim/core/events/algorithms/EventWriterXML.java +++ b/matsim/src/main/java/org/matsim/core/events/algorithms/EventWriterXML.java @@ -32,13 +32,17 @@ import java.io.OutputStreamWriter; import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; -import java.util.Map; public class EventWriterXML implements EventWriter, BasicEventHandler { private static final Logger LOG = LogManager.getLogger(EventWriterXML.class); private final BufferedWriter out; + /** + * Cache for StringBuilder instances to avoid creating a new one for each event. + */ + private final ThreadLocal stringBuilder = ThreadLocal.withInitial(StringBuilder::new); + public EventWriterXML(final String outfilename) { this.out = IOUtils.getBufferedWriter(outfilename); this.writeHeader(); @@ -83,73 +87,14 @@ public void reset(final int iter) { @Override public void handleEvent(final Event event) { try { - this.out.append("\t attr = event.getAttributes(); - for (Map.Entry entry : attr.entrySet()) { - this.out.append(entry.getKey()); - this.out.append("=\""); - this.out.append(encodeAttributeValue(entry.getValue())); - this.out.append("\" "); - } - this.out.append(" />\n"); - } catch (IOException e) { - LOG.error(e.getMessage(), e); - } - } + StringBuilder b = stringBuilder.get(); - // the following method was taken from MatsimXmlWriter in order to correctly encode attributes, but - // to forego the overhead of using the full MatsimXmlWriter. - /** - * Encodes the given string in such a way that it no longer contains - * characters that have a special meaning in xml. - * - * @see http://www.w3.org/International/questions/qa-escapes#use - * @param attributeValue - * @return String with some characters replaced by their xml-encoding. - */ - private String encodeAttributeValue(final String attributeValue) { - if (attributeValue == null) { - return null; - } - int len = attributeValue.length(); - boolean encode = false; - for (int pos = 0; pos < len; pos++) { - char ch = attributeValue.charAt(pos); - if (ch == '<') { - encode = true; - break; - } else if (ch == '>') { - encode = true; - break; - } else if (ch == '\"') { - encode = true; - break; - } else if (ch == '&') { - encode = true; - break; - } - } - if (encode) { - StringBuilder bf = new StringBuilder(attributeValue.length() + 30); - for (int pos = 0; pos < len; pos++) { - char ch = attributeValue.charAt(pos); - if (ch == '<') { - bf.append("<"); - } else if (ch == '>') { - bf.append(">"); - } else if (ch == '\"') { - bf.append("""); - } else if (ch == '&') { - bf.append("&"); - } else { - bf.append(ch); - } - } + b.setLength(0); + event.writeAsXML(b); + this.out.append(b); - return bf.toString(); + } catch (IOException e) { + LOG.error(e.getMessage(), e); } - return attributeValue; - } - } 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 741763e4c87..947b2faa2a6 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 @@ -40,7 +40,6 @@ import org.matsim.core.config.groups.QSimConfigGroup.LinkDynamics; import org.matsim.core.config.groups.QSimConfigGroup.TrafficDynamics; import org.matsim.core.gbl.Gbl; -import org.matsim.core.gbl.MatsimRandom; import org.matsim.core.mobsim.framework.MobsimDriverAgent; import org.matsim.core.mobsim.qsim.interfaces.MobsimVehicle; import org.matsim.core.mobsim.qsim.interfaces.SignalGroupState; @@ -63,8 +62,8 @@ * Separating out the "lane" functionality from the "link" functionality. *

    * Design thoughts:
      - *
    • In fast capacity update, the flows are not accumulated in every time step, - * rather updated only if an agent wants to enter the link or an agent is added to buffer. + *
    • In fast capacity update, the flows are not accumulated in every time step, + * rather updated only if an agent wants to enter the link or an agent is added to buffer. * Improvement of 15-20% in the computational performance is observed. amit feb'16 * (I seem to recall that in the end that statement was not consistently correct. kai, feb'18)
    • *
    • Currently (feb'18), the design is such that (possibly time-dep) flowCap and nEffectiveLanes are "pushed" into the @@ -90,7 +89,7 @@ public final void addFromWait(final QVehicle veh) { addToBuffer(veh); } - + /** * Stores the accumulated fractional parts of the flow capacity. See also * flowCapFraction. @@ -189,7 +188,7 @@ private void addValue(double value1, double now) { private double effectiveNumberOfLanesUsedInQsim = Double.POSITIVE_INFINITY ; private double accumulatedInflowCap = 1. ; - + private final FlowEfficiencyCalculator flowEfficiencyCalculator; private QueueWithBuffer(AbstractQLink.QLinkInternalInterface qlink, final VehicleQ vehicleQueue, Id laneId, @@ -198,7 +197,7 @@ private QueueWithBuffer(AbstractQLink.QLinkInternalInterface qlink, final Vehicl // the general idea is to give this object no longer access to "everything". Objects get back pointers (here qlink), but they // do not present the back pointer to the outside. In consequence, this object can go up to qlink, but not any further. kai, mar'16 // Now I am even trying to get rid of the full qLink back pointer (since it allows, e.g., going back to Link). kai, feb'18 - + // log.setLevel(Level.DEBUG); this.flowEfficiencyCalculator = flowEfficiencyCalculator; @@ -328,7 +327,7 @@ private void updateFastFlowAccumulation(){ double now = context.getSimTimer().getTimeOfDay() ; double remainingFlowCapThisTimeStep = subtractConsumptionOfVehiclesThatAreAlreadyInTheBuffer(); - + if( this.flowcap_accumulate.getTimeStep() < now && this.flowcap_accumulate.getValue() < remainingFlowCapThisTimeStep){ @@ -344,7 +343,7 @@ private void updateFastFlowAccumulation(){ private void updateSlowFlowAccumulation(){ double remainingFlowCapThisTimeStep = subtractConsumptionOfVehiclesThatAreAlreadyInTheBuffer(); - + if (this.thisTimeStepGreen && this.flowcap_accumulate.getValue() < remainingFlowCapThisTimeStep){ double newFlowCap = Math.min(flowcap_accumulate.getValue() + flowCapacityPerTimeStep, @@ -372,15 +371,15 @@ public final void initBeforeSimStep() { private void calculateFlowCapacity() { // the following is not looking at time because it simply assumes that the lookups are "now". kai, feb'18 // I am currently not sure if this statement is correct. kai, feb'18 - + // we need the flow capacity per sim-tick and multiplied with flowCapFactor flowCapacityPerTimeStep = unscaledFlowCapacity_s * context.qsimConfig.getTimeStepSize() * context.qsimConfig.getFlowCapFactor() ; inverseFlowCapacityPerTimeStep = 1.0 / flowCapacityPerTimeStep; - + // start with the base assumption, might be adjusted below depending on the traffic dynamics this.effectiveNumberOfLanesUsedInQsim = this.effectiveNumberOfLanes; this.maxInflowUsedInQsim = this.flowCapacityPerTimeStep; - + switch (context.qsimConfig.getTrafficDynamics()) { case queue: case withHoles: @@ -391,10 +390,10 @@ private void calculateFlowCapacity() { // equal: rho * (vmax + vhole) = vhole * rhojam // rho(qmax) = vhole * rhojam / (vmax + vhole) // qmax = vmax * rho(qmax) = rhojam / (1/vhole + 1/vmax) ; - + // 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.qLinkInternalInterface.getFreespeed() ) ; final double minimumNumberOfLanesFromFdiag = this.flowCapacityPerTimeStep * context.effectiveCellSize * ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLinkInternalInterface.getFreespeed() ); @@ -455,19 +454,19 @@ private void calculateFlowCapacity() { } } break; - + default: throw new RuntimeException("The traffic dynamics "+context.qsimConfig.getTrafficDynamics()+" is not implemented yet."); } // log.debug( "linkId=" + this.qLink.getLink().getId() + "; flowCapPerTimeStep=" + flowCapacityPerTimeStep + // "; invFlowCapPerTimeStep=" + inverseFlowCapacityPerTimeStep + "; maxFlowFromFdiag=" + maxFlowFromFdiag ) ; - + } private void calculateStorageCapacity() { // The following is not adjusted for time-dependence!! kai, apr'16 // No, I think that it simply assumes that the lookups are "now". kai, feb'18 // double now = context.getSimTimer().getTimeOfDay() ; - + // first guess at storageCapacity: storageCapacity = this.length * this.effectiveNumberOfLanesUsedInQsim / context.effectiveCellSize * context.qsimConfig.getStorageCapFactor() ; // storageCapacity = this.length * this.qLink.getLink().getNumberOfLanes(now) / context.effectiveCellSize * context.qsimConfig.getStorageCapFactor() ; @@ -489,7 +488,7 @@ private void calculateStorageCapacity() { if (Double.isNaN(freespeedTravelTime)) { throw new IllegalStateException("Double.NaN is not a valid freespeed travel time for a link. Please check the attributes length and freespeed!"); } - + //this assumes that vehicles have the flowEfficiencyFactor of 1.0; the actual flow can be different double tempStorageCapacity = freespeedTravelTime * unscaledFlowCapacity_s * context.qsimConfig.getFlowCapFactor(); // yy note: freespeedTravelTime may be Inf. In this case, storageCapacity will also be set to Inf. This can still be @@ -505,7 +504,7 @@ private void calculateStorageCapacity() { QueueWithBuffer.spaceCapWarningCount++; } storageCapacity = tempStorageCapacity; - + // write out the modified qsim behavior as link attribute qLinkInternalInterface.getLink().getAttributes().putAttribute("storageCapacityUsedInQsim", storageCapacity ); } @@ -514,7 +513,7 @@ private void calculateStorageCapacity() { * () uncongested branch is q(rho) = rho * v_max * () congested branch is q(rho) = (rho - rho_jam) * v_holes * () rho_maxflow is where these two meet, resulting in rho_maxflow = v_holes * rho_jam / ( v_holes + v_max ) - * () max flow is q(rho_maxflow), resulting in v_max * v_holes * rho_jam / ( v_holes + v_max ) + * () max flow is q(rho_maxflow), resulting in v_max * v_holes * rho_jam / ( v_holes + v_max ) * () Since everything else is given, rho_jam needs to be large enough so that q(rho_maxflow) can reach capacity, resulting in * rho_jam >= capacity * (v_holes + v_max) / (v_max * v_holes) ; * () In consequence, storage capacity needs to be larger than curved_length * rho_jam . @@ -554,7 +553,7 @@ private void calculateStorageCapacity() { } private double getBufferStorageCapacity() { - return flowCapacityPerTimeStep;//this assumes that vehicles have the flowEfficiencyFactor of 1.0 + return flowCapacityPerTimeStep;//this assumes that vehicles have the flowEfficiencyFactor of 1.0 } @Override @@ -664,7 +663,6 @@ private void removeVehicleFromQueue(final QVehicle veh2Remove) { case withHoles: case kinematicWaves: QueueWithBuffer.Hole hole = new QueueWithBuffer.Hole() ; - double ttimeOfHoles = length*3600./HOLE_SPEED_KM_H/1000. ; // double offset = this.storageCapacity/this.flowCapacityPerTimeStep ; /* NOTE: Start with completely full link, i.e. N_storageCap cells filled. Now make light at end of link green, discharge with @@ -680,7 +678,12 @@ private void removeVehicleFromQueue(final QVehicle veh2Remove) { // double nLanes = 2. * flowCapacityPerTimeStep ; // pseudo-lanes // double ttimeOfHoles = 0.1 * this.storageCapacity/this.flowCapacityPerTimeStep/nLanes ; - hole.setEarliestLinkExitTime( now + 1.0*ttimeOfHoles + 0.0*MatsimRandom.getRandom().nextDouble()*ttimeOfHoles ) ; + // The calculation of the earliest exit time looked like the formula below. It looks like someone tried to include some randomness, + // but the random part was multiplied with zero, therefore I removed it. Janek oct' 24 + // now + 1.0*ttimeOfHoles + 0.0*MatsimRandom.getRandom().nextDouble()*ttimeOfHoles + var holeTravelTime = length * 3.6 / HOLE_SPEED_KM_H; + var earliestExitTime = now + holeTravelTime; + hole.setEarliestLinkExitTime(earliestExitTime) ; hole.setSizeInEquivalents(veh2Remove.getSizeInEquivalents()); holes.add( hole ) ; break; @@ -747,9 +750,9 @@ public void recalcTimeVariantAttributes() { // not speed, since that is looked up anyways. // yy might also make flow and storage self-detecting changes (not really that // much more expensive). kai, feb'18 - + // log.debug("just entered recalcTimeVariantAttributes; now=" + this.context.getSimTimer().getTimeOfDay() ) ; - + calculateFlowCapacity(); calculateStorageCapacity(); flowcap_accumulate.setValue(flowCapacityPerTimeStep); @@ -916,7 +919,7 @@ public final double getLastMovementTimeOfFirstVehicle() { public final void addTransitSlightlyUpstreamOfStop( final QVehicle veh) { this.vehQueue.addFirst(veh) ; } - + @Override public final void setSignalized( final boolean isSignalized) { qSignalizedItem = new DefaultSignalizeableItem( qLinkInternalInterface.getToNode().getOutLinks().keySet()); @@ -1020,7 +1023,7 @@ void setVisInfo(Coord upstreamCoord, Coord downstreamCoord) { this.downstreamCoord = downstreamCoord; } } - + private int noOfSeepModeBringFwd = 0; private QVehicle peekFromVehQueue(){ diff --git a/matsim/src/main/java/org/matsim/core/router/MultimodalLinkChooser.java b/matsim/src/main/java/org/matsim/core/router/MultimodalLinkChooser.java index a7239e98198..4d8cf318622 100644 --- a/matsim/src/main/java/org/matsim/core/router/MultimodalLinkChooser.java +++ b/matsim/src/main/java/org/matsim/core/router/MultimodalLinkChooser.java @@ -2,9 +2,8 @@ import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; -import org.matsim.facilities.Facility; public interface MultimodalLinkChooser { - - public Link decideOnLink( final Facility facility, final Network network ); + public Link decideAccessLink(RoutingRequest request, Network network); + public Link decideEgressLink(RoutingRequest request, Network network); } diff --git a/matsim/src/main/java/org/matsim/core/router/MultimodalLinkChooserDefaultImpl.java b/matsim/src/main/java/org/matsim/core/router/MultimodalLinkChooserDefaultImpl.java index cd37d0f0098..00b93eb363a 100644 --- a/matsim/src/main/java/org/matsim/core/router/MultimodalLinkChooserDefaultImpl.java +++ b/matsim/src/main/java/org/matsim/core/router/MultimodalLinkChooserDefaultImpl.java @@ -15,7 +15,16 @@ class MultimodalLinkChooserDefaultImpl implements MultimodalLinkChooser { private static final Logger log = LogManager.getLogger( FacilitiesUtils.class ) ; @Override - public Link decideOnLink(Facility facility, Network network) { + public Link decideAccessLink(RoutingRequest request, Network network) { + return decideOnLink(request.getFromFacility(), network); + } + + @Override + public Link decideEgressLink(RoutingRequest request, Network network) { + return decideOnLink(request.getToFacility(), network); + } + + private Link decideOnLink(Facility facility, Network network) { Link accessActLink = null ; Id accessActLinkId = null ; diff --git a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModule.java b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModule.java index 1a24567b1dd..39338b527dd 100644 --- a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModule.java +++ b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModule.java @@ -140,9 +140,8 @@ public synchronized List calcRoute(RoutingRequest request Gbl.assertNotNull(fromFacility); Gbl.assertNotNull(toFacility); - Link accessActLink = multimodalLinkChooser.decideOnLink(fromFacility, filteredNetwork); - - Link egressActLink = multimodalLinkChooser.decideOnLink(toFacility, filteredNetwork); + Link accessActLink = multimodalLinkChooser.decideAccessLink(request, filteredNetwork); + Link egressActLink = multimodalLinkChooser.decideEgressLink(request, filteredNetwork); double now = departureTime; diff --git a/matsim/src/main/java/org/matsim/core/router/speedy/SpeedyALT.java b/matsim/src/main/java/org/matsim/core/router/speedy/SpeedyALT.java index 47c2f16de86..62b5d21590e 100644 --- a/matsim/src/main/java/org/matsim/core/router/speedy/SpeedyALT.java +++ b/matsim/src/main/java/org/matsim/core/router/speedy/SpeedyALT.java @@ -91,6 +91,7 @@ public Path calcLeastCostPath(Node startNode, Node endNode, double startTime, Pe Arrays.fill(this.iterationIds, this.currentIteration); this.currentIteration = Integer.MIN_VALUE; } + boolean hasTurnRestrictions = this.graph.hasTurnRestrictions(); int startNodeIndex = startNode.getId().index(); int endNodeIndex = endNode.getId().index(); @@ -111,6 +112,11 @@ public Path calcLeastCostPath(Node startNode, Node endNode, double startTime, Pe foundEndNode = true; break; } + // if turn restrictions are used, we might be on a colored node, so check for the original node + if (hasTurnRestrictions && this.graph.getNode(nodeIdx).getId().index() == endNodeIndex) { + foundEndNode = true; + break; + } // ignore dead-ends int deadend = this.astarData.getNodeDeadend(nodeIdx); diff --git a/matsim/src/main/java/org/matsim/core/router/speedy/SpeedyDijkstra.java b/matsim/src/main/java/org/matsim/core/router/speedy/SpeedyDijkstra.java index 735a9795fcf..ec3eb1b3035 100644 --- a/matsim/src/main/java/org/matsim/core/router/speedy/SpeedyDijkstra.java +++ b/matsim/src/main/java/org/matsim/core/router/speedy/SpeedyDijkstra.java @@ -73,6 +73,7 @@ public Path calcLeastCostPath(Node startNode, Node endNode, double startTime, Pe this.currentIteration = Integer.MIN_VALUE; } + boolean hasTurnRestrictions = this.graph.hasTurnRestrictions(); int startNodeIndex = startNode.getId().index(); int endNodeIndex = endNode.getId().index(); @@ -88,6 +89,11 @@ public Path calcLeastCostPath(Node startNode, Node endNode, double startTime, Pe foundEndNode = true; break; } + // if turn restrictions are used, we might be on a colored node, so check for the original node + if (hasTurnRestrictions && this.graph.getNode(nodeIdx).getId().index() == endNodeIndex) { + foundEndNode = true; + break; + } double currTime = getTimeRaw(nodeIdx); if (Double.isInfinite(currTime)) { diff --git a/matsim/src/main/java/org/matsim/core/router/speedy/SpeedyGraph.java b/matsim/src/main/java/org/matsim/core/router/speedy/SpeedyGraph.java index e7cd69bcf3d..7666909ca01 100644 --- a/matsim/src/main/java/org/matsim/core/router/speedy/SpeedyGraph.java +++ b/matsim/src/main/java/org/matsim/core/router/speedy/SpeedyGraph.java @@ -54,14 +54,16 @@ public class SpeedyGraph { private final int[] linkData; private final Link[] links; private final Node[] nodes; + private final boolean hasTurnRestrictions; - SpeedyGraph(int[] nodeData, int[] linkData, Node[] nodes, Link[] links) { + SpeedyGraph(int[] nodeData, int[] linkData, Node[] nodes, Link[] links, boolean hasTurnRestrictions) { this.nodeData = nodeData; this.linkData = linkData; this.nodes = nodes; this.links = links; this.nodeCount = this.nodes.length; this.linkCount = this.links.length; + this.hasTurnRestrictions = hasTurnRestrictions; } public LinkIterator getOutLinkIterator() { @@ -80,6 +82,10 @@ Node getNode(int index) { return this.nodes[index]; } + boolean hasTurnRestrictions() { + return this.hasTurnRestrictions; + } + public interface LinkIterator { void reset(int nodeIdx); diff --git a/matsim/src/main/java/org/matsim/core/router/speedy/SpeedyGraphBuilder.java b/matsim/src/main/java/org/matsim/core/router/speedy/SpeedyGraphBuilder.java index 724343da24d..54f41ee1aa4 100644 --- a/matsim/src/main/java/org/matsim/core/router/speedy/SpeedyGraphBuilder.java +++ b/matsim/src/main/java/org/matsim/core/router/speedy/SpeedyGraphBuilder.java @@ -132,7 +132,7 @@ private SpeedyGraph buildWithTurnRestrictions(Network network) { addLink(link); } - return new SpeedyGraph(this.nodeData, this.linkData, this.nodes, this.links); + return new SpeedyGraph(this.nodeData, this.linkData, this.nodes, this.links, true); } private ColoredLink applyTurnRestriction(TurnRestrictionsContext context, Collection>> restrictions, Link startingLink) { @@ -314,7 +314,7 @@ private SpeedyGraph buildWithoutTurnRestrictions(Network network) { addLink(link); } - return new SpeedyGraph(this.nodeData, this.linkData, this.nodes, this.links); + return new SpeedyGraph(this.nodeData, this.linkData, this.nodes, this.links, false); } private void addLink(Link link) { diff --git a/matsim/src/main/java/org/matsim/core/trafficmonitoring/TravelTimeCalculatorModule.java b/matsim/src/main/java/org/matsim/core/trafficmonitoring/TravelTimeCalculatorModule.java index 687cc456271..577f57583ce 100644 --- a/matsim/src/main/java/org/matsim/core/trafficmonitoring/TravelTimeCalculatorModule.java +++ b/matsim/src/main/java/org/matsim/core/trafficmonitoring/TravelTimeCalculatorModule.java @@ -26,7 +26,8 @@ import com.google.inject.Key; import com.google.inject.Singleton; import com.google.inject.name.Names; - +import jakarta.inject.Inject; +import jakarta.inject.Provider; import org.matsim.api.core.v01.network.Network; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.groups.TravelTimeCalculatorConfigGroup; @@ -35,8 +36,7 @@ import org.matsim.core.router.util.TravelTime; import org.matsim.core.utils.collections.CollectionUtils; -import jakarta.inject.Inject; -import jakarta.inject.Provider; +import java.util.Set; /** @@ -55,28 +55,42 @@ public void install() { if (getConfig().travelTimeCalculator().isCalculateLinkToLinkTravelTimes()) { throw new RuntimeException("separate modes together with link2link routing currently not implemented. doesn't look difficult, " - + "but I cannot say if it would be picked up correctly by downstream modules. kai, nov'16") ; + + "but I cannot say if it would be picked up correctly by downstream modules. kai, nov'16"); } + + Set analyzedModes = getConfig().travelTimeCalculator().getAnalyzedModes(); + // go through all modes: // for (final String mode : CollectionUtils.stringToSet(getConfig().travelTimeCalculator().getAnalyzedModesAsString() )) { - for (final String mode : getConfig().routing().getNetworkModes() ) { + for (final String mode : getConfig().routing().getNetworkModes()) { - // generate and bind the observer: - bind(TravelTimeCalculator.class).annotatedWith(Names.named(mode)).toProvider(new SingleModeTravelTimeCalculatorProvider(mode)).in(Singleton.class); + if (analyzedModes.contains(mode)) { + // generate and bind the observer: + bind(TravelTimeCalculator.class).annotatedWith(Names.named(mode)).toProvider(new SingleModeTravelTimeCalculatorProvider(mode)).in(Singleton.class); - // bind the observer to travel time provider (for router): - addTravelTimeBinding(mode).toProvider(new Provider() { - @Inject Injector injector; - @Override public TravelTime get() { - return injector.getInstance( Key.get( TravelTimeCalculator.class, Names.named( mode ) ) ).getLinkTravelTimes(); - } + // bind the observer to travel time provider (for router): + addTravelTimeBinding(mode).toProvider(new Provider() { + @Inject + Injector injector; - // the following is not there yet (leads to NPE). Presumably, the collection into the underlying multi-binder is - // done later, and until then it is only available per annotation (as above)? kai, nov'19 + @Override + public TravelTime get() { + return injector.getInstance(Key.get(TravelTimeCalculator.class, Names.named(mode))).getLinkTravelTimes(); + } + + // the following is not there yet (leads to NPE). Presumably, the collection into the underlying multi-binder is + // done later, and until then it is only available per annotation (as above)? kai, nov'19 // @Inject Map travelTimes ; // @Override public TravelTime get() { return travelTimes.get( mode ) ; } - }).in( Singleton.class ); - // (This used to be without "Singleton". I think that with Singleton it makes more sense, but don't know ramifications. kai, nov'19) + }).in(Singleton.class); + // (This used to be without "Singleton". I think that with Singleton it makes more sense, but don't know ramifications. kai, nov'19) + } else { + + // For modes that are not analyzed, no travel time calculator is bound + // however, travel time is still provided + addTravelTimeBinding(mode).to(FreeSpeedTravelTime.class).in(Singleton.class); + + } } } else { @@ -88,7 +102,7 @@ public void install() { // bind the TravelTime objects. In this case, this just passes on the same information from TravelTimeCalculator to each individual mode: if (getConfig().travelTimeCalculator().isCalculateLinkTravelTimes()) { // for (String mode : CollectionUtils.stringToSet(getConfig().travelTimeCalculator().getAnalyzedModesAsString() )) { - for ( String mode : getConfig().routing().getNetworkModes() ) { + for (String mode : getConfig().routing().getNetworkModes()) { addTravelTimeBinding(mode).toProvider(ObservedLinkTravelTimes.class); } } @@ -101,9 +115,12 @@ public void install() { private static class SingleModeTravelTimeCalculatorProvider implements Provider { - @Inject TravelTimeCalculatorConfigGroup config; - @Inject EventsManager eventsManager; - @Inject Network network; + @Inject + TravelTimeCalculatorConfigGroup config; + @Inject + EventsManager eventsManager; + @Inject + Network network; private String mode; @@ -117,17 +134,17 @@ public TravelTimeCalculator get() { // config.isCalculateLinkTravelTimes(), config.isCalculateLinkToLinkTravelTimes(), true, CollectionUtils.stringToSet(mode)); // eventsManager.addHandler(calculator); // return TravelTimeCalculator.configure(calculator, config, network); - TravelTimeCalculator.Builder builder = new TravelTimeCalculator.Builder( network ); - builder.setTimeslice( config.getTraveltimeBinSize() ); - builder.setMaxTime( config.getMaxTime() ); - builder.setCalculateLinkTravelTimes( config.isCalculateLinkTravelTimes() ); - builder.setCalculateLinkToLinkTravelTimes( config.isCalculateLinkToLinkTravelTimes() ); - builder.setFilterModes( true ); // no point asking the config since we are in "separateModes" anyways. - builder.setAnalyzedModes( CollectionUtils.stringToSet( mode ) ); - builder.configure( config ); + TravelTimeCalculator.Builder builder = new TravelTimeCalculator.Builder(network); + builder.setTimeslice(config.getTraveltimeBinSize()); + builder.setMaxTime(config.getMaxTime()); + builder.setCalculateLinkTravelTimes(config.isCalculateLinkTravelTimes()); + builder.setCalculateLinkToLinkTravelTimes(config.isCalculateLinkToLinkTravelTimes()); + builder.setFilterModes(true); // no point asking the config since we are in "separateModes" anyways. + builder.setAnalyzedModes(CollectionUtils.stringToSet(mode)); + builder.configure(config); TravelTimeCalculator calculator = builder.build(); - eventsManager.addHandler( calculator ); - return calculator ; + eventsManager.addHandler(calculator); + return calculator; } } diff --git a/matsim/src/main/java/org/matsim/core/utils/io/XmlUtils.java b/matsim/src/main/java/org/matsim/core/utils/io/XmlUtils.java index 57fa2f0b63a..85df85a9fd5 100644 --- a/matsim/src/main/java/org/matsim/core/utils/io/XmlUtils.java +++ b/matsim/src/main/java/org/matsim/core/utils/io/XmlUtils.java @@ -39,12 +39,88 @@ private XmlUtils() { * @return String with some characters replaced by their xml-encoding. */ public static String encodeAttributeValue(final String attributeValue) { - if (attributeValue.contains("&") || attributeValue.contains("\"") || attributeValue.contains("<") || attributeValue.contains(">")) { - return attributeValue.replace("&", "&").replace("\"", """).replace("<", "<").replace(">", ">"); + if (attributeValue == null) { + return null; + } + int len = attributeValue.length(); + boolean encode = false; + for (int pos = 0; pos < len; pos++) { + char ch = attributeValue.charAt(pos); + if (ch == '<') { + encode = true; + break; + } else if (ch == '>') { + encode = true; + break; + } else if (ch == '\"') { + encode = true; + break; + } else if (ch == '&') { + encode = true; + break; + } + } + if (encode) { + StringBuilder bf = new StringBuilder(attributeValue.length() + 30); + for (int pos = 0; pos < len; pos++) { + char ch = attributeValue.charAt(pos); + if (ch == '<') { + bf.append("<"); + } else if (ch == '>') { + bf.append(">"); + } else if (ch == '\"') { + bf.append("""); + } else if (ch == '&') { + bf.append("&"); + } else { + bf.append(ch); + } + } + + return bf.toString(); } return attributeValue; } + /** + * Write encoded attribute value to the given StringBuilder. + * This is an optimized version of {@link #encodeAttributeValue(String)}, which does not create any intermediate objects. + */ + public static StringBuilder writeEncodedAttributeValue(StringBuilder out, String attributeValue) { + + if (attributeValue == null) { + // By convention, null values are written as "null" in the xml output. + out.append("null"); + return out; + } + + int len = attributeValue.length(); + + for (int pos = 0; pos < len; pos++) { + char ch = attributeValue.charAt(pos); + switch (ch) { + case '<' -> out.append("<"); + case '>' -> out.append(">"); + case '\"' -> out.append("""); + case '&' -> out.append("&"); + default -> out.append(ch); + }; + } + + return out; + } + + /** + * Helper function to write an attribute key-value pair to the given StringBuilder. + * Note, do not use this for primitive types as these don't need to be encoded and the {@link StringBuilder} has specialized methods fot these. + */ + public static StringBuilder writeEncodedAttributeKeyValue(StringBuilder out, String key, String value) { + out.append(key).append("=\""); + writeEncodedAttributeValue(out, value); + out.append("\" "); + return out; + } + public static String encodeContent(final String content) { if (content.contains("&") || content.contains("<") || content.contains(">")) { return content.replace("&", "&").replace("<", "<").replace(">", ">"); diff --git a/matsim/src/main/java/org/matsim/facilities/FacilitiesWriterV1.java b/matsim/src/main/java/org/matsim/facilities/FacilitiesWriterV1.java index b312ad56cc6..17751b78d4c 100644 --- a/matsim/src/main/java/org/matsim/facilities/FacilitiesWriterV1.java +++ b/matsim/src/main/java/org/matsim/facilities/FacilitiesWriterV1.java @@ -99,7 +99,6 @@ private void writeFacility(final ActivityFacilityImpl f) { } this.attributesWriter.writeAttributes("\t\t", this.writer, f.getAttributes(), false); this.endFacility(); - this.writer.flush(); } catch (IOException e) { throw new UncheckedIOException(e); } diff --git a/matsim/src/main/java/org/matsim/facilities/FacilitiesWriterV2.java b/matsim/src/main/java/org/matsim/facilities/FacilitiesWriterV2.java index a740d2ae014..d156cda5ff0 100644 --- a/matsim/src/main/java/org/matsim/facilities/FacilitiesWriterV2.java +++ b/matsim/src/main/java/org/matsim/facilities/FacilitiesWriterV2.java @@ -99,7 +99,6 @@ private void writeFacility(final ActivityFacilityImpl f) { } this.attributesWriter.writeAttributes("\t\t", this.writer, f.getAttributes(), false); this.endFacility(); - this.writer.flush(); } catch (IOException e) { throw new UncheckedIOException(e); } diff --git a/matsim/src/main/java/org/matsim/pt/utils/CreatePseudoNetwork.java b/matsim/src/main/java/org/matsim/pt/utils/CreatePseudoNetwork.java index 906c97396ee..104860e67bb 100644 --- a/matsim/src/main/java/org/matsim/pt/utils/CreatePseudoNetwork.java +++ b/matsim/src/main/java/org/matsim/pt/utils/CreatePseudoNetwork.java @@ -152,7 +152,14 @@ private Link getNetworkLink(final TransitRouteStop fromStop, final TransitRouteS } Id newId = Id.create(toFacility.getId().toString() + "." + Integer.toString(copies.size() + 1), TransitStopFacility.class); TransitStopFacility newFacility = this.schedule.getFactory().createTransitStopFacility(newId, toFacility.getCoord(), toFacility.getIsBlockingLane()); - newFacility.setStopAreaId(Id.create(toFacility.getId(), TransitStopArea.class)); + Id transitStopAreaId; + if (toFacility.getStopAreaId() == null) { + transitStopAreaId = Id.create(toFacility.getId(), TransitStopArea.class); + toFacility.setStopAreaId(transitStopAreaId); + } else { + transitStopAreaId = toFacility.getStopAreaId(); + } + newFacility.setStopAreaId(transitStopAreaId); newFacility.setLinkId(link.getId()); newFacility.setName(toFacility.getName()); copies.add(newFacility); diff --git a/matsim/src/main/java/org/matsim/pt/utils/CreateVehiclesForSchedule.java b/matsim/src/main/java/org/matsim/pt/utils/CreateVehiclesForSchedule.java index 3adbd0b8407..287fac979f9 100644 --- a/matsim/src/main/java/org/matsim/pt/utils/CreateVehiclesForSchedule.java +++ b/matsim/src/main/java/org/matsim/pt/utils/CreateVehiclesForSchedule.java @@ -21,6 +21,7 @@ package org.matsim.pt.utils; import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.TransportMode; import org.matsim.pt.transitSchedule.api.Departure; import org.matsim.pt.transitSchedule.api.TransitLine; import org.matsim.pt.transitSchedule.api.TransitRoute; @@ -45,13 +46,18 @@ public CreateVehiclesForSchedule(final TransitSchedule schedule, final Vehicles this.schedule = schedule; this.vehicles = vehicles; } - + public void run() { + run(TransportMode.car); + } + + public void run(String networkMode) { VehiclesFactory vb = this.vehicles.getFactory(); VehicleType vehicleType = vb.createVehicleType(Id.create("defaultTransitVehicleType", VehicleType.class)); // VehicleCapacity capacity = new VehicleCapacity(); vehicleType.getCapacity().setSeats( 101 ); vehicleType.getCapacity().setStandingRoom( 0 ); + vehicleType.setNetworkMode(networkMode); // vehicleType.setCapacity(capacity); this.vehicles.addVehicleType(vehicleType); diff --git a/matsim/src/main/java/org/matsim/pt/utils/TransitScheduleValidator.java b/matsim/src/main/java/org/matsim/pt/utils/TransitScheduleValidator.java index cfd96dbe88f..5f05825abc1 100644 --- a/matsim/src/main/java/org/matsim/pt/utils/TransitScheduleValidator.java +++ b/matsim/src/main/java/org/matsim/pt/utils/TransitScheduleValidator.java @@ -20,17 +20,12 @@ package org.matsim.pt.utils; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; +import java.util.*; import javax.xml.parsers.ParserConfigurationException; +import it.unimi.dsi.fastutil.doubles.DoubleArrayList; +import it.unimi.dsi.fastutil.doubles.DoubleList; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; @@ -39,13 +34,9 @@ import org.matsim.core.population.routes.NetworkRoute; import org.matsim.core.scenario.MutableScenario; import org.matsim.core.scenario.ScenarioUtils; -import org.matsim.pt.transitSchedule.api.MinimalTransferTimes; -import org.matsim.pt.transitSchedule.api.TransitLine; -import org.matsim.pt.transitSchedule.api.TransitRoute; -import org.matsim.pt.transitSchedule.api.TransitRouteStop; -import org.matsim.pt.transitSchedule.api.TransitSchedule; -import org.matsim.pt.transitSchedule.api.TransitScheduleReader; -import org.matsim.pt.transitSchedule.api.TransitStopFacility; +import org.matsim.core.utils.geometry.CoordUtils; +import org.matsim.core.utils.geometry.GeometryUtils; +import org.matsim.pt.transitSchedule.api.*; import org.xml.sax.SAXException; /** @@ -248,6 +239,135 @@ public static ValidationResult validateTransfers(final TransitSchedule schedule) return result; } + public static ValidationResult validateDepartures(TransitSchedule schedule) { + ValidationResult result = new ValidationResult(); + for (TransitLine line : schedule.getTransitLines().values()) { + for (TransitRoute route : line.getRoutes().values()) { + if (route.getDepartures().isEmpty()) + result.addError("No departures defined for line %s, route %s".formatted(line.getId(), route.getId())); + + } + } + + return result; + } + + /** + * Validate if coordinates of stops and given travel times are plausible. + */ + public static ValidationResult validateStopCoordinates(final TransitSchedule schedule) { + + ValidationResult result = new ValidationResult(); + + // List of stops to the collected suspicious stops + Map suspiciousStops = new TreeMap<>(Comparator.comparing(TransitStopFacility::getName)); + + for (TransitLine line : schedule.getTransitLines().values()) { + + for (TransitRoute route : line.getRoutes().values()) { + + List routeStops = route.getStops(); + + // For too short routes, we can not detect outliers + if (routeStops.size() <= 4) + continue; + + double lastDepartureOffset = routeStops.getFirst().getDepartureOffset().or(routeStops.getFirst().getArrivalOffset()).seconds(); + + DoubleList speeds = new DoubleArrayList(); + DoubleList dists = new DoubleArrayList(); + + for (int i = 1; i < routeStops.size(); i++) { + TransitRouteStop routeStop = routeStops.get(i); + + if (routeStop.getStopFacility().getCoord() == null) + break; + + double departureOffset = routeStop.getArrivalOffset().or(routeStop.getDepartureOffset()).orElse(0); + double travelTime = departureOffset - lastDepartureOffset; + double length = CoordUtils.calcEuclideanDistance(routeStop.getStopFacility().getCoord(), + routeStops.get(i - 1).getStopFacility().getCoord()); + + dists.add(length); + + // Short distances are not checked, because here high speeds are not so problematic and arise from few seconds difference + if (length <= 20) { + speeds.add(-1); + continue; + } + + if (travelTime == 0) { + speeds.add(Double.POSITIVE_INFINITY); + continue; + } + + double speed = length / travelTime; + speeds.add(speed); + lastDepartureOffset = departureOffset; + } + + // If all speeds are valid, the stops and speeds can be checked + if (speeds.size() == routeStops.size() - 1) { + + // First check for suspicious stops + // These are stops with very high speed, and also high distance between stops + for (int i = 0; i < speeds.size() - 1; i++) { + TransitRouteStop stop = routeStops.get(i + 1); + double toStop = speeds.getDouble(i); + double fromStop = speeds.getDouble(i + 1); + + double both = (toStop + fromStop) / 2; + + double dist = (dists.getDouble(i) + dists.getDouble(i + 1)) / 2; + + // Only if the distance is large, we assume a mapping error might have occurred + if (dist < 5_000) + continue; + + // Remove the considered speeds from the calculation + DoubleList copy = new DoubleArrayList(speeds); + copy.removeDouble(i); + copy.removeDouble(i); + copy.removeIf(s -> s == -1 || s == Double.POSITIVE_INFINITY); + + double mean = copy.doubleStream().average().orElse(-1); + + // If no mean is known, use a high value to avoid false positives + if (mean == -1) { + mean = 70; + } + + // Some hard coded rules to detect suspicious stops, these are speed m/s, so quite high values + if (((toStop > 3 * mean && both > 50) || toStop > 120) && (((fromStop > 3 * mean && both > 50) || fromStop > 120))) { + DoubleList suspiciousSpeeds = suspiciousStops.computeIfAbsent(stop.getStopFacility(), (k) -> new DoubleArrayList()); + suspiciousSpeeds.add(toStop); + suspiciousSpeeds.add(fromStop); + } + } + + // Then check for implausible travel times + for (int i = 0; i < speeds.size(); i++) { + double speed = speeds.getDouble(i); + TransitStopFacility from = routeStops.get(i).getStopFacility(); + TransitStopFacility to = routeStops.get(i + 1).getStopFacility(); + if (speed > 230) { + result.addWarning("Suspicious high speed from stop %s (%s) to %s (%s) on line %s, route %s, index: %d: %.2f m/s, %.2fm" + .formatted(from.getName(), from.getId(), to.getName(), to.getId(), line.getId(), route.getId(), i, speed, dists.getDouble(i))); + } + } + } + } + } + + for (Map.Entry e : suspiciousStops.entrySet()) { + TransitStopFacility stop = e.getKey(); + double speed = e.getValue().doubleStream().average().orElse(-1); + result.addWarning("Suspicious location for stop %s (%s) at stop area %s: %s, avg. speed: %.2f m/s".formatted(stop.getName(), stop.getId(), stop.getStopAreaId(), stop.getCoord(), speed)); + } + + return result; + } + public static ValidationResult validateAll(final TransitSchedule schedule, final Network network) { ValidationResult v = validateUsedStopsHaveLinkId(schedule); v.add(validateNetworkRoutes(schedule, network)); @@ -259,6 +379,8 @@ public static ValidationResult validateAll(final TransitSchedule schedule, final v.add(validateAllStopsExist(schedule)); v.add(validateOffsets(schedule)); v.add(validateTransfers(schedule)); + v.add(validateStopCoordinates(schedule)); + v.add(validateDepartures(schedule)); return v; } diff --git a/matsim/src/main/java/org/matsim/vehicles/VehicleReaderV1.java b/matsim/src/main/java/org/matsim/vehicles/VehicleReaderV1.java index 697958b0fd6..b2847dc404e 100644 --- a/matsim/src/main/java/org/matsim/vehicles/VehicleReaderV1.java +++ b/matsim/src/main/java/org/matsim/vehicles/VehicleReaderV1.java @@ -3,6 +3,7 @@ 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.TransportMode; import org.matsim.core.utils.io.MatsimXmlParser; import org.xml.sax.Attributes; @@ -38,6 +39,10 @@ public void endTag( final String name, final String content, final Stack public void startTag( final String name, final Attributes atts, final Stack context ){ if( VehicleSchemaV1Names.VEHICLETYPE.equalsIgnoreCase( name ) ){ this.currentVehType = this.builder.createVehicleType( Id.create( atts.getValue( VehicleSchemaV1Names.ID ), VehicleType.class ) ); + // In the old format there is no network mode, and everything was basically a car. + // Vehicle type does not contain a default network mode anymore, therefore we need to set it here. + this.currentVehType.setNetworkMode( TransportMode.car ); + } else if( VehicleSchemaV1Names.LENGTH.equalsIgnoreCase( name ) ){ this.currentVehType.setLength( Double.parseDouble( atts.getValue( VehicleSchemaV1Names.METER ) ) ); } else if( VehicleSchemaV1Names.WIDTH.equalsIgnoreCase( name ) ){ diff --git a/matsim/src/main/java/org/matsim/vehicles/VehicleType.java b/matsim/src/main/java/org/matsim/vehicles/VehicleType.java index 9aef2a705e1..512705d4f0d 100644 --- a/matsim/src/main/java/org/matsim/vehicles/VehicleType.java +++ b/matsim/src/main/java/org/matsim/vehicles/VehicleType.java @@ -26,6 +26,8 @@ import org.matsim.utils.objectattributes.attributable.Attributes; import org.matsim.utils.objectattributes.attributable.AttributesImpl; +import java.util.Objects; + /** * @author dgrether */ @@ -46,13 +48,22 @@ public final class VehicleType implements Attributable, Identifiable id; private final Attributes attributes = new AttributesImpl(); VehicleType( Id typeId ) { this.id = typeId; + // For car typ default network mode is assumed, for others it needs to be set explicitly. + if (typeId != null && Objects.equals(typeId.toString(), TransportMode.car)) + this.networkMode = TransportMode.car; + } + + VehicleType(Id typeId, String networkMode) { + this.id = typeId; + this.networkMode = networkMode; } + public final String getDescription() { return description; } @@ -114,7 +125,7 @@ public final CostInformation getCostInformation() { return costInformation; } public final String getNetworkMode() { - return networkMode; + return Objects.requireNonNull(networkMode, () -> "Network mode not set for vehicle type %s. Network mode needs to be set explicitly for non car modes. You can do this in XML by adding \t\n".formatted(id, id)); } public final VehicleType setNetworkMode( String networkMode ) { this.networkMode = networkMode; diff --git a/matsim/src/main/java/org/matsim/vehicles/VehicleUtils.java b/matsim/src/main/java/org/matsim/vehicles/VehicleUtils.java index aac3e537da9..d149ad07eb2 100644 --- a/matsim/src/main/java/org/matsim/vehicles/VehicleUtils.java +++ b/matsim/src/main/java/org/matsim/vehicles/VehicleUtils.java @@ -27,6 +27,7 @@ import org.apache.logging.log4j.Logger; 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.network.Link; import org.matsim.api.core.v01.population.Person; import org.matsim.core.gbl.Gbl; @@ -64,6 +65,10 @@ public static VehicleType createVehicleType( Id typeId ){ return new VehicleType( typeId ); } + public static VehicleType createVehicleType( Id typeId, String networkMode){ + return new VehicleType( typeId, networkMode ); + } + public static VehiclesFactory getFactory() { return new VehiclesFactoryImpl(); } @@ -75,9 +80,9 @@ public static Vehicles createVehiclesContainer() { public static VehicleType createDefaultVehicleType() { VehicleType defaultVehicleType = VehicleUtils.getFactory() .createVehicleType(Id.create(DEFAULT_VEHICLE_TYPE_ID, VehicleType.class)); - + defaultVehicleType.getCapacity().setSeats(4); - + defaultVehicleType.setNetworkMode(TransportMode.car); return defaultVehicleType; } @@ -294,16 +299,24 @@ public static void setAccessTime(VehicleType vehicleType, double accessTime) { vehicleType.getAttributes().putAttribute(ACCESSTIME, accessTime); } + /** + * @deprecated use getFuelConsumptionPerMeter instead + */ + @Deprecated public static Double getFuelConsumption(VehicleType vehicleType) { - return getFuelConsumption(vehicleType.getEngineInformation()); + return getFuelConsumptionLitersPerMeter(vehicleType.getEngineInformation()); } + /** + * @deprecated use setFuelConsumptionPerMeter instead + */ + @Deprecated public static void setFuelConsumption(VehicleType vehicleType, double literPerMeter) { - setFuelConsumption(vehicleType.getEngineInformation(), literPerMeter); + setFuelConsumptionLitersPerMeter(vehicleType.getEngineInformation(), literPerMeter); } //******** EngineInformation attributes ************ - + //TODO create enum for fuel type public static String getHbefaTechnology( EngineInformation ei ){ return (String) ei.getAttributes().getAttribute( HBEFA_TECHNOLOGY ) ; } @@ -340,6 +353,14 @@ public static void setEnergyConsumptionKWhPerMeter(EngineInformation engineInfor engineInformation.getAttributes().putAttribute(ENERGYCONSUMPTION, energyConsumptionKWhPerMeter); } + public static Double getFuelConsumptionLitersPerMeter(EngineInformation engineInformation) { + return (Double) engineInformation.getAttributes().getAttribute(FUELCONSUMPTION); + } + + public static void setFuelConsumptionLitersPerMeter(EngineInformation engineInformation, double fuelConsumptionLitersPerMeter) { + engineInformation.getAttributes().putAttribute(FUELCONSUMPTION, fuelConsumptionLitersPerMeter); + } + public static Double getEnergyCapacity(EngineInformation engineInformation) { return (Double) engineInformation.getAttributes().getAttribute(ENERGYCAPACITY); } @@ -372,21 +393,33 @@ public static Vehicle createVehicle( Id id , VehicleType type ){ return new VehicleImpl( id , type ); } + /** + * @deprecated use getHbefaTechnology instead + */ @Deprecated static EngineInformation.FuelType getFuelType(EngineInformation engineInformation ){ return (EngineInformation.FuelType) engineInformation.getAttributes().getAttribute( FUEL_TYPE ); } + /** + * @deprecated use setHbefaTechnology instead + */ @Deprecated static void setFuelType(EngineInformation engineInformation, EngineInformation.FuelType fuelType ){ engineInformation.getAttributes().putAttribute( FUEL_TYPE, fuelType); } + /** + * @Deprecated use getFuelConsumptionPerMeter instead + */ @Deprecated static Double getFuelConsumption(EngineInformation engineInformation ){ return (Double) engineInformation.getAttributes().getAttribute( FUELCONSUMPTION ); } + /** + * @Deprecated use setFuelConsumptionPerMeter instead + */ @Deprecated static void setFuelConsumption(EngineInformation engineInformation, double fuelConsumption ){ engineInformation.getAttributes().putAttribute( FUELCONSUMPTION, fuelConsumption); @@ -434,7 +467,7 @@ public static void writeVehicles( Vehicles vehicles, String filename ) { new MatsimVehicleWriter( vehicles ).writeFile( filename ); } - + public static Id getInitialLinkId(Vehicle vehicle) { String attribute = (String) vehicle.getAttributes().getAttribute(INITIAL_LINK_ID); return attribute == null ? null : Id.createLinkId(attribute); diff --git a/matsim/src/main/resources/dtd/chargers_v1.dtd b/matsim/src/main/resources/dtd/chargers_v1.dtd index 5e849dddd91..c9c4f13184d 100644 --- a/matsim/src/main/resources/dtd/chargers_v1.dtd +++ b/matsim/src/main/resources/dtd/chargers_v1.dtd @@ -9,7 +9,7 @@ - + @@ -21,3 +21,10 @@ plug_power CDATA #REQUIRED plug_count CDATA #IMPLIED type CDATA #IMPLIED > + + + + + diff --git a/matsim/src/main/resources/dtd/lspsDefinitions_v1.xsd b/matsim/src/main/resources/dtd/lspsDefinitions_v1.xsd index 32a03b4d072..ff3cb9be076 100644 --- a/matsim/src/main/resources/dtd/lspsDefinitions_v1.xsd +++ b/matsim/src/main/resources/dtd/lspsDefinitions_v1.xsd @@ -1,11 +1,11 @@ + targetNamespace="http://www.matsim.org/files/dtd" + xmlns="http://www.matsim.org/files/dtd" + elementFormDefault="qualified" + xml:lang="en"> - + @@ -24,6 +24,7 @@ + diff --git a/matsim/src/test/java/ch/sbb/matsim/RaptorDeterminismTest.java b/matsim/src/test/java/ch/sbb/matsim/RaptorDeterminismTest.java new file mode 100644 index 00000000000..99689ade903 --- /dev/null +++ b/matsim/src/test/java/ch/sbb/matsim/RaptorDeterminismTest.java @@ -0,0 +1,207 @@ +package ch.sbb.matsim; + +import ch.sbb.matsim.routing.pt.raptor.SwissRailRaptorData; +import ch.sbb.matsim.routing.pt.raptor.RaptorStopFinder; +import ch.sbb.matsim.routing.pt.raptor.RaptorParametersForPerson; +import ch.sbb.matsim.routing.pt.raptor.SwissRailRaptor; +import ch.sbb.matsim.routing.pt.raptor.RaptorParameters; +import ch.sbb.matsim.routing.pt.raptor.InitialStop; +import com.google.inject.Injector; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.population.*; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.events.EventsManagerModule; +import org.matsim.core.router.TripRouter; +import org.matsim.core.router.TripRouterModule; +import org.matsim.core.router.TripStructureUtils; +import org.matsim.core.router.costcalculators.TravelDisutilityModule; +import org.matsim.core.scenario.ScenarioByInstanceModule; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.trafficmonitoring.TravelTimeCalculatorModule; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.core.utils.timing.TimeInterpretationModule; +import org.matsim.examples.ExamplesUtils; +import org.matsim.facilities.ActivityFacilities; +import org.matsim.facilities.FacilitiesUtils; +import org.matsim.facilities.Facility; +import org.matsim.pt.routes.DefaultTransitPassengerRoute; +import org.matsim.pt.transitSchedule.api.TransitStopFacility; + + +import java.net.URL; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; + +public class RaptorDeterminismTest { + + public static boolean comparePlan(List left, List right) { + if(left.size() != right.size()) { + return false; + } + for(int i=0; i[] transitStopFacilitiesByScenario = new List[scenarioSamples]; + List[] personLists = new List[scenarioSamples]; + TripRouter[] tripRouters = new TripRouter[scenarioSamples]; + + logger.info(String.format("Loading scenario %d times", scenarioSamples)); + for(int scenarioIndex=0; scenarioIndex(scenario.getTransitSchedule().getFacilities().values()); + swissRailRaptorData[scenarioIndex] = swissRailRaptors[scenarioIndex].getUnderlyingData(); + personLists[scenarioIndex] = scenario.getPopulation().getPersons().values().stream().toList(); + + tripRouters[scenarioIndex] = injector.getInstance(TripRouter.class); + } + + logger.info(String.format("Comparing stop facilities order %d", scenarioSamples)); + + for(int scenarioIndex=1; scenarioIndex referenceElements = tripRouters[0].calcRoute("pt", fromFacility, toFacility, referenceTrip.getOriginActivity().getEndTime().seconds(), referencePerson, referenceTrip.getTripAttributes()); + + for(int scenarioIndex=1; scenarioIndex referenceInitialStops = raptorStopFinders[0].findStops(fromFacility, toFacility, referencePerson, referenceTrip.getOriginActivity().getEndTime().seconds(), referenceTrip.getTripAttributes(), referenceRaptorParameters, swissRailRaptorData[0], direction); + List sortedReferenceInitialStops = new ArrayList<>(referenceInitialStops); + sortedReferenceInitialStops.sort(Comparator.comparing(InitialStop::toString)); + + List comparedInitialStops = raptorStopFinders[scenarioIndex].findStops(otherFromFacility, otherToFacility, referencePerson, referenceTrip.getOriginActivity().getEndTime().seconds(), referenceTrip.getTripAttributes(), otherRaptorParameters, swissRailRaptorData[scenarioIndex], direction); + + assert referenceInitialStops.size() == comparedInitialStops.size(); + + List sortedComparedInitialStops = new ArrayList<>(comparedInitialStops); + sortedComparedInitialStops.sort(Comparator.comparing(InitialStop::toString)); + for(int j=0; j comparedElements = tripRouters[scenarioIndex].calcRoute("pt", otherFromFacility, otherToFacility, referenceTrip.getOriginActivity().getEndTime().seconds(), otherPerson, referenceTrip.getTripAttributes()); + assert comparePlan(referenceElements, comparedElements); + } + } + } + } + +} diff --git a/matsim/src/test/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysisTest.java b/matsim/src/test/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysisTest.java index 88e5fb60349..f7d680241db 100644 --- a/matsim/src/test/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysisTest.java +++ b/matsim/src/test/java/org/matsim/analysis/pt/stop2stop/PtStop2StopAnalysisTest.java @@ -42,7 +42,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; /** * @author dtamleh @@ -107,7 +106,7 @@ void testPtStop2StopAnalysisSingle() { String networkMode_bus = TransportMode.car; - PtStop2StopAnalysis ptStop2StopAnalysis = new PtStop2StopAnalysis(scenario.getTransitVehicles()); + PtStop2StopAnalysis ptStop2StopAnalysis = new PtStop2StopAnalysis(scenario.getTransitVehicles(), 1.0); ParallelEventsManager events = new ParallelEventsManager(false); events.addHandler(ptStop2StopAnalysis); @@ -141,34 +140,34 @@ void testPtStop2StopAnalysisSingle() { // Tests List line1_route1_dep1_stop1 = ptStop2StopAnalysis.getStop2StopEntriesByDeparture().stream() - .filter(entry -> entry.transitLineId.equals(transitLineId_bus1) && entry.transitRouteId.equals(transitRouteId_bus1_route1) - && entry.departureId.equals(departureId_bus1_route1_dep1) && entry.stopId.equals(transitStopFacilityId1) - && entry.stopSequence == 0).collect(Collectors.toList()); + .filter(entry -> entry.transitLineId().equals(transitLineId_bus1) && entry.transitRouteId().equals(transitRouteId_bus1_route1) + && entry.departureId().equals(departureId_bus1_route1_dep1) && entry.stopId().equals(transitStopFacilityId1) + && entry.stopSequence() == 0).toList(); System.out.println(line1_route1_dep1_stop1.size()); Assertions.assertEquals(1, line1_route1_dep1_stop1.size(), "Either no entry or more than entry for " + transitLineId_bus1 + ", " + transitRouteId_bus1_route1 + ", " + departureId_bus1_route1_dep1 + ", " + departureId_bus1_route1_dep1 + ", " + transitStopFacilityId1 + ", 0"); - Assertions.assertNull(line1_route1_dep1_stop1.get(0).stopPreviousId, "There should be no previous stop, but there was"); - Assertions.assertEquals(1.0, line1_route1_dep1_stop1.get(0).arrivalTimeScheduled, MatsimTestUtils.EPSILON, "Wrong arrivalTimeScheduled"); - Assertions.assertEquals(0.0, line1_route1_dep1_stop1.get(0).arrivalDelay, MatsimTestUtils.EPSILON, "Wrong arrivalDelay"); - Assertions.assertEquals(3.0, line1_route1_dep1_stop1.get(0).departureTimeScheduled, MatsimTestUtils.EPSILON); - Assertions.assertEquals(0.0, line1_route1_dep1_stop1.get(0).departureDelay, MatsimTestUtils.EPSILON); - Assertions.assertEquals(0.0, line1_route1_dep1_stop1.get(0).passengersAtArrival, MatsimTestUtils.EPSILON); - Assertions.assertEquals(veh_bus1.getType().getCapacity().getSeats() + veh_bus1.getType().getCapacity().getStandingRoom(), line1_route1_dep1_stop1.get(0).totalVehicleCapacity, MatsimTestUtils.EPSILON); - Assertions.assertEquals(0.0, line1_route1_dep1_stop1.get(0).passengersAlighting, MatsimTestUtils.EPSILON); - Assertions.assertEquals(2.0, line1_route1_dep1_stop1.get(0).passengersBoarding, MatsimTestUtils.EPSILON); + Assertions.assertNull(line1_route1_dep1_stop1.get(0).stopPreviousId(), "There should be no previous stop, but there was"); + Assertions.assertEquals(1.0, line1_route1_dep1_stop1.get(0).arrivalTimeScheduled(), MatsimTestUtils.EPSILON, "Wrong arrivalTimeScheduled"); + Assertions.assertEquals(0.0, line1_route1_dep1_stop1.get(0).arrivalDelay(), MatsimTestUtils.EPSILON, "Wrong arrivalDelay"); + Assertions.assertEquals(3.0, line1_route1_dep1_stop1.get(0).departureTimeScheduled(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(0.0, line1_route1_dep1_stop1.get(0).departureDelay(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(0.0, line1_route1_dep1_stop1.get(0).passengersAtArrival(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(veh_bus1.getType().getCapacity().getSeats() + veh_bus1.getType().getCapacity().getStandingRoom(), line1_route1_dep1_stop1.get(0).totalVehicleCapacity(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(0.0, line1_route1_dep1_stop1.get(0).passengersAlighting(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(2.0, line1_route1_dep1_stop1.get(0).passengersBoarding(), MatsimTestUtils.EPSILON); List> linkList = new ArrayList<>(); linkList.add(linkId1); - Assertions.assertEquals(linkList, line1_route1_dep1_stop1.get(0).linkIdsSincePreviousStop, "Wrong links"); + Assertions.assertEquals(linkList, line1_route1_dep1_stop1.get(0).linkIdsSincePreviousStop(), "Wrong links"); List line1_route1_dep1_stop3 = ptStop2StopAnalysis.getStop2StopEntriesByDeparture().stream() - .filter(entry -> entry.transitLineId.equals(transitLineId_bus1) && entry.transitRouteId.equals(transitRouteId_bus1_route1) - && entry.departureId.equals(departureId_bus1_route1_dep1) && entry.stopId.equals(transitStopFacilityId3) - && entry.stopSequence == 2).collect(Collectors.toList()); + .filter(entry -> entry.transitLineId().equals(transitLineId_bus1) && entry.transitRouteId().equals(transitRouteId_bus1_route1) + && entry.departureId().equals(departureId_bus1_route1_dep1) && entry.stopId().equals(transitStopFacilityId3) + && entry.stopSequence() == 2).toList(); Assertions.assertEquals(1, line1_route1_dep1_stop3.size(), "Either no entry or more than entry for " + transitLineId_bus1 + ", " + transitRouteId_bus1_route1 + ", " + departureId_bus1_route1_dep1 + ", " + departureId_bus1_route1_dep1 + ", " + transitStopFacilityId3 + ", 0"); - Assertions.assertEquals(transitStopFacilityId2, line1_route1_dep1_stop3.get(0).stopPreviousId, "There is no previous stop"); - Assertions.assertEquals(12.0, line1_route1_dep1_stop3.get(0).departureTimeScheduled, MatsimTestUtils.EPSILON); - Assertions.assertEquals(12.0, line1_route1_dep1_stop3.get(0).arrivalTimeScheduled, MatsimTestUtils.EPSILON, "Wrong arrivalTimeScheduled"); - Assertions.assertEquals(-1.0, line1_route1_dep1_stop3.get(0).arrivalDelay, MatsimTestUtils.EPSILON, "Wrong arrival delay"); - Assertions.assertEquals(1.0, line1_route1_dep1_stop3.get(0).departureDelay, MatsimTestUtils.EPSILON, "Wrong departure delay"); + Assertions.assertEquals(transitStopFacilityId2, line1_route1_dep1_stop3.get(0).stopPreviousId(), "There is no previous stop"); + Assertions.assertEquals(12.0, line1_route1_dep1_stop3.get(0).departureTimeScheduled(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(12.0, line1_route1_dep1_stop3.get(0).arrivalTimeScheduled(), MatsimTestUtils.EPSILON, "Wrong arrivalTimeScheduled"); + Assertions.assertEquals(-1.0, line1_route1_dep1_stop3.get(0).arrivalDelay(), MatsimTestUtils.EPSILON, "Wrong arrival delay"); + Assertions.assertEquals(1.0, line1_route1_dep1_stop3.get(0).departureDelay(), MatsimTestUtils.EPSILON, "Wrong departure delay"); } // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -257,7 +256,7 @@ void testPtStop2StopAnalysisMulti() { String networkMode_bus = TransportMode.car; String networkMode_train = TransportMode.train; - PtStop2StopAnalysis ptStop2StopAnalysis = new PtStop2StopAnalysis(scenario.getTransitVehicles()); + PtStop2StopAnalysis ptStop2StopAnalysis = new PtStop2StopAnalysis(scenario.getTransitVehicles(), 1.0); ParallelEventsManager events = new ParallelEventsManager(false); events.addHandler(ptStop2StopAnalysis); @@ -444,54 +443,54 @@ void testPtStop2StopAnalysisMulti() { // Tests - List bus1_dep1_stop1 = ptStop2StopAnalysis.getStop2StopEntriesByDeparture().stream().filter(entry -> entry.transitLineId.equals(transitLineId_bus1) && entry.transitRouteId.equals(transitRouteId_bus1_route1) && entry.departureId.equals(departureId_bus1_dep1) && entry.stopId.equals(transitStopFacilityId1) && entry.stopSequence == 0).collect(Collectors.toList()); + List bus1_dep1_stop1 = ptStop2StopAnalysis.getStop2StopEntriesByDeparture().stream().filter(entry -> entry.transitLineId().equals(transitLineId_bus1) && entry.transitRouteId().equals(transitRouteId_bus1_route1) && entry.departureId().equals(departureId_bus1_dep1) && entry.stopId().equals(transitStopFacilityId1) && entry.stopSequence() == 0).toList(); Assertions.assertEquals(1, bus1_dep1_stop1.size(), "Either no entry or more than entry for " + transitLineId_bus1 + ", " + transitRouteId_bus1_route1 + ", " + departureId_bus1_dep1 + ", " + departureId_bus1_dep1 + ", " + transitStopFacilityId1 + ", 0"); - Assertions.assertNull(bus1_dep1_stop1.get(0).stopPreviousId, "There should be no previous stop, but there was"); - Assertions.assertEquals(1.0, bus1_dep1_stop1.get(0).arrivalTimeScheduled, MatsimTestUtils.EPSILON, "Wrong arrivalTimeScheduled"); - Assertions.assertEquals(0.0, bus1_dep1_stop1.get(0).arrivalDelay, MatsimTestUtils.EPSILON, "Wrong arrivalDelay"); - Assertions.assertEquals(3.0, bus1_dep1_stop1.get(0).departureTimeScheduled, MatsimTestUtils.EPSILON); - Assertions.assertEquals(0.0, bus1_dep1_stop1.get(0).departureDelay, MatsimTestUtils.EPSILON); - Assertions.assertEquals(0.0, bus1_dep1_stop1.get(0).passengersAtArrival, MatsimTestUtils.EPSILON); - Assertions.assertEquals(veh_bus1_dep1.getType().getCapacity().getSeats() + veh_bus1_dep1.getType().getCapacity().getStandingRoom(), bus1_dep1_stop1.get(0).totalVehicleCapacity, MatsimTestUtils.EPSILON); - Assertions.assertEquals(0.0, bus1_dep1_stop1.get(0).passengersAlighting, MatsimTestUtils.EPSILON); - Assertions.assertEquals(2.0, bus1_dep1_stop1.get(0).passengersBoarding, MatsimTestUtils.EPSILON); + Assertions.assertNull(bus1_dep1_stop1.get(0).stopPreviousId(), "There should be no previous stop, but there was"); + Assertions.assertEquals(1.0, bus1_dep1_stop1.get(0).arrivalTimeScheduled(), MatsimTestUtils.EPSILON, "Wrong arrivalTimeScheduled"); + Assertions.assertEquals(0.0, bus1_dep1_stop1.get(0).arrivalDelay(), MatsimTestUtils.EPSILON, "Wrong arrivalDelay"); + Assertions.assertEquals(3.0, bus1_dep1_stop1.get(0).departureTimeScheduled(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(0.0, bus1_dep1_stop1.get(0).departureDelay(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(0.0, bus1_dep1_stop1.get(0).passengersAtArrival(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(veh_bus1_dep1.getType().getCapacity().getSeats() + veh_bus1_dep1.getType().getCapacity().getStandingRoom(), bus1_dep1_stop1.get(0).totalVehicleCapacity(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(0.0, bus1_dep1_stop1.get(0).passengersAlighting(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(2.0, bus1_dep1_stop1.get(0).passengersBoarding(), MatsimTestUtils.EPSILON); List> linkList = new ArrayList<>(); linkList.add(linkId1); - Assertions.assertEquals(linkList, bus1_dep1_stop1.get(0).linkIdsSincePreviousStop, "Wrong links"); + Assertions.assertEquals(linkList, bus1_dep1_stop1.get(0).linkIdsSincePreviousStop(), "Wrong links"); - List bus1_dep1_stop3 = ptStop2StopAnalysis.getStop2StopEntriesByDeparture().stream().filter(entry -> entry.transitLineId.equals(transitLineId_bus1) && entry.transitRouteId.equals(transitRouteId_bus1_route1) && entry.departureId.equals(departureId_bus1_dep1) && entry.stopId.equals(transitStopFacilityId4) && entry.stopSequence == 2).collect(Collectors.toList()); + List bus1_dep1_stop3 = ptStop2StopAnalysis.getStop2StopEntriesByDeparture().stream().filter(entry -> entry.transitLineId().equals(transitLineId_bus1) && entry.transitRouteId().equals(transitRouteId_bus1_route1) && entry.departureId().equals(departureId_bus1_dep1) && entry.stopId().equals(transitStopFacilityId4) && entry.stopSequence() == 2).toList(); System.out.println(bus1_dep1_stop3.isEmpty()); Assertions.assertEquals(1, bus1_dep1_stop3.size(), "Either no entry or more than entry for " + transitLineId_bus1 + ", " + transitRouteId_bus1_route1 + ", " + departureId_bus1_dep1 + ", " + departureId_bus1_dep1 + ", " + transitStopFacilityId4 + ", 0"); - Assertions.assertEquals(0.0, bus1_dep1_stop3.get(0).arrivalDelay, MatsimTestUtils.EPSILON, "Wrong arrivalDelay"); - Assertions.assertEquals(15.0, bus1_dep1_stop3.get(0).departureTimeScheduled, MatsimTestUtils.EPSILON); - Assertions.assertEquals(0.0, bus1_dep1_stop3.get(0).departureDelay, MatsimTestUtils.EPSILON); - Assertions.assertEquals(3.0, bus1_dep1_stop3.get(0).passengersAtArrival, MatsimTestUtils.EPSILON); - Assertions.assertEquals(veh_bus1_dep1.getType().getCapacity().getSeats() + veh_bus1_dep1.getType().getCapacity().getStandingRoom(), bus1_dep1_stop1.get(0).totalVehicleCapacity, MatsimTestUtils.EPSILON); - Assertions.assertEquals(3.0, bus1_dep1_stop3.get(0).passengersAlighting, MatsimTestUtils.EPSILON); - Assertions.assertEquals(0.0, bus1_dep1_stop3.get(0).passengersBoarding, MatsimTestUtils.EPSILON); - - List bus1_dep1_stop4 = ptStop2StopAnalysis.getStop2StopEntriesByDeparture().stream().filter(entry -> entry.transitLineId.equals(transitLineId_bus1) && entry.transitRouteId.equals(transitRouteId_bus1_route2) && entry.departureId.equals(departureId_bus1_dep1) && entry.stopId.equals(transitStopFacilityId2) && entry.stopSequence == 1).collect(Collectors.toList()); + Assertions.assertEquals(0.0, bus1_dep1_stop3.get(0).arrivalDelay(), MatsimTestUtils.EPSILON, "Wrong arrivalDelay"); + Assertions.assertEquals(15.0, bus1_dep1_stop3.get(0).departureTimeScheduled(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(0.0, bus1_dep1_stop3.get(0).departureDelay(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(3.0, bus1_dep1_stop3.get(0).passengersAtArrival(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(veh_bus1_dep1.getType().getCapacity().getSeats() + veh_bus1_dep1.getType().getCapacity().getStandingRoom(), bus1_dep1_stop1.get(0).totalVehicleCapacity(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(3.0, bus1_dep1_stop3.get(0).passengersAlighting(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(0.0, bus1_dep1_stop3.get(0).passengersBoarding(), MatsimTestUtils.EPSILON); + + List bus1_dep1_stop4 = ptStop2StopAnalysis.getStop2StopEntriesByDeparture().stream().filter(entry -> entry.transitLineId().equals(transitLineId_bus1) && entry.transitRouteId().equals(transitRouteId_bus1_route2) && entry.departureId().equals(departureId_bus1_dep1) && entry.stopId().equals(transitStopFacilityId2) && entry.stopSequence() == 1).toList(); Assertions.assertEquals(1, bus1_dep1_stop4.size(), "Either no entry or more than entry for " + transitLineId_bus1 + ", " + transitRouteId_bus1_route2 + ", " + departureId_bus1_dep1 + ", " + departureId_bus1_dep1 + ", " + transitStopFacilityId2 + ", 0"); - Assertions.assertEquals(28.0, bus1_dep1_stop4.get(0).arrivalTimeScheduled, MatsimTestUtils.EPSILON, "Wrong arrivalTimeScheduled"); - Assertions.assertEquals(0.0, bus1_dep1_stop4.get(0).arrivalDelay, MatsimTestUtils.EPSILON, "Wrong arrivalDelay"); - Assertions.assertEquals(29.0, bus1_dep1_stop4.get(0).departureTimeScheduled, MatsimTestUtils.EPSILON); - Assertions.assertEquals(0.0, bus1_dep1_stop4.get(0).departureDelay, MatsimTestUtils.EPSILON); - Assertions.assertEquals(5.0, bus1_dep1_stop4.get(0).passengersAtArrival, MatsimTestUtils.EPSILON); - Assertions.assertEquals(veh_bus1_dep1.getType().getCapacity().getSeats() + veh_bus1_dep1.getType().getCapacity().getStandingRoom(), bus1_dep1_stop1.get(0).totalVehicleCapacity, MatsimTestUtils.EPSILON); - Assertions.assertEquals(2.0, bus1_dep1_stop4.get(0).passengersAlighting, MatsimTestUtils.EPSILON); - Assertions.assertEquals(2.0, bus1_dep1_stop4.get(0).passengersBoarding, MatsimTestUtils.EPSILON); - - List train1_dep1_stop4 = ptStop2StopAnalysis.getStop2StopEntriesByDeparture().stream().filter(entry -> entry.transitLineId.equals(transitLineId_train1) && entry.transitRouteId.equals(transitRouteId_train1_route1) && entry.departureId.equals(departureId_train1_dep1) && entry.stopId.equals(transitStopFacilityId6) && entry.stopSequence == 3).collect(Collectors.toList()); + Assertions.assertEquals(28.0, bus1_dep1_stop4.get(0).arrivalTimeScheduled(), MatsimTestUtils.EPSILON, "Wrong arrivalTimeScheduled"); + Assertions.assertEquals(0.0, bus1_dep1_stop4.get(0).arrivalDelay(), MatsimTestUtils.EPSILON, "Wrong arrivalDelay"); + Assertions.assertEquals(29.0, bus1_dep1_stop4.get(0).departureTimeScheduled(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(0.0, bus1_dep1_stop4.get(0).departureDelay(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(5.0, bus1_dep1_stop4.get(0).passengersAtArrival(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(veh_bus1_dep1.getType().getCapacity().getSeats() + veh_bus1_dep1.getType().getCapacity().getStandingRoom(), bus1_dep1_stop1.get(0).totalVehicleCapacity(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(2.0, bus1_dep1_stop4.get(0).passengersAlighting(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(2.0, bus1_dep1_stop4.get(0).passengersBoarding(), MatsimTestUtils.EPSILON); + + List train1_dep1_stop4 = ptStop2StopAnalysis.getStop2StopEntriesByDeparture().stream().filter(entry -> entry.transitLineId().equals(transitLineId_train1) && entry.transitRouteId().equals(transitRouteId_train1_route1) && entry.departureId().equals(departureId_train1_dep1) && entry.stopId().equals(transitStopFacilityId6) && entry.stopSequence() == 3).toList(); Assertions.assertEquals(1, train1_dep1_stop4.size(), "Either no entry or more than entry for " + transitLineId_train1 + ", " + transitRouteId_train1_route1 + ", " + departureId_train1_dep1 + ", " + transitStopFacilityId6 + ", 0"); - Assertions.assertEquals(19.0, train1_dep1_stop4.get(0).arrivalTimeScheduled, MatsimTestUtils.EPSILON, "Wrong arrivalTimeScheduled"); - Assertions.assertEquals(0.0, train1_dep1_stop4.get(0).arrivalDelay, MatsimTestUtils.EPSILON, "Wrong arrivalDelay"); - Assertions.assertEquals(21.0, train1_dep1_stop4.get(0).departureTimeScheduled, MatsimTestUtils.EPSILON); - Assertions.assertEquals(0.0, train1_dep1_stop4.get(0).departureDelay, MatsimTestUtils.EPSILON); - Assertions.assertEquals(6.0, train1_dep1_stop4.get(0).passengersAtArrival, MatsimTestUtils.EPSILON); - Assertions.assertEquals(veh_bus1_dep1.getType().getCapacity().getSeats() + veh_bus1_dep1.getType().getCapacity().getStandingRoom(), bus1_dep1_stop1.get(0).totalVehicleCapacity, MatsimTestUtils.EPSILON); - Assertions.assertEquals(4.0, train1_dep1_stop4.get(0).passengersAlighting, MatsimTestUtils.EPSILON); - Assertions.assertEquals(1.0, train1_dep1_stop4.get(0).passengersBoarding, MatsimTestUtils.EPSILON); + Assertions.assertEquals(19.0, train1_dep1_stop4.get(0).arrivalTimeScheduled(), MatsimTestUtils.EPSILON, "Wrong arrivalTimeScheduled"); + Assertions.assertEquals(0.0, train1_dep1_stop4.get(0).arrivalDelay(), MatsimTestUtils.EPSILON, "Wrong arrivalDelay"); + Assertions.assertEquals(21.0, train1_dep1_stop4.get(0).departureTimeScheduled(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(0.0, train1_dep1_stop4.get(0).departureDelay(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(6.0, train1_dep1_stop4.get(0).passengersAtArrival(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(veh_bus1_dep1.getType().getCapacity().getSeats() + veh_bus1_dep1.getType().getCapacity().getStandingRoom(), bus1_dep1_stop1.get(0).totalVehicleCapacity(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(4.0, train1_dep1_stop4.get(0).passengersAlighting(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(1.0, train1_dep1_stop4.get(0).passengersBoarding(), MatsimTestUtils.EPSILON); } -} \ No newline at end of file +} diff --git a/matsim/src/test/java/org/matsim/core/controler/OutputDirectoryHierarchyTest.java b/matsim/src/test/java/org/matsim/core/controler/OutputDirectoryHierarchyTest.java index 5fa3ccb628a..8a1f9c7ce16 100644 --- a/matsim/src/test/java/org/matsim/core/controler/OutputDirectoryHierarchyTest.java +++ b/matsim/src/test/java/org/matsim/core/controler/OutputDirectoryHierarchyTest.java @@ -21,14 +21,26 @@ 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.api.core.v01.population.Activity; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.ControllerConfigGroup; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; +import static org.junit.jupiter.api.Assertions.assertTrue; + import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; +import java.net.URL; +import java.util.Set; +import java.util.stream.Collectors; /** * @author thibautd @@ -146,4 +158,29 @@ void testDeleteIfDirectoryExists() { "Directory was not cleared" ); } + + @Test + void testTmpDir() { + + String javaTempDir = System.getProperty("java.io.tmpdir"); + System.setProperty(OutputDirectoryHierarchy.MATSIM_TEMP_DIR_PROPERTY, javaTempDir); + Assertions.assertNotNull(javaTempDir); + + System.setProperty("matsim.preferLocalDtds", "true"); + + URL scenarioURL = ExamplesUtils.getTestScenarioURL("siouxfalls-2014"); + + Config config = ConfigUtils.loadConfig(IOUtils.extendUrl(scenarioURL, "config_default.xml")); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setLastIteration(1); + + Scenario scenario = ScenarioUtils.loadScenario(config); + + Controler controller = new Controler(scenario); + controller.run(); + + String matsimTempDir = controller.getControlerIO().getTempPath(); + Assertions.assertEquals(javaTempDir, matsimTempDir); + } + } diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueWithBufferTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueWithBufferTest.java new file mode 100644 index 00000000000..244f51b1246 --- /dev/null +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueWithBufferTest.java @@ -0,0 +1,199 @@ +package org.matsim.core.mobsim.qsim.qnetsimengine; + +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.Id; +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.QSimConfigGroup; +import org.matsim.core.mobsim.framework.MobsimDriverAgent; +import org.matsim.core.mobsim.framework.MobsimTimer; +import org.matsim.core.mobsim.qsim.interfaces.AgentCounter; +import org.matsim.core.network.NetworkUtils; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; +import org.matsim.vis.snapshotwriters.SnapshotLinkWidthCalculator; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; + +/** + * This suite of unit tests is not exhaustive! I wrote these tests, because I wanted to understand what is happening when the QueueWithBuffer is operated + * with config::qsim.trafficDynamics = 'kinematicWaves'. + */ +class QueueWithBufferTest { + + @Test + void initLinkQueue() { + + var config = ConfigUtils.createConfig(); + var context = createNetsimeEngineContext(config, new MobsimTimer()); + var link = createQLink(10, 2, 5400, context, config); + + assertEquals(1, link.getOfferingQLanes().size()); + assertEquals(link.getAcceptingQLane(), link.getOfferingQLanes().getFirst()); + QueueWithBuffer qwb = (QueueWithBuffer) link.getAcceptingQLane(); + assertEquals(1.5, qwb.getSimulatedFlowCapacityPerTimeStep()); + assertEquals(2 * 2, qwb.getStorageCapacity()); + } + + @Test + void initLinkKinematicWaves() { + + var config = ConfigUtils.createConfig(); + config.qsim().setTrafficDynamics(QSimConfigGroup.TrafficDynamics.kinematicWaves); + var context = createNetsimeEngineContext(config, new MobsimTimer()); + var link = createQLink(10, 2, 5400, context, config); + + assertEquals(1, link.getOfferingQLanes().size()); + assertEquals(link.getAcceptingQLane(), link.getOfferingQLanes().getFirst()); + QueueWithBuffer qwb = (QueueWithBuffer) link.getAcceptingQLane(); + assertEquals(1.5, qwb.getSimulatedFlowCapacityPerTimeStep()); + + var vHole = 15 / 3.6; + // according to https://doi.org/10.1080/23249935.2017.1364802 equation 7 + var expectedStorageCap = link.getSimulatedFlowCapacityPerTimeStep() * link.getLink().getLength() * ( 1 / link.getLink().getFreespeed() + 1 / vHole); + assertEquals(expectedStorageCap, qwb.getStorageCapacity(), 0.001); + } + + @Test + void freeStorageQueue() { + var config = ConfigUtils.createConfig(); + var timer = new MobsimTimer(); + var context = createNetsimeEngineContext(config, timer); + var link = createQLink(10, 1, 1800, context, config); + var driver = mock(MobsimDriverAgent.class); + var vehicle1 = createVehicle("vehicle-1", driver, 10,1); + var vehicle2 = createVehicle("vehicle-2", driver, 10,1); + + // the link should accept vehicles until the storage capacity is exhausted + assertTrue(link.getAcceptingQLane().isAcceptingFromUpstream()); + link.getAcceptingQLane().addFromUpstream(vehicle1); + assertTrue(link.getAcceptingQLane().isAcceptingFromUpstream()); + link.getAcceptingQLane().addFromUpstream(vehicle2); + assertFalse(link.getAcceptingQLane().isAcceptingFromUpstream()); + + // this should move one vehicle into the buffer, and free one pcu in the queue immediately + timer.setTime(1); + link.doSimStep(); + + // test that capacity is available at the upstream end of the queue + assertTrue(link.getAcceptingQLane().isAcceptingFromUpstream()); + + // test that only one vehicle was moved into the buffer. Remove the first vehicle, and then the link should not offer more vehicles + assertEquals(vehicle1.getId(), link.getOfferingQLanes().getFirst().popFirstVehicle().getId()); + // this double negation is so terrible! + assertTrue(link.getOfferingQLanes().getFirst().isNotOfferingVehicle()); + } + + @Test + void freeStorageKinematicWaves() { + var config = ConfigUtils.createConfig(); + config.qsim().setTrafficDynamics(QSimConfigGroup.TrafficDynamics.kinematicWaves); + var timer = new MobsimTimer(); + var context = createNetsimeEngineContext(config, timer); + var link = createQLink(15, 1, 1800, context, config); + var driver = mock(MobsimDriverAgent.class); + var vehicle1 = createVehicle("vehicle-1", driver, 10,2); + var vehicle2 = createVehicle("vehicle-2", driver, 1, 1); + link.doSimStep(); + + // the link should accept vehicles according to its max inflow capacity + // vehicle consumes 2pcu. Max inflow should be: 1/cellSize / (1/vHole + 1/vMax) = 0.588... + // the queue with buffer seems to increase the accumulated inflow per 'doSimStep' regardless of the time between invocations. This works, because + // in the simulation 'doSimStep' is invoked every timestep. We need 3 'doSimStep's to increase the accumulated inflow to a value over 1. + assertTrue(link.getAcceptingQLane().isAcceptingFromUpstream()); + link.getAcceptingQLane().addFromUpstream(vehicle1); + // acc inflow is -1.422 + assertFalse(link.getAcceptingQLane().isAcceptingFromUpstream()); + link.doSimStep(); + // acc inflow is -0.842 + assertFalse(link.getAcceptingQLane().isAcceptingFromUpstream()); + link.doSimStep(); + // acc inflow is -0.236 + assertFalse(link.getAcceptingQLane().isAcceptingFromUpstream()); + link.doSimStep(); + // acc inflow is +0.352 > 0 + assertTrue(link.getAcceptingQLane().isAcceptingFromUpstream()); + link.getAcceptingQLane().addFromUpstream(vehicle2); + assertFalse(link.getAcceptingQLane().isAcceptingFromUpstream()); + + // this should move one vehicle into the buffer, and start a backwards travelling hole + timer.setTime(1); + link.doSimStep(); + + // now, one vehicle should be in the buffer and one vehicle should be in the queue. + // The link has free storage capacity, but it is not freed yet, because the leaving vehicle has sent a backwards travelling hole on its way. + // the earliest exit time of that hole should be: now + length / vHole -> 1 + 15 * 3.6 / 15km/h = 4.6s + assertFalse(link.getAcceptingQLane().isAcceptingFromUpstream()); + // remove the first vehicle from the buffer and asser that it was the only vehicle in the buffer + assertEquals(vehicle1.getId(), link.getOfferingQLanes().getFirst().popFirstVehicle().getId()); + assertTrue(link.getOfferingQLanes().getFirst().isNotOfferingVehicle()); + + // pretend we are doing 5 sim steps. I think we need to do this, as the inflow capacity accumulates per 'doSimStep' and does not keep track + // of the last update time. + timer.setTime(2); + link.doSimStep(); + assertFalse(link.getAcceptingQLane().isAcceptingFromUpstream()); + assertTrue(link.getOfferingQLanes().getFirst().isNotOfferingVehicle()); + timer.setTime(3); + link.doSimStep(); + assertFalse(link.getAcceptingQLane().isAcceptingFromUpstream()); + assertTrue(link.getOfferingQLanes().getFirst().isNotOfferingVehicle()); + timer.setTime(4); + link.doSimStep(); + assertFalse(link.getAcceptingQLane().isAcceptingFromUpstream()); + assertTrue(link.getOfferingQLanes().getFirst().isNotOfferingVehicle()); + timer.setTime(5); // 5 > 4.6: 4.6 is the arrival time of the backwards travelling hole. + link.doSimStep(); + assertTrue(link.getAcceptingQLane().isAcceptingFromUpstream()); + assertTrue(link.getOfferingQLanes().getFirst().isNotOfferingVehicle()); + } + + private static NetsimEngineContext createNetsimeEngineContext(Config config, MobsimTimer timer) { + return new NetsimEngineContext( + mock(EventsManager.class), + 5, + mock(AgentCounter.class), + mock(AbstractAgentSnapshotInfoBuilder.class), + config.qsim(), + timer, + mock(SnapshotLinkWidthCalculator.class) + ); + } + + QLinkImpl createQLink(double length, double lanes, double cap, NetsimEngineContext context, Config config) { + var net = NetworkUtils.createNetwork(); + var n1 = net.getFactory().createNode(Id.createNodeId("n1"), new Coord(0, 0)); + var n2 = net.getFactory().createNode(Id.createNodeId("n2"), new Coord(0, 100)); + net.addNode(n1); + net.addNode(n2); + var link = net.getFactory().createLink(Id.createLinkId("test"), n1, n2); + link.setCapacity(cap); + link.setFreespeed(10); + link.setLength(length); + link.setNumberOfLanes(lanes); + + var internalInterface = mock(QNetsimEngineI.NetsimInternalInterface.class); + QNodeImpl qNode = new QNodeImpl.Builder(internalInterface, context, config.qsim()).build(n2); + qNode.setNetElementActivationRegistry(mock(NetElementActivationRegistry.class)); + var b = new QLinkImpl.Builder(context, internalInterface); + b.setLinkSpeedCalculator(new DefaultLinkSpeedCalculator()); + var l = b.build(link, qNode); + l.setNetElementActivationRegistry(mock(NetElementActivationRegistry.class)); + return l; + } + + QVehicle createVehicle(String id, MobsimDriverAgent driver, double maxV, double pcu) { + + var type = VehicleUtils.createVehicleType(Id.create("type", VehicleType.class)); + type.setMaximumVelocity(10); + type.setPcuEquivalents(pcu); + type.setMaximumVelocity(maxV); + var vehicle = VehicleUtils.createVehicle(Id.createVehicleId(id), type); + var result = new QVehicleImpl(vehicle); + result.setDriver(driver); + return result; + } + } diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SpeedCalculatorTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SpeedCalculatorTest.java index ed394e4bd46..a697a42a9a7 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SpeedCalculatorTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SpeedCalculatorTest.java @@ -40,7 +40,7 @@ public class SpeedCalculatorTest{ @Test void limitedByVehicleSpeed() { Link link = createLinkWithNoGradientAndNoSpecialSurface(); - VehicleType type = VehicleUtils.createVehicleType(Id.create("no-bike", VehicleType.class ) ); + VehicleType type = VehicleUtils.createVehicleType(Id.create("no-bike", VehicleType.class ), TransportMode.car ); type.setMaximumVelocity(link.getFreespeed() / 2); // less than the link's freespeed QVehicle vehicle = new QVehicleImpl(VehicleUtils.createVehicle(Id.createVehicleId(1), type)); @@ -55,7 +55,7 @@ void limitedByLinkSpeed() { Link link = createLinkWithNoGradientAndNoSpecialSurface(); - VehicleType type = VehicleUtils.createVehicleType(Id.create("no-bike", VehicleType.class ) ); + VehicleType type = VehicleUtils.createVehicleType(Id.create("no-bike", VehicleType.class ), TransportMode.car ); type.setMaximumVelocity(link.getFreespeed() * 2); // _more_ than the link's freespeed QVehicle vehicle = new QVehicleImpl(VehicleUtils.createVehicle(Id.createVehicleId(1), type)); diff --git a/matsim/src/test/java/org/matsim/core/router/AbstractLeastCostPathCalculatorTestWithTurnRestrictions.java b/matsim/src/test/java/org/matsim/core/router/AbstractLeastCostPathCalculatorTestWithTurnRestrictions.java index 11e4ddfc1ce..3d96cd73091 100644 --- a/matsim/src/test/java/org/matsim/core/router/AbstractLeastCostPathCalculatorTestWithTurnRestrictions.java +++ b/matsim/src/test/java/org/matsim/core/router/AbstractLeastCostPathCalculatorTestWithTurnRestrictions.java @@ -1,12 +1,6 @@ package org.matsim.core.router; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.IOException; -import java.util.Arrays; - -import javax.xml.parsers.ParserConfigurationException; - +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; @@ -17,23 +11,27 @@ import org.matsim.api.core.v01.network.Node; import org.matsim.core.config.Config; import org.matsim.core.network.NetworkUtils; -import org.matsim.core.network.io.MatsimNetworkReader; import org.matsim.core.router.util.LeastCostPathCalculator; import org.matsim.core.router.util.LeastCostPathCalculator.Path; import org.matsim.core.scenario.ScenarioUtils; -import org.matsim.testcases.MatsimTestUtils; import org.xml.sax.SAXException; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.assertEquals; + public abstract class AbstractLeastCostPathCalculatorTestWithTurnRestrictions extends AbstractLeastCostPathCalculatorTest { @Test void testCalcLeastCostPath_TurnRestrictions() throws SAXException, ParserConfigurationException, IOException { Network network = createTurnRestrictionsTestNetwork(); - + Node nodeS = network.getNodes().get(Id.create("S", Node.class)); Node nodeT = network.getNodes().get(Id.create("T", Node.class)); LeastCostPathCalculator routerAlgo = getLeastCostPathCalculator(network); - Path path = routerAlgo.calcLeastCostPath(nodeS, nodeT, 8.0*3600, null, null); + Path path = routerAlgo.calcLeastCostPath(nodeS, nodeT, 8.0 * 3600, null, null); assertEquals(7, path.nodes.size(), "number of nodes wrong."); assertEquals(6, path.links.size(), "number of links wrong."); @@ -45,7 +43,7 @@ void testCalcLeastCostPath_TurnRestrictions() throws SAXException, ParserConfigu assertEquals(network.getNodes().get(Id.create("4", Node.class)), path.nodes.get(4)); assertEquals(network.getNodes().get(Id.create("5", Node.class)), path.nodes.get(5)); assertEquals(network.getNodes().get(Id.create("T", Node.class)), path.nodes.get(6)); - + assertEquals(network.getLinks().get(Id.create("S1", Link.class)), path.links.get(0)); assertEquals(network.getLinks().get(Id.create("12", Link.class)), path.links.get(1)); assertEquals(network.getLinks().get(Id.create("23", Link.class)), path.links.get(2)); @@ -54,9 +52,46 @@ void testCalcLeastCostPath_TurnRestrictions() throws SAXException, ParserConfigu assertEquals(network.getLinks().get(Id.create("5T", Link.class)), path.links.get(5)); } + @Test + void testCalcLeastCostPath_TurnRestrictions_IntermediateNode() { + Network network = createTurnRestrictionsTestNetwork(); + + Node nodeS = network.getNodes().get(Id.create("S", Node.class)); + Node node3 = network.getNodes().get(Id.create("3", Node.class)); + + LeastCostPathCalculator routerAlgo = getLeastCostPathCalculator(network); + Path path = routerAlgo.calcLeastCostPath(nodeS, node3, 8.0 * 3600, null, null); + Assertions.assertNotNull(path); + } + + @Test + void testCalcLeastCostPath_TurnRestrictions_simple() { + Network network = createTurnRestrictionsTestNetwork(); + + Node nodeS = network.getNodes().get(Id.create("S", Node.class)); + Node node1 = network.getNodes().get(Id.create("1", Node.class)); + + LeastCostPathCalculator routerAlgo = getLeastCostPathCalculator(network); + Path path = routerAlgo.calcLeastCostPath(nodeS, node1, 8.0 * 3600, null, null); + Assertions.assertNotNull(path); + } + + @Test + void testCalcLeastCostPath_noTurnRestrictions_simple() { + Network network = createTurnRestrictionsTestNetwork(); + + Node nodeS = network.getNodes().get(Id.create("5", Node.class)); + Node node1 = network.getNodes().get(Id.create("T", Node.class)); + + LeastCostPathCalculator routerAlgo = getLeastCostPathCalculator(network); + Path path = routerAlgo.calcLeastCostPath(nodeS, node1, 8.0 * 3600, null, null); + Assertions.assertNotNull(path); + } + + //@formatter:off /** * Creates a test network where the shortest path is impossible due to turn restrictions - * + * * S * | * \/ @@ -64,36 +99,37 @@ void testCalcLeastCostPath_TurnRestrictions() throws SAXException, ParserConfigu * | / /\ * \/ / | * 3--->4--->5 - * + * * Where S1 -> 1T and 23 -> 34 -> 4T are forbidden. - * + * * @return */ - private Network createTurnRestrictionsTestNetwork() { - Config config = utils.loadConfig((String)null); + //@formatter:on + private Network createTurnRestrictionsTestNetwork() { + Config config = utils.loadConfig((String) null); Scenario scenario = ScenarioUtils.createScenario(config); - final Network network = scenario.getNetwork(); - - final Node nodeS = NetworkUtils.createAndAddNode(network, Id.createNodeId("S"), new Coord(1,2)); - final Node node1 = NetworkUtils.createAndAddNode(network, Id.createNodeId("1"), new Coord(1,1)); - final Node node2 = NetworkUtils.createAndAddNode(network, Id.createNodeId("2"), new Coord(0,1)); - final Node node3 = NetworkUtils.createAndAddNode(network, Id.createNodeId("3"), new Coord(0,0)); - final Node node4 = NetworkUtils.createAndAddNode(network, Id.createNodeId("4"), new Coord(1,0)); - final Node node5 = NetworkUtils.createAndAddNode(network, Id.createNodeId("5"), new Coord(2,0)); - final Node nodeT = NetworkUtils.createAndAddNode(network, Id.createNodeId("T"), new Coord(2,0)); - - final Link linkS1 = NetworkUtils.createAndAddLink(network, Id.createLinkId("S1"), nodeS, node1, 1, 1,1, 1); - NetworkUtils.createAndAddLink(network, Id.createLinkId("12"), node1, node2, 1, 1,1, 1); - NetworkUtils.createAndAddLink(network, Id.createLinkId("1T"), node1, nodeT, 1, 1,1, 1); - final Link link23 = NetworkUtils.createAndAddLink(network, Id.createLinkId("23"), node2, node3, 1, 1,1, 1); - NetworkUtils.createAndAddLink(network, Id.createLinkId("34"), node3, node4, 1, 1,1, 1); - NetworkUtils.createAndAddLink(network, Id.createLinkId("4T"), node4, nodeT, 1, 1,1, 1); - NetworkUtils.createAndAddLink(network, Id.createLinkId("45"), node4, node5, 1, 1,1, 1); - NetworkUtils.createAndAddLink(network, Id.createLinkId("5T"), node5, nodeT, 1, 1,1, 1); - - NetworkUtils.addDisallowedNextLinks(linkS1, TransportMode.car, Arrays.asList(Id.createLinkId("1T"))); - NetworkUtils.addDisallowedNextLinks(link23, TransportMode.car, Arrays.asList(Id.createLinkId("34"), Id.createLinkId("4T"))); - - return network; - } + final Network network = scenario.getNetwork(); + + final Node nodeS = NetworkUtils.createAndAddNode(network, Id.createNodeId("S"), new Coord(1, 2)); + final Node node1 = NetworkUtils.createAndAddNode(network, Id.createNodeId("1"), new Coord(1, 1)); + final Node node2 = NetworkUtils.createAndAddNode(network, Id.createNodeId("2"), new Coord(0, 1)); + final Node node3 = NetworkUtils.createAndAddNode(network, Id.createNodeId("3"), new Coord(0, 0)); + final Node node4 = NetworkUtils.createAndAddNode(network, Id.createNodeId("4"), new Coord(1, 0)); + final Node node5 = NetworkUtils.createAndAddNode(network, Id.createNodeId("5"), new Coord(2, 0)); + final Node nodeT = NetworkUtils.createAndAddNode(network, Id.createNodeId("T"), new Coord(2, 0)); + + final Link linkS1 = NetworkUtils.createAndAddLink(network, Id.createLinkId("S1"), nodeS, node1, 1, 1, 1, 1); + NetworkUtils.createAndAddLink(network, Id.createLinkId("12"), node1, node2, 1, 1, 1, 1); + NetworkUtils.createAndAddLink(network, Id.createLinkId("1T"), node1, nodeT, 1, 1, 1, 1); + final Link link23 = NetworkUtils.createAndAddLink(network, Id.createLinkId("23"), node2, node3, 1, 1, 1, 1); + NetworkUtils.createAndAddLink(network, Id.createLinkId("34"), node3, node4, 1, 1, 1, 1); + NetworkUtils.createAndAddLink(network, Id.createLinkId("4T"), node4, nodeT, 1, 1, 1, 1); + NetworkUtils.createAndAddLink(network, Id.createLinkId("45"), node4, node5, 1, 1, 1, 1); + NetworkUtils.createAndAddLink(network, Id.createLinkId("5T"), node5, nodeT, 1, 1, 1, 1); + + NetworkUtils.addDisallowedNextLinks(linkS1, TransportMode.car, Arrays.asList(Id.createLinkId("1T"))); + NetworkUtils.addDisallowedNextLinks(link23, TransportMode.car, Arrays.asList(Id.createLinkId("34"), Id.createLinkId("4T"))); + + return network; + } } diff --git a/matsim/src/test/java/org/matsim/core/router/MultimodalLinkChooserTest.java b/matsim/src/test/java/org/matsim/core/router/MultimodalLinkChooserDefaultImplTest.java similarity index 92% rename from matsim/src/test/java/org/matsim/core/router/MultimodalLinkChooserTest.java rename to matsim/src/test/java/org/matsim/core/router/MultimodalLinkChooserDefaultImplTest.java index 78a0dba6426..cb93b4aff0b 100644 --- a/matsim/src/test/java/org/matsim/core/router/MultimodalLinkChooserTest.java +++ b/matsim/src/test/java/org/matsim/core/router/MultimodalLinkChooserDefaultImplTest.java @@ -41,7 +41,7 @@ * */ -public class MultimodalLinkChooserTest { +public class MultimodalLinkChooserDefaultImplTest { @Test void testDecideOnLink() { @@ -75,11 +75,13 @@ void testDecideOnLink() { MultimodalLinkChooser linkChooser = new MultimodalLinkChooserDefaultImpl(); - Link linkFromFacLinkId = linkChooser.decideOnLink(facilityLinkIdNotNull, network); + RoutingRequest request = DefaultRoutingRequest.of(facilityLinkIdNotNull, facilityLinkIdNull, 0, null, null); + + Link linkFromFacLinkId = linkChooser.decideAccessLink(request, network); Assertions.assertEquals(networkLink, linkFromFacLinkId); - Link linkFromFacCoord = linkChooser.decideOnLink(facilityLinkIdNull, network); + Link linkFromFacCoord = linkChooser.decideEgressLink(request, network); Assertions.assertEquals(networkLink, linkFromFacCoord); 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 6781d0872d2..0b4cc89e381 100644 --- a/matsim/src/test/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModuleTest.java +++ b/matsim/src/test/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModuleTest.java @@ -189,6 +189,7 @@ void calcRoute_modeVehiclesFromVehiclesData_differentTypesTakeDifferentRoutes() config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.modeVehicleTypesFromVehiclesData); config.qsim().setMainModes(modes); config.routing().setNetworkModes(modes); + config.travelTimeCalculator().setAnalyzedModes(new HashSet<>(modes)); ScoringConfigGroup scoring = config.scoring(); ScoringConfigGroup.ModeParams slowParams = new ScoringConfigGroup.ModeParams(SLOW_MODE); diff --git a/matsim/src/test/java/org/matsim/core/trafficmonitoring/TravelTimeCalculatorModuleTest.java b/matsim/src/test/java/org/matsim/core/trafficmonitoring/TravelTimeCalculatorModuleTest.java index ae05592d528..356fc5c1cff 100644 --- a/matsim/src/test/java/org/matsim/core/trafficmonitoring/TravelTimeCalculatorModuleTest.java +++ b/matsim/src/test/java/org/matsim/core/trafficmonitoring/TravelTimeCalculatorModuleTest.java @@ -97,9 +97,10 @@ public void install() { void testOneTravelTimeCalculatorPerMode() { Config config = ConfigUtils.createConfig(); -// config.travelTimeCalculator().setAnalyzedModesAsString("car,bike" ); + config.travelTimeCalculator().setAnalyzedModesAsString("car,bike"); config.routing().setNetworkModes( new LinkedHashSet<>( Arrays.asList( TransportMode.car, TransportMode.bike ) ) ); // (this is now newly taken from the router network modes. kai, feb'19) + // analyzed modes still need to be set correctly now, because these two settings can differ rakow, oct'24 config.travelTimeCalculator().setSeparateModes(true); Scenario scenario = ScenarioUtils.createScenario(config); diff --git a/matsim/src/test/java/org/matsim/examples/simple/PtScoringTest.java b/matsim/src/test/java/org/matsim/examples/simple/PtScoringTest.java index 8954e969fe7..9169ff96e92 100644 --- a/matsim/src/test/java/org/matsim/examples/simple/PtScoringTest.java +++ b/matsim/src/test/java/org/matsim/examples/simple/PtScoringTest.java @@ -54,7 +54,7 @@ public class PtScoringTest { @ParameterizedTest @EnumSource(TypicalDurationScoreComputation.class) void test_PtScoringLineswitch(TypicalDurationScoreComputation typicalDurationScoreComputation) { - Config config = this.utils.loadConfig(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("pt-simple-lineswitch"), "config.xml")); + Config config = this.utils.loadConfig(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("pt-simple-lineswitch"), "config.xml"), MatsimTestUtils.TestMethodType.Parameterized); ScoringConfigGroup pcs = config.scoring() ; if(typicalDurationScoreComputation.equals(TypicalDurationScoreComputation.uniform)){ @@ -208,7 +208,7 @@ void test_PtScoringLineswitch(TypicalDurationScoreComputation typicalDurationSco @ParameterizedTest @EnumSource(TypicalDurationScoreComputation.class) void test_PtScoringLineswitchAndPtConstant(TypicalDurationScoreComputation typicalDurationScoreComputation) { - Config config = this.utils.loadConfig(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("pt-simple-lineswitch"), "config.xml")); + Config config = this.utils.loadConfig(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("pt-simple-lineswitch"), "config.xml"), MatsimTestUtils.TestMethodType.Parameterized); ScoringConfigGroup pcs = config.scoring() ; if(typicalDurationScoreComputation.equals(TypicalDurationScoreComputation.uniform)) @@ -365,7 +365,7 @@ void test_PtScoringLineswitchAndPtConstant(TypicalDurationScoreComputation typic @ParameterizedTest @EnumSource(TypicalDurationScoreComputation.class) void test_PtScoring_Wait(TypicalDurationScoreComputation typicalDurationScoreComputation) { - Config config = this.utils.loadConfig(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("pt-simple"), "config.xml")); + Config config = this.utils.loadConfig(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("pt-simple"), "config.xml"), MatsimTestUtils.TestMethodType.Parameterized); ScoringConfigGroup pcs = config.scoring(); if(typicalDurationScoreComputation.equals(TypicalDurationScoreComputation.uniform)){ @@ -452,7 +452,7 @@ void test_PtScoring_Wait(TypicalDurationScoreComputation typicalDurationScoreCom @ParameterizedTest @EnumSource(TypicalDurationScoreComputation.class) void test_PtScoring(TypicalDurationScoreComputation typicalDurationScoreComputation) { - Config config = this.utils.loadConfig(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("pt-simple"), "config.xml")); + Config config = this.utils.loadConfig(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("pt-simple"), "config.xml"), MatsimTestUtils.TestMethodType.Parameterized); ScoringConfigGroup pcs = config.scoring() ; if(typicalDurationScoreComputation.equals(TypicalDurationScoreComputation.uniform)) diff --git a/pom.xml b/pom.xml index d009fff6ca8..f811ec6d8e5 100644 --- a/pom.xml +++ b/pom.xml @@ -205,7 +205,7 @@ com.google.errorprone error_prone_annotations - 2.31.0 + 2.33.0