From 92954b51dc01572879fdba2cb55186ac538d4a2f Mon Sep 17 00:00:00 2001 From: tschlenther Date: Tue, 10 Oct 2023 16:20:32 +0200 Subject: [PATCH 001/111] copy analysis code from matsim-kelheim to application contrib --- .../population/ActivityLengthAnalysis.java | 82 +++++++++++ .../population/DepartureTimeAnalysis.java | 133 ++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 contribs/application/src/main/java/org/matsim/application/analysis/population/ActivityLengthAnalysis.java create mode 100644 contribs/application/src/main/java/org/matsim/application/analysis/population/DepartureTimeAnalysis.java diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/population/ActivityLengthAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/population/ActivityLengthAnalysis.java new file mode 100644 index 00000000000..2e7418462fe --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/analysis/population/ActivityLengthAnalysis.java @@ -0,0 +1,82 @@ +package org.matsim.application.analysis.population; + +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.matsim.api.core.v01.population.Activity; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.PlanElement; +import org.matsim.api.core.v01.population.Population; +import org.matsim.application.MATSimAppCommand; +import org.matsim.core.population.PopulationUtils; +import picocli.CommandLine; + +import java.io.FileWriter; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +@CommandLine.Command( + name = "activity-length-analysis", + description = "Analyze the length of activity" +) +public class ActivityLengthAnalysis implements MATSimAppCommand { + @CommandLine.Option(names = "--population", description = "Path to input population", required = true) + private String populationPath; + + @CommandLine.Option(names = "--reference-population", description = "Path to reference population", defaultValue = "") + private String referencePopulationPath; + + @CommandLine.Option(names = "--output-folder", description = "Path to analysis output folder", required = true) + private Path outputFolder; + + public static void main(String[] args) { + new ActivityLengthAnalysis().execute(args); + } + + @Override + public Integer call() throws Exception { + List activityDurations = new ArrayList<>(); + List referenceActivityDurations = new ArrayList<>(); + + Population population = PopulationUtils.readPopulation(populationPath); + for (Person person : population.getPersons().values()) { + for (PlanElement planElement : person.getSelectedPlan().getPlanElements()) { + if (planElement instanceof Activity) { + double startTime = ((Activity) planElement).getStartTime().orElse(0); + double endTime = ((Activity) planElement).getEndTime().orElse(30 * 3600); + double duration = endTime - startTime; + activityDurations.add(duration); + } + } + } + + CSVPrinter csvWriter = new CSVPrinter(new FileWriter(outputFolder + "/activity-length.csv"), CSVFormat.TDF); + csvWriter.printRecord("activity_duration_in_seconds"); + for (double activityDuration : activityDurations) { + csvWriter.printRecord(Double.toString(activityDuration)); + } + csvWriter.close(); + + if (!referencePopulationPath.equals("")) { + Population referencePopulation = PopulationUtils.readPopulation(referencePopulationPath); + for (Person person : referencePopulation.getPersons().values()) { + for (PlanElement planElement : person.getSelectedPlan().getPlanElements()) { + if (planElement instanceof Activity) { + double startTime = ((Activity) planElement).getStartTime().orElse(0); + double endTime = ((Activity) planElement).getEndTime().orElse(30 * 3600); + double duration = endTime - startTime; + referenceActivityDurations.add(duration); + } + } + } + + CSVPrinter csvWriter2 = new CSVPrinter(new FileWriter(outputFolder + "/reference-activity-length.csv"), CSVFormat.TDF); + csvWriter2.printRecord("activity_duration_in_seconds"); + for (double activityDuration : referenceActivityDurations) { + csvWriter2.printRecord(Double.toString(activityDuration)); + } + csvWriter2.close(); + } + return 0; + } +} diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/population/DepartureTimeAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/population/DepartureTimeAnalysis.java new file mode 100644 index 00000000000..04e800872b9 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/analysis/population/DepartureTimeAnalysis.java @@ -0,0 +1,133 @@ +package org.matsim.application.analysis.population; + +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.lang3.mutable.MutableInt; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.Plan; +import org.matsim.api.core.v01.population.Population; +import org.matsim.application.MATSimAppCommand; +import org.matsim.core.population.PersonUtils; +import org.matsim.core.population.PopulationUtils; +import org.matsim.core.router.TripStructureUtils; +import picocli.CommandLine; + +import java.io.FileWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +@CommandLine.Command( + name = "analyze-departure-time", + description = "Analyze the departure time of the trips" +) +public class DepartureTimeAnalysis implements MATSimAppCommand { + + private static final Logger log = LogManager.getLogger(DepartureTimeAnalysis.class); + + @CommandLine.Option(names = "--plans", description = "Path to input population (plans) file", required = true) + private Path inputPlans; + + @CommandLine.Option(names = "--output-folder", description = "Path to analysis output folder", required = true) + private Path outputFolder; + + private static String[] ageGroups = new String[]{"0-17", "18-29", "30-49", "50-69", "70 or more"}; + + + public static void main(String[] args) { + new DepartureTimeAnalysis().execute(args); + } + + @Override + public Integer call() throws Exception { + Map> recordMap = initializeRecordMap(); + Population population = PopulationUtils.readPopulation(inputPlans.toString()); + + int processedPerson = 0; + int tripsDepartAfter24h = 0; + + for (Person person : population.getPersons().values()) { + //TODO potentially filter persons, e.g. by home location or by subpopulation + + processedPerson++; + int age = PersonUtils.getAge(person); + String ageGroup = determineAgeGroup(age); + Plan plan = person.getSelectedPlan(); + List trips = TripStructureUtils.getTrips(plan); + for (TripStructureUtils.Trip trip : trips) { + double departureTime = trip.getOriginActivity().getEndTime().seconds(); + // maybe the Math.floor operation is not needed? + int timeBin = (int) Math.floor(departureTime / 3600); + if (timeBin >= 24) { + tripsDepartAfter24h++; + continue; + } + // 1 time bin = 1 hour + recordMap.get(ageGroup).get(timeBin).increment(); + } + } + + // write results + if (!Files.exists(outputFolder)) { + Files.createDirectory(outputFolder); + } + CSVPrinter tsvWriter = new CSVPrinter(new FileWriter(outputFolder + "/departure_time_analysis.csv"), CSVFormat.TDF); + List titleRow = new ArrayList<>(); + titleRow.add("age_group"); + for (int i = 0; i < 24; i++) { + titleRow.add(Integer.toString(i)); + } + tsvWriter.printRecord(titleRow); + for (String ageGroup : ageGroups) { + List outputRow = new ArrayList<>(); + outputRow.add(ageGroup); + for (int i = 0; i < 24; i++) { + outputRow.add(Integer.toString(recordMap.get(ageGroup).get(i).intValue())); + } + tsvWriter.printRecord(outputRow); + } + tsvWriter.close(); + + log.info("Person processed (living within the area): {}", processedPerson); + log.info("Number of trips that depart after 24 hours is {}", tripsDepartAfter24h); + + return 0; + } + + private Map> initializeRecordMap() { + Map> recordMap = new HashMap<>(); + for (String ageGroup : ageGroups) { + recordMap.put(ageGroup, new HashMap<>()); + for (int i = 0; i < 24; i++) { + recordMap.get(ageGroup).put(i, new MutableInt(0)); + } + } + return recordMap; + } + + private String determineAgeGroup(int age) { + if (age <= 17) { + return ageGroups[0]; + } + + if (age <= 29) { + return ageGroups[1]; + } + + if (age <= 49) { + return ageGroups[2]; + } + + if (age <= 69) { + return ageGroups[3]; + } + + return ageGroups[4]; + } +} From de64f772c6c69f612f977e605c558928f71f639c Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Thu, 27 Jun 2024 19:39:25 +0200 Subject: [PATCH 002/111] * repair wrong positioning of vehicles if linkSpeedCalculator returns speed larger than free speed * replace some (but not all) link.getAttributes()... by BicycleUtils.set/getXyz( link, ...) * bind BicycleConfigGroup explicitly in BicycleModule so that not materializing it before does not lead to a non-interpretable error message (stating that Scenario is not bound about 20 times although that is not the root of the problem) * possibly one or the other additional things --- ...BicycleLinkSpeedCalculatorDefaultImpl.java | 5 +- .../matsim/contrib/bicycle/BicycleModule.java | 30 ++++++--- .../BicycleTravelDisutilityFactory.java | 19 +++--- .../matsim/contrib/bicycle/BicycleUtils.java | 7 ++ .../network/BicycleOsmNetworkReaderV2.java | 2 +- .../controler/ControlerDefaultsModule.java | 3 +- .../AbstractAgentSnapshotInfoBuilder.java | 19 ++++-- .../qsim/qnetsimengine/QueueWithBuffer.java | 67 ++++++++++--------- .../EquiDistAgentSnapshotInfoBuilderTest.java | 10 +-- .../QueueAgentSnapshotInfoBuilderTest.java | 14 ++-- 10 files changed, 103 insertions(+), 73 deletions(-) diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleLinkSpeedCalculatorDefaultImpl.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleLinkSpeedCalculatorDefaultImpl.java index f580b7e77f1..f6e5104fa86 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleLinkSpeedCalculatorDefaultImpl.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleLinkSpeedCalculatorDefaultImpl.java @@ -18,7 +18,10 @@ public final class BicycleLinkSpeedCalculatorDefaultImpl implements BicycleLinkS private static final Logger log = LogManager.getLogger(BicycleLinkSpeedCalculatorDefaultImpl.class ); @Inject private BicycleConfigGroup bicycleConfigGroup; @Inject private QSimConfigGroup qSimConfigGroup; - @Inject private BicycleLinkSpeedCalculatorDefaultImpl() { } + @Inject private Config config; + @Inject private BicycleLinkSpeedCalculatorDefaultImpl() { + } + /** * for unit testing */ diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java index 7bf5a766bf4..45e03c8a2f9 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java @@ -22,8 +22,12 @@ import com.google.inject.Singleton; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.checkerframework.checker.units.qual.C; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigGroup; +import org.matsim.core.config.ConfigUtils; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.events.StartupEvent; import org.matsim.core.controler.listener.StartupListener; @@ -34,30 +38,34 @@ * @author smetzler, dziemke */ public final class BicycleModule extends AbstractModule { - private static final Logger LOG = LogManager.getLogger(BicycleModule.class); - @Inject - private BicycleConfigGroup bicycleConfigGroup; + @Override public void install() { + BicycleConfigGroup bicycleConfigGroup = ConfigUtils.addOrGetModule( this.getConfig(), BicycleConfigGroup.class ); + this.bind( BicycleConfigGroup.class ).toInstance( bicycleConfigGroup ); + // the above feels odd. But it seems to work. I actually have no idea where the config groups are bound, neither for the core config + // groups nor for the added config groups. In general, the original idea was that AbstractModule provides the config from + // getConfig(), not from injection. kai, jun'24 - @Override - public void install() { // The idea here is the following: // * scores are just added as score events. no scoring function is replaced. // * link speeds are computed via a plugin handler to the DefaultLinkSpeedCalculator. If the plugin handler returns a speed, it is // used, otherwise the default speed is used. This has the advantage that multiple plugins can register such special link speed calculators. + // this gives the typical things to the router: addTravelTimeBinding(bicycleConfigGroup.getBicycleMode()).to(BicycleTravelTime.class).in(Singleton.class); addTravelDisutilityFactoryBinding(bicycleConfigGroup.getBicycleMode()).to(BicycleTravelDisutilityFactory.class).in(Singleton.class); + // (the BicycleTravelTime uses the BicycleLinkSpeed Calculator bound below) + // (the BicycleDisutility uses a BicycleTravelDisutility) + // compute and throw the additional score events: this.addEventHandlerBinding().to( BicycleScoreEventsCreator.class ); - // (the motorized interaction is in the BicycleScoreEventsCreator) + // (this uses the AdditionalBicycleLinkScore to compute and throw corresponding scoring events) + // (it also computes and throws the motorized interaction events, if they are switched on) this.bind( AdditionalBicycleLinkScore.class ).to( AdditionalBicycleLinkScoreDefaultImpl.class ); - - bind( BicycleLinkSpeedCalculator.class ).to( BicycleLinkSpeedCalculatorDefaultImpl.class ) ; - // this is still needed because the bicycle travel time calculator for routing needs to use the same bicycle speed as the mobsim. kai, jun'23 + // (this computes the value of the per-link scoring event. yyyy Very unfortunately, it is a re-implementation of the BicycleTravelDisutility (mentioned above).) this.installOverridingQSimModule( new AbstractQSimModule(){ @Override protected void configureQSim(){ @@ -65,6 +73,9 @@ public void install() { } } ); + bind( BicycleLinkSpeedCalculator.class ).to( BicycleLinkSpeedCalculatorDefaultImpl.class ) ; + // (both the router and the mobsim need this) + addControlerListenerBinding().to(ConsistencyCheck.class); } @@ -73,7 +84,6 @@ static class ConsistencyCheck implements StartupListener { @Inject private Scenario scenario; @Override public void notifyStartup(StartupEvent event) { - Id bicycleVehTypeId = Id.create(bicycleConfigGroup.getBicycleMode(), VehicleType.class); if (scenario.getVehicles().getVehicleTypes().get(bicycleVehTypeId) == null) { LOG.warn("There is no vehicle type '" + bicycleConfigGroup.getBicycleMode() + "' specified in the vehicle types. " diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleTravelDisutilityFactory.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleTravelDisutilityFactory.java index 135bc7e011f..ab7ffad85ad 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleTravelDisutilityFactory.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleTravelDisutilityFactory.java @@ -21,6 +21,8 @@ import com.google.inject.Inject; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.router.costcalculators.TravelDisutilityFactory; @@ -35,21 +37,20 @@ */ public final class BicycleTravelDisutilityFactory implements TravelDisutilityFactory { // public-final is ok since ctor is package-private: can only be used through injection - private static final Logger LOG = LogManager.getLogger(BicycleTravelDisutilityFactory.class); - - @Inject BicycleConfigGroup bicycleConfigGroup; - @Inject - ScoringConfigGroup cnScoringGroup; - @Inject - RoutingConfigGroup routingConfigGroup; - + private BicycleConfigGroup bicycleConfigGroup; + @Inject Config config; + @Inject ScoringConfigGroup cnScoringGroup; + @Inject RoutingConfigGroup routingConfigGroup; private static int normalisationWrnCnt = 0; - /* package-private */ BicycleTravelDisutilityFactory(){} + /* package-private */ BicycleTravelDisutilityFactory(){ + } @Override public TravelDisutility createTravelDisutility(TravelTime timeCalculator) { + this.bicycleConfigGroup = ConfigUtils.addOrGetModule( config, BicycleConfigGroup.class ); + double sigma = routingConfigGroup.getRoutingRandomness(); double normalization = 1; diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleUtils.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleUtils.java index 43bf5e63776..3af954d9c70 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleUtils.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleUtils.java @@ -127,4 +127,11 @@ private static boolean hasNoCycleway( String cyclewayType ) { } return userDefinedNetworkAttributeFactor; } + // === + public static void setSmoothness( Link link, String smoothness ){ + link.getAttributes().putAttribute( SMOOTHNESS, smoothness ); + } + public static void setBicycleInfrastructureFactor( Link link, double factor ){ + link.getAttributes().putAttribute( BICYCLE_INFRASTRUCTURE_SPEED_FACTOR, factor ); + } } diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/network/BicycleOsmNetworkReaderV2.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/network/BicycleOsmNetworkReaderV2.java index cd51b40275b..549f4c25656 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/network/BicycleOsmNetworkReaderV2.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/network/BicycleOsmNetworkReaderV2.java @@ -225,7 +225,7 @@ protected void setOrModifyLinkAttributes(Link l, OsmWay way, boolean forwardDire // Smoothness String smoothness = way.tags.get(BicycleUtils.SMOOTHNESS); if (smoothness != null) { - l.getAttributes().putAttribute(BicycleUtils.SMOOTHNESS, smoothness); + BicycleUtils.setSmoothness( l, smoothness ); this.countSmoothness++; } diff --git a/matsim/src/main/java/org/matsim/core/controler/ControlerDefaultsModule.java b/matsim/src/main/java/org/matsim/core/controler/ControlerDefaultsModule.java index fc5c43da358..293ac9ed415 100755 --- a/matsim/src/main/java/org/matsim/core/controler/ControlerDefaultsModule.java +++ b/matsim/src/main/java/org/matsim/core/controler/ControlerDefaultsModule.java @@ -85,8 +85,7 @@ public void install() { // Maybe not the best place to but this but since ChartUtils is used by many modules, including default ones, // the cache needs to be always set correctly. addControlerListenerBinding().toInstance(new StartupListener() { - @Inject - private OutputDirectoryHierarchy outputDirectoryHierarchy; + @Inject private OutputDirectoryHierarchy outputDirectoryHierarchy; @Override public void notifyStartup(StartupEvent event) { ImageIO.setCacheDirectory(new File(outputDirectoryHierarchy.getTempPath())); } diff --git a/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/AbstractAgentSnapshotInfoBuilder.java b/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/AbstractAgentSnapshotInfoBuilder.java index 78d2b0afe5d..c6bf2e47d49 100644 --- a/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/AbstractAgentSnapshotInfoBuilder.java +++ b/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/AbstractAgentSnapshotInfoBuilder.java @@ -139,12 +139,13 @@ public final void positionAgentGivenDistanceFromFNode(final Collection positionVehiclesAlongLine(Collection positions, - double now, Collection vehs, double curvedLength, double storageCapacity, - Coord upstreamCoord, Coord downstreamCoord, double inverseFlowCapPerTS, double freeSpeed, - int numberOfLanesAsInt, Queue holes) + public final Collection positionVehiclesAlongLine( Collection positions, + double now, Collection vehs, double curvedLength, double storageCapacity, + Coord upstreamCoord, Coord downstreamCoord, double inverseFlowCapPerTS, double freeSpeed, + int numberOfLanesAsInt, Queue holes, AbstractQLink.QLinkInternalInterface qLinkInternalInterface ) { double spacingOfOnePCE = this.calculateVehicleSpacing( curvedLength, storageCapacity, vehs ); + // ("vehs" is needed since the link may be more than full because of squeezing. In this case, spacingOfOnePCE is smaller than one "cell".) double ttimeOfHoles = curvedLength / (QueueWithBuffer.HOLE_SPEED_KM_H*1000./3600.); @@ -211,8 +212,16 @@ public final Collection positionVehiclesAlongLine(Collection< // (starts off relatively small (rightmost vehicle)) final double vehicleSpacing = mveh.getSizeInEquivalents() * spacingOfOnePCE; + + double speed = min( freeSpeed, veh.getMaximumVelocity() ); + if ( qLinkInternalInterface!=null ){ + speed = qLinkInternalInterface.getMaximumVelocityFromLinkSpeedCalculator( veh, now ); + } + distanceFromFromNode = this.calculateOdometerDistanceFromFromNode( - now, curvedLength, min( freeSpeed, veh.getMaximumVelocity()), vehicleSpacing, distanceFromFromNode, remainingTravelTime + now, curvedLength, + speed, // min( freeSpeed, veh.getMaximumVelocity()), + vehicleSpacing, distanceFromFromNode, remainingTravelTime ); // yyyy if the LinkSpeedCalculator says something that is not free speed, we are out of luck here. kai, jan'23 diff --git a/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueWithBuffer.java b/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueWithBuffer.java index 868e9813c65..741763e4c87 100644 --- a/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueWithBuffer.java +++ b/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueWithBuffer.java @@ -162,7 +162,7 @@ private void addValue(double value1, double now) { * pointer, and give access only to reduced number of methods (in particular not the full Link information). kai, feb'18 * This is now done with the {@link AbstractQLink.QLinkInternalInterface}. kai, feb'18 */ - private final AbstractQLink.QLinkInternalInterface qLink; + private final AbstractQLink.QLinkInternalInterface qLinkInternalInterface; private final Id id; private static int spaceCapWarningCount = 0; final static double HOLE_SPEED_KM_H = 15.0; @@ -202,7 +202,7 @@ private QueueWithBuffer(AbstractQLink.QLinkInternalInterface qlink, final Vehicl // log.setLevel(Level.DEBUG); this.flowEfficiencyCalculator = flowEfficiencyCalculator; - this.qLink = qlink; + this.qLinkInternalInterface = qlink; this.id = laneId ; this.context = context ; this.vehQueue = vehicleQueue ; @@ -239,7 +239,7 @@ private void addToBuffer(final QVehicle veh) { // need to reset the lastMovedTime. If, in contrast, there was already a vehicle in the buffer before, we can // use the lastMovedTime that was (somehow) computed for that vehicle.) } - final QNodeI toNode = qLink.getToNodeQ(); + final QNodeI toNode = qLinkInternalInterface.getToNodeQ(); if ( toNode instanceof AbstractQNode ) { ((AbstractQNode) toNode).activateNode(); // yy for an "upstream" QLane, this activates the toNode too early. Yet I think I founds this @@ -266,9 +266,9 @@ private void moveQueueToBuffer() { MobsimDriverAgent driver = veh.getDriver(); if (driver instanceof TransitDriverAgent) { - HandleTransitStopResult handleTransitStop = qLink.handleTransitStop( - now, veh, (TransitDriverAgent) driver, this.qLink.getId() - ); + HandleTransitStopResult handleTransitStop = qLinkInternalInterface.handleTransitStop( + now, veh, (TransitDriverAgent) driver, this.qLinkInternalInterface.getId() + ); if (handleTransitStop == HandleTransitStopResult.accepted) { // vehicle has been accepted into the transit vehicle queue of the link. removeVehicleFromQueue(veh); @@ -285,7 +285,7 @@ private void moveQueueToBuffer() { // Check if veh has reached destination: if (driver.isWantingToArriveOnCurrentLink()) { - if (qLink.letVehicleArrive(veh)) { + if ( qLinkInternalInterface.letVehicleArrive(veh )) { // remove _after_ processing the arrival to keep link active: removeVehicleFromQueue(veh); continue; @@ -395,8 +395,8 @@ private void calculateFlowCapacity() { // yyyyyy this should possibly be getFreespeed(now). But if that's the case, then maxFlowFromFdiag would // also have to be re-computed with each freespeed change. kai, feb'18 - final double maxFlowFromFdiag = (this.effectiveNumberOfLanes/context.effectiveCellSize) / ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLink.getFreespeed() ) ; - final double minimumNumberOfLanesFromFdiag = this.flowCapacityPerTimeStep * context.effectiveCellSize * ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLink.getFreespeed() ); + final double maxFlowFromFdiag = (this.effectiveNumberOfLanes/context.effectiveCellSize) / ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLinkInternalInterface.getFreespeed() ) ; + final double minimumNumberOfLanesFromFdiag = this.flowCapacityPerTimeStep * context.effectiveCellSize * ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLinkInternalInterface.getFreespeed() ); QSimConfigGroup.InflowCapacitySetting inflowCapacitySetting = context.qsimConfig.getInflowCapacitySetting(); @@ -411,19 +411,19 @@ private void calculateFlowCapacity() { log.warn( Gbl.FUTURE_SUPPRESSED ) ; } - this.maxInflowUsedInQsim = (1/context.effectiveCellSize) / ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLink.getFreespeed() ) ; + this.maxInflowUsedInQsim = (1/context.effectiveCellSize) / ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLinkInternalInterface.getFreespeed() ) ; // write out the modified qsim behavior as link attribute - qLink.getLink().getAttributes().putAttribute("maxInflowUsedInQsim", 3600* maxInflowUsedInQsim /context.qsimConfig.getTimeStepSize()); + qLinkInternalInterface.getLink().getAttributes().putAttribute("maxInflowUsedInQsim", 3600* maxInflowUsedInQsim /context.qsimConfig.getTimeStepSize() ); } else { if ( maxFlowFromFdiag < flowCapacityPerTimeStep ){ //warnings if (wrnCnt<10) { wrnCnt++ ; - log.warn( "max flow from fdiag < flow cap in network file; linkId=" + qLink.getId() + + log.warn( "max flow from fdiag < flow cap in network file; linkId=" + qLinkInternalInterface.getId() + "; network file flow cap/h=" + 3600.*flowCapacityPerTimeStep/context.qsimConfig.getTimeStepSize() + "; max flow from fdiag/h=" + 3600*maxFlowFromFdiag/context.qsimConfig.getTimeStepSize() ) ; - log.warn( "number of lanes from fdiag > number of lanes in network file; linkId=" + qLink.getId() + + log.warn( "number of lanes from fdiag > number of lanes in network file; linkId=" + qLinkInternalInterface.getId() + "; number of lanes in network file=" + this.effectiveNumberOfLanes + "; number of lanes from fdiag=" + minimumNumberOfLanesFromFdiag ) ; @@ -445,11 +445,11 @@ private void calculateFlowCapacity() { if (inflowCapacitySetting == QSimConfigGroup.InflowCapacitySetting.INFLOW_FROM_FDIAG) { this.maxInflowUsedInQsim = maxFlowFromFdiag; // write out the modified qsim behavior as link attribute - qLink.getLink().getAttributes().putAttribute("maxInflowUsedInQsim", 3600* maxInflowUsedInQsim /context.qsimConfig.getTimeStepSize()); + qLinkInternalInterface.getLink().getAttributes().putAttribute("maxInflowUsedInQsim", 3600* maxInflowUsedInQsim /context.qsimConfig.getTimeStepSize() ); } else if (inflowCapacitySetting == QSimConfigGroup.InflowCapacitySetting.NR_OF_LANES_FROM_FDIAG) { this.effectiveNumberOfLanesUsedInQsim = minimumNumberOfLanesFromFdiag; // write out the modified qsim behavior as link attribute - qLink.getLink().getAttributes().putAttribute("effectiveNumberOfLanesUsedInQsim", effectiveNumberOfLanesUsedInQsim); + qLinkInternalInterface.getLink().getAttributes().putAttribute("effectiveNumberOfLanesUsedInQsim", effectiveNumberOfLanesUsedInQsim ); } else { throw new RuntimeException("The approach "+ inflowCapacitySetting.toString()+" is not implemented yet."); } @@ -483,7 +483,7 @@ private void calculateStorageCapacity() { * Will base these computations (for the time being) on the standard free speed; i.e. reductions in free speed * will also reduce the maximum flow. */ - double freespeedTravelTime = this.length / qLink.getFreespeed(); + double freespeedTravelTime = this.length / qLinkInternalInterface.getFreespeed(); // yyyyyy this should possibly be getFreespeed(now). But if that's the case, then storageCap would // also have to be re-computed with each freespeed change. kai, feb'18 if (Double.isNaN(freespeedTravelTime)) { @@ -507,7 +507,7 @@ private void calculateStorageCapacity() { storageCapacity = tempStorageCapacity; // write out the modified qsim behavior as link attribute - qLink.getLink().getAttributes().putAttribute("storageCapacityUsedInQsim", storageCapacity); + qLinkInternalInterface.getLink().getAttributes().putAttribute("storageCapacityUsedInQsim", storageCapacity ); } /* About minStorCapForHoles: @@ -527,7 +527,7 @@ private void calculateStorageCapacity() { case withHoles: case kinematicWaves: // final double minStorCapForHoles = 2. * flowCapacityPerTimeStep * context.getSimTimer().getSimTimestepSize(); - final double freeSpeed = qLink.getFreespeed() ; // yyyyyy not clear why this is not time-dep. kai, feb'18 + final double freeSpeed = qLinkInternalInterface.getFreespeed() ; // yyyyyy not clear why this is not time-dep. kai, feb'18 final double holeSpeed = HOLE_SPEED_KM_H/3.6; final double minStorCapForHoles = length * flowCapacityPerTimeStep * (freeSpeed + holeSpeed) / freeSpeed / holeSpeed ; // final double minStorCapForHoles = 2.* length * flowCapacityPerTimeStep * (freeSpeed + holeSpeed) / freeSpeed / holeSpeed ; @@ -541,7 +541,7 @@ private void calculateStorageCapacity() { } storageCapacity = minStorCapForHoles ; // write out the modified qsim behavior as link attribute - qLink.getLink().getAttributes().putAttribute("storageCapacityUsedInQsim", storageCapacity); + qLinkInternalInterface.getLink().getAttributes().putAttribute("storageCapacityUsedInQsim", storageCapacity ); } remainingHolesStorageCapacity = this.storageCapacity; @@ -589,12 +589,12 @@ public final void addFromUpstream(final QVehicle veh) { if (this.context.qsimConfig.isUseLanes()) { if (hasMoreThanOneLane()) { - this.context.getEventsManager().processEvent(new LaneEnterEvent(now, veh.getId(), this.qLink.getId(), this.getId())); + this.context.getEventsManager().processEvent(new LaneEnterEvent(now, veh.getId(), this.qLinkInternalInterface.getId(), this.getId()) ); } } // activate link since there is now action on it: - qLink.activateLink(); + qLinkInternalInterface.activateLink(); if (context.qsimConfig.isSeepModeStorageFree() && context.qsimConfig.getSeepModes().contains(veh.getVehicle().getType().getId().toString())) { // do nothing @@ -604,7 +604,7 @@ public final void addFromUpstream(final QVehicle veh) { // compute and set earliest link exit time: // double linkTravelTime = this.length / this.linkSpeedCalculator.getMaximumVelocity(veh, qLink.getLink(), now); - double linkTravelTime = this.length / this.qLink.getMaximumVelocityFromLinkSpeedCalculator(veh, now); + double linkTravelTime = this.length / this.qLinkInternalInterface.getMaximumVelocityFromLinkSpeedCalculator(veh, now ); linkTravelTime = context.qsimConfig.getTimeStepSize() * Math.floor(linkTravelTime / context.qsimConfig.getTimeStepSize()); veh.setEarliestLinkExitTime(now + linkTravelTime); @@ -619,7 +619,7 @@ public final void addFromUpstream(final QVehicle veh) { // inserted and thus end up after vehicles with a later link exit time. theresa & kai, jun'14 // veh.setCurrentLink(qLink.getLink()); - this.qLink.setCurrentLinkToVehicle(veh); + this.qLinkInternalInterface.setCurrentLinkToVehicle(veh ); vehQueue.add(veh); switch (context.qsimConfig.getTrafficDynamics()) { @@ -795,7 +795,7 @@ public final QVehicle popFirstVehicle() { QVehicle veh = removeFirstVehicle(); if (this.context.qsimConfig.isUseLanes() ) { if ( hasMoreThanOneLane() ) { - this.context.getEventsManager().processEvent(new LaneLeaveEvent( now, veh.getId(), this.qLink.getId(), this.getId() )); + this.context.getEventsManager().processEvent(new LaneLeaveEvent( now, veh.getId(), this.qLinkInternalInterface.getId(), this.getId() ) ); } } return veh; @@ -813,7 +813,7 @@ private final QVehicle removeFirstVehicle(){ @Override public final void setSignalStateForTurningMove( final SignalGroupState state, final Id toLinkId) { - if (!qLink.getToNode().getOutLinks().containsKey(toLinkId)){ + if (!qLinkInternalInterface.getToNode().getOutLinks().containsKey(toLinkId )){ throw new IllegalArgumentException("ToLink " + toLinkId + " is not reachable from QLink Id " + this.id ); } qSignalizedItem.setSignalStateForTurningMove(state, toLinkId); @@ -879,12 +879,12 @@ public final void clearVehicles() { } private double getFlowCapacityConsumptionInEquivalents(QVehicle vehicle, QVehicle prevVehicle, Double timeDiff) { - double flowEfficiency = flowEfficiencyCalculator.calculateFlowEfficiency(vehicle, prevVehicle, timeDiff, qLink.getLink(), id); + double flowEfficiency = flowEfficiencyCalculator.calculateFlowEfficiency(vehicle, prevVehicle, timeDiff, qLinkInternalInterface.getLink(), id ); return vehicle.getSizeInEquivalents() / flowEfficiency; } private boolean hasMoreThanOneLane() { - return this.qLink.getAcceptingQLane() != this.qLink.getOfferingQLanes().get(0); + return this.qLinkInternalInterface.getAcceptingQLane() != this.qLinkInternalInterface.getOfferingQLanes().get(0 ); // this works independent from sorting since if there is only one lane, then it has to be the one to be returned by // getOfferingQLanes().get(0), and it is also the same as the accepting QLane. If, however, "lanes" is used, // there are at least two lanes in sequence, so the accepting lane is never the same as any of the offering lanes, and @@ -919,7 +919,7 @@ public final void addTransitSlightlyUpstreamOfStop( final QVehicle veh) { @Override public final void setSignalized( final boolean isSignalized) { - qSignalizedItem = new DefaultSignalizeableItem(qLink.getToNode().getOutLinks().keySet()); + qSignalizedItem = new DefaultSignalizeableItem( qLinkInternalInterface.getToNode().getOutLinks().keySet()); } @Override @@ -989,10 +989,10 @@ public final Collection addAgentSnapshotInfo(Collection addAgentSnapshotInfo(Collection() - ); + new LinkedList<>(), + null ); // assert assertEquals(1, outCollection.size()); @@ -85,8 +85,8 @@ void positionVehiclesAlongLine_congestedAboveCapacityLimit() { 1 / setUp.linkCapacity, // this would mean the flow capacity is 100 setUp.freespeed, 1, - new LinkedList<>() - ); + new LinkedList<>(), + null ); // assert assertEquals(vehicles.size(), outCollection.size()); @@ -337,4 +337,4 @@ private static Collection createAgents(int size) { return result; } -} \ No newline at end of file +} diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueAgentSnapshotInfoBuilderTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueAgentSnapshotInfoBuilderTest.java index b81a8fb91a0..b815ced0819 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueAgentSnapshotInfoBuilderTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueAgentSnapshotInfoBuilderTest.java @@ -53,8 +53,8 @@ void positionVehiclesAlongLine_singleVehicleFreeFlow() { 1 / setUp.linkCapacity, // this would mean the flow capacity is 100 setUp.freespeed, 1, - new LinkedList<>() - ); + new LinkedList<>(), + null ); // assert assertEquals(1, outCollection.size()); @@ -94,8 +94,8 @@ void positionVehiclesAlongLine_congestedAboveCapacityLimit() { 1 / setUp.linkCapacity, // this would mean the flow capacity is 100 setUp.freespeed, 1, - new LinkedList<>() - ); + new LinkedList<>(), + null ); // assert assertEquals(vehicles.size(), outCollection.size()); @@ -132,8 +132,8 @@ void positionVehiclesAlongLine_queueAtEnd() { 1 / setUp.linkCapacity, setUp.freespeed, 1, - new LinkedList<>() - ); + new LinkedList<>(), + null ); // assert assertEquals(5, outCollection.size()); @@ -473,4 +473,4 @@ private static Collection createAgents(int size) { } return result; } -} \ No newline at end of file +} From 28e33d26de2102ec66cf9da6d04040b64c065c65 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Fri, 28 Jun 2024 12:36:07 +0200 Subject: [PATCH 003/111] add tests for mode restriction --- .../matsim/examples/ModeRestrictionTest.java | 150 ++++++++++++++++++ .../examples/ModeRestrictionTest/config.xml | 82 ++++++++++ .../examples/ModeRestrictionTest/network.xml | 47 ++++++ .../ModeRestrictionTest/plans_act_link15.xml | 17 ++ .../ModeRestrictionTest/plans_act_link20.xml | 17 ++ .../ModeRestrictionTest/plans_act_link6.xml | 17 ++ 6 files changed, 330 insertions(+) create mode 100644 matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java create mode 100755 matsim/test/input/org/matsim/examples/ModeRestrictionTest/config.xml create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/network.xml create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link15.xml create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link20.xml create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link6.xml diff --git a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java new file mode 100644 index 00000000000..5431f14026e --- /dev/null +++ b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java @@ -0,0 +1,150 @@ +package org.matsim.examples; + +import org.junit.jupiter.api.Assertions; +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.ValueSource; +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.events.handler.*; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.population.Leg; +import org.matsim.core.config.Config; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controler; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.testcases.MatsimTestUtils; + +import java.util.*; + +/** + * In this test, we restrict the allowed modes of a link. The base case is the equil scenario. + * + * /... ...\ + * ------o------------o------------o----------- + * l1 (n2) l6 (n7) l15 (n12) l20 + */ +public class ModeRestrictionTest { + @RegisterExtension + private MatsimTestUtils utils = new MatsimTestUtils(); + + /** + * Test if agent still can use a link if the allowed modes of it are restricted. + * This is because the route is already contained in the plans file and not checked again. + */ + @ParameterizedTest + @ValueSource(strings = {"6", "15", "20"}) + void testNoRouteChange_ok(String link){ + final Config config = utils.loadConfig( utils.getClassInputDirectory() + "config.xml"); + config.plans().setInputFile("plans_act_link20.xml"); + config.controller().setLastIteration(0); + + Id linkId = Id.createLinkId(link); + Scenario scenario = ScenarioUtils.loadScenario(config); + scenario.getNetwork().getLinks().get(linkId).setAllowedModes(Set.of()); + + FirstLegRouteCheck firstLegRouteCheck = new FirstLegRouteCheck(linkId); + runAndCheck(scenario, firstLegRouteCheck); + } + + /** + * Test if Exception is thrown, if no route is given and the activity cannot be reached. This is because of a local dead end. + */ + @Test + void testRerouteBeforeSim_toActNotPossible_throws() { + final Config config = utils.loadConfig( utils.getClassInputDirectory() + "config.xml"); + config.plans().setInputFile("plans_act_link15.xml"); + config.controller().setLastIteration(0); + + Id linkId = Id.createLinkId("6"); + Scenario scenario = ScenarioUtils.loadScenario(config); + scenario.getNetwork().getLinks().get(linkId).setAllowedModes(Set.of()); + Leg leg = (Leg) scenario.getPopulation().getPersons().get(Id.createPersonId(1)).getSelectedPlan().getPlanElements().get(1); + leg.setRoute(null); + + FirstLegRouteCheck firstLegRouteCheck = new FirstLegRouteCheck(linkId); + RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runAndCheck(scenario, firstLegRouteCheck)); + Assertions.assertTrue(exception.getMessage().contains("Exception while processing persons. Cannot guarantee that all persons have been fully processed.")); + } + + /** + * Test if Exception is thrown, if no route is given and the activity cannot be left. This is because of a local dead end. + */ + @Test + void testRerouteBeforeSim_fromActNotPossible_throws() { + final Config config = utils.loadConfig( utils.getClassInputDirectory() + "config.xml"); + config.plans().setInputFile("plans_act_link6.xml"); + config.controller().setLastIteration(0); + + Id linkId = Id.createLinkId("15"); + Scenario scenario = ScenarioUtils.loadScenario(config); + scenario.getNetwork().getLinks().get(linkId).setAllowedModes(Set.of()); + Leg leg = (Leg) scenario.getPopulation().getPersons().get(Id.createPersonId(1)).getSelectedPlan().getPlanElements().get(1); + leg.setRoute(null); + + FirstLegRouteCheck firstLegRouteCheck = new FirstLegRouteCheck(linkId); + RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runAndCheck(scenario, firstLegRouteCheck)); + Assertions.assertTrue(exception.getMessage().contains("Exception while processing persons. Cannot guarantee that all persons have been fully processed.")); + } + + private static void runAndCheck(Scenario scenario, FirstLegRouteCheck firstLegRouteCheck) { + Controler controler = new Controler(scenario); + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + this.addEventHandlerBinding().toInstance(firstLegRouteCheck); + } + }); + controler.run(); + + firstLegRouteCheck.assertActualContainsExpected(); + } + + private static class FirstLegRouteCheck implements LinkEnterEventHandler, ActivityEndEventHandler, PersonLeavesVehicleEventHandler { + private final List> expected; + private final List> actual = new ArrayList<>(); + + private boolean firstLeg = true; + + public FirstLegRouteCheck(List> expected) { + this.expected = expected; + } + + public FirstLegRouteCheck(Id expected){ + this.expected = Collections.singletonList(expected); + } + + @Override + public void handleEvent(ActivityEndEvent event) { + addLinkIdToActual(event.getLinkId()); + } + + @Override + public void handleEvent(LinkEnterEvent event) { + addLinkIdToActual(event.getLinkId()); + } + + @Override + public void handleEvent(PersonLeavesVehicleEvent event) { + firstLeg = false; + } + + private void addLinkIdToActual(Id event) { + if (!firstLeg) { + return; + } + actual.add(event); + } + + public void assertActualEqualsExpected() { + Assertions.assertEquals(expected, actual); + } + + public void assertActualContainsExpected() { + Assertions.assertTrue(actual.containsAll(expected)); + } + } + +} diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/config.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/config.xml new file mode 100755 index 00000000000..3cd923f11dc --- /dev/null +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/config.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/network.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/network.xml new file mode 100644 index 00000000000..1f98124e31a --- /dev/null +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/network.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link15.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link15.xml new file mode 100644 index 00000000000..c00caacf2eb --- /dev/null +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link15.xml @@ -0,0 +1,17 @@ + + + + + + + + 2 7 + + + + 12 13 14 15 1 + + + + + diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link20.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link20.xml new file mode 100644 index 00000000000..af3ad532919 --- /dev/null +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link20.xml @@ -0,0 +1,17 @@ + + + + + + + + 2 7 12 + + + + 13 14 15 1 + + + + + diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link6.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link6.xml new file mode 100644 index 00000000000..493ec731e73 --- /dev/null +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link6.xml @@ -0,0 +1,17 @@ + + + + + + + + 2 + + + + 7 12 13 14 15 1 + + + + + From 276a46f45716f039319bc3ea1a89fc8dfb0b85e1 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Fri, 28 Jun 2024 17:42:11 +0200 Subject: [PATCH 004/111] add tests that depict the current behaviour --- .../algorithms/NetworkCleanerTest.java | 24 +++ .../matsim/examples/ModeRestrictionTest.java | 193 +++++++++++++----- .../ModeRestrictionTest/plans_act_link15.xml | 2 +- .../ModeRestrictionTest/plans_act_link20.xml | 2 +- .../ModeRestrictionTest/plans_act_link6.xml | 2 +- 5 files changed, 169 insertions(+), 54 deletions(-) diff --git a/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkCleanerTest.java b/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkCleanerTest.java index db870267bcc..4e98d28fe4a 100644 --- a/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkCleanerTest.java +++ b/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkCleanerTest.java @@ -22,13 +22,18 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; import org.matsim.api.core.v01.network.Node; import org.matsim.core.network.NetworkUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; /** * A very simple test for the NetworkCleaner, it doesn't test by far all possible cases. @@ -189,4 +194,23 @@ void testDoubleSource() { assertEquals(4, network.getLinks().size(), "# links"); } + /** + * This test essentially does the same by modifying the equil scenario. + * Visualization: + * /... ...\ + * ------o------------o------------o----------- + * l1 (n2) l6 (n7) l15 (n12) l20 + */ + @ParameterizedTest + @CsvSource({"6,15", "15,6"}) + void testNetworkCleaner(String removedBefore, String expectedRemovedAfter){ + Network net = NetworkUtils.readNetwork(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("equil"), "network.xml").toString()); + net.removeLink(Id.createLinkId(removedBefore)); + int size = net.getLinks().size(); + + NetworkUtils.runNetworkCleaner(net); + Assertions.assertFalse(net.getLinks().containsKey(Id.createLinkId(expectedRemovedAfter))); + assertEquals(net.getLinks().size(), size - 1); + } + } diff --git a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java index 5431f14026e..c14d0a7563e 100644 --- a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java +++ b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java @@ -1,5 +1,8 @@ package org.matsim.examples; +import com.google.common.collect.Lists; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -7,37 +10,50 @@ import org.junit.jupiter.params.provider.ValueSource; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; -import org.matsim.api.core.v01.events.*; -import org.matsim.api.core.v01.events.handler.*; +import org.matsim.api.core.v01.events.LinkEnterEvent; +import org.matsim.api.core.v01.events.LinkLeaveEvent; +import org.matsim.api.core.v01.events.PersonEntersVehicleEvent; +import org.matsim.api.core.v01.events.PersonLeavesVehicleEvent; +import org.matsim.api.core.v01.events.handler.LinkEnterEventHandler; +import org.matsim.api.core.v01.events.handler.LinkLeaveEventHandler; +import org.matsim.api.core.v01.events.handler.PersonEntersVehicleEventHandler; +import org.matsim.api.core.v01.events.handler.PersonLeavesVehicleEventHandler; import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.population.Activity; import org.matsim.api.core.v01.population.Leg; +import org.matsim.api.core.v01.population.Person; import org.matsim.core.config.Config; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vehicles.Vehicle; import java.util.*; +// @formatter:off /** * In this test, we restrict the allowed modes of a link. The base case is the equil scenario. - * - * /... ...\ + *

+ * /... ...\ * ------o------------o------------o----------- - * l1 (n2) l6 (n7) l15 (n12) l20 + * l1 (n2) l6 (n7) l15 (n12) l20 */ +// @formatter:on public class ModeRestrictionTest { + private static final Logger log = LogManager.getLogger(ModeRestrictionTest.class); + @RegisterExtension private MatsimTestUtils utils = new MatsimTestUtils(); /** - * Test if agent still can use a link if the allowed modes of it are restricted. - * This is because the route is already contained in the plans file and not checked again. + * Setting: The agent has a route from the plan. Link before and at the activity is restricted respectively. + * Expected behaviour: Since it is not checked, if the route contains link, which are not allowed to use anymore, it can still use the restricted link. */ @ParameterizedTest @ValueSource(strings = {"6", "15", "20"}) - void testNoRouteChange_ok(String link){ - final Config config = utils.loadConfig( utils.getClassInputDirectory() + "config.xml"); + void testNoRouteChange_ok(String link) { + final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml"); config.plans().setInputFile("plans_act_link20.xml"); config.controller().setLastIteration(0); @@ -45,51 +61,104 @@ void testNoRouteChange_ok(String link){ Scenario scenario = ScenarioUtils.loadScenario(config); scenario.getNetwork().getLinks().get(linkId).setAllowedModes(Set.of()); - FirstLegRouteCheck firstLegRouteCheck = new FirstLegRouteCheck(linkId); - runAndCheck(scenario, firstLegRouteCheck); + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(Id.createPersonId("car"), linkId); + runController(scenario, firstLegRouteCheck); + firstLegRouteCheck.assertActualContainsExpected(); } /** - * Test if Exception is thrown, if no route is given and the activity cannot be reached. This is because of a local dead end. + * Setting: The agent has no route. The mode of the link in front of the activity is restricted. + * Expected behaviour: By default, the network is not cleaned. The router throws an exception since there is no route from home to the activity. */ @Test void testRerouteBeforeSim_toActNotPossible_throws() { - final Config config = utils.loadConfig( utils.getClassInputDirectory() + "config.xml"); + final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml"); config.plans().setInputFile("plans_act_link15.xml"); config.controller().setLastIteration(0); - Id linkId = Id.createLinkId("6"); - Scenario scenario = ScenarioUtils.loadScenario(config); - scenario.getNetwork().getLinks().get(linkId).setAllowedModes(Set.of()); - Leg leg = (Leg) scenario.getPopulation().getPersons().get(Id.createPersonId(1)).getSelectedPlan().getPlanElements().get(1); - leg.setRoute(null); + Id link = Id.createLinkId("6"); + Id person = Id.createPersonId("car"); + + Scenario scenario = restrictLinkAndResetRoute(config, link, person); - FirstLegRouteCheck firstLegRouteCheck = new FirstLegRouteCheck(linkId); - RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runAndCheck(scenario, firstLegRouteCheck)); - Assertions.assertTrue(exception.getMessage().contains("Exception while processing persons. Cannot guarantee that all persons have been fully processed.")); + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(person, link); + RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runController(scenario, firstLegRouteCheck)); + Assertions.assertTrue( + exception.getMessage().contains("Exception while processing persons. Cannot guarantee that all persons have been fully processed.")); } /** - * Test if Exception is thrown, if no route is given and the activity cannot be left. This is because of a local dead end. + * Setting: The agent has no route. The mode of the link behind the activity is restricted. + * Expected behaviour: By default, the network is not cleaned. The router throws an exception since there is no route from the activity to home. */ @Test void testRerouteBeforeSim_fromActNotPossible_throws() { - final Config config = utils.loadConfig( utils.getClassInputDirectory() + "config.xml"); + final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml"); config.plans().setInputFile("plans_act_link6.xml"); config.controller().setLastIteration(0); - Id linkId = Id.createLinkId("15"); + Id link = Id.createLinkId("15"); + Id person = Id.createPersonId("car"); + + Scenario scenario = restrictLinkAndResetRoute(config, link, person); + + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(person, link); + RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runController(scenario, firstLegRouteCheck)); + Assertions.assertTrue( + exception.getMessage().contains("Exception while processing persons. Cannot guarantee that all persons have been fully processed.")); + } + + /** + * Setting: The agent has no route. The mode of the activity's link is restricted. Activity has x-y-coordinate. + * Expected behaviour: The agent is rerouted to the nearest link to the activity's coordinate. + */ + @Test + void testRerouteBeforeSim_actOnRestrictedLinkWithCoords_ok() { + final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml"); + config.plans().setInputFile("plans_act_link15.xml"); + config.controller().setLastIteration(0); + + Id person = Id.createPersonId("car"); + Scenario scenario = restrictLinkAndResetRoute(config, Id.createLinkId("15"), person); + + // New route. Note that the end link is 20, but the activity's link in the input was 15. + // But since we restricted the mode for link 15, 20 is used as fallback. + List> newRoute = List.of(Id.createLinkId("1"), Id.createLinkId("2"), Id.createLinkId("11"), Id.createLinkId("20")); + + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(person, newRoute); + runController(scenario, firstLegRouteCheck); + firstLegRouteCheck.assertActualEqualsExpected(); + } + + /** + * Setting: The agent has no route. The mode of the activity's link is restricted. Activity has no x-y-coordinate. + * Expected behaviour: The router throws an exception since there is no fallback x-y-coordinate. + */ + @Test + void testRerouteBeforeSim_actOnRestrictedLinkWithoutCoord_throws(){ + final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml"); + config.plans().setInputFile("plans_act_link15.xml"); + config.controller().setLastIteration(0); + + Id person = Id.createPersonId("car"); + Scenario scenario = restrictLinkAndResetRoute(config, Id.createLinkId("15"), person); + Activity act = (Activity) scenario.getPopulation().getPersons().get(person).getPlans().getFirst().getPlanElements().get(2); + act.setCoord(null); + + RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runController(scenario, new FirstLegVisitedLinksCheck())); + Assertions.assertTrue( + exception.getMessage().contains("Exception while processing persons. Cannot guarantee that all persons have been fully processed.")); + } + + private static Scenario restrictLinkAndResetRoute(Config config, Id link, Id person) { Scenario scenario = ScenarioUtils.loadScenario(config); - scenario.getNetwork().getLinks().get(linkId).setAllowedModes(Set.of()); - Leg leg = (Leg) scenario.getPopulation().getPersons().get(Id.createPersonId(1)).getSelectedPlan().getPlanElements().get(1); + scenario.getNetwork().getLinks().get(link).setAllowedModes(Set.of()); + Leg leg = (Leg) scenario.getPopulation().getPersons().get(person).getSelectedPlan().getPlanElements().get(1); leg.setRoute(null); - - FirstLegRouteCheck firstLegRouteCheck = new FirstLegRouteCheck(linkId); - RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runAndCheck(scenario, firstLegRouteCheck)); - Assertions.assertTrue(exception.getMessage().contains("Exception while processing persons. Cannot guarantee that all persons have been fully processed.")); + return scenario; } - private static void runAndCheck(Scenario scenario, FirstLegRouteCheck firstLegRouteCheck) { + private static void runController(Scenario scenario, FirstLegVisitedLinksCheck firstLegRouteCheck) { Controler controler = new Controler(scenario); controler.addOverridingModule(new AbstractModule() { @Override @@ -98,44 +167,61 @@ public void install() { } }); controler.run(); - - firstLegRouteCheck.assertActualContainsExpected(); } - private static class FirstLegRouteCheck implements LinkEnterEventHandler, ActivityEndEventHandler, PersonLeavesVehicleEventHandler { - private final List> expected; - private final List> actual = new ArrayList<>(); - - private boolean firstLeg = true; + /** + * Event handler that checks the visited Links of a person on the first leg. + */ + private static class FirstLegVisitedLinksCheck implements LinkEnterEventHandler, LinkLeaveEventHandler, PersonEntersVehicleEventHandler, + PersonLeavesVehicleEventHandler { + private final Map, List>> expected = new HashMap<>(); + private final Map, List>> actual = new HashMap<>(); + private final Map, Id> currentPersonByVehicle = new HashMap<>(); + private final Map, Boolean> onFirstLeg = new HashMap<>(); + + public FirstLegVisitedLinksCheck() { + } - public FirstLegRouteCheck(List> expected) { - this.expected = expected; + public FirstLegVisitedLinksCheck(Id personId, List> expected) { + this.expected.put(personId, expected); } - public FirstLegRouteCheck(Id expected){ - this.expected = Collections.singletonList(expected); + public FirstLegVisitedLinksCheck(Id personId, Id expected) { + this.expected.put(personId, Collections.singletonList(expected)); } @Override - public void handleEvent(ActivityEndEvent event) { - addLinkIdToActual(event.getLinkId()); + public void handleEvent(LinkLeaveEvent event) { + addLinkIdToActual(this.currentPersonByVehicle.get(event.getVehicleId()), event.getLinkId()); } @Override public void handleEvent(LinkEnterEvent event) { - addLinkIdToActual(event.getLinkId()); + addLinkIdToActual(this.currentPersonByVehicle.get(event.getVehicleId()), event.getLinkId()); } @Override public void handleEvent(PersonLeavesVehicleEvent event) { - firstLeg = false; + this.currentPersonByVehicle.remove(event.getVehicleId()); + this.onFirstLeg.put(event.getPersonId(), false); } - private void addLinkIdToActual(Id event) { - if (!firstLeg) { + @Override + public void handleEvent(PersonEntersVehicleEvent event) { + this.currentPersonByVehicle.put(event.getVehicleId(), event.getPersonId()); + this.onFirstLeg.putIfAbsent(event.getPersonId(), true); + } + + private void addLinkIdToActual(Id personId, Id linkId) { + if (!this.onFirstLeg.get(personId)) { + return; + } + actual.putIfAbsent(personId, Lists.newArrayList(linkId)); + List> linkIds = actual.get(personId); + if (linkIds.getLast() == null || linkIds.getLast() == linkId) { return; } - actual.add(event); + linkIds.add(linkId); } public void assertActualEqualsExpected() { @@ -143,8 +229,13 @@ public void assertActualEqualsExpected() { } public void assertActualContainsExpected() { - Assertions.assertTrue(actual.containsAll(expected)); + for (Map.Entry, List>> entry : expected.entrySet()) { + Id personId = entry.getKey(); + List> expected = entry.getValue(); + List> actual = this.actual.get(personId); + Assertions.assertNotNull(actual); + Assertions.assertTrue(actual.containsAll(expected)); + } } } - } diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link15.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link15.xml index c00caacf2eb..6954bb5cc9f 100644 --- a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link15.xml +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link15.xml @@ -1,7 +1,7 @@ - + diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link20.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link20.xml index af3ad532919..59e9cca0fa6 100644 --- a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link20.xml +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link20.xml @@ -1,7 +1,7 @@ - + diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link6.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link6.xml index 493ec731e73..b3a6f94ec31 100644 --- a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link6.xml +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link6.xml @@ -1,7 +1,7 @@ - + From 02d389f84247b4e4247def39cb77e8c5d0adf050 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Mon, 1 Jul 2024 18:09:21 +0200 Subject: [PATCH 005/111] implement multiple mode test --- .../org/matsim/core/network/NetworkUtils.java | 2 +- .../network/algorithms/NetworkCleaner.java | 4 +- .../io/PopulationReaderMatsimV6.java | 1 + .../core/router/NetworkRoutingModule.java | 2 + .../org/matsim/core/router/PlanRouter.java | 11 -- .../algorithms/NetworkCleanerTest.java | 2 +- .../matsim/examples/ModeRestrictionTest.java | 144 ++++++++++++------ .../examples/ModeRestrictionTest/config.xml | 5 + .../examples/ModeRestrictionTest/network.xml | 46 +++--- .../ModeRestrictionTest/plans_act_link15.xml | 54 ++++--- .../ModeRestrictionTest/plans_act_link20.xml | 54 ++++--- .../ModeRestrictionTest/plans_act_link6.xml | 54 ++++--- .../examples/ModeRestrictionTest/vehicles.xml | 35 +++++ 13 files changed, 275 insertions(+), 139 deletions(-) create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/vehicles.xml diff --git a/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java b/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java index 9e98fbe2269..895bf932cee 100644 --- a/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java +++ b/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java @@ -1018,7 +1018,7 @@ public static boolean addDisallowedNextLinks(Link link, String mode, List, Node> searchBiggestCluster(Network network) { return biggestCluster; } - /** + /** * Reducing the network so it only contains nodes included in the biggest Cluster. * Loop over all nodes and check if they are in the cluster, if not, remove them from the network */ @@ -157,7 +157,7 @@ public static void reduceToBiggestCluster(Network network, Map, Node> b network.getLinks().size() + " links."); log.info("done."); } - + @Override public void run(final Network network) { Map, Node> biggestCluster = this.searchBiggestCluster(network); diff --git a/matsim/src/main/java/org/matsim/core/population/io/PopulationReaderMatsimV6.java b/matsim/src/main/java/org/matsim/core/population/io/PopulationReaderMatsimV6.java index 725ffb83654..54447776f4d 100644 --- a/matsim/src/main/java/org/matsim/core/population/io/PopulationReaderMatsimV6.java +++ b/matsim/src/main/java/org/matsim/core/population/io/PopulationReaderMatsimV6.java @@ -461,6 +461,7 @@ private void startRoute(final Attributes atts) { if ("pt".equals(legMode)) { routeType = "experimentalPt1"; } else if ("car".equals(legMode)) { + //yyyy couldn't we check against all network modes of config here? paul, jul '24 routeType = "links"; } else { routeType = "generic"; diff --git a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingModule.java b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingModule.java index 5380f45d47d..de8b8d4ace3 100644 --- a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingModule.java +++ b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingModule.java @@ -81,11 +81,13 @@ public List calcRoute(RoutingRequest request) { Link fromLink = this.network.getLinks().get(fromFacility.getLinkId()); if ( fromLink==null ) { + //if an activity takes place on a link which is not part of the modal network, use coord as fallback Gbl.assertNotNull( fromFacility.getCoord() ) ; fromLink = NetworkUtils.getNearestLink( network, fromFacility.getCoord()) ; } Link toLink = this.network.getLinks().get(toFacility.getLinkId()); if ( toLink==null ) { + //if an activity takes place on a link which is not part of the modal network, use coord as fallback Gbl.assertNotNull( toFacility.getCoord() ) ; toLink = NetworkUtils.getNearestLink(network, toFacility.getCoord()); } diff --git a/matsim/src/main/java/org/matsim/core/router/PlanRouter.java b/matsim/src/main/java/org/matsim/core/router/PlanRouter.java index 2e96a046a94..f52b9a85169 100644 --- a/matsim/src/main/java/org/matsim/core/router/PlanRouter.java +++ b/matsim/src/main/java/org/matsim/core/router/PlanRouter.java @@ -71,17 +71,6 @@ public PlanRouter( final TripRouter routingHandler, final TimeInterpretation tim this( routingHandler , null, timeInterpretation ); } -// /** -// * Gives access to the {@link TripRouter} used -// * to compute routes. -// * -// * @return the internal TripRouter instance. -// */ -// @Deprecated // get TripRouter out of injection instead. kai, feb'16 -// public TripRouter getTripRouter() { -// return tripRouter; -// } - @Override public void run(final Plan plan) { final List trips = TripStructureUtils.getTrips( plan ); diff --git a/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkCleanerTest.java b/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkCleanerTest.java index 4e98d28fe4a..b60c8052c73 100644 --- a/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkCleanerTest.java +++ b/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkCleanerTest.java @@ -197,7 +197,7 @@ void testDoubleSource() { /** * This test essentially does the same by modifying the equil scenario. * Visualization: - * /... ...\ + * /... ...\ * ------o------------o------------o----------- * l1 (n2) l6 (n7) l15 (n12) l20 */ diff --git a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java index c14d0a7563e..9dbfbc89050 100644 --- a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java +++ b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java @@ -4,12 +4,14 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.Assertions; -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; +import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.events.LinkEnterEvent; import org.matsim.api.core.v01.events.LinkLeaveEvent; import org.matsim.api.core.v01.events.PersonEntersVehicleEvent; @@ -23,19 +25,22 @@ import org.matsim.api.core.v01.population.Leg; import org.matsim.api.core.v01.population.Person; import org.matsim.core.config.Config; +import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; +import org.matsim.core.router.util.TravelTime; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.Vehicle; import java.util.*; +import java.util.stream.Stream; // @formatter:off /** * In this test, we restrict the allowed modes of a link. The base case is the equil scenario. *

- * /... ...\ + * /... ...\ * ------o------------o------------o----------- * l1 (n2) l6 (n7) l15 (n12) l20 */ @@ -46,102 +51,106 @@ public class ModeRestrictionTest { @RegisterExtension private MatsimTestUtils utils = new MatsimTestUtils(); + static Stream provideArguments() { + List links = List.of("6", "15", "20"); + List restrictedModes = List.of("car", "bike"); + + return links.stream() + .flatMap(link -> restrictedModes.stream().map(restrictedMode -> Arguments.of(link, restrictedMode))); + } + /** - * Setting: The agent has a route from the plan. Link before and at the activity is restricted respectively. + * Setting: The agents (both car & bike) have a route from the plan. Link before and at the activity is restricted respectively. * Expected behaviour: Since it is not checked, if the route contains link, which are not allowed to use anymore, it can still use the restricted link. */ @ParameterizedTest - @ValueSource(strings = {"6", "15", "20"}) - void testNoRouteChange_ok(String link) { - final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml"); - config.plans().setInputFile("plans_act_link20.xml"); - config.controller().setLastIteration(0); + @MethodSource("provideArguments") + void testNoRouteChange_ok(String link, String restrictedMode) { + final Config config = prepareConfig("plans_act_link20.xml"); Id linkId = Id.createLinkId(link); Scenario scenario = ScenarioUtils.loadScenario(config); - scenario.getNetwork().getLinks().get(linkId).setAllowedModes(Set.of()); + Link networkLink = scenario.getNetwork().getLinks().get(linkId); + removeModeFromLink(networkLink, restrictedMode); - FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(Id.createPersonId("car"), linkId); + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck( + Map.of(Id.createPersonId("car"), List.of(linkId), Id.createPersonId("bike"), List.of(linkId))); runController(scenario, firstLegRouteCheck); firstLegRouteCheck.assertActualContainsExpected(); } /** - * Setting: The agent has no route. The mode of the link in front of the activity is restricted. + * Setting: The agents (both car & bike) have no route. The mode of the link in front of the activity is restricted. * Expected behaviour: By default, the network is not cleaned. The router throws an exception since there is no route from home to the activity. */ - @Test - void testRerouteBeforeSim_toActNotPossible_throws() { - final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml"); - config.plans().setInputFile("plans_act_link15.xml"); - config.controller().setLastIteration(0); + @ParameterizedTest + @ValueSource(strings = {"car", "bike"}) + void testRerouteBeforeSim_toActNotPossible_throws(String restrictedMode) { + final Config config = prepareConfig("plans_act_link15.xml"); Id link = Id.createLinkId("6"); - Id person = Id.createPersonId("car"); - Scenario scenario = restrictLinkAndResetRoute(config, link, person); + Scenario scenario = restrictLinkAndResetRoutes(config, link, restrictedMode); - FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(person, link); + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(); RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runController(scenario, firstLegRouteCheck)); Assertions.assertTrue( exception.getMessage().contains("Exception while processing persons. Cannot guarantee that all persons have been fully processed.")); } /** - * Setting: The agent has no route. The mode of the link behind the activity is restricted. + * Setting: The agents (both car & bike) have no route. The mode of the link behind the activity is restricted. * Expected behaviour: By default, the network is not cleaned. The router throws an exception since there is no route from the activity to home. */ - @Test - void testRerouteBeforeSim_fromActNotPossible_throws() { - final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml"); - config.plans().setInputFile("plans_act_link6.xml"); - config.controller().setLastIteration(0); + @ParameterizedTest + @ValueSource(strings = {"car", "bike"}) + void testRerouteBeforeSim_fromActNotPossible_throws(String restrictedMode) { + final Config config = prepareConfig("plans_act_link6.xml"); Id link = Id.createLinkId("15"); - Id person = Id.createPersonId("car"); - Scenario scenario = restrictLinkAndResetRoute(config, link, person); + Scenario scenario = restrictLinkAndResetRoutes(config, link, restrictedMode); - FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(person, link); + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(); RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runController(scenario, firstLegRouteCheck)); Assertions.assertTrue( exception.getMessage().contains("Exception while processing persons. Cannot guarantee that all persons have been fully processed.")); } /** - * Setting: The agent has no route. The mode of the activity's link is restricted. Activity has x-y-coordinate. - * Expected behaviour: The agent is rerouted to the nearest link to the activity's coordinate. + * Setting: The agents (both car & bike) have no route. The mode of the activity's link is restricted. Activity has x-y-coordinate. + * Expected behaviour: The agents (both car & bike) are rerouted to the nearest link to the activity's coordinate. */ - @Test - void testRerouteBeforeSim_actOnRestrictedLinkWithCoords_ok() { - final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml"); - config.plans().setInputFile("plans_act_link15.xml"); - config.controller().setLastIteration(0); + @ParameterizedTest + @ValueSource(strings = {"car", "bike"}) + void testRerouteBeforeSim_actOnRestrictedLinkWithCoords_ok(String restrictedMode) { + final Config config = prepareConfig("plans_act_link15.xml"); - Id person = Id.createPersonId("car"); - Scenario scenario = restrictLinkAndResetRoute(config, Id.createLinkId("15"), person); + Scenario scenario = restrictLinkAndResetRoutes(config, Id.createLinkId("15"), restrictedMode); // New route. Note that the end link is 20, but the activity's link in the input was 15. // But since we restricted the mode for link 15, 20 is used as fallback. List> newRoute = List.of(Id.createLinkId("1"), Id.createLinkId("2"), Id.createLinkId("11"), Id.createLinkId("20")); + List> oldRoute = List.of(Id.createLinkId("1"), Id.createLinkId("6"), Id.createLinkId("15")); + + String other = restrictedMode.equals("car") ? "bike" : "car"; - FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(person, newRoute); + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(Map.of(Id.createPersonId(restrictedMode), newRoute, Id.createPersonId(other), oldRoute)); runController(scenario, firstLegRouteCheck); firstLegRouteCheck.assertActualEqualsExpected(); } /** - * Setting: The agent has no route. The mode of the activity's link is restricted. Activity has no x-y-coordinate. + * Setting: The agents (both car & bike) have no route. The mode of the activity's link is restricted. Activity has no x-y-coordinate. * Expected behaviour: The router throws an exception since there is no fallback x-y-coordinate. */ - @Test - void testRerouteBeforeSim_actOnRestrictedLinkWithoutCoord_throws(){ - final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml"); - config.plans().setInputFile("plans_act_link15.xml"); - config.controller().setLastIteration(0); + @ParameterizedTest + @ValueSource(strings = {"car", "bike"}) + void testRerouteBeforeSim_actOnRestrictedLinkWithoutCoord_throws(String restrictedMode){ + final Config config = prepareConfig("plans_act_link15.xml"); - Id person = Id.createPersonId("car"); - Scenario scenario = restrictLinkAndResetRoute(config, Id.createLinkId("15"), person); + Id person = Id.createPersonId(restrictedMode); + Scenario scenario = restrictLinkAndResetRoutes(config, Id.createLinkId("15"), restrictedMode); Activity act = (Activity) scenario.getPopulation().getPersons().get(person).getPlans().getFirst().getPlanElements().get(2); act.setCoord(null); @@ -150,11 +159,28 @@ void testRerouteBeforeSim_actOnRestrictedLinkWithoutCoord_throws(){ exception.getMessage().contains("Exception while processing persons. Cannot guarantee that all persons have been fully processed.")); } - private static Scenario restrictLinkAndResetRoute(Config config, Id link, Id person) { + private Config prepareConfig(String plansFile) { + final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml"); + config.plans().setInputFile(plansFile); + + ScoringConfigGroup.ModeParams params = new ScoringConfigGroup.ModeParams("bike") ; + config.scoring().addModeParams(params); + + config.qsim().setMainModes( new HashSet<>( Arrays.asList( TransportMode.car, TransportMode.bike ) ) ) ; + config.routing().setNetworkModes( Arrays.asList( TransportMode.car, TransportMode.bike ) ); + config.routing().removeTeleportedModeParams("bike"); + + config.controller().setLastIteration(0); + return config; + } + + private static Scenario restrictLinkAndResetRoutes(Config config, Id link, String restrictedMode) { Scenario scenario = ScenarioUtils.loadScenario(config); - scenario.getNetwork().getLinks().get(link).setAllowedModes(Set.of()); - Leg leg = (Leg) scenario.getPopulation().getPersons().get(person).getSelectedPlan().getPlanElements().get(1); - leg.setRoute(null); + removeModeFromLink(scenario.getNetwork().getLinks().get(link), restrictedMode); + for (Person person : scenario.getPopulation().getPersons().values()) { + Leg leg = (Leg) person.getSelectedPlan().getPlanElements().get(1); + leg.setRoute(null); + } return scenario; } @@ -164,11 +190,18 @@ private static void runController(Scenario scenario, FirstLegVisitedLinksCheck f @Override public void install() { this.addEventHandlerBinding().toInstance(firstLegRouteCheck); + this.addTravelTimeBinding(TransportMode.bike).to(BikeTravelTime.class); } }); controler.run(); } + private static void removeModeFromLink(Link networkLink, String restrictedMode) { + Set allowedModes = new HashSet<>(networkLink.getAllowedModes()); + allowedModes.remove(restrictedMode); + networkLink.setAllowedModes(allowedModes); + } + /** * Event handler that checks the visited Links of a person on the first leg. */ @@ -182,6 +215,10 @@ private static class FirstLegVisitedLinksCheck implements LinkEnterEventHandler, public FirstLegVisitedLinksCheck() { } + public FirstLegVisitedLinksCheck(Map, List>> expected) { + this.expected.putAll(expected); + } + public FirstLegVisitedLinksCheck(Id personId, List> expected) { this.expected.put(personId, expected); } @@ -238,4 +275,11 @@ public void assertActualContainsExpected() { } } } + + + private static class BikeTravelTime implements TravelTime { + @Override public double getLinkTravelTime( Link link, double time, Person person, Vehicle vehicle ){ + return 1. ; + } + } } diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/config.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/config.xml index 3cd923f11dc..b61e26d25d8 100755 --- a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/config.xml +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/config.xml @@ -23,6 +23,7 @@ + @@ -65,6 +66,10 @@ + + + + diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/network.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/network.xml index 1f98124e31a..e62e521bf50 100644 --- a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/network.xml +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/network.xml @@ -20,28 +20,28 @@ - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link15.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link15.xml index 6954bb5cc9f..72ac9cf223b 100644 --- a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link15.xml +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link15.xml @@ -1,17 +1,37 @@ - - - - - - - - 2 7 - - - - 12 13 14 15 1 - - - - - + + + + + + + + + 1 6 15 + + + + 15 20 21 22 23 1 + + + + + + + + + + bike + + 1 6 15 + + + + + bike + + 15 20 21 22 23 1 + + + + + diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link20.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link20.xml index 59e9cca0fa6..6209ab27a8f 100644 --- a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link20.xml +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link20.xml @@ -1,17 +1,37 @@ - - - - - - - - 2 7 12 - - - - 13 14 15 1 - - - - - + + + + + + + + + 1 6 15 20 + + + + 20 21 22 23 1 + + + + + + + + + + bike + + 1 6 15 20 + + + + + bike + + 20 21 22 23 1 + + + + + diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link6.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link6.xml index b3a6f94ec31..d8bdcd6ec12 100644 --- a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link6.xml +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/plans_act_link6.xml @@ -1,17 +1,37 @@ - - - - - - - - 2 - - - - 7 12 13 14 15 1 - - - - - + + + + + + + + + 1 6 + + + + 6 15 20 21 22 23 1 + + + + + + + + + + bike + + 1 6 + + + + + bike + + 6 15 20 21 22 23 1 + + + + + diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/vehicles.xml b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/vehicles.xml new file mode 100644 index 00000000000..f38bea12f30 --- /dev/null +++ b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/vehicles.xml @@ -0,0 +1,35 @@ + + + + + + + bike + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 3671fe60a3beb75b73598f56cce9212c04689768 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Tue, 2 Jul 2024 15:15:28 +0200 Subject: [PATCH 006/111] implement option for network inconsistency check; no test adaptation so far --- .../config/groups/ControllerConfigGroup.java | 19 ++ .../core/controler/PrepareForSimImpl.java | 13 +- .../network/algorithms/NetworkCleaner.java | 4 +- .../algorithms/PersonPrepareForSim.java | 279 ++++++++++-------- .../core/router/NetworkRoutingProvider.java | 28 +- .../org/matsim/core/router/TripRouter.java | 35 ++- .../core/controler/PrepareForSimImplTest.java | 3 +- .../algorithms/PersonPrepareForSimTest.java | 122 ++++++-- 8 files changed, 330 insertions(+), 173 deletions(-) rename matsim/src/test/java/org/matsim/{ => core}/population/algorithms/PersonPrepareForSimTest.java (84%) diff --git a/matsim/src/main/java/org/matsim/core/config/groups/ControllerConfigGroup.java b/matsim/src/main/java/org/matsim/core/config/groups/ControllerConfigGroup.java index c84d9eee16c..c2739cc28da 100644 --- a/matsim/src/main/java/org/matsim/core/config/groups/ControllerConfigGroup.java +++ b/matsim/src/main/java/org/matsim/core/config/groups/ControllerConfigGroup.java @@ -58,6 +58,10 @@ public enum CleanIterations { delete, } + public enum NetworkConsistencyCheck { + disable, fixWithWarning, abortOnInconsistency + } + public static final String GROUP_NAME = "controller"; private static final String OUTPUT_DIRECTORY = "outputDirectory"; @@ -81,6 +85,8 @@ public enum CleanIterations { private static final String MEMORY_OBSERVER_INTERVAL = "memoryObserverInterval"; + private static final String NETWORK_CONSISTENCY_CHECK = "networkConsistencyCheck"; + /*package*/ static final String MOBSIM = "mobsim"; public enum MobsimType {qsim, JDEQSim, hermes} @@ -113,6 +119,8 @@ public enum MobsimType {qsim, JDEQSim, hermes} private int memoryObserverInterval = 60; + private NetworkConsistencyCheck networkConsistencyCheck = NetworkConsistencyCheck.fixWithWarning; + public ControllerConfigGroup() { super(GROUP_NAME); } @@ -156,6 +164,7 @@ public final Map getComments() { map.put(DUMP_DATA_AT_END, "true if at the end of a run, plans, network, config etc should be dumped to a file"); map.put(CLEAN_ITERS_AT_END, "Defines what should be done with the ITERS directory when a simulation finished successfully"); map.put(MEMORY_OBSERVER_INTERVAL, "Defines the interval for printing memory usage to the log in [seconds]. Must be positive. Defaults to 60."); + map.put(NETWORK_CONSISTENCY_CHECK, "Defines whether the network consistency should be checked. If enabled, the network cleaner is run and inconsistent routes are removed."); return map; } @@ -443,6 +452,16 @@ public void setMemoryObserverInterval(int memoryObserverInterval) { this.memoryObserverInterval = memoryObserverInterval; } + @StringGetter(NETWORK_CONSISTENCY_CHECK) + public NetworkConsistencyCheck getNetworkConsistencyCheck() { + return networkConsistencyCheck; + } + + @StringSetter(NETWORK_CONSISTENCY_CHECK) + public void setNetworkConsistencyCheck(NetworkConsistencyCheck networkConsistencyCheck) { + this.networkConsistencyCheck = networkConsistencyCheck; + } + // --- int writePlansUntilIteration = 1 ; public int getWritePlansUntilIteration() { diff --git a/matsim/src/main/java/org/matsim/core/controler/PrepareForSimImpl.java b/matsim/src/main/java/org/matsim/core/controler/PrepareForSimImpl.java index 359a812887a..fc9be952cc3 100644 --- a/matsim/src/main/java/org/matsim/core/controler/PrepareForSimImpl.java +++ b/matsim/src/main/java/org/matsim/core/controler/PrepareForSimImpl.java @@ -34,11 +34,8 @@ import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.Population; -import org.matsim.core.config.groups.FacilitiesConfigGroup; -import org.matsim.core.config.groups.GlobalConfigGroup; -import org.matsim.core.config.groups.PlansConfigGroup; +import org.matsim.core.config.groups.*; import org.matsim.core.config.groups.PlansConfigGroup.HandlingOfPlansWithoutRoutingMode; -import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.gbl.Gbl; import org.matsim.core.network.NetworkUtils; import org.matsim.core.network.algorithms.TransportModeNetworkFilter; @@ -331,6 +328,11 @@ private void createAndAddVehicleIfNecessary(Id vehicleId, VehicleType v private static boolean insistingOnPlansWithoutRoutingModeLogWarnNotShownYet = true; + /** + * Make sure that each leg has a routing mode. + * Legs with outdated fallback modes will be treated in a special way. + * Legs with no routing mode will have their network mode as routing mode. + */ private void adaptOutdatedPlansForRoutingMode() { for (Person person : population.getPersons().values()) { for (Plan plan : person.getPlans()) { @@ -369,8 +371,7 @@ private void adaptOutdatedPlansForRoutingMode() { // there is only a single leg (e.g. after Trips2Legs and a mode choice replanning // module) - String oldMainMode = replaceOutdatedFallbackModesAndReturnOldMainMode(legs.get(0), - null); + String oldMainMode = replaceOutdatedFallbackModesAndReturnOldMainMode(legs.get(0), null); if (oldMainMode != null) { routingMode = oldMainMode; TripStructureUtils.setRoutingMode(legs.get(0), routingMode); diff --git a/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkCleaner.java b/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkCleaner.java index 202bb86d95a..99315e01535 100644 --- a/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkCleaner.java +++ b/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkCleaner.java @@ -112,7 +112,7 @@ private Map, Node> findCluster(final Node startNode, final Network netw /** * Searches the biggest cluster in the given Network. The Network is not modified. */ - public Map, Node> searchBiggestCluster(Network network) { + private Map, Node> searchBiggestCluster(Network network) { final Map, Node> visitedNodes = new TreeMap<>(); Map, Node> biggestCluster = new TreeMap<>(); @@ -146,7 +146,7 @@ public Map, Node> searchBiggestCluster(Network network) { * Reducing the network so it only contains nodes included in the biggest Cluster. * Loop over all nodes and check if they are in the cluster, if not, remove them from the network */ - public static void reduceToBiggestCluster(Network network, Map, Node> biggestCluster) { + private static void reduceToBiggestCluster(Network network, Map, Node> biggestCluster) { List allNodes2 = new ArrayList<>(network.getNodes().values()); for (Node node : allNodes2) { if (!biggestCluster.containsKey(node.getId())) { diff --git a/matsim/src/main/java/org/matsim/core/population/algorithms/PersonPrepareForSim.java b/matsim/src/main/java/org/matsim/core/population/algorithms/PersonPrepareForSim.java index cef472de8c9..e5bfce80dd9 100644 --- a/matsim/src/main/java/org/matsim/core/population/algorithms/PersonPrepareForSim.java +++ b/matsim/src/main/java/org/matsim/core/population/algorithms/PersonPrepareForSim.java @@ -40,8 +40,8 @@ import org.matsim.pt.routes.DefaultTransitPassengerRoute; import org.matsim.pt.routes.ExperimentalTransitRoute; -import java.util.HashSet; import java.util.List; +import java.util.Set; /** * Performs several checks that persons are ready for a mobility simulation. @@ -59,12 +59,11 @@ public final class PersonPrepareForSim extends AbstractPersonAlgorithm { private final PlanAlgorithm router; private final XY2Links xy2links; - private final Network carOnlyNetwork; private final ActivityFacilities activityFacilities; private static final Logger log = LogManager.getLogger(PersonPrepareForSim.class); private final Scenario scenario; - + /* * To be used by the controller which creates multiple instances of this class which would * create multiple copies of a car-only-network. Instead, we can create that network once in @@ -73,7 +72,6 @@ public final class PersonPrepareForSim extends AbstractPersonAlgorithm { public PersonPrepareForSim(final PlanAlgorithm router, final Scenario scenario, final Network carOnlyNetwork) { super(); this.router = router; - this.carOnlyNetwork = carOnlyNetwork ; if (NetworkUtils.isMultimodal(carOnlyNetwork)) { throw new RuntimeException("Expected carOnlyNetwork not to be multi-modal. Aborting!"); } @@ -81,19 +79,16 @@ public PersonPrepareForSim(final PlanAlgorithm router, final Scenario scenario, this.activityFacilities = scenario.getActivityFacilities(); this.scenario = scenario ; } - + public PersonPrepareForSim(final PlanAlgorithm router, final Scenario scenario) { super(); this.router = router; - this.carOnlyNetwork = scenario.getNetwork(); - Network net = this.carOnlyNetwork; - if (NetworkUtils.isMultimodal( carOnlyNetwork )) { + Network net = scenario.getNetwork(); + if (NetworkUtils.isMultimodal( scenario.getNetwork() )) { log.info("Network seems to be multimodal. XY2Links will only use car links."); - TransportModeNetworkFilter filter = new TransportModeNetworkFilter( carOnlyNetwork ); + TransportModeNetworkFilter filter = new TransportModeNetworkFilter( scenario.getNetwork() ); net = NetworkUtils.createNetwork(scenario.getConfig().network()); - HashSet modes = new HashSet(); - modes.add(TransportMode.car); - filter.filter(net, modes); + filter.filter(net, Set.of(TransportMode.car)); } this.xy2links = new XY2Links(net, scenario.getActivityFacilities()); @@ -110,121 +105,32 @@ public void run(final Person person) { log.warn("Person " + person.getId() + " has no plans!"); return; } - + // yyyyyy need to find out somewhere here if the access/egress legs of the incoming plans // are consistent with the config setting. Otherwise need to re-route all of them. kai, jul'18 - // make sure all the plans have valid act-locations and valid routes for (Plan plan : person.getPlans()) { boolean needsXY2Links = false; boolean needsReRoute = false; - - // for backward compatibility: add routingMode to legs if not present - for (Trip trip : TripStructureUtils.getTrips(plan.getPlanElements())) { - List legs = trip.getLegsOnly(); - if (legs.size() >= 1) { - String routingMode = TripStructureUtils.getRoutingMode(legs.get(0)); - - for (Leg leg : legs) { - // check all legs either have the same routing mode or all have routingMode==null - String existingRoutingMode = TripStructureUtils.getRoutingMode(leg); - if (existingRoutingMode == null) { - if (routingMode == null) { - // outdated initial plan without routingMode - } else { - String errorMessage = "Found a mixed trip, some legs with routingMode and others without. " - + "This is inconsistent. Agent id: " + person.getId().toString(); - log.error(errorMessage); - throw new RuntimeException(errorMessage); - } - } else { - if (!routingMode.equals(existingRoutingMode)) { - String errorMessage = "Found a trip whose legs have different routingModes. " - + "This is inconsistent. Agent id: " + person.getId().toString(); - log.error(errorMessage); - throw new RuntimeException(errorMessage); - } - } - } - // add routing mode - if (routingMode == null) { - if (legs.size() == 1) { - // there is only a single leg (e.g. after Trips2Legs and a mode choice replanning module) - routingMode = legs.get(0).getMode(); - if (routingMode.equals(TransportMode.transit_walk)) { - String errorMessage = "Found a trip of only one leg of mode transit_walk. " - + "This should not happen during simulation since transit_walk was replaced by walk and " - + "routingMode. Agent id: " + person.getId().toString(); - log.error(errorMessage); - throw new RuntimeException(errorMessage); - } - TripStructureUtils.setRoutingMode(legs.get(0), routingMode); - } else { - String errorMessage = "Found a trip whose legs have no routingMode. " - + "This is only allowed for (outdated) input plans, not during simulation (after PrepareForSim). Agent id: " - + person.getId().toString(); - log.error(errorMessage); - throw new RuntimeException(errorMessage); - } - } - } - } - - for (PlanElement pe : plan.getPlanElements()) { - if (pe instanceof Activity) { - Activity act = (Activity) pe; - if ( act.getLinkId() == null // neither activity nor facility has a link - && - //this check is necessary here, else, XY2Links will put the link/coord back to activity which is clear violation of facilitiesConfigGroup.removingLinksAndCoordinates =true. Amit July'18 - ( act.getFacilityId() == null - || this.activityFacilities.getFacilities().isEmpty() - || this.activityFacilities.getFacilities().get(act.getFacilityId()) == null - || this.activityFacilities.getFacilities().get(act.getFacilityId()).getLinkId() == null) - ) { - needsXY2Links = true; + // for backward compatibility: add routingMode to legs if not present + checkAndAddRoutingMode(plan); + + // make sure all the plans have valid act-locations and valid routes + planLoop: for (PlanElement pe : plan.getPlanElements()) { + switch (pe) { + case Activity act -> { + boolean needsReComputation = needsReComputation(act); + if (needsReComputation) { + needsXY2Links = true; needsReRoute = true; - break; - } - } else if (pe instanceof Leg) { - Leg leg = (Leg) pe; - - if (TripStructureUtils.getRoutingMode(leg) == null) { - String errorMessage = "Routing mode not set for leg :" + leg.toString() + " of agent id " + person.getId().toString(); - log.error( errorMessage ); - throw new RuntimeException( errorMessage ); - } - - if (leg.getRoute() == null) { - needsReRoute = true; - } else if (Double.isNaN(leg.getRoute().getDistance())){ - Double dist = null; - if (leg.getRoute() instanceof NetworkRoute){ - /* So far, 1.0 is always used as relative position on start and end link. - * This means that the end link is considered in route distance and the start link not. - * tt feb'16 - */ - double relativePositionStartLink = scenario.getConfig().global().getRelativePositionOfEntryExitOnLink() ; - double relativePositionEndLink = scenario.getConfig().global().getRelativePositionOfEntryExitOnLink() ; -// dist = RouteUtils.calcDistance((NetworkRoute) leg.getRoute(), relativePositionStartLink, relativePositionEndLink, this.network); - dist = RouteUtils.calcDistance((NetworkRoute) leg.getRoute(), relativePositionStartLink, relativePositionEndLink, scenario.getNetwork() ); - // using the full network for the distance calculation. kai, jul'18 - } else if (leg.getRoute() instanceof ExperimentalTransitRoute) { - // replace deprecated ExperimentalTransitRoute with DefaultTransitPassengerRoute - ExperimentalTransitRoute oldRoute = (ExperimentalTransitRoute) leg.getRoute(); - DefaultTransitPassengerRoute newRoute = new DefaultTransitPassengerRoute( - oldRoute.getStartLinkId(), - oldRoute.getEndLinkId(), - oldRoute.getAccessStopId(), - oldRoute.getEgressStopId(), - oldRoute.getLineId(), - oldRoute.getRouteId()); - leg.setRoute(newRoute); - } - if (dist != null){ - leg.getRoute().setDistance(dist); + break planLoop; } } + case Leg leg -> { + needsReRoute |= needsReRoute(person, leg); + } + default -> throw new IllegalStateException("Unexpected PlanElement: " + pe); } } if (needsXY2Links) { @@ -237,4 +143,143 @@ public void run(final Person person) { } + private boolean needsReRoute(Person person, Leg leg) { + if (TripStructureUtils.getRoutingMode(leg) == null) { + String errorMessage = "Routing mode not set for leg :" + leg + " of agent id " + person.getId().toString(); + log.error( errorMessage ); + throw new RuntimeException( errorMessage ); + } + + if (leg.getRoute() == null) { + return true; + } + + if (!isLegModeConsistent(person, leg)){ + return true; + } + + if(!Double.isNaN(leg.getRoute().getDistance())){ + return false; + } + + adaptRoute(leg); + + return false; + } + + private void adaptRoute(Leg leg) { + if (leg.getRoute() instanceof NetworkRoute){ + /* So far, 1.0 is always used as relative position on start and end link. + * This means that the end link is considered in route distance and the start link not. + * tt feb'16 + */ + double relativePositionStartLink = scenario.getConfig().global().getRelativePositionOfEntryExitOnLink() ; + double relativePositionEndLink = scenario.getConfig().global().getRelativePositionOfEntryExitOnLink() ; +// dist = RouteUtils.calcDistance((NetworkRoute) leg.getRoute(), relativePositionStartLink, relativePositionEndLink, this.network); + double dist = RouteUtils.calcDistance((NetworkRoute) leg.getRoute(), relativePositionStartLink, relativePositionEndLink, scenario.getNetwork() ); + leg.getRoute().setDistance(dist); + // using the full network for the distance calculation. kai, jul'18 + } else if (leg.getRoute() instanceof ExperimentalTransitRoute) { + // replace deprecated ExperimentalTransitRoute with DefaultTransitPassengerRoute + ExperimentalTransitRoute oldRoute = (ExperimentalTransitRoute) leg.getRoute(); + DefaultTransitPassengerRoute newRoute = new DefaultTransitPassengerRoute( + oldRoute.getStartLinkId(), + oldRoute.getEndLinkId(), + oldRoute.getAccessStopId(), + oldRoute.getEgressStopId(), + oldRoute.getLineId(), + oldRoute.getRouteId()); + leg.setRoute(newRoute); + } + } + + private boolean isLegModeConsistent(Person person, Leg leg) { + if(!(leg.getRoute() instanceof NetworkRoute networkRoute)) { + return true; + } + + boolean linkModesConsistent = networkRoute.getLinkIds().stream() + .map(l -> scenario.getNetwork().getLinks().get(l)) + .allMatch(l -> l.getAllowedModes().contains(leg.getMode())); + + switch (this.scenario.getConfig().controller().getNetworkConsistencyCheck()) { + case disable -> { + return true; + } + case fixWithWarning -> { + if(!linkModesConsistent) { + log.warn("Trigger reroute due to inconsistent modes for: Person {}; Leg '{}'", person.getId(), leg); + } + } + case abortOnInconsistency -> { + if(!linkModesConsistent) { + throw new RuntimeException("Route inconsistent with link modes for: Person " + person.getId() + "; Leg '" + leg + "'"); + } + } + } + return linkModesConsistent; + } + + private boolean needsReComputation(Activity act) { + return act.getLinkId() == null // neither activity nor facility has a link + && + //this check is necessary here, else, XY2Links will put the link/coord back to activity which is clear violation of facilitiesConfigGroup.removingLinksAndCoordinates =true. Amit July'18 + (act.getFacilityId() == null + || this.activityFacilities.getFacilities().isEmpty() + || this.activityFacilities.getFacilities().get(act.getFacilityId()) == null + || this.activityFacilities.getFacilities().get(act.getFacilityId()).getLinkId() == null); + } + + private void checkAndAddRoutingMode(Plan plan) { + for (Trip trip : TripStructureUtils.getTrips(plan.getPlanElements())) { + List legs = trip.getLegsOnly(); + if (!legs.isEmpty()) { + String routingMode = TripStructureUtils.getRoutingMode(legs.get(0)); + + for (Leg leg : legs) { + // check all legs either have the same routing mode or all have routingMode==null + String existingRoutingMode = TripStructureUtils.getRoutingMode(leg); + if (existingRoutingMode == null) { + if (routingMode == null) { + // outdated initial plan without routingMode + } else { + String errorMessage = "Found a mixed trip, some legs with routingMode and others without. " + + "This is inconsistent. Agent id: " + plan.getPerson().getId().toString(); + log.error(errorMessage); + throw new RuntimeException(errorMessage); + } + } else { + if (!routingMode.equals(existingRoutingMode)) { + String errorMessage = "Found a trip whose legs have different routingModes. " + + "This is inconsistent. Agent id: " + plan.getPerson().getId().toString(); + log.error(errorMessage); + throw new RuntimeException(errorMessage); + } + } + } + + // add routing mode + if (routingMode == null) { + if (legs.size() == 1) { + // there is only a single leg (e.g. after Trips2Legs and a mode choice replanning module) + routingMode = legs.get(0).getMode(); + if (routingMode.equals(TransportMode.transit_walk)) { + String errorMessage = "Found a trip of only one leg of mode transit_walk. " + + "This should not happen during simulation since transit_walk was replaced by walk and " + + "routingMode. Agent id: " + plan.getPerson().getId().toString(); + log.error(errorMessage); + throw new RuntimeException(errorMessage); + } + TripStructureUtils.setRoutingMode(legs.get(0), routingMode); + } else { + String errorMessage = "Found a trip whose legs have no routingMode. " + + "This is only allowed for (outdated) input plans, not during simulation (after PrepareForSim). Agent id: " + + plan.getPerson().getId().toString(); + log.error(errorMessage); + throw new RuntimeException(errorMessage); + } + } + } + } + } } diff --git a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java index 667764861ca..d960f2bbd43 100644 --- a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java +++ b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java @@ -29,9 +29,11 @@ import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.network.Network; import org.matsim.api.core.v01.population.PopulationFactory; +import org.matsim.core.config.groups.ControllerConfigGroup; import org.matsim.core.config.groups.NetworkConfigGroup; import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.network.NetworkUtils; +import org.matsim.core.network.algorithms.NetworkCleaner; import org.matsim.core.network.algorithms.TransportModeNetworkFilter; import org.matsim.core.router.costcalculators.TravelDisutilityFactory; import org.matsim.core.router.util.LeastCostPathCalculator; @@ -50,13 +52,13 @@ public class NetworkRoutingProvider implements Provider{ private final String routingMode; + @Inject + ControllerConfigGroup controllerConfigGroup; @Inject Map travelTimes; @Inject Map travelDisutilityFactories; @Inject SingleModeNetworksCache singleModeNetworksCache; @Inject RoutingConfigGroup routingConfigGroup; - @Inject Network network; - @Inject NetworkConfigGroup networkConfigGroup; @Inject PopulationFactory populationFactory; @Inject LeastCostPathCalculatorFactory leastCostPathCalculatorFactory; @Inject Scenario scenario ; @@ -101,6 +103,21 @@ public RoutingModule get() { // the network refers to the (transport)mode: Network filteredNetwork = singleModeNetworksCache.getOrCreateSingleModeNetwork(mode); + switch (controllerConfigGroup.getNetworkConsistencyCheck()) { + case disable -> { + } + case fixWithWarning -> { + if (cleanNetwork(filteredNetwork)) { + log.warn("Network for mode '{}' has unreachable links and nodes. They were removed for routing. This may be caused by mode restrictions on certain links.", mode); + } + } + case abortOnInconsistency -> { + if (cleanNetwork(filteredNetwork)) { + throw new RuntimeException("Network for mode '"+mode+"' has unreachable links and nodes. This may be caused by mode restrictions on certain links. Aborting."); + } + } + } + // the travel time & disutility refer to the routing mode: TravelDisutilityFactory travelDisutilityFactory = this.travelDisutilityFactories.get(routingMode); if (travelDisutilityFactory == null) { @@ -138,4 +155,11 @@ public RoutingModule get() { return DefaultRoutingModules.createPureNetworkRouter(mode, populationFactory, filteredNetwork, routeAlgo); } } + + private boolean cleanNetwork(Network filteredNetwork) { + int nLinks = filteredNetwork.getLinks().size(); + int nNodes = filteredNetwork.getNodes().size(); + new NetworkCleaner().run(filteredNetwork); + return nLinks != filteredNetwork.getLinks().size() || nNodes != filteredNetwork.getNodes().size(); + } } diff --git a/matsim/src/main/java/org/matsim/core/router/TripRouter.java b/matsim/src/main/java/org/matsim/core/router/TripRouter.java index ac39295ebe8..84769313c86 100644 --- a/matsim/src/main/java/org/matsim/core/router/TripRouter.java +++ b/matsim/src/main/java/org/matsim/core/router/TripRouter.java @@ -169,26 +169,25 @@ public synchronized List calcRoute( RoutingModule module = routingModules.get( mainMode ); - if (module != null) { - RoutingRequest request = DefaultRoutingRequest.of( - fromFacility, - toFacility, - departureTime, - person, - routingAttributes); - - List trip = module.calcRoute(request); - - if ( trip == null ) { - trip = fallbackRoutingModule.calcRoute(request) ; - } - for (Leg leg: TripStructureUtils.getLegs(trip)) { - TripStructureUtils.setRoutingMode(leg, mainMode); - } - return trip; + if (module == null) { + throw new UnknownModeException( "unregistered main mode |"+mainMode+"|: does not pertain to "+routingModules.keySet() ); } + RoutingRequest request = DefaultRoutingRequest.of( + fromFacility, + toFacility, + departureTime, + person, + routingAttributes); + + List trip = module.calcRoute(request); - throw new UnknownModeException( "unregistered main mode |"+mainMode+"|: does not pertain to "+routingModules.keySet() ); + if ( trip == null ) { + trip = fallbackRoutingModule.calcRoute(request) ; + } + for (Leg leg: TripStructureUtils.getLegs(trip)) { + TripStructureUtils.setRoutingMode(leg, mainMode); + } + return trip; } public static class UnknownModeException extends RuntimeException { diff --git a/matsim/src/test/java/org/matsim/core/controler/PrepareForSimImplTest.java b/matsim/src/test/java/org/matsim/core/controler/PrepareForSimImplTest.java index af9ec71a41b..5f0e60dd990 100644 --- a/matsim/src/test/java/org/matsim/core/controler/PrepareForSimImplTest.java +++ b/matsim/src/test/java/org/matsim/core/controler/PrepareForSimImplTest.java @@ -829,7 +829,7 @@ public List calcRoute(RoutingRequest request) { } } - private Link createAndAddNetwork(Scenario sc) { + private void createAndAddNetwork(Scenario sc) { Network net = sc.getNetwork(); Link link1; { @@ -851,6 +851,5 @@ private Link createAndAddNetwork(Scenario sc) { net.addLink(link1); net.addLink(l2); } - return link1; } } diff --git a/matsim/src/test/java/org/matsim/population/algorithms/PersonPrepareForSimTest.java b/matsim/src/test/java/org/matsim/core/population/algorithms/PersonPrepareForSimTest.java similarity index 84% rename from matsim/src/test/java/org/matsim/population/algorithms/PersonPrepareForSimTest.java rename to matsim/src/test/java/org/matsim/core/population/algorithms/PersonPrepareForSimTest.java index baec9afc911..b2ec1a9cd90 100644 --- a/matsim/src/test/java/org/matsim/population/algorithms/PersonPrepareForSimTest.java +++ b/matsim/src/test/java/org/matsim/core/population/algorithms/PersonPrepareForSimTest.java @@ -17,9 +17,10 @@ * * * *********************************************************************** */ -package org.matsim.population.algorithms; +package org.matsim.core.population.algorithms; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.junit.jupiter.api.Assertions; @@ -38,11 +39,13 @@ import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.Population; import org.matsim.api.core.v01.population.PopulationFactory; +import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.ControllerConfigGroup; import org.matsim.core.controler.PrepareForSimImpl; import org.matsim.core.population.PopulationUtils; -import org.matsim.core.population.algorithms.PersonPrepareForSim; -import org.matsim.core.population.algorithms.PlanAlgorithm; +import org.matsim.core.population.routes.NetworkRoute; +import org.matsim.core.population.routes.RouteUtils; import org.matsim.core.router.TripStructureUtils; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.pt.routes.DefaultTransitPassengerRoute; @@ -144,9 +147,7 @@ void testSingleLegTripRoutingMode() { new PersonPrepareForSim(new DummyRouter(), sc).run(person); - Assertions.assertEquals(TransportMode.pt, - TripStructureUtils.getRoutingMode(leg), - "wrong routing mode!"); + Assertions.assertEquals(TransportMode.pt, TripStructureUtils.getRoutingMode(leg),"wrong routing mode!"); } // test routing mode set @@ -167,9 +168,7 @@ void testSingleLegTripRoutingMode() { new PersonPrepareForSim(new DummyRouter(), sc).run(person); - Assertions.assertEquals(TransportMode.pt, - TripStructureUtils.getRoutingMode(leg), - "wrong routing mode!"); + Assertions.assertEquals(TransportMode.pt, TripStructureUtils.getRoutingMode(leg),"wrong routing mode!"); } } @@ -203,10 +202,7 @@ void testSingleFallbackModeLegTrip() { person.addPlan(plan); pop.addPerson(person); - try { - new PersonPrepareForSim(new DummyRouter(), sc).run(person); - Assertions.fail("expected Exception, got none."); - } catch (RuntimeException expected) {} + Assertions.assertThrows(RuntimeException.class, () -> new PersonPrepareForSim(new DummyRouter(), sc).run(person)); } // test outdated fallback mode single leg trip (arbitrary drt mode) @@ -228,9 +224,7 @@ void testSingleFallbackModeLegTrip() { new PersonPrepareForSim(new DummyRouter(), sc).run(person); Assertions.assertEquals("drt67_fallback", leg.getMode(), "wrong leg mode replacement"); - Assertions.assertEquals("drt67_fallback", - TripStructureUtils.getRoutingMode(leg), - "wrong routing mode set"); + Assertions.assertEquals("drt67_fallback", TripStructureUtils.getRoutingMode(leg),"wrong routing mode set"); } } @@ -368,6 +362,9 @@ void testRoutingModeConsistency() { Population pop = sc.getPopulation(); // test trip with inconsistent routing modes causes exception + // modes: walk - drt - walk + // routing modes: pt - drt - drt + // expected behaviour: throws RuntimeException, because routing modes are inconsistent { PopulationFactory pf = pop.getFactory(); Person person = pf.createPerson(Id.create("3", Person.class)); @@ -392,13 +389,13 @@ void testRoutingModeConsistency() { person.addPlan(plan); pop.addPerson(person); - try { - new PersonPrepareForSim(new DummyRouter(), sc).run(person); - Assertions.fail("expected Exception, got none."); - } catch (RuntimeException expected) {} + Assertions.assertThrows(RuntimeException.class, () -> new PersonPrepareForSim(new DummyRouter(), sc).run(person)); } // test trip with legs with and others without routing modes causes exception + // modes: walk - drt - walk + // routing modes: null - drt - drt + // expected behaviour: throws RuntimeException, because routing modes are inconsistent { PopulationFactory pf = pop.getFactory(); Person person = pf.createPerson(Id.create("4", Person.class)); @@ -423,10 +420,7 @@ void testRoutingModeConsistency() { person.addPlan(plan); pop.addPerson(person); - try { - new PersonPrepareForSim(new DummyRouter(), sc).run(person); - Assertions.fail("expected Exception, got none."); - } catch (RuntimeException expected) {} + Assertions.assertThrows(RuntimeException.class, () -> new PersonPrepareForSim(new DummyRouter(), sc).run(person)); } } @@ -478,13 +472,90 @@ void testReplaceExperimentalTransitRoute() { Assertions.assertEquals(route, ((DefaultTransitPassengerRoute) leg.getRoute()).getRouteId()); } + @Test + void testLegModeConsistency_ok() { + // set config, such that router is called due to inconsistency + Config config = ConfigUtils.createConfig(); + config.controller().setNetworkConsistencyCheck(ControllerConfigGroup.NetworkConsistencyCheck.fixWithWarning); + Scenario scenario = ScenarioUtils.createScenario(config); + Person person = createInconsistentPersonForModeConsistencyCheck(scenario); + + DummyRouter router = new DummyRouter(); + new PersonPrepareForSim(router, scenario).run(person); + // check router call + Assertions.assertEquals(1, router.getCounter()); + } + + @Test + void testLegModeConsistency_throws() { + // set config, such that exception is thrown due to inconsistency + Config config = ConfigUtils.createConfig(); + config.controller().setNetworkConsistencyCheck(ControllerConfigGroup.NetworkConsistencyCheck.abortOnInconsistency); + Scenario scenario = ScenarioUtils.createScenario(config); + Person person = createInconsistentPersonForModeConsistencyCheck(scenario); + + // check exception + Assertions.assertThrows(RuntimeException.class, () -> new PersonPrepareForSim(new DummyRouter(), scenario).run(person)); + } + + @Test + void testLegModeConsistency_ignored() { + // set config, such that inconsistency is ignored + Config config = ConfigUtils.createConfig(); + config.controller().setNetworkConsistencyCheck(ControllerConfigGroup.NetworkConsistencyCheck.disable); + Scenario scenario = ScenarioUtils.createScenario(config); + Person person = createInconsistentPersonForModeConsistencyCheck(scenario); + + DummyRouter router = new DummyRouter(); + new PersonPrepareForSim(router, scenario).run(person); + // check no router call + Assertions.assertEquals(0, router.getCounter()); + } + + /** + * Creates a person with one leg, that has mode pt, but route goes over link with only mode car. + */ + private Person createInconsistentPersonForModeConsistencyCheck(Scenario scenario) { + createAndAddNetwork(scenario); + + Population pop = scenario.getPopulation(); + PopulationFactory pf = pop.getFactory(); + Person person = pf.createPerson(Id.create("1", Person.class)); + Plan plan = pf.createPlan(); + + Id l1Id = Id.createLinkId("1"); + Activity act1 = pf.createActivityFromLinkId("home", l1Id); + // Leg mode is pt, but route goes over links with car mode + Leg leg = pf.createLeg(TransportMode.pt); + NetworkRoute route = RouteUtils.createLinkNetworkRouteImpl(l1Id, List.of(l1Id), l1Id); + leg.setRoute(route); + Activity act2 = pf.createActivityFromLinkId("home", l1Id); + plan.addActivity(act1); + plan.addLeg(leg); + plan.addActivity(act2); + person.addPlan(plan); + return person; + } + private static class DummyRouter implements PlanAlgorithm { + private int counter = 0; @Override public void run(final Plan plan) { + counter++; + } + + public int getCounter() { + return counter; } } - private Link createAndAddNetwork(Scenario sc) { + /** + * Creates Network: + * (n1)---l1---(n2)---l2---(n3) + * l1 modes: car + * l2 modes: pt + */ + private void createAndAddNetwork(Scenario sc) { Network net = sc.getNetwork(); Link link1; { @@ -506,6 +577,5 @@ private Link createAndAddNetwork(Scenario sc) { net.addLink(link1); net.addLink(l2); } - return link1; } } From 08729b0eb9ba97544a3e213a90e81471402e5755 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Wed, 3 Jul 2024 14:13:33 +0200 Subject: [PATCH 007/111] implemented network changer --- .../config/groups/ControllerConfigGroup.java | 22 +-- .../org/matsim/core/network/NetworkUtils.java | 12 ++ .../network/algorithms/NetworkCleaner.java | 4 +- .../algorithms/NetworkModeChanger.java | 85 +++++++++++ .../algorithms/PersonPrepareForSim.java | 30 ++-- .../core/router/NetworkRoutingProvider.java | 32 ++-- .../algorithms/NetworkModeChangerTest.java | 140 ++++++++++++++++++ .../algorithms/PersonPrepareForSimTest.java | 22 +-- .../matsim/examples/ModeRestrictionTest.java | 12 +- 9 files changed, 282 insertions(+), 77 deletions(-) create mode 100644 matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeChanger.java create mode 100644 matsim/src/test/java/org/matsim/core/network/algorithms/NetworkModeChangerTest.java diff --git a/matsim/src/main/java/org/matsim/core/config/groups/ControllerConfigGroup.java b/matsim/src/main/java/org/matsim/core/config/groups/ControllerConfigGroup.java index c2739cc28da..e9a361434d7 100644 --- a/matsim/src/main/java/org/matsim/core/config/groups/ControllerConfigGroup.java +++ b/matsim/src/main/java/org/matsim/core/config/groups/ControllerConfigGroup.java @@ -58,8 +58,8 @@ public enum CleanIterations { delete, } - public enum NetworkConsistencyCheck { - disable, fixWithWarning, abortOnInconsistency + public enum NetworkRouteConsistencyCheck { + disable, abortOnInconsistency } public static final String GROUP_NAME = "controller"; @@ -85,7 +85,7 @@ public enum NetworkConsistencyCheck { private static final String MEMORY_OBSERVER_INTERVAL = "memoryObserverInterval"; - private static final String NETWORK_CONSISTENCY_CHECK = "networkConsistencyCheck"; + private static final String NETWORK_ROUTE_CONSISTENCY_CHECK = "networkConsistencyCheck"; /*package*/ static final String MOBSIM = "mobsim"; public enum MobsimType {qsim, JDEQSim, hermes} @@ -119,7 +119,7 @@ public enum MobsimType {qsim, JDEQSim, hermes} private int memoryObserverInterval = 60; - private NetworkConsistencyCheck networkConsistencyCheck = NetworkConsistencyCheck.fixWithWarning; + private NetworkRouteConsistencyCheck networkRouteConsistencyCheck = NetworkRouteConsistencyCheck.abortOnInconsistency; public ControllerConfigGroup() { super(GROUP_NAME); @@ -164,7 +164,7 @@ public final Map getComments() { map.put(DUMP_DATA_AT_END, "true if at the end of a run, plans, network, config etc should be dumped to a file"); map.put(CLEAN_ITERS_AT_END, "Defines what should be done with the ITERS directory when a simulation finished successfully"); map.put(MEMORY_OBSERVER_INTERVAL, "Defines the interval for printing memory usage to the log in [seconds]. Must be positive. Defaults to 60."); - map.put(NETWORK_CONSISTENCY_CHECK, "Defines whether the network consistency should be checked. If enabled, the network cleaner is run and inconsistent routes are removed."); + map.put(NETWORK_ROUTE_CONSISTENCY_CHECK, "Defines whether the network consistency should be checked. If enabled, the network cleaner is run and inconsistent routes are removed."); return map; } @@ -452,14 +452,14 @@ public void setMemoryObserverInterval(int memoryObserverInterval) { this.memoryObserverInterval = memoryObserverInterval; } - @StringGetter(NETWORK_CONSISTENCY_CHECK) - public NetworkConsistencyCheck getNetworkConsistencyCheck() { - return networkConsistencyCheck; + @StringGetter(NETWORK_ROUTE_CONSISTENCY_CHECK) + public NetworkRouteConsistencyCheck getNetworkRouteConsistencyCheck() { + return networkRouteConsistencyCheck; } - @StringSetter(NETWORK_CONSISTENCY_CHECK) - public void setNetworkConsistencyCheck(NetworkConsistencyCheck networkConsistencyCheck) { - this.networkConsistencyCheck = networkConsistencyCheck; + @StringSetter(NETWORK_ROUTE_CONSISTENCY_CHECK) + public void setNetworkRouteConsistencyCheck(NetworkRouteConsistencyCheck networkRouteConsistencyCheck) { + this.networkRouteConsistencyCheck = networkRouteConsistencyCheck; } // --- diff --git a/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java b/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java index 895bf932cee..a2e4693b4e5 100644 --- a/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java +++ b/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java @@ -1022,4 +1022,16 @@ public static boolean addDisallowedNextLinks(Link link, String mode, List modes = new HashSet<>(link.getAllowedModes()); + modes.add(mode); + link.setAllowedModes(modes); + } + + public static void removeAllowedMode(Link link, String mode) { + Set modes = new HashSet<>(link.getAllowedModes()); + modes.remove(mode); + link.setAllowedModes(modes); + } } diff --git a/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkCleaner.java b/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkCleaner.java index 99315e01535..9df6cd6d896 100644 --- a/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkCleaner.java +++ b/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkCleaner.java @@ -75,7 +75,7 @@ private Map, Node> findCluster(final Node startNode, final Network netw pendingBackward.add(startNode); // step through the network in forward mode - while (pendingForward.size() > 0) { + while (!pendingForward.isEmpty()) { int idx = pendingForward.size() - 1; Node currNode = pendingForward.remove(idx); // get the last element to prevent object shifting in the array for (Link link : currNode.getOutLinks().values()) { @@ -89,7 +89,7 @@ private Map, Node> findCluster(final Node startNode, final Network netw } // now step through the network in backward mode - while (pendingBackward.size() > 0) { + while (!pendingBackward.isEmpty()) { int idx = pendingBackward.size()-1; Node currNode = pendingBackward.remove(idx); // get the last element to prevent object shifting in the array for (Link link : currNode.getInLinks().values()) { diff --git a/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeChanger.java b/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeChanger.java new file mode 100644 index 00000000000..bbadec73ce6 --- /dev/null +++ b/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeChanger.java @@ -0,0 +1,85 @@ +package org.matsim.core.network.algorithms; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.network.Node; +import org.matsim.core.api.internal.NetworkRunnable; +import org.matsim.core.network.NetworkUtils; + +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * This class changes the allowed modes of links in a network and cleans the network afterward. + * I.e. for each mode, it removes by running the {@link NetworkCleaner} that mode for links, that are not reachable from all other links + * or from which all other links are not reachable. + */ +public class NetworkModeChanger implements NetworkRunnable { + private static final Logger log = LogManager.getLogger(NetworkModeChanger.class); + + private final Map, Set> changes; + + public NetworkModeChanger(Map, Set> changes) { + this.changes = changes; + } + + @Override + public void run(Network network) { + applyModeChanges(network); + cleanNetworkPerMode(network); + removeLinksWithNoModes(network); + removeNodesWithNoLinks(network); + } + + private void applyModeChanges(Network network) { + for (Map.Entry, Set> entry : changes.entrySet()) { + Link link = network.getLinks().get(entry.getKey()); + link.setAllowedModes(entry.getValue()); + } + } + + private void cleanNetworkPerMode(Network network) { + Set modes = network.getLinks().values().stream().flatMap(l -> l.getAllowedModes().stream()).collect(Collectors.toSet()); + for (String mode : modes) { + cleanNetworkForMode(network, mode); + } + } + + private void cleanNetworkForMode(Network network, String mode) { + TransportModeNetworkFilter filter = new TransportModeNetworkFilter(network); + Network modalSubNetwork = NetworkUtils.createNetwork(); + filter.filter(modalSubNetwork, Set.of(mode)); + + log.info("Cleaning network for mode: {}", mode); + int sizeBeforeCleaning = modalSubNetwork.getLinks().size(); + new NetworkCleaner().run(modalSubNetwork); + int sizeAfterCleaning = modalSubNetwork.getLinks().size(); + log.info("Removed mode {} from {} links.", mode, sizeBeforeCleaning - sizeAfterCleaning); + + //remove mode from links that are not in the modal subnetwork + for (Link link : network.getLinks().values()) { + if (Objects.isNull(modalSubNetwork.getLinks().get(link.getId()))) { + NetworkUtils.removeAllowedMode(link, mode); + } + } + } + + private void removeLinksWithNoModes(Network network) { + network.getLinks().values().stream() + .filter(l -> l.getAllowedModes().isEmpty()) + .map(Link::getId) + .forEach(network::removeLink); + } + + private void removeNodesWithNoLinks(Network network) { + network.getNodes().values().stream() + .filter(n -> n.getInLinks().isEmpty() && n.getOutLinks().isEmpty()) + .map(Node::getId) + .forEach(network::removeNode); + } +} diff --git a/matsim/src/main/java/org/matsim/core/population/algorithms/PersonPrepareForSim.java b/matsim/src/main/java/org/matsim/core/population/algorithms/PersonPrepareForSim.java index e5bfce80dd9..f6b316b6c02 100644 --- a/matsim/src/main/java/org/matsim/core/population/algorithms/PersonPrepareForSim.java +++ b/matsim/src/main/java/org/matsim/core/population/algorithms/PersonPrepareForSim.java @@ -30,6 +30,7 @@ import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.PlanElement; +import org.matsim.core.config.groups.ControllerConfigGroup; import org.matsim.core.network.NetworkUtils; import org.matsim.core.network.algorithms.TransportModeNetworkFilter; import org.matsim.core.population.routes.NetworkRoute; @@ -154,9 +155,7 @@ private boolean needsReRoute(Person person, Leg leg) { return true; } - if (!isLegModeConsistent(person, leg)){ - return true; - } + checkModeConsistent(person, leg); if(!Double.isNaN(leg.getRoute().getDistance())){ return false; @@ -193,31 +192,22 @@ private void adaptRoute(Leg leg) { } } - private boolean isLegModeConsistent(Person person, Leg leg) { + private void checkModeConsistent(Person person, Leg leg) { + if(this.scenario.getConfig().controller().getNetworkRouteConsistencyCheck() == ControllerConfigGroup.NetworkRouteConsistencyCheck.disable) { + return; + } + if(!(leg.getRoute() instanceof NetworkRoute networkRoute)) { - return true; + return; } boolean linkModesConsistent = networkRoute.getLinkIds().stream() .map(l -> scenario.getNetwork().getLinks().get(l)) .allMatch(l -> l.getAllowedModes().contains(leg.getMode())); - switch (this.scenario.getConfig().controller().getNetworkConsistencyCheck()) { - case disable -> { - return true; - } - case fixWithWarning -> { - if(!linkModesConsistent) { - log.warn("Trigger reroute due to inconsistent modes for: Person {}; Leg '{}'", person.getId(), leg); - } - } - case abortOnInconsistency -> { - if(!linkModesConsistent) { - throw new RuntimeException("Route inconsistent with link modes for: Person " + person.getId() + "; Leg '" + leg + "'"); - } - } + if(!linkModesConsistent){ + throw new RuntimeException("Route inconsistent with link modes for: Person " + person.getId() + "; Leg '" + leg + "'"); } - return linkModesConsistent; } private boolean needsReComputation(Activity act) { diff --git a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java index d960f2bbd43..3b71a8de64e 100644 --- a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java +++ b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java @@ -30,11 +30,8 @@ import org.matsim.api.core.v01.network.Network; import org.matsim.api.core.v01.population.PopulationFactory; import org.matsim.core.config.groups.ControllerConfigGroup; -import org.matsim.core.config.groups.NetworkConfigGroup; import org.matsim.core.config.groups.RoutingConfigGroup; -import org.matsim.core.network.NetworkUtils; import org.matsim.core.network.algorithms.NetworkCleaner; -import org.matsim.core.network.algorithms.TransportModeNetworkFilter; import org.matsim.core.router.costcalculators.TravelDisutilityFactory; import org.matsim.core.router.util.LeastCostPathCalculator; import org.matsim.core.router.util.LeastCostPathCalculatorFactory; @@ -43,9 +40,7 @@ import com.google.inject.name.Named; -import java.util.HashSet; import java.util.Map; -import java.util.Set; public class NetworkRoutingProvider implements Provider{ private static final Logger log = LogManager.getLogger( NetworkRoutingProvider.class ) ; @@ -103,20 +98,7 @@ public RoutingModule get() { // the network refers to the (transport)mode: Network filteredNetwork = singleModeNetworksCache.getOrCreateSingleModeNetwork(mode); - switch (controllerConfigGroup.getNetworkConsistencyCheck()) { - case disable -> { - } - case fixWithWarning -> { - if (cleanNetwork(filteredNetwork)) { - log.warn("Network for mode '{}' has unreachable links and nodes. They were removed for routing. This may be caused by mode restrictions on certain links.", mode); - } - } - case abortOnInconsistency -> { - if (cleanNetwork(filteredNetwork)) { - throw new RuntimeException("Network for mode '"+mode+"' has unreachable links and nodes. This may be caused by mode restrictions on certain links. Aborting."); - } - } - } + checkNetwork(filteredNetwork); // the travel time & disutility refer to the routing mode: TravelDisutilityFactory travelDisutilityFactory = this.travelDisutilityFactories.get(routingMode); @@ -156,10 +138,18 @@ public RoutingModule get() { } } - private boolean cleanNetwork(Network filteredNetwork) { + private void checkNetwork(Network filteredNetwork) { + if(controllerConfigGroup.getNetworkRouteConsistencyCheck() == ControllerConfigGroup.NetworkRouteConsistencyCheck.disable) { + return; + } + int nLinks = filteredNetwork.getLinks().size(); int nNodes = filteredNetwork.getNodes().size(); new NetworkCleaner().run(filteredNetwork); - return nLinks != filteredNetwork.getLinks().size() || nNodes != filteredNetwork.getNodes().size(); + boolean changed = nLinks != filteredNetwork.getLinks().size() || nNodes != filteredNetwork.getNodes().size(); + + if(changed) { + throw new RuntimeException("Network for mode '"+mode+"' has unreachable links and nodes. This may be caused by mode restrictions on certain links. Aborting."); + } } } diff --git a/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkModeChangerTest.java b/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkModeChangerTest.java new file mode 100644 index 00000000000..bcfc8606be1 --- /dev/null +++ b/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkModeChangerTest.java @@ -0,0 +1,140 @@ +package org.matsim.core.network.algorithms; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +// @formatter:off +/** + * In this test, we restrict the allowed modes of a link. The base case is the equil scenario. + *

+ * /... ...\ + * ------o------------o------------o----------- + * l1 (n2) l6 (n7) l15 (n12) l20 + */ +// @formatter:on +class NetworkModeChangerTest { + + /** + * Test that all links and nodes are removed if the network is not connected any more for every mode. + */ + @Test + void testRemoveWholeNetwork() { + Network network = getNetwork(); + + Map, Set> changes = new HashMap<>(); + changes.put(Id.createLinkId(1), Set.of()); + + new NetworkModeChanger(changes).run(network); + + assertTrue(network.getLinks().isEmpty()); + assertTrue(network.getNodes().isEmpty()); + } + + /** + * Test that mode is removed from each node if there it is not connected any more for this mode. + */ + @ParameterizedTest + @ValueSource(strings = {"car", "bike"}) + void testRemoveWholeMode(String mode) { + Network network = getNetwork(); + + int linksBefore = network.getLinks().size(); + int nodesBefore = network.getNodes().size(); + + Map, Set> changes = new HashMap<>(); + changes.put(Id.createLinkId(1), Set.of(mode)); + + new NetworkModeChanger(changes).run(network); + + assertEquals(linksBefore, network.getLinks().size()); + assertEquals(nodesBefore, network.getNodes().size()); + + Assertions.assertTrue(network.getLinks().values().stream() + .allMatch(l -> l.getAllowedModes().size() == 1 && l.getAllowedModes().contains(mode))); + } + + /** + * Test that removing a mode from link 6 or 15 also removes it from the other link. + */ + @ParameterizedTest + @CsvSource({"6,car", "6,bike", "15,car", "15,bike"}) + void testRemoveModePartially(int link, String mode) { + Network network = getNetwork(); + + int linksBefore = network.getLinks().size(); + int nodesBefore = network.getNodes().size(); + + //prepare removal + Map, Set> changes = new HashMap<>(); + changes.put(Id.createLinkId(link), Set.of(mode)); + + //remove + new NetworkModeChanger(changes).run(network); + + //links and nodes should all still be there + assertEquals(linksBefore, network.getLinks().size()); + assertEquals(nodesBefore, network.getNodes().size()); + + Set link6Modes = network.getLinks().get(Id.createLinkId(6)).getAllowedModes(); + Set link15Modes = network.getLinks().get(Id.createLinkId(15)).getAllowedModes(); + + //link 6 and 15 should have the mode removed + Assertions.assertEquals(1, link6Modes.size()); + Assertions.assertEquals(1, link15Modes.size()); + Assertions.assertTrue(link6Modes.contains(mode)); + Assertions.assertTrue(link15Modes.contains(mode)); + } + + /** + * Test that removing each mode from link 6 or 15 also removes both links at all. + */ + @ParameterizedTest + @ValueSource(ints = {6, 15}) + void testRemovePartialNetwork(int link) { + Network network = getNetwork(); + + int linksBefore = network.getLinks().size(); + int nodesBefore = network.getNodes().size(); + + //prepare removal + Map, Set> changes = new HashMap<>(); + changes.put(Id.createLinkId(link), Set.of()); + + //remove + new NetworkModeChanger(changes).run(network); + + //both links and the node in between should be removed + assertEquals(linksBefore - 2, network.getLinks().size()); + assertEquals(nodesBefore - 1, network.getNodes().size()); + + //check node + Assertions.assertNull(network.getNodes().get(Id.createNodeId(7))); + + //check links + Assertions.assertNull(network.getLinks().get(Id.createLinkId(6))); + Assertions.assertNull(network.getLinks().get(Id.createLinkId(15))); + } + + + private static Network getNetwork() { + Network network = NetworkUtils.readNetwork(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("equil"), "network.xml").toString()); + network.getLinks().values().forEach(l -> l.setAllowedModes(Set.of("car", "bike"))); + return network; + } +} diff --git a/matsim/src/test/java/org/matsim/core/population/algorithms/PersonPrepareForSimTest.java b/matsim/src/test/java/org/matsim/core/population/algorithms/PersonPrepareForSimTest.java index b2ec1a9cd90..556837c6d88 100644 --- a/matsim/src/test/java/org/matsim/core/population/algorithms/PersonPrepareForSimTest.java +++ b/matsim/src/test/java/org/matsim/core/population/algorithms/PersonPrepareForSimTest.java @@ -473,24 +473,10 @@ void testReplaceExperimentalTransitRoute() { } @Test - void testLegModeConsistency_ok() { - // set config, such that router is called due to inconsistency - Config config = ConfigUtils.createConfig(); - config.controller().setNetworkConsistencyCheck(ControllerConfigGroup.NetworkConsistencyCheck.fixWithWarning); - Scenario scenario = ScenarioUtils.createScenario(config); - Person person = createInconsistentPersonForModeConsistencyCheck(scenario); - - DummyRouter router = new DummyRouter(); - new PersonPrepareForSim(router, scenario).run(person); - // check router call - Assertions.assertEquals(1, router.getCounter()); - } - - @Test - void testLegModeConsistency_throws() { + void testLegRouteModeConsistency_throws() { // set config, such that exception is thrown due to inconsistency Config config = ConfigUtils.createConfig(); - config.controller().setNetworkConsistencyCheck(ControllerConfigGroup.NetworkConsistencyCheck.abortOnInconsistency); + config.controller().setNetworkRouteConsistencyCheck(ControllerConfigGroup.NetworkRouteConsistencyCheck.abortOnInconsistency); Scenario scenario = ScenarioUtils.createScenario(config); Person person = createInconsistentPersonForModeConsistencyCheck(scenario); @@ -499,10 +485,10 @@ void testLegModeConsistency_throws() { } @Test - void testLegModeConsistency_ignored() { + void testLegRouteModeConsistency_ignored() { // set config, such that inconsistency is ignored Config config = ConfigUtils.createConfig(); - config.controller().setNetworkConsistencyCheck(ControllerConfigGroup.NetworkConsistencyCheck.disable); + config.controller().setNetworkRouteConsistencyCheck(ControllerConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = ScenarioUtils.createScenario(config); Person person = createInconsistentPersonForModeConsistencyCheck(scenario); diff --git a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java index 9dbfbc89050..95b1e688f9d 100644 --- a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java +++ b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java @@ -25,6 +25,7 @@ import org.matsim.api.core.v01.population.Leg; import org.matsim.api.core.v01.population.Person; import org.matsim.core.config.Config; +import org.matsim.core.config.groups.ControllerConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; @@ -60,7 +61,7 @@ static Stream provideArguments() { } /** - * Setting: The agents (both car & bike) have a route from the plan. Link before and at the activity is restricted respectively. + * Setting: The agents (both car & bike) have a route from the plan. Link before and at the activity is restricted respectively. Consistency check is turned off. * Expected behaviour: Since it is not checked, if the route contains link, which are not allowed to use anymore, it can still use the restricted link. */ @ParameterizedTest @@ -80,7 +81,7 @@ void testNoRouteChange_ok(String link, String restrictedMode) { } /** - * Setting: The agents (both car & bike) have no route. The mode of the link in front of the activity is restricted. + * Setting: The agents (both car & bike) have no route. The mode of the link in front of the activity is restricted. Consistency check is turned off. * Expected behaviour: By default, the network is not cleaned. The router throws an exception since there is no route from home to the activity. */ @ParameterizedTest @@ -99,7 +100,7 @@ void testRerouteBeforeSim_toActNotPossible_throws(String restrictedMode) { } /** - * Setting: The agents (both car & bike) have no route. The mode of the link behind the activity is restricted. + * Setting: The agents (both car & bike) have no route. The mode of the link behind the activity is restricted. Consistency check is turned off. * Expected behaviour: By default, the network is not cleaned. The router throws an exception since there is no route from the activity to home. */ @ParameterizedTest @@ -118,7 +119,7 @@ void testRerouteBeforeSim_fromActNotPossible_throws(String restrictedMode) { } /** - * Setting: The agents (both car & bike) have no route. The mode of the activity's link is restricted. Activity has x-y-coordinate. + * Setting: The agents (both car & bike) have no route. The mode of the activity's link is restricted. Activity has x-y-coordinate. Consistency check is turned off. * Expected behaviour: The agents (both car & bike) are rerouted to the nearest link to the activity's coordinate. */ @ParameterizedTest @@ -141,7 +142,7 @@ void testRerouteBeforeSim_actOnRestrictedLinkWithCoords_ok(String restrictedMode } /** - * Setting: The agents (both car & bike) have no route. The mode of the activity's link is restricted. Activity has no x-y-coordinate. + * Setting: The agents (both car & bike) have no route. The mode of the activity's link is restricted. Activity has no x-y-coordinate. Consistency check is turned off. * Expected behaviour: The router throws an exception since there is no fallback x-y-coordinate. */ @ParameterizedTest @@ -161,6 +162,7 @@ void testRerouteBeforeSim_actOnRestrictedLinkWithoutCoord_throws(String restrict private Config prepareConfig(String plansFile) { final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml"); + config.controller().setNetworkRouteConsistencyCheck(ControllerConfigGroup.NetworkRouteConsistencyCheck.disable); config.plans().setInputFile(plansFile); ScoringConfigGroup.ModeParams params = new ScoringConfigGroup.ModeParams("bike") ; From a527e84f99ecf616a6822b2c14ed015259215e2b Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Wed, 3 Jul 2024 17:25:01 +0200 Subject: [PATCH 008/111] implement functionality in Util classes and moved config --- .../config/groups/ControllerConfigGroup.java | 19 ------- .../config/groups/RoutingConfigGroup.java | 22 ++++++- .../org/matsim/core/network/NetworkUtils.java | 11 ++++ ...anger.java => NetworkModeRestriction.java} | 57 ++++++++++--------- .../core/population/PopulationUtils.java | 13 +++++ .../algorithms/PersonPrepareForSim.java | 8 ++- .../algorithms/PersonRouteCheck.java | 43 ++++++++++++++ .../core/router/DefaultRoutingModules.java | 1 + .../core/router/NetworkRoutingModule.java | 1 + .../core/router/NetworkRoutingProvider.java | 9 +-- ...t.java => NetworkModeRestrictionTest.java} | 34 ++++++----- .../algorithms/PersonPrepareForSimTest.java | 6 +- .../matsim/examples/ModeRestrictionTest.java | 7 +-- 13 files changed, 153 insertions(+), 78 deletions(-) rename matsim/src/main/java/org/matsim/core/network/algorithms/{NetworkModeChanger.java => NetworkModeRestriction.java} (57%) create mode 100644 matsim/src/main/java/org/matsim/core/population/algorithms/PersonRouteCheck.java rename matsim/src/test/java/org/matsim/core/network/algorithms/{NetworkModeChangerTest.java => NetworkModeRestrictionTest.java} (79%) diff --git a/matsim/src/main/java/org/matsim/core/config/groups/ControllerConfigGroup.java b/matsim/src/main/java/org/matsim/core/config/groups/ControllerConfigGroup.java index e9a361434d7..c84d9eee16c 100644 --- a/matsim/src/main/java/org/matsim/core/config/groups/ControllerConfigGroup.java +++ b/matsim/src/main/java/org/matsim/core/config/groups/ControllerConfigGroup.java @@ -58,10 +58,6 @@ public enum CleanIterations { delete, } - public enum NetworkRouteConsistencyCheck { - disable, abortOnInconsistency - } - public static final String GROUP_NAME = "controller"; private static final String OUTPUT_DIRECTORY = "outputDirectory"; @@ -85,8 +81,6 @@ public enum NetworkRouteConsistencyCheck { private static final String MEMORY_OBSERVER_INTERVAL = "memoryObserverInterval"; - private static final String NETWORK_ROUTE_CONSISTENCY_CHECK = "networkConsistencyCheck"; - /*package*/ static final String MOBSIM = "mobsim"; public enum MobsimType {qsim, JDEQSim, hermes} @@ -119,8 +113,6 @@ public enum MobsimType {qsim, JDEQSim, hermes} private int memoryObserverInterval = 60; - private NetworkRouteConsistencyCheck networkRouteConsistencyCheck = NetworkRouteConsistencyCheck.abortOnInconsistency; - public ControllerConfigGroup() { super(GROUP_NAME); } @@ -164,7 +156,6 @@ public final Map getComments() { map.put(DUMP_DATA_AT_END, "true if at the end of a run, plans, network, config etc should be dumped to a file"); map.put(CLEAN_ITERS_AT_END, "Defines what should be done with the ITERS directory when a simulation finished successfully"); map.put(MEMORY_OBSERVER_INTERVAL, "Defines the interval for printing memory usage to the log in [seconds]. Must be positive. Defaults to 60."); - map.put(NETWORK_ROUTE_CONSISTENCY_CHECK, "Defines whether the network consistency should be checked. If enabled, the network cleaner is run and inconsistent routes are removed."); return map; } @@ -452,16 +443,6 @@ public void setMemoryObserverInterval(int memoryObserverInterval) { this.memoryObserverInterval = memoryObserverInterval; } - @StringGetter(NETWORK_ROUTE_CONSISTENCY_CHECK) - public NetworkRouteConsistencyCheck getNetworkRouteConsistencyCheck() { - return networkRouteConsistencyCheck; - } - - @StringSetter(NETWORK_ROUTE_CONSISTENCY_CHECK) - public void setNetworkRouteConsistencyCheck(NetworkRouteConsistencyCheck networkRouteConsistencyCheck) { - this.networkRouteConsistencyCheck = networkRouteConsistencyCheck; - } - // --- int writePlansUntilIteration = 1 ; public int getWritePlansUntilIteration() { diff --git a/matsim/src/main/java/org/matsim/core/config/groups/RoutingConfigGroup.java b/matsim/src/main/java/org/matsim/core/config/groups/RoutingConfigGroup.java index a693d0c0297..4311f61c707 100644 --- a/matsim/src/main/java/org/matsim/core/config/groups/RoutingConfigGroup.java +++ b/matsim/src/main/java/org/matsim/core/config/groups/RoutingConfigGroup.java @@ -91,8 +91,8 @@ public enum AccessEgressType { } private static final String ACCESSEGRESSTYPE = "accessEgressType"; - private static final String ACCESSEGRESSTYPE_CMT = "Defines how access and egress to main mode is simulated. Either of [none, accessEgressModeToLink, walkConstantTimeToLink, accessEgressModeToLinkPlusTimeConstant], Current default=none which means no access or egress trips are simulated."; - private AccessEgressType accessEgressType = AccessEgressType.none; + private static final String ACCESSEGRESSTYPE_CMT = "Defines how access and egress to main mode is simulated. Either of [none, accessEgressModeToLink, walkConstantTimeToLink, accessEgressModeToLinkPlusTimeConstant], Current default=accessEgressModeToLink which means walk over euclidean distance from nearest point on link to facility is simulated."; + private AccessEgressType accessEgressType = AccessEgressType.accessEgressModeToLink; // --- private static final String RANDOMNESS = "routingRandomness" ; @@ -104,6 +104,13 @@ public enum AccessEgressType { "settings for helper modes such as for " + TransportMode.non_network_walk; private boolean clearingDefaultModeRoutingParams = false ; + private static final String NETWORK_ROUTE_CONSISTENCY_CHECK = "networkRouteConsistencyCheck"; + private NetworkRouteConsistencyCheck networkRouteConsistencyCheck = NetworkRouteConsistencyCheck.abortOnInconsistency; + + public enum NetworkRouteConsistencyCheck { + disable, abortOnInconsistency + } + /** * @deprecated -- use {@link TeleportedModeParams} to be consistent with xml config. kai, jun'23 */ @@ -547,6 +554,7 @@ public final Map getComments() { + "Technically the width parameter of a log-normal distribution. 3.0 seems to be a good value. " ) ; map.put( CLEAR_MODE_ROUTING_PARAMS, CLEAR_MODE_ROUTING_PARAMS_CMT ) ; map.put(ACCESSEGRESSTYPE, ACCESSEGRESSTYPE_CMT); + map.put(NETWORK_ROUTE_CONSISTENCY_CHECK, "Defines whether the network consistency should be checked."); return map; } @@ -650,6 +658,16 @@ public void setRoutingRandomness(double routingRandomness) { this.routingRandomness = routingRandomness; } + @StringGetter(NETWORK_ROUTE_CONSISTENCY_CHECK) + public NetworkRouteConsistencyCheck getNetworkRouteConsistencyCheck() { + return networkRouteConsistencyCheck; + } + + @StringSetter(NETWORK_ROUTE_CONSISTENCY_CHECK) + public void setNetworkRouteConsistencyCheck(NetworkRouteConsistencyCheck networkRouteConsistencyCheck) { + this.networkRouteConsistencyCheck = networkRouteConsistencyCheck; + } + @Override protected void checkConsistency(Config config) { super.checkConsistency(config); Set modesRoutedAsTeleportation = this.getModeRoutingParams().keySet(); diff --git a/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java b/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java index a2e4693b4e5..1053e7516c2 100644 --- a/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java +++ b/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java @@ -38,6 +38,7 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.NetworkConfigGroup; import org.matsim.core.gbl.Gbl; +import org.matsim.core.network.algorithms.NetworkModeRestriction; import org.matsim.core.network.algorithms.NetworkSimplifier; import org.matsim.core.network.io.MatsimNetworkReader; import org.matsim.core.utils.geometry.CoordUtils; @@ -1034,4 +1035,14 @@ public static void removeAllowedMode(Link link, String mode) { modes.remove(mode); link.setAllowedModes(modes); } + + /** + * Removes the given modes from the links and runs the network cleaner afterwards. Thus, some more links may be restricted to keep the network consistent. + * That means, each link can be reached from each other link. + * @param network the network + * @param modesToRemoveByLinkId map of modes that should be removed from the links + */ + public static void restrictModesAndCleanNetwork(Network network, Map, Set> modesToRemoveByLinkId) { + new NetworkModeRestriction(modesToRemoveByLinkId).run(network); + } } diff --git a/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeChanger.java b/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeRestriction.java similarity index 57% rename from matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeChanger.java rename to matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeRestriction.java index bbadec73ce6..1372552520d 100644 --- a/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeChanger.java +++ b/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeRestriction.java @@ -10,7 +10,6 @@ import org.matsim.core.network.NetworkUtils; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -19,53 +18,42 @@ * I.e. for each mode, it removes by running the {@link NetworkCleaner} that mode for links, that are not reachable from all other links * or from which all other links are not reachable. */ -public class NetworkModeChanger implements NetworkRunnable { - private static final Logger log = LogManager.getLogger(NetworkModeChanger.class); +public class NetworkModeRestriction implements NetworkRunnable { + private static final Logger log = LogManager.getLogger(NetworkModeRestriction.class); - private final Map, Set> changes; + private final Map, Set> modesToRemoveByLinkId; - public NetworkModeChanger(Map, Set> changes) { - this.changes = changes; + public NetworkModeRestriction(Map, Set> modesToRemoveByLinkId) { + this.modesToRemoveByLinkId = modesToRemoveByLinkId; } @Override public void run(Network network) { + Map modeCountBefore = countModes(network); + applyModeChanges(network); cleanNetworkPerMode(network); removeLinksWithNoModes(network); removeNodesWithNoLinks(network); + + Map modeCountAfter = countModes(network); + logModeCountDifference(modeCountBefore, modeCountAfter); } private void applyModeChanges(Network network) { - for (Map.Entry, Set> entry : changes.entrySet()) { + for (Map.Entry, Set> entry : modesToRemoveByLinkId.entrySet()) { Link link = network.getLinks().get(entry.getKey()); - link.setAllowedModes(entry.getValue()); + for (String modeToRemove : entry.getValue()) { + NetworkUtils.removeAllowedMode(link, modeToRemove); + } } } private void cleanNetworkPerMode(Network network) { Set modes = network.getLinks().values().stream().flatMap(l -> l.getAllowedModes().stream()).collect(Collectors.toSet()); for (String mode : modes) { - cleanNetworkForMode(network, mode); - } - } - - private void cleanNetworkForMode(Network network, String mode) { - TransportModeNetworkFilter filter = new TransportModeNetworkFilter(network); - Network modalSubNetwork = NetworkUtils.createNetwork(); - filter.filter(modalSubNetwork, Set.of(mode)); - - log.info("Cleaning network for mode: {}", mode); - int sizeBeforeCleaning = modalSubNetwork.getLinks().size(); - new NetworkCleaner().run(modalSubNetwork); - int sizeAfterCleaning = modalSubNetwork.getLinks().size(); - log.info("Removed mode {} from {} links.", mode, sizeBeforeCleaning - sizeAfterCleaning); - - //remove mode from links that are not in the modal subnetwork - for (Link link : network.getLinks().values()) { - if (Objects.isNull(modalSubNetwork.getLinks().get(link.getId()))) { - NetworkUtils.removeAllowedMode(link, mode); - } + MultimodalNetworkCleaner multimodalNetworkCleaner = new MultimodalNetworkCleaner(network); + multimodalNetworkCleaner.run(Set.of(mode)); } } @@ -82,4 +70,17 @@ private void removeNodesWithNoLinks(Network network) { .map(Node::getId) .forEach(network::removeNode); } + + private void logModeCountDifference(Map modeCountBefore, Map modeCountAfter) { + modeCountBefore.forEach((mode, countBefore) -> { + long countAfter = modeCountAfter.getOrDefault(mode, 0L); + log.info("Removed mode {} from {} links.", mode, countBefore - countAfter); + }); + } + + private static Map countModes(Network network) { + return network.getLinks().values().stream() + .flatMap(l -> l.getAllowedModes().stream()) + .collect(Collectors.groupingBy(m -> m, Collectors.counting())); + } } diff --git a/matsim/src/main/java/org/matsim/core/population/PopulationUtils.java b/matsim/src/main/java/org/matsim/core/population/PopulationUtils.java index 5755982b6ed..5b62242de72 100644 --- a/matsim/src/main/java/org/matsim/core/population/PopulationUtils.java +++ b/matsim/src/main/java/org/matsim/core/population/PopulationUtils.java @@ -57,6 +57,7 @@ import org.matsim.core.config.groups.PlansConfigGroup; import org.matsim.core.gbl.Gbl; import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.population.algorithms.PersonRouteCheck; import org.matsim.core.population.io.PopulationReader; import org.matsim.core.population.io.PopulationWriter; import org.matsim.core.population.io.StreamingPopulationReader; @@ -1295,4 +1296,16 @@ public static void insertVehicleIdsIntoPersonAttributes(Person person, Map l.getAllowedModes().contains(leg.getMode())); if(!linkModesConsistent){ - throw new RuntimeException("Route inconsistent with link modes for: Person " + person.getId() + "; Leg '" + leg + "'"); + String errorMessage = "Route inconsistent with link modes for: Person " + person.getId() + "; Leg '" + leg + "'"; + log.error(errorMessage + "\n Consider cleaning inconsistent routes by using PopulationUtils.checkRouteModeAndReset()."); + throw new RuntimeException(errorMessage); } } diff --git a/matsim/src/main/java/org/matsim/core/population/algorithms/PersonRouteCheck.java b/matsim/src/main/java/org/matsim/core/population/algorithms/PersonRouteCheck.java new file mode 100644 index 00000000000..aca5f9bb976 --- /dev/null +++ b/matsim/src/main/java/org/matsim/core/population/algorithms/PersonRouteCheck.java @@ -0,0 +1,43 @@ +package org.matsim.core.population.algorithms; + +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.population.Leg; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.Route; +import org.matsim.core.population.routes.NetworkRoute; + +public class PersonRouteCheck implements PersonAlgorithm{ + private final Network network; + + public PersonRouteCheck(Network network) { + this.network = network; + } + + @Override + public void run(Person person) { + person.getPlans().stream() + .flatMap(p -> p.getPlanElements().stream()) + .filter(pe -> pe instanceof Leg) + .map(pe -> (Leg) pe) + .forEach(this::resetRouteIfInconsistentModes); + } + + private void resetRouteIfInconsistentModes(Leg leg) { + Route route = leg.getRoute(); + if (route == null) { + return; + } + + if (!(route instanceof NetworkRoute netRoute)) { + return; + } + + boolean allLinksHaveLegMode = netRoute.getLinkIds().stream() + .map(id -> network.getLinks().get(id)) + .allMatch(link -> link.getAllowedModes().contains(leg.getMode())); + + if (!allLinksHaveLegMode) { + leg.setRoute(null); + } + } +} diff --git a/matsim/src/main/java/org/matsim/core/router/DefaultRoutingModules.java b/matsim/src/main/java/org/matsim/core/router/DefaultRoutingModules.java index 8e26e960a76..88e99ba95ce 100644 --- a/matsim/src/main/java/org/matsim/core/router/DefaultRoutingModules.java +++ b/matsim/src/main/java/org/matsim/core/router/DefaultRoutingModules.java @@ -60,6 +60,7 @@ public static RoutingModule createTeleportationRouter( String mode, Scenario sce /** * Creates network router without access/egress. */ + @Deprecated // use AccessEgressNetworkRouter instead public static RoutingModule createPureNetworkRouter( String mode, PopulationFactory popFact, Network net, final LeastCostPathCalculator routeAlgo ) { return new NetworkRoutingModule( mode, diff --git a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingModule.java b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingModule.java index de8b8d4ace3..82e9b04928f 100644 --- a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingModule.java +++ b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingModule.java @@ -42,6 +42,7 @@ * * @author thibautd */ +@Deprecated // use NetworkRoutingInclAccessEgressModule instead public final class NetworkRoutingModule implements RoutingModule { // I think it makes sense to NOT add the bushwhacking mode directly into here ... // ... since it makes sense be able to to route from facility.getLinkId() to facility.getLinkId(). kai, dec'15 diff --git a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java index 3b71a8de64e..6f4a1bbd40f 100644 --- a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java +++ b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java @@ -47,8 +47,6 @@ public class NetworkRoutingProvider implements Provider{ private final String routingMode; - @Inject - ControllerConfigGroup controllerConfigGroup; @Inject Map travelTimes; @Inject Map travelDisutilityFactories; @Inject SingleModeNetworksCache singleModeNetworksCache; @@ -134,12 +132,13 @@ public RoutingModule get() { } } else { + log.warn("[mode: {}; routingMode: {}] Using deprecated routing module without access/egress. Consider using AccessEgressNetworkRouter instead.", mode, routingMode); return DefaultRoutingModules.createPureNetworkRouter(mode, populationFactory, filteredNetwork, routeAlgo); } } private void checkNetwork(Network filteredNetwork) { - if(controllerConfigGroup.getNetworkRouteConsistencyCheck() == ControllerConfigGroup.NetworkRouteConsistencyCheck.disable) { + if(routingConfigGroup.getNetworkRouteConsistencyCheck() == RoutingConfigGroup.NetworkRouteConsistencyCheck.disable) { return; } @@ -149,7 +148,9 @@ private void checkNetwork(Network filteredNetwork) { boolean changed = nLinks != filteredNetwork.getLinks().size() || nNodes != filteredNetwork.getNodes().size(); if(changed) { - throw new RuntimeException("Network for mode '"+mode+"' has unreachable links and nodes. This may be caused by mode restrictions on certain links. Aborting."); + String errorMessage = "Network for mode '" + mode + "' has unreachable links and nodes. This may be caused by mode restrictions on certain links. Aborting."; + log.error(errorMessage + "\n If you restricted modes on some links, consider doing that with NetworkUtils.restrictModesAndCleanNetwork(). This makes sure, that the network is consistent for each mode."); + throw new RuntimeException(errorMessage); } } } diff --git a/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkModeChangerTest.java b/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkModeRestrictionTest.java similarity index 79% rename from matsim/src/test/java/org/matsim/core/network/algorithms/NetworkModeChangerTest.java rename to matsim/src/test/java/org/matsim/core/network/algorithms/NetworkModeRestrictionTest.java index bcfc8606be1..92f3bef546f 100644 --- a/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkModeChangerTest.java +++ b/matsim/src/test/java/org/matsim/core/network/algorithms/NetworkModeRestrictionTest.java @@ -28,7 +28,7 @@ * l1 (n2) l6 (n7) l15 (n12) l20 */ // @formatter:on -class NetworkModeChangerTest { +class NetworkModeRestrictionTest { /** * Test that all links and nodes are removed if the network is not connected any more for every mode. @@ -38,35 +38,35 @@ void testRemoveWholeNetwork() { Network network = getNetwork(); Map, Set> changes = new HashMap<>(); - changes.put(Id.createLinkId(1), Set.of()); + changes.put(Id.createLinkId(1), Set.of("car","bike")); - new NetworkModeChanger(changes).run(network); + new NetworkModeRestriction(changes).run(network); assertTrue(network.getLinks().isEmpty()); assertTrue(network.getNodes().isEmpty()); } /** - * Test that mode is removed from each node if there it is not connected any more for this mode. + * Test that mode is removed from each node if there is not connected any more for this mode. */ @ParameterizedTest @ValueSource(strings = {"car", "bike"}) - void testRemoveWholeMode(String mode) { + void testRemoveWholeMode(String modeToRemove) { Network network = getNetwork(); int linksBefore = network.getLinks().size(); int nodesBefore = network.getNodes().size(); Map, Set> changes = new HashMap<>(); - changes.put(Id.createLinkId(1), Set.of(mode)); + changes.put(Id.createLinkId(1), Set.of(modeToRemove)); - new NetworkModeChanger(changes).run(network); + new NetworkModeRestriction(changes).run(network); assertEquals(linksBefore, network.getLinks().size()); assertEquals(nodesBefore, network.getNodes().size()); Assertions.assertTrue(network.getLinks().values().stream() - .allMatch(l -> l.getAllowedModes().size() == 1 && l.getAllowedModes().contains(mode))); + .allMatch(l -> l.getAllowedModes().size() == 1 && l.getAllowedModes().contains(getOtherMode(modeToRemove)))); } /** @@ -74,7 +74,7 @@ void testRemoveWholeMode(String mode) { */ @ParameterizedTest @CsvSource({"6,car", "6,bike", "15,car", "15,bike"}) - void testRemoveModePartially(int link, String mode) { + void testRemoveModePartially(int link, String modeToRemove) { Network network = getNetwork(); int linksBefore = network.getLinks().size(); @@ -82,10 +82,10 @@ void testRemoveModePartially(int link, String mode) { //prepare removal Map, Set> changes = new HashMap<>(); - changes.put(Id.createLinkId(link), Set.of(mode)); + changes.put(Id.createLinkId(link), Set.of(modeToRemove)); //remove - new NetworkModeChanger(changes).run(network); + new NetworkModeRestriction(changes).run(network); //links and nodes should all still be there assertEquals(linksBefore, network.getLinks().size()); @@ -97,8 +97,8 @@ void testRemoveModePartially(int link, String mode) { //link 6 and 15 should have the mode removed Assertions.assertEquals(1, link6Modes.size()); Assertions.assertEquals(1, link15Modes.size()); - Assertions.assertTrue(link6Modes.contains(mode)); - Assertions.assertTrue(link15Modes.contains(mode)); + Assertions.assertTrue(link6Modes.contains(getOtherMode(modeToRemove))); + Assertions.assertTrue(link15Modes.contains(getOtherMode(modeToRemove))); } /** @@ -114,10 +114,10 @@ void testRemovePartialNetwork(int link) { //prepare removal Map, Set> changes = new HashMap<>(); - changes.put(Id.createLinkId(link), Set.of()); + changes.put(Id.createLinkId(link), Set.of("car", "bike")); //remove - new NetworkModeChanger(changes).run(network); + new NetworkModeRestriction(changes).run(network); //both links and the node in between should be removed assertEquals(linksBefore - 2, network.getLinks().size()); @@ -137,4 +137,8 @@ private static Network getNetwork() { network.getLinks().values().forEach(l -> l.setAllowedModes(Set.of("car", "bike"))); return network; } + + private String getOtherMode(String mode) { + return mode.equals("car") ? "bike" : "car"; + } } diff --git a/matsim/src/test/java/org/matsim/core/population/algorithms/PersonPrepareForSimTest.java b/matsim/src/test/java/org/matsim/core/population/algorithms/PersonPrepareForSimTest.java index 556837c6d88..4a5cf91dd6a 100644 --- a/matsim/src/test/java/org/matsim/core/population/algorithms/PersonPrepareForSimTest.java +++ b/matsim/src/test/java/org/matsim/core/population/algorithms/PersonPrepareForSimTest.java @@ -41,7 +41,7 @@ import org.matsim.api.core.v01.population.PopulationFactory; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; -import org.matsim.core.config.groups.ControllerConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimImpl; import org.matsim.core.population.PopulationUtils; import org.matsim.core.population.routes.NetworkRoute; @@ -476,7 +476,7 @@ void testReplaceExperimentalTransitRoute() { void testLegRouteModeConsistency_throws() { // set config, such that exception is thrown due to inconsistency Config config = ConfigUtils.createConfig(); - config.controller().setNetworkRouteConsistencyCheck(ControllerConfigGroup.NetworkRouteConsistencyCheck.abortOnInconsistency); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.abortOnInconsistency); Scenario scenario = ScenarioUtils.createScenario(config); Person person = createInconsistentPersonForModeConsistencyCheck(scenario); @@ -488,7 +488,7 @@ void testLegRouteModeConsistency_throws() { void testLegRouteModeConsistency_ignored() { // set config, such that inconsistency is ignored Config config = ConfigUtils.createConfig(); - config.controller().setNetworkRouteConsistencyCheck(ControllerConfigGroup.NetworkRouteConsistencyCheck.disable); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = ScenarioUtils.createScenario(config); Person person = createInconsistentPersonForModeConsistencyCheck(scenario); diff --git a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java index 95b1e688f9d..83754f8c59e 100644 --- a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java +++ b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java @@ -25,10 +25,11 @@ import org.matsim.api.core.v01.population.Leg; import org.matsim.api.core.v01.population.Person; import org.matsim.core.config.Config; -import org.matsim.core.config.groups.ControllerConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; +import org.matsim.core.events.EventsUtils; import org.matsim.core.router.util.TravelTime; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.testcases.MatsimTestUtils; @@ -47,8 +48,6 @@ */ // @formatter:on public class ModeRestrictionTest { - private static final Logger log = LogManager.getLogger(ModeRestrictionTest.class); - @RegisterExtension private MatsimTestUtils utils = new MatsimTestUtils(); @@ -162,7 +161,7 @@ void testRerouteBeforeSim_actOnRestrictedLinkWithoutCoord_throws(String restrict private Config prepareConfig(String plansFile) { final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml"); - config.controller().setNetworkRouteConsistencyCheck(ControllerConfigGroup.NetworkRouteConsistencyCheck.disable); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.plans().setInputFile(plansFile); ScoringConfigGroup.ModeParams params = new ScoringConfigGroup.ModeParams("bike") ; From bd6a5fc45edff1e9fef8dfebb4b12cd0da80e01f Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Wed, 3 Jul 2024 18:08:20 +0200 Subject: [PATCH 009/111] implement test using the new functionality for mode restriction --- .../matsim/examples/ModeRestrictionTest.java | 109 +++++++++++++++--- 1 file changed, 96 insertions(+), 13 deletions(-) diff --git a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java index 83754f8c59e..b07fbbfb680 100644 --- a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java +++ b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java @@ -1,8 +1,8 @@ package org.matsim.examples; import com.google.common.collect.Lists; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import com.google.inject.ProvisionException; +import com.google.inject.spi.Message; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.params.ParameterizedTest; @@ -29,7 +29,8 @@ import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; -import org.matsim.core.events.EventsUtils; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.population.PopulationUtils; import org.matsim.core.router.util.TravelTime; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.testcases.MatsimTestUtils; @@ -51,7 +52,7 @@ public class ModeRestrictionTest { @RegisterExtension private MatsimTestUtils utils = new MatsimTestUtils(); - static Stream provideArguments() { + static Stream intersectLinkAndMode() { List links = List.of("6", "15", "20"); List restrictedModes = List.of("car", "bike"); @@ -64,9 +65,9 @@ static Stream provideArguments() { * Expected behaviour: Since it is not checked, if the route contains link, which are not allowed to use anymore, it can still use the restricted link. */ @ParameterizedTest - @MethodSource("provideArguments") - void testNoRouteChange_ok(String link, String restrictedMode) { - final Config config = prepareConfig("plans_act_link20.xml"); + @MethodSource("intersectLinkAndMode") + void testNoRouteChange_noConsistencyCheck_ok(String link, String restrictedMode) { + final Config config = prepareConfig("plans_act_link20.xml", RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Id linkId = Id.createLinkId(link); Scenario scenario = ScenarioUtils.loadScenario(config); @@ -79,6 +80,28 @@ void testNoRouteChange_ok(String link, String restrictedMode) { firstLegRouteCheck.assertActualContainsExpected(); } + /** + * Setting: The agents (both car & bike) have a route from the plan. Link before and at the activity is restricted respectively. Consistency check is turned on. + * Expected behaviour: An exception is thrown because the route is inconsistent and this is checked. + */ + @ParameterizedTest + @MethodSource("intersectLinkAndMode") + void testNoRouteChange_withConsistencyCheck_throws(String link, String restrictedMode) { + final Config config = prepareConfig("plans_act_link20.xml", RoutingConfigGroup.NetworkRouteConsistencyCheck.abortOnInconsistency); + + Id linkId = Id.createLinkId(link); + Scenario scenario = ScenarioUtils.loadScenario(config); + Link networkLink = scenario.getNetwork().getLinks().get(linkId); + removeModeFromLink(networkLink, restrictedMode); + + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(); + RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runController(scenario, firstLegRouteCheck)); + Assertions.assertTrue(exception instanceof ProvisionException); + Assertions.assertTrue(((ProvisionException) exception).getErrorMessages().stream() + .map(Message::getMessage) + .anyMatch(m -> m.equals("java.lang.RuntimeException: Network for mode '" + restrictedMode + "' has unreachable links and nodes. This may be caused by mode restrictions on certain links. Aborting."))); + } + /** * Setting: The agents (both car & bike) have no route. The mode of the link in front of the activity is restricted. Consistency check is turned off. * Expected behaviour: By default, the network is not cleaned. The router throws an exception since there is no route from home to the activity. @@ -86,7 +109,7 @@ void testNoRouteChange_ok(String link, String restrictedMode) { @ParameterizedTest @ValueSource(strings = {"car", "bike"}) void testRerouteBeforeSim_toActNotPossible_throws(String restrictedMode) { - final Config config = prepareConfig("plans_act_link15.xml"); + final Config config = prepareConfig("plans_act_link15.xml", RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Id link = Id.createLinkId("6"); @@ -94,6 +117,8 @@ void testRerouteBeforeSim_toActNotPossible_throws(String restrictedMode) { FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(); RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runController(scenario, firstLegRouteCheck)); + + //we can't check the root exception because the check is done in another thread. So we check for the more general exception. Assertions.assertTrue( exception.getMessage().contains("Exception while processing persons. Cannot guarantee that all persons have been fully processed.")); } @@ -105,7 +130,7 @@ void testRerouteBeforeSim_toActNotPossible_throws(String restrictedMode) { @ParameterizedTest @ValueSource(strings = {"car", "bike"}) void testRerouteBeforeSim_fromActNotPossible_throws(String restrictedMode) { - final Config config = prepareConfig("plans_act_link6.xml"); + final Config config = prepareConfig("plans_act_link6.xml", RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Id link = Id.createLinkId("15"); @@ -113,10 +138,66 @@ void testRerouteBeforeSim_fromActNotPossible_throws(String restrictedMode) { FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(); RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runController(scenario, firstLegRouteCheck)); + + //we can't check the root exception because the check is done in another thread. So we check for the more general exception. Assertions.assertTrue( exception.getMessage().contains("Exception while processing persons. Cannot guarantee that all persons have been fully processed.")); } + /** + * Setting: Network and routes are cleaned before simulation. Link before the activity is restricted. Consistency check is turned off. + * Expected behaviour: The agent using the restricted are mode is rerouted. The new link of the activity for this agent is the one which is closest to the activity. + */ + @ParameterizedTest + @ValueSource(strings = {"car", "bike"}) + void testCleanNetworkAndRerouteBeforeSim_toActNotPossible_withConsistencyCheck_ok(String restrictedMode){ + final Config config = prepareConfig("plans_act_link15.xml", RoutingConfigGroup.NetworkRouteConsistencyCheck.abortOnInconsistency); + + Id link = Id.createLinkId("6"); + + Scenario scenario = ScenarioUtils.loadScenario(config); + NetworkUtils.restrictModesAndCleanNetwork(scenario.getNetwork(), Map.of(link, Set.of(restrictedMode))); + PopulationUtils.checkRouteModeAndReset(scenario.getPopulation(), scenario.getNetwork()); + + // New route. Note that the end link is 20, but the activity's link in the input was 15. + // But since we restricted the mode for link 6 AND 15, 20 is used as fallback. + List> newRoute = List.of(Id.createLinkId("1"), Id.createLinkId("2"), Id.createLinkId("11"), Id.createLinkId("20")); + List> oldRoute = List.of(Id.createLinkId("1"), Id.createLinkId("6"), Id.createLinkId("15")); + + String other = restrictedMode.equals("car") ? "bike" : "car"; + + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(Map.of(Id.createPersonId(restrictedMode), newRoute, Id.createPersonId(other), oldRoute)); + runController(scenario, firstLegRouteCheck); + firstLegRouteCheck.assertActualEqualsExpected(); + } + + /** + * Setting: Network and routes are cleaned before simulation. Link from the activity is restricted. Consistency check is turned off. + * Expected behaviour: The agent using the restricted are mode is rerouted. The new link of the activity for this agent is the one which is closest to the activity. + */ + @ParameterizedTest + @ValueSource(strings = {"car", "bike"}) + void testCleanNetworkAndRerouteBeforeSim_fromActNotPossible_withConsistencyCheck_ok(String restrictedMode){ + final Config config = prepareConfig("plans_act_link6.xml", RoutingConfigGroup.NetworkRouteConsistencyCheck.abortOnInconsistency); + + Id link = Id.createLinkId("15"); + + Scenario scenario = ScenarioUtils.loadScenario(config); + NetworkUtils.restrictModesAndCleanNetwork(scenario.getNetwork(), Map.of(link, Set.of(restrictedMode))); + PopulationUtils.checkRouteModeAndReset(scenario.getPopulation(), scenario.getNetwork()); + + // New route. Note that the end link is 20, but the activity's link in the input was 6. + // But since we restricted the mode for link 6 AND 15, 20 is used as fallback. + List> newRoute = List.of(Id.createLinkId("1"), Id.createLinkId("2"), Id.createLinkId("11"), Id.createLinkId("20")); + List> oldRoute = List.of(Id.createLinkId("1"), Id.createLinkId("6")); + + String other = restrictedMode.equals("car") ? "bike" : "car"; + + FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(Map.of(Id.createPersonId(restrictedMode), newRoute, Id.createPersonId(other), oldRoute)); + runController(scenario, firstLegRouteCheck); + firstLegRouteCheck.assertActualEqualsExpected(); + } + /** * Setting: The agents (both car & bike) have no route. The mode of the activity's link is restricted. Activity has x-y-coordinate. Consistency check is turned off. * Expected behaviour: The agents (both car & bike) are rerouted to the nearest link to the activity's coordinate. @@ -124,7 +205,7 @@ void testRerouteBeforeSim_fromActNotPossible_throws(String restrictedMode) { @ParameterizedTest @ValueSource(strings = {"car", "bike"}) void testRerouteBeforeSim_actOnRestrictedLinkWithCoords_ok(String restrictedMode) { - final Config config = prepareConfig("plans_act_link15.xml"); + final Config config = prepareConfig("plans_act_link15.xml", RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = restrictLinkAndResetRoutes(config, Id.createLinkId("15"), restrictedMode); @@ -147,7 +228,7 @@ void testRerouteBeforeSim_actOnRestrictedLinkWithCoords_ok(String restrictedMode @ParameterizedTest @ValueSource(strings = {"car", "bike"}) void testRerouteBeforeSim_actOnRestrictedLinkWithoutCoord_throws(String restrictedMode){ - final Config config = prepareConfig("plans_act_link15.xml"); + final Config config = prepareConfig("plans_act_link15.xml", RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Id person = Id.createPersonId(restrictedMode); Scenario scenario = restrictLinkAndResetRoutes(config, Id.createLinkId("15"), restrictedMode); @@ -155,13 +236,15 @@ void testRerouteBeforeSim_actOnRestrictedLinkWithoutCoord_throws(String restrict act.setCoord(null); RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runController(scenario, new FirstLegVisitedLinksCheck())); + + //we can't check the root exception because the check is done in another thread. So we check for the more general exception. Assertions.assertTrue( exception.getMessage().contains("Exception while processing persons. Cannot guarantee that all persons have been fully processed.")); } - private Config prepareConfig(String plansFile) { + private Config prepareConfig(String plansFile, RoutingConfigGroup.NetworkRouteConsistencyCheck consistencyCheck) { final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml"); - config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + config.routing().setNetworkRouteConsistencyCheck(consistencyCheck); config.plans().setInputFile(plansFile); ScoringConfigGroup.ModeParams params = new ScoringConfigGroup.ModeParams("bike") ; From 40ef8a2e7994ca385ce5991784007e262b615ab6 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Wed, 3 Jul 2024 18:40:47 +0200 Subject: [PATCH 010/111] revert changing the default access egress type --- .../contrib/signals/builder/TravelTimeFourWaysTest.java | 3 +++ .../org/matsim/core/config/groups/RoutingConfigGroup.java | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/TravelTimeFourWaysTest.java b/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/TravelTimeFourWaysTest.java index ba97489f89e..ff0080324d1 100644 --- a/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/TravelTimeFourWaysTest.java +++ b/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/TravelTimeFourWaysTest.java @@ -30,6 +30,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.*; import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; import org.matsim.core.events.EventsUtils; @@ -77,6 +78,8 @@ private Scenario createTestScenario(){ conf.network().setLaneDefinitionsFile("testLaneDefinitions_v2.0.xml"); conf.qsim().setUseLanes(true); conf.qsim().setUsingFastCapacityUpdate(false); + conf.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + SignalSystemsConfigGroup signalsConfig = ConfigUtils.addOrGetModule(conf, SignalSystemsConfigGroup.GROUP_NAME, SignalSystemsConfigGroup.class ); signalsConfig.setUseSignalSystems(true); diff --git a/matsim/src/main/java/org/matsim/core/config/groups/RoutingConfigGroup.java b/matsim/src/main/java/org/matsim/core/config/groups/RoutingConfigGroup.java index 4311f61c707..f233c55e796 100644 --- a/matsim/src/main/java/org/matsim/core/config/groups/RoutingConfigGroup.java +++ b/matsim/src/main/java/org/matsim/core/config/groups/RoutingConfigGroup.java @@ -91,8 +91,8 @@ public enum AccessEgressType { } private static final String ACCESSEGRESSTYPE = "accessEgressType"; - private static final String ACCESSEGRESSTYPE_CMT = "Defines how access and egress to main mode is simulated. Either of [none, accessEgressModeToLink, walkConstantTimeToLink, accessEgressModeToLinkPlusTimeConstant], Current default=accessEgressModeToLink which means walk over euclidean distance from nearest point on link to facility is simulated."; - private AccessEgressType accessEgressType = AccessEgressType.accessEgressModeToLink; + private static final String ACCESSEGRESSTYPE_CMT = "Defines how access and egress to main mode is simulated. Either of [none, accessEgressModeToLink, walkConstantTimeToLink, accessEgressModeToLinkPlusTimeConstant], Current default=none which means no access or egress trips are simulated."; + private AccessEgressType accessEgressType = AccessEgressType.none; // --- private static final String RANDOMNESS = "routingRandomness" ; From 3200fe1a4c546d37cb0ca17b0e61aaf4be951f0c Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Thu, 4 Jul 2024 11:07:34 +0200 Subject: [PATCH 011/111] explicitly set access egress type --- .../src/test/java/org/matsim/examples/ModeRestrictionTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java index b07fbbfb680..5a668c8a86e 100644 --- a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java +++ b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java @@ -253,6 +253,7 @@ private Config prepareConfig(String plansFile, RoutingConfigGroup.NetworkRouteCo config.qsim().setMainModes( new HashSet<>( Arrays.asList( TransportMode.car, TransportMode.bike ) ) ) ; config.routing().setNetworkModes( Arrays.asList( TransportMode.car, TransportMode.bike ) ); config.routing().removeTeleportedModeParams("bike"); + config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.accessEgressModeToLink); config.controller().setLastIteration(0); return config; From d647a6b70d2f38ffe2c4c372d4849ea9b5e87162 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Thu, 4 Jul 2024 11:24:36 +0200 Subject: [PATCH 012/111] fix test failures in contribs --- .../contrib/dvrp/router/DiversionTest.java | 4 +- .../emissions/TestPositionEmissionModule.java | 7 +-- .../freight/carriers/CarrierModuleTest.java | 2 + .../locationchoice/LocationChoiceIT.java | 1 + .../MultiModalControlerListenerTest.java | 2 +- .../multimodal/MultiModalTripRouterTest.java | 2 + .../pt/MultiModalPTCombinationTest.java | 1 + .../multimodal/simengine/StuckAgentTest.java | 3 +- .../contrib/noise/NoiseConfigGroupIT.java | 22 +++---- .../contrib/roadpricing/CalcPaidTollTest.java | 4 ++ .../PlansCalcRouteWithTollOrNotTest.java | 4 ++ .../TollTravelCostCalculatorTest.java | 4 ++ .../analysis/DelayAnalysisToolTest.java | 2 + .../contrib/signals/builder/Fixture.java | 2 + ...aultPlanbasedSignalSystemControllerIT.java | 2 + .../router/JointTripRouterFactoryTest.java | 3 + .../drtAndPt/PtAlongALine2Test.java | 2 +- .../CombinedFlowAndStorageDelayTest.java | 2 + .../vsp/congestion/CorridorNetworkTest.java | 60 ++++++++++--------- ...nalCongestionHandlerFlowQueueQsimTest.java | 2 + ...tionHandlerFlowSpillbackQueueQsimTest.java | 8 +++ .../MarginalCongestionHandlerV3Test.java | 2 +- .../MarginalCongestionPricingTest.java | 2 + .../vsp/congestion/TestForEmergenceTime.java | 2 + 24 files changed, 96 insertions(+), 49 deletions(-) diff --git a/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/router/DiversionTest.java b/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/router/DiversionTest.java index ed2c0c27587..16e1f5be09f 100644 --- a/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/router/DiversionTest.java +++ b/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/router/DiversionTest.java @@ -51,6 +51,7 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.config.groups.QSimConfigGroup.StarttimeInterpretation; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.Controler; import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; import org.matsim.core.mobsim.framework.MobsimTimer; @@ -124,7 +125,7 @@ void testRepeatedSameDestinationDiversions() { { /* Create some necessary configuration for the test */ - + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setLastIteration(0); @@ -454,6 +455,7 @@ void testRepeatedDiversionToDifferentDestinationRightBeforeLastLink() { config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setLastIteration(0); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setStartTime(0.0); config.qsim().setSimStarttimeInterpretation(StarttimeInterpretation.onlyUseStarttime); diff --git a/contribs/emissions/src/test/java/org/matsim/contrib/emissions/TestPositionEmissionModule.java b/contribs/emissions/src/test/java/org/matsim/contrib/emissions/TestPositionEmissionModule.java index f1824def7cd..a3059795499 100644 --- a/contribs/emissions/src/test/java/org/matsim/contrib/emissions/TestPositionEmissionModule.java +++ b/contribs/emissions/src/test/java/org/matsim/contrib/emissions/TestPositionEmissionModule.java @@ -18,11 +18,7 @@ import org.matsim.contrib.emissions.utils.EmissionsConfigGroup; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.ConfigUtils; -import org.matsim.core.config.groups.ControllerConfigGroup; -import org.matsim.core.config.groups.NetworkConfigGroup; -import org.matsim.core.config.groups.ReplanningConfigGroup; -import org.matsim.core.config.groups.ScoringConfigGroup; -import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.*; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; import org.matsim.core.controler.OutputDirectoryHierarchy; @@ -91,6 +87,7 @@ void compareToOtherModule_singleVehicleSingleLink() { var config = ConfigUtils.loadConfig(configFile, emissionConfig); config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setOutputDirectory(testUtils.getOutputDirectory()); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); emissionConfig.setAverageColdEmissionFactorsFile("../sample_41_EFA_ColdStart_vehcat_2020average.csv"); emissionConfig.setAverageWarmEmissionFactorsFile( "../sample_41_EFA_HOT_vehcat_2020average.csv" ); diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierModuleTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierModuleTest.java index b0d4922fcf9..49dc173dd05 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierModuleTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierModuleTest.java @@ -27,6 +27,7 @@ import org.matsim.api.core.v01.Scenario; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; @@ -53,6 +54,7 @@ public class CarrierModuleTest { @BeforeEach public void setUp(){ Config config = ConfigUtils.createConfig() ; + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ScoringConfigGroup.ActivityParams workParams = new ScoringConfigGroup.ActivityParams("w"); workParams.setTypicalDuration(60 * 60 * 8); config.scoring().addActivityParams(workParams); diff --git a/contribs/locationchoice/src/test/java/org/matsim/contrib/locationchoice/LocationChoiceIT.java b/contribs/locationchoice/src/test/java/org/matsim/contrib/locationchoice/LocationChoiceIT.java index 4f39e4a0b72..1a045c7c8f6 100644 --- a/contribs/locationchoice/src/test/java/org/matsim/contrib/locationchoice/LocationChoiceIT.java +++ b/contribs/locationchoice/src/test/java/org/matsim/contrib/locationchoice/LocationChoiceIT.java @@ -84,6 +84,7 @@ public class LocationChoiceIT { void testLocationChoice() { final Config config = localCreateConfig( utils.getPackageInputDirectory() + "config2.xml"); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); final MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); diff --git a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/MultiModalControlerListenerTest.java b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/MultiModalControlerListenerTest.java index cb24c3d8849..fa7c3b2f767 100644 --- a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/MultiModalControlerListenerTest.java +++ b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/MultiModalControlerListenerTest.java @@ -89,7 +89,7 @@ void testSimpleScenario() { static void runSimpleScenario(int numberOfThreads) { Config config = ConfigUtils.createConfig(); - + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setEndTime(24 * 3600); config.controller().setLastIteration(0); diff --git a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/MultiModalTripRouterTest.java b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/MultiModalTripRouterTest.java index a939cb76327..ea6ba8549c3 100644 --- a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/MultiModalTripRouterTest.java +++ b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/MultiModalTripRouterTest.java @@ -39,6 +39,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Injector; @@ -73,6 +74,7 @@ void testRouteLeg() { config.routing().addParam("teleportedModeSpeed_ride", "15.0"); config.routing().addParam("teleportedModeSpeed_undefined", "13.88888888888889"); config.routing().addParam("teleportedModeSpeed_walk", "1.34"); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.scoring().addModeParams( new ScoringConfigGroup.ModeParams( TransportMode.ride ) ); final Scenario scenario = ScenarioUtils.createScenario(config); diff --git a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/pt/MultiModalPTCombinationTest.java b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/pt/MultiModalPTCombinationTest.java index ca3a78fce35..78231bd1790 100644 --- a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/pt/MultiModalPTCombinationTest.java +++ b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/pt/MultiModalPTCombinationTest.java @@ -85,6 +85,7 @@ void testMultiModalPtCombination() { Scenario scenario = f.scenario; Config config = scenario.getConfig(); config.controller().setOutputDirectory(utils.getOutputDirectory()); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MultiModalConfigGroup mmcg = new MultiModalConfigGroup(); mmcg.setMultiModalSimulationEnabled(true); diff --git a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/simengine/StuckAgentTest.java b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/simengine/StuckAgentTest.java index 790922dd590..d0776605026 100644 --- a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/simengine/StuckAgentTest.java +++ b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/simengine/StuckAgentTest.java @@ -46,6 +46,7 @@ import org.matsim.contrib.multimodal.config.MultiModalConfigGroup; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.controler.Controler; import org.matsim.core.events.handler.BasicEventHandler; @@ -69,7 +70,7 @@ public class StuckAgentTest { void testStuckEvents() { Config config = ConfigUtils.createConfig(); config.controller().setOutputDirectory(utils.getOutputDirectory()); - + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setEndTime(24*3600); config.controller().setLastIteration(0); diff --git a/contribs/noise/src/test/java/org/matsim/contrib/noise/NoiseConfigGroupIT.java b/contribs/noise/src/test/java/org/matsim/contrib/noise/NoiseConfigGroupIT.java index d5b61b0b590..1b5e2db9ccd 100644 --- a/contribs/noise/src/test/java/org/matsim/contrib/noise/NoiseConfigGroupIT.java +++ b/contribs/noise/src/test/java/org/matsim/contrib/noise/NoiseConfigGroupIT.java @@ -22,17 +22,18 @@ */ package org.matsim.contrib.noise; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Scenario; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.Controler; import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.core.scenario.ScenarioUtils; -import org.matsim.testcases.MatsimTestUtils; - +import org.matsim.testcases.MatsimTestUtils; + /** * @author ikaddoura * @@ -41,9 +42,9 @@ public class NoiseConfigGroupIT { @RegisterExtension - private MatsimTestUtils testUtils = new MatsimTestUtils(); - - @Test + private MatsimTestUtils testUtils = new MatsimTestUtils(); + + @Test final void test0(){ String configFile = testUtils.getPackageInputDirectory() + "NoiseConfigGroupTest/config0.xml"; @@ -69,14 +70,15 @@ final void test0(){ String tunnelLinkIds = noiseParameters.getTunnelLinkIDsSet().toArray()[0] + "," + noiseParameters.getTunnelLinkIDsSet().toArray()[1]; Assertions.assertEquals("link1,link2", tunnelLinkIds, "wrong config parameter"); - } - - @Test + } + + @Test final void test1(){ String configFile = testUtils.getPackageInputDirectory() + "NoiseConfigGroupTest/config1.xml"; Config config = ConfigUtils.loadConfig(configFile, new NoiseConfigGroup()); config.controller().setOutputDirectory(testUtils.getOutputDirectory()); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); NoiseConfigGroup noiseParameters = (NoiseConfigGroup) config.getModule("noise"); diff --git a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/CalcPaidTollTest.java b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/CalcPaidTollTest.java index 85c90cb3e79..9cfbfca06ed 100644 --- a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/CalcPaidTollTest.java +++ b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/CalcPaidTollTest.java @@ -34,6 +34,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -58,6 +59,7 @@ public class CalcPaidTollTest { @Test void testDistanceToll() { Config config = ConfigUtils.loadConfig(utils.getClassInputDirectory() + "config.xml"); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); final String tollFile = utils.getClassInputDirectory() + "/roadpricing1.xml"; Id id1 = Id.create("1", Person.class); @@ -94,6 +96,7 @@ void testDistanceToll() { @Test void testAreaToll() { Config config = ConfigUtils.loadConfig(utils.getClassInputDirectory() + "config.xml"); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); final String tollFile = utils.getClassInputDirectory() + "/roadpricing2.xml"; Id id1 = Id.create("1", Person.class); @@ -145,6 +148,7 @@ void testAreaToll() { @Test void testCordonToll() { Config config = ConfigUtils.loadConfig(utils.getClassInputDirectory() + "config.xml"); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); final String tollFile = utils.getClassInputDirectory() + "/roadpricing3.xml"; Id id1 = Id.create("1", Person.class); diff --git a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/PlansCalcRouteWithTollOrNotTest.java b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/PlansCalcRouteWithTollOrNotTest.java index e75ed598afa..ac22d50cf11 100644 --- a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/PlansCalcRouteWithTollOrNotTest.java +++ b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/PlansCalcRouteWithTollOrNotTest.java @@ -36,6 +36,7 @@ import org.matsim.api.core.v01.population.PlanElement; import org.matsim.api.core.v01.population.Population; import org.matsim.core.config.Config; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.RoutingConfigGroup.AccessEgressType; import org.matsim.core.controler.Injector; import org.matsim.core.controler.NewControlerModule; @@ -180,6 +181,7 @@ private PlansCalcRouteWithTollOrNot testee(final Scenario scenario, final RoadPr @Test void testTolledActLink() { Config config = matsimTestUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); RoadPricingTestUtils.createNetwork2(scenario); @@ -206,6 +208,7 @@ void testTolledActLink() { @Test void testAllAlternativesTolled() { Config config = matsimTestUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); RoadPricingTestUtils.createNetwork2(scenario); @@ -245,6 +248,7 @@ private static Leg getLeg3(Config config, Population population, Id id1) @Test void testOutsideTollTime() { Config config = matsimTestUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); RoadPricingTestUtils.createNetwork2(scenario); diff --git a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/TollTravelCostCalculatorTest.java b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/TollTravelCostCalculatorTest.java index 84052e33d8c..b72e2661670 100644 --- a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/TollTravelCostCalculatorTest.java +++ b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/TollTravelCostCalculatorTest.java @@ -74,6 +74,7 @@ public class TollTravelCostCalculatorTest { @Test void testDisutilityResults() { Config config = ConfigUtils.createConfig() ; + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = ScenarioUtils.createScenario(config) ; RoadPricingTestUtils.createNetwork2((MutableScenario)scenario); @@ -124,6 +125,7 @@ void testDisutilityResults() { @Test void testDistanceTollRouter() { Config config = utils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); RoadPricingTestUtils.createNetwork2(scenario); Network network = scenario.getNetwork(); @@ -209,6 +211,7 @@ void testDistanceTollRouter() { @Test void testLinkTollRouter() { Config config = utils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); RoadPricingTestUtils.createNetwork2(scenario); Network network = scenario.getNetwork(); @@ -304,6 +307,7 @@ void testLinkTollRouter() { @Test void testCordonTollRouter() { Config config = utils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); RoadPricingTestUtils.createNetwork2(scenario); Network network = scenario.getNetwork(); diff --git a/contribs/signals/src/test/java/org/matsim/contrib/signals/analysis/DelayAnalysisToolTest.java b/contribs/signals/src/test/java/org/matsim/contrib/signals/analysis/DelayAnalysisToolTest.java index 22c34ad8ddc..c7b0852857e 100644 --- a/contribs/signals/src/test/java/org/matsim/contrib/signals/analysis/DelayAnalysisToolTest.java +++ b/contribs/signals/src/test/java/org/matsim/contrib/signals/analysis/DelayAnalysisToolTest.java @@ -25,6 +25,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.events.algorithms.EventWriterXML; @@ -140,6 +141,7 @@ private void generateOutput(Scenario scenario, final List eventslist) { private Scenario prepareTest(int numberOfPersons) { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = ScenarioUtils.createScenario(config); createNetwork(scenario); createPopulation(scenario, numberOfPersons); diff --git a/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/Fixture.java b/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/Fixture.java index 63f18a921a9..d51e4727e4b 100644 --- a/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/Fixture.java +++ b/contribs/signals/src/test/java/org/matsim/contrib/signals/builder/Fixture.java @@ -45,6 +45,7 @@ import org.matsim.contrib.signals.model.SignalSystem; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.config.groups.ReplanningConfigGroup.StrategySettings; import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; @@ -87,6 +88,7 @@ private Config createConfigOneSignal(Boolean useIntergreens) { } Config conf = ConfigUtils.createConfig(testUtils.classInputResourcePath()); conf.controller().setOverwriteFileSetting(OverwriteFileSetting.overwriteExistingFiles); + conf.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ActivityParams params = new ActivityParams("h"); params.setTypicalDuration(24.0 * 3600.0); conf.scoring().addActivityParams(params); diff --git a/contribs/signals/src/test/java/org/matsim/contrib/signals/controller/fixedTime/DefaultPlanbasedSignalSystemControllerIT.java b/contribs/signals/src/test/java/org/matsim/contrib/signals/controller/fixedTime/DefaultPlanbasedSignalSystemControllerIT.java index e5f7d325967..91323bda153 100644 --- a/contribs/signals/src/test/java/org/matsim/contrib/signals/controller/fixedTime/DefaultPlanbasedSignalSystemControllerIT.java +++ b/contribs/signals/src/test/java/org/matsim/contrib/signals/controller/fixedTime/DefaultPlanbasedSignalSystemControllerIT.java @@ -61,6 +61,7 @@ import org.matsim.contrib.signals.utils.SignalUtils; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.config.groups.ReplanningConfigGroup.StrategySettings; import org.matsim.core.controler.AbstractModule; @@ -719,6 +720,7 @@ private void createSignals() { private Config defineConfig() { Config config = ConfigUtils.createConfig(); config.controller().setOutputDirectory(testUtils.getOutputDirectory()); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); // set number of iterations config.controller().setLastIteration(0); diff --git a/contribs/socnetsim/src/test/java/org/matsim/contrib/socnetsim/jointtrips/router/JointTripRouterFactoryTest.java b/contribs/socnetsim/src/test/java/org/matsim/contrib/socnetsim/jointtrips/router/JointTripRouterFactoryTest.java index 993cfdb52bb..71b3dbf77b9 100644 --- a/contribs/socnetsim/src/test/java/org/matsim/contrib/socnetsim/jointtrips/router/JointTripRouterFactoryTest.java +++ b/contribs/socnetsim/src/test/java/org/matsim/contrib/socnetsim/jointtrips/router/JointTripRouterFactoryTest.java @@ -48,6 +48,7 @@ import org.matsim.contrib.socnetsim.jointtrips.population.PassengerRoute; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Injector; import org.matsim.core.events.EventsUtils; @@ -95,6 +96,8 @@ private static Scenario createScenario() { Scenario sc = ScenarioUtils.createScenario( ConfigUtils.createConfig() ); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + Network net = (Network) sc.getNetwork(); final Id id5 = node1; Node node1inst = NetworkUtils.createAndAddNode(net, id5, new Coord((double) 0, (double) 1)); diff --git a/contribs/vsp/src/test/java/org/matsim/integration/drtAndPt/PtAlongALine2Test.java b/contribs/vsp/src/test/java/org/matsim/integration/drtAndPt/PtAlongALine2Test.java index d298b4ad003..f90f6112f3a 100644 --- a/contribs/vsp/src/test/java/org/matsim/integration/drtAndPt/PtAlongALine2Test.java +++ b/contribs/vsp/src/test/java/org/matsim/integration/drtAndPt/PtAlongALine2Test.java @@ -111,7 +111,7 @@ void testPtAlongALineWithRaptorAndDrtServiceArea() { // === ROUTER: === config.routing().setAccessEgressType(AccessEgressType.accessEgressModeToLink); - + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.modeVehicleTypesFromVehiclesData); // (as of today, will also influence router. kai, jun'19) diff --git a/contribs/vsp/src/test/java/playground/vsp/congestion/CombinedFlowAndStorageDelayTest.java b/contribs/vsp/src/test/java/playground/vsp/congestion/CombinedFlowAndStorageDelayTest.java index 755df67d97d..b8b5dfa08b2 100644 --- a/contribs/vsp/src/test/java/playground/vsp/congestion/CombinedFlowAndStorageDelayTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/congestion/CombinedFlowAndStorageDelayTest.java @@ -40,6 +40,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -163,6 +164,7 @@ private class createPseudoInputs { public createPseudoInputs(){ config=ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); this.scenario = ScenarioUtils.loadScenario(config); network = (Network) this.scenario.getNetwork(); population = this.scenario.getPopulation(); diff --git a/contribs/vsp/src/test/java/playground/vsp/congestion/CorridorNetworkTest.java b/contribs/vsp/src/test/java/playground/vsp/congestion/CorridorNetworkTest.java index ae8f04f18a4..be42f9e8a5a 100644 --- a/contribs/vsp/src/test/java/playground/vsp/congestion/CorridorNetworkTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/congestion/CorridorNetworkTest.java @@ -42,6 +42,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.events.handler.BasicEventHandler; @@ -68,7 +69,7 @@ public class CorridorNetworkTest { void v3Test(){ CorridorNetworkAndPlans inputs = new CorridorNetworkAndPlans(); Scenario sc = inputs.getDesiredScenario(); - + List v3_events = getCongestionEvents("v3", sc); Assertions.assertEquals(6, v3_events.size(), MatsimTestUtils.EPSILON, "wrong number of congestion events"); @@ -83,27 +84,27 @@ void v3Test(){ } else if ( event.getAffectedAgentId().equals(Id.createPersonId(3)) ) { // agent 3 is delayed on link 2 due to agent 2, 1 if(event.getCausingAgentId().equals(Id.createPersonId(2))) { - + Assertions.assertEquals(4, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - + } else { - + Assertions.assertEquals(2, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - + } - } else if(event.getAffectedAgentId().equals(Id.createPersonId(4))){ // agent 4 is first delayed due to spill back on link 1 (3 sec) and then on link 2 (6sec) + } else if(event.getAffectedAgentId().equals(Id.createPersonId(4))){ // agent 4 is first delayed due to spill back on link 1 (3 sec) and then on link 2 (6sec) if(event.getCausingAgentId().equals(Id.createPersonId(3))){ - + Assertions.assertEquals(4, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - + } else if (event.getCausingAgentId().equals(Id.createPersonId(2))){ - + Assertions.assertEquals(4, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - + } else { - + Assertions.assertEquals("1", event.getCausingAgentId().toString(), "wrong causing agent"); Assertions.assertEquals(1, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); } @@ -130,35 +131,35 @@ void v4Test(){ } else if ( event.getAffectedAgentId().equals(Id.createPersonId(3)) ) { // agent 3 is delayed on link 2 due to agent 2, 1 if(event.getCausingAgentId().equals(Id.createPersonId(2))) { - + Assertions.assertEquals(4, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - + } else { - + Assertions.assertEquals(2, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - + } - } else if(event.getAffectedAgentId().equals(Id.createPersonId(4))){ // agent 4 is first delayed due to spill back on link 1 (3 sec) and then on link 2 (6sec) + } else if(event.getAffectedAgentId().equals(Id.createPersonId(4))){ // agent 4 is first delayed due to spill back on link 1 (3 sec) and then on link 2 (6sec) if(event.getCausingAgentId().equals(Id.createPersonId(3)) ){ if ( event.getTime() == 10.0 ) { - + Assertions.assertEquals(3, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - + } else { - + Assertions.assertEquals(18.0, event.getTime(), MatsimTestUtils.EPSILON, "wrong congestion event time"); Assertions.assertEquals(4, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - + } - + } else { - + Assertions.assertEquals("2", event.getCausingAgentId().toString(), "wrong causing agent"); Assertions.assertEquals(2, event.getDelay(), MatsimTestUtils.EPSILON, "wrong delay"); - - } + + } } } } @@ -173,7 +174,7 @@ private List getCongestionEvents (String congestionPricingImpl, events.addHandler( new CongestionEventHandler() { @Override - public void reset(int iteration) { + public void reset(int iteration) { } @Override @@ -188,7 +189,7 @@ public void handleEvent(CongestionEvent event) { LogManager.getLogger( CorridorNetworkTest.class ).warn( event ); } }); - + if(congestionPricingImpl.equalsIgnoreCase("v3")) { events.addHandler(new CongestionHandlerImplV3(events, (MutableScenario)sc)); } @@ -204,10 +205,10 @@ public void handleEvent(CongestionEvent event) { private class CorridorNetworkAndPlans { /** - * generates network with 3 links. - *

+ * generates network with 3 links. + *

*

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

+ *

*/ Scenario scenario; Config config; @@ -221,6 +222,7 @@ private class CorridorNetworkAndPlans { CorridorNetworkAndPlans(){ config=ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); this.scenario = ScenarioUtils.loadScenario(config); network = (Network) this.scenario.getNetwork(); population = this.scenario.getPopulation(); diff --git a/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerFlowQueueQsimTest.java b/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerFlowQueueQsimTest.java index 94c1f09f388..576d33e53ed 100644 --- a/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerFlowQueueQsimTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerFlowQueueQsimTest.java @@ -45,6 +45,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSim; @@ -301,6 +302,7 @@ private Scenario loadScenario1() { // -----link1---- ----link2---- ----link3---- ----link4---- ----link5---- Config config = testUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); QSimConfigGroup qSimConfigGroup = config.qsim(); qSimConfigGroup.setFlowCapFactor(1.0); qSimConfigGroup.setStorageCapFactor(1.0); diff --git a/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerFlowSpillbackQueueQsimTest.java b/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerFlowSpillbackQueueQsimTest.java index 1d0f93eb272..a3952fcf727 100644 --- a/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerFlowSpillbackQueueQsimTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerFlowSpillbackQueueQsimTest.java @@ -136,6 +136,7 @@ public class MarginalCongestionHandlerFlowSpillbackQueueQsimTest { final void testFlowAndStorageCongestion_3agents(){ Scenario sc = loadScenario1(); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); setPopulation1(sc); final List congestionEvents = new ArrayList(); @@ -181,6 +182,7 @@ public void handleEvent(CongestionEvent event) { final void testFlowAndStorageCongestion_3agents_V9() { Scenario sc = loadScenario1(); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); setPopulation1(sc); final List congestionEvents = new ArrayList(); @@ -222,6 +224,7 @@ public void handleEvent(CongestionEvent event) { final void testFlowAndStorageCongestion_3agents_V8() { Scenario sc = loadScenario1(); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); setPopulation1(sc); final List congestionEvents = new ArrayList(); @@ -264,6 +267,7 @@ public void handleEvent(CongestionEvent event) { final void testFlowAndStorageCongestion_3agents_V10() { Scenario sc = loadScenario1(); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); setPopulation1(sc); final List congestionEvents = new ArrayList(); @@ -318,6 +322,7 @@ final void testRouting(){ Config config = ConfigUtils.loadConfig( configFile ) ; config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.none); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); final Scenario scenario = ScenarioUtils.loadScenario( config ); Controler controler = new Controler( scenario ); @@ -454,6 +459,7 @@ else if(((event.getServices().getConfig().controller().getLastIteration())-(even final void testInsertingWaitingVehicles_01(){ Scenario sc = loadScenario4(); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); setPopulation4(sc); final List congestionEvents = new ArrayList(); @@ -513,6 +519,7 @@ public void handleEvent(LinkLeaveEvent event) { final void testInsertingWaitingVehicles_02(){ Scenario sc = loadScenario5(); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); setPopulation5(sc); final List congestionEvents = new ArrayList(); @@ -574,6 +581,7 @@ public void handleEvent(LinkLeaveEvent event) { final void testInsertingWaitingVehicles_03(){ Scenario sc = loadScenario4(); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); setPopulation6(sc); final List congestionEvents = new ArrayList(); diff --git a/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerV3Test.java b/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerV3Test.java index 1f70380e3de..a9ca7a13c8e 100644 --- a/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerV3Test.java +++ b/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionHandlerV3Test.java @@ -70,7 +70,7 @@ final void testCongestionExample(){ Config config = ConfigUtils.loadConfig( configFile ) ; config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.none); - + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); final Controler controler = new Controler(config); controler.addOverridingModule(new AbstractModule() { @Override diff --git a/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionPricingTest.java b/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionPricingTest.java index a398d462e77..4ef9873280a 100644 --- a/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionPricingTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/congestion/MarginalCongestionPricingTest.java @@ -42,6 +42,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -81,6 +82,7 @@ final void implV4Test(){ sc.getVehicles().addVehicleType(car); sc.getConfig().qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.modeVehicleTypesFromVehiclesData); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); EventsManager events = EventsUtils.createEventsManager(); diff --git a/contribs/vsp/src/test/java/playground/vsp/congestion/TestForEmergenceTime.java b/contribs/vsp/src/test/java/playground/vsp/congestion/TestForEmergenceTime.java index 9cdfa5b37b1..835ef5a9c9a 100644 --- a/contribs/vsp/src/test/java/playground/vsp/congestion/TestForEmergenceTime.java +++ b/contribs/vsp/src/test/java/playground/vsp/congestion/TestForEmergenceTime.java @@ -40,6 +40,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -109,6 +110,7 @@ private List getAffectedPersonId2Delays(String congestionPricin sc.getVehicles().addVehicleType(car); sc.getConfig().qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.modeVehicleTypesFromVehiclesData); + sc.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); EventsManager events = EventsUtils.createEventsManager(); From 79f0f237d05c24caea1a73b1ac5dfa55fbae1752 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Thu, 4 Jul 2024 11:59:12 +0200 Subject: [PATCH 013/111] fix test failures in contribs and add config parameter so relevant functions --- .../controler/EquilWithCarrierWithPersonsIT.java | 3 +++ .../EquilWithCarrierWithoutPersonsIT.java | 2 ++ .../multimodal/RunMultimodalExampleTest.java | 5 +++-- .../PlansCalcRouteWithTollOrNotTest.java | 1 + .../roadpricing/TollTravelCostCalculatorTest.java | 14 +++++++------- .../marginals/ModalDistanceAndCountsCadytsIT.java | 1 + .../ModalDistanceCadytsMultipleDistancesIT.java | 7 +++---- .../ModalDistanceCadytsSingleDistanceIT.java | 2 +- .../core/config/groups/RoutingConfigGroup.java | 3 +++ 9 files changed, 24 insertions(+), 14 deletions(-) diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT.java index acfb8eab226..75800bfd34d 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithPersonsIT.java @@ -30,6 +30,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.ReplanningConfigGroup.StrategySettings; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; @@ -57,6 +58,8 @@ static Config commonConfig( MatsimTestUtils testUtils ) { config.controller().setOutputDirectory(testUtils.getOutputDirectory()); config.network().setInputFile( testUtils.getClassInputDirectory() + "network.xml" ); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + return config; } diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT.java index 83f1dd9e021..70b01111b10 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/controler/EquilWithCarrierWithoutPersonsIT.java @@ -30,6 +30,7 @@ import org.matsim.api.core.v01.Scenario; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; import org.matsim.freight.carriers.FreightCarriersConfigGroup; @@ -50,6 +51,7 @@ public class EquilWithCarrierWithoutPersonsIT { public void setUp() { Config config = EquilWithCarrierWithPersonsIT.commonConfig( testUtils ); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = EquilWithCarrierWithPersonsIT.commonScenario( config, testUtils ); controler = new Controler(scenario); } diff --git a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/RunMultimodalExampleTest.java b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/RunMultimodalExampleTest.java index 3a3c2101c9a..4cad691e8b5 100644 --- a/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/RunMultimodalExampleTest.java +++ b/contribs/multimodal/src/test/java/org/matsim/contrib/multimodal/RunMultimodalExampleTest.java @@ -20,8 +20,9 @@ void main(){ URL url = IOUtils.extendUrl( ExamplesUtils.getTestScenarioURL( "berlin" ), "config_multimodal.xml" );; String [] args = { url.toString(), - "--config:controler.outputDirectory" , utils.getOutputDirectory() - } ; + "--config:controler.outputDirectory" , utils.getOutputDirectory(), + "--config:routing.networkRouteConsistencyCheck", "disable" + } ;; try{ RunMultimodalExample.main( args ); diff --git a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/PlansCalcRouteWithTollOrNotTest.java b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/PlansCalcRouteWithTollOrNotTest.java index ac22d50cf11..e5651f02648 100644 --- a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/PlansCalcRouteWithTollOrNotTest.java +++ b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/PlansCalcRouteWithTollOrNotTest.java @@ -75,6 +75,7 @@ public class PlansCalcRouteWithTollOrNotTest { @Test void testBestAlternatives() { Config config = matsimTestUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.overwriteExistingFiles); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); RoadPricingTestUtils.createNetwork2(scenario); diff --git a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/TollTravelCostCalculatorTest.java b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/TollTravelCostCalculatorTest.java index b72e2661670..4eecbfef4df 100644 --- a/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/TollTravelCostCalculatorTest.java +++ b/contribs/roadpricing/src/test/java/org/matsim/contrib/roadpricing/TollTravelCostCalculatorTest.java @@ -24,6 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertNull; import java.util.List; +import java.util.Map; import jakarta.inject.Provider; import org.junit.jupiter.api.Test; @@ -126,11 +127,11 @@ void testDisutilityResults() { void testDistanceTollRouter() { Config config = utils.createConfig(); config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); - MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); + MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); RoadPricingTestUtils.createNetwork2(scenario); Network network = scenario.getNetwork(); // a basic toll where only the morning hours are tolled - RoadPricingSchemeImpl toll = RoadPricingUtils.addOrGetMutableRoadPricingScheme(ScenarioUtils.createScenario( ConfigUtils.createConfig() ) ); + RoadPricingSchemeImpl toll = RoadPricingUtils.addOrGetMutableRoadPricingScheme(ScenarioUtils.createScenario( config ) ); toll.setType(RoadPricingScheme.TOLL_TYPE_DISTANCE); toll.addLink(Id.create("5", Link.class)); toll.addLink(Id.create("11", Link.class)); @@ -212,11 +213,11 @@ void testDistanceTollRouter() { void testLinkTollRouter() { Config config = utils.createConfig(); config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); - MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); + MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); RoadPricingTestUtils.createNetwork2(scenario); Network network = scenario.getNetwork(); // a basic toll where only the morning hours are tolled - RoadPricingSchemeImpl toll = RoadPricingUtils.addOrGetMutableRoadPricingScheme(ScenarioUtils.createScenario( ConfigUtils.createConfig() ) ); + RoadPricingSchemeImpl toll = RoadPricingUtils.addOrGetMutableRoadPricingScheme(ScenarioUtils.createScenario( config ) ); toll.setType(RoadPricingScheme.TOLL_TYPE_LINK); toll.addLink(Id.create("5", Link.class)); toll.addLink(Id.create("11", Link.class)); @@ -308,11 +309,10 @@ void testLinkTollRouter() { void testCordonTollRouter() { Config config = utils.createConfig(); config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); - MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); + MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); RoadPricingTestUtils.createNetwork2(scenario); - Network network = scenario.getNetwork(); // a basic toll where only the morning hours are tolled - RoadPricingSchemeImpl toll = RoadPricingUtils.addOrGetMutableRoadPricingScheme(ScenarioUtils.createScenario( ConfigUtils.createConfig() ) ); + RoadPricingSchemeImpl toll = RoadPricingUtils.addOrGetMutableRoadPricingScheme(ScenarioUtils.createScenario( config ) ); // toll.setType(RoadPricingScheme.TOLL_TYPE_CORDON); toll.setType(RoadPricingScheme.TOLL_TYPE_LINK); toll.addLink(Id.create("5", Link.class)); diff --git a/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceAndCountsCadytsIT.java b/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceAndCountsCadytsIT.java index 0173d5e8552..dbdb804cb9b 100644 --- a/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceAndCountsCadytsIT.java +++ b/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceAndCountsCadytsIT.java @@ -68,6 +68,7 @@ private Config createConfig() { Config config = ConfigUtils.createConfig(); String[] modes = new String[]{TransportMode.car, TransportMode.bike}; + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setOutputDirectory(this.utils.getOutputDirectory()); config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setLastIteration(40); diff --git a/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceCadytsMultipleDistancesIT.java b/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceCadytsMultipleDistancesIT.java index 796380440ad..add356bc92e 100644 --- a/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceCadytsMultipleDistancesIT.java +++ b/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceCadytsMultipleDistancesIT.java @@ -14,11 +14,8 @@ import org.matsim.contrib.cadyts.general.CadytsScoring; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; -import org.matsim.core.config.groups.ChangeModeConfigGroup; -import org.matsim.core.config.groups.ReplanningConfigGroup; -import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.config.groups.*; import org.matsim.core.config.groups.RoutingConfigGroup.AccessEgressType; -import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; import org.matsim.core.controler.OutputDirectoryHierarchy; @@ -134,6 +131,8 @@ public ScoringFunction createNewScoringFunction(Person person) { private Config createConfig() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + String[] modes = new String[]{TransportMode.car, TransportMode.bike}; config.controller().setOutputDirectory(this.utils.getOutputDirectory()); diff --git a/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceCadytsSingleDistanceIT.java b/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceCadytsSingleDistanceIT.java index 2a7f0fdc897..133a4a48d83 100644 --- a/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceCadytsSingleDistanceIT.java +++ b/contribs/vsp/src/test/java/playground/vsp/cadyts/marginals/ModalDistanceCadytsSingleDistanceIT.java @@ -139,7 +139,7 @@ private Config createConfig() { Config config = ConfigUtils.createConfig(); String[] modes = new String[]{TransportMode.car, TransportMode.bike}; - + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setOutputDirectory(this.utils.getOutputDirectory()); config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setLastIteration(20); diff --git a/matsim/src/main/java/org/matsim/core/config/groups/RoutingConfigGroup.java b/matsim/src/main/java/org/matsim/core/config/groups/RoutingConfigGroup.java index f233c55e796..c38fba94eec 100644 --- a/matsim/src/main/java/org/matsim/core/config/groups/RoutingConfigGroup.java +++ b/matsim/src/main/java/org/matsim/core/config/groups/RoutingConfigGroup.java @@ -526,6 +526,8 @@ public void addParam(final String key, final String value) { } else if (ACCESSEGRESSTYPE.equals( key ) ) { this.setAccessEgressType(AccessEgressType.valueOf(value)); + } else if (NETWORK_ROUTE_CONSISTENCY_CHECK.equals(key)){ + this.setNetworkRouteConsistencyCheck(NetworkRouteConsistencyCheck.valueOf(value)); } else { throw new IllegalArgumentException(key); @@ -539,6 +541,7 @@ public final Map getParams() { map.put( CLEAR_MODE_ROUTING_PARAMS, Boolean.toString( this.clearingDefaultModeRoutingParams ) ) ; map.put( RANDOMNESS, Double.toString( this.routingRandomness ) ) ; map.put( ACCESSEGRESSTYPE, getAccessEgressType().toString()) ; + map.put(NETWORK_ROUTE_CONSISTENCY_CHECK, NetworkRouteConsistencyCheck.abortOnInconsistency.toString()); return map; } From 7b0e554550586153cf2a8c42f286b8fa34e6f89e Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Thu, 4 Jul 2024 18:37:46 +0200 Subject: [PATCH 014/111] repair test failures --- .../org/matsim/contrib/bicycle/BicycleModule.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java index 45e03c8a2f9..030a54935f5 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java @@ -40,13 +40,20 @@ public final class BicycleModule extends AbstractModule { private static final Logger LOG = LogManager.getLogger(BicycleModule.class); + @Inject private BicycleConfigGroup bicycleConfigGroup; + @Override public void install() { - BicycleConfigGroup bicycleConfigGroup = ConfigUtils.addOrGetModule( this.getConfig(), BicycleConfigGroup.class ); - this.bind( BicycleConfigGroup.class ).toInstance( bicycleConfigGroup ); +// BicycleConfigGroup bicycleConfigGroup = ConfigUtils.addOrGetModule( this.getConfig(), BicycleConfigGroup.class ); +// this.bind( BicycleConfigGroup.class ).toInstance( bicycleConfigGroup ); // the above feels odd. But it seems to work. I actually have no idea where the config groups are bound, neither for the core config // groups nor for the added config groups. In general, the original idea was that AbstractModule provides the config from // getConfig(), not from injection. kai, jun'24 + // It actually does not work in general. The ExplodedConfigModule injects all config groups that are materialized by then. Which + // means that it needs to be materialized "quite early", and in particular before this install method is called. For the time being, + // a run script using the contrib thus needs to materialize the config group. kai, jul'24 + + // The idea here is the following: // * scores are just added as score events. no scoring function is replaced. From 3c72fcbc01bfeb5dcafcdd104490228ed6d15db6 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Wed, 10 Jul 2024 16:29:41 +0200 Subject: [PATCH 015/111] pass lambda function as parameter --- .../org/matsim/core/network/NetworkUtils.java | 3 ++- .../algorithms/NetworkModeRestriction.java | 16 +++++++++------- .../org/matsim/examples/ModeRestrictionTest.java | 4 ++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java b/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java index 1053e7516c2..9e7da2c044f 100644 --- a/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java +++ b/matsim/src/main/java/org/matsim/core/network/NetworkUtils.java @@ -21,6 +21,7 @@ package org.matsim.core.network; import java.util.*; +import java.util.function.Function; import javax.annotation.Nullable; @@ -1042,7 +1043,7 @@ public static void removeAllowedMode(Link link, String mode) { * @param network the network * @param modesToRemoveByLinkId map of modes that should be removed from the links */ - public static void restrictModesAndCleanNetwork(Network network, Map, Set> modesToRemoveByLinkId) { + public static void restrictModesAndCleanNetwork(Network network, Function, Set> modesToRemoveByLinkId) { new NetworkModeRestriction(modesToRemoveByLinkId).run(network); } } diff --git a/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeRestriction.java b/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeRestriction.java index 1372552520d..c2457da636c 100644 --- a/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeRestriction.java +++ b/matsim/src/main/java/org/matsim/core/network/algorithms/NetworkModeRestriction.java @@ -11,6 +11,7 @@ import java.util.Map; import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -21,12 +22,16 @@ public class NetworkModeRestriction implements NetworkRunnable { private static final Logger log = LogManager.getLogger(NetworkModeRestriction.class); - private final Map, Set> modesToRemoveByLinkId; + private final Function, Set> modesToRemoveByLinkId; - public NetworkModeRestriction(Map, Set> modesToRemoveByLinkId) { + public NetworkModeRestriction(Function, Set> modesToRemoveByLinkId) { this.modesToRemoveByLinkId = modesToRemoveByLinkId; } + public NetworkModeRestriction(Map, Set> modesToRemoveByLinkId) { + this.modesToRemoveByLinkId = l -> modesToRemoveByLinkId.getOrDefault(l, Set.of()); + } + @Override public void run(Network network) { Map modeCountBefore = countModes(network); @@ -41,11 +46,8 @@ public void run(Network network) { } private void applyModeChanges(Network network) { - for (Map.Entry, Set> entry : modesToRemoveByLinkId.entrySet()) { - Link link = network.getLinks().get(entry.getKey()); - for (String modeToRemove : entry.getValue()) { - NetworkUtils.removeAllowedMode(link, modeToRemove); - } + for (Map.Entry, ? extends Link> link : network.getLinks().entrySet()) { + this.modesToRemoveByLinkId.apply(link.getKey()).forEach(m -> NetworkUtils.removeAllowedMode(link.getValue(), m)); } } diff --git a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java index 5a668c8a86e..a1bb8fb9c6b 100644 --- a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java +++ b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java @@ -156,7 +156,7 @@ void testCleanNetworkAndRerouteBeforeSim_toActNotPossible_withConsistencyCheck_o Id link = Id.createLinkId("6"); Scenario scenario = ScenarioUtils.loadScenario(config); - NetworkUtils.restrictModesAndCleanNetwork(scenario.getNetwork(), Map.of(link, Set.of(restrictedMode))); + NetworkUtils.restrictModesAndCleanNetwork(scenario.getNetwork(), l -> Map.of(link, Set.of(restrictedMode)).getOrDefault(l, Set.of())); PopulationUtils.checkRouteModeAndReset(scenario.getPopulation(), scenario.getNetwork()); // New route. Note that the end link is 20, but the activity's link in the input was 15. @@ -183,7 +183,7 @@ void testCleanNetworkAndRerouteBeforeSim_fromActNotPossible_withConsistencyCheck Id link = Id.createLinkId("15"); Scenario scenario = ScenarioUtils.loadScenario(config); - NetworkUtils.restrictModesAndCleanNetwork(scenario.getNetwork(), Map.of(link, Set.of(restrictedMode))); + NetworkUtils.restrictModesAndCleanNetwork(scenario.getNetwork(), l -> Map.of(link, Set.of(restrictedMode)).getOrDefault(l, Set.of())); PopulationUtils.checkRouteModeAndReset(scenario.getPopulation(), scenario.getNetwork()); // New route. Note that the end link is 20, but the activity's link in the input was 6. From e5bf4d970394abe86abf5ebc342e0956c05249b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Jul 2024 14:11:57 +0000 Subject: [PATCH 016/111] Bump com.google.errorprone:error_prone_annotations from 2.28.0 to 2.29.2 Bumps [com.google.errorprone:error_prone_annotations](https://github.com/google/error-prone) from 2.28.0 to 2.29.2. - [Release notes](https://github.com/google/error-prone/releases) - [Commits](https://github.com/google/error-prone/compare/v2.28.0...v2.29.2) --- updated-dependencies: - dependency-name: com.google.errorprone:error_prone_annotations dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3f97fb8c5d3..d03e82ea2be 100644 --- a/pom.xml +++ b/pom.xml @@ -205,7 +205,7 @@ com.google.errorprone error_prone_annotations - 2.28.0 + 2.29.2 From 1b9041f859bfba587b35a70454028a5fc4808e18 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Thu, 25 Jul 2024 10:33:32 +0200 Subject: [PATCH 017/111] fix tests by disabling net consistency check --- .../java/ch/sbb/matsim/routing/pt/raptor/Fixture.java | 2 ++ .../matsim/routing/pt/raptor/IntermodalFixture.java | 2 ++ .../analysis/LinkStatsControlerListenerTest.java | 2 ++ .../controler/TransitControlerIntegrationTest.java | 2 ++ .../java/org/matsim/core/mobsim/hermes/HermesTest.java | 4 ++++ .../matsim/core/mobsim/hermes/StorageCapacityTest.java | 4 ++++ .../core/mobsim/qsim/FlowStorageSpillbackTest.java | 2 ++ .../core/mobsim/qsim/NetsimRoutingConsistencyTest.java | 3 ++- .../matsim/core/mobsim/qsim/NodeTransitionTest.java | 7 +++++++ .../java/org/matsim/core/mobsim/qsim/QSimTest.java | 5 +++++ .../qsim/TeleportationEngineWDistanceCheckTest.java | 2 ++ .../org/matsim/core/mobsim/qsim/VehicleSourceTest.java | 2 ++ .../core/mobsim/qsim/pt/QSimIntegrationTest.java | 4 +++- .../matsim/core/mobsim/qsim/pt/TransitAgentTest.java | 10 ++++++++-- .../mobsim/qsim/pt/TransitQueueSimulationTest.java | 6 ++++++ .../DeparturesOnSameLinkSameTimeTest.java | 2 ++ .../qsim/qnetsimengine/FlowCapacityVariationTest.java | 3 ++- .../qnetsimengine/FlowEfficiencyCalculatorTest.java | 2 ++ .../qnetsimengine/JavaRoundingErrorInQsimTest.java | 2 ++ .../LinkSpeedCalculatorIntegrationTest.java | 5 ++++- .../core/mobsim/qsim/qnetsimengine/PassingTest.java | 2 ++ .../core/mobsim/qsim/qnetsimengine/QLinkLanesTest.java | 5 +++++ .../core/mobsim/qsim/qnetsimengine/QLinkTest.java | 4 ++++ .../core/mobsim/qsim/qnetsimengine/SeepageTest.java | 2 ++ .../qnetsimengine/SimulatedLaneFlowCapacityTest.java | 5 +++++ .../mobsim/qsim/qnetsimengine/VehVsLinkSpeedTest.java | 2 ++ .../mobsim/qsim/qnetsimengine/VehicleHandlerTest.java | 2 ++ .../core/network/io/NetworkReprojectionIOTest.java | 3 +++ .../matsim/core/router/FallbackRoutingModuleTest.java | 2 ++ .../NetworkRoutingInclAccessEgressModuleTest.java | 10 +++++++++- .../core/router/PseudoTransitRoutingModuleTest.java | 2 ++ .../matsim/core/router/TripRouterFactoryImplTest.java | 2 ++ .../core/utils/timing/TimeInterpretationTest.java | 3 +++ .../org/matsim/integration/SimulateAndScoreTest.java | 6 +++++- .../replanning/ChangeTripModeIntegrationTest.java | 2 ++ .../timevariantnetworks/QSimIntegrationTest.java | 4 ++++ .../controller/ExperiencedPlansWriterTest.java | 2 ++ ...WithinDayTravelTimeWithNetworkChangeEventsTest.java | 2 ++ 38 files changed, 123 insertions(+), 8 deletions(-) diff --git a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/Fixture.java b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/Fixture.java index 97bdc02747a..f842302b4d6 100644 --- a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/Fixture.java +++ b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/Fixture.java @@ -30,6 +30,7 @@ import org.matsim.api.core.v01.network.Node; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.population.routes.NetworkRoute; import org.matsim.core.population.routes.RouteUtils; import org.matsim.core.scenario.MutableScenario; @@ -100,6 +101,7 @@ public Fixture() { this.config = ConfigUtils.createConfig(); this.config.transit().setUseTransit(true); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ScenarioBuilder scBuilder = new ScenarioBuilder(config) ; this.scenario = (MutableScenario) scBuilder.build() ; diff --git a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/IntermodalFixture.java b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/IntermodalFixture.java index 495868e6991..a29767b6a48 100644 --- a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/IntermodalFixture.java +++ b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/IntermodalFixture.java @@ -30,6 +30,7 @@ import org.matsim.api.core.v01.population.Person; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.population.routes.NetworkRoute; import org.matsim.core.population.routes.RouteUtils; import org.matsim.core.scenario.ScenarioUtils; @@ -96,6 +97,7 @@ class IntermodalFixture { IntermodalFixture() { this.srrConfig = new SwissRailRaptorConfigGroup(); this.config = ConfigUtils.createConfig(this.srrConfig); + this.config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); this.scenario = ScenarioUtils.createScenario(this.config); TransitSchedule schedule = this.scenario.getTransitSchedule(); diff --git a/matsim/src/test/java/org/matsim/analysis/LinkStatsControlerListenerTest.java b/matsim/src/test/java/org/matsim/analysis/LinkStatsControlerListenerTest.java index 8ec2fb9f37d..0a47e4b929f 100644 --- a/matsim/src/test/java/org/matsim/analysis/LinkStatsControlerListenerTest.java +++ b/matsim/src/test/java/org/matsim/analysis/LinkStatsControlerListenerTest.java @@ -33,6 +33,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.LinkStatsConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.*; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Injector; @@ -352,6 +353,7 @@ void testReset_CorrectlyExecuted() throws IOException { config.controller().setFirstIteration(0); config.controller().setLastIteration(7); config.controller().setWritePlansInterval(0); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); LinkStatsConfigGroup lsConfig = config.linkStats(); lsConfig.setWriteLinkStatsInterval(3); diff --git a/matsim/src/test/java/org/matsim/core/controler/TransitControlerIntegrationTest.java b/matsim/src/test/java/org/matsim/core/controler/TransitControlerIntegrationTest.java index 10d912cfe9d..20699888afa 100644 --- a/matsim/src/test/java/org/matsim/core/controler/TransitControlerIntegrationTest.java +++ b/matsim/src/test/java/org/matsim/core/controler/TransitControlerIntegrationTest.java @@ -41,6 +41,7 @@ import org.matsim.api.core.v01.population.Population; import org.matsim.api.core.v01.population.PopulationFactory; import org.matsim.core.config.Config; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.config.groups.ReplanningConfigGroup.StrategySettings; import org.matsim.core.population.routes.NetworkRoute; @@ -68,6 +69,7 @@ public class TransitControlerIntegrationTest { @Test void testTransitRouteCopy() { Config config = utils.loadConfig((String)null); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.transit().setUseTransit(true); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/hermes/HermesTest.java b/matsim/src/test/java/org/matsim/core/mobsim/hermes/HermesTest.java index 09cb1763746..426a984aa8a 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/hermes/HermesTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/hermes/HermesTest.java @@ -59,6 +59,7 @@ import org.matsim.core.api.experimental.events.TeleportationArrivalEvent; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.events.handler.BasicEventHandler; @@ -808,6 +809,7 @@ private LogCounter runConsistentRoutesTestSim(final String startLinkId, final St void testStartAndEndTime() { final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); // --- @@ -864,6 +866,7 @@ void testStartAndEndTime() { void testCleanupSim_EarlyEnd() { MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); Config config = scenario.getConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); double simEndTime = 8.0*3600; @@ -990,6 +993,7 @@ public static final class Fixture { public Fixture() { this.scenario = ScenarioUtils.createScenario(ConfigUtils.createConfig()); this.config = scenario.getConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); /* build network */ diff --git a/matsim/src/test/java/org/matsim/core/mobsim/hermes/StorageCapacityTest.java b/matsim/src/test/java/org/matsim/core/mobsim/hermes/StorageCapacityTest.java index fd7958999fb..290d4632d45 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/hermes/StorageCapacityTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/hermes/StorageCapacityTest.java @@ -44,6 +44,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.events.EventsUtils; import org.matsim.core.network.NetworkUtils; import org.matsim.core.population.PersonUtils; @@ -68,6 +69,7 @@ public class StorageCapacityTest { void testStorageCapacity() { ScenarioImporter.flush(); Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.hermes().setStuckTime(Integer.MAX_VALUE); Scenario scenario = ScenarioUtils.createScenario(config); var links = generateNetwork(scenario.getNetwork()); @@ -120,6 +122,7 @@ void testStorageCapacityDownscaling() { config.hermes().setStuckTime(Integer.MAX_VALUE); config.hermes().setFlowCapacityFactor(0.1); config.hermes().setStorageCapacityFactor(0.1); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = ScenarioUtils.createScenario(config); var links = generateNetwork(scenario.getNetwork()); @@ -169,6 +172,7 @@ void testStorageCapacityDownscaling() { void testStorageCapacityWithDifferentPCUs() { ScenarioImporter.flush(); Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.hermes().setStuckTime(Integer.MAX_VALUE); Scenario scenario = ScenarioUtils.createScenario(config); var links = generateNetwork(scenario.getNetwork()); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/FlowStorageSpillbackTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/FlowStorageSpillbackTest.java index dbf47866033..311831b6bad 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/FlowStorageSpillbackTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/FlowStorageSpillbackTest.java @@ -38,6 +38,7 @@ import org.matsim.api.core.v01.population.*; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.population.PopulationUtils; @@ -230,6 +231,7 @@ private Scenario loadScenario() { // (0)-----link1-----(1)-----link2-----(2)-----link3-----(3)-----link4-----(4) Config config = testUtils.loadConfig((String) null); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = (ScenarioUtils.createScenario(config)); Network network = (Network) scenario.getNetwork(); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/NetsimRoutingConsistencyTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/NetsimRoutingConsistencyTest.java index 6899e6c95f1..e8693333c25 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/NetsimRoutingConsistencyTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/NetsimRoutingConsistencyTest.java @@ -46,6 +46,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; @@ -213,7 +214,7 @@ void testRoutingVsSimulation() { @Test void testRoutingVsSimulationFullStack() { Config config = ConfigUtils.createConfig(); - + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setLastIteration(0); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/NodeTransitionTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/NodeTransitionTest.java index b37c5f2a32d..40403107cb9 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/NodeTransitionTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/NodeTransitionTest.java @@ -43,6 +43,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.config.groups.QSimConfigGroup.NodeTransition; import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; @@ -292,6 +293,7 @@ void testBlockedNodeSituationWithEmptyBufferAfterBufferRandomDistribution(boolea Scenario scenario = Fixture.createBlockedNodeScenario(); scenario.getConfig().qsim().setNodeTransitionLogic(NodeTransition.emptyBufferAfterBufferRandomDistribution_nodeBlockedWhenSingleOutlinkFull); scenario.getConfig().qsim().setUsingFastCapacityUpdate(useFastCapUpdate); + scenario.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); EventsManager events = EventsUtils.createEventsManager(); List> linksOfInterest = new LinkedList<>(); @@ -374,6 +376,7 @@ void testBlockedNodeSituationWithMoveVehByVehRandomDistribution(boolean useFastC Scenario scenario = Fixture.createBlockedNodeScenario(); scenario.getConfig().qsim().setNodeTransitionLogic(NodeTransition.moveVehByVehRandomDistribution_nodeBlockedWhenSingleOutlinkFull); scenario.getConfig().qsim().setUsingFastCapacityUpdate(useFastCapUpdate); + scenario.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); EventsManager events = EventsUtils.createEventsManager(); List> linksOfInterest = new LinkedList<>(); @@ -457,6 +460,7 @@ void testBlockedNodeSituationWithMoveVehByVehDeterministicPriorities(boolean use Scenario scenario = Fixture.createBlockedNodeScenario(); scenario.getConfig().qsim().setNodeTransitionLogic(NodeTransition.moveVehByVehDeterministicPriorities_nodeBlockedWhenSingleOutlinkFull); scenario.getConfig().qsim().setUsingFastCapacityUpdate(useFastCapUpdate); + scenario.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); EventsManager events = EventsUtils.createEventsManager(); List> linksOfInterest = new LinkedList<>(); @@ -548,6 +552,7 @@ void testNodeTransitionWithTimeStepSizeSmallerOne(boolean useFastCapUpdate) { scenario.getConfig().qsim().setNodeTransitionLogic(NodeTransition.emptyBufferAfterBufferRandomDistribution_dontBlockNode); scenario.getConfig().qsim().setTimeStepSize(0.5); scenario.getConfig().qsim().setUsingFastCapacityUpdate(useFastCapUpdate); + scenario.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); EventsManager events = EventsUtils.createEventsManager(); List> linksOfInterest = new LinkedList<>(); @@ -633,9 +638,11 @@ static Scenario createMergeScenario() { config.controller().setLastIteration(0); config.qsim().setStuckTime(24*3600); config.qsim().setRemoveStuckVehicles(false); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ScoringConfigGroup.ActivityParams dummyAct = new ScoringConfigGroup.ActivityParams("dummy"); dummyAct.setTypicalDuration(12 * 3600); config.scoring().addActivityParams(dummyAct); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = ScenarioUtils.createScenario(config); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/QSimTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/QSimTest.java index e33947ee22f..96c12d442be 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/QSimTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/QSimTest.java @@ -66,6 +66,7 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.config.groups.QSimConfigGroup.TrafficDynamics; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.events.ParallelEventsManager; @@ -1393,6 +1394,7 @@ private LogCounter runConsistentRoutesTestSim(final String startLinkId, final St void testStartAndEndTime(boolean isUsingFastCapacityUpdate, int numberOfThreads) { final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setUsingFastCapacityUpdate(isUsingFastCapacityUpdate); // --- @@ -1461,6 +1463,7 @@ void testCleanupSim_EarlyEnd(boolean isUsingFastCapacityUpdate, int numberOfThre MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); Config config = scenario.getConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setUsingFastCapacityUpdate(isUsingFastCapacityUpdate); config.qsim().setNumberOfThreads(numberOfThreads); @@ -1806,6 +1809,8 @@ public Fixture(boolean isUsingFastCapacityUpdate, int numberOfThreads) { this.config.qsim().setUsingFastCapacityUpdate(isUsingFastCapacityUpdate); this.config.qsim().setNumberOfThreads(numberOfThreads); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + /* build network */ this.network = this.scenario.getNetwork(); this.network.setCapacityPeriod(Time.parseTime("1:00:00")); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/TeleportationEngineWDistanceCheckTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/TeleportationEngineWDistanceCheckTest.java index 8f0286cf9cd..5fa782435f3 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/TeleportationEngineWDistanceCheckTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/TeleportationEngineWDistanceCheckTest.java @@ -39,6 +39,7 @@ import org.matsim.api.core.v01.population.PopulationFactory; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.config.groups.ReplanningConfigGroup.StrategySettings; import org.matsim.core.controler.AbstractModule; @@ -64,6 +65,7 @@ final void test() { config.controller().setOutputDirectory( utils.getOutputDirectory() ); config.controller().setOverwriteFileSetting( OverwriteFileSetting.deleteDirectoryIfExists ); config.controller().setLastIteration(0); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ActivityParams params = new ActivityParams("dummy" ) ; config.scoring().addActivityParams(params); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/VehicleSourceTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/VehicleSourceTest.java index 9460bd95d03..367eb5d10db 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/VehicleSourceTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/VehicleSourceTest.java @@ -36,6 +36,7 @@ import org.matsim.api.core.v01.population.*; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.config.groups.QSimConfigGroup.VehiclesSource; @@ -94,6 +95,7 @@ void main(VehiclesSource vehiclesSource, boolean usingPersonIdForMissingVehicleI createPlans(vehiclesSource, providingVehiclesInPerson); Config config = scenario.getConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setFlowCapFactor(1.0); config.qsim().setStorageCapFactor(1.0); config.qsim().setMainModes(Arrays.asList(transportModes)); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/QSimIntegrationTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/QSimIntegrationTest.java index 25234b89cd0..078d2355b42 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/QSimIntegrationTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/QSimIntegrationTest.java @@ -44,6 +44,7 @@ import org.matsim.core.api.experimental.events.VehicleDepartsAtFacilityEvent; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -425,7 +426,8 @@ private static class Fixture { public Fixture() throws SAXException, ParserConfigurationException, IOException { // setup: config final Config config = ConfigUtils.createConfig(); - config.transit().setUseTransit(true); + config.transit().setUseTransit(true); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setEndTime(8.0*3600); this.scenario = (MutableScenario) ScenarioUtils.createScenario(config); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/TransitAgentTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/TransitAgentTest.java index 59c7341e27e..7b73108a13f 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/TransitAgentTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/TransitAgentTest.java @@ -39,7 +39,9 @@ import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.PopulationFactory; import org.matsim.core.api.experimental.events.EventsManager; +import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSim; @@ -65,7 +67,9 @@ public class TransitAgentTest { @Test void testAcceptLineRoute() { - MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); + Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); Network network = (Network) scenario.getNetwork(); Node node1 = NetworkUtils.createAndAddNode(network, Id.create("1", Node.class), new Coord((double) 0, (double) 0)); @@ -117,7 +121,9 @@ void testAcceptLineRoute() { @Test void testArriveAtStop() { - MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(ConfigUtils.createConfig()); + Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); Network network = (Network) scenario.getNetwork(); Node node1 = NetworkUtils.createAndAddNode(network, Id.create("1", Node.class), new Coord((double) 0, (double) 0)); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/TransitQueueSimulationTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/TransitQueueSimulationTest.java index 914190b0228..c635f01df74 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/TransitQueueSimulationTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/pt/TransitQueueSimulationTest.java @@ -63,6 +63,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.ExternalMobimConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.events.handler.BasicEventHandler; @@ -108,6 +109,7 @@ public class TransitQueueSimulationTest { void testCreateAgents() { // setup: config final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.transit().setUseTransit(true); config.qsim().setEndTime(8.0*3600); @@ -310,6 +312,7 @@ void testAddAgentToStopWrongLink() { assertThrows(TransitAgentTriesToTeleportException.class, () -> { // setup: config final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.transit().setUseTransit(true); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); @@ -381,6 +384,7 @@ void testAddAgentToStopWrongLink() { void testHandleStop() { // setup: config final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.transit().setUseTransit(true); config.qsim().setEndTime(8.0*3600); @@ -631,6 +635,7 @@ protected SpyHandleStopData(final TransitStopFacility stopFacility, final double @Test void testStartAndEndTime() { final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.transit().setUseTransit(true); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); @@ -728,6 +733,7 @@ public void reset(final int iteration) { @Test void testEvents() { final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.transit().setUseTransit(true); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/DeparturesOnSameLinkSameTimeTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/DeparturesOnSameLinkSameTimeTest.java index bc69576a7f2..f603260e3ce 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/DeparturesOnSameLinkSameTimeTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/DeparturesOnSameLinkSameTimeTest.java @@ -34,6 +34,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup.VehiclesSource; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -147,6 +148,7 @@ public PseudoInputs(String travelMode) { config=ConfigUtils.createConfig(); this.scenario = ScenarioUtils.loadScenario(config); config.qsim().setMainModes(Arrays.asList(travelMode)); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); //following is necessary for mixed traffic, providing a route was obstructing // the requirement of these which might be all right in some cases. Amit Jan'18 diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/FlowCapacityVariationTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/FlowCapacityVariationTest.java index d94ce42724a..2507353faa1 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/FlowCapacityVariationTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/FlowCapacityVariationTest.java @@ -37,6 +37,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup.VehiclesSource; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -130,7 +131,7 @@ public PseudoInputs(String travelMode){ config = scenario.getConfig(); config.qsim().setMainModes(Arrays.asList(travelMode)); config.qsim().setUsingFastCapacityUpdate(true); - + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); population = scenario.getPopulation(); } diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/FlowEfficiencyCalculatorTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/FlowEfficiencyCalculatorTest.java index 2d373a8e2b1..89594e75077 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/FlowEfficiencyCalculatorTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/FlowEfficiencyCalculatorTest.java @@ -37,6 +37,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; @@ -132,6 +133,7 @@ private Scenario createScenario() { Config config = ConfigUtils.createConfig(); config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setLastIteration(0); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ActivityParams genericParams = new ActivityParams("generic"); genericParams.setTypicalDuration(1.0); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/JavaRoundingErrorInQsimTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/JavaRoundingErrorInQsimTest.java index ca771b4156c..bf41bf3241c 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/JavaRoundingErrorInQsimTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/JavaRoundingErrorInQsimTest.java @@ -39,6 +39,7 @@ import org.matsim.api.core.v01.population.*; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -142,6 +143,7 @@ private static final class PseudoInputs{ public PseudoInputs(){ scenario = ScenarioUtils.createScenario(ConfigUtils.createConfig()); scenario.getConfig().qsim().setUsingFastCapacityUpdate(true); + scenario.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); population = scenario.getPopulation(); } diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/LinkSpeedCalculatorIntegrationTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/LinkSpeedCalculatorIntegrationTest.java index 2a6554df93d..c84fa35e061 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/LinkSpeedCalculatorIntegrationTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/LinkSpeedCalculatorIntegrationTest.java @@ -39,6 +39,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.Injector; import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; import org.matsim.core.controler.PrepareForSimUtils; @@ -222,7 +223,9 @@ static class Fixture { Scenario scenario; public Fixture() { - this.scenario = ScenarioUtils.createScenario(ConfigUtils.createConfig()); + Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + this.scenario = ScenarioUtils.createScenario(config); Id[] nodeIds = new Id[5]; for (int i = 0; i < nodeIds.length; i++) { diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/PassingTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/PassingTest.java index a145ecf6c39..2db8d64118c 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/PassingTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/PassingTest.java @@ -38,6 +38,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.controler.events.IterationEndsEvent; import org.matsim.core.controler.events.StartupEvent; @@ -182,6 +183,7 @@ public SimpleNetwork(){ config.qsim().setStorageCapFactor(1.0); config.qsim().setMainModes(Arrays.asList("car","bike")); config.qsim().setLinkDynamics(QSimConfigGroup.LinkDynamics.PassingQ); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); network = (Network) scenario.getNetwork(); this.network.setCapacityPeriod(Time.parseTime("1:00:00")); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QLinkLanesTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QLinkLanesTest.java index 53794c1f44a..ba289374fe9 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QLinkLanesTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QLinkLanesTest.java @@ -33,6 +33,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSim; @@ -137,6 +138,7 @@ private static void createThreeLanes(Scenario scenario) { @Test void testCapacityWoLanes() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); initNetwork(scenario.getNetwork()); @@ -155,6 +157,7 @@ void testCapacityWoLanes() { @Test void testCapacityWithOneLaneOneLane() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); initNetwork(scenario.getNetwork()); createOneLane(scenario, 1); @@ -191,6 +194,7 @@ void testCapacityWithOneLaneOneLane() { @Test void testCapacityWithOneLaneTwoLanes() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); initNetwork(scenario.getNetwork()); createOneLane(scenario, 2); @@ -228,6 +232,7 @@ void testCapacityWithOneLaneTwoLanes() { @Test void testCapacityWithLanes() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); initNetwork(scenario.getNetwork()); createThreeLanes(scenario); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QLinkTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QLinkTest.java index 394ef272b28..93e9ed84e07 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QLinkTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QLinkTest.java @@ -46,6 +46,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.gbl.MatsimRandom; @@ -313,6 +314,7 @@ void testGetVehicle_Departing(boolean isUsingFastCapacityUpdate) { @ValueSource(booleans = {true, false}) void testBuffer(boolean isUsingFastCapacityUpdate) { Config conf = utils.loadConfig((String)null); + conf.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); conf.qsim().setUsingFastCapacityUpdate(isUsingFastCapacityUpdate); @@ -543,6 +545,7 @@ void testStuckEvents(boolean isUsingFastCapacityUpdate) { Scenario scenario = ScenarioUtils.createScenario(ConfigUtils.createConfig()); scenario.getConfig().qsim().setStuckTime(100); scenario.getConfig().qsim().setRemoveStuckVehicles(true); + scenario.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); MatsimRandom.reset(4711); // yyyyyy !!!!!! Network network = (Network) scenario.getNetwork(); network.setCapacityPeriod(3600.0); @@ -622,6 +625,7 @@ private static final class Fixture { this.scenario.getConfig().qsim().setStuckTime(100); this.scenario.getConfig().qsim().setRemoveStuckVehicles(true); this.scenario.getConfig().qsim().setUsingFastCapacityUpdate(usingFastCapacityUpdate); + this.scenario.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Network network = (Network) this.scenario.getNetwork(); network.setCapacityPeriod(3600.0); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SeepageTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SeepageTest.java index c562b59987b..081028398b1 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SeepageTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SeepageTest.java @@ -40,6 +40,7 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup.LinkDynamics; import org.matsim.core.config.groups.QSimConfigGroup.VehiclesSource; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -170,6 +171,7 @@ public SimpleNetwork(){ config.qsim().setStorageCapFactor(1.0); config.qsim().setMainModes(Arrays.asList(TransportMode.car,TransportMode.walk)); config.qsim().setLinkDynamics(LinkDynamics.SeepageQ); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setSeepModes(Arrays.asList(TransportMode.walk) ); config.qsim().setSeepModeStorageFree(false); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SimulatedLaneFlowCapacityTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SimulatedLaneFlowCapacityTest.java index 018ef7c995f..36d56ad9d2c 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SimulatedLaneFlowCapacityTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/SimulatedLaneFlowCapacityTest.java @@ -48,6 +48,7 @@ import org.matsim.core.api.experimental.events.handler.LaneLeaveEventHandler; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; @@ -210,6 +211,7 @@ private static void initPopulation(Population population) { @Test void testCapacityWoLanes() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ActivityParams dummyAct = new ActivityParams("dummy"); dummyAct.setTypicalDuration(12 * 3600); config.scoring().addActivityParams(dummyAct); @@ -238,6 +240,7 @@ void testCapacityWoLanes() { @Test void testCapacityWithOneLaneOneLane() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ActivityParams dummyAct = new ActivityParams("dummy"); dummyAct.setTypicalDuration(12 * 3600); config.scoring().addActivityParams(dummyAct); @@ -270,6 +273,7 @@ void testCapacityWithOneLaneOneLane() { @Test void testCapacityWithOneLaneTwoLanes() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ActivityParams dummyAct = new ActivityParams("dummy"); dummyAct.setTypicalDuration(12 * 3600); config.scoring().addActivityParams(dummyAct); @@ -303,6 +307,7 @@ void testCapacityWithOneLaneTwoLanes() { @Test void testCapacityWithThreeLanes() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); ActivityParams dummyAct = new ActivityParams("dummy"); dummyAct.setTypicalDuration(12 * 3600); config.scoring().addActivityParams(dummyAct); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/VehVsLinkSpeedTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/VehVsLinkSpeedTest.java index 820914fc323..51d9f80872f 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/VehVsLinkSpeedTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/VehVsLinkSpeedTest.java @@ -39,6 +39,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -128,6 +129,7 @@ public SimpleNetwork(){ config.qsim().setMainModes(Arrays.asList("car")); config.qsim().setLinkDynamics(QSimConfigGroup.LinkDynamics.PassingQ); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.modeVehicleTypesFromVehiclesData); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); network = (Network) scenario.getNetwork(); this.network.setCapacityPeriod(Time.parseTime("1:00:00")); diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/VehicleHandlerTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/VehicleHandlerTest.java index 292ae461e58..bfaac4a4eaa 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/VehicleHandlerTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/VehicleHandlerTest.java @@ -43,6 +43,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; @@ -184,6 +185,7 @@ public void handleEvent(PersonArrivalEvent event) { private Scenario createScenario() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); config.controller().setLastIteration(0); config.controller().setOutputDirectory(utils.getOutputDirectory()); diff --git a/matsim/src/test/java/org/matsim/core/network/io/NetworkReprojectionIOTest.java b/matsim/src/test/java/org/matsim/core/network/io/NetworkReprojectionIOTest.java index 8398f1a7db1..3e0170943e9 100644 --- a/matsim/src/test/java/org/matsim/core/network/io/NetworkReprojectionIOTest.java +++ b/matsim/src/test/java/org/matsim/core/network/io/NetworkReprojectionIOTest.java @@ -32,6 +32,7 @@ import org.matsim.api.core.v01.network.Node; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.Controler; import org.matsim.core.network.NetworkUtils; import org.matsim.core.scenario.ProjectionUtils; @@ -119,6 +120,7 @@ void testWithControlerAndAttributes() { new NetworkWriter( initialNetwork ).write( networkFile ); final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.network().setInputFile( networkFile ); // web mercator. This would be a pretty silly choice for simulation, @@ -171,6 +173,7 @@ void testWithControlerAndConfigParameters() { new NetworkWriter( initialNetwork ).write( networkFile ); final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.network().setInputFile( networkFile ); config.network().setInputCRS( INITIAL_CRS ); diff --git a/matsim/src/test/java/org/matsim/core/router/FallbackRoutingModuleTest.java b/matsim/src/test/java/org/matsim/core/router/FallbackRoutingModuleTest.java index b2654bc7734..ecfb14eefe0 100644 --- a/matsim/src/test/java/org/matsim/core/router/FallbackRoutingModuleTest.java +++ b/matsim/src/test/java/org/matsim/core/router/FallbackRoutingModuleTest.java @@ -20,6 +20,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.ReplanningConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; import org.matsim.core.replanning.strategies.DefaultPlanStrategiesModule; @@ -33,6 +34,7 @@ public class FallbackRoutingModuleTest{ void calcRoute(){ Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setOutputDirectory( utils.getOutputDirectory() ); config.controller().setLastIteration( 1 ); diff --git a/matsim/src/test/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModuleTest.java b/matsim/src/test/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModuleTest.java index 392a301d1c4..6781d0872d2 100644 --- a/matsim/src/test/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModuleTest.java +++ b/matsim/src/test/java/org/matsim/core/router/NetworkRoutingInclAccessEgressModuleTest.java @@ -181,6 +181,7 @@ private static List> getNetworkRoute(List elements) { void calcRoute_modeVehiclesFromVehiclesData_differentTypesTakeDifferentRoutes() { Config config = createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); // set test specific things Collection modes = Arrays.asList(SLOW_MODE, FAST_MODE); @@ -234,6 +235,7 @@ void calcRoute_modeVehiclesFromVehiclesData_differentTypesTakeDifferentRoutes() void calcRoute_defaultVehicle_defaultVehicleIsAssigned() { Config config = createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.defaultVehicle); Scenario scenario = createScenario(config); @@ -266,7 +268,8 @@ void useAccessEgressTimeFromLinkAttributes() { Config config = createConfig(); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.defaultVehicle); config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.walkConstantTimeToLink); - Scenario scenario = createScenario(config); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + Scenario scenario = createScenario(config); NetworkUtils.setLinkAccessTime(scenario.getNetwork().getLinks().get(Id.createLinkId(START_LINK)),TransportMode.car,75); NetworkUtils.setLinkEgressTime(scenario.getNetwork().getLinks().get(Id.createLinkId(END_LINK)),TransportMode.car,180); // add persons @@ -285,6 +288,7 @@ void useAccessEgressTimeFromLinkAttributes() { void useAccessEgressTimeFromConstantAndWalkTime() { Config config = createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.defaultVehicle); config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.accessEgressModeToLinkPlusTimeConstant); Scenario scenario = createScenario(config); @@ -308,6 +312,7 @@ void useAccessEgressTimeFromConstantAndWalkTime() { void routingModeInEvents() { Config config = createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.defaultVehicle); config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.accessEgressModeToLinkPlusTimeConstant); Scenario scenario = createScenario(config); @@ -352,6 +357,7 @@ void failifNoAccessTimeSet() { Config config = createConfig(); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.defaultVehicle); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.walkConstantTimeToLink); Scenario scenario = createScenario(config); NetworkUtils.setLinkAccessTime(scenario.getNetwork().getLinks().get(Id.createLinkId(START_LINK)), TransportMode.car, 75); @@ -385,6 +391,7 @@ void calcAccessTimeFromDistanceToLink() { Config config = createConfig(); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.defaultVehicle); config.routing().setAccessEgressType(RoutingConfigGroup.AccessEgressType.accessEgressModeToLink); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = createScenario(config); NetworkUtils.setLinkAccessTime(scenario.getNetwork().getLinks().get(Id.createLinkId(START_LINK)),TransportMode.car,75); NetworkUtils.setLinkAccessTime(scenario.getNetwork().getLinks().get(Id.createLinkId(END_LINK)),TransportMode.car,180); @@ -410,6 +417,7 @@ void noBushwackingLegs() { Config config = createConfig(); config.qsim().setVehiclesSource(QSimConfigGroup.VehiclesSource.defaultVehicle); config.routing().setAccessEgressType(AccessEgressType.none); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); Scenario scenario = createScenario(config); NetworkUtils.setLinkAccessTime(scenario.getNetwork().getLinks().get(Id.createLinkId(START_LINK)),TransportMode.car,75); NetworkUtils.setLinkAccessTime(scenario.getNetwork().getLinks().get(Id.createLinkId(END_LINK)),TransportMode.car,180); diff --git a/matsim/src/test/java/org/matsim/core/router/PseudoTransitRoutingModuleTest.java b/matsim/src/test/java/org/matsim/core/router/PseudoTransitRoutingModuleTest.java index 74f366f4864..60a48326aeb 100644 --- a/matsim/src/test/java/org/matsim/core/router/PseudoTransitRoutingModuleTest.java +++ b/matsim/src/test/java/org/matsim/core/router/PseudoTransitRoutingModuleTest.java @@ -37,6 +37,7 @@ import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.PlanElement; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.RoutingConfigGroup.TeleportedModeParams; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.ControlerDefaultsModule; @@ -135,6 +136,7 @@ private static class Fixture { public Fixture() { s.getConfig().controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + s.getConfig().routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); TeleportedModeParams walk = new TeleportedModeParams(TransportMode.walk); walk.setBeelineDistanceFactor(1.3); walk.setTeleportedModeSpeed(3.0 / 3.6); diff --git a/matsim/src/test/java/org/matsim/core/router/TripRouterFactoryImplTest.java b/matsim/src/test/java/org/matsim/core/router/TripRouterFactoryImplTest.java index d2a23b546a1..bd671737a31 100644 --- a/matsim/src/test/java/org/matsim/core/router/TripRouterFactoryImplTest.java +++ b/matsim/src/test/java/org/matsim/core/router/TripRouterFactoryImplTest.java @@ -66,6 +66,7 @@ public class TripRouterFactoryImplTest { void testRestrictedNetworkNoPt() throws Exception { Config config = ConfigUtils.createConfig(); config.transit().setUseTransit( false ); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); testRestrictedNetwork( config ); } @@ -153,6 +154,7 @@ public void install() { @Test void testMonomodalNetwork() throws Exception { final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); final Scenario scenario = ScenarioUtils.createScenario( config ); Network net = scenario.getNetwork(); diff --git a/matsim/src/test/java/org/matsim/core/utils/timing/TimeInterpretationTest.java b/matsim/src/test/java/org/matsim/core/utils/timing/TimeInterpretationTest.java index d771d585de9..497f1233891 100644 --- a/matsim/src/test/java/org/matsim/core/utils/timing/TimeInterpretationTest.java +++ b/matsim/src/test/java/org/matsim/core/utils/timing/TimeInterpretationTest.java @@ -39,6 +39,7 @@ import org.matsim.api.core.v01.population.PopulationFactory; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.config.groups.PlansConfigGroup.TripDurationHandling; import org.matsim.core.controler.Controler; @@ -55,6 +56,7 @@ public class TimeInterpretationTest { @Test void testIgnoreDelays() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.plans().setTripDurationHandling(TripDurationHandling.ignoreDelays); Controler controller = prepareController(config); @@ -76,6 +78,7 @@ void testIgnoreDelays() { @Test void testShiftActivityEndTime() { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.plans().setTripDurationHandling(TripDurationHandling.shiftActivityEndTimes); Controler controller = prepareController(config); diff --git a/matsim/src/test/java/org/matsim/integration/SimulateAndScoreTest.java b/matsim/src/test/java/org/matsim/integration/SimulateAndScoreTest.java index 9bd875631c0..6c57b14d3ca 100644 --- a/matsim/src/test/java/org/matsim/integration/SimulateAndScoreTest.java +++ b/matsim/src/test/java/org/matsim/integration/SimulateAndScoreTest.java @@ -43,6 +43,7 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Injector; @@ -89,6 +90,7 @@ public class SimulateAndScoreTest { @Test void testRealPtScore() { final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.transit().setUseTransit(true); ScoringConfigGroup.ActivityParams h = new ScoringConfigGroup.ActivityParams("h"); @@ -240,7 +242,9 @@ public void install() { @Test void testTeleportationScore() { - Scenario scenario = ScenarioUtils.createScenario(ConfigUtils.createConfig()); + Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + Scenario scenario = ScenarioUtils.createScenario(config); Network network = scenario.getNetwork(); Node node1 = network.getFactory().createNode(Id.create("1", Node.class), new Coord(0, 0)); Node node2 = network.getFactory().createNode(Id.create("2", Node.class), new Coord(100, 0)); diff --git a/matsim/src/test/java/org/matsim/integration/replanning/ChangeTripModeIntegrationTest.java b/matsim/src/test/java/org/matsim/integration/replanning/ChangeTripModeIntegrationTest.java index e3d4651b7e0..950434f316d 100644 --- a/matsim/src/test/java/org/matsim/integration/replanning/ChangeTripModeIntegrationTest.java +++ b/matsim/src/test/java/org/matsim/integration/replanning/ChangeTripModeIntegrationTest.java @@ -38,6 +38,7 @@ import org.matsim.api.core.v01.population.Population; import org.matsim.core.config.Config; import org.matsim.core.config.groups.ReplanningConfigGroup.StrategySettings; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Injector; import org.matsim.core.controler.NewControlerModule; @@ -78,6 +79,7 @@ public class ChangeTripModeIntegrationTest { void testStrategyManagerConfigLoaderIntegration() { // setup config final Config config = utils.loadConfig((String)null); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); final MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); final StrategySettings strategySettings = new StrategySettings(Id.create("1", StrategySettings.class)); strategySettings.setStrategyName("ChangeTripMode"); diff --git a/matsim/src/test/java/org/matsim/integration/timevariantnetworks/QSimIntegrationTest.java b/matsim/src/test/java/org/matsim/integration/timevariantnetworks/QSimIntegrationTest.java index 609737eb135..7c0b8b6eac7 100644 --- a/matsim/src/test/java/org/matsim/integration/timevariantnetworks/QSimIntegrationTest.java +++ b/matsim/src/test/java/org/matsim/integration/timevariantnetworks/QSimIntegrationTest.java @@ -50,6 +50,7 @@ import org.matsim.api.core.v01.population.Population; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.PrepareForSimUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.mobsim.qsim.QSimBuilder; @@ -82,6 +83,7 @@ public class QSimIntegrationTest { @Test void testFreespeed() { Config config = utils.loadConfig((String)null); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.network().setTimeVariantNetwork(true); Scenario scenario = ScenarioUtils.createScenario(config); @@ -132,6 +134,7 @@ void testCapacity() { final double capacityFactor = 0.5; Config config = utils.loadConfig((String)null); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.network().setTimeVariantNetwork(true); MutableScenario scenario = (MutableScenario) ScenarioUtils.createScenario(config); @@ -203,6 +206,7 @@ void testZeroCapacity() { final double capacityFactor = 0.0; Config config = utils.loadConfig((String)null); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.network().setTimeVariantNetwork(true); config.qsim().setStartTime(0.0); final double simEndTime = 7200.0; diff --git a/matsim/src/test/java/org/matsim/withinday/controller/ExperiencedPlansWriterTest.java b/matsim/src/test/java/org/matsim/withinday/controller/ExperiencedPlansWriterTest.java index bad57d42cc7..e6cc6ff0c15 100644 --- a/matsim/src/test/java/org/matsim/withinday/controller/ExperiencedPlansWriterTest.java +++ b/matsim/src/test/java/org/matsim/withinday/controller/ExperiencedPlansWriterTest.java @@ -38,6 +38,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.ControllerConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; @@ -82,6 +83,7 @@ void testWriteFile() { Config config = ConfigUtils.createConfig(); config.controller().setOutputDirectory(this.utils.getOutputDirectory()); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.qsim().setEndTime(24 * 3600); diff --git a/matsim/src/test/java/org/matsim/withinday/trafficmonitoring/WithinDayTravelTimeWithNetworkChangeEventsTest.java b/matsim/src/test/java/org/matsim/withinday/trafficmonitoring/WithinDayTravelTimeWithNetworkChangeEventsTest.java index 2b63bbb9f0d..1de5fb1096d 100644 --- a/matsim/src/test/java/org/matsim/withinday/trafficmonitoring/WithinDayTravelTimeWithNetworkChangeEventsTest.java +++ b/matsim/src/test/java/org/matsim/withinday/trafficmonitoring/WithinDayTravelTimeWithNetworkChangeEventsTest.java @@ -43,6 +43,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.ControllerConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; @@ -77,6 +78,7 @@ final void testTTviaMobSimAfterSimStepListener() { String outputDirectory = testUtils.getOutputDirectory() + "output_TTviaMobsimAfterSimStepListener/"; final Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setFirstIteration(0); config.controller().setLastIteration(0); From ad6f17ef81eec7b56a9defc49f5e4e93843a4dc4 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Thu, 25 Jul 2024 11:25:16 +0200 Subject: [PATCH 018/111] adapt error messages --- .../matsim/core/population/algorithms/PersonPrepareForSim.java | 3 ++- .../java/org/matsim/core/router/NetworkRoutingProvider.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/matsim/src/main/java/org/matsim/core/population/algorithms/PersonPrepareForSim.java b/matsim/src/main/java/org/matsim/core/population/algorithms/PersonPrepareForSim.java index 05ace3d8040..ac5c47c8081 100644 --- a/matsim/src/main/java/org/matsim/core/population/algorithms/PersonPrepareForSim.java +++ b/matsim/src/main/java/org/matsim/core/population/algorithms/PersonPrepareForSim.java @@ -207,7 +207,8 @@ private void checkModeConsistent(Person person, Leg leg) { if(!linkModesConsistent){ String errorMessage = "Route inconsistent with link modes for: Person " + person.getId() + "; Leg '" + leg + "'"; - log.error(errorMessage + "\n Consider cleaning inconsistent routes by using PopulationUtils.checkRouteModeAndReset()."); + log.error(errorMessage + "\n Consider cleaning inconsistent routes by using PopulationUtils.checkRouteModeAndReset()." + + "\n If this is intended, set the routing config parameter 'networkRouteConsistencyCheck' to 'disable'."); throw new RuntimeException(errorMessage); } } diff --git a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java index 6f4a1bbd40f..a6c00d06942 100644 --- a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java +++ b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java @@ -149,7 +149,8 @@ private void checkNetwork(Network filteredNetwork) { if(changed) { String errorMessage = "Network for mode '" + mode + "' has unreachable links and nodes. This may be caused by mode restrictions on certain links. Aborting."; - log.error(errorMessage + "\n If you restricted modes on some links, consider doing that with NetworkUtils.restrictModesAndCleanNetwork(). This makes sure, that the network is consistent for each mode."); + log.error(errorMessage + "\n If you restricted modes on some links, consider doing that with NetworkUtils.restrictModesAndCleanNetwork(). This makes sure, that the network is consistent for each mode." + + "\n If this network topology is intended, set the routing config parameter 'networkRouteConsistencyCheck' to 'disable'."); throw new RuntimeException(errorMessage); } } From 96b14eea07da6bbb5e2e1d611fe4b2ee69ef3df1 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Thu, 25 Jul 2024 17:21:28 +0200 Subject: [PATCH 019/111] fix test failures by disable net consistency check --- matsim/src/test/java/org/matsim/core/controler/ControlerIT.java | 1 + .../invertednetworks/InvertedNetworkRoutingTestFixture.java | 2 ++ .../integration/population/NonAlternatingPlanElementsIT.java | 2 ++ 3 files changed, 5 insertions(+) diff --git a/matsim/src/test/java/org/matsim/core/controler/ControlerIT.java b/matsim/src/test/java/org/matsim/core/controler/ControlerIT.java index 2a735f508af..703ea500d06 100644 --- a/matsim/src/test/java/org/matsim/core/controler/ControlerIT.java +++ b/matsim/src/test/java/org/matsim/core/controler/ControlerIT.java @@ -1018,6 +1018,7 @@ private static class Fixture { Link link3 = null; protected Fixture(final Config config) { + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); this.scenario = ScenarioUtils.createScenario(config); this.network = this.scenario.getNetwork(); diff --git a/matsim/src/test/java/org/matsim/integration/invertednetworks/InvertedNetworkRoutingTestFixture.java b/matsim/src/test/java/org/matsim/integration/invertednetworks/InvertedNetworkRoutingTestFixture.java index e63fb5115fa..4a0a6ef92bd 100644 --- a/matsim/src/test/java/org/matsim/integration/invertednetworks/InvertedNetworkRoutingTestFixture.java +++ b/matsim/src/test/java/org/matsim/integration/invertednetworks/InvertedNetworkRoutingTestFixture.java @@ -38,6 +38,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; import org.matsim.core.config.groups.ReplanningConfigGroup.StrategySettings; import org.matsim.core.replanning.strategies.DefaultPlanStrategiesModule; @@ -78,6 +79,7 @@ public class InvertedNetworkRoutingTestFixture { public InvertedNetworkRoutingTestFixture(boolean doCreateModes, boolean doCreateLanes, boolean doCreateSignals) { Config config = ConfigUtils.createConfig(); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setLastIteration(0); config.controller().setLinkToLinkRoutingEnabled(true); config.travelTimeCalculator().setCalculateLinkToLinkTravelTimes(true); diff --git a/matsim/src/test/java/org/matsim/integration/population/NonAlternatingPlanElementsIT.java b/matsim/src/test/java/org/matsim/integration/population/NonAlternatingPlanElementsIT.java index 033857c8a4c..d4caf530dc0 100644 --- a/matsim/src/test/java/org/matsim/integration/population/NonAlternatingPlanElementsIT.java +++ b/matsim/src/test/java/org/matsim/integration/population/NonAlternatingPlanElementsIT.java @@ -37,6 +37,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.groups.FacilitiesConfigGroup; import org.matsim.core.config.groups.PlansConfigGroup.HandlingOfPlansWithoutRoutingMode; +import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.Controler; import org.matsim.core.network.io.MatsimNetworkReader; import org.matsim.core.population.routes.NetworkRoute; @@ -97,6 +98,7 @@ void test_Controler_QSim_Routechoice_acts() { @Test void test_Controler_QSim_Routechoice_legs() { Config config = this.utils.loadConfig("test/scenarios/equil/config.xml"); + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); config.controller().setMobsim("qsim"); config.controller().setLastIteration(10); config.plans().setHandlingOfPlansWithoutRoutingMode(HandlingOfPlansWithoutRoutingMode.useMainModeIdentifier); From ec12c86f97b0f0918036b9b65f94340d41ffc723 Mon Sep 17 00:00:00 2001 From: Chengqi Lu <43133404+luchengqi7@users.noreply.github.com> Date: Thu, 1 Aug 2024 15:41:27 +0200 Subject: [PATCH 020/111] Update GenerateFreightPlans.java (#3387) Fixing one typo in "GenerateFreightPlans.java" and some minor updates in the input sample size interpretation and output naming. No changes in the functionality. --- .../freight/tripGeneration/GenerateFreightPlans.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripGeneration/GenerateFreightPlans.java b/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripGeneration/GenerateFreightPlans.java index 0d4fa163ee1..e79d06632d6 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripGeneration/GenerateFreightPlans.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripGeneration/GenerateFreightPlans.java @@ -35,7 +35,7 @@ public class GenerateFreightPlans implements MATSimAppCommand { defaultValue = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/german-wide-freight/v2/germany-europe-network.xml.gz") private String networkPath; - @CommandLine.Option(names = "--nuts", description = "Path to desired network file", required = true) + @CommandLine.Option(names = "--nuts", description = "Path to NUTS file (available on SVN: )", required = true) // TODO Change this to URL pointing to SVN--> need to update the Location calculator private Path shpPath; @@ -48,8 +48,8 @@ public class GenerateFreightPlans implements MATSimAppCommand { @CommandLine.Option(names = "--working-days", defaultValue = "260", description = "Number of working days in a year") private int workingDays; - @CommandLine.Option(names = "--sample", defaultValue = "1", description = "Scaling factor of the freight traffic (0, 1)") - private double sample; + @CommandLine.Option(names = "--sample", defaultValue = "100", description = "Sample size of the freight plans (0, 100]") + private double pct; @CommandLine.Mixin private LanduseOptions landuse = new LanduseOptions(); @@ -60,7 +60,7 @@ public Integer call() throws Exception { log.info("Network successfully loaded!"); log.info("preparing freight agent generator..."); - FreightAgentGenerator freightAgentGenerator = new FreightAgentGenerator(network, shpPath, landuse, averageTruckLoad, workingDays, sample); + FreightAgentGenerator freightAgentGenerator = new FreightAgentGenerator(network, shpPath, landuse, averageTruckLoad, workingDays, pct / 100); log.info("Freight agent generator successfully created!"); log.info("Reading trip relations..."); @@ -84,7 +84,7 @@ public Integer call() throws Exception { Files.createDirectory(output); } - String outputPlansPath = output.toString() + "/german_freight.25pct.plans.xml.gz"; + String outputPlansPath = output.toString() + "/german_freight." + pct + "pct.plans.xml.gz"; PopulationWriter populationWriter = new PopulationWriter(outputPopulation); populationWriter.write(outputPlansPath); From 8dc0f7397154a42ad7108998dcd0240aba8e1be3 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Thu, 1 Aug 2024 15:54:03 +0200 Subject: [PATCH 021/111] add events files comparison --- .../matsim/examples/ModeRestrictionTest.java | 26 +++++++++- .../org/matsim/testcases/MatsimTestUtils.java | 47 +++++++++++++++--- .../bike/output_events.xml.gz | Bin 0 -> 854 bytes .../car/output_events.xml.gz | Bin 0 -> 864 bytes .../bike/output_events.xml.gz | Bin 0 -> 854 bytes .../car/output_events.xml.gz | Bin 0 -> 867 bytes .../15_bike/output_events.xml.gz | Bin 0 -> 686 bytes .../15_car/output_events.xml.gz | Bin 0 -> 686 bytes .../20_bike/output_events.xml.gz | Bin 0 -> 686 bytes .../20_car/output_events.xml.gz | Bin 0 -> 686 bytes .../6_bike/output_events.xml.gz | Bin 0 -> 686 bytes .../6_car/output_events.xml.gz | Bin 0 -> 686 bytes .../bike/output_events.xml.gz | Bin 0 -> 972 bytes .../car/output_events.xml.gz | Bin 0 -> 982 bytes 14 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_fromActNotPossible_withConsistencyCheck_ok/bike/output_events.xml.gz create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_fromActNotPossible_withConsistencyCheck_ok/car/output_events.xml.gz create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_toActNotPossible_withConsistencyCheck_ok/bike/output_events.xml.gz create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_toActNotPossible_withConsistencyCheck_ok/car/output_events.xml.gz create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/15_bike/output_events.xml.gz create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/15_car/output_events.xml.gz create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/20_bike/output_events.xml.gz create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/20_car/output_events.xml.gz create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/6_bike/output_events.xml.gz create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/6_car/output_events.xml.gz create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/testRerouteBeforeSim_actOnRestrictedLinkWithCoords_ok/bike/output_events.xml.gz create mode 100644 matsim/test/input/org/matsim/examples/ModeRestrictionTest/testRerouteBeforeSim_actOnRestrictedLinkWithCoords_ok/car/output_events.xml.gz diff --git a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java index a1bb8fb9c6b..dee40f8f38d 100644 --- a/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java +++ b/matsim/src/test/java/org/matsim/examples/ModeRestrictionTest.java @@ -29,11 +29,13 @@ import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; +import org.matsim.core.events.EventsUtils; import org.matsim.core.network.NetworkUtils; import org.matsim.core.population.PopulationUtils; import org.matsim.core.router.util.TravelTime; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.testcases.MatsimTestUtils; +import org.matsim.utils.eventsfilecomparison.ComparisonResult; import org.matsim.vehicles.Vehicle; import java.util.*; @@ -78,6 +80,7 @@ void testNoRouteChange_noConsistencyCheck_ok(String link, String restrictedMode) Map.of(Id.createPersonId("car"), List.of(linkId), Id.createPersonId("bike"), List.of(linkId))); runController(scenario, firstLegRouteCheck); firstLegRouteCheck.assertActualContainsExpected(); + assertEventFilesSame(); } /** @@ -96,7 +99,7 @@ void testNoRouteChange_withConsistencyCheck_throws(String link, String restricte FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(); RuntimeException exception = Assertions.assertThrows(RuntimeException.class, () -> runController(scenario, firstLegRouteCheck)); - Assertions.assertTrue(exception instanceof ProvisionException); + Assertions.assertInstanceOf(ProvisionException.class, exception); Assertions.assertTrue(((ProvisionException) exception).getErrorMessages().stream() .map(Message::getMessage) .anyMatch(m -> m.equals("java.lang.RuntimeException: Network for mode '" + restrictedMode + "' has unreachable links and nodes. This may be caused by mode restrictions on certain links. Aborting."))); @@ -169,6 +172,7 @@ void testCleanNetworkAndRerouteBeforeSim_toActNotPossible_withConsistencyCheck_o FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(Map.of(Id.createPersonId(restrictedMode), newRoute, Id.createPersonId(other), oldRoute)); runController(scenario, firstLegRouteCheck); firstLegRouteCheck.assertActualEqualsExpected(); + assertEventFilesSame(); } /** @@ -196,6 +200,7 @@ void testCleanNetworkAndRerouteBeforeSim_fromActNotPossible_withConsistencyCheck FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(Map.of(Id.createPersonId(restrictedMode), newRoute, Id.createPersonId(other), oldRoute)); runController(scenario, firstLegRouteCheck); firstLegRouteCheck.assertActualEqualsExpected(); + assertEventFilesSame(); } /** @@ -219,6 +224,7 @@ void testRerouteBeforeSim_actOnRestrictedLinkWithCoords_ok(String restrictedMode FirstLegVisitedLinksCheck firstLegRouteCheck = new FirstLegVisitedLinksCheck(Map.of(Id.createPersonId(restrictedMode), newRoute, Id.createPersonId(other), oldRoute)); runController(scenario, firstLegRouteCheck); firstLegRouteCheck.assertActualEqualsExpected(); + assertEventFilesSame(); } /** @@ -243,7 +249,7 @@ void testRerouteBeforeSim_actOnRestrictedLinkWithoutCoord_throws(String restrict } private Config prepareConfig(String plansFile, RoutingConfigGroup.NetworkRouteConsistencyCheck consistencyCheck) { - final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml"); + final Config config = utils.loadConfig(utils.getClassInputDirectory() + "config.xml", MatsimTestUtils.TestMethodType.Parameterized); config.routing().setNetworkRouteConsistencyCheck(consistencyCheck); config.plans().setInputFile(plansFile); @@ -367,4 +373,20 @@ private static class BikeTravelTime implements TravelTime { return 1. ; } } + + /** + * Note that this method alone would be sufficient to check the simulation behaviour. But since I have already written the eventHandler, I will use it as well. + * If at some point it is too nervig, to maintain both test methodologies here, the eventHandler can be removed. + * But, I think it makes clearer what is the relevant thing to check. paul aug '24 + */ + private void assertEventFilesSame() { + String fileName = "output_events.xml.gz"; + + String inputFile = utils.getInputDirectory() + utils.getParameterizedTestInputString() + "/" + fileName; + String outputFile = utils.getOutputDirectory() + "/" + fileName; + + ComparisonResult comparisonResult = EventsUtils.compareEventsFiles(inputFile, outputFile); + if (comparisonResult != ComparisonResult.FILES_ARE_EQUAL) + Assertions.fail("Event files are not equal: " + comparisonResult); + } } diff --git a/matsim/src/test/java/org/matsim/testcases/MatsimTestUtils.java b/matsim/src/test/java/org/matsim/testcases/MatsimTestUtils.java index 112bcaaddaf..287858329cb 100644 --- a/matsim/src/test/java/org/matsim/testcases/MatsimTestUtils.java +++ b/matsim/src/test/java/org/matsim/testcases/MatsimTestUtils.java @@ -51,6 +51,10 @@ public final class MatsimTestUtils implements BeforeEachCallback, AfterEachCallback { private static final Logger log = LogManager.getLogger(MatsimTestUtils.class); + public enum TestMethodType { + Normal, Parameterized + } + /** * A constant for the exactness when comparing doubles. */ @@ -79,6 +83,7 @@ public final class MatsimTestUtils implements BeforeEachCallback, AfterEachCallb private Class testClass = null; private String testMethodName = null; + private String testDisplayName = null; public MatsimTestUtils() { MatsimRandom.reset(); @@ -88,6 +93,7 @@ public MatsimTestUtils() { public void beforeEach(ExtensionContext extensionContext) { this.testClass = extensionContext.getTestClass().orElseThrow(); this.testMethodName = extensionContext.getRequiredTestMethod().getName(); + this.testDisplayName = extensionContext.getDisplayName(); } @Override @@ -163,37 +169,62 @@ public Config createConfig(URL context) { return config; } - /** - * Loads a configuration from file (or the default config if configfile is null). + * Loads a configuration from file (or the default config if configfile is null) + * and sets the output directory to {classPath}/{methodName}/. For parameterized tests, the output directory is {classPath}/{methodName}/{parameters}/. * * @param configfile The path/filename of a configuration file, or null to load the default configuration. * @return The loaded configuration. */ - public Config loadConfig(final String configfile, final ConfigGroup... customGroups) { + public Config loadConfig(final String configfile, TestMethodType testMethodType, final ConfigGroup... customGroups) { Config config; if (configfile != null) { config = ConfigUtils.loadConfig(configfile, customGroups); } else { config = ConfigUtils.createConfig( customGroups ); } - this.outputDirectory = getOutputDirectory(); - config.controller().setOutputDirectory(this.outputDirectory); - return config; + return setOutputDirectory(config, testMethodType); } - public Config loadConfig(final URL configfile, final ConfigGroup... customGroups) { + public Config loadConfig(final String configfile, final ConfigGroup... customGroups) { + return loadConfig(configfile, TestMethodType.Normal, customGroups); + } + + public Config loadConfig(final URL configfile, TestMethodType testMethodType, final ConfigGroup... customGroups) { Config config; if (configfile != null) { config = ConfigUtils.loadConfig(configfile, customGroups); } else { config = ConfigUtils.createConfig( customGroups ); } - this.outputDirectory = getOutputDirectory(); + return setOutputDirectory(config, testMethodType); + } + + public Config loadConfig(final URL configfile, final ConfigGroup... customGroups) { + return loadConfig(configfile, TestMethodType.Normal, customGroups); + } + + /** + * Sets the output directory to {classPath}/{methodName}/{subDir}. For normal tests, there is no {subDir}. + * For parameterized tests, {subDir} is a slightly adapted test input parameter string (aka display name of JUnit 5). + * E.g.: "[1] car, 6" will be transformed to "car_6". + */ + private Config setOutputDirectory(Config config, TestMethodType testMethodType) { + String subDirectory = switch (testMethodType) { + case Normal -> ""; + case Parameterized -> getParameterizedTestInputString(); + }; + this.outputDirectory = getOutputDirectory(subDirectory); config.controller().setOutputDirectory(this.outputDirectory); return config; } + public String getParameterizedTestInputString() { + String parameters = this.testDisplayName.replaceFirst("^.*?\\]", "").trim(); + parameters = parameters.replaceAll(" ", "").replaceAll("[^a-zA-Z0-9]", "_"); + return parameters; + } + public Config createConfig(final ConfigGroup... customGroups) { Config config = ConfigUtils.createConfig( customGroups ); this.outputDirectory = getOutputDirectory(); diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_fromActNotPossible_withConsistencyCheck_ok/bike/output_events.xml.gz b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_fromActNotPossible_withConsistencyCheck_ok/bike/output_events.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..b310d236f60666334525ab3d0c3b0f9e477e85c2 GIT binary patch literal 854 zcmV-c1F8HUiwFP!00000|Gk-AZ<{a_hOgIOfw=E#K1-w|z1rO-RnxTFiGkCiI1mws zwEunvx)vKaJ|@tsC=Pz!<71x>ll8;PfmszTPg#*~Z09SnEt)4qn&nR$`^v!<;WSTe>nP^bQ zkaoiB#%?~vlwZxC>E&t=Wn*BOFKx>c=ymHW_!p*?L4jGn+L=Rs=Z|KGT!a7 zWNd$Af8~^4igMrCl9DoEOGO`xQ^r4z=dcydhZT(Oc%w3^rA0Igps7R&5fs8-sW@5{=^1BU?@OwoWqrJ8+&4hBEh)2Spop9(hURrL?4{#%= z=k+`>)P0WD#rk0@s}HUi66XV_sO@&=)H7&)+wlp_udE1G=9ck(`s=TMAg)1yR+crS zAw_sQgb#6H4OFN{B({_dJb> zTyvllbHJKm5;h7KOqun%l=#;J!JJtWMG_mW9+(u?7aUEQ3&?3QrsT4z?+bj_?Mlv8 zE)_1g_aUNOsyuM(C*2~2@3DJ52Vb+feV>@`ZQw+U?5)DZ$2AtXcwF}d7maI0&Lpm< zwnB>JY^_ku4f>@E(+Vw7x@vR4n<%;_Dd5bP=f199(-OYwH zq-1CD!QIW5e%)imk!;b*k1=im?ES>QrWqq;j=U4!({9Pq8hNxR4}3TB-nQs=72$rv z`xbSde9O;n?+fz0I|n}}r?h65nwUgT^8CHZ`IE0HJs>Zuj;9Mt8P`9hKdKAkCicH~ z+nn-bd;Sy$va~^xj1P3&~iMzeG>O2S^N`Y<%7CY0OSkf-Wguupf@YvX@vL&=_X!W<%=LjMX}N?skOpj zSQ6sUqSj=RRxNmbU5CT6!Cj~!loGjV$O|6yWyYU~qyG8hpsqWyN)ocR32vN{gEXCu zF-P!cy`nudzQWxbCePJJ%_t4tRdvhbn<`P9H92*N4^OfHM`R_@7!fX{qizMBjn?*T zq{wn2w2=j&tgQ)XJVKig0rmvgk8C+-0>haEjhGNewnG7DEQzF5Xa$GGL+e~E;lOoO zqp$E?Neyc+2ntCFXv@E?A!0^x<81l2|yU94nJ9jl4o4fv>%-vriVr@eC8~^}QvYmDS literal 0 HcmV?d00001 diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_toActNotPossible_withConsistencyCheck_ok/bike/output_events.xml.gz b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testCleanNetworkAndRerouteBeforeSim_toActNotPossible_withConsistencyCheck_ok/bike/output_events.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..42ba2aa5fe1580b81af3663b1b629f3f4d274fc2 GIT binary patch literal 854 zcmV-c1F8HUiwFP!00000|Gk-AZ<{a_hOgIOfw=E#%twfnq*uG!q-vUWJ27xt6ao=( zNc-<+plY#!<6{E5isInsJwEpNFxfo59y6OKC~Zq zcN(;)f zK4~YsZSCe$O!?K!eX%X;LBmhjDJuD;WMdK;d;U=*?0q;cj;9NcxG+D;eij!lR@nJj zEBDlBe9O7`{LNm{I8%kIb`%R#{qr|Hu%#WOXnc6+8f6E_MeRJT;=2dL397wh@iN-) z(|BxuWPjz1UyJh4*^-iF!j_6X73Y+H9?xMboKGttHB^XTL zdw?ku7=xx@(xUJ9K4gkHW6%_ezyxa&K&F^822F7hn3YFXkSXSj!90(lth*GGG(TtT z$X3jdW8hgKDc5?oDZC$w&$Hw&!7cv$0xMFvLaXzTgJ!fufP6*xDLK9D$5$u zkRrSt!iTu92I_1_B(O8o1AV9u`gtQ*znVw+0@iUCG(X zrNV{FrH`nWDiE%hlkRWA``F!{ML<^(`))DcU*8EA*-WnSrX5Ea>9(Fey zQjwgU#T$1w-`eXA%Z_A=R&I!K4PYN9{xwb*$y4N<_?mi25|_xKS$^QFk@LPqx2piR z3qH1}`Q%G}Hf!II zgHdBaDx=&04D$up{|84&ToK!Y(}+xZa-uoy`Fv`OnRY%!Zd{gG6;r)mQlQy^2|F_$ zym}%}4=&bahpSQ|^d$*>`k6z(mVWx%G9v$olJn&skvk~=EOCsvIi4v2!Q)dTse*ll z!LZ23zQL@~B&AvKEW7r*#e+Ysicm`A)*;P!h~){tBMjR6kDcmn#r9&}*euv_y@*%z zH`;jQ_c~d0CeFAKy*fg3xVHUfye#Y zH`e%`mKC9lEC^+7OhCgC$~FVwkB8mBlygQftVvLd@o`|<6mZ6pNJ@iNa9G&&&eno; zj&9%S31?R_!`OO(LQ(>n@^9^km{IIFQ~s@aJSA$UF+f7>%jweZ{9@+pD{R)t(bl{7 zacBw!_~{i%%24pYu*mQ3!(5$!gf(^o0iYF-dB#>?RBP_>DsXRlKJYCSNy;=1W%0@c zjEQkxOMFWc(tlEe!@zfi%^5WP&ObFs*335iN?h~s3z&Uno_Y2i^=8bE@DhnY!h%Z@ zl(%qA>dP%ylO(YLHEG;PAn8pX32I=_4{pFnFl%2`n_(=qfX-E7SjTNGCJ2mGWjMpy z`f4x%_HYDkKwu1O>!HO&cnz(!Fovzl>L{+)r3{z^<{V-rE2a+u5)k?#21r}_JxpJ3 t$@egl+T#Cl1#7pfH&>yRuv6c?$vDU}w>2D_yY@fL-Cy(t-dzJ7002pLtq}kK literal 0 HcmV?d00001 diff --git a/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/15_bike/output_events.xml.gz b/matsim/test/input/org/matsim/examples/ModeRestrictionTest/testNoRouteChange_noConsistencyCheck_ok/15_bike/output_events.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..c6c664e79df325ee9f407712f85dd33c6def4622 GIT binary patch literal 686 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 E0OT0pq5uE@ literal 0 HcmV?d00001 From 7dd60f1552ba5c527b740694c5e4766029423229 Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Fri, 2 Aug 2024 19:35:34 +0200 Subject: [PATCH 022/111] more (javadoc) comments --- .../matsim/application/MATSimApplication.java | 53 ++++++++++++++----- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/contribs/application/src/main/java/org/matsim/application/MATSimApplication.java b/contribs/application/src/main/java/org/matsim/application/MATSimApplication.java index 7d63518e323..4e4c6860d63 100644 --- a/contribs/application/src/main/java/org/matsim/application/MATSimApplication.java +++ b/contribs/application/src/main/java/org/matsim/application/MATSimApplication.java @@ -153,7 +153,14 @@ public Integer call() throws Exception { // load config if not present yet. if (config == null) { - config = loadConfig(Objects.requireNonNull( configPath, "No default scenario location given" ).getAbsoluteFile().toString() ); + String path = Objects.requireNonNull( configPath, "No default scenario location given" ).getAbsoluteFile().toString(); + List customModules = getCustomModules(); + + final Config config1 = ConfigUtils.loadConfig(path, customModules.toArray(new ConfigGroup[0] ) ); + Config prepared = prepareConfig( config1 ); + + config = prepared != null ? prepared : config1; + // (The above lines of code come from inlining so maybe it happened there: I cannot see how prepared could be null but config1 not except if user code returns null which I would consider a bug. kai, aug'24) } else { Config tmp = prepareConfig(config); config = tmp != null ? tmp : config; @@ -306,15 +313,6 @@ protected final void addRunOption(Config config, String option) { addRunOption(config, option, ""); } - private Config loadConfig(String path) { - List customModules = getCustomModules(); - - final Config config = ConfigUtils.loadConfig(path, customModules.toArray(new ConfigGroup[0])); - Config prepared = prepareConfig(config); - - return prepared != null ? prepared : config; - } - @Override public String defaultValue(CommandLine.Model.ArgSpec argSpec) throws Exception { Object obj = argSpec.userObject(); @@ -374,8 +372,39 @@ public static void run(Class clazz, String... args) } /** - * Convenience method to run a scenario from code or automatically with gui when desktop application is detected. - * This method may also be used to predefine some default arguments. + *

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

+ * + *

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

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

+ * + *

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

+ * + *

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

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

+ * * @param clazz class of the scenario to run * @param args pass arguments from the main method * @param defaultArgs predefined default arguments that will always be present From d4a2962d3217da15a6265f77604800e4471c1584 Mon Sep 17 00:00:00 2001 From: Kai Martins-Turner Date: Sun, 4 Aug 2024 22:00:37 +0200 Subject: [PATCH 023/111] add test which includes tolling. One test is failing, because it is not possible to create different schemes for the different types. --- .../NetworkBasedTransportCostsTest.java | 174 ++++++++++++++++-- 1 file changed, 163 insertions(+), 11 deletions(-) diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsTest.java index ccdb7095162..63870ca8ed3 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 @@ -30,9 +30,13 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.roadpricing.RoadPricingScheme; +import org.matsim.contrib.roadpricing.RoadPricingSchemeImpl; +import org.matsim.contrib.roadpricing.RoadPricingUtils; import org.matsim.core.config.Config; import org.matsim.core.network.io.MatsimNetworkReader; import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.misc.Time; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.CostInformation; import org.matsim.vehicles.VehicleType; @@ -47,6 +51,8 @@ public class NetworkBasedTransportCostsTest { + private static final String TYPE_1 = "type1"; + private static final String TYPE_2 = "type2"; @RegisterExtension public final MatsimTestUtils utils = new MatsimTestUtils(); @@ -60,21 +66,21 @@ void test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem(){ Network network = scenario.getNetwork(); NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(network); - builder.addVehicleTypeSpecificCosts("type1", 10.0, 0.0, 2.0); - builder.addVehicleTypeSpecificCosts("type2", 20.0, 0.0, 4.0); + builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); + builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); NetworkBasedTransportCosts c = builder.build(); Vehicle vehicle1 = mock(Vehicle.class); com.graphhopper.jsprit.core.problem.vehicle.VehicleType type1 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); when(type1.getMaxVelocity()).thenReturn(5.0); - when(type1.getTypeId()).thenReturn("type1"); + when(type1.getTypeId()).thenReturn(TYPE_1); when(vehicle1.getType()).thenReturn(type1); when(vehicle1.getId()).thenReturn("vehicle1"); Vehicle vehicle2 = mock(Vehicle.class); com.graphhopper.jsprit.core.problem.vehicle.VehicleType type2 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); when(type2.getMaxVelocity()).thenReturn(5.0); - when(type2.getTypeId()).thenReturn("type2"); + when(type2.getTypeId()).thenReturn(TYPE_2); when(vehicle2.getType()).thenReturn(type2); when(vehicle2.getId()).thenReturn("vehicle2"); @@ -94,8 +100,8 @@ void test_whenVehicleTypeNotKnow_throwException(){ Network network = scenario.getNetwork(); NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(network); - builder.addVehicleTypeSpecificCosts("type1", 10.0, 0.0, 2.0); - builder.addVehicleTypeSpecificCosts("type2", 20.0, 0.0, 4.0); + builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); + builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); NetworkBasedTransportCosts c = builder.build(); Vehicle vehicle2 = mock(Vehicle.class); @@ -120,14 +126,14 @@ void test_whenAddingTwoVehicleTypesViaConstructor_itMustAccountForThat(){ String NETWORK_FILENAME = utils.getClassInputDirectory() + "network.xml"; new MatsimNetworkReader(scenario.getNetwork()).readFile(NETWORK_FILENAME); - VehicleType vehType1 = VehicleUtils.getFactory().createVehicleType(Id.create( "type1", VehicleType.class )); + VehicleType vehType1 = VehicleUtils.getFactory().createVehicleType(Id.create(TYPE_1, VehicleType.class )); CostInformation costInformation1 = vehType1.getCostInformation() ; costInformation1.setFixedCost( 0.0 ); costInformation1.setCostsPerMeter( 2.0 ); costInformation1.setCostsPerSecond( 0.0 ); - VehicleType vehType2 = VehicleUtils.getFactory().createVehicleType(Id.create( "type2", VehicleType.class )); + VehicleType vehType2 = VehicleUtils.getFactory().createVehicleType(Id.create(TYPE_2, VehicleType.class )); CostInformation costInformation = vehType2.getCostInformation() ; costInformation.setFixedCost( 0.0 ); @@ -136,20 +142,20 @@ void test_whenAddingTwoVehicleTypesViaConstructor_itMustAccountForThat(){ Network network = scenario.getNetwork(); NetworkBasedTransportCosts.Builder builder = - NetworkBasedTransportCosts.Builder.newInstance(network,Arrays.asList(vehType1,vehType2)); + NetworkBasedTransportCosts.Builder.newInstance(network,Arrays.asList(vehType1,vehType2)); NetworkBasedTransportCosts networkBasedTransportCosts = builder.build(); Vehicle vehicle1 = mock(Vehicle.class); com.graphhopper.jsprit.core.problem.vehicle.VehicleType type1 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); when(type1.getMaxVelocity()).thenReturn(5.0); - when(type1.getTypeId()).thenReturn("type1"); + when(type1.getTypeId()).thenReturn(TYPE_1); when(vehicle1.getType()).thenReturn(type1); when(vehicle1.getId()).thenReturn("vehicle1"); Vehicle vehicle2 = mock(Vehicle.class); com.graphhopper.jsprit.core.problem.vehicle.VehicleType type2 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); when(type2.getMaxVelocity()).thenReturn(5.0); - when(type2.getTypeId()).thenReturn("type2"); + when(type2.getTypeId()).thenReturn(TYPE_2); when(vehicle2.getType()).thenReturn(type2); when(vehicle2.getId()).thenReturn("vehicle2"); @@ -159,4 +165,150 @@ void test_whenAddingTwoVehicleTypesViaConstructor_itMustAccountForThat(){ Assertions.assertEquals(20000.0, networkBasedTransportCosts.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); } + /** + * This test is a modified version of {@link #test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem} + * In addition, there is added a road pricing scheme. + * The scheme is only set for one vehicle type: type1. + * So, only the vehicle using that type (vehicle1) should be tolled, the other (vehicle2) not. + * + */ + @Test + void test_whenAddingTwoDifferentVehicleTypes_tollOneType(){ + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile(utils.getClassInputDirectory() + "network.xml"); + + //Create Rp Scheme from code. + RoadPricingSchemeImpl scheme = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); + /* Configure roadpricing scheme. */ + RoadPricingUtils.setName(scheme, "DemoToll4Test"); + RoadPricingUtils.setType(scheme, RoadPricingScheme.TOLL_TYPE_LINK); + RoadPricingUtils.setDescription(scheme, "Tolling scheme for test."); + + /* Add general link based toll for one link */ + RoadPricingUtils.addLink(scheme, Id.createLinkId("21")); + RoadPricingUtils.createAndAddGeneralCost(scheme, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 99.99); + + /* Create the rpCalculator based on the scheme. + * Here, only for one type, the see the vehicleType dependent work of it + * */ + VehicleTypeDependentRoadPricingCalculator roadPricingCalculator = new VehicleTypeDependentRoadPricingCalculator(); + roadPricingCalculator.addPricingScheme(TYPE_1, scheme); + ///___ End creating from Code + + NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(scenario.getNetwork()); + builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); + builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); + builder.setRoadPricingCalculator(roadPricingCalculator); //add the rpCalculator to activite the tolling. + NetworkBasedTransportCosts c = builder.build(); + + Vehicle vehicle1 = mock(Vehicle.class); + com.graphhopper.jsprit.core.problem.vehicle.VehicleType type1 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); + when(type1.getMaxVelocity()).thenReturn(5.0); + when(type1.getTypeId()).thenReturn(TYPE_1); + when(vehicle1.getType()).thenReturn(type1); + when(vehicle1.getId()).thenReturn("vehicle1"); + + Vehicle vehicle2 = mock(Vehicle.class); + com.graphhopper.jsprit.core.problem.vehicle.VehicleType type2 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); + when(type2.getMaxVelocity()).thenReturn(5.0); + when(type2.getTypeId()).thenReturn(TYPE_2); + when(vehicle2.getType()).thenReturn(type2); + when(vehicle2.getId()).thenReturn("vehicle2"); + + //vehicle1: includes toll + Assertions.assertEquals(20099.99, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle1), 0.01); + Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle1), 0.01); + + //vehicle 2: no toll + Assertions.assertEquals(40000.0, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle2), 0.01); + Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); + } + + /** + * This test is a modified version of {@link #test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem} + * In addition, there is added a road pricing scheme. + * Two different schemes are created to toll the two different vehicle types differently. + */ + @Test + void test_whenAddingTwoDifferentVehicleTypes_tollBothTypesDifferently(){ + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile(utils.getClassInputDirectory() + "network.xml"); + + //Create Rp Scheme from code. + RoadPricingSchemeImpl scheme1 = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); + /* Configure roadpricing scheme. */ + RoadPricingUtils.setName(scheme1, "DemoToll4TestType1"); + RoadPricingUtils.setType(scheme1, RoadPricingScheme.TOLL_TYPE_LINK); + RoadPricingUtils.setDescription(scheme1, "Tolling scheme for test."); + + /* Add general link based toll for one link */ + RoadPricingUtils.addLink(scheme1, Id.createLinkId("21")); + RoadPricingUtils.createAndAddGeneralCost(scheme1, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 99.99); + + //Create Rp Scheme from code. + //Fixme: The following does not work as one may expect: In the end, both schemes are the same object. + // --> It is just added a second entry to the costs, which is not taken into account anyways... + // Questions: + // 1.) How to build ab a second scheme, that is "independently" settable? Currently no new RoadPricingSchemeImpl() can be created without + // the addOrGet methods provided in {@link RoadPricingUtils}. + // 2.) Why does not both costs are summede up in the current behavior, so, the toll is 99.99 + 42.42 = 142.41? + // --> Which one is choose? The first? The higher one?...??? + // One solution might be to use the "withTollFactor" approach. --> Todo write an additional test for it. + // Nevertheless, the current approach leads IMO (KMT) easily to unintentional mistakes. + //kmt, Aug'24 + RoadPricingSchemeImpl scheme2 = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); + /* Configure roadpricing scheme. */ + RoadPricingUtils.setName(scheme2, "DemoToll4TestType1"); + RoadPricingUtils.setType(scheme2, RoadPricingScheme.TOLL_TYPE_LINK); + RoadPricingUtils.setDescription(scheme2, "Tolling scheme for test."); + + /* Add general link based toll for one link */ + RoadPricingUtils.addLink(scheme2, Id.createLinkId("21")); + RoadPricingUtils.createAndAddGeneralCost(scheme2, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 42.42); + + + /* Create the rpCalculator based on the scheme. + * Each vehicle type gets affected by a different tolling scheme. + * */ + //FIXME: See above/below: schem1 and scheme2 are the same object.... + VehicleTypeDependentRoadPricingCalculator roadPricingCalculator = new VehicleTypeDependentRoadPricingCalculator(); + roadPricingCalculator.addPricingScheme(TYPE_1, scheme1); + roadPricingCalculator.addPricingScheme(TYPE_2, scheme2); + + ///___ End creating from Code + + NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(scenario.getNetwork()); + builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); + builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); + builder.setRoadPricingCalculator(roadPricingCalculator); //add the rpCalculator to activate the tolling. + NetworkBasedTransportCosts c = builder.build(); + + Vehicle vehicle1 = mock(Vehicle.class); + com.graphhopper.jsprit.core.problem.vehicle.VehicleType type1 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); + when(type1.getMaxVelocity()).thenReturn(5.0); + when(type1.getTypeId()).thenReturn(TYPE_1); + when(vehicle1.getType()).thenReturn(type1); + when(vehicle1.getId()).thenReturn("vehicle1"); + + Vehicle vehicle2 = mock(Vehicle.class); + com.graphhopper.jsprit.core.problem.vehicle.VehicleType type2 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); + when(type2.getMaxVelocity()).thenReturn(5.0); + when(type2.getTypeId()).thenReturn(TYPE_2); + when(vehicle2.getType()).thenReturn(type2); + when(vehicle2.getId()).thenReturn("vehicle2"); + + //vehicle1: includes toll of 99.99 for entering the final link + Assertions.assertEquals(20099.99, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle1), 0.01); + Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle1), 0.01); + + //vehicle 2: includes toll of 42.42 for entering the final link + //Fixme: This currently fails... see comments above. + Assertions.assertEquals(40042.42, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle2), 0.01); + Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); + } + } From 3b7896d47256e7fc05cbf7550c6113608d45961e Mon Sep 17 00:00:00 2001 From: Kai Martins-Turner Date: Sun, 4 Aug 2024 22:06:31 +0200 Subject: [PATCH 024/111] WIP: Prepare test for tolling with factor. Not implemented to the end now -> Disabled. --- .../NetworkBasedTransportCostsTest.java | 66 ++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) 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 63870ca8ed3..1b7ce8fe5e3 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 @@ -25,6 +25,7 @@ import com.graphhopper.jsprit.core.problem.driver.Driver; import com.graphhopper.jsprit.core.problem.vehicle.Vehicle; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Id; @@ -270,7 +271,6 @@ void test_whenAddingTwoDifferentVehicleTypes_tollBothTypesDifferently(){ RoadPricingUtils.addLink(scheme2, Id.createLinkId("21")); RoadPricingUtils.createAndAddGeneralCost(scheme2, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 42.42); - /* Create the rpCalculator based on the scheme. * Each vehicle type gets affected by a different tolling scheme. * */ @@ -311,4 +311,68 @@ void test_whenAddingTwoDifferentVehicleTypes_tollBothTypesDifferently(){ Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); } + /** + * This test is a modified version of {@link #test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem} + * In addition, there is added a road pricing scheme. + * Two different schemes are created to toll the two different vehicle types differently. + * Here the approach using a factor is used to take into account the different types. + * //TODO: Write it completely + */ + @Test + @Disabled + void test_whenAddingTwoDifferentVehicleTypes_tollBothTypesDifferentlyWithFactor(){ + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile(utils.getClassInputDirectory() + "network.xml"); + + //Create Rp Scheme from code. + RoadPricingSchemeImpl scheme1 = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); + /* Configure roadpricing scheme. */ + RoadPricingUtils.setName(scheme1, "DemoToll4TestType1"); + RoadPricingUtils.setType(scheme1, RoadPricingScheme.TOLL_TYPE_LINK); + RoadPricingUtils.setDescription(scheme1, "Tolling scheme for test."); + + /* Add general link based toll for one link */ + RoadPricingUtils.addLink(scheme1, Id.createLinkId("21")); + RoadPricingUtils.createAndAddGeneralCost(scheme1, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 99.99); + + //Use a factor to take into account the differnt types. type2 gehts tolled with 50% of the toll of type1 + //TODO: Include factor + + VehicleTypeDependentRoadPricingCalculator roadPricingCalculator = new VehicleTypeDependentRoadPricingCalculator(); + roadPricingCalculator.addPricingScheme(TYPE_1, scheme1); + + ///___ End creating from Code + + NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(scenario.getNetwork()); + builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); + builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); + builder.setRoadPricingCalculator(roadPricingCalculator); //add the rpCalculator to activate the tolling. + NetworkBasedTransportCosts c = builder.build(); + + Vehicle vehicle1 = mock(Vehicle.class); + com.graphhopper.jsprit.core.problem.vehicle.VehicleType type1 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); + when(type1.getMaxVelocity()).thenReturn(5.0); + when(type1.getTypeId()).thenReturn(TYPE_1); + when(vehicle1.getType()).thenReturn(type1); + when(vehicle1.getId()).thenReturn("vehicle1"); + + Vehicle vehicle2 = mock(Vehicle.class); + com.graphhopper.jsprit.core.problem.vehicle.VehicleType type2 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); + when(type2.getMaxVelocity()).thenReturn(5.0); + when(type2.getTypeId()).thenReturn(TYPE_2); + when(vehicle2.getType()).thenReturn(type2); + when(vehicle2.getId()).thenReturn("vehicle2"); + + //vehicle1: includes toll of 99.99 for entering the final link + Assertions.assertEquals(20099.99, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle1), 0.01); + Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle1), 0.01); + + //vehicle 2: includes toll of 49.995 (50% of 99.99) for entering the final link + //Fixme: This currently fails... see comments above. + Assertions.assertEquals(40049.995, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle2), 0.01); + Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); + } + } From 40240461c419d161c9b1850602bd9d8af2ea0acb Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Sun, 4 Aug 2024 23:30:50 +0200 Subject: [PATCH 025/111] replace self-build RoadPricingCalculator with official RoadPricingScheme --- .../controler/CarrierVehicleReRouter.java | 7 ++-- .../jsprit/NetworkBasedTransportCosts.java | 37 +++++++++++-------- ...cleTypeDependentRoadPricingCalculator.java | 1 + .../NetworkBasedTransportCostsTest.java | 33 +++++++++++++---- 4 files changed, 51 insertions(+), 27 deletions(-) diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierVehicleReRouter.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierVehicleReRouter.java index 4a75e5c607d..cd03cb5fd94 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierVehicleReRouter.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierVehicleReRouter.java @@ -36,6 +36,7 @@ import com.graphhopper.jsprit.io.algorithm.AlgorithmConfigXmlReader; import com.graphhopper.jsprit.io.algorithm.VehicleRoutingAlgorithms; import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.roadpricing.RoadPricingScheme; import org.matsim.core.replanning.ReplanningContext; import org.matsim.core.replanning.modules.GenericPlanStrategyModule; import org.matsim.core.router.util.TravelTime; @@ -58,7 +59,7 @@ class CarrierVehicleReRouter implements GenericPlanStrategyModule{ private final VehicleRoutingActivityCosts vehicleRoutingActivityCosts; - public CarrierVehicleReRouter( Network network, CarrierVehicleTypes vehicleTypes, TravelTime travelTimes, String vrpAlgoConfigFile, VehicleTypeDependentRoadPricingCalculator roadPricing ) { + public CarrierVehicleReRouter( Network network, CarrierVehicleTypes vehicleTypes, TravelTime travelTimes, String vrpAlgoConfigFile, RoadPricingScheme roadPricing ) { this.network = network; vehicleRoutingTransportCosts = getNetworkBasedTransportCosts(network,vehicleTypes,travelTimes,roadPricing); vehicleRoutingActivityCosts = new VehicleRoutingActivityCosts() { @@ -146,7 +147,7 @@ public void handlePlan(CarrierPlan carrierPlan) { } - private NetworkBasedTransportCosts getNetworkBasedTransportCosts(Network network, CarrierVehicleTypes vehicleTypes, TravelTime travelTimes, VehicleTypeDependentRoadPricingCalculator roadPricing) { + private NetworkBasedTransportCosts getNetworkBasedTransportCosts(Network network, CarrierVehicleTypes vehicleTypes, TravelTime travelTimes, RoadPricingScheme roadPricing ) { //****** //Define transport-costs //****** @@ -157,7 +158,7 @@ private NetworkBasedTransportCosts getNetworkBasedTransportCosts(Network network //sets time-dependent travelTimes tpcostsBuilder.setTravelTime(travelTimes); - if(roadPricing != null) tpcostsBuilder.setRoadPricingCalculator(roadPricing); + if(roadPricing != null) tpcostsBuilder.setRoadPricingScheme(roadPricing ); //sets time-slice to build time-dependent tpcosts and travelTime matrices tpcostsBuilder.setTimeSliceWidth(900); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCosts.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCosts.java index f332b84cb0b..6ad51d3f5bc 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCosts.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCosts.java @@ -30,6 +30,8 @@ import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; import org.matsim.api.core.v01.population.Person; +import org.matsim.contrib.roadpricing.RoadPricingScheme; +import org.matsim.contrib.roadpricing.RoadPricingSchemeImpl; import org.matsim.core.router.speedy.SpeedyALTFactory; import org.matsim.core.router.util.LeastCostPathCalculator; import org.matsim.core.router.util.LeastCostPathCalculator.Path; @@ -83,6 +85,8 @@ */ public class NetworkBasedTransportCosts implements VRPTransportCosts { + private final RoadPricingScheme roadPricingScheme; + public interface InternalLeastCostPathCalculatorListener { void startCalculation(long routerId); @@ -320,13 +324,13 @@ static class VehicleTransportCostsIncludingToll implements TravelDisutility { private final TravelDisutility baseTransportDisutility; - private final VehicleTypeDependentRoadPricingCalculator vehicleTypeDependentPricingCalculator; + private final RoadPricingScheme roadPricingScheme; - public VehicleTransportCostsIncludingToll(TravelDisutility baseTransportDisutility, - VehicleTypeDependentRoadPricingCalculator vehicleTypeDependentPricingCalculator) { + public VehicleTransportCostsIncludingToll( TravelDisutility baseTransportDisutility, + RoadPricingScheme roadPricingScheme ) { super(); this.baseTransportDisutility = baseTransportDisutility; - this.vehicleTypeDependentPricingCalculator = vehicleTypeDependentPricingCalculator; + this.roadPricingScheme = roadPricingScheme; // System.out.println("huuuuuuuuuuuuuuuuuuuu - initialize transport costs with toll"); } @@ -334,8 +338,10 @@ public VehicleTransportCostsIncludingToll(TravelDisutility baseTransportDisutili public double getLinkTravelDisutility(Link link, double time, Person person, org.matsim.vehicles.Vehicle vehicle) { double costs = baseTransportDisutility.getLinkTravelDisutility(link, time, person, vehicle); - Id typeId = vehicle.getType().getId(); - double toll = vehicleTypeDependentPricingCalculator.getTollAmount(typeId, link, time); +// Id typeId = vehicle.getType().getId(); +// double toll = roadPricingScheme.getTollAmount(typeId, link, time ); + RoadPricingSchemeImpl.Cost costInfo = roadPricingScheme.getLinkCostInfo( link.getId(), time, person.getId(), vehicle.getId() ); + double toll = costInfo.amount; // System.out.println("huuuuuuuuuuuuuuuuuuuu - paid toll"); return costs + toll; } @@ -377,7 +383,8 @@ public static Builder newInstance(Network network) { private LeastCostPathCalculatorFactory leastCostPathCalculatorFactory = (network, travelCosts, travelTimes) -> new SpeedyALTFactory().createPathCalculator(network, travelCosts, travelTime); - private VehicleTypeDependentRoadPricingCalculator roadPricingCalculator = new VehicleTypeDependentRoadPricingCalculator(); +// private VehicleTypeDependentRoadPricingCalculator roadPricingScheme = new VehicleTypeDependentRoadPricingCalculator(); + private RoadPricingScheme roadPricingScheme; private boolean withToll = false; @@ -472,9 +479,9 @@ public Builder setThreadSafeLeastCostPathCalculatorFactory( return this; } - public Builder setRoadPricingCalculator(VehicleTypeDependentRoadPricingCalculator calculator) { + public Builder setRoadPricingScheme( RoadPricingScheme roadPricingScheme) { withToll = true; - this.roadPricingCalculator = calculator; + this.roadPricingScheme = roadPricingScheme; return this; } @@ -501,7 +508,7 @@ public NetworkBasedTransportCosts build() { baseDisutility = new BaseVehicleTransportCosts(typeSpecificCosts, travelTime); } if (withToll) { - finalDisutility = new VehicleTransportCostsIncludingToll(baseDisutility, roadPricingCalculator); + finalDisutility = new VehicleTransportCostsIncludingToll(baseDisutility, roadPricingScheme ); } else finalDisutility = baseDisutility; return new NetworkBasedTransportCosts(this); @@ -551,8 +558,6 @@ public void addVehicleTypeSpecificCosts(String typeId, double fix, double perSec private final Map matsimVehicles = new HashMap<>(); - private final VehicleTypeDependentRoadPricingCalculator roadPricingCalc; - /** * by default sets the {@link SpeedyALTFactory} */ @@ -568,7 +573,7 @@ private NetworkBasedTransportCosts(Builder builder) { this.travelTime = builder.travelTime; this.network = builder.network; this.leastCostPathCalculatorFactory = builder.leastCostPathCalculatorFactory; - this.roadPricingCalc = builder.roadPricingCalculator; + this.roadPricingScheme = builder.roadPricingScheme; this.timeSliceWidth = builder.timeSliceWidth; this.defaultTypeId = builder.defaultTypeId; this.ttMemorizedCounter = new Counter("#TransportCostValues cached "); @@ -882,8 +887,8 @@ public TravelTime getTravelTime() { * * @return {@link VehicleTypeDependentRoadPricingCalculator} */ - public VehicleTypeDependentRoadPricingCalculator getRoadPricingCalculator() { - return roadPricingCalc; - } +// public VehicleTypeDependentRoadPricingCalculator getRoadPricingCalculator() { +// return roadPricingCalc; +// } } diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/VehicleTypeDependentRoadPricingCalculator.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/VehicleTypeDependentRoadPricingCalculator.java index ed5d3694720..6175780ab9a 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/VehicleTypeDependentRoadPricingCalculator.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/VehicleTypeDependentRoadPricingCalculator.java @@ -35,6 +35,7 @@ * @author stefan schröder * */ +@Deprecated // use RoadPricingScheme public class VehicleTypeDependentRoadPricingCalculator { interface TollCalculator { diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsTest.java index 1b7ce8fe5e3..cb90a059a6e 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 @@ -30,10 +30,10 @@ 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.network.Link; import org.matsim.api.core.v01.network.Network; -import org.matsim.contrib.roadpricing.RoadPricingScheme; -import org.matsim.contrib.roadpricing.RoadPricingSchemeImpl; -import org.matsim.contrib.roadpricing.RoadPricingUtils; +import org.matsim.api.core.v01.population.Person; +import org.matsim.contrib.roadpricing.*; import org.matsim.core.config.Config; import org.matsim.core.network.io.MatsimNetworkReader; import org.matsim.core.scenario.ScenarioUtils; @@ -44,6 +44,9 @@ import org.matsim.vehicles.VehicleUtils; import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -194,14 +197,28 @@ void test_whenAddingTwoDifferentVehicleTypes_tollOneType(){ /* Create the rpCalculator based on the scheme. * Here, only for one type, the see the vehicleType dependent work of it * */ - VehicleTypeDependentRoadPricingCalculator roadPricingCalculator = new VehicleTypeDependentRoadPricingCalculator(); - roadPricingCalculator.addPricingScheme(TYPE_1, scheme); +// VehicleTypeDependentRoadPricingCalculator roadPricingScheme = new VehicleTypeDependentRoadPricingCalculator(); +// roadPricingScheme.addPricingScheme(TYPE_1, scheme); ///___ End creating from Code + TollFactor tollFactor = new TollFactor(){ + @Override public double getTollFactor( Id personId, Id vehicleId, Id linkId, double time ){ + double tollFactor = 1.; + // find vehicle: + org.matsim.vehicles.Vehicle vehicle = scenario.getVehicles().getVehicles().get( vehicleId ); // das ist schlussendlich ziemlich dumm, aber so ist die Schnittstelle im Moment + VehicleType type = vehicle.getType(); + if ( type......) { + tollFactor = 2.; + } + return tollFactor; + } + }; + RoadPricingScheme schemeUsingTollFactor = new RoadPricingSchemeUsingTollFactor( scheme , tollFactor ); + NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(scenario.getNetwork()); builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); - builder.setRoadPricingCalculator(roadPricingCalculator); //add the rpCalculator to activite the tolling. + builder.setRoadPricingScheme(schemeUsingTollFactor ); NetworkBasedTransportCosts c = builder.build(); Vehicle vehicle1 = mock(Vehicle.class); @@ -284,7 +301,7 @@ void test_whenAddingTwoDifferentVehicleTypes_tollBothTypesDifferently(){ NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(scenario.getNetwork()); builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); - builder.setRoadPricingCalculator(roadPricingCalculator); //add the rpCalculator to activate the tolling. + builder.setRoadPricingScheme(roadPricingCalculator ); //add the rpCalculator to activate the tolling. NetworkBasedTransportCosts c = builder.build(); Vehicle vehicle1 = mock(Vehicle.class); @@ -348,7 +365,7 @@ void test_whenAddingTwoDifferentVehicleTypes_tollBothTypesDifferentlyWithFactor( NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(scenario.getNetwork()); builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); - builder.setRoadPricingCalculator(roadPricingCalculator); //add the rpCalculator to activate the tolling. + builder.setRoadPricingScheme(roadPricingCalculator ); //add the rpCalculator to activate the tolling. NetworkBasedTransportCosts c = builder.build(); Vehicle vehicle1 = mock(Vehicle.class); From ae8aa5ab28408b6343cac852f528f38e08902495 Mon Sep 17 00:00:00 2001 From: Kai Martins-Turner Date: Mon, 5 Aug 2024 23:09:03 +0200 Subject: [PATCH 026/111] adapt test: use tollFactor --- .../NetworkBasedTransportCostsTest.java | 203 +++++++++--------- 1 file changed, 106 insertions(+), 97 deletions(-) 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 cb90a059a6e..58681271e6a 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 @@ -203,12 +203,16 @@ void test_whenAddingTwoDifferentVehicleTypes_tollOneType(){ TollFactor tollFactor = new TollFactor(){ @Override public double getTollFactor( Id personId, Id vehicleId, Id linkId, double time ){ - double tollFactor = 1.; - // find vehicle: - org.matsim.vehicles.Vehicle vehicle = scenario.getVehicles().getVehicles().get( vehicleId ); // das ist schlussendlich ziemlich dumm, aber so ist die Schnittstelle im Moment - VehicleType type = vehicle.getType(); - if ( type......) { - tollFactor = 2.; + double tollFactor = 0.; + + var vehTypeIdString = VehicleUtils.findVehicle(vehicleId, scenario).getType().getId().toString(); + +// // find vehicle: +// org.matsim.vehicles.Vehicle vehicle = scenario.getVehicles().getVehicles().get( vehicleId ); // das ist schlussendlich ziemlich dumm, aber so ist die Schnittstelle im Moment +// VehicleType type = vehicle.getType(); +// if (TYPE_1.equals(type.getId().toString())) { + if (TYPE_1.equals(vehTypeIdString)) { + tollFactor = 1.; } return tollFactor; } @@ -244,89 +248,89 @@ void test_whenAddingTwoDifferentVehicleTypes_tollOneType(){ Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); } - /** - * This test is a modified version of {@link #test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem} - * In addition, there is added a road pricing scheme. - * Two different schemes are created to toll the two different vehicle types differently. - */ - @Test - void test_whenAddingTwoDifferentVehicleTypes_tollBothTypesDifferently(){ - Config config = new Config(); - config.addCoreModules(); - Scenario scenario = ScenarioUtils.createScenario(config); - new MatsimNetworkReader(scenario.getNetwork()).readFile(utils.getClassInputDirectory() + "network.xml"); - - //Create Rp Scheme from code. - RoadPricingSchemeImpl scheme1 = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); - /* Configure roadpricing scheme. */ - RoadPricingUtils.setName(scheme1, "DemoToll4TestType1"); - RoadPricingUtils.setType(scheme1, RoadPricingScheme.TOLL_TYPE_LINK); - RoadPricingUtils.setDescription(scheme1, "Tolling scheme for test."); - - /* Add general link based toll for one link */ - RoadPricingUtils.addLink(scheme1, Id.createLinkId("21")); - RoadPricingUtils.createAndAddGeneralCost(scheme1, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 99.99); - - //Create Rp Scheme from code. - //Fixme: The following does not work as one may expect: In the end, both schemes are the same object. - // --> It is just added a second entry to the costs, which is not taken into account anyways... - // Questions: - // 1.) How to build ab a second scheme, that is "independently" settable? Currently no new RoadPricingSchemeImpl() can be created without - // the addOrGet methods provided in {@link RoadPricingUtils}. - // 2.) Why does not both costs are summede up in the current behavior, so, the toll is 99.99 + 42.42 = 142.41? - // --> Which one is choose? The first? The higher one?...??? - // One solution might be to use the "withTollFactor" approach. --> Todo write an additional test for it. - // Nevertheless, the current approach leads IMO (KMT) easily to unintentional mistakes. - //kmt, Aug'24 - RoadPricingSchemeImpl scheme2 = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); - /* Configure roadpricing scheme. */ - RoadPricingUtils.setName(scheme2, "DemoToll4TestType1"); - RoadPricingUtils.setType(scheme2, RoadPricingScheme.TOLL_TYPE_LINK); - RoadPricingUtils.setDescription(scheme2, "Tolling scheme for test."); - - /* Add general link based toll for one link */ - RoadPricingUtils.addLink(scheme2, Id.createLinkId("21")); - RoadPricingUtils.createAndAddGeneralCost(scheme2, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 42.42); - - /* Create the rpCalculator based on the scheme. - * Each vehicle type gets affected by a different tolling scheme. - * */ - //FIXME: See above/below: schem1 and scheme2 are the same object.... - VehicleTypeDependentRoadPricingCalculator roadPricingCalculator = new VehicleTypeDependentRoadPricingCalculator(); - roadPricingCalculator.addPricingScheme(TYPE_1, scheme1); - roadPricingCalculator.addPricingScheme(TYPE_2, scheme2); - - ///___ End creating from Code - - NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(scenario.getNetwork()); - builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); - builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); - builder.setRoadPricingScheme(roadPricingCalculator ); //add the rpCalculator to activate the tolling. - NetworkBasedTransportCosts c = builder.build(); - - Vehicle vehicle1 = mock(Vehicle.class); - com.graphhopper.jsprit.core.problem.vehicle.VehicleType type1 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); - when(type1.getMaxVelocity()).thenReturn(5.0); - when(type1.getTypeId()).thenReturn(TYPE_1); - when(vehicle1.getType()).thenReturn(type1); - when(vehicle1.getId()).thenReturn("vehicle1"); - - Vehicle vehicle2 = mock(Vehicle.class); - com.graphhopper.jsprit.core.problem.vehicle.VehicleType type2 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); - when(type2.getMaxVelocity()).thenReturn(5.0); - when(type2.getTypeId()).thenReturn(TYPE_2); - when(vehicle2.getType()).thenReturn(type2); - when(vehicle2.getId()).thenReturn("vehicle2"); - - //vehicle1: includes toll of 99.99 for entering the final link - Assertions.assertEquals(20099.99, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle1), 0.01); - Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle1), 0.01); - - //vehicle 2: includes toll of 42.42 for entering the final link - //Fixme: This currently fails... see comments above. - Assertions.assertEquals(40042.42, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle2), 0.01); - Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); - } +// /** +// * This test is a modified version of {@link #test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem} +// * In addition, there is added a road pricing scheme. +// * Two different schemes are created to toll the two different vehicle types differently. +// */ +// @Test +// void test_whenAddingTwoDifferentVehicleTypes_tollBothTypesDifferently(){ +// Config config = new Config(); +// config.addCoreModules(); +// Scenario scenario = ScenarioUtils.createScenario(config); +// new MatsimNetworkReader(scenario.getNetwork()).readFile(utils.getClassInputDirectory() + "network.xml"); +// +// //Create Rp Scheme from code. +// RoadPricingSchemeImpl scheme1 = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); +// /* Configure roadpricing scheme. */ +// RoadPricingUtils.setName(scheme1, "DemoToll4TestType1"); +// RoadPricingUtils.setType(scheme1, RoadPricingScheme.TOLL_TYPE_LINK); +// RoadPricingUtils.setDescription(scheme1, "Tolling scheme for test."); +// +// /* Add general link based toll for one link */ +// RoadPricingUtils.addLink(scheme1, Id.createLinkId("21")); +// RoadPricingUtils.createAndAddGeneralCost(scheme1, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 99.99); +// +// //Create Rp Scheme from code. +// //Fixme: The following does not work as one may expect: In the end, both schemes are the same object. +// // --> It is just added a second entry to the costs, which is not taken into account anyways... +// // Questions: +// // 1.) How to build ab a second scheme, that is "independently" settable? Currently no new RoadPricingSchemeImpl() can be created without +// // the addOrGet methods provided in {@link RoadPricingUtils}. +// // 2.) Why does not both costs are summede up in the current behavior, so, the toll is 99.99 + 42.42 = 142.41? +// // --> Which one is choose? The first? The higher one?...??? +// // One solution might be to use the "withTollFactor" approach. --> Todo write an additional test for it. +// // Nevertheless, the current approach leads IMO (KMT) easily to unintentional mistakes. +// //kmt, Aug'24 +// RoadPricingSchemeImpl scheme2 = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); +// /* Configure roadpricing scheme. */ +// RoadPricingUtils.setName(scheme2, "DemoToll4TestType1"); +// RoadPricingUtils.setType(scheme2, RoadPricingScheme.TOLL_TYPE_LINK); +// RoadPricingUtils.setDescription(scheme2, "Tolling scheme for test."); +// +// /* Add general link based toll for one link */ +// RoadPricingUtils.addLink(scheme2, Id.createLinkId("21")); +// RoadPricingUtils.createAndAddGeneralCost(scheme2, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 42.42); +// +// /* Create the rpCalculator based on the scheme. +// * Each vehicle type gets affected by a different tolling scheme. +// * */ +// //FIXME: See above/below: schem1 and scheme2 are the same object.... +// VehicleTypeDependentRoadPricingCalculator roadPricingCalculator = new VehicleTypeDependentRoadPricingCalculator(); +// roadPricingCalculator.addPricingScheme(TYPE_1, scheme1); +// roadPricingCalculator.addPricingScheme(TYPE_2, scheme2); +// +// ///___ End creating from Code +// +// NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(scenario.getNetwork()); +// builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); +// builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); +// builder.setRoadPricingScheme(roadPricingCalculator ); //add the rpCalculator to activate the tolling. +// NetworkBasedTransportCosts c = builder.build(); +// +// Vehicle vehicle1 = mock(Vehicle.class); +// com.graphhopper.jsprit.core.problem.vehicle.VehicleType type1 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); +// when(type1.getMaxVelocity()).thenReturn(5.0); +// when(type1.getTypeId()).thenReturn(TYPE_1); +// when(vehicle1.getType()).thenReturn(type1); +// when(vehicle1.getId()).thenReturn("vehicle1"); +// +// Vehicle vehicle2 = mock(Vehicle.class); +// com.graphhopper.jsprit.core.problem.vehicle.VehicleType type2 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); +// when(type2.getMaxVelocity()).thenReturn(5.0); +// when(type2.getTypeId()).thenReturn(TYPE_2); +// when(vehicle2.getType()).thenReturn(type2); +// when(vehicle2.getId()).thenReturn("vehicle2"); +// +// //vehicle1: includes toll of 99.99 for entering the final link +// Assertions.assertEquals(20099.99, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle1), 0.01); +// Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle1), 0.01); +// +// //vehicle 2: includes toll of 42.42 for entering the final link +// //Fixme: This currently fails... see comments above. +// Assertions.assertEquals(40042.42, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle2), 0.01); +// Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); +// } /** * This test is a modified version of {@link #test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem} @@ -336,7 +340,6 @@ void test_whenAddingTwoDifferentVehicleTypes_tollBothTypesDifferently(){ * //TODO: Write it completely */ @Test - @Disabled void test_whenAddingTwoDifferentVehicleTypes_tollBothTypesDifferentlyWithFactor(){ Config config = new Config(); config.addCoreModules(); @@ -355,17 +358,24 @@ void test_whenAddingTwoDifferentVehicleTypes_tollBothTypesDifferentlyWithFactor( RoadPricingUtils.createAndAddGeneralCost(scheme1, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 99.99); //Use a factor to take into account the differnt types. type2 gehts tolled with 50% of the toll of type1 - //TODO: Include factor - - VehicleTypeDependentRoadPricingCalculator roadPricingCalculator = new VehicleTypeDependentRoadPricingCalculator(); - roadPricingCalculator.addPricingScheme(TYPE_1, scheme1); + TollFactor tollFactor = (personId, vehicleId, linkId, time) -> { + var vehTypeIdString = VehicleUtils.findVehicle(vehicleId, scenario).getType().getId().toString(); + if (TYPE_1.equals(vehTypeIdString)) { + return 1; + } else if (TYPE_2.equals(vehTypeIdString)) { + return 0.5; + } else { + return 0; + } + }; + RoadPricingSchemeUsingTollFactor rpSchemeWTollFactor = new RoadPricingSchemeUsingTollFactor( scheme1 , tollFactor ); - ///___ End creating from Code + ///___ End creating toll scheme from code NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(scenario.getNetwork()); builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); - builder.setRoadPricingScheme(roadPricingCalculator ); //add the rpCalculator to activate the tolling. + builder.setRoadPricingScheme(rpSchemeWTollFactor); //add the rpCalculator to activate the tolling. NetworkBasedTransportCosts c = builder.build(); Vehicle vehicle1 = mock(Vehicle.class); @@ -387,7 +397,6 @@ void test_whenAddingTwoDifferentVehicleTypes_tollBothTypesDifferentlyWithFactor( Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle1), 0.01); //vehicle 2: includes toll of 49.995 (50% of 99.99) for entering the final link - //Fixme: This currently fails... see comments above. Assertions.assertEquals(40049.995, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle2), 0.01); Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); } From 3bc9b188fb6d1e61d49291545ccaa486ddc09916 Mon Sep 17 00:00:00 2001 From: Kai Martins-Turner Date: Mon, 5 Aug 2024 23:09:32 +0200 Subject: [PATCH 027/111] add option if person==null --- .../carriers/jsprit/NetworkBasedTransportCosts.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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 6ad51d3f5bc..df48a3e6451 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 @@ -340,7 +340,12 @@ public double getLinkTravelDisutility(Link link, double time, Person person, double costs = baseTransportDisutility.getLinkTravelDisutility(link, time, person, vehicle); // Id typeId = vehicle.getType().getId(); // double toll = roadPricingScheme.getTollAmount(typeId, link, time ); - RoadPricingSchemeImpl.Cost costInfo = roadPricingScheme.getLinkCostInfo( link.getId(), time, person.getId(), vehicle.getId() ); + RoadPricingSchemeImpl.Cost costInfo; + if (person == null) { + costInfo = roadPricingScheme.getLinkCostInfo( link.getId(), time, null, vehicle.getId() ); + } else { + costInfo = roadPricingScheme.getLinkCostInfo( link.getId(), time, person.getId(), vehicle.getId() ); + } double toll = costInfo.amount; // System.out.println("huuuuuuuuuuuuuuuuuuuu - paid toll"); return costs + toll; From f051660abb897ac0b5bebf44db93066405e030ca Mon Sep 17 00:00:00 2001 From: Kai Martins-Turner Date: Tue, 6 Aug 2024 09:14:53 +0200 Subject: [PATCH 028/111] more tests --- .../NetworkBasedTransportCostsTest.java | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) 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 58681271e6a..7de43a75c87 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 @@ -169,6 +169,60 @@ void test_whenAddingTwoVehicleTypesViaConstructor_itMustAccountForThat(){ Assertions.assertEquals(20000.0, networkBasedTransportCosts.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); } + + /** + * This test is a modified version of {@link #test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem} + * In addition, there is added a road pricing scheme. + * The scheme is only set for one vehicle type: type1. + * So, only the vehicle using that type (vehicle1) should be tolled, the other (vehicle2) not. + * + */ + @Test + void test_whenAddingTwoDifferentVehicleTypes_tollAllTypes(){ + Config config = new Config(); + config.addCoreModules(); + Scenario scenario = ScenarioUtils.createScenario(config); + new MatsimNetworkReader(scenario.getNetwork()).readFile(utils.getClassInputDirectory() + "network.xml"); + + //Create Rp Scheme from code. + RoadPricingSchemeImpl scheme = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); + /* Configure roadpricing scheme. */ + RoadPricingUtils.setName(scheme, "DemoToll4Test"); + RoadPricingUtils.setType(scheme, RoadPricingScheme.TOLL_TYPE_LINK); + RoadPricingUtils.setDescription(scheme, "Tolling scheme for test."); + + /* Add general link based toll for one link */ + RoadPricingUtils.addLink(scheme, Id.createLinkId("21")); + RoadPricingUtils.createAndAddGeneralCost(scheme, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 99.99); + + NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(scenario.getNetwork()); + builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); + builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); + builder.setRoadPricingScheme(scheme); + NetworkBasedTransportCosts c = builder.build(); + + Vehicle vehicle1 = mock(Vehicle.class); + com.graphhopper.jsprit.core.problem.vehicle.VehicleType type1 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); + when(type1.getMaxVelocity()).thenReturn(5.0); + when(type1.getTypeId()).thenReturn(TYPE_1); + when(vehicle1.getType()).thenReturn(type1); + when(vehicle1.getId()).thenReturn("vehicle1"); + + Vehicle vehicle2 = mock(Vehicle.class); + com.graphhopper.jsprit.core.problem.vehicle.VehicleType type2 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); + when(type2.getMaxVelocity()).thenReturn(5.0); + when(type2.getTypeId()).thenReturn(TYPE_2); + when(vehicle2.getType()).thenReturn(type2); + when(vehicle2.getId()).thenReturn("vehicle2"); + + //vehicle1: includes toll + Assertions.assertEquals(20099.99, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle1), 0.01); + Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle1), 0.01); + + //vehicle 2: no toll + Assertions.assertEquals(40099.99, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle2), 0.01); + Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); + } /** * This test is a modified version of {@link #test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem} * In addition, there is added a road pricing scheme. @@ -177,7 +231,7 @@ void test_whenAddingTwoVehicleTypesViaConstructor_itMustAccountForThat(){ * */ @Test - void test_whenAddingTwoDifferentVehicleTypes_tollOneType(){ + void test_whenAddingTwoDifferentVehicleTypes_tollOneTypeTollFactor(){ Config config = new Config(); config.addCoreModules(); Scenario scenario = ScenarioUtils.createScenario(config); From 99f008a937b17517515066f7826b66b474123272 Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Tue, 6 Aug 2024 09:54:59 +0200 Subject: [PATCH 029/111] more steps forward --- .../jsprit/NetworkBasedTransportCosts.java | 5 +- .../NetworkBasedTransportCostsTest.java | 46 ++++++++++++++----- 2 files changed, 38 insertions(+), 13 deletions(-) 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 df48a3e6451..e12b8b1b1e3 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 @@ -346,7 +346,10 @@ public double getLinkTravelDisutility(Link link, double time, Person person, } else { costInfo = roadPricingScheme.getLinkCostInfo( link.getId(), time, person.getId(), vehicle.getId() ); } - double toll = costInfo.amount; + double toll=0.; + if ( costInfo != null ){ + toll = costInfo.amount; + } // System.out.println("huuuuuuuuuuuuuuuuuuuu - paid toll"); return costs + toll; } 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 7de43a75c87..f4049d554a1 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 @@ -28,6 +28,7 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.network.Link; @@ -38,10 +39,12 @@ import org.matsim.core.network.io.MatsimNetworkReader; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.misc.Time; +import org.matsim.freight.carriers.CarrierVehicle; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.CostInformation; import org.matsim.vehicles.VehicleType; import org.matsim.vehicles.VehicleUtils; +import org.matsim.vehicles.VehiclesFactory; import java.util.Arrays; import java.util.List; @@ -279,19 +282,38 @@ void test_whenAddingTwoDifferentVehicleTypes_tollOneTypeTollFactor(){ builder.setRoadPricingScheme(schemeUsingTollFactor ); NetworkBasedTransportCosts c = builder.build(); - Vehicle vehicle1 = mock(Vehicle.class); - com.graphhopper.jsprit.core.problem.vehicle.VehicleType type1 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); - when(type1.getMaxVelocity()).thenReturn(5.0); - when(type1.getTypeId()).thenReturn(TYPE_1); - when(vehicle1.getType()).thenReturn(type1); - when(vehicle1.getId()).thenReturn("vehicle1"); + VehiclesFactory vf = scenario.getVehicles().getFactory(); + final Vehicle vehicle1; + { + VehicleType vehType1 = vf.createVehicleType( Id.create( TYPE_1, VehicleType.class ) ); + scenario.getVehicles().addVehicleType( vehType1 ); +// org.matsim.vehicles.Vehicle matsimVehicle1 = vf.createVehicle( Id.createVehicleId( "vehicle1" ), vehType1 ); + CarrierVehicle matsimVehicle1 = CarrierVehicle.newInstance( Id.createVehicleId( "vehicle1" ), null, vehType1 ); + scenario.getVehicles().addVehicle( matsimVehicle1 ); + vehicle1 = MatsimJspritFactory.createJspritVehicle( matsimVehicle1, new Coord() ); + } + VehicleType vehType2 = vf.createVehicleType( Id.create( TYPE_2, VehicleType.class ) ); + scenario.getVehicles().addVehicleType( vehType2 ); +// org.matsim.vehicles.Vehicle matsimVehicle2 = vf.createVehicle( Id.createVehicleId( "vehicle2" ), vehType2 ); + CarrierVehicle matsimVehicle2 = CarrierVehicle.newInstance( Id.createVehicleId( "vehicle2" ), null, vehType2 ); + scenario.getVehicles().addVehicle( matsimVehicle2 ); - Vehicle vehicle2 = mock(Vehicle.class); - com.graphhopper.jsprit.core.problem.vehicle.VehicleType type2 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); - when(type2.getMaxVelocity()).thenReturn(5.0); - when(type2.getTypeId()).thenReturn(TYPE_2); - when(vehicle2.getType()).thenReturn(type2); - when(vehicle2.getId()).thenReturn("vehicle2"); + Vehicle vehicle2 = MatsimJspritFactory.createJspritVehicle( matsimVehicle2, new Coord() ); + +// // for the following rather use the MatsimJspritFactory#createCarrierVehicle +// Vehicle vehicle1 = mock(Vehicle.class); +// com.graphhopper.jsprit.core.problem.vehicle.VehicleType type1 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); +// when(type1.getMaxVelocity()).thenReturn(5.0); +// when(type1.getTypeId()).thenReturn(TYPE_1); +// when(vehicle1.getType()).thenReturn(type1); +// when(vehicle1.getId()).thenReturn("vehicle1"); +// +// Vehicle vehicle2 = mock(Vehicle.class); +// com.graphhopper.jsprit.core.problem.vehicle.VehicleType type2 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); +// when(type2.getMaxVelocity()).thenReturn(5.0); +// when(type2.getTypeId()).thenReturn(TYPE_2); +// when(vehicle2.getType()).thenReturn(type2); +// when(vehicle2.getId()).thenReturn("vehicle2"); //vehicle1: includes toll Assertions.assertEquals(20099.99, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle1), 0.01); From 9b3f81881594988eedbd5082889e820c70b345c4 Mon Sep 17 00:00:00 2001 From: Kai Martins-Turner Date: Tue, 6 Aug 2024 11:12:29 +0200 Subject: [PATCH 030/111] fix one test: Use MATSim's vehicles --- .../NetworkBasedTransportCostsTest.java | 168 ++++-------------- 1 file changed, 34 insertions(+), 134 deletions(-) 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 f4049d554a1..d1a8a5107bc 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 @@ -40,6 +40,7 @@ import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.misc.Time; import org.matsim.freight.carriers.CarrierVehicle; +import org.matsim.freight.carriers.CarriersUtils; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.CostInformation; import org.matsim.vehicles.VehicleType; @@ -240,7 +241,7 @@ void test_whenAddingTwoDifferentVehicleTypes_tollOneTypeTollFactor(){ Scenario scenario = ScenarioUtils.createScenario(config); new MatsimNetworkReader(scenario.getNetwork()).readFile(utils.getClassInputDirectory() + "network.xml"); - //Create Rp Scheme from code. + //Create RoadPricing Scheme from code. RoadPricingSchemeImpl scheme = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); /* Configure roadpricing scheme. */ RoadPricingUtils.setName(scheme, "DemoToll4Test"); @@ -251,69 +252,51 @@ void test_whenAddingTwoDifferentVehicleTypes_tollOneTypeTollFactor(){ RoadPricingUtils.addLink(scheme, Id.createLinkId("21")); RoadPricingUtils.createAndAddGeneralCost(scheme, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 99.99); - /* Create the rpCalculator based on the scheme. - * Here, only for one type, the see the vehicleType dependent work of it - * */ -// VehicleTypeDependentRoadPricingCalculator roadPricingScheme = new VehicleTypeDependentRoadPricingCalculator(); -// roadPricingScheme.addPricingScheme(TYPE_1, scheme); - ///___ End creating from Code - - TollFactor tollFactor = new TollFactor(){ - @Override public double getTollFactor( Id personId, Id vehicleId, Id linkId, double time ){ - double tollFactor = 0.; - - var vehTypeIdString = VehicleUtils.findVehicle(vehicleId, scenario).getType().getId().toString(); - -// // find vehicle: -// org.matsim.vehicles.Vehicle vehicle = scenario.getVehicles().getVehicles().get( vehicleId ); // das ist schlussendlich ziemlich dumm, aber so ist die Schnittstelle im Moment -// VehicleType type = vehicle.getType(); -// if (TYPE_1.equals(type.getId().toString())) { - if (TYPE_1.equals(vehTypeIdString)) { - tollFactor = 1.; - } - return tollFactor; + //Use toll factor to only toll vehicles of type1. + TollFactor tollFactor = (personId, vehicleId, linkId, time) -> { + double tollFactor1 = 0.; + var vehTypeIdString = VehicleUtils.findVehicle(vehicleId, scenario).getType().getId().toString(); + if (TYPE_1.equals(vehTypeIdString)) { + tollFactor1 = 1.; } + return tollFactor1; }; RoadPricingScheme schemeUsingTollFactor = new RoadPricingSchemeUsingTollFactor( scheme , tollFactor ); - NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(scenario.getNetwork()); - builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); - builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); - builder.setRoadPricingScheme(schemeUsingTollFactor ); - NetworkBasedTransportCosts c = builder.build(); + /// End creating roadPricing scheme from Code + //Build MATSim vehicles and convert them to jsprit Vehicles ... just to see, that this works across the whole chain and + //that we can filter/search by (MATSim) vehicle types in Toll Factor usage VehiclesFactory vf = scenario.getVehicles().getFactory(); final Vehicle vehicle1; { VehicleType vehType1 = vf.createVehicleType( Id.create( TYPE_1, VehicleType.class ) ); + vehType1.getCostInformation().setFixedCost(10.0); + vehType1.getCostInformation().setCostsPerSecond(0.0); + vehType1.getCostInformation().setCostsPerMeter(2.0); scenario.getVehicles().addVehicleType( vehType1 ); -// org.matsim.vehicles.Vehicle matsimVehicle1 = vf.createVehicle( Id.createVehicleId( "vehicle1" ), vehType1 ); - CarrierVehicle matsimVehicle1 = CarrierVehicle.newInstance( Id.createVehicleId( "vehicle1" ), null, vehType1 ); + CarrierVehicle matsimVehicle1 = CarrierVehicle.newInstance( Id.createVehicleId( "vehicle1" ), Id.createLinkId("20"), vehType1 ); scenario.getVehicles().addVehicle( matsimVehicle1 ); vehicle1 = MatsimJspritFactory.createJspritVehicle( matsimVehicle1, new Coord() ); } - VehicleType vehType2 = vf.createVehicleType( Id.create( TYPE_2, VehicleType.class ) ); - scenario.getVehicles().addVehicleType( vehType2 ); -// org.matsim.vehicles.Vehicle matsimVehicle2 = vf.createVehicle( Id.createVehicleId( "vehicle2" ), vehType2 ); - CarrierVehicle matsimVehicle2 = CarrierVehicle.newInstance( Id.createVehicleId( "vehicle2" ), null, vehType2 ); - scenario.getVehicles().addVehicle( matsimVehicle2 ); - - Vehicle vehicle2 = MatsimJspritFactory.createJspritVehicle( matsimVehicle2, new Coord() ); - -// // for the following rather use the MatsimJspritFactory#createCarrierVehicle -// Vehicle vehicle1 = mock(Vehicle.class); -// com.graphhopper.jsprit.core.problem.vehicle.VehicleType type1 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); -// when(type1.getMaxVelocity()).thenReturn(5.0); -// when(type1.getTypeId()).thenReturn(TYPE_1); -// when(vehicle1.getType()).thenReturn(type1); -// when(vehicle1.getId()).thenReturn("vehicle1"); -// -// Vehicle vehicle2 = mock(Vehicle.class); -// com.graphhopper.jsprit.core.problem.vehicle.VehicleType type2 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); -// when(type2.getMaxVelocity()).thenReturn(5.0); -// when(type2.getTypeId()).thenReturn(TYPE_2); -// when(vehicle2.getType()).thenReturn(type2); -// when(vehicle2.getId()).thenReturn("vehicle2"); + + final Vehicle vehicle2; + { + VehicleType vehType2 = vf.createVehicleType(Id.create(TYPE_2, VehicleType.class)); + vehType2.getCostInformation().setFixedCost(20.0); + vehType2.getCostInformation().setCostsPerSecond(0.0); + vehType2.getCostInformation().setCostsPerMeter(4.0); + scenario.getVehicles().addVehicleType(vehType2); + + CarrierVehicle matsimVehicle2 = CarrierVehicle.newInstance(Id.createVehicleId("vehicle2"), Id.createLinkId("20"), vehType2); + scenario.getVehicles().addVehicle(matsimVehicle2); + vehicle2 = MatsimJspritFactory.createJspritVehicle(matsimVehicle2, new Coord()); + } + + //Build the NetbasedTransportCosts opbejct with the roadpricing scheme. + NetworkBasedTransportCosts c = NetworkBasedTransportCosts.Builder.newInstance(scenario.getNetwork(), scenario.getVehicles().getVehicleTypes().values() ) + .setRoadPricingScheme(schemeUsingTollFactor) + .build() ; //vehicle1: includes toll Assertions.assertEquals(20099.99, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle1), 0.01); @@ -324,89 +307,6 @@ void test_whenAddingTwoDifferentVehicleTypes_tollOneTypeTollFactor(){ Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); } -// /** -// * This test is a modified version of {@link #test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem} -// * In addition, there is added a road pricing scheme. -// * Two different schemes are created to toll the two different vehicle types differently. -// */ -// @Test -// void test_whenAddingTwoDifferentVehicleTypes_tollBothTypesDifferently(){ -// Config config = new Config(); -// config.addCoreModules(); -// Scenario scenario = ScenarioUtils.createScenario(config); -// new MatsimNetworkReader(scenario.getNetwork()).readFile(utils.getClassInputDirectory() + "network.xml"); -// -// //Create Rp Scheme from code. -// RoadPricingSchemeImpl scheme1 = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); -// /* Configure roadpricing scheme. */ -// RoadPricingUtils.setName(scheme1, "DemoToll4TestType1"); -// RoadPricingUtils.setType(scheme1, RoadPricingScheme.TOLL_TYPE_LINK); -// RoadPricingUtils.setDescription(scheme1, "Tolling scheme for test."); -// -// /* Add general link based toll for one link */ -// RoadPricingUtils.addLink(scheme1, Id.createLinkId("21")); -// RoadPricingUtils.createAndAddGeneralCost(scheme1, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 99.99); -// -// //Create Rp Scheme from code. -// //Fixme: The following does not work as one may expect: In the end, both schemes are the same object. -// // --> It is just added a second entry to the costs, which is not taken into account anyways... -// // Questions: -// // 1.) How to build ab a second scheme, that is "independently" settable? Currently no new RoadPricingSchemeImpl() can be created without -// // the addOrGet methods provided in {@link RoadPricingUtils}. -// // 2.) Why does not both costs are summede up in the current behavior, so, the toll is 99.99 + 42.42 = 142.41? -// // --> Which one is choose? The first? The higher one?...??? -// // One solution might be to use the "withTollFactor" approach. --> Todo write an additional test for it. -// // Nevertheless, the current approach leads IMO (KMT) easily to unintentional mistakes. -// //kmt, Aug'24 -// RoadPricingSchemeImpl scheme2 = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); -// /* Configure roadpricing scheme. */ -// RoadPricingUtils.setName(scheme2, "DemoToll4TestType1"); -// RoadPricingUtils.setType(scheme2, RoadPricingScheme.TOLL_TYPE_LINK); -// RoadPricingUtils.setDescription(scheme2, "Tolling scheme for test."); -// -// /* Add general link based toll for one link */ -// RoadPricingUtils.addLink(scheme2, Id.createLinkId("21")); -// RoadPricingUtils.createAndAddGeneralCost(scheme2, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 42.42); -// -// /* Create the rpCalculator based on the scheme. -// * Each vehicle type gets affected by a different tolling scheme. -// * */ -// //FIXME: See above/below: schem1 and scheme2 are the same object.... -// VehicleTypeDependentRoadPricingCalculator roadPricingCalculator = new VehicleTypeDependentRoadPricingCalculator(); -// roadPricingCalculator.addPricingScheme(TYPE_1, scheme1); -// roadPricingCalculator.addPricingScheme(TYPE_2, scheme2); -// -// ///___ End creating from Code -// -// NetworkBasedTransportCosts.Builder builder = NetworkBasedTransportCosts.Builder.newInstance(scenario.getNetwork()); -// builder.addVehicleTypeSpecificCosts(TYPE_1, 10.0, 0.0, 2.0); -// builder.addVehicleTypeSpecificCosts(TYPE_2, 20.0, 0.0, 4.0); -// builder.setRoadPricingScheme(roadPricingCalculator ); //add the rpCalculator to activate the tolling. -// NetworkBasedTransportCosts c = builder.build(); -// -// Vehicle vehicle1 = mock(Vehicle.class); -// com.graphhopper.jsprit.core.problem.vehicle.VehicleType type1 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); -// when(type1.getMaxVelocity()).thenReturn(5.0); -// when(type1.getTypeId()).thenReturn(TYPE_1); -// when(vehicle1.getType()).thenReturn(type1); -// when(vehicle1.getId()).thenReturn("vehicle1"); -// -// Vehicle vehicle2 = mock(Vehicle.class); -// com.graphhopper.jsprit.core.problem.vehicle.VehicleType type2 = mock( com.graphhopper.jsprit.core.problem.vehicle.VehicleType.class ); -// when(type2.getMaxVelocity()).thenReturn(5.0); -// when(type2.getTypeId()).thenReturn(TYPE_2); -// when(vehicle2.getType()).thenReturn(type2); -// when(vehicle2.getId()).thenReturn("vehicle2"); -// -// //vehicle1: includes toll of 99.99 for entering the final link -// Assertions.assertEquals(20099.99, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle1), 0.01); -// Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle1), 0.01); -// -// //vehicle 2: includes toll of 42.42 for entering the final link -// //Fixme: This currently fails... see comments above. -// Assertions.assertEquals(40042.42, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle2), 0.01); -// Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); -// } /** * This test is a modified version of {@link #test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem} From 8a3cd452528f9da7486fff38613d09e9fa2da517 Mon Sep 17 00:00:00 2001 From: Kai Martins-Turner Date: Tue, 6 Aug 2024 11:27:02 +0200 Subject: [PATCH 031/111] fix the last test: Building the netbased costs without MATSim's vehicle types --- .../NetworkBasedTransportCostsTest.java | 51 ++++++++++--------- 1 file changed, 26 insertions(+), 25 deletions(-) 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 d1a8a5107bc..65b691b5737 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 @@ -25,7 +25,6 @@ import com.graphhopper.jsprit.core.problem.driver.Driver; import com.graphhopper.jsprit.core.problem.vehicle.Vehicle; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Coord; @@ -40,7 +39,6 @@ import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.misc.Time; import org.matsim.freight.carriers.CarrierVehicle; -import org.matsim.freight.carriers.CarriersUtils; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.CostInformation; import org.matsim.vehicles.VehicleType; @@ -48,9 +46,6 @@ import org.matsim.vehicles.VehiclesFactory; import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Set; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -176,10 +171,7 @@ void test_whenAddingTwoVehicleTypesViaConstructor_itMustAccountForThat(){ /** * This test is a modified version of {@link #test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem} - * In addition, there is added a road pricing scheme. - * The scheme is only set for one vehicle type: type1. - * So, only the vehicle using that type (vehicle1) should be tolled, the other (vehicle2) not. - * + * In addition, there is added a road pricing scheme to toll all vehicles */ @Test void test_whenAddingTwoDifferentVehicleTypes_tollAllTypes(){ @@ -227,12 +219,14 @@ void test_whenAddingTwoDifferentVehicleTypes_tollAllTypes(){ Assertions.assertEquals(40099.99, c.getTransportCost(Location.newInstance("20"), Location.newInstance("21"), 0.0, mock(Driver.class), vehicle2), 0.01); Assertions.assertEquals(20000.0, c.getDistance(Location.newInstance("6"), Location.newInstance("21"), 0.0, vehicle2), 0.01); } + /** * This test is a modified version of {@link #test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem} * In addition, there is added a road pricing scheme. * The scheme is only set for one vehicle type: type1. * So, only the vehicle using that type (vehicle1) should be tolled, the other (vehicle2) not. - * + * This test is build, in a way, that it uses the MATSim infrastructure for filtering the vehicles in the toll factor. + * To see it just on jsprit setting, please refer to {@link #test_whenAddingTwoDifferentVehicleTypes_tollBasedOnVehicleId} */ @Test void test_whenAddingTwoDifferentVehicleTypes_tollOneTypeTollFactor(){ @@ -255,7 +249,7 @@ void test_whenAddingTwoDifferentVehicleTypes_tollOneTypeTollFactor(){ //Use toll factor to only toll vehicles of type1. TollFactor tollFactor = (personId, vehicleId, linkId, time) -> { double tollFactor1 = 0.; - var vehTypeIdString = VehicleUtils.findVehicle(vehicleId, scenario).getType().getId().toString(); + var vehTypeIdString = VehicleUtils.findVehicle(vehicleId, scenario).getType().getId().toString(); //This needs, the vehicles registered in the scenario. if (TYPE_1.equals(vehTypeIdString)) { tollFactor1 = 1.; } @@ -266,7 +260,7 @@ void test_whenAddingTwoDifferentVehicleTypes_tollOneTypeTollFactor(){ /// End creating roadPricing scheme from Code //Build MATSim vehicles and convert them to jsprit Vehicles ... just to see, that this works across the whole chain and - //that we can filter/search by (MATSim) vehicle types in Toll Factor usage + //that we can filter/search by (MATSim) vehicle types in TollFactor usage VehiclesFactory vf = scenario.getVehicles().getFactory(); final Vehicle vehicle1; { @@ -294,7 +288,9 @@ void test_whenAddingTwoDifferentVehicleTypes_tollOneTypeTollFactor(){ } //Build the NetbasedTransportCosts opbejct with the roadpricing scheme. - NetworkBasedTransportCosts c = NetworkBasedTransportCosts.Builder.newInstance(scenario.getNetwork(), scenario.getVehicles().getVehicleTypes().values() ) + NetworkBasedTransportCosts c = NetworkBasedTransportCosts.Builder.newInstance( + scenario.getNetwork(), + scenario.getVehicles().getVehicleTypes().values() ) .setRoadPricingScheme(schemeUsingTollFactor) .build() ; @@ -311,12 +307,12 @@ void test_whenAddingTwoDifferentVehicleTypes_tollOneTypeTollFactor(){ /** * This test is a modified version of {@link #test_whenAddingTwoDifferentVehicleTypes_itMustAccountForThem} * In addition, there is added a road pricing scheme. - * Two different schemes are created to toll the two different vehicle types differently. - * Here the approach using a factor is used to take into account the different types. - * //TODO: Write it completely + * With using a toll factor, the tolling can be set differently for the two vehicles. + * This test is build, in a way, that it uses the JSPRIT vehicle directly. + * To see it with the MATSim settings, please refer to {@link #test_whenAddingTwoDifferentVehicleTypes_tollOneTypeTollFactor()} */ @Test - void test_whenAddingTwoDifferentVehicleTypes_tollBothTypesDifferentlyWithFactor(){ + void test_whenAddingTwoDifferentVehicleTypes_tollBasedOnVehicleId(){ Config config = new Config(); config.addCoreModules(); Scenario scenario = ScenarioUtils.createScenario(config); @@ -334,14 +330,19 @@ void test_whenAddingTwoDifferentVehicleTypes_tollBothTypesDifferentlyWithFactor( RoadPricingUtils.createAndAddGeneralCost(scheme1, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 99.99); //Use a factor to take into account the differnt types. type2 gehts tolled with 50% of the toll of type1 - TollFactor tollFactor = (personId, vehicleId, linkId, time) -> { - var vehTypeIdString = VehicleUtils.findVehicle(vehicleId, scenario).getType().getId().toString(); - if (TYPE_1.equals(vehTypeIdString)) { - return 1; - } else if (TYPE_2.equals(vehTypeIdString)) { - return 0.5; - } else { - return 0; + TollFactor tollFactor = new TollFactor() { + @Override + public double getTollFactor(Id personId, Id vehicleId, Id linkId, double time) { + //No information about the vehicleType available anywhere, because is is nowhere registered centrally, + // -> Use the vehicleId to distinguish the types. + var vehTypeIdString = vehicleId.toString(); + if (vehTypeIdString.equals("vehicle1")) { + return 1; + } else if (vehTypeIdString.equals("vehicle2")) { + return 0.5; + } else { + return 0; + } } }; RoadPricingSchemeUsingTollFactor rpSchemeWTollFactor = new RoadPricingSchemeUsingTollFactor( scheme1 , tollFactor ); From 883f2d34fbfa617038acefd8a51a02e3a4207a62 Mon Sep 17 00:00:00 2001 From: Kai Martins-Turner Date: Tue, 6 Aug 2024 11:37:37 +0200 Subject: [PATCH 032/111] some cleanup and javadoc --- .../jsprit/NetworkBasedTransportCosts.java | 44 +++++++------------ 1 file changed, 16 insertions(+), 28 deletions(-) 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 e12b8b1b1e3..e6d8e1a0e45 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCosts.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCosts.java @@ -320,7 +320,6 @@ private static class VehicleTypeVarCosts { */ static class VehicleTransportCostsIncludingToll implements TravelDisutility { -// private static Logger logger = LogManager.getLogger(VehicleTransportCostsIncludingToll.class); private final TravelDisutility baseTransportDisutility; @@ -331,26 +330,24 @@ public VehicleTransportCostsIncludingToll( TravelDisutility baseTransportDisutil super(); this.baseTransportDisutility = baseTransportDisutility; this.roadPricingScheme = roadPricingScheme; -// System.out.println("huuuuuuuuuuuuuuuuuuuu - initialize transport costs with toll"); } @Override public double getLinkTravelDisutility(Link link, double time, Person person, org.matsim.vehicles.Vehicle vehicle) { double costs = baseTransportDisutility.getLinkTravelDisutility(link, time, person, vehicle); -// Id typeId = vehicle.getType().getId(); -// double toll = roadPricingScheme.getTollAmount(typeId, link, time ); + RoadPricingSchemeImpl.Cost costInfo; if (person == null) { costInfo = roadPricingScheme.getLinkCostInfo( link.getId(), time, null, vehicle.getId() ); } else { costInfo = roadPricingScheme.getLinkCostInfo( link.getId(), time, person.getId(), vehicle.getId() ); } - double toll=0.; + + double toll = 0.; if ( costInfo != null ){ toll = costInfo.amount; } -// System.out.println("huuuuuuuuuuuuuuuuuuuu - paid toll"); return costs + toll; } @@ -408,7 +405,7 @@ public static Builder newInstance(Network network) { * Creates the builder requiring {@link Network} and a collection of * {@link VehicleType}. * - * @param network + * @param network the MATSim network * @param vehicleTypes must be all vehicleTypes and their assigned * costInformation in the system. */ @@ -429,7 +426,7 @@ private void retrieveTypeSpecificCosts(Collection vehicleTypes) { * Sets the travelTime. By default, travelTime is based on * link.getFreespeed();. * - * @param travelTime + * @param travelTime the travelTime to set * @return this builder */ public Builder setTravelTime(TravelTime travelTime) { @@ -478,7 +475,7 @@ public Builder setFIFO(boolean isFIFO) { *

* By default, it use {@link SpeedyALTFactory} * - * @param {@link {@link LeastCostPathCalculatorFactory} + * @param leastCostPathCalcFactory {@link LeastCostPathCalculatorFactory} * @return this builder */ public Builder setThreadSafeLeastCostPathCalculatorFactory( @@ -526,10 +523,10 @@ public NetworkBasedTransportCosts build() { * Adds type-specific costs. If typeId already exists, existing entry is * overwritten. * - * @param typeId - * @param fix - * @param perSecond - * @param perMeter + * @param typeId the vehicleType-id as String + * @param fix fix costs for the vehicle + * @param perSecond variable costs per second + * @param perMeter variable costs per meter */ public void addVehicleTypeSpecificCosts(String typeId, double fix, double perSecond, double perMeter) { typeSpecificCosts.put(typeId, new VehicleTypeVarCosts(perMeter, perSecond)); @@ -598,7 +595,7 @@ private NetworkBasedTransportCosts(Builder builder) { * cached travel-time. If not, it computes and caches new values with the * leastCostPathCalc defined in here. * - * @Throws {@link IllegalStateException} if vehicle is null + * @exception IllegalStateException if vehicle is null */ @Override public double getTransportTime(Location fromId, Location toId, double departureTime, Driver driver, @@ -679,7 +676,7 @@ private void informStartCalc() { * cached travel-cost value. If not, it computes and caches new values with the * leastCostPathCalc defined in here. * - * @Throws {@link IllegalStateException} if vehicle is null + * @exception IllegalStateException if vehicle is null */ @Override public double getTransportCost(Location fromId, Location toId, double departureTime, Driver driver, @@ -747,7 +744,7 @@ public double getTransportCost(Location fromId, Location toId, double departureT * cached distance. If not, it computes and caches new values with the * leastCostPathCalc defined in here. * - * @Throws {@link IllegalStateException} if vehicle is null + * @exception IllegalStateException if vehicle is null */ @Override public double getDistance(Location fromId, Location toId, double departureTime, Vehicle vehicle) { @@ -812,7 +809,7 @@ public Collection getInternalListeners( * This is a rather bad approximation. If you require this, you should implement * another {@link VehicleRoutingTransportCosts} * - * @Throws {@link IllegalStateException} if vehicle is null + * @exception IllegalStateException if vehicle is null */ @Override public double getBackwardTransportCost(Location fromId, Location toId, double arrivalTime, Driver driver, @@ -828,7 +825,7 @@ public double getBackwardTransportCost(Location fromId, Location toId, double ar * This is a rather bad approximation. If you require this, you should implement * another {@link VehicleRoutingTransportCosts}. * - * @Throws {@link IllegalStateException} if vehicle is null + * @exception IllegalStateException if vehicle is null */ @Override public double getBackwardTransportTime(Location fromId, Location toId, double arrivalTime, Driver driver, @@ -875,7 +872,7 @@ private int getTimeSlice(double time) { /** * Gets the network the calculation is based on. * - * @return + * @return the network */ public Network getNetwork() { return network; @@ -890,13 +887,4 @@ public TravelTime getTravelTime() { return travelTime; } - /** - * Gets the {@link VehicleTypeDependentRoadPricingCalculator} - * - * @return {@link VehicleTypeDependentRoadPricingCalculator} - */ -// public VehicleTypeDependentRoadPricingCalculator getRoadPricingCalculator() { -// return roadPricingCalc; -// } - } From 307c602ab7577fd5bcebb7fc7d9c285b8de70b67 Mon Sep 17 00:00:00 2001 From: Kai Martins-Turner Date: Tue, 6 Aug 2024 11:42:33 +0200 Subject: [PATCH 033/111] fix typos, internal renaming --- .../NetworkBasedTransportCostsTest.java | 49 +++++++++---------- 1 file changed, 22 insertions(+), 27 deletions(-) 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 65b691b5737..64e7eeba641 100644 --- a/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsTest.java +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/jsprit/NetworkBasedTransportCostsTest.java @@ -30,9 +30,7 @@ import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; -import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; -import org.matsim.api.core.v01.population.Person; import org.matsim.contrib.roadpricing.*; import org.matsim.core.config.Config; import org.matsim.core.network.io.MatsimNetworkReader; @@ -255,7 +253,7 @@ void test_whenAddingTwoDifferentVehicleTypes_tollOneTypeTollFactor(){ } return tollFactor1; }; - RoadPricingScheme schemeUsingTollFactor = new RoadPricingSchemeUsingTollFactor( scheme , tollFactor ); + RoadPricingScheme rpSchemeWTollFactor = new RoadPricingSchemeUsingTollFactor( scheme , tollFactor ); /// End creating roadPricing scheme from Code @@ -287,11 +285,11 @@ void test_whenAddingTwoDifferentVehicleTypes_tollOneTypeTollFactor(){ vehicle2 = MatsimJspritFactory.createJspritVehicle(matsimVehicle2, new Coord()); } - //Build the NetbasedTransportCosts opbejct with the roadpricing scheme. + //Build the NetbasedTransportCosts object with the roadpricing scheme. NetworkBasedTransportCosts c = NetworkBasedTransportCosts.Builder.newInstance( scenario.getNetwork(), scenario.getVehicles().getVehicleTypes().values() ) - .setRoadPricingScheme(schemeUsingTollFactor) + .setRoadPricingScheme(rpSchemeWTollFactor) .build() ; //vehicle1: includes toll @@ -319,33 +317,30 @@ void test_whenAddingTwoDifferentVehicleTypes_tollBasedOnVehicleId(){ new MatsimNetworkReader(scenario.getNetwork()).readFile(utils.getClassInputDirectory() + "network.xml"); //Create Rp Scheme from code. - RoadPricingSchemeImpl scheme1 = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); + RoadPricingSchemeImpl scheme = RoadPricingUtils.addOrGetMutableRoadPricingScheme(scenario ); /* Configure roadpricing scheme. */ - RoadPricingUtils.setName(scheme1, "DemoToll4TestType1"); - RoadPricingUtils.setType(scheme1, RoadPricingScheme.TOLL_TYPE_LINK); - RoadPricingUtils.setDescription(scheme1, "Tolling scheme for test."); + RoadPricingUtils.setName(scheme, "DemoToll4TestType1"); + RoadPricingUtils.setType(scheme, RoadPricingScheme.TOLL_TYPE_LINK); + RoadPricingUtils.setDescription(scheme, "Tolling scheme for test."); /* Add general link based toll for one link */ - RoadPricingUtils.addLink(scheme1, Id.createLinkId("21")); - RoadPricingUtils.createAndAddGeneralCost(scheme1, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 99.99); - - //Use a factor to take into account the differnt types. type2 gehts tolled with 50% of the toll of type1 - TollFactor tollFactor = new TollFactor() { - @Override - public double getTollFactor(Id personId, Id vehicleId, Id linkId, double time) { - //No information about the vehicleType available anywhere, because is is nowhere registered centrally, - // -> Use the vehicleId to distinguish the types. - var vehTypeIdString = vehicleId.toString(); - if (vehTypeIdString.equals("vehicle1")) { - return 1; - } else if (vehTypeIdString.equals("vehicle2")) { - return 0.5; - } else { - return 0; - } + RoadPricingUtils.addLink(scheme, Id.createLinkId("21")); + RoadPricingUtils.createAndAddGeneralCost(scheme, Time.parseTime("00:00:00"), Time.parseTime("72:00:00"), 99.99); + + //Use a factor to take into account the different types. type2 gehts tolled with 50% of the toll of type1 + TollFactor tollFactor = (personId, vehicleId, linkId, time) -> { + //No information about the vehicleType available anywhere, because it is not registered centrally. + // -> Use the vehicleId to distinguish the types. + var vehTypeIdString = vehicleId.toString(); + if (vehTypeIdString.equals("vehicle1")) { + return 1; + } else if (vehTypeIdString.equals("vehicle2")) { + return 0.5; + } else { + return 0; } }; - RoadPricingSchemeUsingTollFactor rpSchemeWTollFactor = new RoadPricingSchemeUsingTollFactor( scheme1 , tollFactor ); + RoadPricingSchemeUsingTollFactor rpSchemeWTollFactor = new RoadPricingSchemeUsingTollFactor( scheme , tollFactor ); ///___ End creating toll scheme from code From 71c63dbac2f19d82e022c73a403c3ec8f029c09e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 11:41:11 +0000 Subject: [PATCH 034/111] Bump org.apache.maven.plugins:maven-surefire-report-plugin Bumps [org.apache.maven.plugins:maven-surefire-report-plugin](https://github.com/apache/maven-surefire) from 3.3.0 to 3.3.1. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.3.0...surefire-3.3.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-report-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- matsim/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matsim/pom.xml b/matsim/pom.xml index 17556c8ac08..3f2321ada6d 100644 --- a/matsim/pom.xml +++ b/matsim/pom.xml @@ -118,7 +118,7 @@ org.apache.maven.plugins maven-surefire-report-plugin - 3.3.0 + 3.3.1 From 79c687fce1bdd909e2a2e0b233f348bbd220a6a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 12:14:38 +0000 Subject: [PATCH 035/111] Bump io.grpc:grpc-all from 1.65.0 to 1.65.1 Bumps [io.grpc:grpc-all](https://github.com/grpc/grpc-java) from 1.65.0 to 1.65.1. - [Release notes](https://github.com/grpc/grpc-java/releases) - [Commits](https://github.com/grpc/grpc-java/compare/v1.65.0...v1.65.1) --- updated-dependencies: - dependency-name: io.grpc:grpc-all dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- contribs/hybridsim/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribs/hybridsim/pom.xml b/contribs/hybridsim/pom.xml index 5917f032e3e..f58a572c939 100644 --- a/contribs/hybridsim/pom.xml +++ b/contribs/hybridsim/pom.xml @@ -11,7 +11,7 @@ 4.27.2 - 1.65.0 + 1.65.1 From b0a5f3d57d3db96989c1fc5a9674f08b82539094 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 12:14:40 +0000 Subject: [PATCH 036/111] Bump org.apache.maven.plugins:maven-surefire-plugin from 3.3.0 to 3.3.1 Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.3.0 to 3.3.1. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.3.0...surefire-3.3.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d03e82ea2be..995cc8c2bd8 100644 --- a/pom.xml +++ b/pom.xml @@ -420,7 +420,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.3.0 + 3.3.1 org.apache.maven.plugins From 0ab26476a926ac768f27df7849e2b9468c99dbe9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:42:09 +0000 Subject: [PATCH 037/111] Bump commons-codec:commons-codec from 1.17.0 to 1.17.1 Bumps [commons-codec:commons-codec](https://github.com/apache/commons-codec) from 1.17.0 to 1.17.1. - [Changelog](https://github.com/apache/commons-codec/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-codec/compare/rel/commons-codec-1.17.0...rel/commons-codec-1.17.1) --- updated-dependencies: - dependency-name: commons-codec:commons-codec dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 995cc8c2bd8..404796a50b1 100644 --- a/pom.xml +++ b/pom.xml @@ -128,7 +128,7 @@ commons-codec commons-codec - 1.17.0 + 1.17.1 org.apache.commons From 43b3bcb411c9fddc0bfb9a3fee9480a63c930804 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 14:33:54 +0000 Subject: [PATCH 038/111] Bump it.unimi.dsi:fastutil-core from 8.5.13 to 8.5.14 Bumps [it.unimi.dsi:fastutil-core](https://github.com/vigna/fastutil) from 8.5.13 to 8.5.14. - [Changelog](https://github.com/vigna/fastutil/blob/master/CHANGES) - [Commits](https://github.com/vigna/fastutil/commits/8.5.14) --- updated-dependencies: - dependency-name: it.unimi.dsi:fastutil-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- matsim/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matsim/pom.xml b/matsim/pom.xml index 3f2321ada6d..7f768fffe76 100644 --- a/matsim/pom.xml +++ b/matsim/pom.xml @@ -127,7 +127,7 @@ it.unimi.dsi fastutil-core - 8.5.13 + 8.5.14 org.geotools From 799bf544ebe9b3a0418602751c60549d19ddbb8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 14:34:09 +0000 Subject: [PATCH 039/111] Bump geotools.version from 31.2 to 31.3 Bumps `geotools.version` from 31.2 to 31.3. Updates `org.geotools:gt-main` from 31.2 to 31.3 Updates `org.geotools:gt-referencing` from 31.2 to 31.3 Updates `org.geotools:gt-shapefile` from 31.2 to 31.3 Updates `org.geotools:gt-epsg-hsql` from 31.2 to 31.3 Updates `org.geotools:gt-epsg-extension` from 31.2 to 31.3 Updates `org.geotools:gt-api` from 31.2 to 31.3 Updates `org.geotools.jdbc:gt-jdbc-postgis` from 31.2 to 31.3 Updates `org.geotools:gt-geopkg` from 31.2 to 31.3 Updates `org.geotools:gt-geotiff` from 31.2 to 31.3 Updates `org.geotools:gt-geojson` from 31.2 to 31.3 Updates `org.geotools:gt-coverage` from 31.2 to 31.3 --- updated-dependencies: - dependency-name: org.geotools:gt-main dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.geotools:gt-referencing dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.geotools:gt-shapefile dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.geotools:gt-epsg-hsql dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.geotools:gt-epsg-extension dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.geotools:gt-api dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.geotools.jdbc:gt-jdbc-postgis dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.geotools:gt-geopkg dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.geotools:gt-geotiff dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.geotools:gt-geojson dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.geotools:gt-coverage dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 404796a50b1..a049d60560f 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 2.23.1 - 31.2 + 31.3 0.49.2 1.19.0 7.0.0 From 5bf784e34d408d34d607c9acd4e85d305e53d348 Mon Sep 17 00:00:00 2001 From: rakow Date: Tue, 6 Aug 2024 17:16:37 +0200 Subject: [PATCH 040/111] Preserve the working directory when gui is run from cli (#3391) --- .../org/matsim/application/MATSimApplication.java | 2 ++ .../main/java/org/matsim/application/ShowGUI.java | 7 +++++++ matsim/src/main/java/org/matsim/run/gui/Gui.java | 14 ++++++++++++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/contribs/application/src/main/java/org/matsim/application/MATSimApplication.java b/contribs/application/src/main/java/org/matsim/application/MATSimApplication.java index 4e4c6860d63..2425a0f1491 100644 --- a/contribs/application/src/main/java/org/matsim/application/MATSimApplication.java +++ b/contribs/application/src/main/java/org/matsim/application/MATSimApplication.java @@ -413,6 +413,8 @@ public static void runWithDefaults(Class clazz, Str if (ApplicationUtils.isRunFromDesktop() && args.length == 0) { + System.setProperty("MATSIM_GUI_DESKTOP", "true"); + if (defaultArgs.length > 0) { String value = String.join(ARGS_DELIMITER, defaultArgs); System.setProperty("MATSIM_GUI_ARGS", value); diff --git a/contribs/application/src/main/java/org/matsim/application/ShowGUI.java b/contribs/application/src/main/java/org/matsim/application/ShowGUI.java index e394bfd7b79..6400262eb95 100644 --- a/contribs/application/src/main/java/org/matsim/application/ShowGUI.java +++ b/contribs/application/src/main/java/org/matsim/application/ShowGUI.java @@ -40,6 +40,13 @@ public Integer call() throws Exception { Gui gui = f.get(); + // Set the current working directory to be used in the gui, when run from the command line + // If the gui is run from desktop, the working directory is not overwritten + + // Assumption is that starting something from command line, the user expects that the working directory remains the same + if (!System.getProperty("MATSIM_GUI_DESKTOP", "false").equals("true")) + gui.setWorkingDirectory(new File("")); + while (gui.isShowing()) Thread.sleep(250); diff --git a/matsim/src/main/java/org/matsim/run/gui/Gui.java b/matsim/src/main/java/org/matsim/run/gui/Gui.java index 4b826b14842..1ca4a9afc8d 100644 --- a/matsim/src/main/java/org/matsim/run/gui/Gui.java +++ b/matsim/src/main/java/org/matsim/run/gui/Gui.java @@ -91,6 +91,11 @@ public class Gui extends JFrame { private File configFile; private File lastUsedDirectory; + + /** + * This is the working directory for the simulation. If it is null, the working directory is the directory of the config file. + */ + private File workingDirectory = null; private ConfigEditor editor = null; private ScheduleValidatorWindow transitValidator = null; @@ -439,6 +444,8 @@ private void startMATSim() { textStdOut.setText(""); textErrOut.setText(""); + String cwd = workingDirectory == null ? new File(txtConfigfilename.getText()).getParent() : workingDirectory.getAbsolutePath(); + new Thread(() -> { String classpath = System.getProperty("java.class.path"); String[] cpParts = classpath.split(File.pathSeparator); @@ -457,8 +464,7 @@ private void startMATSim() { "--add-exports", "java.desktop/sun.java2d=ALL-UNNAMED", mainClass, txtConfigfilename.getText() }; // see https://jogamp.org/bugzilla/show_bug.cgi?id=1317#c21 and/or https://github.com/matsim-org/matsim-libs/pull/2940 - exeRunner = ExeRunner.run(cmdArgs, textStdOut, textErrOut, - new File(txtConfigfilename.getText()).getParent()); + exeRunner = ExeRunner.run(cmdArgs, textStdOut, textErrOut, cwd); int exitcode = exeRunner.waitForFinish(); exeRunner = null; @@ -575,6 +581,10 @@ public static void main(String[] args) { Gui.show("MATSim", RunMatsim.class, args.length == 1 ? new File(args[0]) : null); } + public void setWorkingDirectory(File cwd) { + this.workingDirectory = cwd; + } + // Is it a problem to make the following available to the outside? If so, why? Would it // be better to rather copy/paste the above code and start from there? kai, jun/aug'18 From 4e4afdcb6822f294685f67ccc8b039b15744f176 Mon Sep 17 00:00:00 2001 From: schlenther Date: Wed, 7 Aug 2024 16:36:03 +0200 Subject: [PATCH 041/111] use asterisk for act type default --- .../org/matsim/application/analysis/noise/NoiseAnalysis.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java index c5927fcdb04..7cd5fea5502 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 @@ -46,7 +46,8 @@ public class NoiseAnalysis implements MATSimAppCommand { @CommandLine.Mixin private final ShpOptions shp = new ShpOptions(); - @CommandLine.Option(names = "--consider-activities", split = ",", description = "Considered activities for noise calculation", defaultValue = "h,w,home,work") + @CommandLine.Option(names = "--consider-activities", split = ",", description = "Considered activities for noise calculation." + + " Use asterisk ('*') for acttype prefixes, if all such acts shall be considered.", defaultValue = "h,w,home*,work*") private Set considerActivities; @CommandLine.Option(names = "--noise-barrier", description = "Path to the noise barrier File", defaultValue = "") From 6a30c28d370e72729199eee0d9a48741f9cc98d8 Mon Sep 17 00:00:00 2001 From: schlenther Date: Wed, 7 Aug 2024 17:24:55 +0200 Subject: [PATCH 042/111] NoiseAnalysis: set the scale factor for according to sample size --- .../analysis/noise/NoiseAnalysis.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) 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 7cd5fea5502..6730cae8996 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java @@ -1,5 +1,7 @@ package org.matsim.application.analysis.noise; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.locationtech.jts.geom.Envelope; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Scenario; @@ -8,6 +10,7 @@ import org.matsim.application.MATSimAppCommand; import org.matsim.application.options.InputOptions; import org.matsim.application.options.OutputOptions; +import org.matsim.application.options.SampleOptions; import org.matsim.application.options.ShpOptions; import org.matsim.contrib.noise.NoiseConfigGroup; import org.matsim.contrib.noise.NoiseOfflineCalculation; @@ -38,6 +41,8 @@ ) public class NoiseAnalysis implements MATSimAppCommand { + private static final Logger log = LogManager.getLogger(NoiseAnalysis.class); + @CommandLine.Mixin private final InputOptions input = InputOptions.ofCommand(NoiseAnalysis.class); @CommandLine.Mixin @@ -46,6 +51,9 @@ public class NoiseAnalysis implements MATSimAppCommand { @CommandLine.Mixin private final ShpOptions shp = new ShpOptions(); + @CommandLine.Mixin + private final SampleOptions sampleOptions = new SampleOptions(); + @CommandLine.Option(names = "--consider-activities", split = ",", description = "Considered activities for noise calculation." + " Use asterisk ('*') for acttype prefixes, if all such acts shall be considered.", defaultValue = "h,w,home*,work*") private Set considerActivities; @@ -89,6 +97,16 @@ public Integer call() throws Exception { noiseParameters.setNoiseBarriersFilePath(noiseBarrierFile); } + if(! sampleOptions.isSet() && noiseParameters.getScaleFactor() == 1d){ + log.warn("You didn't provide the simulation sample size via command line option --sample-size! This means, noise damages are not scaled!!!"); + } else if (noiseParameters.getScaleFactor() == 1d){ + if (sampleOptions.getSample() == 1d){ + log.warn("Be aware that the noise output is not scaled. This might be unintended. If so, assure to provide the sample size via command line option --sample-size, in the SimWrapperConfigGroup," + + "or provide the scaleFactor (the inverse of the sample size) in the NoiseConfigGroup!!!"); + } + noiseParameters.setScaleFactor(sampleOptions.getUpscaleFactor()); + } + Scenario scenario = ScenarioUtils.loadScenario(config); String outputFilePath = output.getPath().getParent() == null ? "." : output.getPath().getParent().toString(); @@ -120,6 +138,7 @@ private Config prepareConfig() { config.facilities().setInputFile(null); config.eventsManager().setNumberOfThreads(null); config.eventsManager().setEstimatedNumberOfEvents(null); + //ts, aug '24: not sure if and why we need to set 1 thread config.global().setNumberOfThreads(1); return config; From ea1f72cef8315e9d253fde79198ffaa471c96ceb Mon Sep 17 00:00:00 2001 From: simei94 <67737999+simei94@users.noreply.github.com> Date: Thu, 8 Aug 2024 14:09:32 +0200 Subject: [PATCH 043/111] add fare zone based pt pricing (#3382) * first try to implement fare zone based pt pricing, deutschlandtarif numbers still missing * put deutschlandtarif price linear functions into code * unit test for FareZoneBasedPtFareHandler --- .../pt/fare/DistanceBasedPtFareParams.java | 13 ++ .../pt/fare/FareZoneBasedPtFareHandler.java | 163 ++++++++++++++++++ .../vsp/pt/fare/PtFareConfigGroup.java | 2 +- .../playground/vsp/pt/fare/PtFareModule.java | 11 +- .../fare/FareZoneBasedPtFareHandlerTest.java | 124 +++++++++++++ .../scenarios/kelheim/ptTestArea/pt-area.cpg | 1 + .../scenarios/kelheim/ptTestArea/pt-area.dbf | Bin 0 -> 330 bytes .../scenarios/kelheim/ptTestArea/pt-area.prj | 1 + .../scenarios/kelheim/ptTestArea/pt-area.shp | Bin 0 -> 348 bytes .../scenarios/kelheim/ptTestArea/pt-area.shx | Bin 0 -> 108 bytes 10 files changed, 310 insertions(+), 5 deletions(-) create mode 100644 contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandler.java create mode 100644 contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java create mode 100644 examples/scenarios/kelheim/ptTestArea/pt-area.cpg create mode 100644 examples/scenarios/kelheim/ptTestArea/pt-area.dbf create mode 100644 examples/scenarios/kelheim/ptTestArea/pt-area.prj create mode 100644 examples/scenarios/kelheim/ptTestArea/pt-area.shp create mode 100644 examples/scenarios/kelheim/ptTestArea/pt-area.shx diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java index a86cd173c14..442d956bf3c 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java @@ -22,6 +22,7 @@ public class DistanceBasedPtFareParams extends ReflectiveConfigGroup { public static final String LONG_DISTANCE_TRIP_THRESHOLD = "longDistanceTripThreshold"; public static final String LONG_DISTANCE_TRIP_SLOPE = "longDistanceTripSlope"; public static final String LONG_DISTANCE_TRIP_INTERCEPT = "longDistanceTripIntercept"; + public static final String FARE_ZONE_SHP = "fareZoneShp"; @PositiveOrZero private double minFare = 2.0; @@ -35,6 +36,7 @@ public class DistanceBasedPtFareParams extends ReflectiveConfigGroup { private double longDistanceTripIntercept = 30.0; @PositiveOrZero private double longDistanceTripSlope = 0.00025; + private String fareZoneShp; public DistanceBasedPtFareParams() { super(SET_NAME); @@ -52,6 +54,7 @@ public Map getComments() { map.put(LONG_DISTANCE_TRIP_THRESHOLD, "Threshold of the long trips in meters. Below this value, " + "the trips are considered as normal trips. Above this value, the trips are considered as " + "inter-city trips"); + map.put(FARE_ZONE_SHP, "Shp file with fare zone(s). This parameter is only used for PtFareCalculationModel 'fareZoneBased'."); return map; } @@ -114,4 +117,14 @@ public double getLongDistanceTripThreshold() { public void setLongDistanceTripThreshold(double longDistanceTripThreshold) { this.longDistanceTripThreshold = longDistanceTripThreshold; } + + @StringGetter(FARE_ZONE_SHP) + public String getFareZoneShp() { + return fareZoneShp; + } + + @StringSetter(FARE_ZONE_SHP) + public void setFareZoneShp(String fareZoneShp) { + this.fareZoneShp = fareZoneShp; + } } diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandler.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandler.java new file mode 100644 index 00000000000..962a18fac57 --- /dev/null +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandler.java @@ -0,0 +1,163 @@ +package playground.vsp.pt.fare; + +import com.google.inject.Inject; +import org.apache.commons.math.stat.regression.SimpleRegression; +import org.geotools.api.feature.simple.SimpleFeature; +import org.locationtech.jts.geom.Geometry; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.events.ActivityStartEvent; +import org.matsim.api.core.v01.events.PersonMoneyEvent; +import org.matsim.api.core.v01.events.handler.ActivityStartEventHandler; +import org.matsim.api.core.v01.population.Person; +import org.matsim.application.options.ShpOptions; +import org.matsim.core.api.experimental.events.EventsManager; +import org.matsim.core.router.StageActivityTypeIdentifier; +import org.matsim.core.utils.geometry.CoordUtils; +import org.matsim.core.utils.geometry.geotools.MGC; +import org.matsim.pt.PtConstants; + +import java.util.AbstractMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class FareZoneBasedPtFareHandler implements ActivityStartEventHandler { + @Inject + private EventsManager events; + + public static final String FARE = "fare"; + public static final String PT_FARE_ZONE_BASED = "fare zone based pt fare"; + public static final String PT_GERMANWIDE_FARE_BASED = "german-wide fare based pt fare"; + + private final ShpOptions shp; + + private final Map, Coord> personDepartureCoordMap = new HashMap<>(); + private final Map, Coord> personArrivalCoordMap = new HashMap<>(); + + public FareZoneBasedPtFareHandler(DistanceBasedPtFareParams params) { + this.shp = new ShpOptions(params.getFareZoneShp(), null, null); + } + + @Override + public void handleEvent(ActivityStartEvent event) { + + if (event.getActType().equals(PtConstants.TRANSIT_ACTIVITY_TYPE)) { + personDepartureCoordMap.computeIfAbsent(event.getPersonId(), c -> event.getCoord()); // The departure place is fixed to the place of first pt interaction an agent has in the whole leg + personArrivalCoordMap.put(event.getPersonId(), event.getCoord()); // The arrival stop will keep updating until the agent start a real activity (i.e. finish the leg) + } + + if (!StageActivityTypeIdentifier.isStageActivity(event.getActType())) { + Id personId = event.getPersonId(); + if (personDepartureCoordMap.containsKey(personId)) { + double distance = CoordUtils.calcEuclideanDistance + (personDepartureCoordMap.get(personId), personArrivalCoordMap.get(personId)); + + SimpleFeature departureZone = determineFareZone(personDepartureCoordMap.get(personId), shp.readFeatures()); + SimpleFeature arrivalZone = determineFareZone(personArrivalCoordMap.get(personId), shp.readFeatures()); + + Map.Entry fareEntry = computeFare(distance, departureZone, arrivalZone); + // charge fare to the person + events.processEvent( + new PersonMoneyEvent(event.getTime(), event.getPersonId(), -fareEntry.getValue(), + PtFareConfigGroup.PT_FARE, fareEntry.getKey(), event.getPersonId().toString())); + + personDepartureCoordMap.remove(personId); + personArrivalCoordMap.remove(personId); + } + } + } + + public static Map.Entry computeFare(double distance, SimpleFeature departureZone, SimpleFeature arrivalZone) { + + if (departureZone != null && arrivalZone != null) { +// if both zones are not null -> departure and arrival point are inside of one of the tarifzonen + if (departureZone.getID().equals(arrivalZone.getID())) { + return new AbstractMap.SimpleEntry<>(PT_FARE_ZONE_BASED ,(double) departureZone.getAttribute(FARE)); + } + } +// in every other case return german wide fare / Deutschlandtarif + return getGermanWideFare(distance); + } + + private static Map.Entry getGermanWideFare(double distance) { + + SimpleRegression regression = new SimpleRegression(); + +// in Deutschlandtarif, the linear function for the prices above 100km seem to have a different steepness +// hence the following difference in data points +// prices taken from https://deutschlandtarifverbund.de/wp-content/uploads/2024/07/20231201_TBDT_J_10_Preisliste_V07.pdf + if (distance / 1000 <= 100.) { + regression.addData(1, 1.70); + regression.addData(2,1.90); + regression.addData(3,2.00); + regression.addData(4,2.10); + regression.addData(5,2.20); + regression.addData(6,3.20); + regression.addData(7,3.70); + regression.addData(8,3.80); + regression.addData(9,3.90); + regression.addData(10,4.10); + regression.addData(11,5.00); + regression.addData(12,5.40); + regression.addData(13,5.60); + regression.addData(14,5.80); + regression.addData(15,5.90); + regression.addData(16,6.40); + regression.addData(17,6.50); + regression.addData(18,6.60); + regression.addData(19,6.70); + regression.addData(20,6.90); + regression.addData(30,9.90); + regression.addData(40,13.70); + regression.addData(50,16.30); + regression.addData(60,18.10); + regression.addData(70,20.10); + regression.addData(80,23.20); + regression.addData(90,26.20); + regression.addData(100,28.10); + } else { + regression.addData(100,28.10); + regression.addData(200,47.20); + regression.addData(300,59.70); + regression.addData(400,71.70); + regression.addData(500,83.00); + regression.addData(600,94.60); + regression.addData(700,106.30); + regression.addData(800,118.20); + regression.addData(900,130.10); + regression.addData(1000,141.00); + regression.addData(1100,148.60); + regression.addData(1200,158.10); + regression.addData(1300,169.20); + regression.addData(1400,179.80); + regression.addData(1500,190.10); + regression.addData(1600,201.50); + regression.addData(1700,212.80); + regression.addData(1800,223.30); + regression.addData(1900,233.90); + regression.addData(2000,244.00); + } + return new AbstractMap.SimpleEntry<>(PT_GERMANWIDE_FARE_BASED, regression.getSlope() * distance / 1000 + regression.getIntercept()); + } + + static SimpleFeature determineFareZone(Coord coord, List features) { + SimpleFeature zone = null; + + for (SimpleFeature ft : features) { + Geometry geom = (Geometry) ft.getDefaultGeometry(); + + if (MGC.coord2Point(coord).within(geom)) { + zone = ft; + break; + } + } + return zone; + } + + @Override + public void reset(int iteration) { + personArrivalCoordMap.clear(); + personDepartureCoordMap.clear(); + } +} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java index 20c9291dc1b..8abf76dcb37 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java @@ -13,7 +13,7 @@ public class PtFareConfigGroup extends ReflectiveConfigGroup { public static final String APPLY_UPPER_BOUND = "applyUpperBound"; public static final String UPPER_BOUND_FACTOR = "upperBoundFactor"; - public enum PtFareCalculationModels {distanceBased} // More to come (e.g. zone based, hybrid...) + public enum PtFareCalculationModels {distanceBased, fareZoneBased} // More to come (e.g. zone based, hybrid...) private static final String PT_FARE_CALCULATION_CMT = "PT fare calculation scheme. Current implementation: distanceBased (more to come...)"; public static final String UPPER_BOUND_FACTOR_CMT = "When upper bound is applied, upperBound = upperBoundFactor * max Fare of the day. " + diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java index 9bd25cc81f4..4da41c16612 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java @@ -11,12 +11,15 @@ public void install() { getConfig().scoring().getModes().get(TransportMode.pt).setDailyMonetaryConstant(0); getConfig().scoring().getModes().get(TransportMode.pt).setMarginalUtilityOfDistance(0); PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(this.getConfig(), PtFareConfigGroup.class); + DistanceBasedPtFareParams distanceBasedPtFareParams = ConfigUtils.addOrGetModule(this.getConfig(), DistanceBasedPtFareParams.class); + if (ptFareConfigGroup.getPtFareCalculation() == PtFareConfigGroup.PtFareCalculationModels.distanceBased) { - DistanceBasedPtFareParams distanceBasedPtFareParams = ConfigUtils.addOrGetModule(this.getConfig(), DistanceBasedPtFareParams.class); - addEventHandlerBinding().toInstance(new DistanceBasedPtFareHandler(distanceBasedPtFareParams)); - } else { + addEventHandlerBinding().toInstance(new DistanceBasedPtFareHandler(distanceBasedPtFareParams)); + } else if (ptFareConfigGroup.getPtFareCalculation() == PtFareConfigGroup.PtFareCalculationModels.fareZoneBased) { + addEventHandlerBinding().toInstance(new FareZoneBasedPtFareHandler(distanceBasedPtFareParams)); + } else { throw new RuntimeException("Please choose from the following fare Calculation method: [" + - PtFareConfigGroup.PtFareCalculationModels.distanceBased + "]"); + PtFareConfigGroup.PtFareCalculationModels.distanceBased + ", " + PtFareConfigGroup.PtFareCalculationModels.fareZoneBased + "]"); } if (ptFareConfigGroup.getApplyUpperBound()) { diff --git a/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java b/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java new file mode 100644 index 00000000000..ec486ec2cee --- /dev/null +++ b/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java @@ -0,0 +1,124 @@ +package playground.vsp.pt.fare; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.analysis.personMoney.PersonMoneyEventsAnalysisModule; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.population.*; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controler; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.scenario.MutableScenario; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; +import org.matsim.testcases.MatsimTestUtils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import static org.matsim.application.ApplicationUtils.globFile; + +public class FareZoneBasedPtFareHandlerTest { + + @RegisterExtension + private MatsimTestUtils utils = new MatsimTestUtils(); + + @Test + void testFareZoneBasedPtFareHandler() { + + URL context = ExamplesUtils.getTestScenarioURL("kelheim"); + Config config = ConfigUtils.loadConfig(IOUtils.extendUrl(context, "config.xml")); + config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + config.controller().setLastIteration(0); + + PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(config, PtFareConfigGroup.class); + ptFareConfigGroup.setPtFareCalculationModel(PtFareConfigGroup.PtFareCalculationModels.fareZoneBased); + + DistanceBasedPtFareParams fareParams = ConfigUtils.addOrGetModule(config, DistanceBasedPtFareParams.class); + fareParams.setFareZoneShp(IOUtils.extendUrl(context, "ptTestArea/pt-area.shp").toString()); + + + ScoringConfigGroup scoring = ConfigUtils.addOrGetModule(config, ScoringConfigGroup.class); + + ScoringConfigGroup.ActivityParams homeParams = new ScoringConfigGroup.ActivityParams("home"); + ScoringConfigGroup.ActivityParams workParams = new ScoringConfigGroup.ActivityParams("work"); + homeParams.setTypicalDuration(8 * 3600.); + workParams.setTypicalDuration(8 * 3600.); + scoring.addActivityParams(homeParams); + scoring.addActivityParams(workParams); + + + MutableScenario scenario = (MutableScenario) ScenarioUtils.loadScenario(config); + + Population population = ScenarioUtils.createScenario(ConfigUtils.createConfig()).getPopulation(); + PopulationFactory fac = population.getFactory(); + + Person person = fac.createPerson(Id.createPersonId("fareTestPerson")); + Plan plan = fac.createPlan(); + + Activity home = fac.createActivityFromCoord("home", new Coord(710300.624,5422165.737)); +// bus to Saal (Donau) work location departs at 09:14 + home.setEndTime(9 * 3600.); + Activity work = fac.createActivityFromCoord("work", new Coord(714940.65,5420707.78)); +// rb17 to regensburg 2nd home location departs at 13:59 + work.setEndTime(13 * 3600. + 45 * 60); + Activity home2 = fac.createActivityFromCoord("home", new Coord(726634.40,5433508.07)); + + Leg leg = fac.createLeg(TransportMode.pt); + + plan.addActivity(home); + plan.addLeg(leg); + plan.addActivity(work); + plan.addLeg(leg); + plan.addActivity(home2); + + person.addPlan(plan); + population.addPerson(person); + scenario.setPopulation(population); + + Controler controler = new Controler(scenario); + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new PtFareModule()); + install(new PersonMoneyEventsAnalysisModule()); + } + }); + controler.run(); + + Assertions.assertTrue(Files.exists(Path.of(utils.getOutputDirectory()))); + +// read personMoneyEvents.tsv and check if both fare entries do have the correct fare type + String filePath = globFile(Path.of(utils.getOutputDirectory()), "*output_personMoneyEvents.tsv*").toString(); + String line; + List events = new ArrayList<>(); + + try (BufferedReader br = IOUtils.getBufferedReader(filePath)) { +// skip header + br.readLine(); + + while ((line = br.readLine()) != null) { + events.add(line.split(";")); + } + } catch (IOException e) { + e.printStackTrace(); + } + + Assertions.assertEquals(2, events.size()); + Assertions.assertEquals(FareZoneBasedPtFareHandler.PT_FARE_ZONE_BASED, events.get(0)[4]); + Assertions.assertEquals(FareZoneBasedPtFareHandler.PT_GERMANWIDE_FARE_BASED, events.get(1)[4]); + } +} diff --git a/examples/scenarios/kelheim/ptTestArea/pt-area.cpg b/examples/scenarios/kelheim/ptTestArea/pt-area.cpg new file mode 100644 index 00000000000..3ad133c048f --- /dev/null +++ b/examples/scenarios/kelheim/ptTestArea/pt-area.cpg @@ -0,0 +1 @@ +UTF-8 \ No newline at end of file diff --git a/examples/scenarios/kelheim/ptTestArea/pt-area.dbf b/examples/scenarios/kelheim/ptTestArea/pt-area.dbf new file mode 100644 index 0000000000000000000000000000000000000000..e17541dab999012ee260f988c47319e51b56771b GIT binary patch literal 330 zcmZRs;b3KCU|=}N&;cYdL1qeE%n!ukf^#7ZKSy6zsE{*=4uEoClw**qBa{u+FToF! zfzY}6DXCBquzqy&(-Mnd@?ibk%&7W#72v?oB`8GKzaX_Ju_QA;PuH<1H4!dH7DEdM QNGU2oG0#xX)WARr09(r;z5oCK literal 0 HcmV?d00001 diff --git a/examples/scenarios/kelheim/ptTestArea/pt-area.prj b/examples/scenarios/kelheim/ptTestArea/pt-area.prj new file mode 100644 index 00000000000..bd846aeb220 --- /dev/null +++ b/examples/scenarios/kelheim/ptTestArea/pt-area.prj @@ -0,0 +1 @@ +PROJCS["ETRS_1989_UTM_Zone_32N",GEOGCS["GCS_ETRS_1989",DATUM["D_ETRS_1989",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",9.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/examples/scenarios/kelheim/ptTestArea/pt-area.shp b/examples/scenarios/kelheim/ptTestArea/pt-area.shp new file mode 100644 index 0000000000000000000000000000000000000000..a798ec1b8bf6937c07c6ae55c679a3412e7ed06c GIT binary patch literal 348 zcmZQzQ0HR64%WS3W?*0i$~B%pRI_f5s-x}KoKT)MA&w%6yXAh}RdtN$O*Qq|6yk_o zJBlbHkXJ#BSs;ZxP_0`Ue5%7&A?(@l?+fR%4XTbAo*xc~1MPM7dbfGwSye}!_#c^8 z8$ulKPBn4ceM8kzTFdgwi**QhZY(?{Vzf5IanJUzBC~I*Iwo!6?6wB_c)s#!Nj)zS8APAJcs5J!>3-EzO~syasWrkeU}3US1) L9Yxd#$g2PVpUn^* literal 0 HcmV?d00001 From e981bde003b91aa599b51cac12c43d36ea35ed6a Mon Sep 17 00:00:00 2001 From: schlenther Date: Thu, 8 Aug 2024 16:34:20 +0200 Subject: [PATCH 044/111] better defaults for NoiseDashboard --- .../org/matsim/simwrapper/dashboard/NoiseDashboard.java | 8 ++++---- .../main/java/org/matsim/simwrapper/viz/ColorScheme.java | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java index dc934e6c2e2..b502f3fbf57 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java @@ -42,7 +42,7 @@ public void configure(Header header, Layout layout) { viz.maxHeight = 20; viz.center = data.context().getCenter(); viz.zoom = data.context().mapZoomLevel; - viz.setColorRamp(new double[]{40, 50, 60}, new String[]{"#1175b3", "#95c7df", "#f4a986", "#cc0c27"}); + viz.setColorRamp(new double[]{30, 40, 50, 60, 70}, new String[]{"#1175b3", "#95c7df", "#dfdb95", "#dfb095", "#f4a986", "#cc0c27"}); viz.file = data.computeWithPlaceholder(NoiseAnalysis.class, "immission_per_day.%s", "avro"); }) .el(MapPlot.class, (viz, data) -> { @@ -58,8 +58,8 @@ public void configure(Header header, Layout layout) { viz.display.lineColor.dataset = "noise"; viz.display.lineColor.columnName = "value"; viz.display.lineColor.join = "Link Id"; - viz.display.lineColor.fixedColors = new String[]{"#1175b3", "#95c7df", "#f4a986", "#cc0c27"}; - viz.display.lineColor.setColorRamp(ColorScheme.RdYlBu, 4, true, "45, 55, 65"); + //viz.display.lineColor.fixedColors = new String[]{"#1175b3", "#95c7df", "#f4a986", "#cc0c27"}; + viz.display.lineColor.setColorRamp(ColorScheme.Oranges, 8, false, "35, 45, 55, 65, 75, 85, 95"); viz.display.lineWidth.dataset = "noise"; viz.display.lineWidth.columnName = "value"; viz.display.lineWidth.scaleFactor = 8d; @@ -75,7 +75,7 @@ public void configure(Header header, Layout layout) { viz.maxHeight = 20; viz.center = data.context().getCenter(); viz.zoom = data.context().mapZoomLevel; - viz.setColorRamp(new double[]{40, 50, 60}, new String[]{"#1175b3", "#95c7df", "#f4a986", "#cc0c27"}); + viz.setColorRamp(new double[]{30, 40, 50, 60, 70}, new String[]{"#1175b3", "#95c7df", "#dfdb95", "#dfb095", "#f4a986", "#cc0c27"}); viz.file = data.computeWithPlaceholder(NoiseAnalysis.class, "immission_per_hour.%s", "avro"); }); } diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/viz/ColorScheme.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/viz/ColorScheme.java index 37e31cc97ca..df8f6410679 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/viz/ColorScheme.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/viz/ColorScheme.java @@ -27,6 +27,7 @@ public final class ColorScheme { public static final String Inferne = "Inferne"; public static final String Cividis = "Cividis"; public static final String Rainbow = "Rainbow"; + public static final String Oranges = "Oranges"; private ColorScheme() { From cdfe0bc6de01513c198ed851e089a212e2da2b11 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Thu, 8 Aug 2024 17:02:45 +0200 Subject: [PATCH 045/111] remove the static --- .../prepare/CreateDataDistributionOfStructureData.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/prepare/CreateDataDistributionOfStructureData.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/prepare/CreateDataDistributionOfStructureData.java index 477231505c1..dcd4c3732d9 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/prepare/CreateDataDistributionOfStructureData.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/prepare/CreateDataDistributionOfStructureData.java @@ -29,7 +29,7 @@ public class CreateDataDistributionOfStructureData implements MATSimAppCommand { private static final Logger log = LogManager.getLogger(CreateDataDistributionOfStructureData.class); - private static LanduseDataConnectionCreator landuseDataConnectionCreator; + private final LanduseDataConnectionCreator landuseDataConnectionCreator; private enum LanduseConfiguration { useOnlyOSMLanduse, useOSMBuildingsAndLanduse @@ -78,16 +78,16 @@ private enum LanduseConfiguration { private final Map>> buildingsPerZone = new HashMap<>(); public CreateDataDistributionOfStructureData(LanduseDataConnectionCreator landuseDataConnectionCreator) { - CreateDataDistributionOfStructureData.landuseDataConnectionCreator = landuseDataConnectionCreator; + this.landuseDataConnectionCreator = landuseDataConnectionCreator; log.info("Using LanduseDataConnectionCreator {} to connect the types of the landuse data to the categories of the small scale commercial traffic generation", landuseDataConnectionCreator.getClass().getSimpleName()); } public CreateDataDistributionOfStructureData() { - landuseDataConnectionCreator = new LanduseDataConnectionCreatorForOSM_Data(); + this.landuseDataConnectionCreator = new LanduseDataConnectionCreatorForOSM_Data(); log.info("Using default LanduseDataConnectionCreatorForOSM_Data to connect the types of the landuse data to the categories of the small scale commercial traffic generation"); } public static void main(String[] args) { - System.exit(new CommandLine(new CreateDataDistributionOfStructureData(landuseDataConnectionCreator)).execute(args)); + System.exit(new CommandLine(new CreateDataDistributionOfStructureData()).execute(args)); } @Override From 624ca13d060c4313c753868fc14f5c947da6d845 Mon Sep 17 00:00:00 2001 From: schlenther Date: Thu, 8 Aug 2024 18:05:56 +0200 Subject: [PATCH 046/111] NoiseAnalysis: more explicit parameter settings + bug fix in MergeNoiseOutput --- .../analysis/noise/MergeNoiseOutput.java | 14 ++-- .../analysis/noise/NoiseAnalysis.java | 67 +++++++++++++------ .../contrib/noise/NoiseConfigGroup.java | 4 +- .../simwrapper/dashboard/NoiseDashboard.java | 4 +- 4 files changed, 60 insertions(+), 29 deletions(-) diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/noise/MergeNoiseOutput.java b/contribs/application/src/main/java/org/matsim/application/analysis/noise/MergeNoiseOutput.java index aef1ec23d05..88f8f9354e5 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/noise/MergeNoiseOutput.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/noise/MergeNoiseOutput.java @@ -118,6 +118,7 @@ public void run() { * @param output */ private void writeAvro(XYTData xytData, File output) { + log.info(String.format("Start writing avro file to %s", output.toString() )); DatumWriter datumWriter = new SpecificDatumWriter<>(XYTData.class); try (DataFileWriter dataFileWriter = new DataFileWriter<>(datumWriter)) { dataFileWriter.setCodec(CodecFactory.deflateCodec(9)); @@ -143,9 +144,8 @@ private void mergeEmissions(String pathParameter, String label) { .separator(';').build()); for (Row row : table) { - // index for Noise Emission xx:xx:xx -> 7 String linkId = row.getString("Link Id"); - double value = row.getDouble(7); + double value = row.getDouble(row.columnCount() - 1); mergedData.mergeDouble(linkId, value, Double::max); } @@ -188,7 +188,10 @@ private void mergeImissions(String pathParameter, String label) { // Read the file Table table = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(path)) - .columnTypesPartial(Map.of("x", ColumnType.FLOAT, "y", ColumnType.FLOAT, "Receiver Point Id", ColumnType.INTEGER, "t", ColumnType.DOUBLE)) + .columnTypesPartial(Map.of("x", ColumnType.FLOAT, + "y", ColumnType.FLOAT, + "Receiver Point Id", ColumnType.INTEGER, + "t", ColumnType.DOUBLE)) .sample(false) .separator(';').build()); @@ -278,7 +281,10 @@ private void mergeImmissionsCSV(String pathParameter, String label) { // Read the file Table table = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(path)) - .columnTypesPartial(Map.of("x", ColumnType.DOUBLE, "y", ColumnType.DOUBLE, "Receiver Point Id", ColumnType.INTEGER, "t", ColumnType.DOUBLE)) + .columnTypesPartial(Map.of("x", ColumnType.DOUBLE, + "y", ColumnType.DOUBLE, + "Receiver Point Id", ColumnType.INTEGER, + "t", ColumnType.DOUBLE)) .sample(false) .separator(';').build()); 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 6730cae8996..02d6337de15 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 @@ -55,7 +55,7 @@ public class NoiseAnalysis implements MATSimAppCommand { private final SampleOptions sampleOptions = new SampleOptions(); @CommandLine.Option(names = "--consider-activities", split = ",", description = "Considered activities for noise calculation." + - " Use asterisk ('*') for acttype prefixes, if all such acts shall be considered.", defaultValue = "h,w,home*,work*") + " Use asterisk ('*') for acttype prefixes, if all such acts shall be considered.", defaultValue = "home*,work*,educ*,leisure*") private Set considerActivities; @CommandLine.Option(names = "--noise-barrier", description = "Path to the noise barrier File", defaultValue = "") @@ -71,32 +71,55 @@ public Integer call() throws Exception { config.controller().setOutputDirectory(input.getRunDirectory().toString()); - // adjust the default noise parameters + //trying to set noise parameters more explicitly, here... + //if NoiseConfigGroup was added before. do not override (most) parameters + boolean overrideParameters = ! ConfigUtils.hasModule(config, NoiseConfigGroup.class); NoiseConfigGroup noiseParameters = ConfigUtils.addOrGetModule(config, NoiseConfigGroup.class); - noiseParameters.setConsideredActivitiesForReceiverPointGridArray(considerActivities.toArray(String[]::new)); - noiseParameters.setConsideredActivitiesForDamageCalculationArray(considerActivities.toArray(String[]::new)); - if (shp.getShapeFile() != null) { - CoordinateTransformation ct = shp.createInverseTransformation(config.global().getCoordinateSystem()); - Envelope bbox = shp.getGeometry().getEnvelopeInternal(); + if(overrideParameters){ + log.warn("no NoiseConfigGroup was configured before. Will set som estandards. You should check the next lines in the log file!"); + noiseParameters.setConsideredActivitiesForReceiverPointGridArray(considerActivities.toArray(String[]::new)); + noiseParameters.setConsideredActivitiesForDamageCalculationArray(considerActivities.toArray(String[]::new)); - Coord minCoord = ct.transform(new Coord(bbox.getMinX(), bbox.getMinY())); - Coord maxCoord = ct.transform(new Coord(bbox.getMaxX(), bbox.getMaxY())); + //use actual speed and not freespeed + noiseParameters.setUseActualSpeedLevel(true); + //use the valid speed range (recommended by IK) + noiseParameters.setAllowForSpeedsOutsideTheValidRange(false); - noiseParameters.setReceiverPointsGridMinX(minCoord.getX()); - noiseParameters.setReceiverPointsGridMinY(minCoord.getY()); - noiseParameters.setReceiverPointsGridMaxX(maxCoord.getX()); - noiseParameters.setReceiverPointsGridMaxY(maxCoord.getY()); - } + if (shp.getShapeFile() != null) { + CoordinateTransformation ct = shp.createInverseTransformation(config.global().getCoordinateSystem()); + + Envelope bbox = shp.getGeometry().getEnvelopeInternal(); + + Coord minCoord = ct.transform(new Coord(bbox.getMinX(), bbox.getMinY())); + Coord maxCoord = ct.transform(new Coord(bbox.getMaxX(), bbox.getMaxY())); + + noiseParameters.setReceiverPointsGridMinX(minCoord.getX()); + noiseParameters.setReceiverPointsGridMinY(minCoord.getY()); + noiseParameters.setReceiverPointsGridMaxX(maxCoord.getX()); + noiseParameters.setReceiverPointsGridMaxY(maxCoord.getY()); + } - noiseParameters.setNoiseComputationMethod(NoiseConfigGroup.NoiseComputationMethod.RLS19); + noiseParameters.setNoiseComputationMethod(NoiseConfigGroup.NoiseComputationMethod.RLS19); - if (!Objects.equals(noiseBarrierFile, "")) { - noiseParameters.setNoiseBarriersSourceCRS(config.global().getCoordinateSystem()); - noiseParameters.setConsiderNoiseBarriers(true); - noiseParameters.setNoiseBarriersFilePath(noiseBarrierFile); + if (!Objects.equals(noiseBarrierFile, "")) { + noiseParameters.setNoiseBarriersSourceCRS(config.global().getCoordinateSystem()); + noiseParameters.setConsiderNoiseBarriers(true); + noiseParameters.setNoiseBarriersFilePath(noiseBarrierFile); + } + } else { + log.warn("will override a few settings in NoiseConfigGroup, as we are now doing postprocessing and do not want any internalization etc." + + " You should check the next lines in the log file!"); } + // we only mean to do postprocessing here, thus no internalization etc + noiseParameters.setInternalizeNoiseDamages(false); + noiseParameters.setComputeCausingAgents(false); + //we don't need events (for Dashboard) - spare disk space. + noiseParameters.setThrowNoiseEventsAffected(false); + noiseParameters.setThrowNoiseEventsCaused(false); + noiseParameters.setComputeNoiseDamages(true); + if(! sampleOptions.isSet() && noiseParameters.getScaleFactor() == 1d){ log.warn("You didn't provide the simulation sample size via command line option --sample-size! This means, noise damages are not scaled!!!"); } else if (noiseParameters.getScaleFactor() == 1d){ @@ -111,6 +134,9 @@ public Integer call() throws Exception { String outputFilePath = output.getPath().getParent() == null ? "." : output.getPath().getParent().toString(); + log.info("starting " + NoiseOfflineCalculation.class + " with the following parameters:\n" + + noiseParameters); + NoiseOfflineCalculation noiseCalculation = new NoiseOfflineCalculation(scenario, outputFilePath); outputFilePath += "/noise-analysis"; noiseCalculation.run(); @@ -122,12 +148,11 @@ public Integer call() throws Exception { MergeNoiseOutput mergeNoiseOutput = new MergeNoiseOutput(paths, Path.of(outputFilePath), config.global().getCoordinateSystem()); mergeNoiseOutput.run(); - return 0; } private Config prepareConfig() { - Config config = ConfigUtils.loadConfig(ApplicationUtils.matchInput("config.xml", input.getRunDirectory()).toAbsolutePath().toString(), new NoiseConfigGroup()); + Config config = ConfigUtils.loadConfig(ApplicationUtils.matchInput("config.xml", input.getRunDirectory()).toAbsolutePath().toString()); //it is important to match "output_vehicles.xml.gz" specifically, because otherwise dvrpVehicle files might be matched and the code crashes later config.vehicles().setVehiclesFile(ApplicationUtils.matchInput("output_vehicles.xml.gz", input.getRunDirectory()).toAbsolutePath().toString()); diff --git a/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseConfigGroup.java b/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseConfigGroup.java index cd7b2a500ab..06e793c85d9 100644 --- a/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseConfigGroup.java +++ b/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseConfigGroup.java @@ -95,8 +95,8 @@ public NoiseConfigGroup() { private double receiverPointGap = 250.; - private String[] consideredActivitiesForReceiverPointGrid = {"home", "work"}; - private String[] consideredActivitiesForDamageCalculation = {"home", "work"}; + private String[] consideredActivitiesForReceiverPointGrid = {"home*", "work*"}; + private String[] consideredActivitiesForDamageCalculation = {"home*", "work*"}; private double receiverPointsGridMinX = 0.; private double receiverPointsGridMinY = 0.; diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java index b502f3fbf57..036b3c5a718 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java @@ -35,7 +35,7 @@ public void configure(Header header, Layout layout) { layout.row("aggregate noise") .el(GridMap.class, (viz, data) -> { viz.title = "Noise Immissions (Grid)"; - viz.description = "Aggregate Noise Immissions per day"; + viz.description = "Total Noise Immissions per day"; viz.height = 12.0; viz.cellSize = 250; viz.opacity = 0.2; @@ -47,7 +47,7 @@ public void configure(Header header, Layout layout) { }) .el(MapPlot.class, (viz, data) -> { viz.title = "Noise Emissions (Link)"; - viz.description = "Aggregate Noise Emissions per day"; + viz.description = "Maximum Noise Level per day [dB]"; viz.height = 12.0; viz.center = data.context().getCenter(); viz.zoom = data.context().mapZoomLevel; From a455df3d4280aeced29d55a5044014b8e61eb995 Mon Sep 17 00:00:00 2001 From: Chengqi Lu <43133404+luchengqi7@users.noreply.github.com> Date: Fri, 9 Aug 2024 10:26:20 +0200 Subject: [PATCH 047/111] Update DRT estimate and teleport module (#3333) Re-organizing the DRT estimation scripts. For more details, please see detailed description above. --- .../MultiModalDrtLegEstimatorTest.java | 4 +- .../impl/DetourBasedDrtEstimator.java | 76 ---------- .../impl/DirectTripBasedDrtEstimator.java | 130 ++++++++++++++++++ .../EuclideanDistanceBasedDrtEstimator.java | 65 ++++----- ...stimator.java => ExampleDrtEstimator.java} | 6 +- ...=> OnlineSimulationBasedDrtEstimator.java} | 11 +- .../distribution/DistributionGenerator.java | 10 ++ .../LogNormalDistributionGenerator.java | 35 +++++ .../impl/distribution/NoDistribution.java | 8 ++ .../NormalDistributionGenerator.java | 34 +++++ .../ConstantRideDurationEstimator.java | 20 +++ .../RideDurationEstimator.java | 11 ++ .../ConstantWaitingTimeEstimator.java | 18 +++ .../ShapeFileBasedWaitingTimeEstimator.java | 63 +++++++++ .../WaitingTimeEstimator.java | 9 ++ .../estimator/DrtEstimateAndTeleportTest.java | 59 ++++++++ .../DrtTeleportationWithModeChoiceTest.java | 3 - 17 files changed, 441 insertions(+), 121 deletions(-) delete mode 100644 contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/DetourBasedDrtEstimator.java create mode 100644 contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/DirectTripBasedDrtEstimator.java rename contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/{ConstantDrtEstimator.java => ExampleDrtEstimator.java} (82%) rename contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/{BasicDrtEstimator.java => OnlineSimulationBasedDrtEstimator.java} (90%) create mode 100644 contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/DistributionGenerator.java create mode 100644 contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/LogNormalDistributionGenerator.java create mode 100644 contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/NoDistribution.java create mode 100644 contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/NormalDistributionGenerator.java create mode 100644 contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/trip_estimation/ConstantRideDurationEstimator.java create mode 100644 contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/trip_estimation/RideDurationEstimator.java create mode 100644 contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/ConstantWaitingTimeEstimator.java create mode 100644 contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/ShapeFileBasedWaitingTimeEstimator.java create mode 100644 contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/WaitingTimeEstimator.java create mode 100644 contribs/drt/src/test/java/org/matsim/contrib/drt/estimator/DrtEstimateAndTeleportTest.java diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimatorTest.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimatorTest.java index f925ed604dd..d5e606ed980 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimatorTest.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimatorTest.java @@ -5,7 +5,7 @@ import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.application.MATSimApplication; import org.matsim.contrib.drt.estimator.DrtEstimatorModule; -import org.matsim.contrib.drt.estimator.impl.ConstantDrtEstimator; +import org.matsim.contrib.drt.estimator.impl.ExampleDrtEstimator; import org.matsim.contrib.drt.extension.DrtTestScenario; import org.matsim.contrib.drt.extension.modechoice.MultiModalDrtLegEstimator; import org.matsim.contrib.drt.run.DrtConfigGroup; @@ -51,7 +51,7 @@ public void install() { for (DrtConfigGroup el : drtConfig.getModalElements()) { install(new DrtEstimatorModule(el.mode, el, el.getDrtEstimatorParams().get())); - DrtEstimatorModule.bindEstimator(binder(), el.mode).toInstance(new ConstantDrtEstimator(1.05, 300)); + DrtEstimatorModule.bindEstimator(binder(), el.mode).toInstance(new ExampleDrtEstimator(1.05, 300)); } } }); diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/DetourBasedDrtEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/DetourBasedDrtEstimator.java deleted file mode 100644 index e85e5595930..00000000000 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/DetourBasedDrtEstimator.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.matsim.contrib.drt.estimator.impl; - -import org.matsim.contrib.drt.estimator.DrtEstimator; -import org.matsim.contrib.drt.routing.DrtRoute; -import org.matsim.core.utils.misc.OptionalTime; - -import java.util.Random; - -/** - * A simple DRT estimator that uses normal distributions to estimate the ride time, wait time, ride distance and acceptance. - */ -public final class DetourBasedDrtEstimator implements DrtEstimator { - - private final NormalDistributionGenerator distributionGenerator; - - private DetourBasedDrtEstimator(double estRideTimeAlpha, double estRideTimeBeta, double rideTimeStd, double estMeanWaitTime, - double waitTimeStd) { - this.distributionGenerator = new NormalDistributionGenerator(estRideTimeAlpha, estRideTimeBeta, rideTimeStd, estMeanWaitTime, waitTimeStd); - } - - public static DetourBasedDrtEstimator normalDistributed(double estRideTimeAlpha, double estRideTimeBeta, double rideTimeStd, double estMeanWaitTime, - double waitTimeStd) { - return new DetourBasedDrtEstimator(estRideTimeAlpha, estRideTimeBeta, rideTimeStd, estMeanWaitTime, waitTimeStd); - } - - @Override - public Estimate estimate(DrtRoute route, OptionalTime departureTime) { - double directRideTIme = route.getDirectRideTime(); - double directDistance = route.getDistance(); - double waitTime = distributionGenerator.generateWaitTime(); - double rideTime = distributionGenerator.generateRideTime(directRideTIme); - double rideDistance = distributionGenerator.generateRideDistance(rideTime, directRideTIme, directDistance); - double acceptanceRate = distributionGenerator.generateAcceptanceRate(); - - return new Estimate(rideDistance, waitTime + rideTime, waitTime, acceptanceRate); - } - - private static class NormalDistributionGenerator { - private final Random random = new Random(4711); - private final double estRideTimeAlpha; - private final double estRideTimeBeta; - private final double rideTimeStd; - private final double estMeanWaitTime; - private final double waitTimeStd; - - public NormalDistributionGenerator(double estRideTimeAlpha, double estRideTimeBeta, double rideTimeStd, double estMeanWaitTime, - double waitTimeStd) { - this.estRideTimeAlpha = estRideTimeAlpha; - this.estRideTimeBeta = estRideTimeBeta; - this.rideTimeStd = rideTimeStd; - this.estMeanWaitTime = estMeanWaitTime; - this.waitTimeStd = waitTimeStd; - } - - public double generateRideTime(double directRideTime) { - // TODO improve this distribution - double estMeanRideTime = estRideTimeAlpha * directRideTime + estRideTimeBeta; - return Math.max(directRideTime, estMeanRideTime * (1 + random.nextGaussian() * rideTimeStd)); - } - - public double generateRideDistance(double estRideTime, double directRideTime, double directRideDistance) { - // TODO Currently, same ratio is used as in the ride time estimation; improve this distribution - double ratio = estRideTime / directRideTime; - return ratio * directRideDistance; - } - - public double generateWaitTime() { - // TODO improve this distribution - return Math.max(estMeanWaitTime * (1 + random.nextGaussian() * waitTimeStd), 0); - } - - public double generateAcceptanceRate() { - return 1; - } - } -} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/DirectTripBasedDrtEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/DirectTripBasedDrtEstimator.java new file mode 100644 index 00000000000..08ae52d5a0a --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/DirectTripBasedDrtEstimator.java @@ -0,0 +1,130 @@ +package org.matsim.contrib.drt.estimator.impl; + +import org.checkerframework.checker.units.qual.C; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.drt.estimator.DrtEstimator; +import org.matsim.contrib.drt.estimator.impl.distribution.DistributionGenerator; +import org.matsim.contrib.drt.estimator.impl.distribution.LogNormalDistributionGenerator; +import org.matsim.contrib.drt.estimator.impl.distribution.NoDistribution; +import org.matsim.contrib.drt.estimator.impl.distribution.NormalDistributionGenerator; +import org.matsim.contrib.drt.estimator.impl.trip_estimation.ConstantRideDurationEstimator; +import org.matsim.contrib.drt.estimator.impl.trip_estimation.RideDurationEstimator; +import org.matsim.contrib.drt.estimator.impl.waiting_time_estimation.ConstantWaitingTimeEstimator; +import org.matsim.contrib.drt.estimator.impl.waiting_time_estimation.WaitingTimeEstimator; +import org.matsim.contrib.drt.routing.DrtRoute; +import org.matsim.core.utils.misc.OptionalTime; + +/** + * DRT estimator that uses available data (e.g., real-world operational data, simulation-based data) to provide estimated data for DRT trips. + */ +public final class DirectTripBasedDrtEstimator implements DrtEstimator { + private final RideDurationEstimator rideDurationEstimator; + private final WaitingTimeEstimator waitingTimeEstimator; + private final DistributionGenerator waitingTimeDistributionGenerator; + private final DistributionGenerator rideTimeDistributionGenerator; + + public static class Builder { + // Initialize with default estimation + private RideDurationEstimator rideDurationEstimator = new ConstantRideDurationEstimator(1.25, 300); + private WaitingTimeEstimator waitingTimeEstimator = new ConstantWaitingTimeEstimator(300); + private DistributionGenerator waitingTimeDistributionGenerator = new NoDistribution(); + private DistributionGenerator rideTimeDistributionGenerator = new NoDistribution(); + + public Builder setRideDurationEstimator(RideDurationEstimator rideDurationEstimator) { + this.rideDurationEstimator = rideDurationEstimator; + return this; + } + + public Builder setWaitingTimeEstimator(WaitingTimeEstimator waitingTimeEstimator) { + this.waitingTimeEstimator = waitingTimeEstimator; + return this; + } + + public Builder setRideDurationDistributionGenerator(DistributionGenerator rideTimeDistributionGenerator) { + this.rideTimeDistributionGenerator = rideTimeDistributionGenerator; + return this; + } + + public Builder setWaitingTimeDistributionGenerator(DistributionGenerator waitingTimeDistributionGenerator) { + this.waitingTimeDistributionGenerator = waitingTimeDistributionGenerator; + return this; + } + + public DirectTripBasedDrtEstimator build() { + return new DirectTripBasedDrtEstimator(rideDurationEstimator, waitingTimeEstimator, rideTimeDistributionGenerator, waitingTimeDistributionGenerator); + } + + } + + public DirectTripBasedDrtEstimator(RideDurationEstimator rideDurationEstimator, WaitingTimeEstimator waitingTimeEstimator, + DistributionGenerator rideTimeDistribution, DistributionGenerator waitTimeDistribution) { + this.rideDurationEstimator = rideDurationEstimator; + this.waitingTimeEstimator = waitingTimeEstimator; + this.rideTimeDistributionGenerator = rideTimeDistribution; + this.waitingTimeDistributionGenerator = waitTimeDistribution; + } + + /** + * Example DRT estimator based on the normal distributed ride time and waiting time + * @param estRideTimeAlpha typical ride duration = alpha * direct ride time + beta, alpha is specified here + * @param estRideTimeBeta typical ride duration = alpha * direct ride time + beta, beta is specified here + * @param rideTimeStd standard deviation of ride duration (normalized to 1) + * @param estMeanWaitTime estimated waiting time (i.e., mean wait time) + * @param waitTimeStd standard deviation of waiting time (normalized to 1) + * @return NetworkBasedDrtEstimator + */ + public static DirectTripBasedDrtEstimator normalDistributedNetworkBasedDrtEstimator(double estRideTimeAlpha, double estRideTimeBeta, + double rideTimeStd, double estMeanWaitTime, + double waitTimeStd) { + return new Builder() + .setWaitingTimeEstimator(new ConstantWaitingTimeEstimator(estMeanWaitTime)) + .setRideDurationEstimator(new ConstantRideDurationEstimator(estRideTimeAlpha, estRideTimeBeta)) + .setWaitingTimeDistributionGenerator(new NormalDistributionGenerator(1, waitTimeStd)) + .setRideDurationDistributionGenerator(new NormalDistributionGenerator(2, rideTimeStd)) + .build(); + } + + /** + * Example DRT estimator based on the log-normal distributed ride time and normal distributed waiting time + * @param estRideTimeAlpha typical ride duration = alpha * direct ride time + beta, alpha is specified here + * @param estRideTimeBeta typical ride duration = alpha * direct ride time + beta, beta is specified here + * @param mu log-normal distribution parameter for ride duration (normalized to typical ride duration) + * @param sigma log-normal distribution parameter for ride duration (normalized to typical ride duration) + * @param estMeanWaitTime estimated waiting time (i.e., mean wait time) + * @param waitTimeStd standard deviation of waiting time (normalized to 1) + * @return NetworkBasedDrtEstimator + */ + public static DirectTripBasedDrtEstimator mixDistributedNetworkBasedDrtEstimator(double estRideTimeAlpha, double estRideTimeBeta, + double mu, double sigma, double estMeanWaitTime, + double waitTimeStd) { + return new Builder() + .setWaitingTimeEstimator(new ConstantWaitingTimeEstimator(estMeanWaitTime)) + .setRideDurationEstimator(new ConstantRideDurationEstimator(estRideTimeAlpha, estRideTimeBeta)) + .setWaitingTimeDistributionGenerator(new NormalDistributionGenerator(1, waitTimeStd)) + .setRideDurationDistributionGenerator(new LogNormalDistributionGenerator(2, mu, sigma)) + .build(); + } + + @Override + public Estimate estimate(DrtRoute route, OptionalTime departureTime) { + double directRideTIme = route.getDirectRideTime(); + double directDistance = route.getDistance(); + Id fromLinkId = route.getStartLinkId(); + Id toLinkId = route.getEndLinkId(); + double typicalRideDuration = rideDurationEstimator.getEstimatedRideDuration(fromLinkId, toLinkId, departureTime, directRideTIme); + double typicalRideDistance = (typicalRideDuration / directRideTIme) * directDistance; + double typicalWaitingTime = waitingTimeEstimator.estimateWaitTime(fromLinkId, toLinkId, departureTime); + + double estimatedWaitingTime = typicalWaitingTime * waitingTimeDistributionGenerator.generateRandomValue(); + + double detourRandomFactor = rideTimeDistributionGenerator.generateRandomValue(); + double estimatedRideDuration = detourRandomFactor * typicalRideDuration; + double estimatedRideDistance = detourRandomFactor * typicalRideDistance; + + double acceptanceRate = 1.0; + + return new Estimate(estimatedRideDistance, estimatedRideDuration, estimatedWaitingTime, acceptanceRate); + } + +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/EuclideanDistanceBasedDrtEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/EuclideanDistanceBasedDrtEstimator.java index dd3a2492ce9..8b617888084 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/EuclideanDistanceBasedDrtEstimator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/EuclideanDistanceBasedDrtEstimator.java @@ -3,12 +3,18 @@ import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.network.Network; import org.matsim.contrib.drt.estimator.DrtEstimator; +import org.matsim.contrib.drt.estimator.impl.distribution.DistributionGenerator; +import org.matsim.contrib.drt.estimator.impl.distribution.LogNormalDistributionGenerator; +import org.matsim.contrib.drt.estimator.impl.distribution.NormalDistributionGenerator; +import org.matsim.contrib.drt.estimator.impl.trip_estimation.ConstantRideDurationEstimator; +import org.matsim.contrib.drt.estimator.impl.trip_estimation.RideDurationEstimator; +import org.matsim.contrib.drt.estimator.impl.waiting_time_estimation.ConstantWaitingTimeEstimator; +import org.matsim.contrib.drt.estimator.impl.waiting_time_estimation.WaitingTimeEstimator; import org.matsim.contrib.drt.routing.DrtRoute; +import org.matsim.core.utils.collections.Tuple; import org.matsim.core.utils.geometry.CoordUtils; import org.matsim.core.utils.misc.OptionalTime; -import java.util.Random; - public class EuclideanDistanceBasedDrtEstimator implements DrtEstimator { private final Network network; /** @@ -16,26 +22,16 @@ public class EuclideanDistanceBasedDrtEstimator implements DrtEstimator { * Estimated network distance = Euclidean distance * network distance factor */ private final double networkDistanceFactor; - /** - * Slope of the linear regression - */ - private final double slope; - /** - * Intercept of the linear regression - */ - private final double intercept; - - private final double estimatedMeanWaitTime; - - private final double waitTimeStd; + private final RideDurationEstimator rideDurationEstimator; + private final WaitingTimeEstimator waitingTimeEstimator; + private final DistributionGenerator rideDurationDistributionGenerator; + private final DistributionGenerator waitingTimeDistributionGenerator; - private final double mu; - private final double sigma; - private final Random random = new Random(1234); /** * We use log normal distribution to estimate the ride duration of each individual trip. The distribution * is based on the linear regression. + * * @params networkDistanceFactor: Estimated network distance = Euclidean distance * network distance factor * @params slope: slope for the linear regression * @params intercept: intercept for linear regression @@ -47,12 +43,21 @@ public EuclideanDistanceBasedDrtEstimator(Network network, double networkDistanc double mu, double sigma) { this.network = network; this.networkDistanceFactor = networkDistanceFactor; - this.slope = slope; - this.intercept = intercept; - this.estimatedMeanWaitTime = estimatedMeanWaitTime; - this.waitTimeStd = waitTimeStd; - this.mu = mu; - this.sigma = sigma; + this.rideDurationEstimator = new ConstantRideDurationEstimator(slope, intercept); + this.waitingTimeEstimator = new ConstantWaitingTimeEstimator(estimatedMeanWaitTime); + this.rideDurationDistributionGenerator = new LogNormalDistributionGenerator(1, mu, sigma); + this.waitingTimeDistributionGenerator = new NormalDistributionGenerator(2, waitTimeStd); + } + + public EuclideanDistanceBasedDrtEstimator(Network network, double networkDistanceFactor, RideDurationEstimator rideDurationEstimator, + WaitingTimeEstimator waitingTimeEstimator, DistributionGenerator rideDurationDistributionGenerator, + DistributionGenerator waitingTimeDistributionGenerator) { + this.network = network; + this.networkDistanceFactor = networkDistanceFactor; + this.rideDurationEstimator = rideDurationEstimator; + this.waitingTimeEstimator = waitingTimeEstimator; + this.rideDurationDistributionGenerator = rideDurationDistributionGenerator; + this.waitingTimeDistributionGenerator = waitingTimeDistributionGenerator; } @Override @@ -60,19 +65,15 @@ public Estimate estimate(DrtRoute route, OptionalTime departureTime) { Coord fromCoord = network.getLinks().get(route.getStartLinkId()).getToNode().getCoord(); Coord toCoord = network.getLinks().get(route.getEndLinkId()).getToNode().getCoord(); double euclideanDistance = CoordUtils.calcEuclideanDistance(fromCoord, toCoord); - double typicalRideDuration = euclideanDistance * slope + intercept; + + double typicalRideDuration = rideDurationEstimator.getEstimatedRideDuration(route.getStartLinkId(), route.getEndLinkId(), departureTime, euclideanDistance); double typicalRideDistance = networkDistanceFactor * euclideanDistance; - double randomFactor = nextLogNormal(mu, sigma); - double waitTime = Math.max(estimatedMeanWaitTime * (1 + random.nextGaussian() * waitTimeStd), 0); + double typicalWaitingTime = waitingTimeEstimator.estimateWaitTime(route.getStartLinkId(), route.getEndLinkId(), departureTime); + double randomFactor = rideDurationDistributionGenerator.generateRandomValue(); + double waitTime = Math.max(typicalWaitingTime * waitingTimeDistributionGenerator.generateRandomValue(), 0); return new Estimate(typicalRideDistance * randomFactor, typicalRideDuration * randomFactor, waitTime, 0); } - public double nextLogNormal(double mu, double sigma) { - if (sigma == 0) - return Math.exp(mu); - - return Math.exp(sigma * random.nextGaussian() + mu); - } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/ConstantDrtEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/ExampleDrtEstimator.java similarity index 82% rename from contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/ConstantDrtEstimator.java rename to contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/ExampleDrtEstimator.java index 20ea18ee120..b49b3b988f0 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/ConstantDrtEstimator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/ExampleDrtEstimator.java @@ -2,13 +2,13 @@ import org.matsim.contrib.drt.estimator.DrtEstimator; import org.matsim.contrib.drt.routing.DrtRoute; -import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.core.utils.misc.OptionalTime; /** * Estimates using a constant detour factor and waiting time. */ -public class ConstantDrtEstimator implements DrtEstimator { +@Deprecated +public class ExampleDrtEstimator implements DrtEstimator { /** * Detour factor for the estimate. 1.0 means no detour, 2.0 means twice the distance. @@ -20,7 +20,7 @@ public class ConstantDrtEstimator implements DrtEstimator { */ private final double waitingTime; - public ConstantDrtEstimator(double detourFactor, double waitingTime) { + public ExampleDrtEstimator(double detourFactor, double waitingTime) { this.detourFactor = detourFactor; this.waitingTime = waitingTime; } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/BasicDrtEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/OnlineSimulationBasedDrtEstimator.java similarity index 90% rename from contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/BasicDrtEstimator.java rename to contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/OnlineSimulationBasedDrtEstimator.java index f02c4ee59b2..db1f3e83ccd 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/BasicDrtEstimator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/OnlineSimulationBasedDrtEstimator.java @@ -1,7 +1,6 @@ package org.matsim.contrib.drt.estimator.impl; import org.apache.commons.math3.stat.descriptive.SummaryStatistics; -import org.apache.commons.math3.stat.regression.RegressionResults; import org.apache.commons.math3.stat.regression.SimpleRegression; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -23,12 +22,14 @@ import java.util.SplittableRandom; /** + * When this estimator is used, explicit simulations of DRT will be carried out intermittently. During the iterations where no + * DRT is simulated, estimated DRT will be used. This estimator will replace the original DRT speed-up module * Estimates drt trips based only daily averages. No spatial or temporal differentiation is taken into account for the estimate. * This estimator is suited for small scenarios with few vehicles and trips and consequently few data points. */ -public class BasicDrtEstimator implements DrtOnlineEstimator, IterationEndsListener { +public class OnlineSimulationBasedDrtEstimator implements DrtOnlineEstimator, IterationEndsListener { - private static final Logger log = LogManager.getLogger(BasicDrtEstimator.class); + private static final Logger log = LogManager.getLogger(OnlineSimulationBasedDrtEstimator.class); private final DrtEventSequenceCollector collector; private final DrtEstimatorParams config; @@ -41,8 +42,8 @@ public class BasicDrtEstimator implements DrtOnlineEstimator, IterationEndsListe */ private GlobalEstimate currentEst; - public BasicDrtEstimator(DrtEventSequenceCollector collector, DrtEstimator initial, - DrtEstimatorParams config, DrtConfigGroup drtConfig) { + public OnlineSimulationBasedDrtEstimator(DrtEventSequenceCollector collector, DrtEstimator initial, + DrtEstimatorParams config, DrtConfigGroup drtConfig) { //zones = injector.getModal(DrtZonalSystem.class); this.collector = collector; this.initial = initial; diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/DistributionGenerator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/DistributionGenerator.java new file mode 100644 index 00000000000..d5e6e890729 --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/DistributionGenerator.java @@ -0,0 +1,10 @@ +package org.matsim.contrib.drt.estimator.impl.distribution; + +public interface DistributionGenerator { + /** + * @return relative value to the typical ride duration (i.e., generate a distribution around 1.0) + */ + double generateRandomValue(); + + enum DistributionType {NO_DISTRIBUTION, NORMAL, LOG_NORMAL, CUSTOM} +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/LogNormalDistributionGenerator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/LogNormalDistributionGenerator.java new file mode 100644 index 00000000000..1be1250a870 --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/LogNormalDistributionGenerator.java @@ -0,0 +1,35 @@ +package org.matsim.contrib.drt.estimator.impl.distribution; + +import java.util.Random; + +public class LogNormalDistributionGenerator implements DistributionGenerator { + private final Random random; + private final double mu; + private final double sigma; + private final double minValue; + + private final double maxValue; + + public LogNormalDistributionGenerator(long seed, double mu, double sigma) { + this.random = new Random(seed); + this.mu = mu; + this.sigma = sigma; + this.minValue = 0.5; + this.maxValue = 3; + } + + public LogNormalDistributionGenerator(long seed, double mu, double sigma, double minValue, double maxValue) { + this.random = new Random(seed); + this.mu = mu; + this.sigma = sigma; + this.minValue = minValue; + this.maxValue = maxValue; + } + + @Override + public double generateRandomValue() { + if (sigma == 0) + return Math.exp(mu); + return Math.max(Math.min(Math.exp(sigma * random.nextGaussian() + mu), maxValue), minValue); + } +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/NoDistribution.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/NoDistribution.java new file mode 100644 index 00000000000..0643c45ba53 --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/NoDistribution.java @@ -0,0 +1,8 @@ +package org.matsim.contrib.drt.estimator.impl.distribution; + +public class NoDistribution implements DistributionGenerator{ + @Override + public double generateRandomValue() { + return 1.0; + } +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/NormalDistributionGenerator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/NormalDistributionGenerator.java new file mode 100644 index 00000000000..5b6a23fc31a --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/distribution/NormalDistributionGenerator.java @@ -0,0 +1,34 @@ +package org.matsim.contrib.drt.estimator.impl.distribution; + +import java.util.Random; + +public class NormalDistributionGenerator implements DistributionGenerator{ + private final Random random; + private final double std; + + private final double minValue; + + private final double maxValue; + + public NormalDistributionGenerator(long seed, double std) { + this.random = new Random(seed); + this.std = std; + this.minValue = 0.5; + this.maxValue = 3.0; + } + + public NormalDistributionGenerator(long seed, double std, double minValue, double maxValue) { + this.random = new Random(seed); + this.std = std; + this.minValue = minValue; + this.maxValue = maxValue; + } + + @Override + public double generateRandomValue() { + double randomValue = 1 + random.nextGaussian() * std; + randomValue = Math.min(maxValue, randomValue); + randomValue = Math.max(minValue, randomValue); + return randomValue; + } +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/trip_estimation/ConstantRideDurationEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/trip_estimation/ConstantRideDurationEstimator.java new file mode 100644 index 00000000000..7c431fb39ba --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/trip_estimation/ConstantRideDurationEstimator.java @@ -0,0 +1,20 @@ +package org.matsim.contrib.drt.estimator.impl.trip_estimation; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.utils.misc.OptionalTime; + +public class ConstantRideDurationEstimator implements RideDurationEstimator { + private final double alpha; + private final double beta; + + public ConstantRideDurationEstimator(double alpha, double beta) { + this.alpha = alpha; + this.beta = beta; + } + + @Override + public double getEstimatedRideDuration(Id fromLinkId, Id toLinkId, OptionalTime departureTime, double directRideDuration) { + return alpha * directRideDuration + beta; + } +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/trip_estimation/RideDurationEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/trip_estimation/RideDurationEstimator.java new file mode 100644 index 00000000000..d19a4e9fa6c --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/trip_estimation/RideDurationEstimator.java @@ -0,0 +1,11 @@ +package org.matsim.contrib.drt.estimator.impl.trip_estimation; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.utils.collections.Tuple; +import org.matsim.core.utils.misc.OptionalTime; + +public interface RideDurationEstimator { + double getEstimatedRideDuration(Id fromLinkId, Id toLinkId, OptionalTime departureTime, double directTripDuration); + +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/ConstantWaitingTimeEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/ConstantWaitingTimeEstimator.java new file mode 100644 index 00000000000..1b2d18288d5 --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/ConstantWaitingTimeEstimator.java @@ -0,0 +1,18 @@ +package org.matsim.contrib.drt.estimator.impl.waiting_time_estimation; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.utils.misc.OptionalTime; + +public class ConstantWaitingTimeEstimator implements WaitingTimeEstimator { + private final double typicalWaitingTime; + + public ConstantWaitingTimeEstimator(double typicalWaitingTime) { + this.typicalWaitingTime = typicalWaitingTime; + } + + @Override + public double estimateWaitTime(Id fromLinkId, Id toLinkId, OptionalTime departureTime) { + return typicalWaitingTime; + } +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/ShapeFileBasedWaitingTimeEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/ShapeFileBasedWaitingTimeEstimator.java new file mode 100644 index 00000000000..32bcb03c8cd --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/ShapeFileBasedWaitingTimeEstimator.java @@ -0,0 +1,63 @@ +package org.matsim.contrib.drt.estimator.impl.waiting_time_estimation; + +import org.geotools.api.feature.simple.SimpleFeature; +import org.locationtech.jts.geom.Geometry; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.utils.geometry.geotools.MGC; +import org.matsim.core.utils.misc.OptionalTime; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ShapeFileBasedWaitingTimeEstimator implements WaitingTimeEstimator { + /** + * Typical waiting time. Due to the length limit of the attribute name, we have to use some abbreviate + */ + private final static String TYPICAL_WAITING_TIME_NAME = "typ_wt"; + private final Map, Double> typicalWaitingTimeForEachLink = new HashMap<>(); + /** + * The default typical waiting time. This value will be used for links that are not covered by any + * waiting time zone. The baseTypicalWaitingTime is usually larger than the typical waiting time + * in any waiting time zone. + */ + private final double baseTypicalWaitingTime; + + public ShapeFileBasedWaitingTimeEstimator(Network network, List features) { + baseTypicalWaitingTime = 1800; + initializeWaitingTimeMap(network, features); + } + + public ShapeFileBasedWaitingTimeEstimator(Network network, List features, double baseTypicalWaitingTime) { + this.baseTypicalWaitingTime = baseTypicalWaitingTime; + initializeWaitingTimeMap(network, features); + } + + private void initializeWaitingTimeMap(Network network, List features) { + for (Link link : network.getLinks().values()) { + if (!link.getAllowedModes().contains(TransportMode.car) && !link.getAllowedModes().contains(TransportMode.drt)) { + continue; + } + double minTypicalWaitingTime = baseTypicalWaitingTime; + for (SimpleFeature feature : features) { + Geometry geometry = (Geometry) feature.getDefaultGeometry(); + if (geometry.contains(MGC.coord2Point(link.getToNode().getCoord()))) { + // The link is located within the zone -> reduce typical waiting time if necessary + double typicalWaitingTimeForCurrentZone = (long) feature.getAttribute(TYPICAL_WAITING_TIME_NAME); + if (typicalWaitingTimeForCurrentZone < minTypicalWaitingTime) { + minTypicalWaitingTime = typicalWaitingTimeForCurrentZone; + } + } + } + typicalWaitingTimeForEachLink.put(link.getId(), minTypicalWaitingTime); + } + } + + @Override + public double estimateWaitTime(Id fromLinkId, Id toLinkId, OptionalTime departureTime) { + return typicalWaitingTimeForEachLink.get(fromLinkId); + } +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/WaitingTimeEstimator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/WaitingTimeEstimator.java new file mode 100644 index 00000000000..8649cd88a2c --- /dev/null +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/estimator/impl/waiting_time_estimation/WaitingTimeEstimator.java @@ -0,0 +1,9 @@ +package org.matsim.contrib.drt.estimator.impl.waiting_time_estimation; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.utils.misc.OptionalTime; + +public interface WaitingTimeEstimator { + double estimateWaitTime(Id fromLinkId, Id toLinkId, OptionalTime departureTime); +} diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/estimator/DrtEstimateAndTeleportTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/estimator/DrtEstimateAndTeleportTest.java new file mode 100644 index 00000000000..cafd39170b3 --- /dev/null +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/estimator/DrtEstimateAndTeleportTest.java @@ -0,0 +1,59 @@ +package org.matsim.contrib.drt.estimator; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.contrib.common.zones.systems.grid.square.SquareGridZoneSystemParams; +import org.matsim.contrib.drt.estimator.impl.DirectTripBasedDrtEstimator; +import org.matsim.contrib.drt.estimator.impl.distribution.NormalDistributionGenerator; +import org.matsim.contrib.drt.estimator.impl.trip_estimation.ConstantRideDurationEstimator; +import org.matsim.contrib.drt.estimator.impl.waiting_time_estimation.ConstantWaitingTimeEstimator; +import org.matsim.contrib.drt.run.DrtConfigGroup; +import org.matsim.contrib.drt.run.DrtControlerCreator; +import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; +import org.matsim.contrib.dvrp.run.DvrpConfigGroup; +import org.matsim.contrib.zone.skims.DvrpTravelTimeMatrixParams; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controler; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vis.otfvis.OTFVisConfigGroup; + +import java.net.URL; + +public class DrtEstimateAndTeleportTest { + @RegisterExtension + public MatsimTestUtils utils = new MatsimTestUtils(); + + @Test + public void testDrtEstimateAndTeleport() { + URL configUrl = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("mielec"), "mielec_drt_config.xml"); + + DvrpConfigGroup dvrpConfig = new DvrpConfigGroup(); + DvrpTravelTimeMatrixParams matrixParams = dvrpConfig.getTravelTimeMatrixParams(); + matrixParams.addParameterSet(matrixParams.createParameterSet(SquareGridZoneSystemParams.SET_NAME)); + + Config config = ConfigUtils.loadConfig(configUrl, new MultiModeDrtConfigGroup(), dvrpConfig, + new OTFVisConfigGroup()); + DrtConfigGroup drtConfigGroup = DrtConfigGroup.getSingleModeDrtConfig(config); + drtConfigGroup.simulationType = DrtConfigGroup.SimulationType.estimateAndTeleport; + + Controler controler = DrtControlerCreator.createControler(config, false); + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + DrtEstimatorModule.bindEstimator(binder(), drtConfigGroup.mode).toInstance( + new DirectTripBasedDrtEstimator.Builder() + .setWaitingTimeEstimator(new ConstantWaitingTimeEstimator(300)) + .setWaitingTimeDistributionGenerator(new NormalDistributionGenerator(1, 0.4)) + .setRideDurationEstimator(new ConstantRideDurationEstimator(1.25, 300)) + .setRideDurationDistributionGenerator(new NormalDistributionGenerator(2, 0.3)) + .build() + ); + } + }); + controler.run(); + } +} diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/teleportation/DrtTeleportationWithModeChoiceTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/teleportation/DrtTeleportationWithModeChoiceTest.java index effd09b64ac..0e035acb518 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/teleportation/DrtTeleportationWithModeChoiceTest.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/teleportation/DrtTeleportationWithModeChoiceTest.java @@ -6,7 +6,6 @@ import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.network.Network; import org.matsim.contrib.drt.estimator.DrtEstimator; -import org.matsim.contrib.drt.estimator.impl.DetourBasedDrtEstimator; import org.matsim.contrib.drt.estimator.impl.EuclideanDistanceBasedDrtEstimator; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.run.DrtControlerCreator; @@ -72,8 +71,6 @@ void testModeChoice() { controler.addOverridingModule(new AbstractDvrpModeModule(drtConfigGroup.mode) { @Override public void install() { -// bindModal(DrtEstimator.class).toInstance(DetourBasedDrtEstimator.normalDistributed(1.2, 32, -// 0.3, 300, 0.4)); bindModal(DrtEstimator.class).toProvider(modalProvider(getter -> new EuclideanDistanceBasedDrtEstimator(getter.getModal(Network.class), 2.0, 0.1577493, 103.0972273, 120, 0.3, -0.1, 0.28))); From 1730ac8213fb52066926563386badd19b3e9e71f Mon Sep 17 00:00:00 2001 From: schlenther Date: Fri, 9 Aug 2024 11:01:06 +0200 Subject: [PATCH 048/111] NoiseAnalysis: merge damages files --- .../analysis/noise/MergeNoiseOutput.java | 76 +++++++++---------- .../analysis/noise/NoiseAnalysis.java | 3 +- .../contrib/noise/MergeNoiseCSVFile.java | 1 + .../org/matsim/contrib/noise/NoiseWriter.java | 14 ++-- 4 files changed, 42 insertions(+), 52 deletions(-) diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/noise/MergeNoiseOutput.java b/contribs/application/src/main/java/org/matsim/application/analysis/noise/MergeNoiseOutput.java index 88f8f9354e5..e59c4aee75c 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/noise/MergeNoiseOutput.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/noise/MergeNoiseOutput.java @@ -13,11 +13,14 @@ import org.apache.avro.file.DataFileWriter; import org.apache.avro.io.DatumWriter; import org.apache.avro.specific.SpecificDatumWriter; +import org.apache.commons.lang.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Coord; import org.matsim.application.avro.XYTData; +import org.matsim.core.config.Config; import org.matsim.core.utils.io.IOUtils; +import org.matsim.core.utils.misc.Time; import tech.tablesaw.api.*; import tech.tablesaw.io.csv.CsvReadOptions; @@ -29,7 +32,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.*; -import java.util.stream.Collectors; + +import static org.geotools.gml3.v3_2.GML.coordinateSystem; /** * Merges noise data from multiple files into one file. @@ -44,17 +48,14 @@ final class MergeNoiseOutput { */ private static final boolean CREATE_CSV_FILES = false; - private final String[] inputPath; private final Path outputDirectory; private final String crs; - private final String[] labels = {"immission", "emission"}; private final int minTime = 3600; private int maxTime = 24 * 3600; - MergeNoiseOutput(String[] inputPath, Path outputDirectory, String crs) { - this.inputPath = inputPath; - this.outputDirectory = outputDirectory; - this.crs = crs; + MergeNoiseOutput(Path path, String coordinateSystem ) { + this.outputDirectory = path; + this.crs = coordinateSystem; } /** @@ -90,25 +91,9 @@ public void setMaxTime(int maxTime) { * Merges noise data from multiple files into one file. */ public void run() { - - // Loop over all paths - for (int i = 0; i < labels.length; i++) { - - // Select the correct method based on the label - switch (labels[i]) { - case "immission" -> { - if (CREATE_CSV_FILES) { - mergeImmissionsCSV(inputPath[i], labels[i]); - } else { - mergeImissions(inputPath[i], labels[i]); - } - - } - case "emission" -> mergeEmissions(inputPath[i], labels[i]); - default -> log.warn("Unknown path: " + inputPath[i]); - } - - } + mergeReceiverPointData(outputDirectory + "/immissions/", "immission"); + mergeReceiverPointData(outputDirectory + "/damages_receiverPoint/", "damages_receiverPoint"); + mergeLinkData(outputDirectory.toString() + "/emissions/", "emission"); } /** @@ -129,7 +114,7 @@ private void writeAvro(XYTData xytData, File output) { } } - private void mergeEmissions(String pathParameter, String label) { + private void mergeLinkData(String pathParameter, String label) { log.info("Merging emissions data for label {}", label); Object2DoubleMap mergedData = new Object2DoubleOpenHashMap<>(); Table csvOutputMerged = Table.create(TextColumn.create("Link Id"), DoubleColumn.create("value")); @@ -165,41 +150,48 @@ private void mergeEmissions(String pathParameter, String label) { } /** - * Merges the immissions data + * Merges receiverPoint data (written by {@link org.matsim.contrib.noise.NoiseWriter} * - * @param pathParameter path to the immissions data - * @param label label for the immissions data + * @param outputDir path to the receiverPoint data + * @param label label for the receiverPoint data (which kind of data) */ - private void mergeImissions(String pathParameter, String label) { + private void mergeReceiverPointData(String outputDir, String label) { // data per time step, maps coord to value Int2ObjectMap> data = new Int2ObjectOpenHashMap<>(); // Loop over all files + //TODO could be adjusted to time bin size from noise config group for (int time = minTime; time <= maxTime; time += 3600) { - String path = pathParameter + label + "_" + round(time, 1) + ".csv"; + String timeDataFile = outputDir + label + "_" + round(time, 1) + ".csv"; + Object2FloatOpenHashMap values = new Object2FloatOpenHashMap<>(); - if (!Files.exists(Path.of(path))) { - log.warn("File {} does not exist", path); + if (!Files.exists(Path.of(timeDataFile))) { + log.warn("File {} does not exist", timeDataFile); continue; } - // Read the file - Table table = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(path)) + //we need "damages_receiverPoint" -> "Damages 01:00:00" and "immission" -> "Immision 01:00:00" + String substrToCapitalize = label.contains("_") ? label.substring(0, label.lastIndexOf("_")) : label; + String valueHeader = StringUtils.capitalize(substrToCapitalize) + " " + Time.writeTime(time, Time.TIMEFORMAT_HHMMSS); + + // Read the data file + Table dataTable = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(timeDataFile)) .columnTypesPartial(Map.of("x", ColumnType.FLOAT, "y", ColumnType.FLOAT, "Receiver Point Id", ColumnType.INTEGER, - "t", ColumnType.DOUBLE)) + "t", ColumnType.DOUBLE, + valueHeader, ColumnType.DOUBLE)) .sample(false) .separator(';').build()); - // Loop over all rows in the file - for (Row row : table) { + // Loop over all rows in the data file + for (Row row : dataTable) { float x = row.getFloat("x"); float y = row.getFloat("y"); - float value = (float) row.getDouble(1); // 1 + float value = (float) row.getDouble(valueHeader); FloatFloatPair coord = FloatFloatPair.of(x, y); values.put(coord, value); } @@ -235,7 +227,7 @@ private void mergeImissions(String pathParameter, String label) { } } - xytHourData.setData(Map.of("imissions", raw)); + xytHourData.setData(Map.of(label, raw)); xytHourData.setCrs(crs); File out = outputDirectory.getParent().resolve(label + "_per_hour.avro").toFile(); @@ -257,7 +249,7 @@ private void mergeImissions(String pathParameter, String label) { xytDayData.setTimestamps(List.of(0)); xytDayData.setXCoords(xCoords); xytDayData.setYCoords(yCoords); - xytDayData.setData(Map.of("imissions", raw)); + xytDayData.setData(Map.of(label, raw)); xytDayData.setCrs(crs); File outDay = outputDirectory.getParent().resolve(label + "_per_day.avro").toFile(); 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 02d6337de15..deceb84624e 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 @@ -144,8 +144,7 @@ public Integer call() throws Exception { ProcessNoiseImmissions process = new ProcessNoiseImmissions(outputFilePath + "/immissions/", outputFilePath + "/receiverPoints/receiverPoints.csv", noiseParameters.getReceiverPointGap()); process.run(); - final String[] paths = {outputFilePath + "/immissions/", outputFilePath + "/emissions/"}; - MergeNoiseOutput mergeNoiseOutput = new MergeNoiseOutput(paths, Path.of(outputFilePath), config.global().getCoordinateSystem()); + MergeNoiseOutput mergeNoiseOutput = new MergeNoiseOutput(Path.of(outputFilePath), config.global().getCoordinateSystem()); mergeNoiseOutput.run(); return 0; diff --git a/contribs/noise/src/main/java/org/matsim/contrib/noise/MergeNoiseCSVFile.java b/contribs/noise/src/main/java/org/matsim/contrib/noise/MergeNoiseCSVFile.java index d052f341cfe..7abae434d94 100644 --- a/contribs/noise/src/main/java/org/matsim/contrib/noise/MergeNoiseCSVFile.java +++ b/contribs/noise/src/main/java/org/matsim/contrib/noise/MergeNoiseCSVFile.java @@ -392,6 +392,7 @@ private void readReceiverPoints() { } } + //TODO this should be updated to use CSVReader or something as robust private void readValues() { for (int ll = 0; ll < this.labels.length; ll++) { diff --git a/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseWriter.java b/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseWriter.java index de465940c1a..6187e0b2f06 100644 --- a/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseWriter.java +++ b/contribs/noise/src/main/java/org/matsim/contrib/noise/NoiseWriter.java @@ -78,17 +78,17 @@ public static void writeReceiverPoints(NoiseContext noiseContext, String outputP // .addAttribute("Id", String.class) // .create(); // Collection features = new ArrayList(); -// +// // for (ReceiverPoint rp : noiseContext.getReceiverPoints().values()) { -// +// // SimpleFeature feature = factory.createPoint(MGC.coord2Coordinate(rp.getCoord()), new Object[] {rp.getId().toString()}, null); // features.add(feature); // } -// +// // String filePath = outputPath; // File file = new File(filePath); // file.mkdirs(); -// +// // log.info("Writing receiver points to shapefile... "); // ShapeFileWriter.writeGeometries(features, filePath + "receiverPoints.shp"); // log.info("Writing receiver points to shapefile... Done. "); @@ -318,13 +318,11 @@ public static void writeDamageInfoPerHour(NoiseContext noiseContext, String outp try { BufferedWriter bw = new BufferedWriter(new FileWriter(file)); - - bw.write("Receiver Point Id;Damages " + Time.writeTime(timeInterval, Time.TIMEFORMAT_HHMMSS)); + bw.write("Receiver Point Id;Damages " + Time.writeTime(timeInterval, Time.TIMEFORMAT_HHMMSS) + ";x;y;t"); bw.newLine(); for (NoiseReceiverPoint rp : noiseContext.getReceiverPoints().values()) { - - bw.write(rp.getId() + ";" + rp.getDamageCosts()); + bw.write(rp.getId() + ";" + rp.getDamageCosts() + ";" + rp.getCoord().getX() + ";" + rp.getCoord().getY() + ";" + timeInterval ); bw.newLine(); } From 6ba2578003eaed40f431e3401b88c3a98035aefc Mon Sep 17 00:00:00 2001 From: schlenther Date: Fri, 9 Aug 2024 13:11:10 +0200 Subject: [PATCH 049/111] NoiseDashboard: include stats and damage plots --- .../analysis/noise/MergeNoiseOutput.java | 11 +++- .../analysis/noise/NoiseAnalysis.java | 26 +++++++- .../simwrapper/dashboard/NoiseDashboard.java | 65 ++++++++++++++----- .../dashboard/NoiseDashboardTests.java | 7 +- 4 files changed, 89 insertions(+), 20 deletions(-) diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/noise/MergeNoiseOutput.java b/contribs/application/src/main/java/org/matsim/application/analysis/noise/MergeNoiseOutput.java index e59c4aee75c..b5b85336c1c 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/noise/MergeNoiseOutput.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/noise/MergeNoiseOutput.java @@ -53,6 +53,8 @@ final class MergeNoiseOutput { private final int minTime = 3600; private int maxTime = 24 * 3600; + private final Map totalReceiverPointValues = new HashMap<>(); + MergeNoiseOutput(Path path, String coordinateSystem ) { this.outputDirectory = path; this.crs = coordinateSystem; @@ -162,6 +164,7 @@ private void mergeReceiverPointData(String outputDir, String label) { // Loop over all files //TODO could be adjusted to time bin size from noise config group + String substrToCapitalize = null; for (int time = minTime; time <= maxTime; time += 3600) { String timeDataFile = outputDir + label + "_" + round(time, 1) + ".csv"; @@ -174,7 +177,7 @@ private void mergeReceiverPointData(String outputDir, String label) { } //we need "damages_receiverPoint" -> "Damages 01:00:00" and "immission" -> "Immision 01:00:00" - String substrToCapitalize = label.contains("_") ? label.substring(0, label.lastIndexOf("_")) : label; + substrToCapitalize = label.contains("_") ? label.substring(0, label.lastIndexOf("_")) : label; String valueHeader = StringUtils.capitalize(substrToCapitalize) + " " + Time.writeTime(time, Time.TIMEFORMAT_HHMMSS); // Read the data file @@ -255,9 +258,12 @@ private void mergeReceiverPointData(String outputDir, String label) { File outDay = outputDirectory.getParent().resolve(label + "_per_day.avro").toFile(); writeAvro(xytDayData, outDay); + //cache the overall sum + this.totalReceiverPointValues.put(substrToCapitalize, raw.stream().reduce(0f, Float::sum)); } // Merges the immissions data + @Deprecated private void mergeImmissionsCSV(String pathParameter, String label) { log.info("Merging immissions data for label {}", label); @@ -317,4 +323,7 @@ private void mergeImmissionsCSV(String pathParameter, String label) { log.info("Merged noise data written to {} ", outPerDay); } + public Map getTotalReceiverPointValues() { + return totalReceiverPointValues; + } } diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java index deceb84624e..1892de7fb74 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java @@ -1,5 +1,7 @@ package org.matsim.application.analysis.noise; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.locationtech.jts.geom.Envelope; @@ -19,9 +21,15 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.geometry.CoordinateTransformation; +import org.matsim.core.utils.io.IOUtils; import picocli.CommandLine; +import java.io.IOException; import java.nio.file.Path; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.util.Locale; +import java.util.Map; import java.util.Objects; import java.util.Set; @@ -36,7 +44,10 @@ produces = { "emission_per_day.csv", "immission_per_day.%s", - "immission_per_hour.%s" + "immission_per_hour.%s", + "damages_receiverPoint_per_hour.%s", + "damages_receiverPoint_per_day.%s", + "noise_stats.csv" } ) public class NoiseAnalysis implements MATSimAppCommand { @@ -77,7 +88,7 @@ public Integer call() throws Exception { NoiseConfigGroup noiseParameters = ConfigUtils.addOrGetModule(config, NoiseConfigGroup.class); if(overrideParameters){ - log.warn("no NoiseConfigGroup was configured before. Will set som estandards. You should check the next lines in the log file!"); + 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)); @@ -147,6 +158,17 @@ public Integer call() throws Exception { MergeNoiseOutput mergeNoiseOutput = new MergeNoiseOutput(Path.of(outputFilePath), config.global().getCoordinateSystem()); mergeNoiseOutput.run(); + // Total stats + DecimalFormat df = new DecimalFormat("#.###", DecimalFormatSymbols.getInstance(Locale.US)); + try (CSVPrinter printer = new CSVPrinter(IOUtils.getBufferedWriter(output.getPath("noise_stats.csv").toString()), CSVFormat.DEFAULT)) { + printer.printRecord("Annual cost rate per pop. unit [€]:", df.format(noiseParameters.getAnnualCostRate())); + for (Map.Entry labelValueEntry : mergeNoiseOutput.getTotalReceiverPointValues().entrySet()) { + printer.printRecord("Total " + labelValueEntry.getKey() + " at receiver points", df.format(labelValueEntry.getValue())); + } + } catch (IOException ex) { + log.error(ex); + } + return 0; } diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java index 036b3c5a718..48f173a8adb 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java @@ -1,6 +1,7 @@ package org.matsim.simwrapper.dashboard; import org.matsim.application.analysis.noise.NoiseAnalysis; +import org.matsim.application.analysis.population.StuckAgentAnalysis; import org.matsim.application.prepare.network.CreateAvroNetwork; import org.matsim.simwrapper.Dashboard; import org.matsim.simwrapper.Header; @@ -8,6 +9,7 @@ import org.matsim.simwrapper.viz.ColorScheme; import org.matsim.simwrapper.viz.GridMap; import org.matsim.simwrapper.viz.MapPlot; +import org.matsim.simwrapper.viz.Tile; /** * Shows emission in the scenario. @@ -32,19 +34,12 @@ public void configure(Header header, Layout layout) { header.title = "Noise"; header.description = "Shows the noise footprint and spatial distribution."; - layout.row("aggregate noise") - .el(GridMap.class, (viz, data) -> { - viz.title = "Noise Immissions (Grid)"; - viz.description = "Total Noise Immissions per day"; - viz.height = 12.0; - viz.cellSize = 250; - viz.opacity = 0.2; - viz.maxHeight = 20; - viz.center = data.context().getCenter(); - viz.zoom = data.context().mapZoomLevel; - viz.setColorRamp(new double[]{30, 40, 50, 60, 70}, new String[]{"#1175b3", "#95c7df", "#dfdb95", "#dfb095", "#f4a986", "#cc0c27"}); - viz.file = data.computeWithPlaceholder(NoiseAnalysis.class, "immission_per_day.%s", "avro"); - }) + layout.row("stats") + .el(Tile.class, (viz, data) -> { + viz.dataset = data.compute(NoiseAnalysis.class, "noise_stats.csv"); + viz.height = 0.1; + }); + layout.row("emissions") .el(MapPlot.class, (viz, data) -> { viz.title = "Noise Emissions (Link)"; viz.description = "Maximum Noise Level per day [dB]"; @@ -65,18 +60,56 @@ public void configure(Header header, Layout layout) { viz.display.lineWidth.scaleFactor = 8d; viz.display.lineWidth.join = "Link Id"; }); - layout.row("hourly noise") + layout.row("imissions") + .el(GridMap.class, (viz, data) -> { + viz.title = "Noise Immissions (Grid)"; + viz.description = "Total Noise Immissions per day"; + viz.height = 12.0; + viz.cellSize = 250; + viz.opacity = 0.1; + viz.maxHeight = 40; + viz.center = data.context().getCenter(); + viz.zoom = data.context().mapZoomLevel; + viz.setColorRamp(new double[]{30, 40, 50, 60, 70}, new String[]{"#1175b3", "#95c7df", "#dfdb95", "#dfb095", "#f4a986", "#cc0c27"}); + viz.file = data.computeWithPlaceholder(NoiseAnalysis.class, "immission_per_day.%s", "avro"); + }) .el(GridMap.class, (viz, data) -> { viz.title = "Hourly Noise Immissions (Grid)"; viz.description = "Noise Immissions per hour"; viz.height = 12.0; viz.cellSize = 250; - viz.opacity = 0.2; - viz.maxHeight = 20; + viz.opacity = 0.1; + viz.maxHeight = 40; viz.center = data.context().getCenter(); viz.zoom = data.context().mapZoomLevel; viz.setColorRamp(new double[]{30, 40, 50, 60, 70}, new String[]{"#1175b3", "#95c7df", "#dfdb95", "#dfb095", "#f4a986", "#cc0c27"}); viz.file = data.computeWithPlaceholder(NoiseAnalysis.class, "immission_per_hour.%s", "avro"); }); + layout.row("damages") + .el(GridMap.class, (viz, data) -> { + viz.title = "Daily Noise Damages (Grid)"; + viz.description = "Total Noise Damages per day [€]"; + viz.height = 12.0; + viz.cellSize = 250; + viz.opacity = 0.1; + viz.maxHeight = 40; + viz.center = data.context().getCenter(); + viz.zoom = data.context().mapZoomLevel; + viz.setColorRamp(ColorScheme.Oranges); + viz.file = data.computeWithPlaceholder(NoiseAnalysis.class, "damages_receiverPoint_per_day.%s", "avro"); + }) + .el(GridMap.class, (viz, data) -> { + viz.title = "Hourly Noise Damages (Grid)"; + viz.description = "Noise Damages per hour [€]"; + viz.height = 12.0; + viz.cellSize = 250; + viz.opacity = 0.2; + viz.maxHeight = 40; + viz.center = data.context().getCenter(); + viz.zoom = data.context().mapZoomLevel; +// viz.setColorRamp(new double[]{30, 40, 50, 60, 70}, new String[]{"#1175b3", "#95c7df", "#dfdb95", "#dfb095", "#f4a986", "#cc0c27"}); + viz.setColorRamp(ColorScheme.Oranges); + viz.file = data.computeWithPlaceholder(NoiseAnalysis.class, "damages_receiverPoint_per_hour.%s", "avro"); + }); } } diff --git a/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/NoiseDashboardTests.java b/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/NoiseDashboardTests.java index 6ca2a08cee3..fdc846cdff5 100644 --- a/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/NoiseDashboardTests.java +++ b/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/NoiseDashboardTests.java @@ -46,6 +46,11 @@ void generate() { Assertions.assertThat(out) .isDirectoryContaining("glob:**emission_per_day.csv") .isDirectoryContaining("glob:**immission_per_day.avro") - .isDirectoryContaining("glob:**immission_per_hour.avro"); + .isDirectoryContaining("glob:**immission_per_hour.avro") + .isDirectoryContaining("glob:**damages_receiverPoint_per_hour.avro") + .isDirectoryContaining("glob:**damages_receiverPoint_per_day.avro") + .isDirectoryContaining("glob:**noise_stats.csv"); + + //TODO check content / values of the files } } From cda5767f20627d1e8f8283cb1cb542c6be8c36d8 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Fri, 9 Aug 2024 13:34:12 +0200 Subject: [PATCH 050/111] only perform net consistency check once --- .../org/matsim/core/router/NetworkRoutingProvider.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java index a6c00d06942..7b874593fa1 100644 --- a/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java +++ b/matsim/src/main/java/org/matsim/core/router/NetworkRoutingProvider.java @@ -46,6 +46,7 @@ public class NetworkRoutingProvider implements Provider{ private static final Logger log = LogManager.getLogger( NetworkRoutingProvider.class ) ; private final String routingMode; + private boolean alreadyCheckedConsistency = false; @Inject Map travelTimes; @Inject Map travelDisutilityFactories; @@ -142,6 +143,12 @@ private void checkNetwork(Network filteredNetwork) { return; } + if(alreadyCheckedConsistency){ + return; + } + + log.info("Checking network for mode '{}' for consistency...", mode); + int nLinks = filteredNetwork.getLinks().size(); int nNodes = filteredNetwork.getNodes().size(); new NetworkCleaner().run(filteredNetwork); @@ -153,5 +160,7 @@ private void checkNetwork(Network filteredNetwork) { "\n If this network topology is intended, set the routing config parameter 'networkRouteConsistencyCheck' to 'disable'."); throw new RuntimeException(errorMessage); } + + alreadyCheckedConsistency = true; } } From e2f7c360eda279ed4a0b07ec3298b5bb910413af Mon Sep 17 00:00:00 2001 From: schlenther Date: Fri, 9 Aug 2024 14:18:15 +0200 Subject: [PATCH 051/111] CreateSingleSimWrapperDashboard --- .../CreateSingleSimWrapperDashboard.java | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 contribs/simwrapper/src/main/java/org/matsim/simwrapper/CreateSingleSimWrapperDashboard.java diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/CreateSingleSimWrapperDashboard.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/CreateSingleSimWrapperDashboard.java new file mode 100644 index 00000000000..fce848736a6 --- /dev/null +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/CreateSingleSimWrapperDashboard.java @@ -0,0 +1,148 @@ +/* *********************************************************************** * + * project: org.matsim.* + * Controler.java + * * + * *********************************************************************** * + * * + * copyright : (C) 2007 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ + +package org.matsim.simwrapper; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.application.ApplicationUtils; +import org.matsim.application.MATSimAppCommand; +import org.matsim.application.options.ShpOptions; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.simwrapper.dashboard.*; +import picocli.CommandLine; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; + +@CommandLine.Command( + name = "dashboard", + description = "Run analysis and create SimWrapper dashboard for existing run output." +) + +/** + * This class creates single SimWrapper dashboards for multiple output directories. It is meant to be run as a post-process, + * e.g. when a specific dashboard was missing after the initial run (for whatever reason). + * It will create the dashboard with all standard settings. + * Depending on the dashboard type, it might be required to provide ShpOptions for data filtering. + * TODO: test whether this works for the non-noise DashboardTypes. + */ +final class CreateSingleSimWrapperDashboard implements MATSimAppCommand { + + private static final Logger log = LogManager.getLogger(CreateSingleSimWrapperDashboard.class); + + @CommandLine.Option(names = "--type", required = true, description = "Provide the dashboard type to be generated. See DashboardType enum within this class.") + private DashboardType dashboardType; + + @CommandLine.Parameters(arity = "1..*", description = "Path to run output directories for which the dashboards is to be generated.") + private List inputPaths; + + @CommandLine.Mixin + private final ShpOptions shp = new ShpOptions(); + + enum DashboardType{ + noise, + emissions, + traffic, + overview, + stuckAgent, + populationAttribute, + ODTrip, + trip, + publicTransit + } + + private CreateSingleSimWrapperDashboard(){ + } + + @Override + public Integer call() throws Exception { + + for (Path runDirectory : inputPaths) { + log.info("Creating " + dashboardType + " for {}", runDirectory); + + Path configPath = ApplicationUtils.matchInput("config.xml", runDirectory); + Config config = ConfigUtils.loadConfig(configPath.toString()); + SimWrapper sw = SimWrapper.create(config); + + SimWrapperConfigGroup simwrapperCfg = ConfigUtils.addOrGetModule(config, SimWrapperConfigGroup.class); + + if (shp.isDefined()){ + //not sure if this is the best way to go, might be that the shape file would be automatically read by providing the --shp command line option + simwrapperCfg.defaultParams().shp = shp.getShapeFile().toString(); + } + + //skip default dashboards + simwrapperCfg.defaultDashboards = SimWrapperConfigGroup.Mode.disabled; + + //add dashboard + switch (dashboardType) { + case noise -> { + sw.addDashboard(new NoiseDashboard()); + } + case emissions -> { + sw.addDashboard(new EmissionsDashboard()); + } + case traffic -> { + sw.addDashboard(new TrafficDashboard()); + } + case overview -> { + sw.addDashboard(new OverviewDashboard()); + } + case stuckAgent -> { + sw.addDashboard(new StuckAgentDashboard()); + } + case populationAttribute -> { + sw.addDashboard(new PopulationAttributeDashboard()); + } + case ODTrip -> { + throw new RuntimeException("ODTripDashboard needs additional information. Single creation is currently not implemented"); +// sw.addDashboard(new ODTripDashboard()); + } + case trip -> { + sw.addDashboard(new TripDashboard()); + } + case publicTransit -> { + sw.addDashboard(new PublicTransitDashboard()); + } + default -> throw new IllegalArgumentException("unkown dashboard type: " + dashboardType); + } + + try { + //append dashboard to existing ones + boolean append = true; + sw.generate(runDirectory, append); + sw.run(runDirectory); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + return 0; + } + + public static void main(String[] args) { + new CreateSingleSimWrapperDashboard().execute(args); + } + +} + From 9175ec805299815d0d8797c57de367e908aa31eb Mon Sep 17 00:00:00 2001 From: schlenther Date: Fri, 9 Aug 2024 14:40:02 +0200 Subject: [PATCH 052/111] fix noise tests: explicitly set activity types for rp grid, when setting act type for damage calculation --- .../org/matsim/contrib/noise/NoiseIT.java | 4 ++ .../noise/NoiseConfigGroupTest/config1.xml | 47 ++++++++++--------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/contribs/noise/src/test/java/org/matsim/contrib/noise/NoiseIT.java b/contribs/noise/src/test/java/org/matsim/contrib/noise/NoiseIT.java index e8aa97a3ab3..542580dcb44 100644 --- a/contribs/noise/src/test/java/org/matsim/contrib/noise/NoiseIT.java +++ b/contribs/noise/src/test/java/org/matsim/contrib/noise/NoiseIT.java @@ -93,6 +93,7 @@ final void test1(){ String[] consideredActivities = {"home", "work"}; noiseParameters.setConsideredActivitiesForDamageCalculationArray(consideredActivities); + noiseParameters.setConsideredActivitiesForReceiverPointGridArray(consideredActivities); com.google.inject.Injector injector = Injector.createInjector( scenario.getConfig() , new AbstractModule(){ @Override public void install(){ @@ -197,6 +198,7 @@ private static void runTest2a( Config runConfig ) { String[] consideredActivities = {"home", "work"}; noiseParameters.setConsideredActivitiesForDamageCalculationArray(consideredActivities); + noiseParameters.setConsideredActivitiesForReceiverPointGridArray(consideredActivities); noiseParameters.setScaleFactor(1.); noiseParameters.setUseActualSpeedLevel(false); @@ -984,6 +986,7 @@ final void test2b(){ String[] consideredActivities = {"home", "work"}; noiseParameters.setConsideredActivitiesForDamageCalculationArray(consideredActivities); + noiseParameters.setConsideredActivitiesForReceiverPointGridArray(consideredActivities); noiseParameters.setScaleFactor(1.); noiseParameters.setNoiseAllocationApproach(NoiseConfigGroup.NoiseAllocationApproach.MarginalCost); @@ -1073,6 +1076,7 @@ final void test2c(){ String[] consideredActivities = {"home", "work"}; noiseParameters.setConsideredActivitiesForDamageCalculationArray(consideredActivities); + noiseParameters.setConsideredActivitiesForReceiverPointGridArray(consideredActivities); noiseParameters.setScaleFactor(1.); noiseParameters.setUseActualSpeedLevel(true); diff --git a/contribs/noise/test/input/org/matsim/contrib/noise/NoiseConfigGroupTest/config1.xml b/contribs/noise/test/input/org/matsim/contrib/noise/NoiseConfigGroupTest/config1.xml index e2d42df47cf..f4830014284 100644 --- a/contribs/noise/test/input/org/matsim/contrib/noise/NoiseConfigGroupTest/config1.xml +++ b/contribs/noise/test/input/org/matsim/contrib/noise/NoiseConfigGroupTest/config1.xml @@ -1,24 +1,25 @@ - + - + + - + - + - + @@ -34,20 +35,20 @@ - - + + - + - + - + - + @@ -66,26 +67,26 @@ - + - + - + - + - + - + @@ -171,20 +172,20 @@ - + - + - + - + - + @@ -199,5 +200,5 @@ - + From 61c65bf0f76f2edd8fab837a47e71d43adf233af Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Fri, 9 Aug 2024 17:43:49 +0200 Subject: [PATCH 053/111] add simple way of rejecting request insertion offers by the customer --- .../DefaultUnplannedRequestInserter.java | 61 +++++++++++-------- .../drt/run/examples/RunDrtExampleIT.java | 54 ++++++++++++++++ 2 files changed, 89 insertions(+), 26 deletions(-) diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/DefaultUnplannedRequestInserter.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/DefaultUnplannedRequestInserter.java index 0f8443f0141..1854e93ffd1 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/DefaultUnplannedRequestInserter.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/optimizer/insertion/DefaultUnplannedRequestInserter.java @@ -54,6 +54,7 @@ public class DefaultUnplannedRequestInserter implements UnplannedRequestInserter { private static final Logger log = LogManager.getLogger(DefaultUnplannedRequestInserter.class); public static final String NO_INSERTION_FOUND_CAUSE = "no_insertion_found"; + public static final String OFFER_REJECTED_CAUSE = "offer_rejected"; private final String mode; private final Fleet fleet; @@ -125,17 +126,7 @@ private void scheduleUnplannedRequest(DrtRequest req, Map, Vehic Optional best = insertionSearch.findBestInsertion(req, Collections.unmodifiableCollection(vehicleEntries.values())); if (best.isEmpty()) { - if (!insertionRetryQueue.tryAddFailedRequest(req, now)) { - eventsManager.processEvent( - new PassengerRequestRejectedEvent(now, mode, req.getId(), req.getPassengerIds(), - NO_INSERTION_FOUND_CAUSE)); - log.debug("No insertion found for drt request " - + req - + " with passenger ids=" - + req.getPassengerIds().stream().map(Object::toString).collect(Collectors.joining(",")) - + " fromLinkId=" - + req.getFromLink().getId()); - } + retryOrReject(req, now, NO_INSERTION_FOUND_CAUSE); } else { InsertionWithDetourData insertion = best.get(); @@ -144,26 +135,44 @@ private void scheduleUnplannedRequest(DrtRequest req, Map, Vehic insertion.detourTimeInfo.pickupDetourInfo.departureTime, insertion.detourTimeInfo.dropoffDetourInfo.arrivalTime); - var vehicle = insertion.insertion.vehicleEntry.vehicle; - var pickupDropoffTaskPair = insertionScheduler.scheduleRequest(acceptedRequest.get(), insertion); + if(acceptedRequest.isPresent()) { + var vehicle = insertion.insertion.vehicleEntry.vehicle; + var pickupDropoffTaskPair = insertionScheduler.scheduleRequest(acceptedRequest.get(), insertion); - VehicleEntry newVehicleEntry = vehicleEntryFactory.create(vehicle, now); - if (newVehicleEntry != null) { - vehicleEntries.put(vehicle.getId(), newVehicleEntry); - } else { - vehicleEntries.remove(vehicle.getId()); - } + VehicleEntry newVehicleEntry = vehicleEntryFactory.create(vehicle, now); + if (newVehicleEntry != null) { + vehicleEntries.put(vehicle.getId(), newVehicleEntry); + } else { + vehicleEntries.remove(vehicle.getId()); + } + + double expectedPickupTime = pickupDropoffTaskPair.pickupTask.getBeginTime(); + expectedPickupTime = Math.max(expectedPickupTime, acceptedRequest.get().getEarliestStartTime()); + expectedPickupTime += stopDurationProvider.calcPickupDuration(vehicle, req); - double expectedPickupTime = pickupDropoffTaskPair.pickupTask.getBeginTime(); - expectedPickupTime = Math.max(expectedPickupTime, acceptedRequest.get().getEarliestStartTime()); - expectedPickupTime += stopDurationProvider.calcPickupDuration(vehicle, req); + double expectedDropoffTime = pickupDropoffTaskPair.dropoffTask.getBeginTime(); + expectedDropoffTime += stopDurationProvider.calcDropoffDuration(vehicle, req); - double expectedDropoffTime = pickupDropoffTaskPair.dropoffTask.getBeginTime(); - expectedDropoffTime += stopDurationProvider.calcDropoffDuration(vehicle, req); + eventsManager.processEvent( + new PassengerRequestScheduledEvent(now, mode, req.getId(), req.getPassengerIds(), vehicle.getId(), + expectedPickupTime, expectedDropoffTime)); + } else { + retryOrReject(req, now, OFFER_REJECTED_CAUSE); + } + } + } + private void retryOrReject(DrtRequest req, double now, String cause) { + if (!insertionRetryQueue.tryAddFailedRequest(req, now)) { eventsManager.processEvent( - new PassengerRequestScheduledEvent(now, mode, req.getId(), req.getPassengerIds(), vehicle.getId(), - expectedPickupTime, expectedDropoffTime)); + new PassengerRequestRejectedEvent(now, mode, req.getId(), req.getPassengerIds(), + cause)); + log.debug("No insertion found for drt request " + + req + + " with passenger ids=" + + req.getPassengerIds().stream().map(Object::toString).collect(Collectors.joining(",")) + + " fromLinkId=" + + req.getFromLink().getId()); } } } diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java index 0b2adb16db2..50c7440b957 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java @@ -29,6 +29,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -37,6 +38,10 @@ import org.matsim.contrib.drt.optimizer.DrtRequestInsertionRetryParams; import org.matsim.contrib.drt.optimizer.insertion.repeatedselective.RepeatedSelectiveInsertionSearchParams; import org.matsim.contrib.drt.optimizer.insertion.selective.SelectiveInsertionSearchParams; +import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; +import org.matsim.contrib.drt.passenger.DefaultOfferAcceptor; +import org.matsim.contrib.drt.passenger.DrtOfferAcceptor; +import org.matsim.contrib.drt.passenger.DrtRequest; import org.matsim.contrib.drt.prebooking.PrebookingParams; import org.matsim.contrib.drt.prebooking.logic.ProbabilityBasedPrebookingLogic; import org.matsim.contrib.drt.run.DrtConfigGroup; @@ -53,6 +58,7 @@ import org.matsim.contrib.dvrp.passenger.PassengerRequestScheduledEvent; import org.matsim.contrib.dvrp.passenger.PassengerRequestScheduledEventHandler; import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; +import org.matsim.contrib.dvrp.run.AbstractDvrpModeQSimModule; import org.matsim.contrib.dvrp.run.DvrpConfigGroup; import org.matsim.contrib.zone.skims.DvrpTravelTimeMatrixParams; import org.matsim.core.config.Config; @@ -60,6 +66,7 @@ import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.gbl.MatsimRandom; import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; @@ -392,6 +399,39 @@ void testRunDrtWithPrebooking() { verifyDrtCustomerStatsCloseToExpectedStats(utils.getOutputDirectory(), expectedStats); } + + @Test + void testRunDrtOfferRejectionExample() { + Id.resetCaches(); + URL configUrl = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("mielec"), + "mielec_stop_based_drt_config.xml"); + Config config = ConfigUtils.loadConfig(configUrl, new MultiModeDrtConfigGroup(), new DvrpConfigGroup(), + new OTFVisConfigGroup()); + + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + + Controler controller = DrtControlerCreator.createControler(config, false); + controller.addOverridingQSimModule(new AbstractDvrpModeQSimModule("drt") { + @Override + protected void configureQSim() { + bindModal(DrtOfferAcceptor.class).toProvider(modalProvider(getter -> new ProbabilisticOfferAcceptor())); + } + }); + controller.run(); + + + var expectedStats = Stats.newBuilder() + .rejectionRate(0.1) + .rejections(190) + .waitAverage(217.01) + .inVehicleTravelTimeMean(362.57) + .totalTravelTimeMean(579.58) + .build(); + + verifyDrtCustomerStatsCloseToExpectedStats(utils.getOutputDirectory(), expectedStats); + } + /** * Early warning system: if customer stats vary more than the defined percentage above or below the expected values * then the following unit tests will fail. This is meant to serve as a red flag. @@ -536,4 +576,18 @@ public void install() { }); } } + + private static class ProbabilisticOfferAcceptor implements DrtOfferAcceptor { + + private final DefaultOfferAcceptor delegate = new DefaultOfferAcceptor(); + + @Override + public Optional acceptDrtOffer(DrtRequest request, double departureTime, double arrivalTime) { + if (MatsimRandom.getLocalInstance().nextBoolean()) { + return Optional.empty(); + } else { + return delegate.acceptDrtOffer(request, departureTime, arrivalTime); + } + } + } } From 954d5528bb04d78a31d6110ab8ab7e64fd6f4da8 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Fri, 9 Aug 2024 17:59:43 +0200 Subject: [PATCH 054/111] update test --- .../drt/run/examples/RunDrtExampleIT.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java index 50c7440b957..7b62adcace0 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java @@ -26,10 +26,7 @@ import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.stream.Collectors; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -422,11 +419,11 @@ protected void configureQSim() { var expectedStats = Stats.newBuilder() - .rejectionRate(0.1) - .rejections(190) - .waitAverage(217.01) - .inVehicleTravelTimeMean(362.57) - .totalTravelTimeMean(579.58) + .rejectionRate(0.46) + .rejections(174.0) + .waitAverage(222.66) + .inVehicleTravelTimeMean(369.74) + .totalTravelTimeMean(592.4) .build(); verifyDrtCustomerStatsCloseToExpectedStats(utils.getOutputDirectory(), expectedStats); @@ -581,9 +578,11 @@ private static class ProbabilisticOfferAcceptor implements DrtOfferAcceptor { private final DefaultOfferAcceptor delegate = new DefaultOfferAcceptor(); + private final Random random = new Random(123); + @Override public Optional acceptDrtOffer(DrtRequest request, double departureTime, double arrivalTime) { - if (MatsimRandom.getLocalInstance().nextBoolean()) { + if (random.nextBoolean()) { return Optional.empty(); } else { return delegate.acceptDrtOffer(request, departureTime, arrivalTime); From c316aa5af2af5dd7eadd77ab3d5e320e8b059eec Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Sun, 11 Aug 2024 22:17:07 +0200 Subject: [PATCH 055/111] fix nasty insertion scheduler bug --- .../drt/scheduler/DefaultRequestInsertionScheduler.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java index 8b3755ba082..72082906255 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java @@ -128,8 +128,7 @@ private void verifyConstraints(InsertionWithDetourData insertion) { Schedule schedule = insertion.insertion.vehicleEntry.vehicle.getSchedule(); for (Task task : schedule.getTasks()) { - if (task instanceof DrtStopTask) { - DrtStopTask stopTask = (DrtStopTask) task; + if (task instanceof DrtStopTask stopTask) { for (AcceptedDrtRequest request : stopTask.getPickupRequests().values()) { Verify.verify(stopTask.getEndTime() <= request.getLatestStartTime()); @@ -211,12 +210,16 @@ private DrtStopTask insertPickup(AcceptedDrtRequest request, InsertionWithDetour beforePickupTask = insertWait(vehicleEntry.vehicle, currentTask, dropoffIdx); } } + if(!stops.isEmpty() && stops.size() + 1 > pickupIdx) { + //there is an existing stop which was scheduled earlier and was not the destination of the already diverted drive task + removeBetween(schedule, beforePickupTask, stops.get(pickupIdx).task); + } } else { // insert pickup after an existing stop/stay task StayTask stayTask = null; DrtStopTask stopTask = null; if (pickupIdx == 0) { if (scheduleStatus == ScheduleStatus.PLANNED) {// PLANNED schedule - stayTask = (StayTask)schedule.getTasks().get(0); + stayTask = (StayTask)schedule.getTasks().getFirst(); stayTask.setEndTime(stayTask.getBeginTime());// could get later removed with ScheduleTimingUpdater } else if (STAY.isBaseTypeOf(currentTask)) { stayTask = (StayTask)currentTask; // ongoing stay task From 940cad870b4c150068e35167de39ca3c96611267 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2024 08:53:07 +0000 Subject: [PATCH 056/111] Bump org.hamcrest:hamcrest from 2.2 to 3.0 Bumps [org.hamcrest:hamcrest](https://github.com/hamcrest/JavaHamcrest) from 2.2 to 3.0. - [Release notes](https://github.com/hamcrest/JavaHamcrest/releases) - [Changelog](https://github.com/hamcrest/JavaHamcrest/blob/master/CHANGES.md) - [Commits](https://github.com/hamcrest/JavaHamcrest/compare/v2.2...v3.0) --- updated-dependencies: - dependency-name: org.hamcrest:hamcrest dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a049d60560f..be4f98f1127 100644 --- a/pom.xml +++ b/pom.xml @@ -333,7 +333,7 @@ org.hamcrest hamcrest - 2.2 + 3.0 test From 3599e4b45b4bf9e531927dd37327079570b4be29 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2024 09:54:35 +0000 Subject: [PATCH 057/111] Bump org.openjfx:javafx-graphics from 22.0.1 to 22.0.2 Bumps org.openjfx:javafx-graphics from 22.0.1 to 22.0.2. --- updated-dependencies: - dependency-name: org.openjfx:javafx-graphics dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- contribs/vsp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribs/vsp/pom.xml b/contribs/vsp/pom.xml index b2bf9fb3a41..8f4e01bec37 100644 --- a/contribs/vsp/pom.xml +++ b/contribs/vsp/pom.xml @@ -184,7 +184,7 @@ org.openjfx javafx-graphics - 22.0.1 + 22.0.2 com.graphhopper From de00c66b030127d1223bc170a029ec106f408063 Mon Sep 17 00:00:00 2001 From: Chengqi Lu <43133404+luchengqi7@users.noreply.github.com> Date: Tue, 13 Aug 2024 18:36:48 +0200 Subject: [PATCH 058/111] Accept optional OD pairs in route validation (#3409) * add option for existing input od file * Update SampleValidationRoutes.java --------- Co-authored-by: rakow --- .../traveltime/SampleValidationRoutes.java | 73 +++++++++++++++++-- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/traffic/traveltime/SampleValidationRoutes.java b/contribs/application/src/main/java/org/matsim/application/analysis/traffic/traveltime/SampleValidationRoutes.java index 0e6c0f2af59..aa3a1fc4ba0 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/traffic/traveltime/SampleValidationRoutes.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/traffic/traveltime/SampleValidationRoutes.java @@ -19,10 +19,7 @@ import org.matsim.api.core.v01.network.Node; import org.matsim.application.CommandSpec; import org.matsim.application.MATSimAppCommand; -import org.matsim.application.options.CrsOptions; -import org.matsim.application.options.InputOptions; -import org.matsim.application.options.OutputOptions; -import org.matsim.application.options.ShpOptions; +import org.matsim.application.options.*; import org.matsim.application.prepare.network.SampleNetwork; import org.matsim.core.network.NetworkUtils; import org.matsim.core.router.costcalculators.OnlyTimeDependentTravelDisutility; @@ -32,9 +29,11 @@ import org.matsim.core.trafficmonitoring.FreeSpeedTravelTime; import org.matsim.core.utils.geometry.CoordUtils; import org.matsim.core.utils.geometry.transformations.GeotoolsTransformation; +import org.matsim.core.utils.io.IOUtils; import picocli.CommandLine; import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; @@ -86,6 +85,8 @@ public class SampleValidationRoutes implements MATSimAppCommand { @CommandLine.Option(names = "--mode", description = "Mode to validate", defaultValue = TransportMode.car) private String mode; + @CommandLine.Option(names = "--input-od", description = "Use input fromNode,toNode instead of sampling", required = false) + private String inputOD; public static void main(String[] args) { new SampleValidationRoutes().execute(args); @@ -142,9 +143,15 @@ public Integer call() throws Exception { OnlyTimeDependentTravelDisutility util = new OnlyTimeDependentTravelDisutility(tt); LeastCostPathCalculator router = new SpeedyALTFactory().createPathCalculator(network, util, tt); - List routes = sampleRoutes(network, router, rnd); - log.info("Sampled {} routes in range {}", routes.size(), distRange); + List routes; + if (inputOD != null) { + log.info("Using input OD file {}", inputOD); + routes = queryRoutes(network, router); + } else { + routes = sampleRoutes(network, router, rnd); + log.info("Sampled {} routes in range {}", routes.size(), distRange); + } try (CSVPrinter csv = new CSVPrinter(Files.newBufferedWriter(output.getPath()), CSVFormat.DEFAULT)) { csv.printRecord("from_node", "to_node", "beeline_dist", "dist", "travel_time", "geometry"); @@ -228,6 +235,7 @@ private List sampleRoutes(Network network, LeastCostPathCalculator router ShpOptions.Index index = shp.isDefined() ? shp.createIndex(crs, "_") : null; Predicate exclude = excludeRoads != null && !excludeRoads.isBlank() ? new Predicate<>() { final Pattern p = Pattern.compile(excludeRoads, Pattern.CASE_INSENSITIVE); + @Override public boolean test(Link link) { return p.matcher(NetworkUtils.getHighwayType(link)).find(); @@ -282,6 +290,59 @@ public boolean test(Link link) { return result; } + /** + * Use given od pairs as input for validation. + */ + private List queryRoutes(Network network, LeastCostPathCalculator router) { + + List result = new ArrayList<>(); + String crs = ProjectionUtils.getCRS(network); + + if (this.crs.getInputCRS() != null) + crs = this.crs.getInputCRS(); + + if (crs == null) { + throw new IllegalArgumentException("Input CRS could not be detected. Please specify with --input-crs [EPSG:xxx]"); + } + + GeotoolsTransformation ct = new GeotoolsTransformation(crs, "EPSG:4326"); + + try (CSVParser parser = CSVParser.parse(IOUtils.getBufferedReader(inputOD), CSVFormat.DEFAULT.builder().setHeader().setSkipHeaderRecord(true). + setDelimiter(CsvOptions.detectDelimiter(inputOD)).build())) { + + List header = parser.getHeaderNames(); + if (!header.contains("from_node")) + throw new IllegalArgumentException("Missing 'from_node' column in input file"); + if (!header.contains("to_node")) + throw new IllegalArgumentException("Missing 'to_node' column in input file"); + + for (CSVRecord r : parser) { + Node fromNode = network.getNodes().get(Id.createNodeId(r.get("from_node"))); + Node toNode = network.getNodes().get(Id.createNodeId(r.get("to_node"))); + + if (fromNode == null) + throw new IllegalArgumentException("Node " + r.get("from_node") + " not found"); + if (toNode == null) + throw new IllegalArgumentException("Node " + r.get("to_node") + " not found"); + + LeastCostPathCalculator.Path path = router.calcLeastCostPath(fromNode, toNode, 0, null, null); + result.add(new Route( + fromNode.getId(), + toNode.getId(), + ct.transform(fromNode.getCoord()), + ct.transform(toNode.getCoord()), + path.travelTime, + path.links.stream().mapToDouble(Link::getLength).sum() + )); + } + + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + return result; + } + /** * Key as pair of from and to node. */ From 4dbce8e468fee032e2311fc1ee3245a76bd5a8b7 Mon Sep 17 00:00:00 2001 From: vsp-gleich Date: Thu, 15 Aug 2024 18:59:26 +0200 Subject: [PATCH 059/111] add ride scoring parametrization based on car (#3410) --- .../RideScoringParamsFromCarParams.java | 37 +++++++++++++++++++ .../RideScoringParamsFromCarParamsTest.java | 34 +++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 contribs/vsp/src/main/java/org/matsim/contrib/vsp/scoring/RideScoringParamsFromCarParams.java create mode 100644 contribs/vsp/src/test/java/org/matsim/contrib/vsp/scoring/RideScoringParamsFromCarParamsTest.java diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/scoring/RideScoringParamsFromCarParams.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/scoring/RideScoringParamsFromCarParams.java new file mode 100644 index 00000000000..2286692e4d6 --- /dev/null +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/scoring/RideScoringParamsFromCarParams.java @@ -0,0 +1,37 @@ +package org.matsim.contrib.vsp.scoring; + +import org.matsim.api.core.v01.TransportMode; +import org.matsim.core.config.groups.ScoringConfigGroup; + +public class RideScoringParamsFromCarParams { + + /** + * Sets ride scoring params based on car scoring params (including prices). This assumes that the ride passenger somehow has + * to compensate the driver for the additional driving effort to provide the ride. + * + * @param scoringConfigGroup config.scoring() + * @param alpha represents the share of an average ride trip that the car driver has to drive additionally to the car + * trip to provide the ride. Typical values are between 1 (i.e. driver drives additional 10km to provide a 10 km + * ride) and 2 (i.e. driver drives additional 20km to provide a 10 km ride). Alpha can be calibrated and must + * be alpha >= 0. + */ + public static void setRideScoringParamsBasedOnCarParams (ScoringConfigGroup scoringConfigGroup, double alpha) { + ScoringConfigGroup.ModeParams carParams = scoringConfigGroup.getOrCreateModeParams(TransportMode.car); + ScoringConfigGroup.ModeParams rideParams = scoringConfigGroup.getOrCreateModeParams(TransportMode.ride); + + // constant is a calibration parameter and should not be changed + + // ride has no fixed cost + rideParams.setDailyMonetaryConstant(0.0); + + // account for the driver's monetary distance rate. + rideParams.setMonetaryDistanceRate(alpha * carParams.getMonetaryDistanceRate()); + + // rider and driver have marginalUtilityOfDistance + rideParams.setMarginalUtilityOfDistance((alpha + 1.0) * carParams.getMarginalUtilityOfDistance()); + + // rider and driver have marginalUtilityOfTravelling, the driver additionally loses the opportunity to perform an activity + rideParams.setMarginalUtilityOfTraveling((alpha + 1.0) * carParams.getMarginalUtilityOfTraveling() + + alpha * -scoringConfigGroup.getPerforming_utils_hr()); + } +} diff --git a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/scoring/RideScoringParamsFromCarParamsTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/scoring/RideScoringParamsFromCarParamsTest.java new file mode 100644 index 00000000000..2703f23443a --- /dev/null +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/scoring/RideScoringParamsFromCarParamsTest.java @@ -0,0 +1,34 @@ +package org.matsim.contrib.vsp.scoring; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.ScoringConfigGroup; + +public class RideScoringParamsFromCarParamsTest { + + @Test + void testSetRideScoringParamsBasedOnCarParams() { + Config config = ConfigUtils.createConfig(); + ScoringConfigGroup scoringConfigGroup = config.scoring(); + + scoringConfigGroup.setPerforming_utils_hr(6.0); + ScoringConfigGroup.ModeParams carParams = scoringConfigGroup.getOrCreateModeParams(TransportMode.car); + carParams.setDailyMonetaryConstant(-10.0); + carParams.setMarginalUtilityOfDistance(-2.0); + carParams.setMarginalUtilityOfTraveling(-1.0); + carParams.setMonetaryDistanceRate(-0.3); + + double alpha = 2.0; + + RideScoringParamsFromCarParams.setRideScoringParamsBasedOnCarParams(scoringConfigGroup, alpha); + + ScoringConfigGroup.ModeParams rideParams = scoringConfigGroup.getOrCreateModeParams(TransportMode.ride); + Assertions.assertEquals(0.0, rideParams.getDailyMonetaryConstant()); + Assertions.assertEquals(-0.6, rideParams.getMonetaryDistanceRate()); + Assertions.assertEquals(-6.0, rideParams.getMarginalUtilityOfDistance()); + Assertions.assertEquals(alpha * -6.0 + (alpha + 1) * -1.0, rideParams.getMarginalUtilityOfTraveling()); + } +} From 091b754394337e771aefd5b43a358b0b9419ec17 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Fri, 16 Aug 2024 11:53:08 +0200 Subject: [PATCH 060/111] add chained pt fare handler --- .../vsp/pt/fare/ChainedPtFareCalculator.java | 23 ++ .../vsp/pt/fare/ChainedPtFareHandler.java | 68 ++++++ .../fare/DistanceBasedPtFareCalculator.java | 71 ++++++ .../pt/fare/DistanceBasedPtFareHandler.java | 81 ------- .../pt/fare/DistanceBasedPtFareParams.java | 213 ++++++++---------- .../fare/FareZoneBasedPtFareCalculator.java | 44 ++++ .../pt/fare/FareZoneBasedPtFareHandler.java | 163 -------------- .../pt/fare/FareZoneBasedPtFareParams.java | 33 +++ .../vsp/pt/fare/PtFareCalculator.java | 12 + .../vsp/pt/fare/PtFareConfigGroup.java | 119 +++++----- .../playground/vsp/pt/fare/PtFareHandler.java | 8 + .../playground/vsp/pt/fare/PtFareModule.java | 63 ++++-- .../playground/vsp/pt/fare/PtFareParams.java | 71 ++++++ .../PtTripWithDistanceBasedFareEstimator.java | 33 ++- .../fare/FareZoneBasedPtFareHandlerTest.java | 27 ++- 15 files changed, 562 insertions(+), 467 deletions(-) create mode 100644 contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareCalculator.java create mode 100644 contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareHandler.java create mode 100644 contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculator.java delete mode 100644 contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareHandler.java create mode 100644 contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculator.java delete mode 100644 contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandler.java create mode 100644 contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareParams.java create mode 100644 contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareCalculator.java create mode 100644 contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareHandler.java create mode 100644 contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareParams.java diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareCalculator.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareCalculator.java new file mode 100644 index 00000000000..a1156d01740 --- /dev/null +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareCalculator.java @@ -0,0 +1,23 @@ +package playground.vsp.pt.fare; + +import com.google.inject.Inject; +import org.matsim.api.core.v01.Coord; + +import java.util.Optional; +import java.util.Set; + +public class ChainedPtFareCalculator implements PtFareCalculator { + @Inject + private Set fareCalculators; + + @Override + public Optional calculateFare(Coord from, Coord to) { + for (PtFareCalculator fareCalculator : fareCalculators) { + Optional fareResult = fareCalculator.calculateFare(from, to); + if (fareResult.isPresent()) { + return fareResult; + } + } + return Optional.empty(); + } +} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareHandler.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareHandler.java new file mode 100644 index 00000000000..cc5963e6345 --- /dev/null +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareHandler.java @@ -0,0 +1,68 @@ +package playground.vsp.pt.fare; + +import com.google.inject.Inject; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.events.ActivityStartEvent; +import org.matsim.api.core.v01.events.PersonMoneyEvent; +import org.matsim.api.core.v01.population.Person; +import org.matsim.core.api.experimental.events.AgentWaitingForPtEvent; +import org.matsim.core.api.experimental.events.EventsManager; +import org.matsim.core.router.StageActivityTypeIdentifier; +import org.matsim.pt.PtConstants; + +import java.util.HashMap; +import java.util.Map; + +public class ChainedPtFareHandler implements PtFareHandler { + @Inject + private EventsManager events; + + private final Map, Coord> personDepartureCoordMap = new HashMap<>(); + private final Map, Coord> personArrivalCoordMap = new HashMap<>(); + + @Inject + private ChainedPtFareCalculator fareCalculator; + + @Override + public void handleEvent(ActivityStartEvent event) { + if (event.getActType().equals(PtConstants.TRANSIT_ACTIVITY_TYPE)) { + personDepartureCoordMap.computeIfAbsent(event.getPersonId(), c -> event.getCoord()); // The departure place is fixed to the place of + // first pt interaction an agent has in the whole leg + personArrivalCoordMap.put(event.getPersonId(), event.getCoord()); // The arrival stop will keep updating until the agent start a real + // activity (i.e. finish the leg) + } + + if (StageActivityTypeIdentifier.isStageActivity(event.getActType())) { + return; + } + + Id personId = event.getPersonId(); + if (!personDepartureCoordMap.containsKey(personId)) { + return; + } + + Coord from = personDepartureCoordMap.get(personId); + Coord to = personArrivalCoordMap.get(personId); + + PtFareCalculator.FareResult fare = fareCalculator.calculateFare(from, to).orElseThrow(); + + // charge fare to the person + events.processEvent(new PersonMoneyEvent(event.getTime(), event.getPersonId(), -fare.fare(), PtFareConfigGroup.PT_FARE, + fare.transactionPartner(), event.getPersonId().toString())); + + personDepartureCoordMap.remove(personId); + personArrivalCoordMap.remove(personId); + } + + @Override + public void handleEvent(AgentWaitingForPtEvent event) { + //TODO + } + + @Override + public void reset(int iteration) { + personArrivalCoordMap.clear(); + personDepartureCoordMap.clear(); + } +} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculator.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculator.java new file mode 100644 index 00000000000..cc3de24235c --- /dev/null +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculator.java @@ -0,0 +1,71 @@ +package playground.vsp.pt.fare; + +import org.geotools.api.feature.simple.SimpleFeature; +import org.locationtech.jts.geom.Geometry; +import org.matsim.api.core.v01.Coord; +import org.matsim.application.options.ShpOptions; +import org.matsim.core.utils.geometry.CoordUtils; +import org.matsim.core.utils.geometry.geotools.MGC; + +import java.util.List; +import java.util.Optional; + +public class DistanceBasedPtFareCalculator implements PtFareCalculator { + private final double minFare; + private final double shortTripIntercept; + private final double shortTripSlope; + private final double longTripIntercept; + private final double longTripSlope; + private final double longTripThreshold; + private ShpOptions shp = null; + private final String transactionPartner; + + public DistanceBasedPtFareCalculator(DistanceBasedPtFareParams params) { + this.minFare = params.getMinFare(); + this.shortTripIntercept = params.getNormalTripIntercept(); + this.shortTripSlope = params.getNormalTripSlope(); + this.longTripIntercept = params.getLongDistanceTripIntercept(); + this.longTripSlope = params.getLongDistanceTripSlope(); + this.longTripThreshold = params.getLongDistanceTripThreshold(); + this.transactionPartner = params.getTransactionPartner(); + + if (params.getFareZoneShp() != null) { + this.shp = new ShpOptions(params.getFareZoneShp(), null, null); + } + } + + @Override + public Optional calculateFare(Coord from, Coord to) { + if (!shapeCheck(from, to)) { + return Optional.empty(); + } + + double distance = CoordUtils.calcEuclideanDistance(from, to); + + double fare = computeFare(distance, longTripThreshold, minFare, shortTripIntercept, shortTripSlope, longTripIntercept, longTripSlope); + return Optional.of(new FareResult(fare, transactionPartner)); + } + + private boolean shapeCheck(Coord from, Coord to) { + if (shp == null) { + return true; + } + + return inShape(from, shp.readFeatures()) && inShape(to, shp.readFeatures()); + } + + boolean inShape(Coord coord, List features) { + return features.stream().anyMatch(f -> MGC.coord2Point(coord).within((Geometry) f.getDefaultGeometry())); + } + + public static double computeFare(double distance, double longTripThreshold, double minFare, double shortTripIntercept, double shortTripSlope, + double longTripIntercept, double longTripSlope) { + if (distance <= longTripThreshold) { + return Math.max(minFare, shortTripIntercept + shortTripSlope * distance); + } else { + return Math.max(minFare, longTripIntercept + longTripSlope * distance); + } + } + + +} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareHandler.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareHandler.java deleted file mode 100644 index 79741e54919..00000000000 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareHandler.java +++ /dev/null @@ -1,81 +0,0 @@ -package playground.vsp.pt.fare; - -import com.google.inject.Inject; -import org.matsim.api.core.v01.Coord; -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.events.ActivityStartEvent; -import org.matsim.api.core.v01.events.PersonMoneyEvent; -import org.matsim.api.core.v01.events.handler.ActivityStartEventHandler; -import org.matsim.api.core.v01.population.Person; -import org.matsim.core.api.experimental.events.EventsManager; -import org.matsim.core.router.StageActivityTypeIdentifier; -import org.matsim.core.utils.geometry.CoordUtils; -import org.matsim.pt.PtConstants; - -import java.util.HashMap; -import java.util.Map; - -public class DistanceBasedPtFareHandler implements ActivityStartEventHandler { - @Inject - private EventsManager events; - - private final double minFare; - private final double shortTripIntercept; - private final double shortTripSlope; - private final double longTripIntercept; - private final double longTripSlope; - private final double longTripThreshold; - - private final Map, Coord> personDepartureCoordMap = new HashMap<>(); - private final Map, Coord> personArrivalCoordMap = new HashMap<>(); - - public DistanceBasedPtFareHandler(DistanceBasedPtFareParams params) { - this.minFare = params.getMinFare(); - this.shortTripIntercept = params.getNormalTripIntercept(); - this.shortTripSlope = params.getNormalTripSlope(); - this.longTripIntercept = params.getLongDistanceTripIntercept(); - this.longTripSlope = params.getLongDistanceTripSlope(); - this.longTripThreshold = params.getLongDistanceTripThreshold(); - } - - @Override - public void handleEvent(ActivityStartEvent event) { - if (event.getActType().equals(PtConstants.TRANSIT_ACTIVITY_TYPE)) { - personDepartureCoordMap.computeIfAbsent(event.getPersonId(), c -> event.getCoord()); // The departure place is fixed to the place of first pt interaction an agent has in the whole leg - personArrivalCoordMap.put(event.getPersonId(), event.getCoord()); // The arrival stop will keep updating until the agent start a real activity (i.e. finish the leg) - } - - if (!StageActivityTypeIdentifier.isStageActivity(event.getActType())) { - Id personId = event.getPersonId(); - if (personDepartureCoordMap.containsKey(personId)) { - double distance = CoordUtils.calcEuclideanDistance - (personDepartureCoordMap.get(personId), personArrivalCoordMap.get(personId)); - - double fare = computeFare(distance, longTripThreshold, minFare, shortTripIntercept, shortTripSlope, longTripIntercept, longTripSlope); - // charge fare to the person - events.processEvent( - new PersonMoneyEvent(event.getTime(), event.getPersonId(), -fare, - PtFareConfigGroup.PT_FARE, DistanceBasedPtFareParams.PT_FARE_DISTANCE_BASED, event.getPersonId().toString())); - - personDepartureCoordMap.remove(personId); - personArrivalCoordMap.remove(personId); - } - } - } - - public static double computeFare(double distance, double longTripThreshold, double minFare, - double shortTripIntercept, double shortTripSlope, - double longTripIntercept, double longTripSlope) { - if (distance <= longTripThreshold) { - return Math.max(minFare, shortTripIntercept + shortTripSlope * distance); - } else { - return Math.max(minFare, longTripIntercept + longTripSlope * distance); - } - } - - @Override - public void reset(int iteration) { - personArrivalCoordMap.clear(); - personDepartureCoordMap.clear(); - } -} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java index 442d956bf3c..cc393f92175 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java @@ -1,7 +1,5 @@ package playground.vsp.pt.fare; -import org.matsim.core.config.ReflectiveConfigGroup; - import jakarta.validation.constraints.PositiveOrZero; import java.util.Map; @@ -12,119 +10,106 @@ * The default values are set based on the fitting results of the trip and fare data collected on September 2021 * The values are based on the standard unit of meter (m) and Euro (EUR) */ -public class DistanceBasedPtFareParams extends ReflectiveConfigGroup { - public static final String PT_FARE_DISTANCE_BASED = "distance based pt fare"; - - public static final String SET_NAME = "ptFareCalculationDistanceBased"; - public static final String MIN_FARE = "minFare"; - public static final String NORMAL_TRIP_SLOPE = "normalTripSlope"; - public static final String NORMAL_TRIP_INTERCEPT = "normalTripIntercept"; - public static final String LONG_DISTANCE_TRIP_THRESHOLD = "longDistanceTripThreshold"; - public static final String LONG_DISTANCE_TRIP_SLOPE = "longDistanceTripSlope"; - public static final String LONG_DISTANCE_TRIP_INTERCEPT = "longDistanceTripIntercept"; - public static final String FARE_ZONE_SHP = "fareZoneShp"; - - @PositiveOrZero - private double minFare = 2.0; - @PositiveOrZero - private double normalTripIntercept = 1.6; - @PositiveOrZero - private double normalTripSlope = 0.00017; - @PositiveOrZero - private double longDistanceTripThreshold = 50000.0; - @PositiveOrZero - private double longDistanceTripIntercept = 30.0; - @PositiveOrZero - private double longDistanceTripSlope = 0.00025; - private String fareZoneShp; - - public DistanceBasedPtFareParams() { - super(SET_NAME); - } - - @Override - public Map getComments() { - Map map = super.getComments(); - map.put(MIN_FARE, "Minimum fare for a PT trip " + - "(e.g. Kurzstrecke/short distance ticket in cities, ticket for 1 zone in rural areas)"); - map.put(NORMAL_TRIP_SLOPE, "Linear model y = ax + b: the value of a, for normal trips (e.g. within the city or region)"); - map.put(NORMAL_TRIP_INTERCEPT, "Linear model y = ax + b: the value of b, for normal trips"); - map.put(LONG_DISTANCE_TRIP_SLOPE, "Linear model y = ax + b: the value of a, for long distance trips (e.g. intercity trips)"); - map.put(LONG_DISTANCE_TRIP_INTERCEPT, "Linear model y = ax + b: the value of b, for long trips"); - map.put(LONG_DISTANCE_TRIP_THRESHOLD, "Threshold of the long trips in meters. Below this value, " + - "the trips are considered as normal trips. Above this value, the trips are considered as " + - "inter-city trips"); - map.put(FARE_ZONE_SHP, "Shp file with fare zone(s). This parameter is only used for PtFareCalculationModel 'fareZoneBased'."); - return map; - } - - @StringGetter(MIN_FARE) - public double getMinFare() { - return minFare; - } - - @StringSetter(MIN_FARE) - public void setMinFare(double minFare) { - this.minFare = minFare; - } - - @StringGetter(NORMAL_TRIP_SLOPE) - public double getNormalTripSlope() { - return normalTripSlope; - } - - @StringSetter(NORMAL_TRIP_SLOPE) - public void setNormalTripSlope(double normalTripSlope) { - this.normalTripSlope = normalTripSlope; - } - - @StringGetter(NORMAL_TRIP_INTERCEPT) - public double getNormalTripIntercept() { - return normalTripIntercept; - } - - @StringSetter(NORMAL_TRIP_INTERCEPT) - public void setNormalTripIntercept(double normalTripIntercept) { - this.normalTripIntercept = normalTripIntercept; - } - - @StringGetter(LONG_DISTANCE_TRIP_SLOPE) - public double getLongDistanceTripSlope() { - return longDistanceTripSlope; - } - - @StringSetter(LONG_DISTANCE_TRIP_SLOPE) - public void setLongDistanceTripSlope(double longDistanceTripSlope) { - this.longDistanceTripSlope = longDistanceTripSlope; - } - - @StringGetter(LONG_DISTANCE_TRIP_INTERCEPT) - public double getLongDistanceTripIntercept() { - return longDistanceTripIntercept; - } - - @StringSetter(LONG_DISTANCE_TRIP_INTERCEPT) - public void setLongDistanceTripIntercept(double longDistanceTripIntercept) { - this.longDistanceTripIntercept = longDistanceTripIntercept; - } - - @StringGetter(LONG_DISTANCE_TRIP_THRESHOLD) - public double getLongDistanceTripThreshold() { - return longDistanceTripThreshold; - } - - @StringSetter(LONG_DISTANCE_TRIP_THRESHOLD) - public void setLongDistanceTripThreshold(double longDistanceTripThreshold) { - this.longDistanceTripThreshold = longDistanceTripThreshold; - } - - @StringGetter(FARE_ZONE_SHP) - public String getFareZoneShp() { - return fareZoneShp; +public class DistanceBasedPtFareParams extends PtFareParams { + public static final String SET_NAME = "ptFareCalculationDistanceBased"; + public static final String MIN_FARE = "minFare"; + public static final String NORMAL_TRIP_SLOPE = "normalTripSlope"; + public static final String NORMAL_TRIP_INTERCEPT = "normalTripIntercept"; + public static final String LONG_DISTANCE_TRIP_THRESHOLD = "longDistanceTripThreshold"; + public static final String LONG_DISTANCE_TRIP_SLOPE = "longDistanceTripSlope"; + public static final String LONG_DISTANCE_TRIP_INTERCEPT = "longDistanceTripIntercept"; + + @PositiveOrZero + private double minFare = 2.0; + @PositiveOrZero + private double normalTripIntercept = 1.6; + @PositiveOrZero + private double normalTripSlope = 0.00017; + @PositiveOrZero + private double longDistanceTripThreshold = 50000.0; + @PositiveOrZero + private double longDistanceTripIntercept = 30.0; + @PositiveOrZero + private double longDistanceTripSlope = 0.00025; + + public DistanceBasedPtFareParams() { + super(SET_NAME); + } + + @Override + public Map getComments() { + Map map = super.getComments(); + map.put(MIN_FARE, "Minimum fare for a PT trip (e.g. Kurzstrecke/short distance ticket in cities, ticket for 1 zone in rural areas). Default" + + " " + + "is 2.0EUR."); + map.put(NORMAL_TRIP_SLOPE, "Linear model y = ax + b: the value of a, for normal trips (e.g. within the city or region). Default is 0.00017" + + "EUR."); + map.put(NORMAL_TRIP_INTERCEPT, "Linear model y = ax + b: the value of b, for normal trips. Default is 1.6EUR."); + map.put(LONG_DISTANCE_TRIP_SLOPE, "Linear model y = ax + b: the value of a, for long distance trips (e.g. intercity trips). Default is 0" + + ".00025EUR."); + map.put(LONG_DISTANCE_TRIP_INTERCEPT, "Linear model y = ax + b: the value of b, for long trips. Default is 30.0EUR."); + map.put(LONG_DISTANCE_TRIP_THRESHOLD, "Threshold of the long trips in meters. Below this value, the trips are considered as normal trips. " + + "Above this value, the trips are considered as inter-city trips. Default is 50000.0m."); + return map; + } + + @StringGetter(MIN_FARE) + public double getMinFare() { + return minFare; + } + + @StringSetter(MIN_FARE) + public void setMinFare(double minFare) { + this.minFare = minFare; + } + + @StringGetter(NORMAL_TRIP_SLOPE) + public double getNormalTripSlope() { + return normalTripSlope; + } + + @StringSetter(NORMAL_TRIP_SLOPE) + public void setNormalTripSlope(double normalTripSlope) { + this.normalTripSlope = normalTripSlope; + } + + @StringGetter(NORMAL_TRIP_INTERCEPT) + public double getNormalTripIntercept() { + return normalTripIntercept; + } + + @StringSetter(NORMAL_TRIP_INTERCEPT) + public void setNormalTripIntercept(double normalTripIntercept) { + this.normalTripIntercept = normalTripIntercept; + } + + @StringGetter(LONG_DISTANCE_TRIP_SLOPE) + public double getLongDistanceTripSlope() { + return longDistanceTripSlope; + } + + @StringSetter(LONG_DISTANCE_TRIP_SLOPE) + public void setLongDistanceTripSlope(double longDistanceTripSlope) { + this.longDistanceTripSlope = longDistanceTripSlope; + } + + @StringGetter(LONG_DISTANCE_TRIP_INTERCEPT) + public double getLongDistanceTripIntercept() { + return longDistanceTripIntercept; + } + + @StringSetter(LONG_DISTANCE_TRIP_INTERCEPT) + public void setLongDistanceTripIntercept(double longDistanceTripIntercept) { + this.longDistanceTripIntercept = longDistanceTripIntercept; + } + + @StringGetter(LONG_DISTANCE_TRIP_THRESHOLD) + public double getLongDistanceTripThreshold() { + return longDistanceTripThreshold; } - @StringSetter(FARE_ZONE_SHP) - public void setFareZoneShp(String fareZoneShp) { - this.fareZoneShp = fareZoneShp; + @StringSetter(LONG_DISTANCE_TRIP_THRESHOLD) + public void setLongDistanceTripThreshold(double longDistanceTripThreshold) { + this.longDistanceTripThreshold = longDistanceTripThreshold; } } diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculator.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculator.java new file mode 100644 index 00000000000..feda2b3a950 --- /dev/null +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculator.java @@ -0,0 +1,44 @@ +package playground.vsp.pt.fare; + +import org.geotools.api.feature.simple.SimpleFeature; +import org.locationtech.jts.geom.Geometry; +import org.matsim.api.core.v01.Coord; +import org.matsim.application.options.ShpOptions; +import org.matsim.core.utils.geometry.geotools.MGC; + +import java.util.List; +import java.util.Optional; + +public class FareZoneBasedPtFareCalculator implements PtFareCalculator { + private final ShpOptions shp; + private final String transactionPartner; + + public static final String FARE = "fare"; + + public FareZoneBasedPtFareCalculator(FareZoneBasedPtFareParams params) { + this.shp = new ShpOptions(params.getFareZoneShp(), null, null); + transactionPartner = params.getTransactionPartner(); + } + + @Override + public Optional calculateFare(Coord from, Coord to) { + Optional departureZone = determineFareZone(from, shp.readFeatures()); + Optional arrivalZone = determineFareZone(to, shp.readFeatures()); + + //if one of the zones is empty, it is not included in the shape file, so this calculator cannot compute the fare + if (departureZone.isEmpty() || arrivalZone.isEmpty()) { + return Optional.empty(); + } + + if (!departureZone.get().getID().equals(arrivalZone.get().getID())) { + return Optional.empty(); + } + + Double fare = (Double) departureZone.get().getAttribute(FARE); + return Optional.of(new FareResult(fare, transactionPartner)); + } + + Optional determineFareZone(Coord coord, List features) { + return features.stream().filter(f -> MGC.coord2Point(coord).within((Geometry) f.getDefaultGeometry())).findFirst(); + } +} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandler.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandler.java deleted file mode 100644 index 962a18fac57..00000000000 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandler.java +++ /dev/null @@ -1,163 +0,0 @@ -package playground.vsp.pt.fare; - -import com.google.inject.Inject; -import org.apache.commons.math.stat.regression.SimpleRegression; -import org.geotools.api.feature.simple.SimpleFeature; -import org.locationtech.jts.geom.Geometry; -import org.matsim.api.core.v01.Coord; -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.events.ActivityStartEvent; -import org.matsim.api.core.v01.events.PersonMoneyEvent; -import org.matsim.api.core.v01.events.handler.ActivityStartEventHandler; -import org.matsim.api.core.v01.population.Person; -import org.matsim.application.options.ShpOptions; -import org.matsim.core.api.experimental.events.EventsManager; -import org.matsim.core.router.StageActivityTypeIdentifier; -import org.matsim.core.utils.geometry.CoordUtils; -import org.matsim.core.utils.geometry.geotools.MGC; -import org.matsim.pt.PtConstants; - -import java.util.AbstractMap; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class FareZoneBasedPtFareHandler implements ActivityStartEventHandler { - @Inject - private EventsManager events; - - public static final String FARE = "fare"; - public static final String PT_FARE_ZONE_BASED = "fare zone based pt fare"; - public static final String PT_GERMANWIDE_FARE_BASED = "german-wide fare based pt fare"; - - private final ShpOptions shp; - - private final Map, Coord> personDepartureCoordMap = new HashMap<>(); - private final Map, Coord> personArrivalCoordMap = new HashMap<>(); - - public FareZoneBasedPtFareHandler(DistanceBasedPtFareParams params) { - this.shp = new ShpOptions(params.getFareZoneShp(), null, null); - } - - @Override - public void handleEvent(ActivityStartEvent event) { - - if (event.getActType().equals(PtConstants.TRANSIT_ACTIVITY_TYPE)) { - personDepartureCoordMap.computeIfAbsent(event.getPersonId(), c -> event.getCoord()); // The departure place is fixed to the place of first pt interaction an agent has in the whole leg - personArrivalCoordMap.put(event.getPersonId(), event.getCoord()); // The arrival stop will keep updating until the agent start a real activity (i.e. finish the leg) - } - - if (!StageActivityTypeIdentifier.isStageActivity(event.getActType())) { - Id personId = event.getPersonId(); - if (personDepartureCoordMap.containsKey(personId)) { - double distance = CoordUtils.calcEuclideanDistance - (personDepartureCoordMap.get(personId), personArrivalCoordMap.get(personId)); - - SimpleFeature departureZone = determineFareZone(personDepartureCoordMap.get(personId), shp.readFeatures()); - SimpleFeature arrivalZone = determineFareZone(personArrivalCoordMap.get(personId), shp.readFeatures()); - - Map.Entry fareEntry = computeFare(distance, departureZone, arrivalZone); - // charge fare to the person - events.processEvent( - new PersonMoneyEvent(event.getTime(), event.getPersonId(), -fareEntry.getValue(), - PtFareConfigGroup.PT_FARE, fareEntry.getKey(), event.getPersonId().toString())); - - personDepartureCoordMap.remove(personId); - personArrivalCoordMap.remove(personId); - } - } - } - - public static Map.Entry computeFare(double distance, SimpleFeature departureZone, SimpleFeature arrivalZone) { - - if (departureZone != null && arrivalZone != null) { -// if both zones are not null -> departure and arrival point are inside of one of the tarifzonen - if (departureZone.getID().equals(arrivalZone.getID())) { - return new AbstractMap.SimpleEntry<>(PT_FARE_ZONE_BASED ,(double) departureZone.getAttribute(FARE)); - } - } -// in every other case return german wide fare / Deutschlandtarif - return getGermanWideFare(distance); - } - - private static Map.Entry getGermanWideFare(double distance) { - - SimpleRegression regression = new SimpleRegression(); - -// in Deutschlandtarif, the linear function for the prices above 100km seem to have a different steepness -// hence the following difference in data points -// prices taken from https://deutschlandtarifverbund.de/wp-content/uploads/2024/07/20231201_TBDT_J_10_Preisliste_V07.pdf - if (distance / 1000 <= 100.) { - regression.addData(1, 1.70); - regression.addData(2,1.90); - regression.addData(3,2.00); - regression.addData(4,2.10); - regression.addData(5,2.20); - regression.addData(6,3.20); - regression.addData(7,3.70); - regression.addData(8,3.80); - regression.addData(9,3.90); - regression.addData(10,4.10); - regression.addData(11,5.00); - regression.addData(12,5.40); - regression.addData(13,5.60); - regression.addData(14,5.80); - regression.addData(15,5.90); - regression.addData(16,6.40); - regression.addData(17,6.50); - regression.addData(18,6.60); - regression.addData(19,6.70); - regression.addData(20,6.90); - regression.addData(30,9.90); - regression.addData(40,13.70); - regression.addData(50,16.30); - regression.addData(60,18.10); - regression.addData(70,20.10); - regression.addData(80,23.20); - regression.addData(90,26.20); - regression.addData(100,28.10); - } else { - regression.addData(100,28.10); - regression.addData(200,47.20); - regression.addData(300,59.70); - regression.addData(400,71.70); - regression.addData(500,83.00); - regression.addData(600,94.60); - regression.addData(700,106.30); - regression.addData(800,118.20); - regression.addData(900,130.10); - regression.addData(1000,141.00); - regression.addData(1100,148.60); - regression.addData(1200,158.10); - regression.addData(1300,169.20); - regression.addData(1400,179.80); - regression.addData(1500,190.10); - regression.addData(1600,201.50); - regression.addData(1700,212.80); - regression.addData(1800,223.30); - regression.addData(1900,233.90); - regression.addData(2000,244.00); - } - return new AbstractMap.SimpleEntry<>(PT_GERMANWIDE_FARE_BASED, regression.getSlope() * distance / 1000 + regression.getIntercept()); - } - - static SimpleFeature determineFareZone(Coord coord, List features) { - SimpleFeature zone = null; - - for (SimpleFeature ft : features) { - Geometry geom = (Geometry) ft.getDefaultGeometry(); - - if (MGC.coord2Point(coord).within(geom)) { - zone = ft; - break; - } - } - return zone; - } - - @Override - public void reset(int iteration) { - personArrivalCoordMap.clear(); - personDepartureCoordMap.clear(); - } -} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareParams.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareParams.java new file mode 100644 index 00000000000..d869f18eaa7 --- /dev/null +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareParams.java @@ -0,0 +1,33 @@ +package playground.vsp.pt.fare; + +import java.util.Map; + +public class FareZoneBasedPtFareParams extends PtFareParams { + public static final String SET_NAME = "ptFareCalculationFareZoneBased"; + + public static final String COST = "cost"; + + private Double cost; + + public FareZoneBasedPtFareParams() { + super(SET_NAME); + } + + @Override + public Map getComments() { + Map map = super.getComments(); + map.put(COST, "Cost of a trip within the fare zone."); + return map; + } + + @StringGetter(COST) + public Double getCost() { + return cost; + } + + @StringSetter(COST) + public void setCost(Double cost) { + this.cost = cost; + } + //TODO check consistency +} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareCalculator.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareCalculator.java new file mode 100644 index 00000000000..06fa0af4ca9 --- /dev/null +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareCalculator.java @@ -0,0 +1,12 @@ +package playground.vsp.pt.fare; + +import org.matsim.api.core.v01.Coord; + +import java.util.Optional; + +public interface PtFareCalculator { + Optional calculateFare(Coord from, Coord to); + + record FareResult(Double fare, String transactionPartner) { + } +} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java index 8abf76dcb37..b629bbf9eb5 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java @@ -1,75 +1,60 @@ package playground.vsp.pt.fare; -import org.matsim.core.config.ReflectiveConfigGroup; - import jakarta.validation.constraints.PositiveOrZero; +import org.matsim.core.config.ReflectiveConfigGroup; import java.util.Map; public class PtFareConfigGroup extends ReflectiveConfigGroup { - public static final String PT_FARE = "pt fare"; - public static final String MODULE_NAME = "ptFare"; - public static final String PT_FARE_CALCULATION = "ptFareCalculation"; - public static final String APPLY_UPPER_BOUND = "applyUpperBound"; - public static final String UPPER_BOUND_FACTOR = "upperBoundFactor"; - - public enum PtFareCalculationModels {distanceBased, fareZoneBased} // More to come (e.g. zone based, hybrid...) - - private static final String PT_FARE_CALCULATION_CMT = "PT fare calculation scheme. Current implementation: distanceBased (more to come...)"; - public static final String UPPER_BOUND_FACTOR_CMT = "When upper bound is applied, upperBound = upperBoundFactor * max Fare of the day. " + - "This value is decided by the ratio between average daily cost of a ticket subscription and the single " + - "trip ticket of the same trip. Usually this value should be somewhere between 1.0 and 2.0"; - public static final String APPLY_UPPER_BOUND_CMT = "Enable the upper bound for daily PT fare to count for ticket subscription. Input value: true or false"; - - private PtFareCalculationModels ptFareCalculation = PtFareCalculationModels.distanceBased; // Use distance based calculation by default - private boolean applyUpperBound = true; - @PositiveOrZero - private double upperBoundFactor = 1.5; - - public PtFareConfigGroup() { - super(MODULE_NAME); - } - - @Override - public Map getComments() { - Map map = super.getComments(); - map.put(PT_FARE_CALCULATION, PT_FARE_CALCULATION_CMT ); - map.put(APPLY_UPPER_BOUND, APPLY_UPPER_BOUND_CMT ); - map.put(UPPER_BOUND_FACTOR, UPPER_BOUND_FACTOR_CMT ); - return map; - } - - @StringGetter(PT_FARE_CALCULATION) - public PtFareCalculationModels getPtFareCalculation() { - return ptFareCalculation; - } - - @StringSetter(PT_FARE_CALCULATION) - public void setPtFareCalculationModel(PtFareCalculationModels ptFareCalculation) { - this.ptFareCalculation = ptFareCalculation; - } - - @StringGetter(APPLY_UPPER_BOUND) - public boolean getApplyUpperBound() { - return applyUpperBound; - } - - @StringSetter(APPLY_UPPER_BOUND) - public void setApplyUpperBound(boolean applyUpperBound) { - this.applyUpperBound = applyUpperBound; - } - - - @StringGetter(UPPER_BOUND_FACTOR) - public double getUpperBoundFactor() { - return upperBoundFactor; - } - - /** - * @param upperBoundFactor -- {@value #UPPER_BOUND_FACTOR_CMT} - */ - @StringSetter(UPPER_BOUND_FACTOR) - public void setUpperBoundFactor(double upperBoundFactor) { - this.upperBoundFactor = upperBoundFactor; - } + public static final String PT_FARE = "pt fare"; + public static final String MODULE_NAME = "ptFare"; + public static final String APPLY_UPPER_BOUND = "applyUpperBound"; + public static final String UPPER_BOUND_FACTOR = "upperBoundFactor"; + + public static final String UPPER_BOUND_FACTOR_CMT = "When upper bound is applied, upperBound = upperBoundFactor * max Fare of the day. " + + "This value is decided by the ratio between average daily cost of a ticket subscription and the single " + + "trip ticket of the same trip. Usually this value should be somewhere between 1.0 and 2.0"; + public static final String APPLY_UPPER_BOUND_CMT = "Enable the upper bound for daily PT fare to count for ticket subscription. Input value: " + + "true" + + " or false"; + + private boolean applyUpperBound = true; + @PositiveOrZero + private double upperBoundFactor = 1.5; + + public PtFareConfigGroup() { + super(MODULE_NAME); + } + + @Override + public Map getComments() { + Map map = super.getComments(); + map.put(APPLY_UPPER_BOUND, APPLY_UPPER_BOUND_CMT); + map.put(UPPER_BOUND_FACTOR, UPPER_BOUND_FACTOR_CMT); + return map; + } + + @StringGetter(APPLY_UPPER_BOUND) + public boolean getApplyUpperBound() { + return applyUpperBound; + } + + @StringSetter(APPLY_UPPER_BOUND) + public void setApplyUpperBound(boolean applyUpperBound) { + this.applyUpperBound = applyUpperBound; + } + + + @StringGetter(UPPER_BOUND_FACTOR) + public double getUpperBoundFactor() { + return upperBoundFactor; + } + + /** + * @param upperBoundFactor -- {@value #UPPER_BOUND_FACTOR_CMT} + */ + @StringSetter(UPPER_BOUND_FACTOR) + public void setUpperBoundFactor(double upperBoundFactor) { + this.upperBoundFactor = upperBoundFactor; + } } diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareHandler.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareHandler.java new file mode 100644 index 00000000000..d911486a0e2 --- /dev/null +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareHandler.java @@ -0,0 +1,8 @@ +package playground.vsp.pt.fare; + +import org.matsim.api.core.v01.events.handler.ActivityStartEventHandler; +import org.matsim.core.api.experimental.events.handler.AgentWaitingForPtEventHandler; + +public interface PtFareHandler extends ActivityStartEventHandler, AgentWaitingForPtEventHandler { + //other methods for informed mode choice +} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java index 4da41c16612..9c0ee97efc2 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java @@ -1,31 +1,50 @@ package playground.vsp.pt.fare; +import com.google.inject.multibindings.Multibinder; import org.matsim.api.core.v01.TransportMode; +import org.matsim.core.config.ConfigGroup; import org.matsim.core.config.ConfigUtils; import org.matsim.core.controler.AbstractModule; +import java.util.Collection; +import java.util.Comparator; +import java.util.stream.Stream; + public class PtFareModule extends AbstractModule { - @Override - public void install() { - getConfig().scoring().getModes().get(TransportMode.pt).setDailyMonetaryConstant(0); - getConfig().scoring().getModes().get(TransportMode.pt).setMarginalUtilityOfDistance(0); - PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(this.getConfig(), PtFareConfigGroup.class); - DistanceBasedPtFareParams distanceBasedPtFareParams = ConfigUtils.addOrGetModule(this.getConfig(), DistanceBasedPtFareParams.class); - - if (ptFareConfigGroup.getPtFareCalculation() == PtFareConfigGroup.PtFareCalculationModels.distanceBased) { - addEventHandlerBinding().toInstance(new DistanceBasedPtFareHandler(distanceBasedPtFareParams)); - } else if (ptFareConfigGroup.getPtFareCalculation() == PtFareConfigGroup.PtFareCalculationModels.fareZoneBased) { - addEventHandlerBinding().toInstance(new FareZoneBasedPtFareHandler(distanceBasedPtFareParams)); - } else { - throw new RuntimeException("Please choose from the following fare Calculation method: [" + - PtFareConfigGroup.PtFareCalculationModels.distanceBased + ", " + PtFareConfigGroup.PtFareCalculationModels.fareZoneBased + "]"); - } - - if (ptFareConfigGroup.getApplyUpperBound()) { - PtFareUpperBoundHandler ptFareUpperBoundHandler = new PtFareUpperBoundHandler(ptFareConfigGroup.getUpperBoundFactor()); - addEventHandlerBinding().toInstance(ptFareUpperBoundHandler); - addControlerListenerBinding().toInstance(ptFareUpperBoundHandler); - } - } + @Override + public void install() { + //TODO check consistency: order unique, cost set + + getConfig().scoring().getModes().get(TransportMode.pt).setDailyMonetaryConstant(0); + getConfig().scoring().getModes().get(TransportMode.pt).setMarginalUtilityOfDistance(0); + Multibinder ptFareCalculator = Multibinder.newSetBinder(binder(), PtFareCalculator.class); + + PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(this.getConfig(), PtFareConfigGroup.class); + Collection fareZoneBased = ptFareConfigGroup.getParameterSets(FareZoneBasedPtFareParams.SET_NAME); + Collection distanceBased = ptFareConfigGroup.getParameterSets(DistanceBasedPtFareParams.SET_NAME); + + Stream.concat(fareZoneBased.stream(), distanceBased.stream()) + .map(c -> (PtFareParams) c) + .sorted(Comparator.comparing(PtFareParams::getPriority).reversed()) + .forEach(p -> { + if (p instanceof FareZoneBasedPtFareParams fareZoneBasedPtFareParams) { + ptFareCalculator.addBinding().toInstance(new FareZoneBasedPtFareCalculator(fareZoneBasedPtFareParams)); + } else if (p instanceof DistanceBasedPtFareParams distanceBasedPtFareParams) { + ptFareCalculator.addBinding().toInstance(new DistanceBasedPtFareCalculator(distanceBasedPtFareParams)); + } else { + throw new RuntimeException("Unknown PtFareParams: " + p.getClass()); + } + }); + + bind(ChainedPtFareCalculator.class); + bind(PtFareHandler.class).to(ChainedPtFareHandler.class); + addEventHandlerBinding().to(PtFareHandler.class); + + if (ptFareConfigGroup.getApplyUpperBound()) { + PtFareUpperBoundHandler ptFareUpperBoundHandler = new PtFareUpperBoundHandler(ptFareConfigGroup.getUpperBoundFactor()); + addEventHandlerBinding().toInstance(ptFareUpperBoundHandler); + addControlerListenerBinding().toInstance(ptFareUpperBoundHandler); + } + } } diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareParams.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareParams.java new file mode 100644 index 00000000000..ece2641d9ad --- /dev/null +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareParams.java @@ -0,0 +1,71 @@ +package playground.vsp.pt.fare; + +import org.matsim.core.config.ReflectiveConfigGroup; + +import java.util.Map; + +public abstract class PtFareParams extends ReflectiveConfigGroup { + public static final String FARE_ZONE_SHP = "fareZoneShp"; + public static final String PRIORITY = "priority"; + public static final String TRANSACTION_PARTNER = "transactionPartner"; + public static final String DESCRIPTION = "description"; + + private int priority; + private String fareZoneShp; + private String transactionPartner; + private String description; + + public PtFareParams(String name) { + super(name); + } + + @Override + public Map getComments() { + var map = super.getComments(); + map.put(FARE_ZONE_SHP, "Shp file with fare zone(s). This parameter is only used for PtFareCalculationModel 'fareZoneBased'."); + map.put(PRIORITY, "Priority of this fare calculation in the list of fare calculations. Higher values mean to be evaluated first."); + map.put(TRANSACTION_PARTNER, "The transaction partner for the fare calculation. This is used in the PersonMoneyEvent."); + map.put(DESCRIPTION, "Description of the fare zone."); + return map; + } + + @StringGetter(FARE_ZONE_SHP) + public String getFareZoneShp() { + return fareZoneShp; + } + + @StringSetter(FARE_ZONE_SHP) + public void setFareZoneShp(String fareZoneShp) { + this.fareZoneShp = fareZoneShp; + } + + @StringGetter(PRIORITY) + public int getPriority() { + return priority; + } + + @StringSetter(PRIORITY) + public void setPriority(int priority) { + this.priority = priority; + } + + @StringGetter(TRANSACTION_PARTNER) + public String getTransactionPartner() { + return transactionPartner; + } + + @StringSetter(TRANSACTION_PARTNER) + public void setTransactionPartner(String transactionPartner) { + this.transactionPartner = transactionPartner; + } + + @StringGetter(DESCRIPTION) + public String getDescription() { + return description; + } + + @StringSetter(DESCRIPTION) + public void setDescription(String description) { + this.description = description; + } +} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java index 5af45c407fe..5795934440e 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java @@ -29,7 +29,8 @@ public class PtTripWithDistanceBasedFareEstimator extends PtTripEstimator { private final Map, TransitStopFacility> facilities; @Inject - public PtTripWithDistanceBasedFareEstimator(TransitSchedule transitSchedule, PtFareConfigGroup config, DistanceBasedPtFareParams ptFare, Scenario scenario) { + public PtTripWithDistanceBasedFareEstimator(TransitSchedule transitSchedule, PtFareConfigGroup config, DistanceBasedPtFareParams ptFare, + Scenario scenario) { super(transitSchedule); this.config = config; this.ptFare = ptFare; @@ -55,8 +56,9 @@ public MinMaxEstimate estimate(EstimatorContext context, String mode, PlanModel maxFareUtility = Math.max(fareUtility, maxFareUtility); max = estimate + maxFareUtility; - } else + } else { max = estimate + fareUtility; + } // Distance fareUtility is the highest possible price, therefore the minimum utility return MinMaxEstimate.of(estimate + fareUtility, max); @@ -78,8 +80,9 @@ public double estimate(EstimatorContext context, String mode, String[] modes, Pl List legs = plan.getLegs(mode, i); // Legs can be null if there is a predefined pt trip - if (legs == null) + if (legs == null) { continue; + } //assert legs != null : "Legs must be not null at this point"; @@ -121,8 +124,9 @@ private DoubleDoublePair estimateTrip(EstimatorContext context, List trip) TransitPassengerRoute route = (TransitPassengerRoute) leg.getRoute(); - if (access == null) + if (access == null) { access = facilities.get(route.getAccessStopId()); + } egress = facilities.get(route.getEgressStopId()); @@ -139,8 +143,9 @@ private DoubleDoublePair estimateTrip(EstimatorContext context, List trip) double dist = CoordUtils.calcEuclideanDistance(access.getCoord(), egress.getCoord()); - double fareUtility = -context.scoring.marginalUtilityOfMoney * DistanceBasedPtFareHandler.computeFare(dist, ptFare.getLongDistanceTripThreshold(), ptFare.getMinFare(), - ptFare.getNormalTripIntercept(), ptFare.getNormalTripSlope(), ptFare.getLongDistanceTripIntercept(), ptFare.getLongDistanceTripSlope()); + double fareUtility = -context.scoring.marginalUtilityOfMoney * DistanceBasedPtFareCalculator.computeFare(dist, + ptFare.getLongDistanceTripThreshold(), ptFare.getMinFare(), ptFare.getNormalTripIntercept(), ptFare.getNormalTripSlope(), + ptFare.getLongDistanceTripIntercept(), ptFare.getLongDistanceTripSlope()); estimate += context.scoring.marginalUtilityOfWaitingPt_s * totalWaitingTime; @@ -165,8 +170,9 @@ private double calcMinimumFare(PlanModel plan) { List legs = plan.getLegs(TransportMode.pt, i); - if (legs == null) + if (legs == null) { continue; + } // first access and last egress TransitStopFacility access = null; @@ -183,8 +189,9 @@ private double calcMinimumFare(PlanModel plan) { TransitPassengerRoute route = (TransitPassengerRoute) leg.getRoute(); hasPT = true; - if (access == null) + if (access == null) { access = facilities.get(route.getAccessStopId()); + } egress = facilities.get(route.getEgressStopId()); } @@ -206,15 +213,17 @@ private double calcMinimumFare(PlanModel plan) { // a single pt trip could never benefit from the upper bound if (n == 1) { - return DistanceBasedPtFareHandler.computeFare(minDist, ptFare.getLongDistanceTripThreshold(), ptFare.getMinFare(), - ptFare.getNormalTripIntercept(), ptFare.getNormalTripSlope(), ptFare.getLongDistanceTripIntercept(), ptFare.getLongDistanceTripSlope()); + return DistanceBasedPtFareCalculator.computeFare(minDist, ptFare.getLongDistanceTripThreshold(), ptFare.getMinFare(), + ptFare.getNormalTripIntercept(), ptFare.getNormalTripSlope(), ptFare.getLongDistanceTripIntercept(), + ptFare.getLongDistanceTripSlope()); } // the upper bound is the maximum single trip times a factor // therefore the minimum upper bound is the fare for the second-longest trip // the max costs are then assumed to be evenly distributed over all pt trips - return 1d / n * config.getUpperBoundFactor() * DistanceBasedPtFareHandler.computeFare(secondMinDist, ptFare.getLongDistanceTripThreshold(), ptFare.getMinFare(), - ptFare.getNormalTripIntercept(), ptFare.getNormalTripSlope(), ptFare.getLongDistanceTripIntercept(), ptFare.getLongDistanceTripSlope()); + return 1d / n * config.getUpperBoundFactor() * DistanceBasedPtFareCalculator.computeFare(secondMinDist, + ptFare.getLongDistanceTripThreshold(), ptFare.getMinFare(), ptFare.getNormalTripIntercept(), ptFare.getNormalTripSlope(), + ptFare.getLongDistanceTripIntercept(), ptFare.getLongDistanceTripSlope()); } @Override diff --git a/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java b/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java index ec486ec2cee..a894bb44141 100644 --- a/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java @@ -37,6 +37,8 @@ public class FareZoneBasedPtFareHandlerTest { @Test void testFareZoneBasedPtFareHandler() { + final String FARE_ZONE_TRANSACTION_PARTNER = "fare zone transaction partner"; + final String DISTANCE_BASED_TRANSACTION_PARTNER = "distance based transaction partner"; URL context = ExamplesUtils.getTestScenarioURL("kelheim"); Config config = ConfigUtils.loadConfig(IOUtils.extendUrl(context, "config.xml")); @@ -45,11 +47,20 @@ void testFareZoneBasedPtFareHandler() { config.controller().setLastIteration(0); PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(config, PtFareConfigGroup.class); - ptFareConfigGroup.setPtFareCalculationModel(PtFareConfigGroup.PtFareCalculationModels.fareZoneBased); - DistanceBasedPtFareParams fareParams = ConfigUtils.addOrGetModule(config, DistanceBasedPtFareParams.class); - fareParams.setFareZoneShp(IOUtils.extendUrl(context, "ptTestArea/pt-area.shp").toString()); + FareZoneBasedPtFareParams fareZoneBased = new FareZoneBasedPtFareParams(); + fareZoneBased.setCost(2.5); + fareZoneBased.setDescription("simple fare zone based"); + fareZoneBased.setFareZoneShp(IOUtils.extendUrl(context, "ptTestArea/pt-area.shp").toString()); + fareZoneBased.setPriority(10); + fareZoneBased.setTransactionPartner(FARE_ZONE_TRANSACTION_PARTNER); + DistanceBasedPtFareParams distanceBased = new DistanceBasedPtFareParams(); + distanceBased.setPriority(5); + distanceBased.setTransactionPartner(DISTANCE_BASED_TRANSACTION_PARTNER); + + ptFareConfigGroup.addParameterSet(fareZoneBased); + ptFareConfigGroup.addParameterSet(distanceBased); ScoringConfigGroup scoring = ConfigUtils.addOrGetModule(config, ScoringConfigGroup.class); @@ -69,13 +80,13 @@ void testFareZoneBasedPtFareHandler() { Person person = fac.createPerson(Id.createPersonId("fareTestPerson")); Plan plan = fac.createPlan(); - Activity home = fac.createActivityFromCoord("home", new Coord(710300.624,5422165.737)); + Activity home = fac.createActivityFromCoord("home", new Coord(710300.624, 5422165.737)); // bus to Saal (Donau) work location departs at 09:14 home.setEndTime(9 * 3600.); - Activity work = fac.createActivityFromCoord("work", new Coord(714940.65,5420707.78)); + Activity work = fac.createActivityFromCoord("work", new Coord(714940.65, 5420707.78)); // rb17 to regensburg 2nd home location departs at 13:59 work.setEndTime(13 * 3600. + 45 * 60); - Activity home2 = fac.createActivityFromCoord("home", new Coord(726634.40,5433508.07)); + Activity home2 = fac.createActivityFromCoord("home", new Coord(726634.40, 5433508.07)); Leg leg = fac.createLeg(TransportMode.pt); @@ -118,7 +129,7 @@ public void install() { } Assertions.assertEquals(2, events.size()); - Assertions.assertEquals(FareZoneBasedPtFareHandler.PT_FARE_ZONE_BASED, events.get(0)[4]); - Assertions.assertEquals(FareZoneBasedPtFareHandler.PT_GERMANWIDE_FARE_BASED, events.get(1)[4]); + Assertions.assertEquals(FARE_ZONE_TRANSACTION_PARTNER, events.get(0)[4]); + Assertions.assertEquals(DISTANCE_BASED_TRANSACTION_PARTNER, events.get(1)[4]); } } From 6b15b10bf22f966f80f00fdfcc02c3b67ce8d906 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Fri, 16 Aug 2024 13:55:38 +0200 Subject: [PATCH 061/111] implemented tests --- .../vsp/pt/fare/ChainedPtFareCalculator.java | 5 ++ .../fare/DistanceBasedPtFareCalculator.java | 29 +++++-- .../pt/fare/DistanceBasedPtFareParams.java | 78 ++++++++++++++++++- .../fare/FareZoneBasedPtFareCalculator.java | 15 ++-- .../pt/fare/FareZoneBasedPtFareParams.java | 24 ------ .../vsp/pt/fare/PtFareConfigGroup.java | 23 ++++++ .../playground/vsp/pt/fare/PtFareModule.java | 2 - .../PtTripWithDistanceBasedFareEstimator.java | 12 ++- .../DistanceBasedPtFareCalculatorTest.java | 76 ++++++++++++++++++ .../FareZoneBasedPtFareCalculatorTest.java | 57 ++++++++++++++ .../fare/FareZoneBasedPtFareHandlerTest.java | 1 - .../vsp/pt/fare/PtFareConfigGroupTest.java | 45 +++++++++++ .../vsp/pt/fare/PtTripFareEstimatorTest.java | 29 +++---- 13 files changed, 338 insertions(+), 58 deletions(-) create mode 100644 contribs/vsp/src/test/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java create mode 100644 contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java create mode 100644 contribs/vsp/src/test/java/playground/vsp/pt/fare/PtFareConfigGroupTest.java diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareCalculator.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareCalculator.java index a1156d01740..bd38fc3237b 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareCalculator.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareCalculator.java @@ -6,6 +6,11 @@ import java.util.Optional; import java.util.Set; +/** + * This class is a {@link PtFareCalculator} that chains multiple {@link PtFareCalculator}s together. As soon as one of the chained calculators + * returns a fare, this calculator returns that fare. In {@link PtFareModule} all available {@link PtFareCalculator}s are bound to this class. The + * order in which the calculators are bound is determined by the priority of the {@link PtFareParams} they are created from. + */ public class ChainedPtFareCalculator implements PtFareCalculator { @Inject private Set fareCalculators; diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculator.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculator.java index cc3de24235c..3708bf7acce 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculator.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculator.java @@ -1,16 +1,25 @@ package playground.vsp.pt.fare; -import org.geotools.api.feature.simple.SimpleFeature; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.locationtech.jts.geom.Geometry; import org.matsim.api.core.v01.Coord; import org.matsim.application.options.ShpOptions; import org.matsim.core.utils.geometry.CoordUtils; import org.matsim.core.utils.geometry.geotools.MGC; -import java.util.List; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; +/** + * This class calculates the fare for a public transport trip based on the distance between the origin and destination. If a shape file is + * provided, the + * fare will be calculated only if the trip is within the shape. + */ public class DistanceBasedPtFareCalculator implements PtFareCalculator { + private static final Logger log = LogManager.getLogger(DistanceBasedPtFareCalculator.class); + private final double minFare; private final double shortTripIntercept; private final double shortTripSlope; @@ -20,6 +29,8 @@ public class DistanceBasedPtFareCalculator implements PtFareCalculator { private ShpOptions shp = null; private final String transactionPartner; + private final Map inShapeCache = new HashMap<>(); + public DistanceBasedPtFareCalculator(DistanceBasedPtFareParams params) { this.minFare = params.getMinFare(); this.shortTripIntercept = params.getNormalTripIntercept(); @@ -30,7 +41,12 @@ public DistanceBasedPtFareCalculator(DistanceBasedPtFareParams params) { this.transactionPartner = params.getTransactionPartner(); if (params.getFareZoneShp() != null) { + log.info("For DistanceBasedPtFareCalculator '{}' a fare zone shape file was provided. During the computation, the fare will be " + + "calculated only if the trip is within the shape.", params.getDescription()); this.shp = new ShpOptions(params.getFareZoneShp(), null, null); + } else { + log.info("For DistanceBasedPtFareCalculator '{}' no fare zone shape file was provided. The fare will be calculated for all trips.", + params.getDescription()); } } @@ -50,12 +66,11 @@ private boolean shapeCheck(Coord from, Coord to) { if (shp == null) { return true; } - - return inShape(from, shp.readFeatures()) && inShape(to, shp.readFeatures()); + return inShapeCache.computeIfAbsent(from, this::inShape) && inShapeCache.computeIfAbsent(to, this::inShape); } - boolean inShape(Coord coord, List features) { - return features.stream().anyMatch(f -> MGC.coord2Point(coord).within((Geometry) f.getDefaultGeometry())); + private boolean inShape(Coord coord) { + return shp.readFeatures().stream().anyMatch(f -> MGC.coord2Point(coord).within((Geometry) f.getDefaultGeometry())); } public static double computeFare(double distance, double longTripThreshold, double minFare, double shortTripIntercept, double shortTripSlope, @@ -66,6 +81,4 @@ public static double computeFare(double distance, double longTripThreshold, doub return Math.max(minFare, longTripIntercept + longTripSlope * distance); } } - - } diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java index cc393f92175..605a266e131 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java @@ -1,6 +1,7 @@ package playground.vsp.pt.fare; import jakarta.validation.constraints.PositiveOrZero; +import org.apache.commons.math.stat.regression.SimpleRegression; import java.util.Map; @@ -11,6 +12,8 @@ * The values are based on the standard unit of meter (m) and Euro (EUR) */ public class DistanceBasedPtFareParams extends PtFareParams { + public static final DistanceBasedPtFareParams GERMAN_WIDE_FARE = germanWideFare(); + public static final String SET_NAME = "ptFareCalculationDistanceBased"; public static final String MIN_FARE = "minFare"; public static final String NORMAL_TRIP_SLOPE = "normalTripSlope"; @@ -39,9 +42,8 @@ public DistanceBasedPtFareParams() { @Override public Map getComments() { Map map = super.getComments(); - map.put(MIN_FARE, "Minimum fare for a PT trip (e.g. Kurzstrecke/short distance ticket in cities, ticket for 1 zone in rural areas). Default" + - " " + - "is 2.0EUR."); + map.put(MIN_FARE, "Minimum fare for a PT trip (e.g. Kurzstrecke/short distance ticket in cities, ticket for 1 zone in rural areas). " + + "Default is 2.0EUR."); map.put(NORMAL_TRIP_SLOPE, "Linear model y = ax + b: the value of a, for normal trips (e.g. within the city or region). Default is 0.00017" + "EUR."); map.put(NORMAL_TRIP_INTERCEPT, "Linear model y = ax + b: the value of b, for normal trips. Default is 1.6EUR."); @@ -112,4 +114,74 @@ public double getLongDistanceTripThreshold() { public void setLongDistanceTripThreshold(double longDistanceTripThreshold) { this.longDistanceTripThreshold = longDistanceTripThreshold; } + + // in Deutschlandtarif, the linear function for the prices above 100km seem to have a different steepness + // hence the following difference in data points + // prices taken from https://deutschlandtarifverbund.de/wp-content/uploads/2024/07/20231201_TBDT_J_10_Preisliste_V07.pdf + private static DistanceBasedPtFareParams germanWideFare() { + final double MIN_FARE = 1.70; + + SimpleRegression normalDistanceTrip = new SimpleRegression(); + normalDistanceTrip.addData(1, MIN_FARE); + normalDistanceTrip.addData(2, 1.90); + normalDistanceTrip.addData(3, 2.00); + normalDistanceTrip.addData(4, 2.10); + normalDistanceTrip.addData(5, 2.20); + normalDistanceTrip.addData(6, 3.20); + normalDistanceTrip.addData(7, 3.70); + normalDistanceTrip.addData(8, 3.80); + normalDistanceTrip.addData(9, 3.90); + normalDistanceTrip.addData(10, 4.10); + normalDistanceTrip.addData(11, 5.00); + normalDistanceTrip.addData(12, 5.40); + normalDistanceTrip.addData(13, 5.60); + normalDistanceTrip.addData(14, 5.80); + normalDistanceTrip.addData(15, 5.90); + normalDistanceTrip.addData(16, 6.40); + normalDistanceTrip.addData(17, 6.50); + normalDistanceTrip.addData(18, 6.60); + normalDistanceTrip.addData(19, 6.70); + normalDistanceTrip.addData(20, 6.90); + normalDistanceTrip.addData(30, 9.90); + normalDistanceTrip.addData(40, 13.70); + normalDistanceTrip.addData(50, 16.30); + normalDistanceTrip.addData(60, 18.10); + normalDistanceTrip.addData(70, 20.10); + normalDistanceTrip.addData(80, 23.20); + normalDistanceTrip.addData(90, 26.20); + normalDistanceTrip.addData(100, 28.10); + + SimpleRegression longDistanceTrip = new SimpleRegression(); + longDistanceTrip.addData(100, 28.10); + longDistanceTrip.addData(200, 47.20); + longDistanceTrip.addData(300, 59.70); + longDistanceTrip.addData(400, 71.70); + longDistanceTrip.addData(500, 83.00); + longDistanceTrip.addData(600, 94.60); + longDistanceTrip.addData(700, 106.30); + longDistanceTrip.addData(800, 118.20); + longDistanceTrip.addData(900, 130.10); + longDistanceTrip.addData(1000, 141.00); + longDistanceTrip.addData(1100, 148.60); + longDistanceTrip.addData(1200, 158.10); + longDistanceTrip.addData(1300, 169.20); + longDistanceTrip.addData(1400, 179.80); + longDistanceTrip.addData(1500, 190.10); + longDistanceTrip.addData(1600, 201.50); + longDistanceTrip.addData(1700, 212.80); + longDistanceTrip.addData(1800, 223.30); + longDistanceTrip.addData(1900, 233.90); + longDistanceTrip.addData(2000, 244.00); + + var params = new DistanceBasedPtFareParams(); + params.setNormalTripSlope(normalDistanceTrip.getSlope()); + params.setNormalTripIntercept(normalDistanceTrip.getIntercept()); + params.setLongDistanceTripSlope(longDistanceTrip.getSlope()); + params.setLongDistanceTripIntercept(longDistanceTrip.getIntercept()); + params.setLongDistanceTripThreshold(100_000.); + params.setTransactionPartner("Deutschlandtarif"); + params.setMinFare(MIN_FARE); + + return params; + } } diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculator.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculator.java index feda2b3a950..a676137b487 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculator.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculator.java @@ -6,12 +6,17 @@ import org.matsim.application.options.ShpOptions; import org.matsim.core.utils.geometry.geotools.MGC; -import java.util.List; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; +/** + * This class calculates the fare for a public transport trip based on the fare zone the origin and destination are in. + */ public class FareZoneBasedPtFareCalculator implements PtFareCalculator { private final ShpOptions shp; private final String transactionPartner; + private final Map> zoneByCoordCache = new HashMap<>(); public static final String FARE = "fare"; @@ -22,8 +27,8 @@ public FareZoneBasedPtFareCalculator(FareZoneBasedPtFareParams params) { @Override public Optional calculateFare(Coord from, Coord to) { - Optional departureZone = determineFareZone(from, shp.readFeatures()); - Optional arrivalZone = determineFareZone(to, shp.readFeatures()); + Optional departureZone = zoneByCoordCache.computeIfAbsent(from, this::determineFareZone); + Optional arrivalZone = zoneByCoordCache.computeIfAbsent(to, this::determineFareZone); //if one of the zones is empty, it is not included in the shape file, so this calculator cannot compute the fare if (departureZone.isEmpty() || arrivalZone.isEmpty()) { @@ -38,7 +43,7 @@ public Optional calculateFare(Coord from, Coord to) { return Optional.of(new FareResult(fare, transactionPartner)); } - Optional determineFareZone(Coord coord, List features) { - return features.stream().filter(f -> MGC.coord2Point(coord).within((Geometry) f.getDefaultGeometry())).findFirst(); + Optional determineFareZone(Coord coord) { + return shp.readFeatures().stream().filter(f -> MGC.coord2Point(coord).within((Geometry) f.getDefaultGeometry())).findFirst(); } } diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareParams.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareParams.java index d869f18eaa7..f213f32dbb0 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareParams.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareParams.java @@ -1,33 +1,9 @@ package playground.vsp.pt.fare; -import java.util.Map; - public class FareZoneBasedPtFareParams extends PtFareParams { public static final String SET_NAME = "ptFareCalculationFareZoneBased"; - public static final String COST = "cost"; - - private Double cost; - public FareZoneBasedPtFareParams() { super(SET_NAME); } - - @Override - public Map getComments() { - Map map = super.getComments(); - map.put(COST, "Cost of a trip within the fare zone."); - return map; - } - - @StringGetter(COST) - public Double getCost() { - return cost; - } - - @StringSetter(COST) - public void setCost(Double cost) { - this.cost = cost; - } - //TODO check consistency } diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java index b629bbf9eb5..1093e607db3 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java @@ -1,9 +1,11 @@ package playground.vsp.pt.fare; import jakarta.validation.constraints.PositiveOrZero; +import org.matsim.core.config.Config; import org.matsim.core.config.ReflectiveConfigGroup; import java.util.Map; +import java.util.stream.Stream; public class PtFareConfigGroup extends ReflectiveConfigGroup { public static final String PT_FARE = "pt fare"; @@ -57,4 +59,25 @@ public double getUpperBoundFactor() { public void setUpperBoundFactor(double upperBoundFactor) { this.upperBoundFactor = upperBoundFactor; } + + @Override + protected void checkConsistency(Config config) { + super.checkConsistency(config); + + var distanceBasedParameterSets = getParameterSets(DistanceBasedPtFareParams.SET_NAME); + var fareZoneBasedParameterSets = getParameterSets(FareZoneBasedPtFareParams.SET_NAME); + + if (distanceBasedParameterSets.isEmpty() && fareZoneBasedParameterSets.isEmpty()) { + throw new IllegalArgumentException("No parameter sets found for pt fare calculation. Please add at least one parameter set."); + } + + long distinctPriorities = Stream.concat(distanceBasedParameterSets.stream(), fareZoneBasedParameterSets.stream()) + .map(PtFareParams.class::cast) + .map(PtFareParams::getPriority) + .distinct().count(); + + if (distinctPriorities != distanceBasedParameterSets.size() + fareZoneBasedParameterSets.size()) { + throw new IllegalArgumentException("Duplicate priorities found in parameter sets. Please make sure that priorities are unique."); + } + } } diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java index 9c0ee97efc2..7974d9b0516 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java @@ -14,8 +14,6 @@ public class PtFareModule extends AbstractModule { @Override public void install() { - //TODO check consistency: order unique, cost set - getConfig().scoring().getModes().get(TransportMode.pt).setDailyMonetaryConstant(0); getConfig().scoring().getModes().get(TransportMode.pt).setMarginalUtilityOfDistance(0); Multibinder ptFareCalculator = Multibinder.newSetBinder(binder(), PtFareCalculator.class); diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java index 5795934440e..90ec2339fa4 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java @@ -29,14 +29,22 @@ public class PtTripWithDistanceBasedFareEstimator extends PtTripEstimator { private final Map, TransitStopFacility> facilities; @Inject - public PtTripWithDistanceBasedFareEstimator(TransitSchedule transitSchedule, PtFareConfigGroup config, DistanceBasedPtFareParams ptFare, + public PtTripWithDistanceBasedFareEstimator(TransitSchedule transitSchedule, PtFareConfigGroup config, Scenario scenario) { super(transitSchedule); this.config = config; - this.ptFare = ptFare; + this.ptFare = extractPtFare(config); this.facilities = scenario.getTransitSchedule().getFacilities(); } + private static DistanceBasedPtFareParams extractPtFare(PtFareConfigGroup config) { + //TODO + return config.getParameterSets(DistanceBasedPtFareParams.SET_NAME).stream() + .map(DistanceBasedPtFareParams.class::cast) + .findFirst() + .orElseThrow(() -> new IllegalStateException("No distance based fare parameters found")); + } + @Override public MinMaxEstimate estimate(EstimatorContext context, String mode, PlanModel plan, List trip, ModeAvailability option) { diff --git a/contribs/vsp/src/test/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java b/contribs/vsp/src/test/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java new file mode 100644 index 00000000000..005b7f3f80d --- /dev/null +++ b/contribs/vsp/src/test/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java @@ -0,0 +1,76 @@ +package playground.vsp.pt.fare; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Coord; +import org.matsim.core.utils.geometry.CoordUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; + +import java.net.URL; +import java.util.Optional; + +class DistanceBasedPtFareCalculatorTest { + private static final String TRANSACTION_PARTNER = "TP"; + + @Test + void testNormalDistance() { + //100m -> 1.1 EUR + calculateAndCheck(null, new Coord(0, 0), new Coord(0, 100), 1.1); + } + + @Test + void testLongDistance() { + //3000m -> 4.5 EUR + calculateAndCheck(null, new Coord(0, 0), new Coord(0, 3000), 4.5); + } + + @Test + void testThreshold() { + //2000m -> 3.0 EUR + calculateAndCheck(null, new Coord(0, 0), new Coord(0, 2000), 3.0); + } + + @Test + void testNotInShapeFile() { + URL context = ExamplesUtils.getTestScenarioURL("kelheim"); + String shape = IOUtils.extendUrl(context, "ptTestArea/pt-area.shp").toString(); + Coord a = new Coord(726634.40, 5433508.07); + Coord b = new Coord(736634.40, 5533508.07); + DistanceBasedPtFareCalculator calculator = getCalculator(shape); + Assertions.assertEquals(Optional.empty(), calculator.calculateFare(a, b)); + } + + @Test + void testInShapeFile() { + URL context = ExamplesUtils.getTestScenarioURL("kelheim"); + String shape = IOUtils.extendUrl(context, "ptTestArea/pt-area.shp").toString(); + Coord a = new Coord(710300.624, 5422165.737); + Coord b = new Coord(714940.65, 5420707.78); + double distance = CoordUtils.calcEuclideanDistance(a, b); + calculateAndCheck(shape, a, b, distance * 0.0005 + 3.); + } + + private void calculateAndCheck(String shape, Coord a, Coord b, double fare) { + DistanceBasedPtFareCalculator distanceBasedPtFareCalculator = getCalculator(shape); + PtFareCalculator.FareResult fareResult = distanceBasedPtFareCalculator.calculateFare(a, b).orElseThrow(); + Assertions.assertEquals(new PtFareCalculator.FareResult(fare, TRANSACTION_PARTNER), fareResult); + } + + private DistanceBasedPtFareCalculator getCalculator(String shapeFile) { + var params = new DistanceBasedPtFareParams(); + params.setTransactionPartner(TRANSACTION_PARTNER); + //0-2000m: 1EUR + 1EUR/km + params.setNormalTripIntercept(1.0); + params.setNormalTripSlope(0.001); + + //2000m+: 3EUR + 0.5EUR/km + params.setLongDistanceTripThreshold(2000.); + params.setLongDistanceTripIntercept(3.); + params.setLongDistanceTripSlope(0.0005); + + params.setMinFare(1.0); + params.setFareZoneShp(shapeFile); + return new DistanceBasedPtFareCalculator(params); + } +} diff --git a/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java b/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java new file mode 100644 index 00000000000..ac3eda11b5a --- /dev/null +++ b/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java @@ -0,0 +1,57 @@ +package playground.vsp.pt.fare; + +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Coord; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; + +import java.net.URL; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class FareZoneBasedPtFareCalculatorTest { + private static final double COST_IN_SHP_FILE = 1.5; + private static final String TRANSACTION_PARTNER = "TP"; + + @Test + void testCalculateFareInShape() { + FareZoneBasedPtFareCalculator fareZoneBasedPtFareCalculator = new FareZoneBasedPtFareCalculator(getParams()); + + Coord inShape = new Coord(710300.624, 5422165.737); + Coord inShape2 = new Coord(714940.65, 5420707.78); + + assertEquals(Optional.of(new PtFareCalculator.FareResult(COST_IN_SHP_FILE, TRANSACTION_PARTNER)), + fareZoneBasedPtFareCalculator.calculateFare(inShape, + inShape2)); + assertEquals(Optional.of(new PtFareCalculator.FareResult(COST_IN_SHP_FILE, TRANSACTION_PARTNER)), + fareZoneBasedPtFareCalculator.calculateFare(inShape2, + inShape)); + } + + @Test + void testCalculateFareOutShape() { + FareZoneBasedPtFareCalculator fareZoneBasedPtFareCalculator = new FareZoneBasedPtFareCalculator(getParams()); + + Coord inShape = new Coord(710300.624, 5422165.737); + Coord inShape2 = new Coord(714940.65, 5420707.78); + Coord outShape = new Coord(726634.40, 5433508.07); + Coord outShape2 = new Coord(736634.40, 5533508.07); + + assertEquals(Optional.empty(), fareZoneBasedPtFareCalculator.calculateFare(inShape, outShape)); + assertEquals(Optional.empty(), fareZoneBasedPtFareCalculator.calculateFare(inShape, outShape2)); + assertEquals(Optional.empty(), fareZoneBasedPtFareCalculator.calculateFare(inShape2, outShape)); + assertEquals(Optional.empty(), fareZoneBasedPtFareCalculator.calculateFare(inShape2, outShape)); + assertEquals(Optional.empty(), fareZoneBasedPtFareCalculator.calculateFare(outShape, outShape2)); + } + + private FareZoneBasedPtFareParams getParams() { + URL context = ExamplesUtils.getTestScenarioURL("kelheim"); + + FareZoneBasedPtFareParams fareZoneBasedPtFareParams = new FareZoneBasedPtFareParams(); + fareZoneBasedPtFareParams.setFareZoneShp(IOUtils.extendUrl(context, "ptTestArea/pt-area.shp").toString()); + fareZoneBasedPtFareParams.setTransactionPartner(TRANSACTION_PARTNER); + return fareZoneBasedPtFareParams; + } + +} diff --git a/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java b/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java index a894bb44141..38cb81e4a11 100644 --- a/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java @@ -49,7 +49,6 @@ void testFareZoneBasedPtFareHandler() { PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(config, PtFareConfigGroup.class); FareZoneBasedPtFareParams fareZoneBased = new FareZoneBasedPtFareParams(); - fareZoneBased.setCost(2.5); fareZoneBased.setDescription("simple fare zone based"); fareZoneBased.setFareZoneShp(IOUtils.extendUrl(context, "ptTestArea/pt-area.shp").toString()); fareZoneBased.setPriority(10); diff --git a/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtFareConfigGroupTest.java b/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtFareConfigGroupTest.java new file mode 100644 index 00000000000..7af7058648f --- /dev/null +++ b/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtFareConfigGroupTest.java @@ -0,0 +1,45 @@ +package playground.vsp.pt.fare; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; + +class PtFareConfigGroupTest { + @Test + void testNoFareParams_throws() { + Config config = ConfigUtils.createConfig(); + PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(config, PtFareConfigGroup.class); + Assertions.assertThrows(IllegalArgumentException.class, () -> ptFareConfigGroup.checkConsistency(config)); + } + + @Test + void testSamePriority_throws() { + Config config = ConfigUtils.createConfig(); + PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(config, PtFareConfigGroup.class); + FareZoneBasedPtFareParams fareZoneBased = new FareZoneBasedPtFareParams(); + fareZoneBased.setPriority(5); + ptFareConfigGroup.addParameterSet(fareZoneBased); + + DistanceBasedPtFareParams distanceBased = new DistanceBasedPtFareParams(); + distanceBased.setPriority(5); + ptFareConfigGroup.addParameterSet(distanceBased); + + Assertions.assertThrows(IllegalArgumentException.class, () -> ptFareConfigGroup.checkConsistency(config)); + } + + @Test + void test_ok() { + Config config = ConfigUtils.createConfig(); + PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(config, PtFareConfigGroup.class); + FareZoneBasedPtFareParams fareZoneBased = new FareZoneBasedPtFareParams(); + fareZoneBased.setPriority(5); + ptFareConfigGroup.addParameterSet(fareZoneBased); + + DistanceBasedPtFareParams distanceBased = new DistanceBasedPtFareParams(); + distanceBased.setPriority(10); + ptFareConfigGroup.addParameterSet(distanceBased); + + ptFareConfigGroup.checkConsistency(config); + } +} diff --git a/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtTripFareEstimatorTest.java b/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtTripFareEstimatorTest.java index 6ddfef69d44..557b8fbdfd6 100644 --- a/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtTripFareEstimatorTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtTripFareEstimatorTest.java @@ -60,7 +60,7 @@ public void setUp() throws Exception { group = ConfigUtils.addOrGetModule(config, InformedModeChoiceConfigGroup.class); PtFareConfigGroup fare = ConfigUtils.addOrGetModule(config, PtFareConfigGroup.class); - DistanceBasedPtFareParams distanceFare = ConfigUtils.addOrGetModule(config, DistanceBasedPtFareParams.class); + DistanceBasedPtFareParams distanceFare = new DistanceBasedPtFareParams(); fare.setApplyUpperBound(true); fare.setUpperBoundFactor(1.5); @@ -73,6 +73,8 @@ public void setUp() throws Exception { distanceFare.setLongDistanceTripIntercept(1); distanceFare.setLongDistanceTripSlope(0.01); + fare.addParameterSet(distanceFare); + controler = MATSimApplication.prepare(TestScenario.class, config); injector = controler.getInjector(); @@ -98,8 +100,9 @@ private List estimateAgent(Id personId) { List trip = model.getLegs(TransportMode.pt, i); - if (trip == null) + if (trip == null) { continue; + } MinMaxEstimate est = estimator.estimate(context, TransportMode.pt, model, trip, ModeAvailability.YES); @@ -116,9 +119,9 @@ void fare() { System.out.println(est); assertThat(est) - .allMatch(e -> e.getMin() < e.getMax(), "Min smaller max") - .first().extracting(MinMaxEstimate::getMin, InstanceOfAssertFactories.DOUBLE) - .isCloseTo(-379.4, Offset.offset(0.1)); + .allMatch(e -> e.getMin() < e.getMax(), "Min smaller max") + .first().extracting(MinMaxEstimate::getMin, InstanceOfAssertFactories.DOUBLE) + .isCloseTo(-379.4, Offset.offset(0.1)); } @@ -129,7 +132,7 @@ void all() { List est = estimateAgent(agent); assertThat(est) - .allMatch(e -> e.getMin() <= e.getMax(), "Min smaller max"); + .allMatch(e -> e.getMin() <= e.getMax(), "Min smaller max"); } } @@ -157,22 +160,22 @@ void planEstimate() { double estimate = estimator.estimate(context, TransportMode.pt, new String[]{"pt", "car", "pt", "pt", "pt"}, model, ModeAvailability.YES); assertThat(estimate) - .isLessThanOrEqualTo(maxSum) - .isGreaterThanOrEqualTo(minSum) - .isCloseTo(-2738.72, Offset.offset(0.1)); + .isLessThanOrEqualTo(maxSum) + .isGreaterThanOrEqualTo(minSum) + .isCloseTo(-2738.72, Offset.offset(0.1)); estimate = estimator.estimate(context, TransportMode.pt, new String[]{"pt", "car", "car", "car", "pt"}, model, ModeAvailability.YES); assertThat(estimate) - .isLessThanOrEqualTo(maxSum) - .isGreaterThanOrEqualTo(minSum) - .isCloseTo(-1222.91, Offset.offset(0.1)); + .isLessThanOrEqualTo(maxSum) + .isGreaterThanOrEqualTo(minSum) + .isCloseTo(-1222.91, Offset.offset(0.1)); // Essentially single trip estimate = estimator.estimate(context, TransportMode.pt, new String[]{"pt", "car", "car", "car", "car"}, model, ModeAvailability.YES); assertThat(estimate) - .isCloseTo(singleTrips.get(0).getMin(), Offset.offset(0.1)); + .isCloseTo(singleTrips.get(0).getMin(), Offset.offset(0.1)); } } From 417a83bf42d3d21ac6cf1fb8714f00f59bf8f670 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Fri, 16 Aug 2024 14:11:11 +0200 Subject: [PATCH 062/111] implemented integration test --- .../vsp/pt/fare/PtFareConfigGroup.java | 15 +-- .../playground/vsp/pt/fare/PtFareModule.java | 2 +- .../playground/vsp/pt/fare/PtFareParams.java | 18 +-- .../fare/FareZoneBasedPtFareHandlerTest.java | 115 ++++++++++-------- .../vsp/pt/fare/PtFareConfigGroupTest.java | 8 +- 5 files changed, 85 insertions(+), 73 deletions(-) diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java index 1093e607db3..e4a72423fb2 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java @@ -52,9 +52,6 @@ public double getUpperBoundFactor() { return upperBoundFactor; } - /** - * @param upperBoundFactor -- {@value #UPPER_BOUND_FACTOR_CMT} - */ @StringSetter(UPPER_BOUND_FACTOR) public void setUpperBoundFactor(double upperBoundFactor) { this.upperBoundFactor = upperBoundFactor; @@ -71,13 +68,13 @@ protected void checkConsistency(Config config) { throw new IllegalArgumentException("No parameter sets found for pt fare calculation. Please add at least one parameter set."); } - long distinctPriorities = Stream.concat(distanceBasedParameterSets.stream(), fareZoneBasedParameterSets.stream()) - .map(PtFareParams.class::cast) - .map(PtFareParams::getPriority) - .distinct().count(); + long distinctOrders = Stream.concat(distanceBasedParameterSets.stream(), fareZoneBasedParameterSets.stream()) + .map(PtFareParams.class::cast) + .map(PtFareParams::getOrder) + .distinct().count(); - if (distinctPriorities != distanceBasedParameterSets.size() + fareZoneBasedParameterSets.size()) { - throw new IllegalArgumentException("Duplicate priorities found in parameter sets. Please make sure that priorities are unique."); + if (distinctOrders != distanceBasedParameterSets.size() + fareZoneBasedParameterSets.size()) { + throw new IllegalArgumentException("Duplicate order values found in parameter sets. Please make sure that order values are unique."); } } } diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java index 7974d9b0516..c9f327a6cec 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java @@ -24,7 +24,7 @@ public void install() { Stream.concat(fareZoneBased.stream(), distanceBased.stream()) .map(c -> (PtFareParams) c) - .sorted(Comparator.comparing(PtFareParams::getPriority).reversed()) + .sorted(Comparator.comparing(PtFareParams::getOrder)) .forEach(p -> { if (p instanceof FareZoneBasedPtFareParams fareZoneBasedPtFareParams) { ptFareCalculator.addBinding().toInstance(new FareZoneBasedPtFareCalculator(fareZoneBasedPtFareParams)); diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareParams.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareParams.java index ece2641d9ad..56e96fb49c2 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareParams.java +++ b/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareParams.java @@ -6,11 +6,11 @@ public abstract class PtFareParams extends ReflectiveConfigGroup { public static final String FARE_ZONE_SHP = "fareZoneShp"; - public static final String PRIORITY = "priority"; + public static final String ORDER = "order"; public static final String TRANSACTION_PARTNER = "transactionPartner"; public static final String DESCRIPTION = "description"; - private int priority; + private int order; private String fareZoneShp; private String transactionPartner; private String description; @@ -23,7 +23,7 @@ public PtFareParams(String name) { public Map getComments() { var map = super.getComments(); map.put(FARE_ZONE_SHP, "Shp file with fare zone(s). This parameter is only used for PtFareCalculationModel 'fareZoneBased'."); - map.put(PRIORITY, "Priority of this fare calculation in the list of fare calculations. Higher values mean to be evaluated first."); + map.put(ORDER, "Order of this fare calculation in the list of fare calculations. Lower values mean to be evaluated first."); map.put(TRANSACTION_PARTNER, "The transaction partner for the fare calculation. This is used in the PersonMoneyEvent."); map.put(DESCRIPTION, "Description of the fare zone."); return map; @@ -39,14 +39,14 @@ public void setFareZoneShp(String fareZoneShp) { this.fareZoneShp = fareZoneShp; } - @StringGetter(PRIORITY) - public int getPriority() { - return priority; + @StringGetter(ORDER) + public int getOrder() { + return order; } - @StringSetter(PRIORITY) - public void setPriority(int priority) { - this.priority = priority; + @StringSetter(ORDER) + public void setOrder(int order) { + this.order = order; } @StringGetter(TRANSACTION_PARTNER) diff --git a/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java b/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java index 38cb81e4a11..9d76e3ea13b 100644 --- a/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java @@ -1,12 +1,14 @@ package playground.vsp.pt.fare; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import org.matsim.analysis.personMoney.PersonMoneyEventsAnalysisModule; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.events.PersonMoneyEvent; +import org.matsim.api.core.v01.events.handler.PersonMoneyEventHandler; import org.matsim.api.core.v01.population.*; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; @@ -20,57 +22,70 @@ import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; -import java.io.BufferedReader; -import java.io.IOException; import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.ArrayList; import java.util.List; -import static org.matsim.application.ApplicationUtils.globFile; - public class FareZoneBasedPtFareHandlerTest { + private final static String FARE_ZONE_TRANSACTION_PARTNER = "fare zone transaction partner"; + private final static String DISTANCE_BASED_TRANSACTION_PARTNER = "distance based transaction partner"; + @RegisterExtension private MatsimTestUtils utils = new MatsimTestUtils(); @Test void testFareZoneBasedPtFareHandler() { - final String FARE_ZONE_TRANSACTION_PARTNER = "fare zone transaction partner"; - final String DISTANCE_BASED_TRANSACTION_PARTNER = "distance based transaction partner"; - - URL context = ExamplesUtils.getTestScenarioURL("kelheim"); - Config config = ConfigUtils.loadConfig(IOUtils.extendUrl(context, "config.xml")); - config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); - config.controller().setOutputDirectory(utils.getOutputDirectory()); - config.controller().setLastIteration(0); + //Prepare + Config config = getConfig(); + //adapt pt fare PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(config, PtFareConfigGroup.class); FareZoneBasedPtFareParams fareZoneBased = new FareZoneBasedPtFareParams(); fareZoneBased.setDescription("simple fare zone based"); - fareZoneBased.setFareZoneShp(IOUtils.extendUrl(context, "ptTestArea/pt-area.shp").toString()); - fareZoneBased.setPriority(10); + fareZoneBased.setFareZoneShp(IOUtils.extendUrl(config.getContext(), "ptTestArea/pt-area.shp").toString()); + fareZoneBased.setOrder(1); fareZoneBased.setTransactionPartner(FARE_ZONE_TRANSACTION_PARTNER); DistanceBasedPtFareParams distanceBased = new DistanceBasedPtFareParams(); - distanceBased.setPriority(5); + distanceBased.setOrder(2); distanceBased.setTransactionPartner(DISTANCE_BASED_TRANSACTION_PARTNER); ptFareConfigGroup.addParameterSet(fareZoneBased); ptFareConfigGroup.addParameterSet(distanceBased); - ScoringConfigGroup scoring = ConfigUtils.addOrGetModule(config, ScoringConfigGroup.class); + MutableScenario scenario = setUpScenario(config); - ScoringConfigGroup.ActivityParams homeParams = new ScoringConfigGroup.ActivityParams("home"); - ScoringConfigGroup.ActivityParams workParams = new ScoringConfigGroup.ActivityParams("work"); - homeParams.setTypicalDuration(8 * 3600.); - workParams.setTypicalDuration(8 * 3600.); - scoring.addActivityParams(homeParams); - scoring.addActivityParams(workParams); + //Run + var fareAnalysis = new FareAnalysis(); + + Controler controler = new Controler(scenario); + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new PtFareModule()); + addEventHandlerBinding().toInstance(fareAnalysis); + } + }); + controler.run(); + + //Check + List events = fareAnalysis.getEvents(); + Assertions.assertEquals(2, events.size()); + + final String FARE_TEST_PERSON = "fareTestPerson"; + //first event is the fare zone based event + Assertions.assertEquals(new PersonMoneyEvent(33264, Id.createPersonId(FARE_TEST_PERSON), -1.5, "pt fare", FARE_ZONE_TRANSACTION_PARTNER, + FARE_TEST_PERSON), events.get(0)); + //second event is the distance based event + Assertions.assertEquals(new PersonMoneyEvent(52056, Id.createPersonId(FARE_TEST_PERSON), -4.526183060514956, "pt fare", + DISTANCE_BASED_TRANSACTION_PARTNER, FARE_TEST_PERSON), events.get(1)); + } + + private @NotNull MutableScenario setUpScenario(Config config) { MutableScenario scenario = (MutableScenario) ScenarioUtils.loadScenario(config); Population population = ScenarioUtils.createScenario(ConfigUtils.createConfig()).getPopulation(); @@ -98,37 +113,37 @@ void testFareZoneBasedPtFareHandler() { person.addPlan(plan); population.addPerson(person); scenario.setPopulation(population); + return scenario; + } - Controler controler = new Controler(scenario); - controler.addOverridingModule(new AbstractModule() { - @Override - public void install() { - install(new PtFareModule()); - install(new PersonMoneyEventsAnalysisModule()); - } - }); - controler.run(); + private @NotNull Config getConfig() { + URL context = ExamplesUtils.getTestScenarioURL("kelheim"); + Config config = ConfigUtils.loadConfig(IOUtils.extendUrl(context, "config.xml")); + config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + config.controller().setLastIteration(0); - Assertions.assertTrue(Files.exists(Path.of(utils.getOutputDirectory()))); + ScoringConfigGroup scoring = ConfigUtils.addOrGetModule(config, ScoringConfigGroup.class); -// read personMoneyEvents.tsv and check if both fare entries do have the correct fare type - String filePath = globFile(Path.of(utils.getOutputDirectory()), "*output_personMoneyEvents.tsv*").toString(); - String line; - List events = new ArrayList<>(); + ScoringConfigGroup.ActivityParams homeParams = new ScoringConfigGroup.ActivityParams("home"); + ScoringConfigGroup.ActivityParams workParams = new ScoringConfigGroup.ActivityParams("work"); + homeParams.setTypicalDuration(8 * 3600.); + workParams.setTypicalDuration(8 * 3600.); + scoring.addActivityParams(homeParams); + scoring.addActivityParams(workParams); + return config; + } - try (BufferedReader br = IOUtils.getBufferedReader(filePath)) { -// skip header - br.readLine(); + private static class FareAnalysis implements PersonMoneyEventHandler { + private final List events = new ArrayList<>(); - while ((line = br.readLine()) != null) { - events.add(line.split(";")); - } - } catch (IOException e) { - e.printStackTrace(); + @Override + public void handleEvent(PersonMoneyEvent event) { + events.add(event); } - Assertions.assertEquals(2, events.size()); - Assertions.assertEquals(FARE_ZONE_TRANSACTION_PARTNER, events.get(0)[4]); - Assertions.assertEquals(DISTANCE_BASED_TRANSACTION_PARTNER, events.get(1)[4]); + public List getEvents() { + return events; + } } } diff --git a/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtFareConfigGroupTest.java b/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtFareConfigGroupTest.java index 7af7058648f..adec9b3aa6b 100644 --- a/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtFareConfigGroupTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtFareConfigGroupTest.java @@ -18,11 +18,11 @@ void testSamePriority_throws() { Config config = ConfigUtils.createConfig(); PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(config, PtFareConfigGroup.class); FareZoneBasedPtFareParams fareZoneBased = new FareZoneBasedPtFareParams(); - fareZoneBased.setPriority(5); + fareZoneBased.setOrder(5); ptFareConfigGroup.addParameterSet(fareZoneBased); DistanceBasedPtFareParams distanceBased = new DistanceBasedPtFareParams(); - distanceBased.setPriority(5); + distanceBased.setOrder(5); ptFareConfigGroup.addParameterSet(distanceBased); Assertions.assertThrows(IllegalArgumentException.class, () -> ptFareConfigGroup.checkConsistency(config)); @@ -33,11 +33,11 @@ void test_ok() { Config config = ConfigUtils.createConfig(); PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(config, PtFareConfigGroup.class); FareZoneBasedPtFareParams fareZoneBased = new FareZoneBasedPtFareParams(); - fareZoneBased.setPriority(5); + fareZoneBased.setOrder(5); ptFareConfigGroup.addParameterSet(fareZoneBased); DistanceBasedPtFareParams distanceBased = new DistanceBasedPtFareParams(); - distanceBased.setPriority(10); + distanceBased.setOrder(10); ptFareConfigGroup.addParameterSet(distanceBased); ptFareConfigGroup.checkConsistency(config); From 4c66b9072f33a34e60fd2fb5b544671e2e6f3d46 Mon Sep 17 00:00:00 2001 From: vsp-gleich Date: Fri, 16 Aug 2024 19:43:37 +0200 Subject: [PATCH 063/111] Pt distance class fares (#3413) * allow for distance based pt fares by distance class * move to contrib.vsp --- .../vsp/pt/fare/ChainedPtFareCalculator.java | 2 +- .../vsp/pt/fare/ChainedPtFareHandler.java | 2 +- .../fare/DistanceBasedPtFareCalculator.java | 31 ++- .../pt/fare/DistanceBasedPtFareParams.java | 210 ++++++++++++++++++ .../fare/FareZoneBasedPtFareCalculator.java | 2 +- .../pt/fare/FareZoneBasedPtFareParams.java | 2 +- .../vsp/pt/fare/PtFareCalculator.java | 2 +- .../vsp/pt/fare/PtFareConfigGroup.java | 2 +- .../contrib}/vsp/pt/fare/PtFareHandler.java | 2 +- .../contrib}/vsp/pt/fare/PtFareModule.java | 2 +- .../contrib}/vsp/pt/fare/PtFareParams.java | 2 +- .../vsp/pt/fare/PtFareUpperBoundHandler.java | 3 +- .../PtTripWithDistanceBasedFareEstimator.java | 13 +- .../pt/fare/DistanceBasedPtFareParams.java | 187 ---------------- .../DistanceBasedPtFareCalculatorTest.java | 15 +- .../FareZoneBasedPtFareCalculatorTest.java | 2 +- .../fare/FareZoneBasedPtFareHandlerTest.java | 7 +- .../vsp/pt/fare/PtFareConfigGroupTest.java | 2 +- .../vsp/pt/fare/PtTripFareEstimatorTest.java | 17 +- .../java/playground/vsp/TestScenario.java | 2 +- 20 files changed, 265 insertions(+), 242 deletions(-) rename contribs/vsp/src/main/java/{playground => org/matsim/contrib}/vsp/pt/fare/ChainedPtFareCalculator.java (96%) rename contribs/vsp/src/main/java/{playground => org/matsim/contrib}/vsp/pt/fare/ChainedPtFareHandler.java (98%) rename contribs/vsp/src/main/java/{playground => org/matsim/contrib}/vsp/pt/fare/DistanceBasedPtFareCalculator.java (68%) create mode 100644 contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java rename contribs/vsp/src/main/java/{playground => org/matsim/contrib}/vsp/pt/fare/FareZoneBasedPtFareCalculator.java (97%) rename contribs/vsp/src/main/java/{playground => org/matsim/contrib}/vsp/pt/fare/FareZoneBasedPtFareParams.java (83%) rename contribs/vsp/src/main/java/{playground => org/matsim/contrib}/vsp/pt/fare/PtFareCalculator.java (85%) rename contribs/vsp/src/main/java/{playground => org/matsim/contrib}/vsp/pt/fare/PtFareConfigGroup.java (98%) rename contribs/vsp/src/main/java/{playground => org/matsim/contrib}/vsp/pt/fare/PtFareHandler.java (88%) rename contribs/vsp/src/main/java/{playground => org/matsim/contrib}/vsp/pt/fare/PtFareModule.java (98%) rename contribs/vsp/src/main/java/{playground => org/matsim/contrib}/vsp/pt/fare/PtFareParams.java (97%) rename contribs/vsp/src/main/java/{playground => org/matsim/contrib}/vsp/pt/fare/PtFareUpperBoundHandler.java (98%) rename contribs/vsp/src/main/java/{playground => org/matsim/contrib}/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java (91%) delete mode 100644 contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java rename contribs/vsp/src/test/java/{playground => org/matsim/contrib}/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java (80%) rename contribs/vsp/src/test/java/{playground => org/matsim/contrib}/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java (98%) rename contribs/vsp/src/test/java/{playground => org/matsim/contrib}/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java (94%) rename contribs/vsp/src/test/java/{playground => org/matsim/contrib}/vsp/pt/fare/PtFareConfigGroupTest.java (97%) rename contribs/vsp/src/test/java/{playground => org/matsim/contrib}/vsp/pt/fare/PtTripFareEstimatorTest.java (90%) diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareCalculator.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareCalculator.java similarity index 96% rename from contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareCalculator.java rename to contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareCalculator.java index bd38fc3237b..1e95a8b909f 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareCalculator.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareCalculator.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import com.google.inject.Inject; import org.matsim.api.core.v01.Coord; diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareHandler.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareHandler.java similarity index 98% rename from contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareHandler.java rename to contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareHandler.java index cc5963e6345..fef87f65ba3 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/ChainedPtFareHandler.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareHandler.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import com.google.inject.Inject; import org.matsim.api.core.v01.Coord; diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculator.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculator.java similarity index 68% rename from contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculator.java rename to contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculator.java index 3708bf7acce..74c1d13b9b5 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculator.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculator.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -11,6 +11,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.SortedMap; /** * This class calculates the fare for a public transport trip based on the distance between the origin and destination. If a shape file is @@ -21,11 +22,7 @@ public class DistanceBasedPtFareCalculator implements PtFareCalculator { private static final Logger log = LogManager.getLogger(DistanceBasedPtFareCalculator.class); private final double minFare; - private final double shortTripIntercept; - private final double shortTripSlope; - private final double longTripIntercept; - private final double longTripSlope; - private final double longTripThreshold; + private final SortedMap distanceClassFareParams; private ShpOptions shp = null; private final String transactionPartner; @@ -33,11 +30,7 @@ public class DistanceBasedPtFareCalculator implements PtFareCalculator { public DistanceBasedPtFareCalculator(DistanceBasedPtFareParams params) { this.minFare = params.getMinFare(); - this.shortTripIntercept = params.getNormalTripIntercept(); - this.shortTripSlope = params.getNormalTripSlope(); - this.longTripIntercept = params.getLongDistanceTripIntercept(); - this.longTripSlope = params.getLongDistanceTripSlope(); - this.longTripThreshold = params.getLongDistanceTripThreshold(); + this.distanceClassFareParams = params.getDistanceClassFareParams(); this.transactionPartner = params.getTransactionPartner(); if (params.getFareZoneShp() != null) { @@ -58,7 +51,7 @@ public Optional calculateFare(Coord from, Coord to) { double distance = CoordUtils.calcEuclideanDistance(from, to); - double fare = computeFare(distance, longTripThreshold, minFare, shortTripIntercept, shortTripSlope, longTripIntercept, longTripSlope); + double fare = computeFare(distance, minFare, distanceClassFareParams); return Optional.of(new FareResult(fare, transactionPartner)); } @@ -73,12 +66,14 @@ private boolean inShape(Coord coord) { return shp.readFeatures().stream().anyMatch(f -> MGC.coord2Point(coord).within((Geometry) f.getDefaultGeometry())); } - public static double computeFare(double distance, double longTripThreshold, double minFare, double shortTripIntercept, double shortTripSlope, - double longTripIntercept, double longTripSlope) { - if (distance <= longTripThreshold) { - return Math.max(minFare, shortTripIntercept + shortTripSlope * distance); - } else { - return Math.max(minFare, longTripIntercept + longTripSlope * distance); + public static double computeFare(double distance, double minFare, + SortedMap distanceClassFareParams) { + for (DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClassFareParam : distanceClassFareParams.values()) { + if (distance <= distanceClassFareParam.getMaxDistance()) { + return Math.max(minFare, distance * distanceClassFareParam.getFareSlope() + distanceClassFareParam.getFareIntercept()); + } } + log.error("No fare found for distance of " + distance + " meters."); + throw new RuntimeException("No fare found for distance of " + distance + " meters."); } } diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java new file mode 100644 index 00000000000..e84a9e88abb --- /dev/null +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java @@ -0,0 +1,210 @@ +package org.matsim.contrib.vsp.pt.fare; + +import jakarta.validation.constraints.PositiveOrZero; +import org.apache.commons.math.stat.regression.SimpleRegression; +import org.matsim.core.config.ReflectiveConfigGroup; + +import java.util.*; + +/** + * @author Chengqi Lu (luchengqi7) + * The parameters for the distance-based PT trip fare calculation. + * The default values are set based on the fitting results of the trip and fare data collected on September 2021 + * The values are based on the standard unit of meter (m) and Euro (EUR) + */ +public class DistanceBasedPtFareParams extends PtFareParams { + public static final DistanceBasedPtFareParams GERMAN_WIDE_FARE = germanWideFare(); + + public static final String SET_NAME = "ptFareCalculationDistanceBased"; + public static final String MIN_FARE = "minFare"; + + @PositiveOrZero + private double minFare = 2.0; + + public DistanceBasedPtFareParams() { + super(SET_NAME); + } + + @Override + public Map getComments() { + Map map = super.getComments(); + map.put(MIN_FARE, "Minimum fare for a PT trip (e.g. Kurzstrecke/short distance ticket in cities, ticket for 1 zone in rural areas). " + + "Default is 2.0EUR."); + return map; + } + + @StringGetter(MIN_FARE) + public double getMinFare() { + return minFare; + } + + @StringSetter(MIN_FARE) + public void setMinFare(double minFare) { + this.minFare = minFare; + } + + // in Deutschlandtarif, the linear function for the prices above 100km seem to have a different steepness + // hence the following difference in data points + // prices taken from https://deutschlandtarifverbund.de/wp-content/uploads/2024/07/20231201_TBDT_J_10_Preisliste_V07.pdf + private static DistanceBasedPtFareParams germanWideFare() { + final double MIN_FARE = 1.70; + + SimpleRegression under100kmTrip = new SimpleRegression(); + under100kmTrip.addData(1, MIN_FARE); + under100kmTrip.addData(2, 1.90); + under100kmTrip.addData(3, 2.00); + under100kmTrip.addData(4, 2.10); + under100kmTrip.addData(5, 2.20); + under100kmTrip.addData(6, 3.20); + under100kmTrip.addData(7, 3.70); + under100kmTrip.addData(8, 3.80); + under100kmTrip.addData(9, 3.90); + under100kmTrip.addData(10, 4.10); + under100kmTrip.addData(11, 5.00); + under100kmTrip.addData(12, 5.40); + under100kmTrip.addData(13, 5.60); + under100kmTrip.addData(14, 5.80); + under100kmTrip.addData(15, 5.90); + under100kmTrip.addData(16, 6.40); + under100kmTrip.addData(17, 6.50); + under100kmTrip.addData(18, 6.60); + under100kmTrip.addData(19, 6.70); + under100kmTrip.addData(20, 6.90); + under100kmTrip.addData(30, 9.90); + under100kmTrip.addData(40, 13.70); + under100kmTrip.addData(50, 16.30); + under100kmTrip.addData(60, 18.10); + under100kmTrip.addData(70, 20.10); + under100kmTrip.addData(80, 23.20); + under100kmTrip.addData(90, 26.20); + under100kmTrip.addData(100, 28.10); + + SimpleRegression longDistanceTrip = new SimpleRegression(); + longDistanceTrip.addData(100, 28.10); + longDistanceTrip.addData(200, 47.20); + longDistanceTrip.addData(300, 59.70); + longDistanceTrip.addData(400, 71.70); + longDistanceTrip.addData(500, 83.00); + longDistanceTrip.addData(600, 94.60); + longDistanceTrip.addData(700, 106.30); + longDistanceTrip.addData(800, 118.20); + longDistanceTrip.addData(900, 130.10); + longDistanceTrip.addData(1000, 141.00); + longDistanceTrip.addData(1100, 148.60); + longDistanceTrip.addData(1200, 158.10); + longDistanceTrip.addData(1300, 169.20); + longDistanceTrip.addData(1400, 179.80); + longDistanceTrip.addData(1500, 190.10); + longDistanceTrip.addData(1600, 201.50); + longDistanceTrip.addData(1700, 212.80); + longDistanceTrip.addData(1800, 223.30); + longDistanceTrip.addData(1900, 233.90); + longDistanceTrip.addData(2000, 244.00); + + var params = new DistanceBasedPtFareParams(); + + DistanceClassLinearFareFunctionParams distanceClass100kmFareParams = params.getOrCreateDistanceClassFareParams(100_000.); + distanceClass100kmFareParams.setFareSlope(under100kmTrip.getSlope()); + distanceClass100kmFareParams.setFareIntercept(under100kmTrip.getIntercept()); + + DistanceClassLinearFareFunctionParams distanceClassLongFareParams = params.getOrCreateDistanceClassFareParams(Double.POSITIVE_INFINITY); + distanceClassLongFareParams.setFareSlope(longDistanceTrip.getSlope()); + distanceClassLongFareParams.setFareIntercept(longDistanceTrip.getIntercept()); + + params.setTransactionPartner("Deutschlandtarif"); + params.setMinFare(MIN_FARE); + + return params; + } + + public SortedMap getDistanceClassFareParams() { + @SuppressWarnings("unchecked") + final Collection distanceClassFareParams = + (Collection) getParameterSets(DistanceClassLinearFareFunctionParams.SET_NAME); + final SortedMap map = new TreeMap<>(); + + for (DistanceClassLinearFareFunctionParams pars : distanceClassFareParams) { + if (this.isLocked()) { + pars.setLocked(); + } + map.put(pars.getMaxDistance(), pars); + } + if (this.isLocked()) { + return Collections.unmodifiableSortedMap(map); + } else { + return map; + } + } + + public DistanceClassLinearFareFunctionParams getOrCreateDistanceClassFareParams(double maxDistance) { + DistanceClassLinearFareFunctionParams distanceClassFareParams = this.getDistanceClassFareParams().get(maxDistance); + if (distanceClassFareParams == null) { + distanceClassFareParams = new DistanceClassLinearFareFunctionParams(maxDistance); + addParameterSet(distanceClassFareParams); + } + return distanceClassFareParams; + } + + public static class DistanceClassLinearFareFunctionParams extends ReflectiveConfigGroup { + + public static final String SET_NAME = "distanceClassLinearFareFunctionParams"; + public static final String FARE_SLOPE = "fareSlope"; + public static final String FARE_INTERCEPT = "fareIntercept"; + public static final String MAX_DISTANCE = "maxDistance"; + + @PositiveOrZero + private double fareSlope; + @PositiveOrZero + private double fareIntercept; + @PositiveOrZero + private double maxDistance; + + public DistanceClassLinearFareFunctionParams(double maxDistance) { + super(SET_NAME); + this.maxDistance = maxDistance; + } + + @StringGetter(FARE_SLOPE) + public double getFareSlope() { + return fareSlope; + } + + @StringSetter(FARE_SLOPE) + public void setFareSlope(double fareSlope) { + this.fareSlope = fareSlope; + } + + @StringGetter(FARE_INTERCEPT) + public double getFareIntercept() { + return fareIntercept; + } + + + @StringSetter(FARE_INTERCEPT) + public void setFareIntercept(double fareIntercept) { + this.fareIntercept = fareIntercept; + } + + @StringGetter(MAX_DISTANCE) + public double getMaxDistance() { + return maxDistance; + } + + @StringSetter(MAX_DISTANCE) + public void setMaxDistance(double maxDistance) { + this.maxDistance = maxDistance; + } + + @Override + public Map getComments() { + Map map = super.getComments(); + map.put(FARE_SLOPE, "Linear function fare = slope * distance + intercept: the value of the slope factor in currency units / m" + + "(not km!)."); + map.put(FARE_INTERCEPT, "Linear function fare = slope * distance + intercept: the value of the intercept in currency units."); + map.put(MAX_DISTANCE, "The given linear function is applied to trips up to this distance threshold in meters. If set to a finite value" + + ", the linear function for the next distance class will be tried out. If no fare is defined with " + MAX_DISTANCE + " greater than" + + "pt trip length, an error is thrown."); + return map; + } + } +} diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculator.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculator.java similarity index 97% rename from contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculator.java rename to contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculator.java index a676137b487..1066bb4b014 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculator.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculator.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import org.geotools.api.feature.simple.SimpleFeature; import org.locationtech.jts.geom.Geometry; diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareParams.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareParams.java similarity index 83% rename from contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareParams.java rename to contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareParams.java index f213f32dbb0..391c609684e 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/FareZoneBasedPtFareParams.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareParams.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; public class FareZoneBasedPtFareParams extends PtFareParams { public static final String SET_NAME = "ptFareCalculationFareZoneBased"; diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareCalculator.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareCalculator.java similarity index 85% rename from contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareCalculator.java rename to contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareCalculator.java index 06fa0af4ca9..597f105c0dc 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareCalculator.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareCalculator.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import org.matsim.api.core.v01.Coord; diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareConfigGroup.java similarity index 98% rename from contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java rename to contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareConfigGroup.java index e4a72423fb2..9001b2ce2e9 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareConfigGroup.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareConfigGroup.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import jakarta.validation.constraints.PositiveOrZero; import org.matsim.core.config.Config; diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareHandler.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareHandler.java similarity index 88% rename from contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareHandler.java rename to contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareHandler.java index d911486a0e2..0bd169e0b60 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareHandler.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareHandler.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import org.matsim.api.core.v01.events.handler.ActivityStartEventHandler; import org.matsim.core.api.experimental.events.handler.AgentWaitingForPtEventHandler; diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareModule.java similarity index 98% rename from contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java rename to contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareModule.java index c9f327a6cec..d3b2f39d02a 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareModule.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareModule.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import com.google.inject.multibindings.Multibinder; import org.matsim.api.core.v01.TransportMode; diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareParams.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareParams.java similarity index 97% rename from contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareParams.java rename to contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareParams.java index 56e96fb49c2..2ab1c501d4f 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareParams.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareParams.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import org.matsim.core.config.ReflectiveConfigGroup; diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareUpperBoundHandler.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareUpperBoundHandler.java similarity index 98% rename from contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareUpperBoundHandler.java rename to contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareUpperBoundHandler.java index 6638c12e7f3..5d05602df2d 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtFareUpperBoundHandler.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareUpperBoundHandler.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import com.google.inject.Inject; import org.matsim.api.core.v01.Id; @@ -10,7 +10,6 @@ import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.controler.events.AfterMobsimEvent; import org.matsim.core.controler.listener.AfterMobsimListener; -import org.matsim.pt.PtConstants; import java.util.ArrayList; import java.util.HashMap; diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java similarity index 91% rename from contribs/vsp/src/main/java/playground/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java rename to contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java index 90ec2339fa4..11bbaae184d 100644 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import com.google.inject.Inject; import it.unimi.dsi.fastutil.doubles.DoubleArrayList; @@ -152,9 +152,7 @@ private DoubleDoublePair estimateTrip(EstimatorContext context, List trip) double dist = CoordUtils.calcEuclideanDistance(access.getCoord(), egress.getCoord()); double fareUtility = -context.scoring.marginalUtilityOfMoney * DistanceBasedPtFareCalculator.computeFare(dist, - ptFare.getLongDistanceTripThreshold(), ptFare.getMinFare(), ptFare.getNormalTripIntercept(), ptFare.getNormalTripSlope(), - ptFare.getLongDistanceTripIntercept(), ptFare.getLongDistanceTripSlope()); - + ptFare.getMinFare(), ptFare.getDistanceClassFareParams()); estimate += context.scoring.marginalUtilityOfWaitingPt_s * totalWaitingTime; @@ -221,17 +219,14 @@ private double calcMinimumFare(PlanModel plan) { // a single pt trip could never benefit from the upper bound if (n == 1) { - return DistanceBasedPtFareCalculator.computeFare(minDist, ptFare.getLongDistanceTripThreshold(), ptFare.getMinFare(), - ptFare.getNormalTripIntercept(), ptFare.getNormalTripSlope(), ptFare.getLongDistanceTripIntercept(), - ptFare.getLongDistanceTripSlope()); + return DistanceBasedPtFareCalculator.computeFare(minDist, ptFare.getMinFare(), ptFare.getDistanceClassFareParams()); } // the upper bound is the maximum single trip times a factor // therefore the minimum upper bound is the fare for the second-longest trip // the max costs are then assumed to be evenly distributed over all pt trips return 1d / n * config.getUpperBoundFactor() * DistanceBasedPtFareCalculator.computeFare(secondMinDist, - ptFare.getLongDistanceTripThreshold(), ptFare.getMinFare(), ptFare.getNormalTripIntercept(), ptFare.getNormalTripSlope(), - ptFare.getLongDistanceTripIntercept(), ptFare.getLongDistanceTripSlope()); + ptFare.getMinFare(), ptFare.getDistanceClassFareParams()); } @Override diff --git a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java b/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java deleted file mode 100644 index 605a266e131..00000000000 --- a/contribs/vsp/src/main/java/playground/vsp/pt/fare/DistanceBasedPtFareParams.java +++ /dev/null @@ -1,187 +0,0 @@ -package playground.vsp.pt.fare; - -import jakarta.validation.constraints.PositiveOrZero; -import org.apache.commons.math.stat.regression.SimpleRegression; - -import java.util.Map; - -/** - * @author Chengqi Lu (luchengqi7) - * The parameters for the distance-based PT trip fare calculation. - * The default values are set based on the fitting results of the trip and fare data collected on September 2021 - * The values are based on the standard unit of meter (m) and Euro (EUR) - */ -public class DistanceBasedPtFareParams extends PtFareParams { - public static final DistanceBasedPtFareParams GERMAN_WIDE_FARE = germanWideFare(); - - public static final String SET_NAME = "ptFareCalculationDistanceBased"; - public static final String MIN_FARE = "minFare"; - public static final String NORMAL_TRIP_SLOPE = "normalTripSlope"; - public static final String NORMAL_TRIP_INTERCEPT = "normalTripIntercept"; - public static final String LONG_DISTANCE_TRIP_THRESHOLD = "longDistanceTripThreshold"; - public static final String LONG_DISTANCE_TRIP_SLOPE = "longDistanceTripSlope"; - public static final String LONG_DISTANCE_TRIP_INTERCEPT = "longDistanceTripIntercept"; - - @PositiveOrZero - private double minFare = 2.0; - @PositiveOrZero - private double normalTripIntercept = 1.6; - @PositiveOrZero - private double normalTripSlope = 0.00017; - @PositiveOrZero - private double longDistanceTripThreshold = 50000.0; - @PositiveOrZero - private double longDistanceTripIntercept = 30.0; - @PositiveOrZero - private double longDistanceTripSlope = 0.00025; - - public DistanceBasedPtFareParams() { - super(SET_NAME); - } - - @Override - public Map getComments() { - Map map = super.getComments(); - map.put(MIN_FARE, "Minimum fare for a PT trip (e.g. Kurzstrecke/short distance ticket in cities, ticket for 1 zone in rural areas). " + - "Default is 2.0EUR."); - map.put(NORMAL_TRIP_SLOPE, "Linear model y = ax + b: the value of a, for normal trips (e.g. within the city or region). Default is 0.00017" + - "EUR."); - map.put(NORMAL_TRIP_INTERCEPT, "Linear model y = ax + b: the value of b, for normal trips. Default is 1.6EUR."); - map.put(LONG_DISTANCE_TRIP_SLOPE, "Linear model y = ax + b: the value of a, for long distance trips (e.g. intercity trips). Default is 0" + - ".00025EUR."); - map.put(LONG_DISTANCE_TRIP_INTERCEPT, "Linear model y = ax + b: the value of b, for long trips. Default is 30.0EUR."); - map.put(LONG_DISTANCE_TRIP_THRESHOLD, "Threshold of the long trips in meters. Below this value, the trips are considered as normal trips. " + - "Above this value, the trips are considered as inter-city trips. Default is 50000.0m."); - return map; - } - - @StringGetter(MIN_FARE) - public double getMinFare() { - return minFare; - } - - @StringSetter(MIN_FARE) - public void setMinFare(double minFare) { - this.minFare = minFare; - } - - @StringGetter(NORMAL_TRIP_SLOPE) - public double getNormalTripSlope() { - return normalTripSlope; - } - - @StringSetter(NORMAL_TRIP_SLOPE) - public void setNormalTripSlope(double normalTripSlope) { - this.normalTripSlope = normalTripSlope; - } - - @StringGetter(NORMAL_TRIP_INTERCEPT) - public double getNormalTripIntercept() { - return normalTripIntercept; - } - - @StringSetter(NORMAL_TRIP_INTERCEPT) - public void setNormalTripIntercept(double normalTripIntercept) { - this.normalTripIntercept = normalTripIntercept; - } - - @StringGetter(LONG_DISTANCE_TRIP_SLOPE) - public double getLongDistanceTripSlope() { - return longDistanceTripSlope; - } - - @StringSetter(LONG_DISTANCE_TRIP_SLOPE) - public void setLongDistanceTripSlope(double longDistanceTripSlope) { - this.longDistanceTripSlope = longDistanceTripSlope; - } - - @StringGetter(LONG_DISTANCE_TRIP_INTERCEPT) - public double getLongDistanceTripIntercept() { - return longDistanceTripIntercept; - } - - @StringSetter(LONG_DISTANCE_TRIP_INTERCEPT) - public void setLongDistanceTripIntercept(double longDistanceTripIntercept) { - this.longDistanceTripIntercept = longDistanceTripIntercept; - } - - @StringGetter(LONG_DISTANCE_TRIP_THRESHOLD) - public double getLongDistanceTripThreshold() { - return longDistanceTripThreshold; - } - - @StringSetter(LONG_DISTANCE_TRIP_THRESHOLD) - public void setLongDistanceTripThreshold(double longDistanceTripThreshold) { - this.longDistanceTripThreshold = longDistanceTripThreshold; - } - - // in Deutschlandtarif, the linear function for the prices above 100km seem to have a different steepness - // hence the following difference in data points - // prices taken from https://deutschlandtarifverbund.de/wp-content/uploads/2024/07/20231201_TBDT_J_10_Preisliste_V07.pdf - private static DistanceBasedPtFareParams germanWideFare() { - final double MIN_FARE = 1.70; - - SimpleRegression normalDistanceTrip = new SimpleRegression(); - normalDistanceTrip.addData(1, MIN_FARE); - normalDistanceTrip.addData(2, 1.90); - normalDistanceTrip.addData(3, 2.00); - normalDistanceTrip.addData(4, 2.10); - normalDistanceTrip.addData(5, 2.20); - normalDistanceTrip.addData(6, 3.20); - normalDistanceTrip.addData(7, 3.70); - normalDistanceTrip.addData(8, 3.80); - normalDistanceTrip.addData(9, 3.90); - normalDistanceTrip.addData(10, 4.10); - normalDistanceTrip.addData(11, 5.00); - normalDistanceTrip.addData(12, 5.40); - normalDistanceTrip.addData(13, 5.60); - normalDistanceTrip.addData(14, 5.80); - normalDistanceTrip.addData(15, 5.90); - normalDistanceTrip.addData(16, 6.40); - normalDistanceTrip.addData(17, 6.50); - normalDistanceTrip.addData(18, 6.60); - normalDistanceTrip.addData(19, 6.70); - normalDistanceTrip.addData(20, 6.90); - normalDistanceTrip.addData(30, 9.90); - normalDistanceTrip.addData(40, 13.70); - normalDistanceTrip.addData(50, 16.30); - normalDistanceTrip.addData(60, 18.10); - normalDistanceTrip.addData(70, 20.10); - normalDistanceTrip.addData(80, 23.20); - normalDistanceTrip.addData(90, 26.20); - normalDistanceTrip.addData(100, 28.10); - - SimpleRegression longDistanceTrip = new SimpleRegression(); - longDistanceTrip.addData(100, 28.10); - longDistanceTrip.addData(200, 47.20); - longDistanceTrip.addData(300, 59.70); - longDistanceTrip.addData(400, 71.70); - longDistanceTrip.addData(500, 83.00); - longDistanceTrip.addData(600, 94.60); - longDistanceTrip.addData(700, 106.30); - longDistanceTrip.addData(800, 118.20); - longDistanceTrip.addData(900, 130.10); - longDistanceTrip.addData(1000, 141.00); - longDistanceTrip.addData(1100, 148.60); - longDistanceTrip.addData(1200, 158.10); - longDistanceTrip.addData(1300, 169.20); - longDistanceTrip.addData(1400, 179.80); - longDistanceTrip.addData(1500, 190.10); - longDistanceTrip.addData(1600, 201.50); - longDistanceTrip.addData(1700, 212.80); - longDistanceTrip.addData(1800, 223.30); - longDistanceTrip.addData(1900, 233.90); - longDistanceTrip.addData(2000, 244.00); - - var params = new DistanceBasedPtFareParams(); - params.setNormalTripSlope(normalDistanceTrip.getSlope()); - params.setNormalTripIntercept(normalDistanceTrip.getIntercept()); - params.setLongDistanceTripSlope(longDistanceTrip.getSlope()); - params.setLongDistanceTripIntercept(longDistanceTrip.getIntercept()); - params.setLongDistanceTripThreshold(100_000.); - params.setTransactionPartner("Deutschlandtarif"); - params.setMinFare(MIN_FARE); - - return params; - } -} diff --git a/contribs/vsp/src/test/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java similarity index 80% rename from contribs/vsp/src/test/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java rename to contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java index 005b7f3f80d..5a62cff6375 100644 --- a/contribs/vsp/src/test/java/playground/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -61,13 +61,16 @@ private DistanceBasedPtFareCalculator getCalculator(String shapeFile) { var params = new DistanceBasedPtFareParams(); params.setTransactionPartner(TRANSACTION_PARTNER); //0-2000m: 1EUR + 1EUR/km - params.setNormalTripIntercept(1.0); - params.setNormalTripSlope(0.001); + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClass2kmFareParams = + params.getOrCreateDistanceClassFareParams(2000.0); + distanceClass2kmFareParams.setFareIntercept(1.0); + distanceClass2kmFareParams.setFareSlope(0.001); //2000m+: 3EUR + 0.5EUR/km - params.setLongDistanceTripThreshold(2000.); - params.setLongDistanceTripIntercept(3.); - params.setLongDistanceTripSlope(0.0005); + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClassLongFareParams = + params.getOrCreateDistanceClassFareParams(Double.POSITIVE_INFINITY); + distanceClassLongFareParams.setFareIntercept(3.0); + distanceClassLongFareParams.setFareSlope(0.0005); params.setMinFare(1.0); params.setFareZoneShp(shapeFile); diff --git a/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java similarity index 98% rename from contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java rename to contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java index ac3eda11b5a..a23019c86f3 100644 --- a/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import org.junit.jupiter.api.Test; import org.matsim.api.core.v01.Coord; diff --git a/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java similarity index 94% rename from contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java rename to contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java index 9d76e3ea13b..f55e7bf7026 100644 --- a/contribs/vsp/src/test/java/playground/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Assertions; @@ -49,6 +49,11 @@ void testFareZoneBasedPtFareHandler() { fareZoneBased.setTransactionPartner(FARE_ZONE_TRANSACTION_PARTNER); DistanceBasedPtFareParams distanceBased = new DistanceBasedPtFareParams(); + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClassFareParams = + distanceBased.getOrCreateDistanceClassFareParams(999_999_999.); + distanceClassFareParams.setFareSlope(0.00017); + distanceClassFareParams.setFareIntercept(1.6); + distanceBased.addParameterSet(distanceClassFareParams); distanceBased.setOrder(2); distanceBased.setTransactionPartner(DISTANCE_BASED_TRANSACTION_PARTNER); diff --git a/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtFareConfigGroupTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/PtFareConfigGroupTest.java similarity index 97% rename from contribs/vsp/src/test/java/playground/vsp/pt/fare/PtFareConfigGroupTest.java rename to contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/PtFareConfigGroupTest.java index adec9b3aa6b..ed32e9ac859 100644 --- a/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtFareConfigGroupTest.java +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/PtFareConfigGroupTest.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtTripFareEstimatorTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/PtTripFareEstimatorTest.java similarity index 90% rename from contribs/vsp/src/test/java/playground/vsp/pt/fare/PtTripFareEstimatorTest.java rename to contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/PtTripFareEstimatorTest.java index 557b8fbdfd6..791931b89a2 100644 --- a/contribs/vsp/src/test/java/playground/vsp/pt/fare/PtTripFareEstimatorTest.java +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/PtTripFareEstimatorTest.java @@ -1,4 +1,4 @@ -package playground.vsp.pt.fare; +package org.matsim.contrib.vsp.pt.fare; import com.google.inject.Inject; import com.google.inject.Injector; @@ -66,12 +66,15 @@ public void setUp() throws Exception { fare.setUpperBoundFactor(1.5); distanceFare.setMinFare(0.1); - distanceFare.setNormalTripIntercept(0.5); - distanceFare.setNormalTripSlope(0.1); - - distanceFare.setLongDistanceTripThreshold(20000); - distanceFare.setLongDistanceTripIntercept(1); - distanceFare.setLongDistanceTripSlope(0.01); + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClass20kmFareParams = + distanceFare.getOrCreateDistanceClassFareParams(20000.0); + distanceClass20kmFareParams.setFareIntercept(0.5); + distanceClass20kmFareParams.setFareSlope(0.1); + + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClassLongFareParams = + distanceFare.getOrCreateDistanceClassFareParams(Double.POSITIVE_INFINITY); + distanceClassLongFareParams.setFareIntercept(1.0); + distanceClassLongFareParams.setFareSlope(0.01); fare.addParameterSet(distanceFare); diff --git a/contribs/vsp/src/test/java/playground/vsp/TestScenario.java b/contribs/vsp/src/test/java/playground/vsp/TestScenario.java index 24fde8c688a..973c9362786 100644 --- a/contribs/vsp/src/test/java/playground/vsp/TestScenario.java +++ b/contribs/vsp/src/test/java/playground/vsp/TestScenario.java @@ -14,7 +14,7 @@ import org.matsim.modechoice.estimators.DefaultLegScoreEstimator; import org.matsim.modechoice.estimators.FixedCostsEstimator; import org.matsim.testcases.MatsimTestUtils; -import playground.vsp.pt.fare.PtTripWithDistanceBasedFareEstimator; +import org.matsim.contrib.vsp.pt.fare.PtTripWithDistanceBasedFareEstimator; import javax.annotation.Nullable; import java.net.URL; From 8d209f69fa166f92c110322d3f9db488a477dd84 Mon Sep 17 00:00:00 2001 From: vsp-gleich Date: Fri, 16 Aug 2024 20:17:38 +0200 Subject: [PATCH 064/111] Pt fares minor cleanup (#3414) * shorten parameter set name, remove duplicate parameter set in test, comment --- .../matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java | 3 ++- .../contrib/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java index e84a9e88abb..6a968d80dda 100644 --- a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java @@ -46,6 +46,7 @@ public void setMinFare(double minFare) { // in Deutschlandtarif, the linear function for the prices above 100km seem to have a different steepness // hence the following difference in data points // prices taken from https://deutschlandtarifverbund.de/wp-content/uploads/2024/07/20231201_TBDT_J_10_Preisliste_V07.pdf + // TODO: This fare will change. We might need a way to select the fare of a specific year private static DistanceBasedPtFareParams germanWideFare() { final double MIN_FARE = 1.70; @@ -147,7 +148,7 @@ public DistanceClassLinearFareFunctionParams getOrCreateDistanceClassFareParams( public static class DistanceClassLinearFareFunctionParams extends ReflectiveConfigGroup { - public static final String SET_NAME = "distanceClassLinearFareFunctionParams"; + public static final String SET_NAME = "distanceClassLinearFare"; public static final String FARE_SLOPE = "fareSlope"; public static final String FARE_INTERCEPT = "fareIntercept"; public static final String MAX_DISTANCE = "maxDistance"; diff --git a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java index f55e7bf7026..687a2c4f522 100644 --- a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java @@ -53,7 +53,6 @@ void testFareZoneBasedPtFareHandler() { distanceBased.getOrCreateDistanceClassFareParams(999_999_999.); distanceClassFareParams.setFareSlope(0.00017); distanceClassFareParams.setFareIntercept(1.6); - distanceBased.addParameterSet(distanceClassFareParams); distanceBased.setOrder(2); distanceBased.setTransactionPartner(DISTANCE_BASED_TRANSACTION_PARTNER); From 3f7824c63ff074ad75fe271cd7c106ecd38f0eaf Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Mon, 19 Aug 2024 13:57:33 +0200 Subject: [PATCH 065/111] add designated vehicle for shifts --- .../shifts/dispatcher/DrtShiftDispatcherImpl.java | 12 ++++++++++++ .../operations/shifts/io/DrtShiftsReader.java | 10 ++++++++-- .../operations/shifts/io/DrtShiftsWriter.java | 3 +++ .../shifts/run/ShiftDrtModeOptimizerQSimModule.java | 4 +++- .../extension/operations/shifts/shift/DrtShift.java | 7 +++++-- .../operations/shifts/shift/DrtShiftImpl.java | 12 ++++++++++-- .../shifts/shift/DrtShiftSpecification.java | 3 +++ .../shifts/shift/DrtShiftSpecificationImpl.java | 13 +++++++++++++ .../extension/operations/shifts/ShiftsIOTest.java | 7 +++++++ .../drt/extension/operations/shifts/testShifts.xml | 4 ++-- 10 files changed, 66 insertions(+), 9 deletions(-) diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java index 6e082f6f7d5..2e962edfa46 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java @@ -218,6 +218,18 @@ private void assignShifts(double timeStep) { for (DrtShift shift : assignableShifts) { ShiftDvrpVehicle vehicle = null; + if(shift.getDesignatedVehicleId().isPresent()) { + DvrpVehicle designatedVehicle = fleet.getVehicles().get(shift.getDesignatedVehicleId().get()); + Verify.verify(designatedVehicle.getSchedule().getStatus() == Schedule.ScheduleStatus.STARTED); + Verify.verify(designatedVehicle instanceof ShiftDvrpVehicle); + if(!vehicle.getShifts().isEmpty()) { + continue; + } + if(shift.getOperationFacilityId().isPresent()) { + Verify.verify(idleVehiclesQueues.get(shift.getOperationFacilityId().get()).contains(designatedVehicle)); + } + } + for (ShiftEntry active : activeShifts) { if (active.shift().getEndTime() > shift.getStartTime()) { break; diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/io/DrtShiftsReader.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/io/DrtShiftsReader.java index f707a8c8108..928fd2360cd 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/io/DrtShiftsReader.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/io/DrtShiftsReader.java @@ -8,6 +8,7 @@ import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftBreakSpecificationImpl; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftSpecificationImpl; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.core.utils.io.MatsimXmlParser; import org.xml.sax.Attributes; @@ -27,6 +28,7 @@ public class DrtShiftsReader extends MatsimXmlParser { public static final String START_TIME = "start"; public static final String END_TIME = "end"; public static final String OPERATION_FACILITY_ID = "operationFacilityId"; + public static final String DESIGNATED_VEHICLE_ID = "designatedVehicleId"; public static final String EARLIEST_BREAK_START_TIME = "earliestStart"; public static final String LATEST_BREAK_END_TIME = "latestEnd"; @@ -55,8 +57,12 @@ public void startTag(final String name, final Attributes atts, final Stack, DrtShiftSpecification> shifts) throws atts.add(createTuple(END_TIME, shift.getEndTime())); shift.getOperationFacilityId().ifPresent(operationFacilityId -> atts.add(createTuple(OPERATION_FACILITY_ID, operationFacilityId.toString()))); + shift.getDesignatedVehicleId().ifPresent(designatedVehicleId -> + atts.add(createTuple(DESIGNATED_VEHICLE_ID, designatedVehicleId.toString()))); this.writeStartTag(SHIFT_NAME, atts); //Write break, if present diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java index a65de06b2c4..64180f24491 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java @@ -92,7 +92,9 @@ public DrtShifts get() { breakSpec.getLatestBreakEndTime(), breakSpec.getDuration()); } - return new DrtShiftImpl(spec.getId(), spec.getStartTime(), spec.getEndTime(), spec.getOperationFacilityId().orElse(null), shiftBreak); + return new DrtShiftImpl(spec.getId(), spec.getStartTime(), spec.getEndTime(), + spec.getOperationFacilityId().orElse(null), spec.getDesignatedVehicleId().orElse(null), + shiftBreak); }) .collect(ImmutableMap.toImmutableMap(DrtShift::getId, s -> s)); return () -> shifts; diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShift.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShift.java index d641677cd38..24442914ba3 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShift.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShift.java @@ -3,6 +3,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Identifiable; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import java.util.Optional; @@ -15,8 +16,6 @@ public interface DrtShift extends Identifiable { double getEndTime(); - Optional getBreak(); - boolean isStarted(); boolean isEnded(); @@ -26,4 +25,8 @@ public interface DrtShift extends Identifiable { void end(); Optional> getOperationFacilityId(); + + Optional getBreak(); + + Optional> getDesignatedVehicleId(); } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftImpl.java index 79373816104..1f929cdd574 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftImpl.java @@ -2,6 +2,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import java.util.Optional; @@ -15,6 +16,7 @@ public class DrtShiftImpl implements DrtShift { private final double start; private final double end; private final Id operationFacilityId; + private final Id designatedVehicleId; private final DrtShiftBreak shiftBreak; @@ -22,12 +24,13 @@ public class DrtShiftImpl implements DrtShift { private boolean ended = false; public DrtShiftImpl(Id id, double start, double end, Id operationFacilityId, - DrtShiftBreak shiftBreak) { + Id designatedVehicleId, DrtShiftBreak shiftBreak) { this.id = id; this.start = start; this.end = end; this.operationFacilityId = operationFacilityId; - this.shiftBreak = shiftBreak; + this.designatedVehicleId = designatedVehicleId; + this.shiftBreak = shiftBreak; } @Override @@ -45,6 +48,11 @@ public Optional getBreak() { return Optional.ofNullable(shiftBreak); } + @Override + public Optional> getDesignatedVehicleId() { + return Optional.ofNullable(designatedVehicleId); + } + @Override public boolean isStarted() { return started; diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftSpecification.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftSpecification.java index 18f877c45e3..e32ad8a8416 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftSpecification.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftSpecification.java @@ -3,6 +3,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Identifiable; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import java.util.Optional; @@ -18,4 +19,6 @@ public interface DrtShiftSpecification extends Identifiable { Optional getBreak(); Optional> getOperationFacilityId(); + + Optional> getDesignatedVehicleId(); } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftSpecificationImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftSpecificationImpl.java index fd5a36f2501..6e0bc88b0dc 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftSpecificationImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftSpecificationImpl.java @@ -2,6 +2,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import java.util.Optional; @@ -15,6 +16,7 @@ public class DrtShiftSpecificationImpl implements DrtShiftSpecification { private final double end; private final DrtShiftBreakSpecification shiftBreak; private final Id operationFacilityId; + private final Id designatedVehicleId; private DrtShiftSpecificationImpl(Builder builder) { this.id = builder.id; @@ -22,6 +24,7 @@ private DrtShiftSpecificationImpl(Builder builder) { this.end = builder.end; this.shiftBreak = builder.shiftBreak; this.operationFacilityId = builder.operationFacilityId; + this.designatedVehicleId = builder.designatedVehicleId; } @Override @@ -44,6 +47,11 @@ public Optional> getOperationFacilityId() { return Optional.ofNullable(operationFacilityId); } + @Override + public Optional> getDesignatedVehicleId() { + return Optional.ofNullable(designatedVehicleId); + } + @Override public Id getId() { return id; @@ -69,6 +77,7 @@ public static final class Builder { private double end; private DrtShiftBreakSpecification shiftBreak; private Id operationFacilityId; + public Id designatedVehicleId; private Builder() { } @@ -97,6 +106,10 @@ public Builder operationFacility(Id operationFacilityId) { this.operationFacilityId = operationFacilityId; return this; } + public Builder designatedVehicle(Id designatedVehicleId) { + this.designatedVehicleId = designatedVehicleId; + return this; + } public DrtShiftSpecificationImpl build() { return new DrtShiftSpecificationImpl(this); diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/ShiftsIOTest.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/ShiftsIOTest.java index ff5eb57ecdc..ae00d55bd16 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/ShiftsIOTest.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/ShiftsIOTest.java @@ -15,6 +15,7 @@ import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftSpecification; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecificationImpl; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.testcases.MatsimTestUtils; /** @@ -35,6 +36,9 @@ public class ShiftsIOTest { private final Id oid1 = Id.create("op1", OperationFacility.class); private final Id oid2 = Id.create("op2", OperationFacility.class); + private final Id vehId1 = Id.create("drt1", DvrpVehicle.class); + private final Id vehId2 = Id.create("drt2", DvrpVehicle.class); + @Test void testBasicReaderWriter() { @@ -69,6 +73,7 @@ private void checkContent(DrtShiftsSpecification shiftsSpecification) { assertEquals(45000., shiftSpecification1.getEndTime(), 0); assertTrue(shiftSpecification1.getOperationFacilityId().isPresent()); assertEquals(oid1, shiftSpecification1.getOperationFacilityId().get()); + assertEquals(vehId1, shiftSpecification1.getDesignatedVehicleId().get()); assertEquals(1800., shiftSpecification1.getBreak().orElseThrow().getDuration(), 0); assertEquals(28800., shiftSpecification1.getBreak().orElseThrow().getEarliestBreakStartTime(), 0); assertEquals(32400., shiftSpecification1.getBreak().orElseThrow().getLatestBreakEndTime(), 0); @@ -80,6 +85,7 @@ private void checkContent(DrtShiftsSpecification shiftsSpecification) { assertEquals(49000., shiftSpecification2.getEndTime(), 0); assertTrue(shiftSpecification2.getOperationFacilityId().isPresent()); assertEquals(oid2, shiftSpecification2.getOperationFacilityId().get()); + assertEquals(vehId2, shiftSpecification2.getDesignatedVehicleId().get()); assertEquals(3600., shiftSpecification2.getBreak().orElseThrow().getDuration(), 0); assertEquals(29200., shiftSpecification2.getBreak().orElseThrow().getEarliestBreakStartTime(), 0); assertEquals(32800., shiftSpecification2.getBreak().orElseThrow().getLatestBreakEndTime(), 0); @@ -91,6 +97,7 @@ private void checkContent(DrtShiftsSpecification shiftsSpecification) { assertEquals(53000., shiftSpecification3.getEndTime(), 0); assertFalse(shiftSpecification3.getOperationFacilityId().isPresent()); assertEquals(Optional.empty(), shiftSpecification3.getOperationFacilityId()); + assertEquals(Optional.empty(), shiftSpecification3.getDesignatedVehicleId()); assertTrue(shiftSpecification3.getBreak().isEmpty()); } } diff --git a/contribs/drt-extensions/test/input/org/matsim/contrib/drt/extension/operations/shifts/testShifts.xml b/contribs/drt-extensions/test/input/org/matsim/contrib/drt/extension/operations/shifts/testShifts.xml index 2cb87bd3c9f..972a28788af 100644 --- a/contribs/drt-extensions/test/input/org/matsim/contrib/drt/extension/operations/shifts/testShifts.xml +++ b/contribs/drt-extensions/test/input/org/matsim/contrib/drt/extension/operations/shifts/testShifts.xml @@ -1,8 +1,8 @@ - + - + From 56e1e328320c5625e02442e5fdc3da5e677b63f4 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Mon, 19 Aug 2024 14:00:56 +0200 Subject: [PATCH 066/111] actually use designated vehicle in assignment --- .../dispatcher/DrtShiftDispatcherImpl.java | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java index 2e962edfa46..2bcebb2e8e5 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java @@ -228,33 +228,36 @@ private void assignShifts(double timeStep) { if(shift.getOperationFacilityId().isPresent()) { Verify.verify(idleVehiclesQueues.get(shift.getOperationFacilityId().get()).contains(designatedVehicle)); } + vehicle = (ShiftDvrpVehicle) designatedVehicle; } - for (ShiftEntry active : activeShifts) { - if (active.shift().getEndTime() > shift.getStartTime()) { - break; - } - if(shift.getOperationFacilityId().isPresent()) { - //we have to check that the vehicle ends the previous shift at the same facility where - //the new shift is to start. - if(active.shift().getOperationFacilityId().isPresent()) { - if(!active.shift().getOperationFacilityId().get().equals(shift.getOperationFacilityId().get())) { - continue; - } - } else { - Optional nextShiftChangeover = ShiftSchedules.getNextShiftChangeover(active.vehicle().getSchedule()); - if(nextShiftChangeover.isPresent()) { - Verify.verify(nextShiftChangeover.get().getShift().equals(active.shift())); - if(!nextShiftChangeover.get().getFacility().getId().equals(shift.getOperationFacilityId().get())) { - // there is already a shift changeover scheduled elsewhere + if(vehicle == null) { + for (ShiftEntry active : activeShifts) { + if (active.shift().getEndTime() > shift.getStartTime()) { + break; + } + if (shift.getOperationFacilityId().isPresent()) { + //we have to check that the vehicle ends the previous shift at the same facility where + //the new shift is to start. + if (active.shift().getOperationFacilityId().isPresent()) { + if (!active.shift().getOperationFacilityId().get().equals(shift.getOperationFacilityId().get())) { continue; } + } else { + Optional nextShiftChangeover = ShiftSchedules.getNextShiftChangeover(active.vehicle().getSchedule()); + if (nextShiftChangeover.isPresent()) { + Verify.verify(nextShiftChangeover.get().getShift().equals(active.shift())); + if (!nextShiftChangeover.get().getFacility().getId().equals(shift.getOperationFacilityId().get())) { + // there is already a shift changeover scheduled elsewhere + continue; + } + } } } - } - if (assignShiftToVehicleLogic.canAssignVehicleToShift(active.vehicle(), shift)) { - vehicle = active.vehicle(); - break; + if (assignShiftToVehicleLogic.canAssignVehicleToShift(active.vehicle(), shift)) { + vehicle = active.vehicle(); + break; + } } } From b96ea9d0783a596bc8ba6aa25807da442dcfab9c Mon Sep 17 00:00:00 2001 From: sime94 Date: Mon, 19 Aug 2024 17:57:15 +0200 Subject: [PATCH 067/111] tourStartTime is always set to 0, which can lead to the end time of a tour being earlier than the start time of the tour... this is fixed now --- .../SmallScaleCommercialTrafficUtils.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java index 3af4dc1fa7f..509ff7f42b2 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java @@ -42,6 +42,7 @@ import org.matsim.application.options.ShpOptions.Index; import org.matsim.core.network.NetworkUtils; import org.matsim.core.population.PopulationUtils; +import org.matsim.core.router.TripStructureUtils; import org.matsim.core.utils.io.IOUtils; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.CarriersUtils; @@ -199,7 +200,6 @@ static void createPlansBasedOnCarrierPlans(Scenario scenario, String smallScaleC String mode = allVehicles.getVehicles().get(vehicleId).getType().getNetworkMode(); List tourElements = person.getSelectedPlan().getPlanElements(); - double tourStartTime = 0; for (PlanElement tourElement : tourElements) { if (tourElement instanceof Activity activity) { @@ -209,8 +209,18 @@ static void createPlansBasedOnCarrierPlans(Scenario scenario, String smallScaleC newActivity.setEndTime(activity.getEndTime().seconds()); newActivity.setType("commercial_start"); } else +// TODO: this causes a crash when PersonPrepareForSim -> PlanRouter tries routing??? newActivity.setEndTimeUndefined(); if (activity.getType().equals("end")) { +// if tourStartTime = 0 it can happen that commecial_start.getEndTime > commercial_end.getStartTime +// this should not happen, hence below the tour start time is taken from the commercial_start act + double tourStartTime = TripStructureUtils.getActivities(plan.getPlanElements(), TripStructureUtils.StageActivityHandling.ExcludeStageActivities) + .stream() + .filter(a -> a.getType().equals("commercial_start")) + .toList() + .getFirst() + .getEndTime() + .seconds(); newActivity.setStartTime(tourStartTime + 8 * 3600); newActivity.setType("commercial_end"); } From 9dcb7a707b30b2cc81437b9ce364b34165c536e8 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Mon, 19 Aug 2024 23:02:10 +0200 Subject: [PATCH 068/111] drt shift designated vehicle fix --- .../operations/shifts/dispatcher/DrtShiftDispatcherImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java index 2bcebb2e8e5..b021d811b3b 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java @@ -222,7 +222,7 @@ private void assignShifts(double timeStep) { DvrpVehicle designatedVehicle = fleet.getVehicles().get(shift.getDesignatedVehicleId().get()); Verify.verify(designatedVehicle.getSchedule().getStatus() == Schedule.ScheduleStatus.STARTED); Verify.verify(designatedVehicle instanceof ShiftDvrpVehicle); - if(!vehicle.getShifts().isEmpty()) { + if(!((ShiftDvrpVehicle) designatedVehicle).getShifts().isEmpty()) { continue; } if(shift.getOperationFacilityId().isPresent()) { From ac0cf1f2c6651563d6c74e014ba16568cd59a847 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Tue, 20 Aug 2024 16:54:40 +0200 Subject: [PATCH 069/111] avoid deadlock situations with undercharged vehicles at hubs --- .../operations/shifts/config/ShiftsParams.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/config/ShiftsParams.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/config/ShiftsParams.java index e61e5541896..3409d13b051 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/config/ShiftsParams.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/config/ShiftsParams.java @@ -8,8 +8,10 @@ */ package org.matsim.contrib.drt.extension.operations.shifts.config; +import com.google.common.base.Verify; import org.matsim.contrib.common.util.ReflectiveConfigGroupWithConfigurableParameterSets; import org.matsim.contrib.ev.infrastructure.ChargerSpecification; +import org.matsim.core.config.Config; import org.matsim.core.config.ConfigGroup; import java.net.URL; @@ -60,7 +62,7 @@ public class ShiftsParams extends ReflectiveConfigGroupWithConfigurableParameter @Parameter @Comment("defines the battery state of charge threshold at which vehicles will start charging" + " at hubs when not in an active shift. values between [0,1)") - public double chargeAtHubThreshold = 0.5; + public double chargeAtHubThreshold = 0.6; @Parameter @Comment("defines the battery state of charge threshold at which vehicles will start charging" + @@ -97,11 +99,19 @@ public class ShiftsParams extends ReflectiveConfigGroupWithConfigurableParameter "In this case, make sure that 'shiftScheduleLookAhead' is larger than the prebboking slack.") public boolean considerUpcomingShiftsForInsertion = false; - public ShiftsParams() { + public ShiftsParams() { super(SET_NAME); } public URL getShiftInputUrl(URL context) { return shiftInputFile == null ? null : ConfigGroup.getInputFileURL(context, shiftInputFile); } + + @Override + protected void checkConsistency(Config config) { + super.checkConsistency(config); + Verify.verify(chargeAtHubThreshold >= shiftAssignmentBatteryThreshold, + "chargeAtHubThreshold must be higher than shiftAssignmentBatteryThreshold to " + + "avoid deadlocks with undercharged vehicles in hubs."); + } } From 0dfee66a495ace7ad8e185bdfa7e5455335c8a20 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Tue, 20 Aug 2024 17:00:13 +0200 Subject: [PATCH 070/111] update (e)shift task schedulers --- .../scheduler/EShiftTaskScheduler.java | 195 +++++++++--------- .../scheduler/ShiftTaskSchedulerImpl.java | 5 +- 2 files changed, 102 insertions(+), 98 deletions(-) diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/scheduler/EShiftTaskScheduler.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/scheduler/EShiftTaskScheduler.java index a87c54a1be8..9c5a7172282 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/scheduler/EShiftTaskScheduler.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/scheduler/EShiftTaskScheduler.java @@ -62,17 +62,17 @@ public class EShiftTaskScheduler implements ShiftTaskScheduler { private final Network network; private final ChargingInfrastructure chargingInfrastructure; - public EShiftTaskScheduler(Network network, TravelTime travelTime, TravelDisutility travelDisutility, - MobsimTimer timer, ShiftDrtTaskFactory taskFactory, ShiftsParams shiftsParams, - ChargingInfrastructure chargingInfrastructure, OperationFacilities operationFacilities, Fleet fleet) { - this.travelTime = travelTime; - this.timer = timer; - this.taskFactory = taskFactory; - this.network = network; - this.shiftsParams = shiftsParams; - this.router = new SpeedyALTFactory().createPathCalculator(network, travelDisutility, travelTime); - this.chargingInfrastructure = chargingInfrastructure; - } + public EShiftTaskScheduler(Network network, TravelTime travelTime, TravelDisutility travelDisutility, + MobsimTimer timer, ShiftDrtTaskFactory taskFactory, ShiftsParams shiftsParams, + ChargingInfrastructure chargingInfrastructure, OperationFacilities operationFacilities, Fleet fleet) { + this.travelTime = travelTime; + this.timer = timer; + this.taskFactory = taskFactory; + this.network = network; + this.shiftsParams = shiftsParams; + this.router = new SpeedyALTFactory().createPathCalculator(network, travelDisutility, travelTime); + this.chargingInfrastructure = chargingInfrastructure; + } public void relocateForBreak(ShiftDvrpVehicle vehicle, OperationFacility breakFacility, DrtShift shift) { final Schedule schedule = vehicle.getSchedule(); @@ -81,7 +81,7 @@ public void relocateForBreak(ShiftDvrpVehicle vehicle, OperationFacility breakFa final Link toLink = network.getLinks().get(breakFacility.getLinkId()); if (currentTask instanceof DriveTask && currentTask.getTaskType().equals(EmptyVehicleRelocator.RELOCATE_VEHICLE_TASK_TYPE) - && currentTask.equals(schedule.getTasks().get(schedule.getTaskCount()-2))) { + && currentTask.equals(schedule.getTasks().get(schedule.getTaskCount() - 2))) { //try to divert/cancel relocation LinkTimePair start = ((OnlineDriveTaskTracker) currentTask.getTaskTracker()).getDiversionPoint(); VrpPathWithTravelData path; @@ -112,13 +112,13 @@ public void relocateForBreak(ShiftDvrpVehicle vehicle, OperationFacility breakFa } else { final Task task = schedule.getTasks().get(schedule.getTaskCount() - 1); final Link lastLink = ((StayTask) task).getLink(); - double departureTime = task.getBeginTime(); + double departureTime = task.getBeginTime(); - // @Nico Did I change something here? - if (schedule.getCurrentTask() == task) { - departureTime = Math.max(task.getBeginTime(), timer.getTimeOfDay()); - } - if (lastLink.getId() != breakFacility.getLinkId()) { + // @Nico Did I change something here? + if (schedule.getCurrentTask() == task) { + departureTime = Math.max(task.getBeginTime(), timer.getTimeOfDay()); + } + if (lastLink.getId() != breakFacility.getLinkId()) { VrpPathWithTravelData path = VrpPaths.calcAndCreatePath(lastLink, toLink, departureTime, router, @@ -154,7 +154,7 @@ public void relocateForBreak(ShiftDvrpVehicle vehicle, OperationFacility breakFa double endTime = startTime + shift.getBreak().orElseThrow().getDuration(); double latestDetourArrival = timer.getTimeOfDay(); - relocateForBreakImpl(vehicle, startTime, endTime, latestDetourArrival, toLink, shift, breakFacility); + relocateForBreakImpl(vehicle, startTime, endTime, latestDetourArrival, toLink, shift, breakFacility); } } } @@ -165,24 +165,24 @@ private void relocateForBreakImpl(ShiftDvrpVehicle vehicle, double startTime, do Schedule schedule = vehicle.getSchedule(); // append SHIFT_BREAK task - DrtShiftBreak shiftBreak = shift.getBreak().orElseThrow(); + DrtShiftBreak shiftBreak = shift.getBreak().orElseThrow(); - ShiftBreakTask dropoffStopTask; - ElectricVehicle ev = ((EvDvrpVehicle) vehicle).getElectricVehicle(); - Optional charger = charge(breakFacility, ev); - if (charger.isPresent()) { + ShiftBreakTask dropoffStopTask; + ElectricVehicle ev = ((EvDvrpVehicle) vehicle).getElectricVehicle(); + Optional charger = charge(breakFacility, ev); + if (charger.isPresent()) { final Charger chargerImpl = charger.get(); - final double waitTime = ChargingEstimations - .estimateMaxWaitTimeForNextVehicle(chargerImpl); + final double waitTime = ChargingEstimations + .estimateMaxWaitTimeForNextVehicle(chargerImpl); - if (ev.getBattery().getCharge() / ev.getBattery().getCapacity() > shiftsParams.chargeDuringBreakThreshold || - waitTime > 0) { + if (ev.getBattery().getCharge() / ev.getBattery().getCapacity() > shiftsParams.chargeDuringBreakThreshold || + waitTime > 0) { dropoffStopTask = taskFactory.createShiftBreakTask(vehicle, startTime, endTime, link, shiftBreak, breakFacility); } else { - double energyCharge = ((BatteryCharging) ev.getChargingPower()).calcEnergyCharged(chargerImpl.getSpecification(), endTime - startTime); - double totalEnergy = -energyCharge; + double energyCharge = ((BatteryCharging) ev.getChargingPower()).calcEnergyCharged(chargerImpl.getSpecification(), endTime - startTime); + double totalEnergy = -energyCharge; ((ChargingWithAssignmentLogic) chargerImpl.getLogic()).assignVehicle(ev); dropoffStopTask = ((ShiftEDrtTaskFactoryImpl) taskFactory).createChargingShiftBreakTask(vehicle, startTime, endTime, link, shiftBreak, chargerImpl, totalEnergy, breakFacility); @@ -199,32 +199,32 @@ private void relocateForBreakImpl(ShiftDvrpVehicle vehicle, double startTime, do final double latestTimeConstraintArrival = shiftBreak.getLatestBreakEndTime() - shiftBreak.getDuration(); - shiftBreak.schedule(Math.min(latestDetourArrival, latestTimeConstraintArrival)); + shiftBreak.schedule(Math.min(latestDetourArrival, latestTimeConstraintArrival)); } private Optional charge(OperationFacility breakFacility, ElectricVehicle electricVehicle) { if (chargingInfrastructure != null) { - List> chargerIds = breakFacility.getChargers(); - if(!chargerIds.isEmpty()) { - Optional selectedCharger = chargerIds - .stream() - .map(id -> chargingInfrastructure.getChargers().get(id)) - .filter(charger -> shiftsParams.breakChargerType.equals(charger.getChargerType())) - .min((c1, c2) -> { - final double waitTime = ChargingEstimations - .estimateMaxWaitTimeForNextVehicle(c1); - final double waitTime2 = ChargingEstimations - .estimateMaxWaitTimeForNextVehicle(c2); - return Double.compare(waitTime, waitTime2); - }); - if(selectedCharger.isPresent()) { - if (selectedCharger.get().getLogic().getChargingStrategy().isChargingCompleted(electricVehicle)) { - return Optional.empty(); - } - } - return selectedCharger; - } - } + List> chargerIds = breakFacility.getChargers(); + if (!chargerIds.isEmpty()) { + Optional selectedCharger = chargerIds + .stream() + .map(id -> chargingInfrastructure.getChargers().get(id)) + .filter(charger -> shiftsParams.breakChargerType.equals(charger.getChargerType())) + .min((c1, c2) -> { + final double waitTime = ChargingEstimations + .estimateMaxWaitTimeForNextVehicle(c1); + final double waitTime2 = ChargingEstimations + .estimateMaxWaitTimeForNextVehicle(c2); + return Double.compare(waitTime, waitTime2); + }); + if (selectedCharger.isPresent()) { + if (selectedCharger.get().getLogic().getChargingStrategy().isChargingCompleted(electricVehicle)) { + return Optional.empty(); + } + } + return selectedCharger; + } + } return Optional.empty(); } @@ -234,7 +234,7 @@ public void relocateForShiftChange(DvrpVehicle vehicle, Link link, DrtShift shif final Task currentTask = schedule.getCurrentTask(); if (currentTask instanceof DriveTask && currentTask.getTaskType().equals(EmptyVehicleRelocator.RELOCATE_VEHICLE_TASK_TYPE) - && currentTask.equals(schedule.getTasks().get(schedule.getTaskCount()-2))) { + && currentTask.equals(schedule.getTasks().get(schedule.getTaskCount() - 2))) { //try to divert/cancel relocation LinkTimePair start = ((OnlineDriveTaskTracker) currentTask.getTaskTracker()).getDiversionPoint(); VrpPathWithTravelData path; @@ -317,22 +317,22 @@ private void appendShiftChange(DvrpVehicle vehicle, DrtShift shift, OperationFac // append SHIFT_CHANGEOVER task - ElectricVehicle ev = ((EvDvrpVehicle) vehicle).getElectricVehicle(); - Optional charger = charge(breakFacility, ev); - if (charger.isPresent()) { - Charger chargingImpl = charger.get(); + ElectricVehicle ev = ((EvDvrpVehicle) vehicle).getElectricVehicle(); + Optional charger = charge(breakFacility, ev); + if (charger.isPresent()) { + Charger chargingImpl = charger.get(); - final double waitTime = ChargingEstimations - .estimateMaxWaitTimeForNextVehicle(chargingImpl); + final double waitTime = ChargingEstimations + .estimateMaxWaitTimeForNextVehicle(chargingImpl); - if (ev.getBattery().getCharge() / ev.getBattery().getCapacity() < shiftsParams.chargeDuringBreakThreshold + if (ev.getBattery().getCharge() / ev.getBattery().getCapacity() < shiftsParams.chargeDuringBreakThreshold || ((ChargingWithAssignmentLogic) chargingImpl.getLogic()).getAssignedVehicles().contains(ev) - || waitTime >0) { + || waitTime > 0) { dropoffStopTask = taskFactory.createShiftChangeoverTask(vehicle, startTime, endTime, link, shift, breakFacility); } else { - double energyCharge = ((BatteryCharging) ev.getChargingPower()).calcEnergyCharged(chargingImpl.getSpecification(), endTime - startTime); - double totalEnergy = -energyCharge; + double energyCharge = ((BatteryCharging) ev.getChargingPower()).calcEnergyCharged(chargingImpl.getSpecification(), endTime - startTime); + double totalEnergy = -energyCharge; ((ChargingWithAssignmentLogic) chargingImpl.getLogic()).assignVehicle(ev); dropoffStopTask = ((ShiftEDrtTaskFactoryImpl) taskFactory).createChargingShiftChangeoverTask(vehicle, startTime, endTime, link, chargingImpl, totalEnergy, shift, breakFacility); @@ -353,9 +353,11 @@ public void startShift(ShiftDvrpVehicle vehicle, double now, DrtShift shift) { if (stayTask instanceof WaitForShiftTask) { ((WaitForShiftTask) stayTask).getFacility().deregisterVehicle(vehicle.getId()); stayTask.setEndTime(now); - if(Schedules.getLastTask(schedule).equals(stayTask)) { + if (Schedules.getLastTask(schedule).equals(stayTask)) { //nothing planned yet. schedule.addTask(taskFactory.createStayTask(vehicle, now, shift.getEndTime(), stayTask.getLink())); + } else { + Schedules.getNextTask(schedule).setBeginTime(now); } } else { throw new IllegalStateException("Vehicle cannot start shift during task:" + stayTask.getTaskType().name()); @@ -370,9 +372,9 @@ public boolean updateShiftChange(ShiftDvrpVehicle vehicle, Link link, DrtShift s VrpPathWithTravelData path = VrpPaths.calcAndCreatePath(start.link, link, Math.max(start.time, timer.getTimeOfDay()), router, travelTime); //if (path.getArrivalTime() <= shift.getEndTime()) { - updateShiftChangeImpl(vehicle, path, shift, facility, lastTask); - return true; - // } + updateShiftChangeImpl(vehicle, path, shift, facility, lastTask); + return true; + // } } return false; } @@ -381,29 +383,28 @@ public boolean updateShiftChange(ShiftDvrpVehicle vehicle, Link link, DrtShift s public void planAssignedShift(ShiftDvrpVehicle vehicle, double timeStep, DrtShift shift) { Schedule schedule = vehicle.getSchedule(); StayTask stayTask = (StayTask) schedule.getCurrentTask(); - if (stayTask instanceof WaitForShiftTask waitForShiftTask) { - if(waitForShiftTask instanceof EDrtWaitForShiftTask eDrtWaitForShiftTask) { - if(eDrtWaitForShiftTask.getChargingTask() != null) { - Task nextTask = Schedules.getNextTask(vehicle.getSchedule()); - if(nextTask instanceof WaitForShiftTask) { - // set +1 to ensure this update happens after next shift start check - nextTask.setEndTime(Math.max(timeStep + 1, shift.getStartTime())); - //append stay task if required - if(Schedules.getLastTask(schedule).equals(nextTask)) { - schedule.addTask(taskFactory.createStayTask(vehicle, nextTask.getEndTime(), shift.getEndTime(), ((WaitForShiftTask) nextTask).getLink())); - } - } else { - throw new RuntimeException(); - } - } else { - stayTask.setEndTime(Math.max(timeStep +1 , shift.getStartTime())); + if (stayTask instanceof EDrtWaitForShiftTask eDrtWaitForShiftTask) { + if (eDrtWaitForShiftTask.getChargingTask() != null) { + Task nextTask = Schedules.getNextTask(vehicle.getSchedule()); + if (nextTask instanceof WaitForShiftTask) { + // set +1 to ensure this update happens after next shift start check + nextTask.setEndTime(Math.max(timeStep + 1, shift.getStartTime())); //append stay task if required - if(Schedules.getLastTask(schedule).equals(stayTask)) { - schedule.addTask(taskFactory.createStayTask(vehicle, stayTask.getEndTime(), shift.getEndTime(), stayTask.getLink())); + if (Schedules.getLastTask(schedule).equals(nextTask)) { + schedule.addTask(taskFactory.createStayTask(vehicle, nextTask.getEndTime(), shift.getEndTime(), ((WaitForShiftTask) nextTask).getLink())); } + } else { + throw new RuntimeException(); + } + } else { + stayTask.setEndTime(Math.max(timeStep + 1, shift.getStartTime())); + //append stay task if required + if (Schedules.getLastTask(schedule).equals(stayTask)) { + schedule.addTask(taskFactory.createStayTask(vehicle, stayTask.getEndTime(), shift.getEndTime(), stayTask.getLink())); } } } + } @@ -412,10 +413,10 @@ public void cancelAssignedShift(ShiftDvrpVehicle vehicle, double timeStep, DrtSh Schedule schedule = vehicle.getSchedule(); StayTask stayTask = (StayTask) schedule.getCurrentTask(); if (stayTask instanceof WaitForShiftTask waitForShiftTask) { - if(waitForShiftTask instanceof EDrtWaitForShiftTask eDrtWaitForShiftTask) { - if(eDrtWaitForShiftTask.getChargingTask() != null) { + if (waitForShiftTask instanceof EDrtWaitForShiftTask eDrtWaitForShiftTask) { + if (eDrtWaitForShiftTask.getChargingTask() != null) { Task nextTask = Schedules.getNextTask(vehicle.getSchedule()); - if(nextTask instanceof WaitForShiftTask) { + if (nextTask instanceof WaitForShiftTask) { nextTask.setEndTime(vehicle.getServiceEndTime()); } else { throw new RuntimeException(); @@ -433,15 +434,15 @@ private void updateShiftChangeImpl(DvrpVehicle vehicle, VrpPathWithTravelData vr DrtShift shift, OperationFacility facility, Task lastTask) { Schedule schedule = vehicle.getSchedule(); - Optional oldChangeOver = ShiftSchedules.getNextShiftChangeover(schedule); - if(oldChangeOver.isPresent() && oldChangeOver.get() instanceof EDrtShiftChangeoverTaskImpl) { - if(((EDrtShiftChangeoverTaskImpl) oldChangeOver.get()).getChargingTask() != null) { - ElectricVehicle ev = ((EvDvrpVehicle) vehicle).getElectricVehicle(); - ((EDrtShiftChangeoverTaskImpl) oldChangeOver.get()).getChargingTask().getChargingLogic().unassignVehicle(ev); - } - } + Optional oldChangeOver = ShiftSchedules.getNextShiftChangeover(schedule); + if (oldChangeOver.isPresent() && oldChangeOver.get() instanceof EDrtShiftChangeoverTaskImpl) { + if (((EDrtShiftChangeoverTaskImpl) oldChangeOver.get()).getChargingTask() != null) { + ElectricVehicle ev = ((EvDvrpVehicle) vehicle).getElectricVehicle(); + ((EDrtShiftChangeoverTaskImpl) oldChangeOver.get()).getChargingTask().getChargingLogic().unassignVehicle(ev); + } + } - List copy = new ArrayList<>(schedule.getTasks().subList(lastTask.getTaskIdx() + 1, schedule.getTasks().size())); + List copy = new ArrayList<>(schedule.getTasks().subList(lastTask.getTaskIdx() + 1, schedule.getTasks().size())); for (Task task : copy) { schedule.removeTask(task); } @@ -449,7 +450,7 @@ private void updateShiftChangeImpl(DvrpVehicle vehicle, VrpPathWithTravelData vr ((OnlineDriveTaskTracker) lastTask.getTaskTracker()).divertPath(vrpPath); } else { //add drive to break location - lastTask.setEndTime(vrpPath.getDepartureTime()); + lastTask.setEndTime(vrpPath.getDepartureTime()); schedule.addTask(taskFactory.createDriveTask(vehicle, vrpPath, RELOCATE_VEHICLE_SHIFT_CHANGEOVER_TASK_TYPE)); // add RELOCATE } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskSchedulerImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskSchedulerImpl.java index 94b5c3d0fed..c2fcc1ac4ee 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskSchedulerImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskSchedulerImpl.java @@ -269,6 +269,8 @@ public void startShift(ShiftDvrpVehicle vehicle, double now, DrtShift shift) { if(Schedules.getLastTask(schedule).equals(stayTask)) { //nothing planned yet. schedule.addTask(taskFactory.createStayTask(vehicle, now, shift.getEndTime(), stayTask.getLink())); + } else { + Schedules.getNextTask(schedule).setBeginTime(now); } } else { throw new IllegalStateException("Vehicle cannot start shift during task:" + stayTask.getTaskType().name()); @@ -296,7 +298,8 @@ public void planAssignedShift(ShiftDvrpVehicle vehicle, double timeStep, DrtShif Schedule schedule = vehicle.getSchedule(); StayTask stayTask = (StayTask) schedule.getCurrentTask(); if (stayTask instanceof WaitForShiftTask) { - stayTask.setEndTime(Math.max(timeStep, shift.getStartTime())); + // set +1 to ensure this update happens after next shift start check + stayTask.setEndTime(Math.max(timeStep + 1, shift.getStartTime())); } } From b2f35162bf97f5eec2b5755c16f59f96fb8b2f5b Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Tue, 20 Aug 2024 17:05:51 +0200 Subject: [PATCH 071/111] update (e)shift task schedulers --- .../DefaultRequestInsertionScheduler.java | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java index 72082906255..bab43ffc742 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java @@ -24,6 +24,7 @@ import java.util.List; +import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.contrib.drt.optimizer.VehicleEntry; import org.matsim.contrib.drt.optimizer.Waypoint; @@ -37,6 +38,7 @@ import org.matsim.contrib.drt.stops.StopTimeCalculator; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.Fleet; +import org.matsim.contrib.dvrp.path.DivertedVrpPath; import org.matsim.contrib.dvrp.path.VrpPathWithTravelData; import org.matsim.contrib.dvrp.path.VrpPaths; import org.matsim.contrib.dvrp.schedule.DriveTask; @@ -65,9 +67,9 @@ public class DefaultRequestInsertionScheduler implements RequestInsertionSchedul private final StopTimeCalculator stopTimeCalculator; private final boolean scheduleWaitBeforeDrive; - public DefaultRequestInsertionScheduler(Fleet fleet, MobsimTimer timer, - TravelTime travelTime, ScheduleTimingUpdater scheduleTimingUpdater, DrtTaskFactory taskFactory, - StopTimeCalculator stopTimeCalculator, boolean scheduleWaitBeforeDrive) { + public DefaultRequestInsertionScheduler(Fleet fleet, MobsimTimer timer, TravelTime travelTime, + ScheduleTimingUpdater scheduleTimingUpdater, DrtTaskFactory taskFactory, + StopTimeCalculator stopTimeCalculator, boolean scheduleWaitBeforeDrive) { this.timer = timer; this.travelTime = travelTime; this.scheduleTimingUpdater = scheduleTimingUpdater; @@ -143,7 +145,7 @@ private void verifyConstraints(InsertionWithDetourData insertion) { } private void verifyStructure(Schedule schedule) { - boolean previousDrive = false; + DriveTask previousDrive = null; int startIndex = schedule.getStatus().equals(ScheduleStatus.STARTED) ? schedule.getCurrentTask().getTaskIdx() : 0; @@ -151,11 +153,18 @@ private void verifyStructure(Schedule schedule) { for (int index = startIndex; index < schedule.getTaskCount(); index++) { Task task = schedule.getTasks().get(index); - if (task instanceof DriveTask) { - Verify.verify(!previousDrive); - previousDrive = true; + if (task instanceof DriveTask driveTask) { + if(previousDrive != null) { + Verify.verify(previousDrive.getPath() instanceof DivertedVrpPath, + "The first of two subsequent drive tasks has to be a diverted path."); + Id firstEnd = previousDrive.getPath().getToLink().getId(); + Id secondStart = driveTask.getPath().getFromLink().getId(); + Verify.verify(firstEnd.equals(secondStart), + String.format("Subsequent drive tasks are not connected link %s !=> %s", firstEnd.toString(), secondStart.toString())); + } + previousDrive = driveTask; } else { - previousDrive = false; + previousDrive = null; } } } @@ -343,7 +352,7 @@ private DrtStopTask insertPickup(AcceptedDrtRequest request, InsertionWithDetour } private DrtStopTask insertDropoff(AcceptedDrtRequest request, InsertionWithDetourData insertionWithDetourData, - DrtStopTask pickupTask) { + DrtStopTask pickupTask) { final double now = timer.getTimeOfDay(); var insertion = insertionWithDetourData.insertion; VehicleEntry vehicleEntry = insertion.vehicleEntry; From f236ed27145796ae6e4d1fa8ed47dc1ed0058f3c Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Wed, 21 Aug 2024 15:30:29 +0200 Subject: [PATCH 072/111] dump shifts after each iteration --- .../shifts/analysis/RegularShiftDump.java | 45 +++++++++++++++++++ .../shifts/run/ShiftDrtModeModule.java | 11 +++++ 2 files changed, 56 insertions(+) create mode 100644 contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/RegularShiftDump.java diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/RegularShiftDump.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/RegularShiftDump.java new file mode 100644 index 00000000000..4d0f1d8c110 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/RegularShiftDump.java @@ -0,0 +1,45 @@ +package org.matsim.contrib.drt.extension.operations.shifts.analysis; + +import com.google.inject.Provider; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.contrib.drt.extension.operations.shifts.io.DrtShiftsWriter; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.controler.events.IterationEndsEvent; +import org.matsim.core.controler.listener.IterationEndsListener; + + +/** + * + * @author nkuehnel / MOIA + */ +final public class RegularShiftDump implements IterationEndsListener { + private static final Logger log = LogManager.getLogger( RegularShiftDump.class ); + + private final Provider shifts; + + + private final OutputDirectoryHierarchy controlerIO; + + public RegularShiftDump(Provider shifts, OutputDirectoryHierarchy controlerIO) { + this.shifts = shifts; + this.controlerIO = controlerIO; + } + + private void dumpShiftPans(int iteration) { + try { + if ( this.shifts!=null){ + new DrtShiftsWriter(shifts.get()).writeFile(this.controlerIO.getIterationFilename(iteration, "output_shifts.xml.gz")); + } + } catch ( Exception ee ) { + log.error("Exception writing shifts.", ee); + } + } + + + @Override + public void notifyIterationEnds(IterationEndsEvent event) { + dumpShiftPans(event.getIteration()); + } +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java index 8b52ca88951..9a31f334f27 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java @@ -137,5 +137,16 @@ public void install() { addControlerListenerBinding().toProvider(modalProvider(getter -> new ProfileWriter(getter.get(MatsimServices.class), drtConfigGroup.getMode(), new VehicleTaskProfileView(getter.getModal(VehicleTaskProfileCalculator.class), taskTypeComparator, taskTypePaints), "shift_task_time_profiles"))).in(Singleton.class); + + bindModal(RegularShiftDump.class).toProvider(modalProvider( + getter -> new RegularShiftDump( + getter.getModal(new TypeLiteral>(){}), + getter.get(OutputDirectoryHierarchy.class) + )) + ).asEagerSingleton(); + + addControlerListenerBinding().toProvider(modalProvider( + getter -> getter.getModal(RegularShiftDump.class) + )); } } From d3ebe1d47503ce6c10990165b659681df5b24718 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Thu, 22 Aug 2024 16:24:32 +0200 Subject: [PATCH 073/111] some updates to drt shifts --- .../run/ShiftEDrtModeOptimizerQSimModule.java | 26 +-- .../analysis/DumpShiftDataAtEndImpl.java | 10 +- .../shifts/analysis/RegularShiftDump.java | 1 - .../shifts/analysis/ShiftDurationXY.java | 26 ++- .../shifts/analysis/ShiftHistogram.java | 36 ++- .../dispatcher/DefaultShiftScheduler.java | 51 +++++ .../dispatcher/DrtShiftDispatcherImpl.java | 45 ++-- .../shifts/dispatcher/ShiftScheduler.java | 19 ++ .../shifts/run/ShiftDrtModeModule.java | 26 ++- .../run/ShiftDrtModeOptimizerQSimModule.java | 40 +--- .../operations/shifts/shift/DrtShift.java | 2 +- .../operations/shifts/shift/DrtShiftImpl.java | 5 + .../run/RunOnTheFlyShiftDrtScenarioIT.java | 210 ++++++++++++++++++ .../run/RunPrebookingShiftDrtScenarioIT.java | 10 +- 14 files changed, 388 insertions(+), 119 deletions(-) create mode 100644 contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DefaultShiftScheduler.java create mode 100644 contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/ShiftScheduler.java create mode 100644 contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunOnTheFlyShiftDrtScenarioIT.java diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java index aefdfeb5e6c..32bf96909bf 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java @@ -17,15 +17,12 @@ import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilities; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilityFinder; import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; -import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DefaultAssignShiftToVehicleLogic; -import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DefaultShiftStartLogic; -import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DrtShiftDispatcher; -import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DrtShiftDispatcherImpl; +import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.*; import org.matsim.contrib.drt.extension.operations.shifts.optimizer.ShiftVehicleDataEntryFactory; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftDrtActionCreator; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftDrtTaskFactory; import org.matsim.contrib.drt.extension.operations.shifts.scheduler.ShiftTaskScheduler; -import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShifts; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; import org.matsim.contrib.drt.optimizer.VehicleEntry; import org.matsim.contrib.drt.prebooking.PrebookingActionCreator; import org.matsim.contrib.drt.run.DrtConfigGroup; @@ -67,19 +64,22 @@ protected void configureQSim() { ).asEagerSingleton(); bindModal(DrtShiftDispatcher.class).toProvider(modalProvider( - getter -> new EDrtShiftDispatcherImpl(((EShiftTaskScheduler) getter.getModal(ShiftTaskScheduler.class)), getter.getModal(ChargingInfrastructure.class), - drtShiftParams, getter.getModal(OperationFacilities.class), new DrtShiftDispatcherImpl(getMode(), - getter.getModal(DrtShifts.class), getter.getModal(Fleet.class), - getter.get(MobsimTimer.class), getter.getModal(OperationFacilities.class), getter.getModal(OperationFacilityFinder.class), - getter.getModal(ShiftTaskScheduler.class), getter.getModal(Network.class), getter.get(EventsManager.class), - drtShiftParams, new EDrtShiftStartLogic(new DefaultShiftStartLogic()), - new EDrtAssignShiftToVehicleLogic(new DefaultAssignShiftToVehicleLogic(drtShiftParams), drtShiftParams)), - getter.getModal(Fleet.class)))).asEagerSingleton(); + getter -> new EDrtShiftDispatcherImpl(((EShiftTaskScheduler) getter.getModal(ShiftTaskScheduler.class)), + getter.getModal(ChargingInfrastructure.class), drtShiftParams, getter.getModal(OperationFacilities.class), + new DrtShiftDispatcherImpl(getMode(), getter.getModal(Fleet.class), getter.get(MobsimTimer.class), + getter.getModal(OperationFacilities.class), getter.getModal(OperationFacilityFinder.class), + getter.getModal(ShiftTaskScheduler.class), getter.getModal(Network.class), getter.get(EventsManager.class), + drtShiftParams, new EDrtShiftStartLogic(new DefaultShiftStartLogic()), + new EDrtAssignShiftToVehicleLogic(new DefaultAssignShiftToVehicleLogic(drtShiftParams), drtShiftParams), + getter.getModal(ShiftScheduler.class)), + getter.getModal(Fleet.class))) + ).asEagerSingleton(); bindModal(VehicleEntry.EntryFactory.class).toProvider(modalProvider(getter -> new ShiftVehicleDataEntryFactory(new EDrtVehicleDataEntryFactory(0), drtShiftParams.considerUpcomingShiftsForInsertion))).asEagerSingleton(); + bindModal(DrtTaskFactory.class).toProvider(modalProvider(getter -> new ShiftEDrtTaskFactoryImpl(new EDrtTaskFactoryImpl(), getter.getModal(OperationFacilities.class)))).in(Singleton.class); bindModal(ShiftDrtTaskFactory.class).toProvider(modalProvider(getter -> ((ShiftDrtTaskFactory) getter.getModal(DrtTaskFactory.class)))); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/DumpShiftDataAtEndImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/DumpShiftDataAtEndImpl.java index 0960125e49d..ee65d26d4fd 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/DumpShiftDataAtEndImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/DumpShiftDataAtEndImpl.java @@ -2,16 +2,14 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesSpecification; import org.matsim.contrib.drt.extension.operations.shifts.io.DrtShiftsWriter; import org.matsim.contrib.drt.extension.operations.shifts.io.OperationFacilitiesWriter; -import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesSpecification; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.core.controler.events.ShutdownEvent; import org.matsim.core.controler.listener.ShutdownListener; -import jakarta.inject.Provider; - /** * Dumps DRT shift related data at end. Based on {@link org.matsim.core.controler.corelisteners.DumpDataAtEndImpl} * @@ -20,13 +18,13 @@ final public class DumpShiftDataAtEndImpl implements ShutdownListener { private static final Logger log = LogManager.getLogger( DumpShiftDataAtEndImpl.class ); - private final Provider shifts; + private final DrtShiftsSpecification shifts; private final OperationFacilitiesSpecification operationFacilities; private final OutputDirectoryHierarchy controlerIO; - public DumpShiftDataAtEndImpl(Provider shifts, OperationFacilitiesSpecification operationFacilities, OutputDirectoryHierarchy controlerIO) { + public DumpShiftDataAtEndImpl(DrtShiftsSpecification shifts, OperationFacilitiesSpecification operationFacilities, OutputDirectoryHierarchy controlerIO) { this.shifts = shifts; this.operationFacilities = operationFacilities; this.controlerIO = controlerIO; @@ -44,7 +42,7 @@ public void notifyShutdown(ShutdownEvent event) { private void dumpShiftPans() { try { if ( this.shifts!=null){ - new DrtShiftsWriter(shifts.get()).writeFile(this.controlerIO.getOutputFilename("output_shifts.xml.gz")); + new DrtShiftsWriter(shifts).writeFile(this.controlerIO.getOutputFilename("output_shifts.xml.gz")); } } catch ( Exception ee ) { log.error("Exception writing shifts.", ee); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/RegularShiftDump.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/RegularShiftDump.java index 4d0f1d8c110..908f66d0008 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/RegularShiftDump.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/RegularShiftDump.java @@ -19,7 +19,6 @@ final public class RegularShiftDump implements IterationEndsListener { private final Provider shifts; - private final OutputDirectoryHierarchy controlerIO; public RegularShiftDump(Provider shifts, OutputDirectoryHierarchy controlerIO) { diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftDurationXY.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftDurationXY.java index 809e4385323..43af5244e69 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftDurationXY.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftDurationXY.java @@ -58,22 +58,28 @@ public void handleEvent(DrtShiftBreakStartedEvent event) { @Override public void handleEvent(final DrtShiftEndedEvent event) { if (event.getMode().equals(mode)) { - final Double start = shift2StartTime.get(event.getShiftId()); - double duration = event.getTime() - start; - final DrtShiftSpecification drtShift = shifts.get().getShiftSpecifications().get(event.getShiftId()); - double plannedDuration = drtShift.getEndTime() - drtShift.getStartTime(); - shift2plannedVsActualDuration.put(event.getShiftId(), new Tuple<>(plannedDuration, duration)); + Map, DrtShiftSpecification> shiftSpecifications = shifts.get().getShiftSpecifications(); + if(shiftSpecifications.containsKey(event.getShiftId())) { + final DrtShiftSpecification drtShift = shiftSpecifications.get(event.getShiftId()); + final Double start = shift2StartTime.get(event.getShiftId()); + double duration = event.getTime() - start; + double plannedDuration = drtShift.getEndTime() - drtShift.getStartTime(); + shift2plannedVsActualDuration.put(event.getShiftId(), new Tuple<>(plannedDuration, duration)); + } } } @Override public void handleEvent(DrtShiftBreakEndedEvent event) { if (event.getMode().equals(mode)) { - final Double start = shift2BreakStartTime.get(event.getShiftId()); - double duration = event.getTime() - start; - final DrtShiftBreakSpecification drtShift = shifts.get().getShiftSpecifications().get(event.getShiftId()).getBreak().orElseThrow(); - double plannedDuration = drtShift.getDuration(); - shift2plannedVsActualBreakDuration.put(event.getShiftId(), new Tuple<>(plannedDuration, duration)); + Map, DrtShiftSpecification> shiftSpecifications = shifts.get().getShiftSpecifications(); + if(shiftSpecifications.containsKey(event.getShiftId())) { + final Double start = shift2BreakStartTime.get(event.getShiftId()); + double duration = event.getTime() - start; + final DrtShiftBreakSpecification drtShift = shifts.get().getShiftSpecifications().get(event.getShiftId()).getBreak().orElseThrow(); + double plannedDuration = drtShift.getDuration(); + shift2plannedVsActualBreakDuration.put(event.getShiftId(), new Tuple<>(plannedDuration, duration)); + } } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftHistogram.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftHistogram.java index 00dc4e85a02..b2539c40ba7 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftHistogram.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftHistogram.java @@ -1,9 +1,6 @@ package org.matsim.contrib.drt.extension.operations.shifts.analysis; -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.population.Population; import org.matsim.contrib.drt.extension.operations.shifts.events.*; -import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShift; import org.matsim.core.config.Config; import org.matsim.core.utils.io.IOUtils; import org.matsim.core.utils.misc.Time; @@ -12,35 +9,30 @@ import java.io.OutputStream; import java.io.PrintStream; import java.io.UncheckedIOException; -import java.util.Set; /** * @author nkuehnel / MOIA */ public class ShiftHistogram implements DrtShiftStartedEventHandler, DrtShiftEndedEventHandler, - DrtShiftBreakStartedEventHandler, DrtShiftBreakEndedEventHandler { + DrtShiftBreakStartedEventHandler, DrtShiftBreakEndedEventHandler { private final String mode; - public static final int DEFAULT_END_TIME = 30 * 3600; - public static final int DEFAULT_BIN_SIZE = 300; + public static final int DEFAULT_END_TIME = 30 * 3600; + public static final int DEFAULT_BIN_SIZE = 300; - private Set> shiftIds; private int iteration = 0; private final int binSize; private final int nofBins; private DataFrame data = null; - public ShiftHistogram(Population population, String mode, Config config) { - super(); + public ShiftHistogram(String mode, Config config) { + super(); this.mode = mode; this.binSize = DEFAULT_BIN_SIZE; - this.nofBins = ((int) config.qsim().getEndTime().orElse(DEFAULT_END_TIME) ) / this.binSize + 1; - reset(0); - if (population == null) { - this.shiftIds = null; - } + this.nofBins = ((int) config.qsim().getEndTime().orElse(DEFAULT_END_TIME)) / this.binSize + 1; + reset(0); } /** @@ -63,10 +55,9 @@ public ShiftHistogram(String mode, final int binSize, final int nofBins) { public void handleEvent(final DrtShiftStartedEvent event) { if (event.getMode().equals(mode)) { int index = getBinIndex(event.getTime()); - if ((this.shiftIds == null || this.shiftIds.contains(event.getShiftId()))) { - DataFrame dataFrame = getData(); - dataFrame.countsStart[index]++; - } + DataFrame dataFrame = getData(); + dataFrame.countsStart[index]++; + } } @@ -74,10 +65,9 @@ public void handleEvent(final DrtShiftStartedEvent event) { public void handleEvent(final DrtShiftEndedEvent event) { if (event.getMode().equals(mode)) { int index = getBinIndex(event.getTime()); - if ((this.shiftIds == null || this.shiftIds.contains(event.getShiftId()))) { - DataFrame dataFrame = getData(); - dataFrame.countsEnd[index]++; - } + DataFrame dataFrame = getData(); + dataFrame.countsEnd[index]++; + } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DefaultShiftScheduler.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DefaultShiftScheduler.java new file mode 100644 index 00000000000..f512ec3a6d1 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DefaultShiftScheduler.java @@ -0,0 +1,51 @@ +package org.matsim.contrib.drt.extension.operations.shifts.dispatcher; + +import com.google.common.collect.ImmutableMap; +import org.matsim.api.core.v01.Id; +import org.matsim.contrib.drt.extension.operations.shifts.shift.*; + +import java.util.Collections; +import java.util.List; +import java.util.function.Function; + +/** + * @author nkuehnel / MOIA + */ +public final class DefaultShiftScheduler implements ShiftScheduler { + + private final DrtShiftsSpecification shiftsSpecification; + public static Function createShiftFromSpec = spec -> { + DefaultShiftBreakImpl shiftBreak = null; + DrtShiftBreakSpecification breakSpec = spec.getBreak().orElse(null); + if (breakSpec != null) { + shiftBreak = new DefaultShiftBreakImpl( + breakSpec.getEarliestBreakStartTime(), + breakSpec.getLatestBreakEndTime(), + breakSpec.getDuration()); + } + return (DrtShift) new DrtShiftImpl(spec.getId(), spec.getStartTime(), spec.getEndTime(), + spec.getOperationFacilityId().orElse(null), spec.getDesignatedVehicleId().orElse(null), + shiftBreak); + }; + + public DefaultShiftScheduler(DrtShiftsSpecification shiftsSpecification) { + this.shiftsSpecification = shiftsSpecification; + } + @Override + public List schedule(double time) { + return Collections.emptyList(); + } + + @Override + public ImmutableMap, DrtShift> initialSchedule() { + return shiftsSpecification.getShiftSpecifications().values() + .stream() + .map(createShiftFromSpec) + .collect(ImmutableMap.toImmutableMap(DrtShift::getId, s -> s)); + } + + @Override + public DrtShiftsSpecification get() { + return shiftsSpecification; + } +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java index b021d811b3b..c2ed2b8acec 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java @@ -20,7 +20,6 @@ import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftSchedules; import org.matsim.contrib.drt.extension.operations.shifts.scheduler.ShiftTaskScheduler; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShift; -import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShifts; import org.matsim.contrib.drt.schedule.DrtDriveTask; import org.matsim.contrib.drt.schedule.DrtStayTask; import org.matsim.contrib.drt.schedule.DrtStopTask; @@ -51,7 +50,7 @@ public class DrtShiftDispatcherImpl implements DrtShiftDispatcher { private final String mode; - private SortedSet unscheduledShifts; + private SortedSet unAssignedShifts; private SortedSet assignedShifts; private SortedSet activeShifts; private SortedSet endingShifts; @@ -59,7 +58,6 @@ public class DrtShiftDispatcherImpl implements DrtShiftDispatcher { private Map, Queue> idleVehiclesQueues; private final Fleet fleet; - private final DrtShifts shifts; private final MobsimTimer timer; @@ -76,12 +74,14 @@ public class DrtShiftDispatcherImpl implements DrtShiftDispatcher { private final ShiftStartLogic shiftStartLogic; private final AssignShiftToVehicleLogic assignShiftToVehicleLogic; - public DrtShiftDispatcherImpl(String mode, DrtShifts shifts, Fleet fleet, MobsimTimer timer, OperationFacilities operationFacilities, + private final ShiftScheduler shiftScheduler; + + public DrtShiftDispatcherImpl(String mode, Fleet fleet, MobsimTimer timer, OperationFacilities operationFacilities, OperationFacilityFinder breakFacilityFinder, ShiftTaskScheduler shiftTaskScheduler, Network network, EventsManager eventsManager, ShiftsParams drtShiftParams, - ShiftStartLogic shiftStartLogic, AssignShiftToVehicleLogic assignShiftToVehicleLogic) { + ShiftStartLogic shiftStartLogic, AssignShiftToVehicleLogic assignShiftToVehicleLogic, + ShiftScheduler shiftScheduler) { this.mode = mode; - this.shifts = shifts; this.fleet = fleet; this.timer = timer; this.operationFacilities = operationFacilities; @@ -92,15 +92,25 @@ public DrtShiftDispatcherImpl(String mode, DrtShifts shifts, Fleet fleet, Mobsim this.drtShiftParams = drtShiftParams; this.shiftStartLogic = shiftStartLogic; this.assignShiftToVehicleLogic = assignShiftToVehicleLogic; + this.shiftScheduler = shiftScheduler; } @Override public void initialize() { - unscheduledShifts = new TreeSet<>(Comparator.comparingDouble(DrtShift::getStartTime)); - unscheduledShifts.addAll(shifts.getShifts().values()); + unAssignedShifts = new TreeSet<>(Comparator.comparingDouble(DrtShift::getStartTime).thenComparing(Comparator.naturalOrder())); + unAssignedShifts.addAll(shiftScheduler.initialSchedule().values()); + + assignedShifts = new TreeSet<>(Comparator + .comparingDouble((ShiftEntry entry) -> entry.shift().getStartTime()) + .thenComparing(ShiftEntry::shift)); - assignedShifts = new TreeSet<>(Comparator.comparingDouble(v -> v.shift().getStartTime())); + activeShifts = new TreeSet<>(Comparator + .comparingDouble((ShiftEntry entry) -> entry.shift().getEndTime()) + .thenComparing(ShiftEntry::shift)); + endingShifts = new TreeSet<>(Comparator + .comparingDouble((ShiftEntry entry) -> entry.shift().getEndTime()) + .thenComparing(ShiftEntry::shift)); idleVehiclesQueues = new LinkedHashMap<>(); for(OperationFacility facility: operationFacilities.getDrtOperationFacilities().values()) { @@ -114,15 +124,13 @@ public void initialize() { queue ); } - activeShifts = new TreeSet<>(Comparator.comparingDouble(v -> v.shift().getEndTime())); - endingShifts = new TreeSet<>(Comparator.comparingDouble(v -> v.shift().getEndTime())); } @Override public void dispatch(double timeStep) { if(timeStep % drtShiftParams.loggingInterval == 0) { logger.info(String.format("Active shifts: %s | Assigned shifts: %s | Unscheduled shifts: %s", - activeShifts.size(), assignedShifts.size(), unscheduledShifts.size())); + activeShifts.size(), assignedShifts.size(), unAssignedShifts.size())); StringJoiner print = new StringJoiner(" | "); for (Map.Entry, Queue> queueEntry : idleVehiclesQueues.entrySet()) { print.add(String.format("Idle vehicles at facility %s: %d", queueEntry.getKey().toString(), queueEntry.getValue().size())); @@ -133,6 +141,7 @@ public void dispatch(double timeStep) { if (timeStep % (drtShiftParams.updateShiftEndInterval) == 0) { updateShiftEnds(timeStep); } + scheduleShifts(timeStep); assignShifts(timeStep); startShifts(timeStep); checkBreaks(); @@ -162,6 +171,12 @@ private void checkBreaks() { } } + + private void scheduleShifts(double timeStep) { + List scheduled = shiftScheduler.schedule(timeStep); + unAssignedShifts.addAll(scheduled); + } + private void startShifts(double timeStep) { final Iterator iterator = this.assignedShifts.iterator(); while (iterator.hasNext()) { @@ -194,7 +209,7 @@ private void startShifts(double timeStep) { private void assignShifts(double timeStep) { // Remove elapsed shifts - unscheduledShifts.removeIf(shift -> { + unAssignedShifts.removeIf(shift -> { if (shift.getStartTime() + drtShiftParams.maxUnscheduledShiftDelay < timeStep ) { logger.warn("Shift with ID " + shift.getId() + " could not be assigned and is being removed as start time is longer in the past than defined by maxUnscheduledShiftDelay."); return true; @@ -204,7 +219,7 @@ private void assignShifts(double timeStep) { // Assign shifts Set assignableShifts = new LinkedHashSet<>(); - Iterator unscheduledShiftsIterator = unscheduledShifts.iterator(); + Iterator unscheduledShiftsIterator = unAssignedShifts.iterator(); while(unscheduledShiftsIterator.hasNext()) { DrtShift unscheduledShift = unscheduledShiftsIterator.next(); if(isSchedulable(unscheduledShift, timeStep)) { @@ -292,7 +307,7 @@ private void assignShifts(double timeStep) { } else { // logger.warn("Could not assign shift " + shift.getId().toString() + " to a // vehicle. Will retry next time step."); - this.unscheduledShifts.add(shift); + this.unAssignedShifts.add(shift); } } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/ShiftScheduler.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/ShiftScheduler.java new file mode 100644 index 00000000000..2d7c6993e59 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/ShiftScheduler.java @@ -0,0 +1,19 @@ +package org.matsim.contrib.drt.extension.operations.shifts.dispatcher; + +import com.google.common.collect.ImmutableMap; +import org.matsim.api.core.v01.Id; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShift; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; + +import jakarta.inject.Provider; +import java.util.List; + +/** + * @author nkuehnel / MOIA + */ +public interface ShiftScheduler extends Provider { + + List schedule(double time); + ImmutableMap, DrtShift> initialSchedule(); + +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java index 9a31f334f27..fd4756bb2ab 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java @@ -5,12 +5,14 @@ import com.google.inject.Provider; import com.google.inject.Singleton; import com.google.inject.TypeLiteral; -import org.matsim.api.core.v01.population.Population; +import org.matsim.contrib.common.timeprofile.ProfileWriter; import org.matsim.contrib.drt.extension.DrtWithExtensionsConfigGroup; import org.matsim.contrib.drt.extension.operations.DrtOperationsParams; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesSpecification; import org.matsim.contrib.drt.extension.operations.shifts.analysis.*; import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; +import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.ShiftScheduler; +import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DefaultShiftScheduler; import org.matsim.contrib.drt.extension.operations.shifts.io.DrtShiftsReader; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftBreakTaskImpl; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftChangeoverTaskImpl; @@ -24,14 +26,13 @@ import org.matsim.contrib.drt.schedule.DrtStayTask; import org.matsim.contrib.drt.schedule.DrtTaskBaseType; import org.matsim.contrib.drt.scheduler.EmptyVehicleRelocator; -import org.matsim.contrib.dvrp.fleet.FleetSpecification; -import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; -import org.matsim.contrib.dvrp.schedule.Task; -import org.matsim.contrib.common.timeprofile.ProfileWriter; import org.matsim.contrib.dvrp.analysis.VehicleOccupancyProfileCalculator; import org.matsim.contrib.dvrp.analysis.VehicleOccupancyProfileView; import org.matsim.contrib.dvrp.analysis.VehicleTaskProfileCalculator; import org.matsim.contrib.dvrp.analysis.VehicleTaskProfileView; +import org.matsim.contrib.dvrp.fleet.FleetSpecification; +import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; +import org.matsim.contrib.dvrp.schedule.Task; import org.matsim.core.config.Config; import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.controler.MatsimServices; @@ -82,14 +83,15 @@ public ShiftDrtModeModule(DrtConfigGroup drtCfg) { @Override public void install() { ShiftsParams shiftsParams = drtOperationsParams.getShiftsParams().orElseThrow(); + + DrtShiftsSpecification drtShiftsSpecification = new DrtShiftsSpecificationImpl(); if (shiftsParams.shiftInputFile != null) { - bindModal(DrtShiftsSpecification.class).toProvider(() -> { - DrtShiftsSpecification drtShiftsSpecification = new DrtShiftsSpecificationImpl(); - new DrtShiftsReader(drtShiftsSpecification).readURL(shiftsParams.getShiftInputUrl(getConfig().getContext())); - return drtShiftsSpecification; - }).asEagerSingleton(); + new DrtShiftsReader(drtShiftsSpecification).readURL(shiftsParams.getShiftInputUrl(getConfig().getContext())); } + bindModal(ShiftScheduler.class).toProvider(modalProvider(getter -> new DefaultShiftScheduler(drtShiftsSpecification))); + bindModal(DrtShiftsSpecification.class).toProvider(modalKey(ShiftScheduler.class)); + bindModal(ShiftDurationXY.class).toProvider(modalProvider( getter -> new ShiftDurationXY(getter.getModal(new TypeLiteral>(){}), getMode()) )).asEagerSingleton(); @@ -99,7 +101,7 @@ public void install() { )).asEagerSingleton(); bindModal(ShiftHistogram.class).toProvider(modalProvider( - getter -> new ShiftHistogram(getter.get(Population.class), getMode(), getter.get(Config.class)))).asEagerSingleton(); + getter -> new ShiftHistogram(getMode(), getter.get(Config.class)))).asEagerSingleton(); addEventHandlerBinding().to(modalKey(ShiftDurationXY.class)); addEventHandlerBinding().to(modalKey(BreakCorridorXY.class)); @@ -115,7 +117,7 @@ public void install() { bindModal(DumpShiftDataAtEndImpl.class).toProvider(modalProvider( getter -> new DumpShiftDataAtEndImpl( - getter.getModal(new TypeLiteral>(){}), + getter.getModal(DrtShiftsSpecification.class), getter.getModal(OperationFacilitiesSpecification.class), getter.get(OutputDirectoryHierarchy.class) )) diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java index 64180f24491..70423f2e59e 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java @@ -1,18 +1,13 @@ package org.matsim.contrib.drt.extension.operations.shifts.run; -import com.google.common.collect.ImmutableMap; import com.google.inject.Singleton; -import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Network; import org.matsim.contrib.drt.extension.DrtWithExtensionsConfigGroup; import org.matsim.contrib.drt.extension.operations.DrtOperationsParams; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilities; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilityFinder; import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; -import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DefaultAssignShiftToVehicleLogic; -import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DefaultShiftStartLogic; -import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DrtShiftDispatcher; -import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DrtShiftDispatcherImpl; +import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.*; import org.matsim.contrib.drt.extension.operations.shifts.fleet.DefaultShiftDvrpVehicle; import org.matsim.contrib.drt.extension.operations.shifts.optimizer.ShiftDrtOptimizer; import org.matsim.contrib.drt.extension.operations.shifts.optimizer.ShiftVehicleDataEntryFactory; @@ -24,7 +19,6 @@ import org.matsim.contrib.drt.extension.operations.shifts.scheduler.ShiftDrtScheduleInquiry; import org.matsim.contrib.drt.extension.operations.shifts.scheduler.ShiftTaskScheduler; import org.matsim.contrib.drt.extension.operations.shifts.scheduler.ShiftTaskSchedulerImpl; -import org.matsim.contrib.drt.extension.operations.shifts.shift.*; import org.matsim.contrib.drt.optimizer.*; import org.matsim.contrib.drt.optimizer.depot.DepotFinder; import org.matsim.contrib.drt.optimizer.insertion.CostCalculationStrategy; @@ -77,29 +71,6 @@ public ShiftDrtModeOptimizerQSimModule(DrtConfigGroup drtCfg) { protected void configureQSim() { ShiftsParams shiftsParams = drtOperationsParams.getShiftsParams().orElseThrow(); - bindModal(DrtShifts.class).toProvider(new ModalProviders.AbstractProvider<>(getMode(), DvrpModes::mode) { - @Override - public DrtShifts get() { - DrtShiftsSpecification shiftsSpecification = getModalInstance(DrtShiftsSpecification.class); - ImmutableMap, DrtShiftImpl> shifts = shiftsSpecification.getShiftSpecifications().values() - .stream() - .map(spec -> { - DefaultShiftBreakImpl shiftBreak = null; - DrtShiftBreakSpecification breakSpec = spec.getBreak().orElse(null); - if(breakSpec != null) { - shiftBreak = new DefaultShiftBreakImpl( - breakSpec.getEarliestBreakStartTime(), - breakSpec.getLatestBreakEndTime(), - breakSpec.getDuration()); - } - return new DrtShiftImpl(spec.getId(), spec.getStartTime(), spec.getEndTime(), - spec.getOperationFacilityId().orElse(null), spec.getDesignatedVehicleId().orElse(null), - shiftBreak); - }) - .collect(ImmutableMap.toImmutableMap(DrtShift::getId, s -> s)); - return () -> shifts; - } - }).asEagerSingleton(); addModalComponent(DrtOptimizer.class, modalProvider( getter -> { @@ -114,11 +85,12 @@ public DrtShifts get() { getter.getModal(ScheduleTimingUpdater.class)); })); - bindModal(DrtShiftDispatcher.class).toProvider(modalProvider( - getter -> new DrtShiftDispatcherImpl(getMode(), getter.getModal(DrtShifts.class), getter.getModal(Fleet.class), - getter.get(MobsimTimer.class), getter.getModal(OperationFacilities.class), getter.getModal(OperationFacilityFinder.class), + bindModal(DrtShiftDispatcher.class).toProvider(modalProvider( + getter -> new DrtShiftDispatcherImpl(getMode(), getter.getModal(Fleet.class), getter.get(MobsimTimer.class), + getter.getModal(OperationFacilities.class), getter.getModal(OperationFacilityFinder.class), getter.getModal(ShiftTaskScheduler.class), getter.getModal(Network.class), getter.get(EventsManager.class), - shiftsParams, new DefaultShiftStartLogic(), new DefaultAssignShiftToVehicleLogic(shiftsParams))) + shiftsParams, new DefaultShiftStartLogic(), new DefaultAssignShiftToVehicleLogic(shiftsParams), + getter.getModal(ShiftScheduler.class))) ).asEagerSingleton(); bindModal(InsertionCostCalculator.class).toProvider(modalProvider( diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShift.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShift.java index 24442914ba3..5682dbeaf55 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShift.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShift.java @@ -10,7 +10,7 @@ /** * @author nkuehnel, fzwick / MOIA */ -public interface DrtShift extends Identifiable { +public interface DrtShift extends Identifiable, Comparable { double getStartTime(); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftImpl.java index 1f929cdd574..676e0fc6cc3 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftImpl.java @@ -95,4 +95,9 @@ public Id getId() { public String toString() { return "Shift " + id.toString() + " ["+start+"-"+end+"]"; } + + @Override + public int compareTo(DrtShift shift) { + return this.id.compareTo(shift.getId()); + } } diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunOnTheFlyShiftDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunOnTheFlyShiftDrtScenarioIT.java new file mode 100644 index 00000000000..d7852ef1ac5 --- /dev/null +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunOnTheFlyShiftDrtScenarioIT.java @@ -0,0 +1,210 @@ +package org.matsim.contrib.drt.extension.operations.shifts.run; + +import com.google.common.collect.ImmutableMap; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.contrib.common.zones.systems.grid.square.SquareGridZoneSystemParams; +import org.matsim.contrib.drt.analysis.zonal.DrtZoneSystemParams; +import org.matsim.contrib.drt.extension.DrtWithExtensionsConfigGroup; +import org.matsim.contrib.drt.extension.operations.DrtOperationsControlerCreator; +import org.matsim.contrib.drt.extension.operations.DrtOperationsParams; +import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesParams; +import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; +import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DefaultShiftScheduler; +import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.ShiftScheduler; +import org.matsim.contrib.drt.extension.operations.shifts.shift.*; +import org.matsim.contrib.drt.fare.DrtFareParams; +import org.matsim.contrib.drt.optimizer.constraints.DefaultDrtOptimizationConstraintsSet; +import org.matsim.contrib.drt.optimizer.insertion.extensive.ExtensiveInsertionSearchParams; +import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams; +import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.MinCostFlowRebalancingStrategyParams; +import org.matsim.contrib.drt.run.DrtConfigGroup; +import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; +import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; +import org.matsim.contrib.dvrp.run.DvrpConfigGroup; +import org.matsim.contrib.zone.skims.DvrpTravelTimeMatrixParams; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigGroup; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.ReplanningConfigGroup; +import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.controler.Controler; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.controler.events.IterationStartsEvent; +import org.matsim.core.controler.listener.IterationStartsListener; +import org.matsim.examples.ExamplesUtils; + +import java.util.*; + +public class RunOnTheFlyShiftDrtScenarioIT { + + @Test + void test() { + + MultiModeDrtConfigGroup multiModeDrtConfigGroup = new MultiModeDrtConfigGroup(DrtWithExtensionsConfigGroup::new); + + String fleetFile = "holzkirchenFleet.xml"; + String plansFile = "holzkirchenPlans.xml.gz"; + String networkFile = "holzkirchenNetwork.xml.gz"; + String opFacilitiesFile = "holzkirchenOperationFacilities.xml"; + + DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup = (DrtWithExtensionsConfigGroup) multiModeDrtConfigGroup.createParameterSet("drt"); + + drtWithShiftsConfigGroup.mode = TransportMode.drt; + DefaultDrtOptimizationConstraintsSet defaultConstraintsSet = + (DefaultDrtOptimizationConstraintsSet) drtWithShiftsConfigGroup.addOrGetDrtOptimizationConstraintsParams() + .addOrGetDefaultDrtOptimizationConstraintsSet(); + drtWithShiftsConfigGroup.stopDuration = 30.; + defaultConstraintsSet.maxTravelTimeAlpha = 1.5; + defaultConstraintsSet.maxTravelTimeBeta = 10. * 60.; + defaultConstraintsSet.maxWaitTime = 600.; + defaultConstraintsSet.rejectRequestIfMaxWaitOrTravelTimeViolated = true; + defaultConstraintsSet.maxWalkDistance = 1000.; + drtWithShiftsConfigGroup.useModeFilteredSubnetwork = false; + drtWithShiftsConfigGroup.vehiclesFile = fleetFile; + drtWithShiftsConfigGroup.operationalScheme = DrtConfigGroup.OperationalScheme.door2door; + drtWithShiftsConfigGroup.plotDetailedCustomerStats = true; + drtWithShiftsConfigGroup.idleVehiclesReturnToDepots = false; + + drtWithShiftsConfigGroup.addParameterSet(new ExtensiveInsertionSearchParams()); + + ConfigGroup rebalancing = drtWithShiftsConfigGroup.createParameterSet("rebalancing"); + drtWithShiftsConfigGroup.addParameterSet(rebalancing); + ((RebalancingParams) rebalancing).interval = 600; + + MinCostFlowRebalancingStrategyParams strategyParams = new MinCostFlowRebalancingStrategyParams(); + strategyParams.targetAlpha = 0.3; + strategyParams.targetBeta = 0.3; + + drtWithShiftsConfigGroup.getRebalancingParams().get().addParameterSet(strategyParams); + + DrtZoneSystemParams drtZoneSystemParams = new DrtZoneSystemParams(); + SquareGridZoneSystemParams zoneParams = (SquareGridZoneSystemParams) drtZoneSystemParams.createParameterSet(SquareGridZoneSystemParams.SET_NAME); + zoneParams.cellSize = 500.; + drtZoneSystemParams.addParameterSet(zoneParams); + drtZoneSystemParams.targetLinkSelection = DrtZoneSystemParams.TargetLinkSelection.mostCentral; + drtWithShiftsConfigGroup.addParameterSet(drtZoneSystemParams); + + multiModeDrtConfigGroup.addParameterSet(drtWithShiftsConfigGroup); + + DvrpConfigGroup dvrpConfigGroup = new DvrpConfigGroup(); + DvrpTravelTimeMatrixParams matrixParams = dvrpConfigGroup.getTravelTimeMatrixParams(); + matrixParams.addParameterSet(matrixParams.createParameterSet(SquareGridZoneSystemParams.SET_NAME)); + + final Config config = ConfigUtils.createConfig(multiModeDrtConfigGroup, + dvrpConfigGroup); + config.setContext(ExamplesUtils.getTestScenarioURL("holzkirchen")); + + Set modes = new HashSet<>(); + modes.add("drt"); + config.travelTimeCalculator().setAnalyzedModes(modes); + + ScoringConfigGroup.ModeParams scoreParams = new ScoringConfigGroup.ModeParams("drt"); + config.scoring().addModeParams(scoreParams); + ScoringConfigGroup.ModeParams scoreParams2 = new ScoringConfigGroup.ModeParams("walk"); + config.scoring().addModeParams(scoreParams2); + + config.plans().setInputFile(plansFile); + config.network().setInputFile(networkFile); + + config.qsim().setSimStarttimeInterpretation(QSimConfigGroup.StarttimeInterpretation.onlyUseStarttime); + config.qsim().setSimEndtimeInterpretation(QSimConfigGroup.EndtimeInterpretation.minOfEndtimeAndMobsimFinished); + + final ScoringConfigGroup.ActivityParams home = new ScoringConfigGroup.ActivityParams("home"); + home.setTypicalDuration(8 * 3600); + final ScoringConfigGroup.ActivityParams other = new ScoringConfigGroup.ActivityParams("other"); + other.setTypicalDuration(4 * 3600); + final ScoringConfigGroup.ActivityParams education = new ScoringConfigGroup.ActivityParams("education"); + education.setTypicalDuration(6 * 3600); + final ScoringConfigGroup.ActivityParams shopping = new ScoringConfigGroup.ActivityParams("shopping"); + shopping.setTypicalDuration(2 * 3600); + final ScoringConfigGroup.ActivityParams work = new ScoringConfigGroup.ActivityParams("work"); + work.setTypicalDuration(2 * 3600); + + config.scoring().addActivityParams(home); + config.scoring().addActivityParams(other); + config.scoring().addActivityParams(education); + config.scoring().addActivityParams(shopping); + config.scoring().addActivityParams(work); + + final ReplanningConfigGroup.StrategySettings stratSets = new ReplanningConfigGroup.StrategySettings(); + stratSets.setWeight(1); + stratSets.setStrategyName("ChangeExpBeta"); + config.replanning().addStrategySettings(stratSets); + + config.controller().setLastIteration(1); + config.controller().setWriteEventsInterval(1); + + config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory("test/output/holzkirchen_shifts"); + + DrtOperationsParams operationsParams = (DrtOperationsParams) drtWithShiftsConfigGroup.createParameterSet(DrtOperationsParams.SET_NAME); + ShiftsParams shiftsParams = (ShiftsParams) operationsParams.createParameterSet(ShiftsParams.SET_NAME); + OperationFacilitiesParams operationFacilitiesParams = (OperationFacilitiesParams) operationsParams.createParameterSet(OperationFacilitiesParams.SET_NAME); + operationsParams.addParameterSet(shiftsParams); + operationsParams.addParameterSet(operationFacilitiesParams); + + operationFacilitiesParams.operationFacilityInputFile = opFacilitiesFile; + shiftsParams.allowInFieldChangeover = true; + drtWithShiftsConfigGroup.addParameterSet(operationsParams); + + DrtFareParams drtFareParams = new DrtFareParams(); + drtFareParams.baseFare = 1.; + drtFareParams.distanceFare_m = 1. / 1000; + drtWithShiftsConfigGroup.addParameterSet(drtFareParams); + + final Controler run = DrtOperationsControlerCreator.createControler(config, false); + + run.addOverridingModule(new AbstractDvrpModeModule(drtWithShiftsConfigGroup.getMode()) { + @Override + public void install() { + this.bindModal(OnTheFlyScheduler.class).toProvider(modalProvider(getter -> + new OnTheFlyScheduler())).asEagerSingleton(); + this.bindModal(ShiftScheduler.class).toProvider(modalProvider( getter -> getter.getModal(OnTheFlyScheduler.class))); + this.addControlerListenerBinding().toProvider(modalProvider( getter -> getter.getModal(OnTheFlyScheduler.class))); + } + }); + + run.run(); + } + + private static class OnTheFlyScheduler implements ShiftScheduler, IterationStartsListener { + + + private DefaultShiftScheduler delegate = new DefaultShiftScheduler(new DrtShiftsSpecificationImpl()); + private int iteration; + + @Override + public DrtShiftsSpecification get() { + return delegate.get(); + } + + @Override + public List schedule(double time) { + List shifts = new ArrayList<>(); + if (time > 4 * 3600 && time < 15 * 3600 && time % 3600 == 0) { + for (int i = 0; i < iteration + 1 ; i++) { + DrtShiftSpecificationImpl shift = DrtShiftSpecificationImpl.newBuilder() + .id(Id.create(time + "_" + i, DrtShift.class)) + .start(time + 3600).end(time + 9 * 3600).build(); + shifts.add(shift); + delegate.get().addShiftSpecification(shift); + } + } + return shifts.stream().map(DefaultShiftScheduler.createShiftFromSpec).toList(); + } + + @Override + public ImmutableMap, DrtShift> initialSchedule() { + delegate = new DefaultShiftScheduler(new DrtShiftsSpecificationImpl()); + return delegate.initialSchedule(); + } + + @Override + public void notifyIterationStarts(IterationStartsEvent event) { + iteration = event.getIteration(); + } + } +} diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java index 5babef611b3..9dc2e4ba071 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 @@ -16,6 +16,8 @@ import org.matsim.contrib.drt.extension.operations.DrtOperationsParams; import org.matsim.contrib.drt.extension.operations.operationFacilities.*; import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; +import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DefaultShiftScheduler; +import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.ShiftScheduler; import org.matsim.contrib.drt.extension.operations.shifts.shift.*; import org.matsim.contrib.drt.optimizer.constraints.DefaultDrtOptimizationConstraintsSet; import org.matsim.contrib.drt.optimizer.insertion.extensive.ExtensiveInsertionSearchParams; @@ -175,10 +177,10 @@ public void install() { Assertions.assertFalse(rejectedPersons.contains(Id.createPersonId(1))); - Assertions.assertTrue(rejectedPersons.contains(Id.createPersonId(2))); Assertions.assertFalse(rejectedPersons.contains(Id.createPersonId(3))); - Assertions.assertTrue(rejectedPersons.contains(Id.createPersonId(4))); Assertions.assertFalse(rejectedPersons.contains(Id.createPersonId(5))); + Assertions.assertTrue(rejectedPersons.contains(Id.createPersonId(2))); + Assertions.assertTrue(rejectedPersons.contains(Id.createPersonId(4))); Assertions.assertTrue(rejectedPersons.contains(Id.createPersonId(6))); } @@ -208,7 +210,7 @@ private void preparePopulation(Scenario scenario) { Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1)); start.setEndTime(5000); start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 900.); - start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 5000.); + start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 5005.); plan.addActivity(start); plan.addLeg(factory.createLeg("drt")); plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2))); @@ -311,7 +313,7 @@ private static void prepareOperations(Controler run, DrtWithExtensionsConfigGrou public void install() { bindModal(FleetSpecification.class).toInstance(fleetSpecification); bindModal(OperationFacilitiesSpecification.class).toInstance(opFasSpecification); - bindModal(DrtShiftsSpecification.class).toInstance(shiftsSpecification); + bindModal(ShiftScheduler.class).toProvider(modalProvider(getter -> new DefaultShiftScheduler(shiftsSpecification))); } }); From 4a6f09550574e08b8aa842ba6e7262594455eb51 Mon Sep 17 00:00:00 2001 From: steffenaxer <26229392+steffenaxer@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:16:42 +0200 Subject: [PATCH 074/111] Bypass Fleet object in schedule interface --- .../operations/shifts/dispatcher/DefaultShiftScheduler.java | 3 ++- .../shifts/dispatcher/DrtShiftDispatcherImpl.java | 6 +++--- .../operations/shifts/dispatcher/ShiftScheduler.java | 4 +++- .../shifts/run/RunOnTheFlyShiftDrtScenarioIT.java | 3 ++- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DefaultShiftScheduler.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DefaultShiftScheduler.java index f512ec3a6d1..e51d7e01ec3 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DefaultShiftScheduler.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DefaultShiftScheduler.java @@ -3,6 +3,7 @@ import com.google.common.collect.ImmutableMap; import org.matsim.api.core.v01.Id; import org.matsim.contrib.drt.extension.operations.shifts.shift.*; +import org.matsim.contrib.dvrp.fleet.Fleet; import java.util.Collections; import java.util.List; @@ -32,7 +33,7 @@ public DefaultShiftScheduler(DrtShiftsSpecification shiftsSpecification) { this.shiftsSpecification = shiftsSpecification; } @Override - public List schedule(double time) { + public List schedule(double time, Fleet fleet) { return Collections.emptyList(); } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java index c2ed2b8acec..198401f4526 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java @@ -141,7 +141,7 @@ public void dispatch(double timeStep) { if (timeStep % (drtShiftParams.updateShiftEndInterval) == 0) { updateShiftEnds(timeStep); } - scheduleShifts(timeStep); + scheduleShifts(timeStep, this.fleet); assignShifts(timeStep); startShifts(timeStep); checkBreaks(); @@ -172,8 +172,8 @@ private void checkBreaks() { } - private void scheduleShifts(double timeStep) { - List scheduled = shiftScheduler.schedule(timeStep); + private void scheduleShifts(double timeStep, Fleet fleet) { + List scheduled = shiftScheduler.schedule(timeStep, fleet); unAssignedShifts.addAll(scheduled); } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/ShiftScheduler.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/ShiftScheduler.java index 2d7c6993e59..e5f74f8b75e 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/ShiftScheduler.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/ShiftScheduler.java @@ -6,6 +6,8 @@ import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; import jakarta.inject.Provider; +import org.matsim.contrib.dvrp.fleet.Fleet; + import java.util.List; /** @@ -13,7 +15,7 @@ */ public interface ShiftScheduler extends Provider { - List schedule(double time); + List schedule(double time, Fleet fleet); ImmutableMap, DrtShift> initialSchedule(); } diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunOnTheFlyShiftDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunOnTheFlyShiftDrtScenarioIT.java index d7852ef1ac5..07c9a0b793b 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunOnTheFlyShiftDrtScenarioIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunOnTheFlyShiftDrtScenarioIT.java @@ -21,6 +21,7 @@ import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.MinCostFlowRebalancingStrategyParams; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; +import org.matsim.contrib.dvrp.fleet.Fleet; import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; import org.matsim.contrib.dvrp.run.DvrpConfigGroup; import org.matsim.contrib.zone.skims.DvrpTravelTimeMatrixParams; @@ -182,7 +183,7 @@ public DrtShiftsSpecification get() { } @Override - public List schedule(double time) { + public List schedule(double time, Fleet fleet) { List shifts = new ArrayList<>(); if (time > 4 * 3600 && time < 15 * 3600 && time % 3600 == 0) { for (int i = 0; i < iteration + 1 ; i++) { From 5335f2338201969240a56f8a0e5ad171b2bf8950 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Mon, 26 Aug 2024 15:53:08 +0200 Subject: [PATCH 075/111] remove static --- .../GenerateSmallScaleCommercialTrafficDemand.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java index 1b8a0b260e8..eb624d9de3e 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 @@ -106,7 +106,7 @@ public class GenerateSmallScaleCommercialTrafficDemand implements MATSimAppComma // Option 3: Leerkamp (nur in RVR Modell). private static final Logger log = LogManager.getLogger(GenerateSmallScaleCommercialTrafficDemand.class); - private static IntegrateExistingTrafficToSmallScaleCommercial integrateExistingTrafficToSmallScaleCommercial; + private final IntegrateExistingTrafficToSmallScaleCommercial integrateExistingTrafficToSmallScaleCommercial; private enum CreationOption { useExistingCarrierFileWithSolution, createNewCarrierFile, useExistingCarrierFileWithoutSolution @@ -174,11 +174,11 @@ public enum SmallScaleCommercialTrafficType { private Index indexZones; public GenerateSmallScaleCommercialTrafficDemand() { - integrateExistingTrafficToSmallScaleCommercial = new DefaultIntegrateExistingTrafficToSmallScaleCommercialImpl(); + this.integrateExistingTrafficToSmallScaleCommercial = new DefaultIntegrateExistingTrafficToSmallScaleCommercialImpl(); log.info("Using default {} if existing models are integrated!", DefaultIntegrateExistingTrafficToSmallScaleCommercialImpl.class.getSimpleName()); } public GenerateSmallScaleCommercialTrafficDemand(IntegrateExistingTrafficToSmallScaleCommercial integrateExistingTrafficToSmallScaleCommercial) { - GenerateSmallScaleCommercialTrafficDemand.integrateExistingTrafficToSmallScaleCommercial = integrateExistingTrafficToSmallScaleCommercial; + this.integrateExistingTrafficToSmallScaleCommercial = integrateExistingTrafficToSmallScaleCommercial; log.info("Using {} if existing models are integrated!", integrateExistingTrafficToSmallScaleCommercial.getClass().getSimpleName()); } From 55e0883e5a56cb8aee064b88c9d93264257211d9 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Mon, 26 Aug 2024 15:53:27 +0200 Subject: [PATCH 076/111] add comment --- .../GenerateSmallScaleCommercialTrafficDemand.java | 6 ++++++ 1 file changed, 6 insertions(+) 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 eb624d9de3e..7b476177872 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 @@ -1305,6 +1305,12 @@ private ValueSelectorUnderGivenProbability createTourDurationTimeDistribution(St return new ValueSelectorUnderGivenProbability(tourDurationProbabilityDistribution, rnd); } + /** + * 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 + */ private EnumeratedDistribution createTourDistribution(String smallScaleCommercialTrafficType) { List> tourDurationProbabilityDistribution = new ArrayList<>(); From 03862288679f6090101713f9cf1ef50d582185d0 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Tue, 27 Aug 2024 08:38:10 +0200 Subject: [PATCH 077/111] fix activity creation --- .../SmallScaleCommercialTrafficUtils.java | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java index 509ff7f42b2..77e5077ad55 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java @@ -42,8 +42,8 @@ import org.matsim.application.options.ShpOptions.Index; import org.matsim.core.network.NetworkUtils; import org.matsim.core.population.PopulationUtils; -import org.matsim.core.router.TripStructureUtils; import org.matsim.core.utils.io.IOUtils; +import org.matsim.core.utils.misc.OptionalTime; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.CarriersUtils; import org.matsim.vehicles.Vehicle; @@ -205,25 +205,14 @@ static void createPlansBasedOnCarrierPlans(Scenario scenario, String smallScaleC if (tourElement instanceof Activity activity) { Activity newActivity = PopulationUtils.createActivityFromCoord(activity.getType(), scenario.getNetwork().getLinks().get(activity.getLinkId()).getFromNode().getCoord()); + if (activity.getMaximumDuration() != OptionalTime.undefined()) + newActivity.setMaximumDuration(activity.getMaximumDuration().seconds()); if (activity.getType().equals("start")) { newActivity.setEndTime(activity.getEndTime().seconds()); newActivity.setType("commercial_start"); - } else -// TODO: this causes a crash when PersonPrepareForSim -> PlanRouter tries routing??? - newActivity.setEndTimeUndefined(); - if (activity.getType().equals("end")) { -// if tourStartTime = 0 it can happen that commecial_start.getEndTime > commercial_end.getStartTime -// this should not happen, hence below the tour start time is taken from the commercial_start act - double tourStartTime = TripStructureUtils.getActivities(plan.getPlanElements(), TripStructureUtils.StageActivityHandling.ExcludeStageActivities) - .stream() - .filter(a -> a.getType().equals("commercial_start")) - .toList() - .getFirst() - .getEndTime() - .seconds(); - newActivity.setStartTime(tourStartTime + 8 * 3600); - newActivity.setType("commercial_end"); } + if (activity.getType().equals("end")) + newActivity.setType("commercial_end"); plan.addActivity(newActivity); } if (tourElement instanceof Leg) { From dd608a245d6f90a4997e56479ee9503ad6f68503 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Tue, 27 Aug 2024 08:45:43 +0200 Subject: [PATCH 078/111] add comments --- ...rateSmallScaleCommercialTrafficDemand.java | 22 +++++++++---------- .../SmallScaleCommercialTrafficUtils.java | 22 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) 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 7b476177872..d25c299f7ff 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 @@ -289,8 +289,8 @@ public Integer call() throws Exception { } /** Creates a map with the different facility types per building. - * @param scenario - * @param facilitiesPerZone + * @param scenario complete Scenario + * @param facilitiesPerZone Map with facilities per zone */ private void filterFacilitiesForZones(Scenario scenario, Map>> facilitiesPerZone) { scenario.getActivityFacilities().getFacilities().values().forEach((activityFacility -> { @@ -834,11 +834,11 @@ private int getVehicleStartTime(TourStartAndDuration t) { /** * Give a service duration based on the purpose and the trafficType under a given probability * - * @param serviceDurationTimeSelector - * @param employeeCategory - * @param modeORvehType - * @param smallScaleCommercialTrafficType - * @return + * @param serviceDurationTimeSelector the selector for the service duration + * @param employeeCategory the category of the employee + * @param modeORvehType the mode or vehicle type + * @param smallScaleCommercialTrafficType the traffic type + * @return the service duration */ private Integer getServiceTimePerStop(Map serviceDurationTimeSelector, String employeeCategory, @@ -1193,7 +1193,7 @@ public double getScore() { * The values are given in [h] and have an upperBound. * Data source: KiD 2002 * - * @return + * @return the probability distribution for the tour start times */ private ValueSelectorUnderGivenProbability createTourStartTimeDistribution(String smallScaleCommercialTrafficType) { @@ -1257,7 +1257,7 @@ private ValueSelectorUnderGivenProbability createTourStartTimeDistribution(Strin * The values are given in [h] and have an upperBound. * Data source: KiD 2002 * - * @return + * @return the probability distribution for the tour duration */ private ValueSelectorUnderGivenProbability createTourDurationTimeDistribution(String smallScaleCommercialTrafficType) { List tourDurationProbabilityDistribution = new ArrayList<>(); @@ -1797,8 +1797,8 @@ else if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType. * The values are given in [min] and have an upperBound. * Data source: KiD 2002 * - * @param smallScaleCommercialTrafficType - * @return + * @param smallScaleCommercialTrafficType the type of small scale commercial traffic + * @return the probability distribution for the duration of the services */ private Map createStopDurationTimeDistributionPerCategory(String smallScaleCommercialTrafficType) { diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java index 77e5077ad55..e0b3a8b23ea 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/SmallScaleCommercialTrafficUtils.java @@ -117,7 +117,7 @@ public static Index getIndexBuildings(Path shapeFileBuildingsPath, String shapeC } /** - * Creates and return the Index of the regions shape. + * Creates and return the Index of the regions shapes. * * @param shapeFileRegionsPath Path to the shape file of the regions * @param shapeCRS CRS of the shape file @@ -132,13 +132,13 @@ public static Index getIndexRegions(Path shapeFileRegionsPath, String shapeCRS, } /** Finds the nearest possible link for the building polygon. - * @param zone - * @param noPossibleLinks - * @param linksPerZone - * @param newLink - * @param centroidPointOfBuildingPolygon - * @param numberOfPossibleLinks - * @return + * @param zone zone of the building + * @param noPossibleLinks list of links that are not possible + * @param linksPerZone map of links per zone + * @param newLink new link + * @param centroidPointOfBuildingPolygon centroid point of the building polygon + * @param numberOfPossibleLinks number of possible links + * @return new possible Link */ static Id findNearestPossibleLink(String zone, List noPossibleLinks, Map, Link>> linksPerZone, Id newLink, Coord centroidPointOfBuildingPolygon, int numberOfPossibleLinks) { @@ -283,9 +283,9 @@ static String findZoneOfLink(Id linkId, Map, Link>> l /** Reads the data distribution of the zones. - * @param pathToDataDistributionToZones - * @return - * @throws IOException + * @param pathToDataDistributionToZones Path to the data distribution of the zones + * @return resultingDataPerZone + * @throws IOException if the file is not found */ static Map> readDataDistribution(Path pathToDataDistributionToZones) throws IOException { if (!Files.exists(pathToDataDistributionToZones)) { From b4a33380be0105a0f895c0ca162e9262edab37d2 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Tue, 27 Aug 2024 09:02:32 +0200 Subject: [PATCH 079/111] update test --- ...nerateSmallScaleCommercialTrafficTest.java | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java index 1e20839af41..7aeefbf5925 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/RunGenerateSmallScaleCommercialTrafficTest.java @@ -28,14 +28,18 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.population.Activity; import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.Population; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.events.EventsUtils; import org.matsim.core.population.PopulationUtils; +import org.matsim.core.router.TripStructureUtils; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.utils.io.IOUtils; +import org.matsim.core.utils.misc.OptionalTime; import org.matsim.freight.carriers.Carrier; import org.matsim.freight.carriers.CarriersUtils; import org.matsim.freight.carriers.FreightCarriersConfigGroup; @@ -47,6 +51,7 @@ import java.io.IOException; import java.nio.file.Path; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Objects; @@ -68,20 +73,12 @@ void testMainRunAndResults() { String sample = "0.1"; String jspritIterations = "2"; String creationOption = "createNewCarrierFile"; - String landuseConfiguration = "useExistingDataDistribution"; String smallScaleCommercialTrafficType = "commercialPersonTraffic"; - String regionsShapeFileName = utils.getPackageInputDirectory() + "/shp/testRegions.shp"; - String regionsShapeRegionColumn = "region"; String zoneShapeFileName = utils.getPackageInputDirectory() + "/shp/testZones.shp"; String zoneShapeFileNameColumn = "name"; - String buildingsShapeFileName = utils.getPackageInputDirectory() + "/shp/testBuildings.shp"; - String shapeFileBuildingTypeColumn = "type"; - String landuseShapeFileName = utils.getPackageInputDirectory() + "/shp/testLanduse.shp"; - String shapeFileLanduseTypeColumn = "fclass"; String shapeCRS = "EPSG:4326"; String resultPopulation = "testPopulation.xml.gz"; - new GenerateSmallScaleCommercialTrafficDemand().execute( pathToConfig, "--pathToDataDistributionToZones", pathToDataDistributionToZones.toString(), @@ -118,6 +115,18 @@ void testMainRunAndResults() { Assertions.assertTrue(person.getAttributes().getAsMap().containsKey("vehicles")); Assertions.assertTrue(person.getAttributes().getAsMap().containsKey("subpopulation")); Assertions.assertTrue(person.getAttributes().getAsMap().containsKey("purpose")); + + for (Plan plan : person.getPlans()) { + List activities = TripStructureUtils.getActivities(plan, TripStructureUtils.StageActivityHandling.ExcludeStageActivities); + Assertions.assertEquals("commercial_start", activities.getFirst().getType()); + Assertions.assertEquals("commercial_end", activities.getLast().getType()); + activities.forEach(activity -> { + Assertions.assertNotNull(activity.getCoord()); + if (!activity.getType().equals("commercial_start") && !activity.getType().equals("commercial_end")) { + Assertions.assertNotEquals(OptionalTime.undefined(), activity.getMaximumDuration()); + } + }); + } } Assertions.assertEquals(CarriersUtils.addOrGetCarriers(scenarioWSolution).getCarriers().size(), @@ -144,10 +153,10 @@ void testMainRunAndResults() { } /** - * Reads a CSV file and creates a map with the first column as key and the rest as a map with the header as key and the value as value + * Reads a CSV file and creates a map with the first column as a key and the rest as a map with the header as key and the value as value * * @param calculatedFile the file to read - * @return + * @return the map with the data distribution */ private static Map> readCSVInputAndCreateMap(String calculatedFile) { Map> dataDistribution = new HashMap<>(); From 2fc9cedf5c17013c3e9e774c3165a00957176a40 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Tue, 27 Aug 2024 09:19:20 +0200 Subject: [PATCH 080/111] use getFirst --- .../GenerateSmallScaleCommercialTrafficDemand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 d25c299f7ff..b06891e9ca4 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 @@ -698,7 +698,7 @@ private void createCarriers(Scenario scenario, TripDistributionMatrix odMatrix, String[] serviceArea = new String[]{stopZone}; int serviceTimePerStop; if (selectedStartCategory.equals("Inhabitants")) - serviceTimePerStop = getServiceTimePerStop(stopDurationTimeSelector, startCategory.get(0), modeORvehType, smallScaleCommercialTrafficType); + serviceTimePerStop = getServiceTimePerStop(stopDurationTimeSelector, startCategory.getFirst(), modeORvehType, smallScaleCommercialTrafficType); else serviceTimePerStop = getServiceTimePerStop(stopDurationTimeSelector, selectedStartCategory, modeORvehType, smallScaleCommercialTrafficType); From 22845b4bc11bf669125b57635c316969004a9c12 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Tue, 27 Aug 2024 09:46:14 +0200 Subject: [PATCH 081/111] rename --- .../GenerateSmallScaleCommercialTrafficDemand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 b06891e9ca4..0f55a7ff5e2 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 @@ -554,7 +554,7 @@ private void createCarriers(Scenario scenario, TripDistributionMatrix odMatrix, EnumeratedDistribution tourDistribution = createTourDistribution(smallScaleCommercialTrafficType); - Map stopDurationTimeSelector = createStopDurationTimeDistributionPerCategory( + Map stopDurationTimeSelector = createStopDurationDistributionPerCategory( smallScaleCommercialTrafficType); CarrierVehicleTypes carrierVehicleTypes = CarriersUtils.getCarrierVehicleTypes(scenario); @@ -1800,7 +1800,7 @@ else if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType. * @param smallScaleCommercialTrafficType the type of small scale commercial traffic * @return the probability distribution for the duration of the services */ - private Map createStopDurationTimeDistributionPerCategory(String smallScaleCommercialTrafficType) { + private Map createStopDurationDistributionPerCategory(String smallScaleCommercialTrafficType) { Map stopDurationProbabilityDistribution = new HashMap<>(); if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { From 809c27ba50cfb8e580be041ceda187220fe31507 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Tue, 27 Aug 2024 09:47:04 +0200 Subject: [PATCH 082/111] deprecate methods --- .../GenerateSmallScaleCommercialTrafficDemand.java | 2 ++ 1 file changed, 2 insertions(+) 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 0f55a7ff5e2..7f5efcf11a9 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 @@ -1196,6 +1196,7 @@ public double getScore() { * @return the probability distribution for the tour start times */ + @Deprecated //use createTourDistribution(String smallScaleCommercialTrafficType) instead private ValueSelectorUnderGivenProbability createTourStartTimeDistribution(String smallScaleCommercialTrafficType) { List tourStartProbabilityDistribution = new ArrayList<>(); @@ -1259,6 +1260,7 @@ private ValueSelectorUnderGivenProbability createTourStartTimeDistribution(Strin * * @return the probability distribution for the tour duration */ + @Deprecated //use createTourDistribution(String smallScaleCommercialTrafficType) instead private ValueSelectorUnderGivenProbability createTourDurationTimeDistribution(String smallScaleCommercialTrafficType) { List tourDurationProbabilityDistribution = new ArrayList<>(); if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { From 5bc00caa557ffc25da1a69e07054daa763a292e6 Mon Sep 17 00:00:00 2001 From: vsp-gleich Date: Tue, 27 Aug 2024 12:49:27 +0200 Subject: [PATCH 083/111] Fix pt fare config write to and read from config file (#3427) * adapt test to test writing PtFareConfigGroup to file and read in again. * fix write and read ptFareConfigGroup --- .../pt/fare/DistanceBasedPtFareParams.java | 27 +++++++++++++------ .../pt/fare/FareZoneBasedPtFareParams.java | 4 +-- .../vsp/pt/fare/PtFareConfigGroup.java | 17 ++++++++++-- .../contrib/vsp/pt/fare/PtFareModule.java | 4 +-- .../PtTripWithDistanceBasedFareEstimator.java | 2 +- .../fare/FareZoneBasedPtFareHandlerTest.java | 9 ++++++- 6 files changed, 47 insertions(+), 16 deletions(-) diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java index 6a968d80dda..1cabc347839 100644 --- a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java @@ -2,6 +2,7 @@ import jakarta.validation.constraints.PositiveOrZero; import org.apache.commons.math.stat.regression.SimpleRegression; +import org.matsim.core.config.ConfigGroup; import org.matsim.core.config.ReflectiveConfigGroup; import java.util.*; @@ -15,14 +16,14 @@ public class DistanceBasedPtFareParams extends PtFareParams { public static final DistanceBasedPtFareParams GERMAN_WIDE_FARE = germanWideFare(); - public static final String SET_NAME = "ptFareCalculationDistanceBased"; + public static final String SET_TYPE = "ptFareCalculationDistanceBased"; public static final String MIN_FARE = "minFare"; @PositiveOrZero private double minFare = 2.0; public DistanceBasedPtFareParams() { - super(SET_NAME); + super(SET_TYPE); } @Override @@ -118,10 +119,20 @@ private static DistanceBasedPtFareParams germanWideFare() { return params; } + @Override + public ConfigGroup createParameterSet(final String type) { + switch (type) { + case DistanceClassLinearFareFunctionParams.SET_TYPE: + return new DistanceClassLinearFareFunctionParams(); + default: + throw new IllegalArgumentException(type); + } + } + public SortedMap getDistanceClassFareParams() { @SuppressWarnings("unchecked") final Collection distanceClassFareParams = - (Collection) getParameterSets(DistanceClassLinearFareFunctionParams.SET_NAME); + (Collection) getParameterSets(DistanceClassLinearFareFunctionParams.SET_TYPE); final SortedMap map = new TreeMap<>(); for (DistanceClassLinearFareFunctionParams pars : distanceClassFareParams) { @@ -140,7 +151,8 @@ public SortedMap getDistanceClass public DistanceClassLinearFareFunctionParams getOrCreateDistanceClassFareParams(double maxDistance) { DistanceClassLinearFareFunctionParams distanceClassFareParams = this.getDistanceClassFareParams().get(maxDistance); if (distanceClassFareParams == null) { - distanceClassFareParams = new DistanceClassLinearFareFunctionParams(maxDistance); + distanceClassFareParams = new DistanceClassLinearFareFunctionParams(); + distanceClassFareParams.setMaxDistance(maxDistance); addParameterSet(distanceClassFareParams); } return distanceClassFareParams; @@ -148,7 +160,7 @@ public DistanceClassLinearFareFunctionParams getOrCreateDistanceClassFareParams( public static class DistanceClassLinearFareFunctionParams extends ReflectiveConfigGroup { - public static final String SET_NAME = "distanceClassLinearFare"; + public static final String SET_TYPE = "distanceClassLinearFare"; public static final String FARE_SLOPE = "fareSlope"; public static final String FARE_INTERCEPT = "fareIntercept"; public static final String MAX_DISTANCE = "maxDistance"; @@ -160,9 +172,8 @@ public static class DistanceClassLinearFareFunctionParams extends ReflectiveConf @PositiveOrZero private double maxDistance; - public DistanceClassLinearFareFunctionParams(double maxDistance) { - super(SET_NAME); - this.maxDistance = maxDistance; + public DistanceClassLinearFareFunctionParams() { + super(SET_TYPE); } @StringGetter(FARE_SLOPE) diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareParams.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareParams.java index 391c609684e..4944ad13d78 100644 --- a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareParams.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareParams.java @@ -1,9 +1,9 @@ package org.matsim.contrib.vsp.pt.fare; public class FareZoneBasedPtFareParams extends PtFareParams { - public static final String SET_NAME = "ptFareCalculationFareZoneBased"; + public static final String SET_TYPE = "ptFareCalculationFareZoneBased"; public FareZoneBasedPtFareParams() { - super(SET_NAME); + super(SET_TYPE); } } diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareConfigGroup.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareConfigGroup.java index 9001b2ce2e9..ca1ce2fdb65 100644 --- a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareConfigGroup.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareConfigGroup.java @@ -2,6 +2,7 @@ import jakarta.validation.constraints.PositiveOrZero; import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigGroup; import org.matsim.core.config.ReflectiveConfigGroup; import java.util.Map; @@ -57,12 +58,24 @@ public void setUpperBoundFactor(double upperBoundFactor) { this.upperBoundFactor = upperBoundFactor; } + @Override + public ConfigGroup createParameterSet(final String type) { + switch (type) { + case DistanceBasedPtFareParams.SET_TYPE: + return new DistanceBasedPtFareParams(); + case FareZoneBasedPtFareParams.SET_TYPE: + return new FareZoneBasedPtFareParams(); + default: + throw new IllegalArgumentException(type); + } + } + @Override protected void checkConsistency(Config config) { super.checkConsistency(config); - var distanceBasedParameterSets = getParameterSets(DistanceBasedPtFareParams.SET_NAME); - var fareZoneBasedParameterSets = getParameterSets(FareZoneBasedPtFareParams.SET_NAME); + var distanceBasedParameterSets = getParameterSets(DistanceBasedPtFareParams.SET_TYPE); + var fareZoneBasedParameterSets = getParameterSets(FareZoneBasedPtFareParams.SET_TYPE); if (distanceBasedParameterSets.isEmpty() && fareZoneBasedParameterSets.isEmpty()) { throw new IllegalArgumentException("No parameter sets found for pt fare calculation. Please add at least one parameter set."); diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareModule.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareModule.java index d3b2f39d02a..b13cf5c2af2 100644 --- a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareModule.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareModule.java @@ -19,8 +19,8 @@ public void install() { Multibinder ptFareCalculator = Multibinder.newSetBinder(binder(), PtFareCalculator.class); PtFareConfigGroup ptFareConfigGroup = ConfigUtils.addOrGetModule(this.getConfig(), PtFareConfigGroup.class); - Collection fareZoneBased = ptFareConfigGroup.getParameterSets(FareZoneBasedPtFareParams.SET_NAME); - Collection distanceBased = ptFareConfigGroup.getParameterSets(DistanceBasedPtFareParams.SET_NAME); + Collection fareZoneBased = ptFareConfigGroup.getParameterSets(FareZoneBasedPtFareParams.SET_TYPE); + Collection distanceBased = ptFareConfigGroup.getParameterSets(DistanceBasedPtFareParams.SET_TYPE); Stream.concat(fareZoneBased.stream(), distanceBased.stream()) .map(c -> (PtFareParams) c) diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java index 11bbaae184d..b1d05244534 100644 --- a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtTripWithDistanceBasedFareEstimator.java @@ -39,7 +39,7 @@ public PtTripWithDistanceBasedFareEstimator(TransitSchedule transitSchedule, PtF private static DistanceBasedPtFareParams extractPtFare(PtFareConfigGroup config) { //TODO - return config.getParameterSets(DistanceBasedPtFareParams.SET_NAME).stream() + return config.getParameterSets(DistanceBasedPtFareParams.SET_TYPE).stream() .map(DistanceBasedPtFareParams.class::cast) .findFirst() .orElseThrow(() -> new IllegalStateException("No distance based fare parameters found")); diff --git a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java index 687a2c4f522..ab65679c2d2 100644 --- a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java @@ -59,7 +59,14 @@ void testFareZoneBasedPtFareHandler() { ptFareConfigGroup.addParameterSet(fareZoneBased); ptFareConfigGroup.addParameterSet(distanceBased); - MutableScenario scenario = setUpScenario(config); + // write config to file and read in again to check config reading and writing + ConfigUtils.writeConfig(config, utils.getOutputDirectory() + "configFromCode.xml"); + Config configFromFile = ConfigUtils.loadConfig(utils.getOutputDirectory() + "configFromCode.xml"); + // re-direct to correct input directory + URL context = ExamplesUtils.getTestScenarioURL("kelheim"); + configFromFile.setContext(context); + + MutableScenario scenario = setUpScenario(configFromFile); //Run var fareAnalysis = new FareAnalysis(); From 3a29317d88971924ce575796a57fd81c88ef846b Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Tue, 27 Aug 2024 13:02:30 +0200 Subject: [PATCH 084/111] use EnumeratedDistribution instead of own class --- ...rateSmallScaleCommercialTrafficDemand.java | 1652 +++++++++-------- .../ValueSelectorUnderGivenProbability.java | 139 -- .../test.output_events.xml.gz | Bin 34108 -> 40003 bytes 3 files changed, 841 insertions(+), 950 deletions(-) delete mode 100644 contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/ValueSelectorUnderGivenProbability.java 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 7f5efcf11a9..cf418411296 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 @@ -554,7 +554,7 @@ private void createCarriers(Scenario scenario, TripDistributionMatrix odMatrix, EnumeratedDistribution tourDistribution = createTourDistribution(smallScaleCommercialTrafficType); - Map stopDurationTimeSelector = createStopDurationDistributionPerCategory( + Map> stopDurationTimeSelector = createStopDurationDistributionPerCategory( smallScaleCommercialTrafficType); CarrierVehicleTypes carrierVehicleTypes = CarriersUtils.getCarrierVehicleTypes(scenario); @@ -718,10 +718,10 @@ private void createCarriers(Scenario scenario, TripDistributionMatrix odMatrix, // System.out.println("Final results for the tour duration distribution"); // tourDurationTimeSelector.writeResults(); - for (StopDurationGoodTrafficKey sector : stopDurationTimeSelector.keySet()) { - System.out.println("Final results for the stop duration distribution in sector " + sector); - stopDurationTimeSelector.get(sector).writeResults(); - } +// for (StopDurationGoodTrafficKey sector : stopDurationTimeSelector.keySet()) { +// System.out.println("Final results for the stop duration distribution in sector " + sector); +// stopDurationTimeSelector.get(sector); +// } log.warn("The jspritIterations are now set to {} in this simulation!", jspritIterations); log.info("Finished creating {} carriers including related services.", createdCarrier); @@ -840,7 +840,7 @@ private int getVehicleStartTime(TourStartAndDuration t) { * @param smallScaleCommercialTrafficType the traffic type * @return the service duration */ - private Integer getServiceTimePerStop(Map serviceDurationTimeSelector, + private Integer getServiceTimePerStop(Map> serviceDurationTimeSelector, String employeeCategory, String modeORvehType, String smallScaleCommercialTrafficType) { StopDurationGoodTrafficKey key = null; @@ -849,10 +849,9 @@ private Integer getServiceTimePerStop(Map createTourStartTimeDistribution(String smallScaleCommercialTrafficType) { - List tourStartProbabilityDistribution = new ArrayList<>(); + List> tourStartProbabilityDistribution = new ArrayList<>(); if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "1", 0.002)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("1", "2", 0.001)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("2", "3", 0.001)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("3", "4", 0.002)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("4", "5", 0.008)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("5", "6", 0.031)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("6", "7", 0.144)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("7", "8", 0.335)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("8", "9", 0.182)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("9", "10", 0.108)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "11", 0.057)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("11", "12", 0.032)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("12", "13", 0.021)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("13", "14", 0.021)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("14", "15", 0.019)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("15", "16", 0.012)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("16", "17", 0.009)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("17", "18", 0.006)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("18", "19", 0.004)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("19", "20", 0.003)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "21", 0.001)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("22", "23", 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 1), 0.002)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(1, 2), 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(2, 3), 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(3, 4), 0.002)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(4, 5), 0.008)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(5, 6), 0.031)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(6, 7), 0.144)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(7, 8), 0.335)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(8, 9), 0.182)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(9, 10), 0.108)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 11), 0.057)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(11, 12), 0.032)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(12, 13), 0.021)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(13, 14), 0.021)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(14, 15), 0.019)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(15, 16), 0.012)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(16, 17), 0.009)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(17, 18), 0.006)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(18, 19), 0.004)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(19, 20), 0.003)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 21), 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(22, 23), 0.001)); } else if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.goodsTraffic.toString())) { - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "1", 0.008)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("1", "2", 0.003)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("2", "3", 0.008)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("3", "4", 0.012)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("4", "5", 0.028)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("5", "6", 0.052)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("6", "7", 0.115)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("7", "8", 0.222)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("8", "9", 0.197)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("9", "10", 0.14)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "11", 0.076)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("11", "12", 0.035)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("12", "13", 0.022)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("13", "14", 0.022)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("14", "15", 0.021)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("15", "16", 0.014)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("16", "17", 0.008)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("17", "18", 0.005)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("18", "19", 0.004)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("19", "20", 0.002)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "21", 0.001)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("21", "22", 0.001)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("22", "23", 0.002)); - tourStartProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("23", "24", 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 1), 0.008)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(1, 2), 0.003)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(2, 3), 0.008)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(3, 4), 0.012)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(4, 5), 0.028)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(5, 6), 0.052)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(6, 7), 0.115)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(7, 8), 0.222)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(8, 9), 0.197)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(9, 10), 0.14)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 11), 0.076)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(11, 12), 0.035)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(12, 13), 0.022)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(13, 14), 0.022)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(14, 15), 0.021)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(15, 16), 0.014)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(16, 17), 0.008)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(17, 18), 0.005)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(18, 19), 0.004)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(19, 20), 0.002)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 21), 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(21, 22), 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(22, 23), 0.002)); + tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(23, 24), 0.001)); } - return new ValueSelectorUnderGivenProbability(tourStartProbabilityDistribution, rnd); + return new EnumeratedDistribution<>(rng, tourStartProbabilityDistribution); } /** @@ -1261,50 +1260,49 @@ private ValueSelectorUnderGivenProbability createTourStartTimeDistribution(Strin * @return the probability distribution for the tour duration */ @Deprecated //use createTourDistribution(String smallScaleCommercialTrafficType) instead - private ValueSelectorUnderGivenProbability createTourDurationTimeDistribution(String smallScaleCommercialTrafficType) { - List tourDurationProbabilityDistribution = new ArrayList<>(); + private EnumeratedDistribution createTourDurationTimeDistribution(String smallScaleCommercialTrafficType) { + List> tourDurationProbabilityDistribution = new ArrayList<>(); if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "1", 0.14)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("1", "2", 0.066)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("2", "3", 0.056)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("3", "4", 0.052)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("4", "5", 0.061)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("5", "6", 0.063)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("6", "7", 0.07)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("7", "8", 0.086)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("8", "9", 0.14)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("9", "10", 0.122)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "11", 0.068)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("11", "12", 0.031)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("12", "13", 0.018)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("13", "14", 0.01)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("14", "15", 0.006)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("15", "16", 0.003)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("16", "17", 0.002)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("17", "18", 0.001)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 1), 0.14)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(1, 2), 0.066)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(2, 3), 0.056)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(3, 4), 0.052)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(4, 5), 0.061)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(5, 6), 0.063)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(6, 7), 0.07)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(7, 8), 0.086)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(8, 9), 0.14)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(9, 10), 0.122)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 11), 0.068)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(11, 12), 0.031)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(12, 13), 0.018)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(13, 14), 0.01)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(14, 15), 0.006)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(15, 16), 0.003)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(16, 17), 0.002)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(17, 18), 0.001)); } else if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.goodsTraffic.toString())) { - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "1", 0.096)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("1", "2", 0.074)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("2", "3", 0.065)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("3", "4", 0.071)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("4", "5", 0.086)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("5", "6", 0.084)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("6", "7", 0.084)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("7", "8", 0.101)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("8", "9", 0.118)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("9", "10", 0.092)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "11", 0.048)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("11", "12", 0.027)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("12", "13", 0.015)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("13", "14", 0.011)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("14", "15", 0.006)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("15", "16", 0.004)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("16", "17", 0.002)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("17", "18", 0.001)); - tourDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("18", "19", 0.001)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 1), 0.096)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(1, 2), 0.074)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(2, 3), 0.065)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(3, 4), 0.071)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(4, 5), 0.086)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(5, 6), 0.084)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(6, 7), 0.084)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(7, 8), 0.101)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(8, 9), 0.118)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(9, 10), 0.092)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 11), 0.048)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(11, 12), 0.027)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(12, 13), 0.015)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(13, 14), 0.011)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(14, 15), 0.006)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(15, 16), 0.004)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(16, 17), 0.002)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(17, 18), 0.001)); + tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(18, 19), 0.001)); } - - return new ValueSelectorUnderGivenProbability(tourDurationProbabilityDistribution, rnd); + return new EnumeratedDistribution<>(rng, tourDurationProbabilityDistribution); } /** @@ -1799,763 +1797,793 @@ else if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType. * The values are given in [min] and have an upperBound. * Data source: KiD 2002 * - * @param smallScaleCommercialTrafficType the type of small scale commercial traffic - * @return the probability distribution for the duration of the services + * @param smallScaleCommercialTrafficType the type of small scale commercial traffic + * @return the probability distribution for the duration of the services */ - private Map createStopDurationDistributionPerCategory(String smallScaleCommercialTrafficType) { + private Map> createStopDurationDistributionPerCategory(String smallScaleCommercialTrafficType) { + + Map> stopDurationProbabilityDistribution = new HashMap<>(); - Map stopDurationProbabilityDistribution = new HashMap<>(); if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { - List singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "30", 0.098)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "60", 0.17)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "90", 0.127)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.11)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "180", 0.17)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.076)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.057)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "360", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("360", "420", 0.026)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "480", 0.045)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("480", "540", 0.064)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "600", 0.034)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("600", "720", 0.012)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("720", "840", 0.002)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", null), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "30", 0.054)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "60", 0.164)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "90", 0.153)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.087)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "180", 0.12)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.055)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.044)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "360", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("360", "420", 0.025)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "480", 0.069)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("480", "540", 0.132)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "600", 0.058)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("600", "720", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("720", "840", 0.002)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", null), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "30", 0.13)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "60", 0.324)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "90", 0.178)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.108)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "180", 0.097)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.034)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "360", 0.018)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("360", "420", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "480", 0.027)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("480", "540", 0.029)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "600", 0.008)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("600", "720", 0.006)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("720", "840", 0.001)); + List> thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 30), 0.098)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 60), 0.17)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 90), 0.127)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.11)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 180), 0.17)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.076)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.057)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 360), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(360, 420), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 480), 0.045)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(480, 540), 0.064)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 600), 0.034)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(600, 720), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(720, 840), 0.002)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector",null), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 30), 0.054)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 60), 0.164)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 90), 0.153)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.087)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 180), 0.12)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.055)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.044)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 360), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(360, 420), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 480), 0.069)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(480, 540), 0.132)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 600), 0.058)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(600, 720), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(720, 840), 0.002)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction",null), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 30), 0.13)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 60), 0.324)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 90), 0.178)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.108)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 180), 0.097)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.034)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 360), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(360, 420), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 480), 0.027)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(480, 540), 0.029)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 600), 0.008)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(600, 720), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(720, 840), 0.001)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest",null), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "30", 0.178)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "60", 0.301)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "90", 0.192)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.104)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "180", 0.092)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.043)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.013)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "360", 0.017)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("360", "420", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "480", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("480", "540", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "600", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("600", "720", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("720", "840", 0.001)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 30), 0.178)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 60), 0.301)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 90), 0.192)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.104)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 180), 0.092)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.043)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.013)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 360), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(360, 420), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 480), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(480, 540), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 600), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(600, 720), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(720, 840), 0.001)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail",null), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "30", 0.144)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "60", 0.372)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "90", 0.203)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.069)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "180", 0.112)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.038)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "360", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("360", "420", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "480", 0.012)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("480", "540", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "600", 0.005)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("600", "720", 0.005)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 30), 0.144)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 60), 0.372)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 90), 0.203)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.069)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 180), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.038)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 360), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(360, 420), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 480), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(480, 540), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 600), 0.005)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(600, 720), 0.005)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels",null), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "30", 0.196)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "60", 0.292)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "90", 0.19)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.101)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "180", 0.105)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.034)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.017)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "360", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("360", "420", 0.013)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "480", 0.019)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("480", "540", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "600", 0.006)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("600", "720", 0.004)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("720", "840", 0.001)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 30), 0.196)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 60), 0.292)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 90), 0.19)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 180), 0.105)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.034)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 360), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(360, 420), 0.013)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 480), 0.019)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(480, 540), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 600), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(600, 720), 0.004)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(720, 840), 0.001)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest",null), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); } else if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.goodsTraffic.toString())) { - List singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.038)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.049)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.052)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.094)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.125)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.094)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.167)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.094)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.113)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.056)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.04)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.026)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.002)); + List> thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.038)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.049)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.052)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.125)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.167)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.113)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.056)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.04)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.002)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp1"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.025)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.025)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.05)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.043)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.112)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.168)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.149)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.081)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.168)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.068)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.068)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.025)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.019)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.05)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.043)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.168)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.149)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.081)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.168)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.068)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.068)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.019)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp2"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.036)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.098)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.036)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.042)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.124)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.085)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.144)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.105)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.052)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.072)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.052)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.023)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.033)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.062)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("660", "780", 0.003)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.036)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.098)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.036)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.042)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.124)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.085)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.144)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.105)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.052)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.072)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.052)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.023)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.033)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(660, 780), 0.003)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp3"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.071)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.143)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.429)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.179)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.107)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.071)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.071)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.143)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.429)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.179)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.107)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.071)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp4"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.026)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.395)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.158)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.132)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.026)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.105)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.079)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.026)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.053)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.395)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.158)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.132)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.105)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.079)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.053)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp5"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.033)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.064)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.109)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.088)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.095)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.112)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.105)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.114)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.053)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.088)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.038)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.012)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.051)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.015)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.033)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.064)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.109)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.088)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.095)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.105)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.114)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.053)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.088)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.038)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.051)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.015)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp1"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.027)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.061)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.045)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.068)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.083)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.112)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.114)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.146)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.058)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.114)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.036)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.022)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.065)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.023)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.027)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.061)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.045)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.068)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.083)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.114)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.146)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.058)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.114)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.036)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.022)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.065)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.023)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp2"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.04)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.074)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.09)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.086)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.069)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.113)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.135)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.071)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.008)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.044)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.041)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.03)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.021)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.075)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.022)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.04)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.074)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.09)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.086)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.069)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.113)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.135)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.071)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.008)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.044)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.041)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.03)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.021)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.075)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.022)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp3"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.036)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.055)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.018)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.236)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.073)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.018)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.164)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.091)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.109)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.055)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.018)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.055)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.055)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.018)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.036)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.055)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.236)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.073)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.164)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.091)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.109)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.055)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.055)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.055)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.018)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp4"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.163)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.21)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.165)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.125)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.095)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.101)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.04)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.03)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.006)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.008)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.002)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.004)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.008)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.004)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.163)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.21)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.165)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.125)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.095)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.04)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.03)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.008)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.002)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.004)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.008)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.004)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp5"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.072)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.093)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.123)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.113)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.137)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.081)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.102)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.087)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.079)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.032)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.021)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.018)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "780", 0.002)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.072)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.123)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.113)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.137)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.081)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.087)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.079)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.032)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.021)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 780), 0.002)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp1"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.062)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.14)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.093)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.115)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.133)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.102)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.098)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.071)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.067)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.038)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.027)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.011)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.14)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.115)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.133)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.098)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.071)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.067)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.038)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.027)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.011)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp2"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.051)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.214)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.146)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.129)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.10)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.072)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.083)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.063)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.054)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.022)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.008)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "900", 0.003)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.051)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.214)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.146)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.129)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.10)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.072)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.083)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.063)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.054)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.022)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.008)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 900), 0.003)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp3"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.163)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.224)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.153)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.061)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.173)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.082)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.122)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.01)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.163)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.224)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.153)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.061)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.173)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.082)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.122)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.01)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp4"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.003)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.195)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.225)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.16)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.143)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.089)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.075)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.031)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.048)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.003)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "660", 0.009)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.003)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.195)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.225)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.16)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.143)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.089)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.075)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.031)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.048)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.003)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 660), 0.009)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp5"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.057)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.108)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.093)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.133)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.133)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.11)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.102)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.064)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.104)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.049)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.015)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.015)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.003)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.005)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.006)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.003)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.057)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.108)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.133)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.133)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.11)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.064)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.104)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.049)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.015)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.015)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.003)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.005)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.003)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp1"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.084)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.119)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.183)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.076)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.085)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.101)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.124)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.069)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.057)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.041)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.002)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.025)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.004)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("780", "900", 0.002)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.084)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.119)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.183)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.076)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.085)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.124)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.069)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.057)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.041)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.002)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.004)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(780, 900), 0.002)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp2"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.103)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.23)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.193)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.08)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.065)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.071)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.072)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.044)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.054)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.035)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.013)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.003)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.003)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.103)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.23)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.193)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.08)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.065)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.071)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.072)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.044)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.054)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.035)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.013)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.003)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.003)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp3"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.094)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.179)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.094)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.245)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.123)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.075)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.094)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.038)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.019)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.019)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.179)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.245)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.123)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.075)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.038)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.019)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.019)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp4"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.066)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.063)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.142)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.165)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.135)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.102)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.122)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.033)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.086)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.043)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.023)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.017)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.003)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.066)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.063)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.142)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.165)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.135)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.122)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.033)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.086)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.043)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.023)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.003)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp5"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.159)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.173)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.173)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.088)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.115)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.071)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.051)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.041)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.031)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.017)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.007)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.159)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.173)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.173)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.088)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.115)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.071)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.051)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.041)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.031)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.007)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp1"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.292)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.135)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.062)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.197)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.051)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.079)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.022)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.045)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.056)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.034)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.006)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.022)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.292)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.135)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.197)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.051)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.079)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.022)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.045)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.056)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.034)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.022)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp2"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.092)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.111)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.224)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.173)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.09)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.103)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.045)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.028)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.056)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.017)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.019)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.025)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.006)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.006)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.092)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.111)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.224)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.173)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.09)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.103)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.045)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.028)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.056)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.019)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.006)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp3"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.146)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.098)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.146)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.195)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.268)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.012)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.037)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.012)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.012)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.146)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.098)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.146)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.195)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.268)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.037)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.012)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp4"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.026)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.042)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.062)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.121)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.133)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.144)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.144)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.104)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.121)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.046)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.026)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.005)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "900", 0.008)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.042)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.121)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.133)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.144)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.144)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.104)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.121)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.046)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.005)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 900), 0.008)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp5"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.061)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.093)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.101)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.125)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.125)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.101)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.124)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.08)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.093)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.046)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.013)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.017)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.004)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.005)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.061)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.125)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.125)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.124)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.08)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.046)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.013)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.004)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.005)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp1"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.081)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.101)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.101)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.109)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.124)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.065)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.109)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.124)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.097)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.032)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.022)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.017)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.003)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.008)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.081)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.109)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.124)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.065)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.109)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.124)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.097)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.032)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.022)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.003)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.008)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp2"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.052)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.114)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.155)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.111)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.151)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.112)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.125)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.043)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.051)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.026)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.016)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.009)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("660", "780", 0.003)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.052)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.114)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.155)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.111)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.151)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.125)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.043)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.051)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(660, 780), 0.003)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp3"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.082)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.102)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.449)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.061)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.163)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.102)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.02)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.082)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.449)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.061)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.163)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.02)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp4"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.02)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.151)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.296)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.156)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.065)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.121)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.05)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.075)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.015)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.005)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.005)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.151)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.296)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.156)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.065)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.121)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.05)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.075)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.015)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.005)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.005)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp5"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); // because no data für private persons; use average numbers of all employee categories - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.056)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.084)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.095)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.118)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.12)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.096)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.112)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.083)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.095)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.045)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.033)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.022)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.018)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.004)); + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.056)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.084)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.095)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.118)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.12)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.096)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.083)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.095)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.045)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.033)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.022)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.004)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp1"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.077)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.093)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.103)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.092)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.098)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.091)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.108)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.092)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.095)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.043)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.035)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.011)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.021)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.007)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.077)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.103)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.092)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.098)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.091)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.108)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.092)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.095)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.043)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.035)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.021)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.007)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp2"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.06)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.141)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.152)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.107)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.094)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.087)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.089)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.067)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.06)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.037)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.023)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.025)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.015)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.012)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.006)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("660", "780", 0.001)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.06)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.141)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.152)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.107)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.087)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.089)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.067)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.06)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.037)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.023)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.015)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(660, 780), 0.001)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp3"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.062)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.11)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.12)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.144)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.151)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.129)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.062)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.079)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.041)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.031)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.019)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "540", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("540", "660", 0.002)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.11)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.12)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.144)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.151)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.129)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.079)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.041)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.031)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.019)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.002)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp4"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); - - singleStopDurationProbabilityDistribution = new ArrayList<>(); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("0", "10", 0.024)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("10", "20", 0.099)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("20", "30", 0.147)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("30", "40", 0.17)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("40", "50", 0.133)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("50", "60", 0.108)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("60", "75", 0.116)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("75", "90", 0.058)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("90", "120", 0.075)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("120", "150", 0.03)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("150", "180", 0.01)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("180", "240", 0.014)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("240", "300", 0.005)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("300", "420", 0.004)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("420", "660", 0.007)); - singleStopDurationProbabilityDistribution.add(new ValueSelectorUnderGivenProbability.ProbabilityForValue("660", "900", 0.002)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.099)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.147)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.17)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.133)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.108)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.116)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.058)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.075)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.03)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.005)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.004)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 660), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(660, 900), 0.002)); stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp5"), - new ValueSelectorUnderGivenProbability(singleStopDurationProbabilityDistribution, rnd)); + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); } return stopDurationProbabilityDistribution; } @@ -2587,4 +2615,6 @@ private StopDurationGoodTrafficKey makeStopDurationGoodTrafficKey(String employe private record TourStartAndDuration(int hourLower, int hourUpper, double minDuration, double maxDuration) {} + public record DurationsBounds(int minDuration, int maxDuration) {} + } diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/ValueSelectorUnderGivenProbability.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/ValueSelectorUnderGivenProbability.java deleted file mode 100644 index 8a2d7ef9407..00000000000 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/ValueSelectorUnderGivenProbability.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.matsim.smallScaleCommercialTrafficGeneration; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -/** This class creates a distribution under given probabilities for the possible values. - * - * @author: Ricardo Ewert - */ -public class ValueSelectorUnderGivenProbability { - - private int anIntAsSum; - private final List ProbabilityDistribution; - private final Random rnd; - - public ValueSelectorUnderGivenProbability(List ProbabilityDistribution, Random rnd) { - this.anIntAsSum = 0; - this.ProbabilityDistribution = ProbabilityDistribution; - this.rnd = rnd; - } - - - public ProbabilityForValue getNextValueUnderGivenProbability() { - anIntAsSum++; - weightedProbability(); - ProbabilityForValue selectedValue = null; - while (selectedValue == null) { - ProbabilityForValue probabilityForValue = ProbabilityDistribution.get(rnd.nextInt(ProbabilityDistribution.size())); - if (probabilityForValue.getRealizedValues() < probabilityForValue.getExpectedCount()) { - selectedValue = probabilityForValue; - selectedValue.increaseRealizedValue(1); - } - } - return selectedValue; - } - - private void weightedProbability() { - - //List to hold the cumulative probabilities of each value - List cumulativeProbabilities = new ArrayList<>(); - double sum = 0; - //Calculate cumulative probabilities for each value - for (ProbabilityForValue l : ProbabilityDistribution) { - sum += l.getProbability(); - cumulativeProbabilities.add(sum); - } - //Generate a random number between 0 and sum - double r = rnd.nextDouble(0.0, sum); - //Select a value based on the cumulative probabilities - String selectedLetter = ProbabilityDistribution.stream() - //Find the first value whose cumulative probability is greater than the random number - .filter(l -> r < cumulativeProbabilities.get(ProbabilityDistribution.indexOf(l))) - .findFirst().get().getValue(); - - //Increment the expectedCount for the selected value - ProbabilityDistribution.stream() - .filter(a -> a.getValue().equals(selectedLetter)) - .findFirst() - .ifPresent(l -> l.setExpectedCount(l.getExpectedCount() + 1)); - } - public void writeResults(){ - for (ProbabilityForValue probabilityForValue : ProbabilityDistribution) { - System.out.println(probabilityForValue.getValue() - + " -> expected: " + probabilityForValue.getExpectedCount() - + "(" + String.format("%.2f", (probabilityForValue.getExpectedCount() * Math.pow(anIntAsSum, - -1)) * 100) + " %); prob: " + ((double) Math.round(probabilityForValue.getProbability() * 1000) / 10) + "%"); - } - } - - public static class ProbabilityForValue { - - private String value; - private String upperBound; - private int expectedCount; - private double probability; - private int realizedValues; - - public ProbabilityForValue(String value, double probability) { - this.value = value; - this.probability = probability; - this.expectedCount = 0; - this.realizedValues = 0; - } - - - public ProbabilityForValue(String lowerBound, String upperBound, double probability) { - this.value = lowerBound; - this.upperBound = upperBound; - this.probability = probability; - this.expectedCount = 0; - this.realizedValues = 0; - } - - public double getProbability() { - return probability; - } - - public void setProbability(double probability) { - this.probability = probability; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public int getExpectedCount() { - return expectedCount; - } - - public void setExpectedCount(int expectedCount) { - this.expectedCount = expectedCount; - } - - public int getRealizedValues() { - return realizedValues; - } - - public void setRealizedValues(int realizedValues) { - this.realizedValues = realizedValues; - } - - public void increaseRealizedValue(int i) { - setRealizedValues(this.getRealizedValues() + i); - } - - public String getUpperBound() { - return upperBound; - } - - public void setUpperBound(String upperBound) { - this.upperBound = upperBound; - } - } -} diff --git a/contribs/small-scale-traffic-generation/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 b402920a875921cf056b3b96bd2da8b8dae7a5e3..6934ebcecc0d338863a9d7a3090d42214105a3e4 100644 GIT binary patch literal 40003 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 X*3*om?w5Z_|0qQ+t<8V#pu_ziz_w6S From 5f49dcabaae7396ea1a775ca2ad369f378f3f0fb Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Tue, 27 Aug 2024 13:35:10 +0200 Subject: [PATCH 085/111] move tour specifications to separate class --- ...rateSmallScaleCommercialTrafficDemand.java | 1435 +---------------- ...faultTourSpecificationsByUsingKID2002.java | 1390 ++++++++++++++++ .../data/GetCommercialTourSpecifications.java | 47 + 3 files changed, 1462 insertions(+), 1410 deletions(-) create mode 100644 contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/DefaultTourSpecificationsByUsingKID2002.java create mode 100644 contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/GetCommercialTourSpecifications.java 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 cf418411296..64a271d14d8 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 @@ -72,6 +72,8 @@ import org.matsim.freight.carriers.CarrierCapabilities.FleetSize; import org.matsim.freight.carriers.controler.*; import org.matsim.freight.carriers.usecases.chessboard.CarrierTravelDisutilities; +import org.matsim.smallScaleCommercialTrafficGeneration.data.DefaultTourSpecificationsByUsingKID2002; +import org.matsim.smallScaleCommercialTrafficGeneration.data.GetCommercialTourSpecifications; import org.matsim.vehicles.CostInformation; import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.VehicleType; @@ -107,6 +109,7 @@ public class GenerateSmallScaleCommercialTrafficDemand implements MATSimAppComma private static final Logger log = LogManager.getLogger(GenerateSmallScaleCommercialTrafficDemand.class); private final IntegrateExistingTrafficToSmallScaleCommercial integrateExistingTrafficToSmallScaleCommercial; + private final GetCommercialTourSpecifications getCommercialTourSpecifications; private enum CreationOption { useExistingCarrierFileWithSolution, createNewCarrierFile, useExistingCarrierFileWithoutSolution @@ -176,10 +179,24 @@ public enum SmallScaleCommercialTrafficType { public GenerateSmallScaleCommercialTrafficDemand() { this.integrateExistingTrafficToSmallScaleCommercial = new DefaultIntegrateExistingTrafficToSmallScaleCommercialImpl(); log.info("Using default {} if existing models are integrated!", DefaultIntegrateExistingTrafficToSmallScaleCommercialImpl.class.getSimpleName()); + this.getCommercialTourSpecifications = new DefaultTourSpecificationsByUsingKID2002(); + log.info("Using default {} for tour specifications!", DefaultTourSpecificationsByUsingKID2002.class.getSimpleName()); } - public GenerateSmallScaleCommercialTrafficDemand(IntegrateExistingTrafficToSmallScaleCommercial integrateExistingTrafficToSmallScaleCommercial) { - this.integrateExistingTrafficToSmallScaleCommercial = integrateExistingTrafficToSmallScaleCommercial; - log.info("Using {} if existing models are integrated!", integrateExistingTrafficToSmallScaleCommercial.getClass().getSimpleName()); + public GenerateSmallScaleCommercialTrafficDemand(IntegrateExistingTrafficToSmallScaleCommercial integrateExistingTrafficToSmallScaleCommercial, GetCommercialTourSpecifications getCommercialTourSpecifications) { + if (integrateExistingTrafficToSmallScaleCommercial == null){ + this.integrateExistingTrafficToSmallScaleCommercial = new DefaultIntegrateExistingTrafficToSmallScaleCommercialImpl(); + log.info("Using default {} if existing models are integrated!", DefaultIntegrateExistingTrafficToSmallScaleCommercialImpl.class.getSimpleName()); + } else { + this.integrateExistingTrafficToSmallScaleCommercial = integrateExistingTrafficToSmallScaleCommercial; + log.info("Using {} if existing models are integrated!", integrateExistingTrafficToSmallScaleCommercial.getClass().getSimpleName()); + } + if (getCommercialTourSpecifications == null){ + this.getCommercialTourSpecifications = new DefaultTourSpecificationsByUsingKID2002(); + log.info("Using default {} for tour specifications!", DefaultTourSpecificationsByUsingKID2002.class.getSimpleName()); + } else { + this.getCommercialTourSpecifications = getCommercialTourSpecifications; + log.info("Using {} for tour specifications!", getCommercialTourSpecifications.getClass().getSimpleName()); + } } public static void main(String[] args) { @@ -552,10 +569,9 @@ private void createCarriers(Scenario scenario, TripDistributionMatrix odMatrix, int createdCarrier = 0; int fixedNumberOfVehiclePerTypeAndLocation = 1; //TODO possible improvement, perhaps check KiD - EnumeratedDistribution tourDistribution = createTourDistribution(smallScaleCommercialTrafficType); + EnumeratedDistribution tourDistribution = getCommercialTourSpecifications.createTourDistribution(smallScaleCommercialTrafficType, rng); - Map> stopDurationTimeSelector = createStopDurationDistributionPerCategory( - smallScaleCommercialTrafficType); + Map> stopDurationTimeSelector = getCommercialTourSpecifications.createStopDurationDistributionPerCategory(smallScaleCommercialTrafficType, rng); CarrierVehicleTypes carrierVehicleTypes = CarriersUtils.getCarrierVehicleTypes(scenario); Map, VehicleType> additionalCarrierVehicleTypes = scenario.getVehicles().getVehicleTypes(); @@ -1187,1408 +1203,7 @@ public double getScore() { } - /** - * Creates the probability distribution for the tour start times for the day. - * The values are given in [h] and have an upperBound. - * Data source: KiD 2002 - * - * @return the probability distribution for the tour start times - */ - - @Deprecated //use createTourDistribution(String smallScaleCommercialTrafficType) instead - private EnumeratedDistribution createTourStartTimeDistribution(String smallScaleCommercialTrafficType) { - - List> tourStartProbabilityDistribution = new ArrayList<>(); - if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 1), 0.002)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(1, 2), 0.001)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(2, 3), 0.001)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(3, 4), 0.002)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(4, 5), 0.008)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(5, 6), 0.031)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(6, 7), 0.144)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(7, 8), 0.335)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(8, 9), 0.182)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(9, 10), 0.108)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 11), 0.057)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(11, 12), 0.032)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(12, 13), 0.021)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(13, 14), 0.021)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(14, 15), 0.019)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(15, 16), 0.012)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(16, 17), 0.009)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(17, 18), 0.006)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(18, 19), 0.004)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(19, 20), 0.003)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 21), 0.001)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(22, 23), 0.001)); - } else if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.goodsTraffic.toString())) { - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 1), 0.008)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(1, 2), 0.003)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(2, 3), 0.008)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(3, 4), 0.012)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(4, 5), 0.028)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(5, 6), 0.052)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(6, 7), 0.115)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(7, 8), 0.222)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(8, 9), 0.197)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(9, 10), 0.14)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 11), 0.076)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(11, 12), 0.035)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(12, 13), 0.022)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(13, 14), 0.022)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(14, 15), 0.021)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(15, 16), 0.014)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(16, 17), 0.008)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(17, 18), 0.005)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(18, 19), 0.004)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(19, 20), 0.002)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 21), 0.001)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(21, 22), 0.001)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(22, 23), 0.002)); - tourStartProbabilityDistribution.add(Pair.create(new DurationsBounds(23, 24), 0.001)); - - } - return new EnumeratedDistribution<>(rng, tourStartProbabilityDistribution); - } - - /** - * Creates the probability distribution for the tour duration for the day. - * The values are given in [h] and have an upperBound. - * Data source: KiD 2002 - * - * @return the probability distribution for the tour duration - */ - @Deprecated //use createTourDistribution(String smallScaleCommercialTrafficType) instead - private EnumeratedDistribution createTourDurationTimeDistribution(String smallScaleCommercialTrafficType) { - List> tourDurationProbabilityDistribution = new ArrayList<>(); - if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 1), 0.14)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(1, 2), 0.066)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(2, 3), 0.056)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(3, 4), 0.052)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(4, 5), 0.061)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(5, 6), 0.063)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(6, 7), 0.07)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(7, 8), 0.086)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(8, 9), 0.14)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(9, 10), 0.122)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 11), 0.068)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(11, 12), 0.031)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(12, 13), 0.018)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(13, 14), 0.01)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(14, 15), 0.006)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(15, 16), 0.003)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(16, 17), 0.002)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(17, 18), 0.001)); - } else if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.goodsTraffic.toString())) { - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 1), 0.096)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(1, 2), 0.074)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(2, 3), 0.065)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(3, 4), 0.071)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(4, 5), 0.086)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(5, 6), 0.084)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(6, 7), 0.084)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(7, 8), 0.101)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(8, 9), 0.118)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(9, 10), 0.092)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 11), 0.048)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(11, 12), 0.027)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(12, 13), 0.015)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(13, 14), 0.011)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(14, 15), 0.006)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(15, 16), 0.004)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(16, 17), 0.002)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(17, 18), 0.001)); - tourDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(18, 19), 0.001)); - } - return new EnumeratedDistribution<>(rng, tourDurationProbabilityDistribution); - } - - /** - * 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 - */ - private EnumeratedDistribution createTourDistribution(String smallScaleCommercialTrafficType) { - List> tourDurationProbabilityDistribution = new ArrayList<>(); - - if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { - - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 0.0, 30.0), 0.0005917893035900173)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 30.0, 60.0), 0.00021859484237437887)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 90.0, 120.0), 0.00037490287407786324)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 120.0, 180.0), 0.0004337321926125666)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 180.0, 240.0), 0.0005834182239827621)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 240.0, 300.0), 0.0005116938323661723)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 300.0, 360.0), 0.0005027065159573272)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 360.0, 420.0), 0.0006719740164147071)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 420.0, 480.0), 0.00022375027665644004)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 480.0, 540.0), 0.00022103749529549306)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 540.0, 600.0), 0.00022119440831885122)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 600.0, 660.0), 0.0002732185104003396)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 660.0, 720.0), 7.287567629774946e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 720.0, 780.0), 0.0005090670761685264)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 780.0, 840.0), 0.0002169454122557984)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 840.0, 1080.0), 0.0016947794402011696)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 0.0, 30.0), 0.00033050926084770643)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 30.0, 60.0), 0.0004963985976117265)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 60.0, 90.0), 0.0009458837608304906)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 90.0, 120.0), 0.0006507941771038976)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 120.0, 180.0), 0.0002949035696660126)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 180.0, 240.0), 0.0005812406149568905)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 240.0, 300.0), 0.00072666224822023)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 300.0, 360.0), 0.0006017750128936798)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 360.0, 420.0), 0.0007696491628020603)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 420.0, 480.0), 0.0006951014583380694)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 480.0, 540.0), 0.0006675367479652174)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 540.0, 600.0), 0.0009951412624367468)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 600.0, 660.0), 0.0006193958232902363)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 660.0, 720.0), 0.0005496335422364244)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 720.0, 780.0), 0.000963763774344583)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 780.0, 840.0), 0.001585152586657775)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 840.0, 1080.0), 0.0022779973751500433)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 0.0, 30.0), 0.003678291745870938)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 30.0, 60.0), 0.0037749680865755936)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 60.0, 90.0), 0.0021464058981758467)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 90.0, 120.0), 0.0010105726369455444)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 120.0, 180.0), 0.0017166729332290624)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 180.0, 240.0), 0.001218657902054598)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 240.0, 300.0), 0.0019212859349972463)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 300.0, 360.0), 0.0018498349748915703)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 360.0, 420.0), 0.0020820722844894844)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 420.0, 480.0), 0.0033255032578691536)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 480.0, 540.0), 0.004499580798913233)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 540.0, 600.0), 0.004508722079694882)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 600.0, 660.0), 0.009460453046374911)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 660.0, 720.0), 0.008632039128635343)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 720.0, 780.0), 0.005173130409039029)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 780.0, 840.0), 0.0021287189901771954)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 840.0, 1080.0), 0.002735246591728173)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 0.0, 30.0), 0.015534599731489868)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 30.0, 60.0), 0.009424737666749776)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 60.0, 90.0), 0.003979757502241877)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 90.0, 120.0), 0.0026219034509082214)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 120.0, 180.0), 0.004373894821911171)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 180.0, 240.0), 0.005349695968407728)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 240.0, 300.0), 0.008398668008895199)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 300.0, 360.0), 0.013017576110359298)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 360.0, 420.0), 0.013178466937493282)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 420.0, 480.0), 0.015799261066253244)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 480.0, 540.0), 0.031932993774084484)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 540.0, 600.0), 0.056976770375347194)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 600.0, 660.0), 0.03411514635058722)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 660.0, 720.0), 0.010952547256934878)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 720.0, 780.0), 0.005071677294689363)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 780.0, 840.0), 0.002758017802376135)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 840.0, 1080.0), 0.003182481371327368)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 0.0, 30.0), 0.018010507239762663)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 30.0, 60.0), 0.009246211080247332)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 60.0, 90.0), 0.006297103845359016)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 90.0, 120.0), 0.003415561088528113)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 120.0, 180.0), 0.010918022744746231)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 180.0, 240.0), 0.011371721163141522)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 240.0, 300.0), 0.01861910064916215)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 300.0, 360.0), 0.015443374909900384)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 360.0, 420.0), 0.020470726990450452)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 420.0, 480.0), 0.030727618880727087)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 480.0, 540.0), 0.07364088624635841)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 540.0, 600.0), 0.04082061588575034)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 600.0, 660.0), 0.012935881167590665)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 660.0, 720.0), 0.005469250367916343)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 720.0, 780.0), 0.0030030673084490513)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 780.0, 840.0), 0.0011042643367551329)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 840.0, 1080.0), 0.0011327583672022575)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 0.0, 30.0), 0.015589932735904798)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 30.0, 60.0), 0.007157798082590814)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 60.0, 90.0), 0.006563655710107534)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 90.0, 120.0), 0.004888423230467872)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 120.0, 180.0), 0.01261126944262904)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 180.0, 240.0), 0.013275311108363174)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 240.0, 300.0), 0.011059737216827653)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 300.0, 360.0), 0.00980644443311104)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 360.0, 420.0), 0.013476523854959467)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 420.0, 480.0), 0.01766932338862498)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 480.0, 540.0), 0.013855266610087914)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 540.0, 600.0), 0.006090238569895901)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 600.0, 660.0), 0.00326688741194661)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 660.0, 720.0), 0.0009742217966822537)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 720.0, 780.0), 0.0008462163162537791)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 780.0, 840.0), 0.0009357453082055104)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 840.0, 1080.0), 0.0006867783494497427)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 0.0, 30.0), 0.011836581569331607)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 30.0, 60.0), 0.0060475163532472224)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 60.0, 90.0), 0.006091033719221284)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 90.0, 120.0), 0.004870323217391879)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 120.0, 180.0), 0.009852214102720915)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 180.0, 240.0), 0.006649077724867284)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 240.0, 300.0), 0.006549809619698136)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 300.0, 360.0), 0.00743649188225418)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 360.0, 420.0), 0.008370330719772223)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 420.0, 480.0), 0.006055410372169952)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 480.0, 540.0), 0.003221026290023441)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 540.0, 600.0), 0.00270804359225063)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 600.0, 660.0), 0.0011328763880567346)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 660.0, 720.0), 0.0005295062815147344)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 720.0, 780.0), 0.0005244739409173669)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 780.0, 840.0), 0.00022261373811852168)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 840.0, 1080.0), 0.0002976820307410009)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 0.0, 30.0), 0.0072347359578799255)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 30.0, 60.0), 0.005528762818372258)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 60.0, 90.0), 0.004301874597910846)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 90.0, 120.0), 0.002706271535768685)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 120.0, 180.0), 0.004461225555303183)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 180.0, 240.0), 0.003289266637558867)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 240.0, 300.0), 0.004773112389257731)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 300.0, 360.0), 0.004153307715767419)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 360.0, 420.0), 0.0023002274828502435)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 420.0, 480.0), 0.002295722460734858)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 480.0, 540.0), 0.0008008191218782178)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 540.0, 600.0), 0.0005302938593833011)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 600.0, 660.0), 0.00012017333498779025)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 660.0, 720.0), 0.00029497120761336085)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 720.0, 780.0), 7.442207741095891e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 780.0, 840.0), 7.491510042413546e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 0.0, 30.0), 0.005979044848708125)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 30.0, 60.0), 0.0030727725862362003)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 60.0, 90.0), 0.0018328582061095421)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 90.0, 120.0), 0.0015730248216810105)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 120.0, 180.0), 0.0025909176745678485)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 180.0, 240.0), 0.0023584284876344117)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 240.0, 300.0), 0.002888683132930499)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 300.0, 360.0), 0.0026723295114103734)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 360.0, 420.0), 0.001368034507711622)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 420.0, 480.0), 0.001322142609646873)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 480.0, 540.0), 0.00014896322977011863)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 540.0, 600.0), 0.00036793050573151096)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 600.0, 660.0), 0.0003024749417379503)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 660.0, 720.0), 7.263766179594998e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 720.0, 780.0), 7.737798495114381e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 840.0, 1080.0), 7.360037219024495e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 0.0, 30.0), 0.005442934607459622)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 30.0, 60.0), 0.0023099603288455053)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 60.0, 90.0), 0.0015476125810207045)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 90.0, 120.0), 0.0015690710859882222)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 120.0, 180.0), 0.003155552178314994)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 180.0, 240.0), 0.0024715148201473933)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 240.0, 300.0), 0.00214638868043489)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 300.0, 360.0), 0.0017134793037846727)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 360.0, 420.0), 0.0009684921868733149)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 420.0, 480.0), 0.0005519992558366529)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 480.0, 540.0), 0.0004441672064981391)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 540.0, 600.0), 0.00022332686365997108)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 600.0, 660.0), 0.00023780343565208111)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 660.0, 720.0), 0.00014898555439278127)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 0.0, 30.0), 0.0065652971880044205)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 30.0, 60.0), 0.0033645458423904226)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 60.0, 90.0), 0.002247264924524252)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 90.0, 120.0), 0.0021755851670695867)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 120.0, 180.0), 0.00292250684836152)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 180.0, 240.0), 0.0029939610328467135)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 240.0, 300.0), 0.0013771262994841458)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 300.0, 360.0), 0.0005929387919824101)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 360.0, 420.0), 0.0007299574379337656)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 420.0, 480.0), 0.00015161310680499916)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 480.0, 540.0), 0.00022326623210165028)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 540.0, 600.0), 0.00021908720500178134)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 0.0, 30.0), 0.004700575755513116)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 30.0, 60.0), 0.002876930233578738)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 60.0, 90.0), 0.0012326059557891803)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 90.0, 120.0), 0.001688513011030605)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 120.0, 180.0), 0.0024148215923521744)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 180.0, 240.0), 0.0009664823712470381)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 240.0, 300.0), 0.0008158516384741175)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 300.0, 360.0), 0.0005326476409500361)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 360.0, 420.0), 0.00037447250704764534)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 420.0, 480.0), 7.278074100962308e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 480.0, 540.0), 0.00015460621875651884)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 540.0, 600.0), 0.00022625636961834557)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 840.0, 1080.0), 7.369704340227916e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 0.0, 30.0), 0.005421542133242069)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 30.0, 60.0), 0.0028543297205245563)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 60.0, 90.0), 0.001320449445343739)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 90.0, 120.0), 0.0011372744623221703)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 120.0, 180.0), 0.0011175546229352943)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 180.0, 240.0), 0.0005212091408906178)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 240.0, 300.0), 0.00025063117439263165)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 300.0, 360.0), 0.0002906557976189996)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 360.0, 420.0), 6.934683987097806e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 420.0, 480.0), 7.198332684426051e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 0.0, 30.0), 0.005997678933359281)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 30.0, 60.0), 0.0014450238860978966)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 60.0, 90.0), 0.0008909835110546583)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 90.0, 120.0), 0.0008692603958852261)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 120.0, 180.0), 0.0004645626068627116)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 180.0, 240.0), 0.0005161866418057845)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 240.0, 300.0), 0.00047492492382272117)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 300.0, 360.0), 7.348989097075777e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 360.0, 420.0), 0.0003000342936128893)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 0.0, 30.0), 0.004621906661329853)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 30.0, 60.0), 0.0015152391398060199)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 60.0, 90.0), 0.0006769045119123614)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 90.0, 120.0), 0.00044820275277284946)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 120.0, 180.0), 0.0007140653752077821)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 180.0, 240.0), 0.0001502672132808765)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 240.0, 300.0), 0.0003842231300012746)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 300.0, 360.0), 0.00021634404805889257)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 0.0, 30.0), 0.0034023082743939916)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 30.0, 60.0), 0.0006251774232962365)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 60.0, 90.0), 0.00022163965781205308)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 90.0, 120.0), 7.360037219024495e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 120.0, 180.0), 0.00045934601255169126)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 180.0, 240.0), 7.511874968194916e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 240.0, 300.0), 0.0001486019187134722)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 300.0, 360.0), 7.505084488366769e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 420.0, 480.0), 7.594714627228585e-05)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 0.0, 30.0), 0.005137034953520923)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 30.0, 60.0), 0.0010774703023578233)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 60.0, 90.0), 0.00048539418673270443)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 90.0, 120.0), 0.0002988049182984063)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 120.0, 180.0), 0.00032644209078127245)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 180.0, 240.0), 0.0005357497395368892)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 240.0, 300.0), 0.0002944914928100358)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 300.0, 360.0), 0.00022851651374757815)); - } - else if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.goodsTraffic.toString())) { - - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 0.0, 30.0), 0.0002666800577200411)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 30.0, 60.0), 0.0006395055678719748)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 60.0, 90.0), 0.0007110769046958423)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 90.0, 120.0), 0.0006665961628449491)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 120.0, 180.0), 0.0023195866923785575)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 180.0, 240.0), 0.00261751319938476)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 240.0, 300.0), 0.0021430032453503087)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 300.0, 360.0), 0.0029303876579925905)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 360.0, 420.0), 0.00283576618143643)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 420.0, 480.0), 0.0027188265347502893)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 480.0, 540.0), 0.002597768116531099)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 540.0, 600.0), 0.002659151494701916)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 600.0, 660.0), 0.0021738406044924437)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 660.0, 720.0), 0.0021949848461843176)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 720.0, 780.0), 0.0021801193011023083)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 780.0, 840.0), 0.001746033717539671)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(0, 4, 840.0, 1080.0), 0.00350888397405923)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 0.0, 30.0), 0.0006845643884312735)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 30.0, 60.0), 0.0004003126952082357)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 60.0, 90.0), 0.0008155012585632697)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 90.0, 120.0), 0.0010930534970200114)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 120.0, 180.0), 0.0011760353713952051)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 180.0, 240.0), 0.0019364061980548415)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 240.0, 300.0), 0.002953452881036028)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 300.0, 360.0), 0.002589370165068672)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 360.0, 420.0), 0.0025604405819583055)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 420.0, 480.0), 0.0034319041631081476)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 480.0, 540.0), 0.0033480025727905907)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 540.0, 600.0), 0.002175717502193024)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 600.0, 660.0), 0.0028036478238686957)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 660.0, 720.0), 0.0028759635193342887)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 720.0, 780.0), 0.0017584406503249872)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 780.0, 840.0), 0.0016742001219093045)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(4, 5, 840.0, 1080.0), 0.0020658205220468245)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 0.0, 30.0), 0.0017247403950228777)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 30.0, 60.0), 0.003090998236080484)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 60.0, 90.0), 0.0015209554995803177)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 90.0, 120.0), 0.0016533392810110293)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 120.0, 180.0), 0.003732306124403562)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 180.0, 240.0), 0.004106247357091271)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 240.0, 300.0), 0.003188442431357427)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 300.0, 360.0), 0.005929370570550301)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 360.0, 420.0), 0.005992695595693005)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 420.0, 480.0), 0.006390572360276255)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 480.0, 540.0), 0.00993732232424166)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 540.0, 600.0), 0.007917613781985494)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 600.0, 660.0), 0.00753055040114282)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 660.0, 720.0), 0.004839531706746983)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 720.0, 780.0), 0.003571294178536547)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 780.0, 840.0), 0.0022261075091276465)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(5, 6, 840.0, 1080.0), 0.0020123396391017526)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 0.0, 30.0), 0.00553085745500388)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 30.0, 60.0), 0.005164301035284355)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 60.0, 90.0), 0.0034287284279468384)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 90.0, 120.0), 0.003359657704287739)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 120.0, 180.0), 0.005963896679549981)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 180.0, 240.0), 0.006376396116305889)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 240.0, 300.0), 0.011553162434249647)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 300.0, 360.0), 0.01216390369869719)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 360.0, 420.0), 0.015303642980241483)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 420.0, 480.0), 0.01894502604909179)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 480.0, 540.0), 0.026995818384739457)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 540.0, 600.0), 0.03735238580259259)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 600.0, 660.0), 0.02007351137947408)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 660.0, 720.0), 0.007579189226621267)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 720.0, 780.0), 0.003806896198418994)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 780.0, 840.0), 0.0020371212990837376)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(6, 7, 840.0, 1080.0), 0.00246729057836831)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 0.0, 30.0), 0.007834929725170775)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 30.0, 60.0), 0.007875284751511802)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 60.0, 90.0), 0.0056369706407995695)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 90.0, 120.0), 0.007252792818630801)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 120.0, 180.0), 0.011595289158181222)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 180.0, 240.0), 0.01584695155572567)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 240.0, 300.0), 0.019385993489144607)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 300.0, 360.0), 0.01804569113072999)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 360.0, 420.0), 0.020338168968415053)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 420.0, 480.0), 0.03244941203821404)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 480.0, 540.0), 0.046986423884473)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 540.0, 600.0), 0.026127574804977814)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 600.0, 660.0), 0.006859707180170414)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 660.0, 720.0), 0.004053368732850601)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 720.0, 780.0), 0.0017728320836715625)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 780.0, 840.0), 0.0008117046283836942)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(7, 8, 840.0, 1080.0), 0.0014889766393137468)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 0.0, 30.0), 0.008702611915372131)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 30.0, 60.0), 0.009703391735884857)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 60.0, 90.0), 0.00833249802530372)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 90.0, 120.0), 0.008160824294542027)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 120.0, 180.0), 0.014522058792957903)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 180.0, 240.0), 0.019189639247661674)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 240.0, 300.0), 0.022628081955363144)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 300.0, 360.0), 0.018168175275565253)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 360.0, 420.0), 0.01830766579908246)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 420.0, 480.0), 0.022414786327228577)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 480.0, 540.0), 0.015454698179801149)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 540.0, 600.0), 0.00743339793333549)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 600.0, 660.0), 0.0028959167218627997)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 660.0, 720.0), 0.0011608823477359163)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 720.0, 780.0), 0.0006126324367099846)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 780.0, 840.0), 0.0007090395380022889)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(8, 9, 840.0, 1080.0), 0.0009650931773638335)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 0.0, 30.0), 0.010532384705529854)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 30.0, 60.0), 0.010106787618396446)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 60.0, 90.0), 0.007305519187631069)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 90.0, 120.0), 0.0065298278976416635)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 120.0, 180.0), 0.012991661099288086)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 180.0, 240.0), 0.011082392048301831)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 240.0, 300.0), 0.013735041027849332)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 300.0, 360.0), 0.012921165569106639)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 360.0, 420.0), 0.010187951930469277)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 420.0, 480.0), 0.0070071162811467125)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 480.0, 540.0), 0.003478434072337058)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 540.0, 600.0), 0.002487434148850001)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 600.0, 660.0), 0.0007617139935295275)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 660.0, 720.0), 0.0004794259473854554)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 720.0, 780.0), 0.00011828408353297643)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(9, 10, 780.0, 840.0), 0.0009221448817170415)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 0.0, 30.0), 0.0053803765038808364)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 30.0, 60.0), 0.00748440387556175)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 60.0, 90.0), 0.003817044622559703)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 90.0, 120.0), 0.0042559767658946045)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 120.0, 180.0), 0.004633517730561146)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 180.0, 240.0), 0.0040156278424527785)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 240.0, 300.0), 0.004097425621422603)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 300.0, 360.0), 0.00534407493573042)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 360.0, 420.0), 0.002849425985304954)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 420.0, 480.0), 0.0024443772372422234)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 480.0, 540.0), 0.0011258612568464076)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 540.0, 600.0), 0.0005966047093584399)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 600.0, 660.0), 0.0005779388889435179)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 660.0, 720.0), 0.0004527621290439082)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 720.0, 780.0), 0.00011727646428602624)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(10, 11, 780.0, 840.0), 0.00011130198744577025)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 0.0, 30.0), 0.0025301846046864363)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 30.0, 60.0), 0.002932856090944951)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 60.0, 90.0), 0.0015297442159744696)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 90.0, 120.0), 0.0016816440829740813)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 120.0, 180.0), 0.0023140070407952395)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 180.0, 240.0), 0.0013768767086426792)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 240.0, 300.0), 0.0019019317686819275)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 300.0, 360.0), 0.0015577691125463963)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 360.0, 420.0), 0.001499121306916632)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 420.0, 480.0), 0.0007361366421130972)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 480.0, 540.0), 0.0007423049940853575)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 540.0, 600.0), 0.00011130198744577025)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 660.0, 720.0), 0.00024243947114654707)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(11, 12, 720.0, 780.0), 0.000261579996858755)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 0.0, 30.0), 0.0021669594044717543)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 30.0, 60.0), 0.0033993161916113994)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 60.0, 90.0), 0.001870484877697732)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 90.0, 120.0), 0.0008448185262884799)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 120.0, 180.0), 0.002024573233571085)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 180.0, 240.0), 0.0021888099857994042)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 240.0, 300.0), 0.0021657834323017752)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 300.0, 360.0), 0.0010623089332746248)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 360.0, 420.0), 0.0006268095760401356)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 420.0, 480.0), 0.0005094532977538987)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 480.0, 540.0), 0.0004744090926784203)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 540.0, 600.0), 0.00016487328572417658)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(12, 13, 660.0, 720.0), 0.0001162996982120756)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 0.0, 30.0), 0.0033401411497772818)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 30.0, 60.0), 0.002492685695459365)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 60.0, 90.0), 0.0027064477589805068)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 90.0, 120.0), 0.0018052297053924354)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 120.0, 180.0), 0.0027984509294891498)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 180.0, 240.0), 0.0022758505657711914)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 240.0, 300.0), 0.0003535503655144059)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 300.0, 360.0), 0.0005890430396050117)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 360.0, 420.0), 0.0002319134363595028)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 420.0, 480.0), 0.00011617748025141993)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 480.0, 540.0), 0.0003690064941818713)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 540.0, 600.0), 0.0001650495071007077)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 600.0, 660.0), 0.00023113252306835525)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(13, 14, 840.0, 1080.0), 0.00017239206443126303)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 0.0, 30.0), 0.003543871129770451)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 30.0, 60.0), 0.0018407982276338393)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 60.0, 90.0), 0.0010649270862293423)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 90.0, 120.0), 0.0009538696044712171)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 120.0, 180.0), 0.0021318639289119572)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 180.0, 240.0), 0.0019740243143620277)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 240.0, 300.0), 0.0006157677659961421)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 300.0, 360.0), 0.0004035374922773149)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 360.0, 420.0), 0.00011607019237524387)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 420.0, 480.0), 0.0003938282727195195)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 480.0, 540.0), 0.00011130198744577025)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(14, 15, 600.0, 660.0), 0.00011942109323430472)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 0.0, 30.0), 0.00254340964132742)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 30.0, 60.0), 0.0017847751078888892)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 60.0, 90.0), 0.000841891386995212)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 90.0, 120.0), 0.0003543852337006742)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 120.0, 180.0), 0.0013974221085794884)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 180.0, 240.0), 0.0006229273683665316)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 240.0, 300.0), 0.00020579571489011056)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 300.0, 360.0), 0.0004809214516599411)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 360.0, 420.0), 0.00022514291890117063)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 420.0, 480.0), 0.00014748146383900364)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(15, 16, 720.0, 780.0), 0.00011605559293173729)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 0.0, 30.0), 0.0019634787835054656)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 30.0, 60.0), 0.000860670737476427)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 60.0, 90.0), 0.0003550148096943092)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 90.0, 120.0), 0.000855728546868917)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 120.0, 180.0), 0.0009283998993093458)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 180.0, 240.0), 0.00022795178106384156)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 240.0, 300.0), 0.00024119874825349313)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 420.0, 480.0), 0.00023429279224671318)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 480.0, 540.0), 0.00011727269965059726)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(16, 17, 660.0, 720.0), 0.00011130198744577025)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 0.0, 30.0), 0.0017099830161073832)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 30.0, 60.0), 0.0006015092064895483)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 60.0, 90.0), 0.00011819436012345105)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 90.0, 120.0), 0.0002279569151752547)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 120.0, 180.0), 0.0006440525787748041)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 180.0, 240.0), 0.0003142746964600832)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 300.0, 360.0), 0.00022788575876606104)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 360.0, 420.0), 0.0004761806298753505)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(17, 18, 480.0, 540.0), 0.00011727269965059726)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 0.0, 30.0), 0.0020011795184968267)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 30.0, 60.0), 0.00023620950461199452)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 60.0, 90.0), 0.00011935825257957617)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 90.0, 120.0), 0.00011130198744577025)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 120.0, 180.0), 0.00012222981614916706)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 180.0, 240.0), 0.0002377005397786721)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 240.0, 300.0), 0.00026373526728965034)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 300.0, 360.0), 0.000256086036315955)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(18, 19, 360.0, 420.0), 0.00011394287938236544)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 0.0, 30.0), 0.0021116872169622083)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 30.0, 60.0), 0.0003681765715703113)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 60.0, 90.0), 0.0004137833254678062)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 90.0, 120.0), 0.00025108497234833097)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 120.0, 180.0), 0.0007576827338029722)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 180.0, 240.0), 0.0005180490039062906)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 240.0, 300.0), 0.0004944106124208977)); - tourDurationProbabilityDistribution.add(Pair.create(new TourStartAndDuration(19, 24, 300.0, 360.0), 0.0002278857587658224)); - } else - throw new IllegalArgumentException("Unknown small scale commercial traffic type: " + smallScaleCommercialTrafficType); - - return new EnumeratedDistribution<>(rng, tourDurationProbabilityDistribution); - } - - /** - * Creates the probability distribution for the duration of the services. - * The values are given in [min] and have an upperBound. - * Data source: KiD 2002 - * - * @param smallScaleCommercialTrafficType the type of small scale commercial traffic - * @return the probability distribution for the duration of the services - */ - private Map> createStopDurationDistributionPerCategory(String smallScaleCommercialTrafficType) { - - Map> stopDurationProbabilityDistribution = new HashMap<>(); - - if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { - List> thisStopDurationProbabilityDistribution = new ArrayList<>(); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 30), 0.098)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 60), 0.17)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 90), 0.127)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.11)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 180), 0.17)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.076)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.057)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 360), 0.01)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(360, 420), 0.026)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 480), 0.045)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(480, 540), 0.064)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 600), 0.034)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(600, 720), 0.012)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(720, 840), 0.002)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector",null), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - thisStopDurationProbabilityDistribution.clear(); - - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 30), 0.054)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 60), 0.164)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 90), 0.153)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.087)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 180), 0.12)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.055)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.044)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 360), 0.02)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(360, 420), 0.025)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 480), 0.069)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(480, 540), 0.132)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 600), 0.058)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(600, 720), 0.016)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(720, 840), 0.002)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction",null), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - thisStopDurationProbabilityDistribution.clear(); - - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 30), 0.13)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 60), 0.324)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 90), 0.178)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.108)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 180), 0.097)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.034)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.02)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 360), 0.018)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(360, 420), 0.02)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 480), 0.027)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(480, 540), 0.029)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 600), 0.008)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(600, 720), 0.006)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(720, 840), 0.001)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest",null), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - thisStopDurationProbabilityDistribution.clear(); - - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 30), 0.178)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 60), 0.301)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 90), 0.192)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.104)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 180), 0.092)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.043)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.013)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 360), 0.017)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(360, 420), 0.011)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 480), 0.016)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(480, 540), 0.016)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 600), 0.007)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(600, 720), 0.007)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(720, 840), 0.001)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail",null), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - thisStopDurationProbabilityDistribution.clear(); - - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 30), 0.144)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 60), 0.372)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 90), 0.203)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.069)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 180), 0.112)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.038)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.011)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 360), 0.011)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(360, 420), 0.011)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 480), 0.012)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(480, 540), 0.007)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 600), 0.005)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(600, 720), 0.005)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels",null), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - thisStopDurationProbabilityDistribution.clear(); - - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 30), 0.196)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 60), 0.292)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 90), 0.19)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.101)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 180), 0.105)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.034)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.017)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 360), 0.009)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(360, 420), 0.013)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 480), 0.019)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(480, 540), 0.014)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 600), 0.006)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(600, 720), 0.004)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(720, 840), 0.001)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest",null), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - - } else if (smallScaleCommercialTrafficType.equals(SmallScaleCommercialTrafficType.goodsTraffic.toString())) { - List> thisStopDurationProbabilityDistribution = new ArrayList<>(); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.038)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.049)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.052)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.094)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.125)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.094)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.167)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.094)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.113)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.056)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.04)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.024)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.009)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.016)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.026)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.002)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp1"), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - thisStopDurationProbabilityDistribution.clear(); - - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.025)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.025)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.05)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.043)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.112)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.168)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.149)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.081)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.168)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.068)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.068)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.025)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.019)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp2"), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - thisStopDurationProbabilityDistribution.clear(); - - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.036)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.098)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.036)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.016)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.042)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.124)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.085)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.144)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.105)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.052)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.072)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.052)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.023)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.033)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.062)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.016)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(660, 780), 0.003)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp3"), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - thisStopDurationProbabilityDistribution.clear(); - - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.071)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.143)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.429)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.179)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.107)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.071)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp4"), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - thisStopDurationProbabilityDistribution.clear(); - - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.026)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.395)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.158)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.132)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.026)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.105)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.079)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.026)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.053)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp5"), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - thisStopDurationProbabilityDistribution.clear(); - - thisStopDurationProbabilityDistribution = new ArrayList<>(); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.014)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.033)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.064)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.109)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.088)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.095)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.112)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.105)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.114)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.053)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.088)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.038)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.012)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.01)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.051)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.02)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.027)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.061)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.045)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.068)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.083)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.112)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.114)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.146)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.058)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.114)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.036)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.022)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.007)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.065)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.009)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.04)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.074)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.09)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.086)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.069)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.113)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.135)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.071)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.008)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.044)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.041)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.03)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.021)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.075)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.036)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.055)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.018)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.236)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.073)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.018)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.164)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.091)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.109)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.055)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.018)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.055)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.055)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.014)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.163)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.21)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.165)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.125)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.095)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.101)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.04)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.03)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.024)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.006)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.008)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.002)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.004)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.008)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.072)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.093)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.123)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.113)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.137)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.081)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.102)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.087)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.079)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.032)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.021)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.018)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.016)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.009)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.014)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.062)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.14)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.093)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.115)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.133)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.102)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.098)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.071)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.067)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.038)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.027)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.011)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.009)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.024)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.051)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.214)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.146)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.129)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.10)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.072)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.083)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.063)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.054)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.02)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.016)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.022)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.008)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.007)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.011)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(10, 20), 0.163)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.224)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.153)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.061)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.173)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.082)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.122)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.01)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.003)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.195)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.225)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.16)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.143)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.089)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.075)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.031)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.048)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.01)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.003)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.007)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.057)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.108)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.093)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.133)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.133)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.11)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.102)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.064)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.104)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.049)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.015)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.015)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.003)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.005)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.006)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.084)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.119)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.183)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.076)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.085)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.101)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.124)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.069)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.057)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.041)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.002)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.025)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.011)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.007)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.007)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.004)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.103)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.23)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.193)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.08)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.065)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.071)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.072)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.044)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.054)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.035)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.009)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.013)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.014)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.01)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.003)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.094)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.179)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.094)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.245)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.123)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.075)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.094)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.038)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.019)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.009)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.009)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.066)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.063)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.142)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.165)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.135)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.102)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.122)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.033)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.086)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.043)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.023)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.017)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.159)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.173)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.173)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.088)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.115)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.071)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.024)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.051)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.041)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.02)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.031)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.024)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.017)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.007)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.292)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.135)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.062)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.197)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.051)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.079)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.022)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.045)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.056)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.034)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.006)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.092)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.111)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.224)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.173)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.09)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.103)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.045)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.028)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.056)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.017)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.019)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.025)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.006)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.007)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.146)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.098)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.146)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.195)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.268)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.012)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.024)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.024)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.024)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.037)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.012)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.026)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.042)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.062)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.121)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.133)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.144)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.144)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.104)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.121)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.046)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.011)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.026)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.007)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.005)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.061)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.093)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.101)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.125)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.125)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.101)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.124)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.08)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.093)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.046)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.013)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.017)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.011)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.004)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.081)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.101)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.101)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.109)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.124)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.065)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.109)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.124)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.097)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.032)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.022)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.017)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.003)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.007)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.052)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.114)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.155)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.111)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.151)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.112)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.125)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.043)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.051)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.026)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.014)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.016)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.011)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.007)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.009)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(20, 30), 0.02)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.082)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.102)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.449)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.061)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.163)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.102)); - thisStopDurationProbabilityDistribution.add(Pair.create(new 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 DurationsBounds(0, 10), 0.02)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.02)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.151)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.296)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.156)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.065)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.121)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.05)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.075)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.01)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.015)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.01)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.005)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.005)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp5"), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - thisStopDurationProbabilityDistribution.clear(); - - // because no data für private persons; use average numbers of all employee categories - thisStopDurationProbabilityDistribution = new ArrayList<>(); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.056)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.084)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.095)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.118)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.12)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.096)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.112)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.083)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.095)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.045)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.033)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.022)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.011)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.007)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.018)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.004)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp1"), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - thisStopDurationProbabilityDistribution.clear(); - - thisStopDurationProbabilityDistribution = new ArrayList<>(); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.077)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.093)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.103)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.092)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.098)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.091)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.108)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.092)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.095)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.043)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.035)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.024)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.01)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.011)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.021)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.007)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp2"), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - thisStopDurationProbabilityDistribution.clear(); - - thisStopDurationProbabilityDistribution = new ArrayList<>(); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.06)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.141)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.152)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.107)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.094)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.087)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.089)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.067)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.06)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.037)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.023)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.025)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.015)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.012)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.024)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.006)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(660, 780), 0.001)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp3"), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - thisStopDurationProbabilityDistribution.clear(); - - thisStopDurationProbabilityDistribution = new ArrayList<>(); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.062)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.11)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.12)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.144)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.151)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.129)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.062)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.079)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.041)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.031)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.019)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.014)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.007)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.014)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 540), 0.014)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(540, 660), 0.002)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp4"), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - thisStopDurationProbabilityDistribution.clear(); - - thisStopDurationProbabilityDistribution = new ArrayList<>(); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(0, 10), 0.024)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(10, 20), 0.099)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(20, 30), 0.147)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(30, 40), 0.17)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(40, 50), 0.133)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(50, 60), 0.108)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(60, 75), 0.116)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(75, 90), 0.058)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(90, 120), 0.075)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(120, 150), 0.03)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(150, 180), 0.01)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(180, 240), 0.014)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(240, 300), 0.005)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(300, 420), 0.004)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(420, 660), 0.007)); - thisStopDurationProbabilityDistribution.add(Pair.create(new DurationsBounds(660, 900), 0.002)); - stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp5"), - new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); - thisStopDurationProbabilityDistribution.clear(); - } - return stopDurationProbabilityDistribution; - } - - private record StopDurationGoodTrafficKey(String employeeCategory, String vehicleType) { + public record StopDurationGoodTrafficKey(String employeeCategory, String vehicleType) { @Override public boolean equals(Object obj) { @@ -2609,11 +1224,11 @@ public boolean equals(Object obj) { } else return vehicleType.equals(other.vehicleType); } } - private StopDurationGoodTrafficKey makeStopDurationGoodTrafficKey(String employeeCategory, String vehicleType) { + public static StopDurationGoodTrafficKey makeStopDurationGoodTrafficKey(String employeeCategory, String vehicleType) { return new StopDurationGoodTrafficKey(employeeCategory, vehicleType); } - private record TourStartAndDuration(int hourLower, int hourUpper, double minDuration, double maxDuration) {} + public record TourStartAndDuration(int hourLower, int hourUpper, double minDuration, double maxDuration) {} public record DurationsBounds(int minDuration, int maxDuration) {} diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/DefaultTourSpecificationsByUsingKID2002.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/DefaultTourSpecificationsByUsingKID2002.java new file mode 100644 index 00000000000..ec4bd9640ab --- /dev/null +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/DefaultTourSpecificationsByUsingKID2002.java @@ -0,0 +1,1390 @@ +package org.matsim.smallScaleCommercialTrafficGeneration.data; + +import org.apache.commons.math3.distribution.EnumeratedDistribution; +import org.apache.commons.math3.random.RandomGenerator; +import org.apache.commons.math3.util.Pair; +import org.matsim.smallScaleCommercialTrafficGeneration.GenerateSmallScaleCommercialTrafficDemand; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.matsim.smallScaleCommercialTrafficGeneration.GenerateSmallScaleCommercialTrafficDemand.makeStopDurationGoodTrafficKey; + +public class DefaultTourSpecificationsByUsingKID2002 implements GetCommercialTourSpecifications { + + @Override + public Map> createStopDurationDistributionPerCategory(String smallScaleCommercialTrafficType, RandomGenerator rng) { + Map> stopDurationProbabilityDistribution = new HashMap<>(); + + if (smallScaleCommercialTrafficType.equals(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { + List> thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 30), 0.098)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 60), 0.17)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 90), 0.127)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.11)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 180), 0.17)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.076)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.057)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 360), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(360, 420), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 480), 0.045)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(480, 540), 0.064)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 600), 0.034)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(600, 720), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(720, 840), 0.002)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector",null), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 30), 0.054)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 60), 0.164)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 90), 0.153)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.087)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 180), 0.12)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.055)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.044)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 360), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(360, 420), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 480), 0.069)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(480, 540), 0.132)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 600), 0.058)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(600, 720), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(720, 840), 0.002)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction",null), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 30), 0.13)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 60), 0.324)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 90), 0.178)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.108)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 180), 0.097)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.034)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 360), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(360, 420), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 480), 0.027)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(480, 540), 0.029)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 600), 0.008)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(600, 720), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(720, 840), 0.001)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest",null), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 30), 0.178)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 60), 0.301)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 90), 0.192)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.104)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 180), 0.092)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.043)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.013)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 360), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(360, 420), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 480), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(480, 540), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 600), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(600, 720), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(720, 840), 0.001)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail",null), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 30), 0.144)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 60), 0.372)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 90), 0.203)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.069)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 180), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.038)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 360), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(360, 420), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 480), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(480, 540), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 600), 0.005)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(600, 720), 0.005)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels",null), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 30), 0.196)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 60), 0.292)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 90), 0.19)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 180), 0.105)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.034)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 360), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(360, 420), 0.013)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 480), 0.019)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(480, 540), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 600), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(600, 720), 0.004)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(720, 840), 0.001)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest",null), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + + } else if (smallScaleCommercialTrafficType.equals(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString())) { + List> thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.038)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.049)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.052)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.125)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.167)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.113)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.056)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.04)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.002)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp1"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.05)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.043)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.168)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.149)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.081)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.168)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.068)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.068)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.019)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp2"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.036)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.098)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.036)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.042)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.124)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.085)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.144)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.105)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.052)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.072)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.052)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.023)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.033)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(660, 780), 0.003)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp3"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.071)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.143)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.429)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.179)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.107)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.071)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp4"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.395)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.158)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.132)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.105)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.079)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.053)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Primary Sector", "vehTyp5"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.033)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.064)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.109)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.088)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.095)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.105)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.114)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.053)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.088)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.038)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.051)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.015)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp1"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.027)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.061)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.045)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.068)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.083)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.114)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.146)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.058)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.114)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.036)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.022)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.065)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.023)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp2"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.04)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.074)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.09)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.086)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.069)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.113)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.135)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.071)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.008)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.044)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.041)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.03)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.021)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.075)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.022)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp3"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.036)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.055)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.236)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.073)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.164)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.091)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.109)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.055)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.055)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.055)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.018)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp4"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.163)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.21)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.165)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.125)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.095)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.04)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.03)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.008)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.002)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.004)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.008)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.004)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Construction", "vehTyp5"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.072)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.123)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.113)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.137)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.081)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.087)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.079)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.032)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.021)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 780), 0.002)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp1"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.14)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.115)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.133)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.098)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.071)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.067)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.038)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.027)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.011)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp2"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.051)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.214)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.146)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.129)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.10)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.072)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.083)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.063)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.054)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.022)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.008)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 900), 0.003)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp3"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.163)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.224)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.153)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.061)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.173)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.082)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.122)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.01)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp4"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.003)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.195)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.225)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.16)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.143)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.089)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.075)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.031)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.048)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.003)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 660), 0.009)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Secondary Sector Rest", "vehTyp5"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.057)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.108)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.133)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.133)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.11)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.064)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.104)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.049)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.015)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.015)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.003)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.005)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.003)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp1"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.084)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.119)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.183)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.076)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.085)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.124)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.069)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.057)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.041)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.002)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.004)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(780, 900), 0.002)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp2"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.103)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.23)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.193)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.08)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.065)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.071)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.072)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.044)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.054)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.035)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.013)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.003)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.003)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp3"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.179)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.245)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.123)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.075)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.038)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.019)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.019)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp4"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.066)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.063)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.142)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.165)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.135)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.122)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.033)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.086)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.043)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.023)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.003)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Retail", "vehTyp5"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.159)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.173)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.173)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.088)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.115)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.071)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.051)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.041)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.031)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.007)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp1"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.292)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.135)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.197)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.051)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.079)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.022)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.045)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.056)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.034)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.022)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp2"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.092)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.111)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.224)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.173)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.09)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.103)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.045)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.028)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.056)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.019)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.006)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp3"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.146)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.098)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.146)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.195)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.268)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.037)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.012)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp4"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.042)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.121)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.133)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.144)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.144)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.104)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.121)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.046)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.005)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 900), 0.008)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Traffic/Parcels", "vehTyp5"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.061)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.125)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.125)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.124)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.08)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.046)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.013)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.004)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.005)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp1"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.081)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.101)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.109)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.124)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.065)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.109)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.124)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.097)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.032)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.022)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.017)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.003)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.008)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp2"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.052)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.114)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.155)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.111)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.151)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.125)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.043)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.051)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.026)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.016)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.009)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(660, 780), 0.003)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp3"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.082)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.449)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.061)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.163)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.102)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.02)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp4"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.02)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.151)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.296)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.156)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.065)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.121)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.05)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.075)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.015)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.005)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.005)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Employee Tertiary Sector Rest", "vehTyp5"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + // because no data für private persons; use average numbers of all employee categories + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.056)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.084)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.095)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.118)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.12)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.096)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.112)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.083)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.095)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.045)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.033)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.022)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.018)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.004)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp1"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.077)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.093)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.103)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.092)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.098)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.091)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.108)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.092)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.095)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.043)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.035)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.011)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.021)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.007)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp2"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.06)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.141)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.152)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.107)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.094)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.087)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.089)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.067)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.06)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.037)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.023)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.025)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.015)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.012)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.006)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(660, 780), 0.001)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp3"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.11)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.12)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.144)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.151)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.129)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.062)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.079)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.041)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.031)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.019)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 540), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(540, 660), 0.002)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp4"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + + thisStopDurationProbabilityDistribution = new ArrayList<>(); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 10), 0.024)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 20), 0.099)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 30), 0.147)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(30, 40), 0.17)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(40, 50), 0.133)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(50, 60), 0.108)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(60, 75), 0.116)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(75, 90), 0.058)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(90, 120), 0.075)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(120, 150), 0.03)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(150, 180), 0.01)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(180, 240), 0.014)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(240, 300), 0.005)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(300, 420), 0.004)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(420, 660), 0.007)); + thisStopDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(660, 900), 0.002)); + stopDurationProbabilityDistribution.put(makeStopDurationGoodTrafficKey("Inhabitants", "vehTyp5"), + new EnumeratedDistribution<>(rng, thisStopDurationProbabilityDistribution)); + thisStopDurationProbabilityDistribution.clear(); + } + return stopDurationProbabilityDistribution; + } + + @Override + public EnumeratedDistribution createTourDistribution( + String smallScaleCommercialTrafficType, RandomGenerator rng) { + List> tourDurationProbabilityDistribution = new ArrayList<>(); + + if (smallScaleCommercialTrafficType.equals(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { + + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 0.0, 30.0), 0.0005917893035900173)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 30.0, 60.0), 0.00021859484237437887)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 90.0, 120.0), 0.00037490287407786324)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 120.0, 180.0), 0.0004337321926125666)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 180.0, 240.0), 0.0005834182239827621)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 240.0, 300.0), 0.0005116938323661723)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 300.0, 360.0), 0.0005027065159573272)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 360.0, 420.0), 0.0006719740164147071)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 420.0, 480.0), 0.00022375027665644004)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 480.0, 540.0), 0.00022103749529549306)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 540.0, 600.0), 0.00022119440831885122)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 600.0, 660.0), 0.0002732185104003396)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 660.0, 720.0), 7.287567629774946e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 720.0, 780.0), 0.0005090670761685264)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 780.0, 840.0), 0.0002169454122557984)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 840.0, 1080.0), 0.0016947794402011696)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 0.0, 30.0), 0.00033050926084770643)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 30.0, 60.0), 0.0004963985976117265)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 60.0, 90.0), 0.0009458837608304906)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 90.0, 120.0), 0.0006507941771038976)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 120.0, 180.0), 0.0002949035696660126)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 180.0, 240.0), 0.0005812406149568905)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 240.0, 300.0), 0.00072666224822023)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 300.0, 360.0), 0.0006017750128936798)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 360.0, 420.0), 0.0007696491628020603)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 420.0, 480.0), 0.0006951014583380694)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 480.0, 540.0), 0.0006675367479652174)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 540.0, 600.0), 0.0009951412624367468)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 600.0, 660.0), 0.0006193958232902363)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 660.0, 720.0), 0.0005496335422364244)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 720.0, 780.0), 0.000963763774344583)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 780.0, 840.0), 0.001585152586657775)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 840.0, 1080.0), 0.0022779973751500433)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 0.0, 30.0), 0.003678291745870938)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 30.0, 60.0), 0.0037749680865755936)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 60.0, 90.0), 0.0021464058981758467)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 90.0, 120.0), 0.0010105726369455444)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 120.0, 180.0), 0.0017166729332290624)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 180.0, 240.0), 0.001218657902054598)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 240.0, 300.0), 0.0019212859349972463)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 300.0, 360.0), 0.0018498349748915703)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 360.0, 420.0), 0.0020820722844894844)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 420.0, 480.0), 0.0033255032578691536)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 480.0, 540.0), 0.004499580798913233)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 540.0, 600.0), 0.004508722079694882)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 600.0, 660.0), 0.009460453046374911)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 660.0, 720.0), 0.008632039128635343)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 720.0, 780.0), 0.005173130409039029)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 780.0, 840.0), 0.0021287189901771954)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 840.0, 1080.0), 0.002735246591728173)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 0.0, 30.0), 0.015534599731489868)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 30.0, 60.0), 0.009424737666749776)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 60.0, 90.0), 0.003979757502241877)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 90.0, 120.0), 0.0026219034509082214)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 120.0, 180.0), 0.004373894821911171)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 180.0, 240.0), 0.005349695968407728)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 240.0, 300.0), 0.008398668008895199)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 300.0, 360.0), 0.013017576110359298)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 360.0, 420.0), 0.013178466937493282)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 420.0, 480.0), 0.015799261066253244)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 480.0, 540.0), 0.031932993774084484)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 540.0, 600.0), 0.056976770375347194)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 600.0, 660.0), 0.03411514635058722)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 660.0, 720.0), 0.010952547256934878)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 720.0, 780.0), 0.005071677294689363)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 780.0, 840.0), 0.002758017802376135)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 840.0, 1080.0), 0.003182481371327368)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 0.0, 30.0), 0.018010507239762663)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 30.0, 60.0), 0.009246211080247332)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 60.0, 90.0), 0.006297103845359016)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 90.0, 120.0), 0.003415561088528113)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 120.0, 180.0), 0.010918022744746231)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 180.0, 240.0), 0.011371721163141522)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 240.0, 300.0), 0.01861910064916215)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 300.0, 360.0), 0.015443374909900384)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 360.0, 420.0), 0.020470726990450452)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 420.0, 480.0), 0.030727618880727087)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 480.0, 540.0), 0.07364088624635841)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 540.0, 600.0), 0.04082061588575034)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 600.0, 660.0), 0.012935881167590665)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 660.0, 720.0), 0.005469250367916343)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 720.0, 780.0), 0.0030030673084490513)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 780.0, 840.0), 0.0011042643367551329)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 840.0, 1080.0), 0.0011327583672022575)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 0.0, 30.0), 0.015589932735904798)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 30.0, 60.0), 0.007157798082590814)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 60.0, 90.0), 0.006563655710107534)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 90.0, 120.0), 0.004888423230467872)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 120.0, 180.0), 0.01261126944262904)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 180.0, 240.0), 0.013275311108363174)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 240.0, 300.0), 0.011059737216827653)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 300.0, 360.0), 0.00980644443311104)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 360.0, 420.0), 0.013476523854959467)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 420.0, 480.0), 0.01766932338862498)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 480.0, 540.0), 0.013855266610087914)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 540.0, 600.0), 0.006090238569895901)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 600.0, 660.0), 0.00326688741194661)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 660.0, 720.0), 0.0009742217966822537)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 720.0, 780.0), 0.0008462163162537791)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 780.0, 840.0), 0.0009357453082055104)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 840.0, 1080.0), 0.0006867783494497427)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 0.0, 30.0), 0.011836581569331607)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 30.0, 60.0), 0.0060475163532472224)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 60.0, 90.0), 0.006091033719221284)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 90.0, 120.0), 0.004870323217391879)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 120.0, 180.0), 0.009852214102720915)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 180.0, 240.0), 0.006649077724867284)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 240.0, 300.0), 0.006549809619698136)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 300.0, 360.0), 0.00743649188225418)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 360.0, 420.0), 0.008370330719772223)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 420.0, 480.0), 0.006055410372169952)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 480.0, 540.0), 0.003221026290023441)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 540.0, 600.0), 0.00270804359225063)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 600.0, 660.0), 0.0011328763880567346)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 660.0, 720.0), 0.0005295062815147344)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 720.0, 780.0), 0.0005244739409173669)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 780.0, 840.0), 0.00022261373811852168)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 840.0, 1080.0), 0.0002976820307410009)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 0.0, 30.0), 0.0072347359578799255)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 30.0, 60.0), 0.005528762818372258)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 60.0, 90.0), 0.004301874597910846)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 90.0, 120.0), 0.002706271535768685)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 120.0, 180.0), 0.004461225555303183)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 180.0, 240.0), 0.003289266637558867)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 240.0, 300.0), 0.004773112389257731)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 300.0, 360.0), 0.004153307715767419)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 360.0, 420.0), 0.0023002274828502435)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 420.0, 480.0), 0.002295722460734858)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 480.0, 540.0), 0.0008008191218782178)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 540.0, 600.0), 0.0005302938593833011)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 600.0, 660.0), 0.00012017333498779025)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 660.0, 720.0), 0.00029497120761336085)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 720.0, 780.0), 7.442207741095891e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 780.0, 840.0), 7.491510042413546e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 0.0, 30.0), 0.005979044848708125)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 30.0, 60.0), 0.0030727725862362003)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 60.0, 90.0), 0.0018328582061095421)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 90.0, 120.0), 0.0015730248216810105)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 120.0, 180.0), 0.0025909176745678485)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 180.0, 240.0), 0.0023584284876344117)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 240.0, 300.0), 0.002888683132930499)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 300.0, 360.0), 0.0026723295114103734)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 360.0, 420.0), 0.001368034507711622)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 420.0, 480.0), 0.001322142609646873)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 480.0, 540.0), 0.00014896322977011863)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 540.0, 600.0), 0.00036793050573151096)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 600.0, 660.0), 0.0003024749417379503)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 660.0, 720.0), 7.263766179594998e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 720.0, 780.0), 7.737798495114381e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 840.0, 1080.0), 7.360037219024495e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 0.0, 30.0), 0.005442934607459622)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 30.0, 60.0), 0.0023099603288455053)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 60.0, 90.0), 0.0015476125810207045)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 90.0, 120.0), 0.0015690710859882222)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 120.0, 180.0), 0.003155552178314994)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 180.0, 240.0), 0.0024715148201473933)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 240.0, 300.0), 0.00214638868043489)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 300.0, 360.0), 0.0017134793037846727)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 360.0, 420.0), 0.0009684921868733149)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 420.0, 480.0), 0.0005519992558366529)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 480.0, 540.0), 0.0004441672064981391)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 540.0, 600.0), 0.00022332686365997108)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 600.0, 660.0), 0.00023780343565208111)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 660.0, 720.0), 0.00014898555439278127)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 0.0, 30.0), 0.0065652971880044205)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 30.0, 60.0), 0.0033645458423904226)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 60.0, 90.0), 0.002247264924524252)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 90.0, 120.0), 0.0021755851670695867)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 120.0, 180.0), 0.00292250684836152)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 180.0, 240.0), 0.0029939610328467135)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 240.0, 300.0), 0.0013771262994841458)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 300.0, 360.0), 0.0005929387919824101)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 360.0, 420.0), 0.0007299574379337656)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 420.0, 480.0), 0.00015161310680499916)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 480.0, 540.0), 0.00022326623210165028)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 540.0, 600.0), 0.00021908720500178134)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 0.0, 30.0), 0.004700575755513116)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 30.0, 60.0), 0.002876930233578738)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 60.0, 90.0), 0.0012326059557891803)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 90.0, 120.0), 0.001688513011030605)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 120.0, 180.0), 0.0024148215923521744)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 180.0, 240.0), 0.0009664823712470381)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 240.0, 300.0), 0.0008158516384741175)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 300.0, 360.0), 0.0005326476409500361)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 360.0, 420.0), 0.00037447250704764534)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 420.0, 480.0), 7.278074100962308e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 480.0, 540.0), 0.00015460621875651884)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 540.0, 600.0), 0.00022625636961834557)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 840.0, 1080.0), 7.369704340227916e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 0.0, 30.0), 0.005421542133242069)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 30.0, 60.0), 0.0028543297205245563)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 60.0, 90.0), 0.001320449445343739)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 90.0, 120.0), 0.0011372744623221703)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 120.0, 180.0), 0.0011175546229352943)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 180.0, 240.0), 0.0005212091408906178)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 240.0, 300.0), 0.00025063117439263165)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 300.0, 360.0), 0.0002906557976189996)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 360.0, 420.0), 6.934683987097806e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 420.0, 480.0), 7.198332684426051e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 0.0, 30.0), 0.005997678933359281)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 30.0, 60.0), 0.0014450238860978966)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 60.0, 90.0), 0.0008909835110546583)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 90.0, 120.0), 0.0008692603958852261)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 120.0, 180.0), 0.0004645626068627116)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 180.0, 240.0), 0.0005161866418057845)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 240.0, 300.0), 0.00047492492382272117)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 300.0, 360.0), 7.348989097075777e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 360.0, 420.0), 0.0003000342936128893)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 0.0, 30.0), 0.004621906661329853)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 30.0, 60.0), 0.0015152391398060199)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 60.0, 90.0), 0.0006769045119123614)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 90.0, 120.0), 0.00044820275277284946)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 120.0, 180.0), 0.0007140653752077821)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 180.0, 240.0), 0.0001502672132808765)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 240.0, 300.0), 0.0003842231300012746)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 300.0, 360.0), 0.00021634404805889257)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 0.0, 30.0), 0.0034023082743939916)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 30.0, 60.0), 0.0006251774232962365)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 60.0, 90.0), 0.00022163965781205308)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 90.0, 120.0), 7.360037219024495e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 120.0, 180.0), 0.00045934601255169126)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 180.0, 240.0), 7.511874968194916e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 240.0, 300.0), 0.0001486019187134722)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 300.0, 360.0), 7.505084488366769e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 420.0, 480.0), 7.594714627228585e-05)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 0.0, 30.0), 0.005137034953520923)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 30.0, 60.0), 0.0010774703023578233)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 60.0, 90.0), 0.00048539418673270443)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 90.0, 120.0), 0.0002988049182984063)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 120.0, 180.0), 0.00032644209078127245)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 180.0, 240.0), 0.0005357497395368892)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 240.0, 300.0), 0.0002944914928100358)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 300.0, 360.0), 0.00022851651374757815)); + } + else if (smallScaleCommercialTrafficType.equals(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString())) { + + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 0.0, 30.0), 0.0002666800577200411)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 30.0, 60.0), 0.0006395055678719748)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 60.0, 90.0), 0.0007110769046958423)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 90.0, 120.0), 0.0006665961628449491)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 120.0, 180.0), 0.0023195866923785575)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 180.0, 240.0), 0.00261751319938476)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 240.0, 300.0), 0.0021430032453503087)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 300.0, 360.0), 0.0029303876579925905)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 360.0, 420.0), 0.00283576618143643)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 420.0, 480.0), 0.0027188265347502893)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 480.0, 540.0), 0.002597768116531099)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 540.0, 600.0), 0.002659151494701916)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 600.0, 660.0), 0.0021738406044924437)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 660.0, 720.0), 0.0021949848461843176)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 720.0, 780.0), 0.0021801193011023083)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 780.0, 840.0), 0.001746033717539671)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(0, 4, 840.0, 1080.0), 0.00350888397405923)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 0.0, 30.0), 0.0006845643884312735)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 30.0, 60.0), 0.0004003126952082357)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 60.0, 90.0), 0.0008155012585632697)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 90.0, 120.0), 0.0010930534970200114)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 120.0, 180.0), 0.0011760353713952051)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 180.0, 240.0), 0.0019364061980548415)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 240.0, 300.0), 0.002953452881036028)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 300.0, 360.0), 0.002589370165068672)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 360.0, 420.0), 0.0025604405819583055)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 420.0, 480.0), 0.0034319041631081476)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 480.0, 540.0), 0.0033480025727905907)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 540.0, 600.0), 0.002175717502193024)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 600.0, 660.0), 0.0028036478238686957)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 660.0, 720.0), 0.0028759635193342887)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 720.0, 780.0), 0.0017584406503249872)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 780.0, 840.0), 0.0016742001219093045)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(4, 5, 840.0, 1080.0), 0.0020658205220468245)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 0.0, 30.0), 0.0017247403950228777)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 30.0, 60.0), 0.003090998236080484)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 60.0, 90.0), 0.0015209554995803177)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 90.0, 120.0), 0.0016533392810110293)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 120.0, 180.0), 0.003732306124403562)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 180.0, 240.0), 0.004106247357091271)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 240.0, 300.0), 0.003188442431357427)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 300.0, 360.0), 0.005929370570550301)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 360.0, 420.0), 0.005992695595693005)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 420.0, 480.0), 0.006390572360276255)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 480.0, 540.0), 0.00993732232424166)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 540.0, 600.0), 0.007917613781985494)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 600.0, 660.0), 0.00753055040114282)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 660.0, 720.0), 0.004839531706746983)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 720.0, 780.0), 0.003571294178536547)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 780.0, 840.0), 0.0022261075091276465)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(5, 6, 840.0, 1080.0), 0.0020123396391017526)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 0.0, 30.0), 0.00553085745500388)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 30.0, 60.0), 0.005164301035284355)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 60.0, 90.0), 0.0034287284279468384)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 90.0, 120.0), 0.003359657704287739)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 120.0, 180.0), 0.005963896679549981)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 180.0, 240.0), 0.006376396116305889)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 240.0, 300.0), 0.011553162434249647)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 300.0, 360.0), 0.01216390369869719)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 360.0, 420.0), 0.015303642980241483)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 420.0, 480.0), 0.01894502604909179)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 480.0, 540.0), 0.026995818384739457)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 540.0, 600.0), 0.03735238580259259)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 600.0, 660.0), 0.02007351137947408)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 660.0, 720.0), 0.007579189226621267)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 720.0, 780.0), 0.003806896198418994)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 780.0, 840.0), 0.0020371212990837376)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(6, 7, 840.0, 1080.0), 0.00246729057836831)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 0.0, 30.0), 0.007834929725170775)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 30.0, 60.0), 0.007875284751511802)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 60.0, 90.0), 0.0056369706407995695)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 90.0, 120.0), 0.007252792818630801)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 120.0, 180.0), 0.011595289158181222)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 180.0, 240.0), 0.01584695155572567)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 240.0, 300.0), 0.019385993489144607)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 300.0, 360.0), 0.01804569113072999)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 360.0, 420.0), 0.020338168968415053)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 420.0, 480.0), 0.03244941203821404)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 480.0, 540.0), 0.046986423884473)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 540.0, 600.0), 0.026127574804977814)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 600.0, 660.0), 0.006859707180170414)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 660.0, 720.0), 0.004053368732850601)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 720.0, 780.0), 0.0017728320836715625)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 780.0, 840.0), 0.0008117046283836942)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(7, 8, 840.0, 1080.0), 0.0014889766393137468)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 0.0, 30.0), 0.008702611915372131)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 30.0, 60.0), 0.009703391735884857)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 60.0, 90.0), 0.00833249802530372)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 90.0, 120.0), 0.008160824294542027)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 120.0, 180.0), 0.014522058792957903)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 180.0, 240.0), 0.019189639247661674)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 240.0, 300.0), 0.022628081955363144)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 300.0, 360.0), 0.018168175275565253)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 360.0, 420.0), 0.01830766579908246)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 420.0, 480.0), 0.022414786327228577)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 480.0, 540.0), 0.015454698179801149)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 540.0, 600.0), 0.00743339793333549)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 600.0, 660.0), 0.0028959167218627997)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 660.0, 720.0), 0.0011608823477359163)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 720.0, 780.0), 0.0006126324367099846)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 780.0, 840.0), 0.0007090395380022889)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(8, 9, 840.0, 1080.0), 0.0009650931773638335)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 0.0, 30.0), 0.010532384705529854)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 30.0, 60.0), 0.010106787618396446)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 60.0, 90.0), 0.007305519187631069)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 90.0, 120.0), 0.0065298278976416635)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 120.0, 180.0), 0.012991661099288086)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 180.0, 240.0), 0.011082392048301831)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 240.0, 300.0), 0.013735041027849332)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 300.0, 360.0), 0.012921165569106639)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 360.0, 420.0), 0.010187951930469277)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 420.0, 480.0), 0.0070071162811467125)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 480.0, 540.0), 0.003478434072337058)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 540.0, 600.0), 0.002487434148850001)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 600.0, 660.0), 0.0007617139935295275)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 660.0, 720.0), 0.0004794259473854554)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 720.0, 780.0), 0.00011828408353297643)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(9, 10, 780.0, 840.0), 0.0009221448817170415)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 0.0, 30.0), 0.0053803765038808364)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 30.0, 60.0), 0.00748440387556175)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 60.0, 90.0), 0.003817044622559703)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 90.0, 120.0), 0.0042559767658946045)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 120.0, 180.0), 0.004633517730561146)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 180.0, 240.0), 0.0040156278424527785)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 240.0, 300.0), 0.004097425621422603)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 300.0, 360.0), 0.00534407493573042)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 360.0, 420.0), 0.002849425985304954)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 420.0, 480.0), 0.0024443772372422234)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 480.0, 540.0), 0.0011258612568464076)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 540.0, 600.0), 0.0005966047093584399)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 600.0, 660.0), 0.0005779388889435179)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 660.0, 720.0), 0.0004527621290439082)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 720.0, 780.0), 0.00011727646428602624)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(10, 11, 780.0, 840.0), 0.00011130198744577025)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 0.0, 30.0), 0.0025301846046864363)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 30.0, 60.0), 0.002932856090944951)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 60.0, 90.0), 0.0015297442159744696)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 90.0, 120.0), 0.0016816440829740813)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 120.0, 180.0), 0.0023140070407952395)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 180.0, 240.0), 0.0013768767086426792)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 240.0, 300.0), 0.0019019317686819275)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 300.0, 360.0), 0.0015577691125463963)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 360.0, 420.0), 0.001499121306916632)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 420.0, 480.0), 0.0007361366421130972)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 480.0, 540.0), 0.0007423049940853575)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 540.0, 600.0), 0.00011130198744577025)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 660.0, 720.0), 0.00024243947114654707)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(11, 12, 720.0, 780.0), 0.000261579996858755)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 0.0, 30.0), 0.0021669594044717543)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 30.0, 60.0), 0.0033993161916113994)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 60.0, 90.0), 0.001870484877697732)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 90.0, 120.0), 0.0008448185262884799)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 120.0, 180.0), 0.002024573233571085)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 180.0, 240.0), 0.0021888099857994042)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 240.0, 300.0), 0.0021657834323017752)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 300.0, 360.0), 0.0010623089332746248)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 360.0, 420.0), 0.0006268095760401356)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 420.0, 480.0), 0.0005094532977538987)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 480.0, 540.0), 0.0004744090926784203)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 540.0, 600.0), 0.00016487328572417658)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(12, 13, 660.0, 720.0), 0.0001162996982120756)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 0.0, 30.0), 0.0033401411497772818)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 30.0, 60.0), 0.002492685695459365)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 60.0, 90.0), 0.0027064477589805068)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 90.0, 120.0), 0.0018052297053924354)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 120.0, 180.0), 0.0027984509294891498)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 180.0, 240.0), 0.0022758505657711914)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 240.0, 300.0), 0.0003535503655144059)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 300.0, 360.0), 0.0005890430396050117)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 360.0, 420.0), 0.0002319134363595028)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 420.0, 480.0), 0.00011617748025141993)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 480.0, 540.0), 0.0003690064941818713)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 540.0, 600.0), 0.0001650495071007077)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 600.0, 660.0), 0.00023113252306835525)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(13, 14, 840.0, 1080.0), 0.00017239206443126303)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 0.0, 30.0), 0.003543871129770451)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 30.0, 60.0), 0.0018407982276338393)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 60.0, 90.0), 0.0010649270862293423)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 90.0, 120.0), 0.0009538696044712171)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 120.0, 180.0), 0.0021318639289119572)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 180.0, 240.0), 0.0019740243143620277)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 240.0, 300.0), 0.0006157677659961421)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 300.0, 360.0), 0.0004035374922773149)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 360.0, 420.0), 0.00011607019237524387)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 420.0, 480.0), 0.0003938282727195195)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 480.0, 540.0), 0.00011130198744577025)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(14, 15, 600.0, 660.0), 0.00011942109323430472)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 0.0, 30.0), 0.00254340964132742)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 30.0, 60.0), 0.0017847751078888892)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 60.0, 90.0), 0.000841891386995212)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 90.0, 120.0), 0.0003543852337006742)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 120.0, 180.0), 0.0013974221085794884)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 180.0, 240.0), 0.0006229273683665316)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 240.0, 300.0), 0.00020579571489011056)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 300.0, 360.0), 0.0004809214516599411)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 360.0, 420.0), 0.00022514291890117063)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 420.0, 480.0), 0.00014748146383900364)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(15, 16, 720.0, 780.0), 0.00011605559293173729)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 0.0, 30.0), 0.0019634787835054656)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 30.0, 60.0), 0.000860670737476427)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 60.0, 90.0), 0.0003550148096943092)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 90.0, 120.0), 0.000855728546868917)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 120.0, 180.0), 0.0009283998993093458)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 180.0, 240.0), 0.00022795178106384156)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 240.0, 300.0), 0.00024119874825349313)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 420.0, 480.0), 0.00023429279224671318)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 480.0, 540.0), 0.00011727269965059726)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(16, 17, 660.0, 720.0), 0.00011130198744577025)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 0.0, 30.0), 0.0017099830161073832)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 30.0, 60.0), 0.0006015092064895483)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 60.0, 90.0), 0.00011819436012345105)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 90.0, 120.0), 0.0002279569151752547)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 120.0, 180.0), 0.0006440525787748041)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 180.0, 240.0), 0.0003142746964600832)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 300.0, 360.0), 0.00022788575876606104)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 360.0, 420.0), 0.0004761806298753505)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(17, 18, 480.0, 540.0), 0.00011727269965059726)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 0.0, 30.0), 0.0020011795184968267)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 30.0, 60.0), 0.00023620950461199452)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 60.0, 90.0), 0.00011935825257957617)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 90.0, 120.0), 0.00011130198744577025)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 120.0, 180.0), 0.00012222981614916706)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 180.0, 240.0), 0.0002377005397786721)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 240.0, 300.0), 0.00026373526728965034)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 300.0, 360.0), 0.000256086036315955)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(18, 19, 360.0, 420.0), 0.00011394287938236544)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 0.0, 30.0), 0.0021116872169622083)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 30.0, 60.0), 0.0003681765715703113)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 60.0, 90.0), 0.0004137833254678062)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 90.0, 120.0), 0.00025108497234833097)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 120.0, 180.0), 0.0007576827338029722)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 180.0, 240.0), 0.0005180490039062906)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 240.0, 300.0), 0.0004944106124208977)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.TourStartAndDuration(19, 24, 300.0, 360.0), 0.0002278857587658224)); + } else + throw new IllegalArgumentException("Unknown small scale commercial traffic type: " + smallScaleCommercialTrafficType); + + return new EnumeratedDistribution<>(rng, tourDurationProbabilityDistribution); + } + + @Override + public EnumeratedDistribution createTourStartTimeDistribution( + String smallScaleCommercialTrafficType, RandomGenerator rng) { + List> tourStartProbabilityDistribution = new ArrayList<>(); + if (smallScaleCommercialTrafficType.equals(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 1), 0.002)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(1, 2), 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(2, 3), 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(3, 4), 0.002)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(4, 5), 0.008)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(5, 6), 0.031)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(6, 7), 0.144)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(7, 8), 0.335)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(8, 9), 0.182)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(9, 10), 0.108)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 11), 0.057)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(11, 12), 0.032)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(12, 13), 0.021)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(13, 14), 0.021)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(14, 15), 0.019)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(15, 16), 0.012)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(16, 17), 0.009)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(17, 18), 0.006)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(18, 19), 0.004)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(19, 20), 0.003)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 21), 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(22, 23), 0.001)); + } else if (smallScaleCommercialTrafficType.equals(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString())) { + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 1), 0.008)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(1, 2), 0.003)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(2, 3), 0.008)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(3, 4), 0.012)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(4, 5), 0.028)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(5, 6), 0.052)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(6, 7), 0.115)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(7, 8), 0.222)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(8, 9), 0.197)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(9, 10), 0.14)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 11), 0.076)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(11, 12), 0.035)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(12, 13), 0.022)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(13, 14), 0.022)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(14, 15), 0.021)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(15, 16), 0.014)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(16, 17), 0.008)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(17, 18), 0.005)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(18, 19), 0.004)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(19, 20), 0.002)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(20, 21), 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(21, 22), 0.001)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(22, 23), 0.002)); + tourStartProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(23, 24), 0.001)); + } + return new EnumeratedDistribution<>(rng, tourStartProbabilityDistribution); + } + + @Override + public EnumeratedDistribution createTourDurationTimeDistribution( + String smallScaleCommercialTrafficType, RandomGenerator rng) { + List> tourDurationProbabilityDistribution = new ArrayList<>(); + if (smallScaleCommercialTrafficType.equals(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.commercialPersonTraffic.toString())) { + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 1), 0.14)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(1, 2), 0.066)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(2, 3), 0.056)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(3, 4), 0.052)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(4, 5), 0.061)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(5, 6), 0.063)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(6, 7), 0.07)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(7, 8), 0.086)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(8, 9), 0.14)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(9, 10), 0.122)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 11), 0.068)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(11, 12), 0.031)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(12, 13), 0.018)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(13, 14), 0.01)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(14, 15), 0.006)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(15, 16), 0.003)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(16, 17), 0.002)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(17, 18), 0.001)); + } else if (smallScaleCommercialTrafficType.equals(GenerateSmallScaleCommercialTrafficDemand.SmallScaleCommercialTrafficType.goodsTraffic.toString())) { + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(0, 1), 0.096)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(1, 2), 0.074)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(2, 3), 0.065)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(3, 4), 0.071)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(4, 5), 0.086)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(5, 6), 0.084)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(6, 7), 0.084)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(7, 8), 0.101)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(8, 9), 0.118)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(9, 10), 0.092)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(10, 11), 0.048)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(11, 12), 0.027)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(12, 13), 0.015)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(13, 14), 0.011)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(14, 15), 0.006)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(15, 16), 0.004)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(16, 17), 0.002)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(17, 18), 0.001)); + tourDurationProbabilityDistribution.add(Pair.create(new GenerateSmallScaleCommercialTrafficDemand.DurationsBounds(18, 19), 0.001)); + } + return new EnumeratedDistribution<>(rng, tourDurationProbabilityDistribution); + } +} diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/GetCommercialTourSpecifications.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/GetCommercialTourSpecifications.java new file mode 100644 index 00000000000..ce6bce3c04c --- /dev/null +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/data/GetCommercialTourSpecifications.java @@ -0,0 +1,47 @@ +package org.matsim.smallScaleCommercialTrafficGeneration.data; + +import org.apache.commons.math3.distribution.EnumeratedDistribution; +import org.apache.commons.math3.random.RandomGenerator; +import org.matsim.smallScaleCommercialTrafficGeneration.GenerateSmallScaleCommercialTrafficDemand; + +import java.util.Map; + +public interface GetCommercialTourSpecifications { + + /** + * Creates the probability distribution for the duration of the services. + * The values are given in [min] and have an upperBound. + * + * @param smallScaleCommercialTrafficType the type of small scale commercial traffic + * @return the probability distribution for the duration of the services + */ + Map> createStopDurationDistributionPerCategory( + String smallScaleCommercialTrafficType, RandomGenerator rng); + + /** + * Creates the distribution of the tour start and the related duration. + * + * @param smallScaleCommercialTrafficType the type of the small scale commercial traffic + * @return the distribution of the tour start and the related duration + */ + EnumeratedDistribution createTourDistribution(String smallScaleCommercialTrafficType, RandomGenerator rng); + + /** + * Creates the probability distribution for the tour start times for the day. + * The values are given in [h] and have an upperBound. + * + * @return the probability distribution for the tour start times + */ + + @Deprecated //use createTourDistribution(String smallScaleCommercialTrafficType) instead + EnumeratedDistribution createTourStartTimeDistribution(String smallScaleCommercialTrafficType, RandomGenerator rng); + + /** + * Creates the probability distribution for the tour duration for the day. + * The values are given in [h] and have an upperBound. + * + * @return the probability distribution for the tour duration + */ + @Deprecated //use createTourDistribution(String smallScaleCommercialTrafficType) instead + EnumeratedDistribution createTourDurationTimeDistribution(String smallScaleCommercialTrafficType, RandomGenerator rng); +} From 53c8f12b14c1886dc8250549e63e4078c31e46b2 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Tue, 27 Aug 2024 13:35:30 +0200 Subject: [PATCH 086/111] add comment --- .../GenerateSmallScaleCommercialTrafficDemand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 64a271d14d8..6bb95d1d18a 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 @@ -576,7 +576,7 @@ private void createCarriers(Scenario scenario, TripDistributionMatrix odMatrix, CarrierVehicleTypes carrierVehicleTypes = CarriersUtils.getCarrierVehicleTypes(scenario); Map, VehicleType> additionalCarrierVehicleTypes = scenario.getVehicles().getVehicleTypes(); - // Only vehicle with cost information will work properly + // Only a vehicle with cost information will work properly additionalCarrierVehicleTypes.values().stream() .filter(vehicleType -> vehicleType.getCostInformation().getCostsPerSecond() != null) .forEach(vehicleType -> carrierVehicleTypes.getVehicleTypes().putIfAbsent(vehicleType.getId(), vehicleType)); @@ -602,6 +602,7 @@ private void createCarriers(Scenario scenario, TripDistributionMatrix odMatrix, } } } + //TODO make vehcile selection configurable if (isStartingLocation) { double occupancyRate = 0; String[] possibleVehicleTypes = null; From 7c47024b3e1c22be99ffed5c8f290479029fb455 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Tue, 27 Aug 2024 13:37:56 +0200 Subject: [PATCH 087/111] fix import --- .../GenerateSmallScaleCommercialTrafficDemand.java | 1 - 1 file changed, 1 deletion(-) 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 6bb95d1d18a..af8fbacf479 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/GenerateSmallScaleCommercialTrafficDemand.java @@ -25,7 +25,6 @@ import org.apache.commons.math3.distribution.EnumeratedDistribution; import org.apache.commons.math3.random.MersenneTwister; import org.apache.commons.math3.random.RandomGenerator; -import org.apache.commons.math3.util.Pair; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; From f9da7597cf2463aeb98e545a5f6093b0e27d8956 Mon Sep 17 00:00:00 2001 From: vsp-gleich Date: Tue, 27 Aug 2024 17:59:43 +0200 Subject: [PATCH 088/111] Pt fares extended tests, check distance classes have distinct max distances (#3428) * rename and extend test for ChainedPtFareHandlerTest * hopefully more efficient distance to distance class fare params lookup * ensure distinct max distances in distance class fare params, set default minFare to 0 --- .../fare/DistanceBasedPtFareCalculator.java | 13 ++-- .../pt/fare/DistanceBasedPtFareParams.java | 21 ++++++- .../vsp/pt/fare/PtFareUpperBoundHandler.java | 2 +- ...est.java => ChainedPtFareHandlerTest.java} | 58 +++++++++++++++--- .../DistanceBasedPtFareCalculatorTest.java | 54 ++++++++++++++++ .../pt-area_Kelheim-BadAbbach.cpg | 1 + .../pt-area_Kelheim-BadAbbach.dbf | Bin 0 -> 330 bytes .../pt-area_Kelheim-BadAbbach.prj | 1 + .../pt-area_Kelheim-BadAbbach.shp | Bin 0 -> 364 bytes .../pt-area_Kelheim-BadAbbach.shx | Bin 0 -> 108 bytes 10 files changed, 132 insertions(+), 18 deletions(-) rename contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/{FareZoneBasedPtFareHandlerTest.java => ChainedPtFareHandlerTest.java} (65%) create mode 100644 examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.cpg create mode 100644 examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.dbf create mode 100644 examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.prj create mode 100644 examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.shp create mode 100644 examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.shx diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculator.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculator.java index 74c1d13b9b5..50ef21d6ff2 100644 --- a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculator.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculator.java @@ -68,12 +68,13 @@ private boolean inShape(Coord coord) { public static double computeFare(double distance, double minFare, SortedMap distanceClassFareParams) { - for (DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClassFareParam : distanceClassFareParams.values()) { - if (distance <= distanceClassFareParam.getMaxDistance()) { - return Math.max(minFare, distance * distanceClassFareParam.getFareSlope() + distanceClassFareParam.getFareIntercept()); - } + try { + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClassFareParam = distanceClassFareParams.tailMap(distance).firstEntry().getValue(); + return Math.max(minFare, distance * distanceClassFareParam.getFareSlope() + distanceClassFareParam.getFareIntercept()); + } catch (IllegalArgumentException e) { + log.error("No fare found for distance of " + distance + " meters."); + log.error(e.getMessage()); + throw new RuntimeException("No fare found for distance of " + distance + " meters."); } - log.error("No fare found for distance of " + distance + " meters."); - throw new RuntimeException("No fare found for distance of " + distance + " meters."); } } diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java index 1cabc347839..86780a92cec 100644 --- a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java @@ -2,6 +2,9 @@ import jakarta.validation.constraints.PositiveOrZero; import org.apache.commons.math.stat.regression.SimpleRegression; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.core.config.Config; import org.matsim.core.config.ConfigGroup; import org.matsim.core.config.ReflectiveConfigGroup; @@ -19,8 +22,10 @@ public class DistanceBasedPtFareParams extends PtFareParams { public static final String SET_TYPE = "ptFareCalculationDistanceBased"; public static final String MIN_FARE = "minFare"; + private static final Logger log = LogManager.getLogger(DistanceBasedPtFareParams.class); + @PositiveOrZero - private double minFare = 2.0; + private double minFare = 0.0; public DistanceBasedPtFareParams() { super(SET_TYPE); @@ -129,6 +134,12 @@ public ConfigGroup createParameterSet(final String type) { } } + @Override + protected final void checkConsistency(final Config config) { + super.checkConsistency(config); + getDistanceClassFareParams(); + } + public SortedMap getDistanceClassFareParams() { @SuppressWarnings("unchecked") final Collection distanceClassFareParams = @@ -139,6 +150,11 @@ public SortedMap getDistanceClass if (this.isLocked()) { pars.setLocked(); } + if (map.containsKey(pars.getMaxDistance())) { + log.error("Multiple " + DistanceClassLinearFareFunctionParams.class + + " with same max distance in same DistanceBasedPtFareParams. Max distance must be unique."); + throw new RuntimeException("Multiple " + DistanceClassLinearFareFunctionParams.class); + } map.put(pars.getMaxDistance(), pars); } if (this.isLocked()) { @@ -215,7 +231,8 @@ public Map getComments() { map.put(FARE_INTERCEPT, "Linear function fare = slope * distance + intercept: the value of the intercept in currency units."); map.put(MAX_DISTANCE, "The given linear function is applied to trips up to this distance threshold in meters. If set to a finite value" + ", the linear function for the next distance class will be tried out. If no fare is defined with " + MAX_DISTANCE + " greater than" + - "pt trip length, an error is thrown."); + "pt trip length, an error is thrown. If multiple distance classes have the same max distance it is unclear which applies, therefore " + + "an error is thrown."); return map; } } diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareUpperBoundHandler.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareUpperBoundHandler.java index 5d05602df2d..8d9accc9759 100644 --- a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareUpperBoundHandler.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareUpperBoundHandler.java @@ -61,7 +61,7 @@ public void notifyAfterMobsim(AfterMobsimEvent event) { // Issue refund to person events.processEvent( new PersonMoneyEvent(getOrCalcCompensationTime(), personId, refund, - PT_REFUND, TransportMode.pt, "Refund for person" + personId.toString())); + PT_REFUND, TransportMode.pt, "Refund for person " + personId.toString())); } } } diff --git a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareHandlerTest.java similarity index 65% rename from contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java rename to contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareHandlerTest.java index ab65679c2d2..5fb7ea83355 100644 --- a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareHandlerTest.java +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/ChainedPtFareHandlerTest.java @@ -26,7 +26,7 @@ import java.util.ArrayList; import java.util.List; -public class FareZoneBasedPtFareHandlerTest { +public class ChainedPtFareHandlerTest { private final static String FARE_ZONE_TRANSACTION_PARTNER = "fare zone transaction partner"; private final static String DISTANCE_BASED_TRANSACTION_PARTNER = "distance based transaction partner"; @@ -35,7 +35,7 @@ public class FareZoneBasedPtFareHandlerTest { private MatsimTestUtils utils = new MatsimTestUtils(); @Test - void testFareZoneBasedPtFareHandler() { + void testChainedPtFareHandler() { //Prepare Config config = getConfig(); @@ -44,20 +44,37 @@ void testFareZoneBasedPtFareHandler() { FareZoneBasedPtFareParams fareZoneBased = new FareZoneBasedPtFareParams(); fareZoneBased.setDescription("simple fare zone based"); + // smallest area (Kelheim and villages) fareZoneBased.setFareZoneShp(IOUtils.extendUrl(config.getContext(), "ptTestArea/pt-area.shp").toString()); fareZoneBased.setOrder(1); fareZoneBased.setTransactionPartner(FARE_ZONE_TRANSACTION_PARTNER); DistanceBasedPtFareParams distanceBased = new DistanceBasedPtFareParams(); DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClassFareParams = - distanceBased.getOrCreateDistanceClassFareParams(999_999_999.); + distanceBased.getOrCreateDistanceClassFareParams(Double.POSITIVE_INFINITY); distanceClassFareParams.setFareSlope(0.00017); distanceClassFareParams.setFareIntercept(1.6); distanceBased.setOrder(2); distanceBased.setTransactionPartner(DISTANCE_BASED_TRANSACTION_PARTNER); + // larger area Kelheim - Regensburg + distanceBased.setFareZoneShp(IOUtils.extendUrl(config.getContext(), "pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.shp").toString()); + distanceBased.setMinFare(2.0); + + // second DistanceBasedPtFareParams, e.g. applicable in a different shape file + DistanceBasedPtFareParams distanceBased2 = new DistanceBasedPtFareParams(); + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClassFareParams2 = + distanceBased2.getOrCreateDistanceClassFareParams(Double.POSITIVE_INFINITY); + distanceClassFareParams2.setFareSlope(0.0003); + distanceClassFareParams2.setFareIntercept(2.0); + distanceBased2.setOrder(3); + distanceBased2.setTransactionPartner(DISTANCE_BASED_TRANSACTION_PARTNER); + distanceBased2.setMinFare(7.0); ptFareConfigGroup.addParameterSet(fareZoneBased); ptFareConfigGroup.addParameterSet(distanceBased); + ptFareConfigGroup.addParameterSet(distanceBased2); + + ptFareConfigGroup.setUpperBoundFactor(2.0); // write config to file and read in again to check config reading and writing ConfigUtils.writeConfig(config, utils.getOutputDirectory() + "configFromCode.xml"); @@ -83,7 +100,8 @@ public void install() { //Check List events = fareAnalysis.getEvents(); - Assertions.assertEquals(2, events.size()); + // 1 event per leg plus 1 event fare capping at upper bound factor + Assertions.assertEquals(5, events.size()); final String FARE_TEST_PERSON = "fareTestPerson"; @@ -91,9 +109,21 @@ public void install() { Assertions.assertEquals(new PersonMoneyEvent(33264, Id.createPersonId(FARE_TEST_PERSON), -1.5, "pt fare", FARE_ZONE_TRANSACTION_PARTNER, FARE_TEST_PERSON), events.get(0)); - //second event is the distance based event - Assertions.assertEquals(new PersonMoneyEvent(52056, Id.createPersonId(FARE_TEST_PERSON), -4.526183060514956, "pt fare", + //second event is the distance based fare of the first DistanceBasedPtFareParams (in area.shp) + Assertions.assertEquals(new PersonMoneyEvent(51062, Id.createPersonId(FARE_TEST_PERSON), -2.788776056323089, "pt fare", DISTANCE_BASED_TRANSACTION_PARTNER, FARE_TEST_PERSON), events.get(1)); + + //third event is the distance based fare of the second DistanceBasedPtFareParams (outside area.shp), ca. 5.069 < min fare 7.0 + Assertions.assertEquals(new PersonMoneyEvent(61622, Id.createPersonId(FARE_TEST_PERSON), -7.0, "pt fare", + DISTANCE_BASED_TRANSACTION_PARTNER, FARE_TEST_PERSON), events.get(2)); + + //fourth event is the distance based fare of the second DistanceBasedPtFareParams (outside area.shp) + Assertions.assertEquals(new PersonMoneyEvent(70354, Id.createPersonId(FARE_TEST_PERSON), -7.961415135189197, "pt fare", + DISTANCE_BASED_TRANSACTION_PARTNER, FARE_TEST_PERSON), events.get(3)); + + //fifth event is the upper bound fare capping compensation + Assertions.assertEquals(new PersonMoneyEvent(129600, Id.createPersonId(FARE_TEST_PERSON), 3.3273609211338915, "pt fare refund", + "pt", "Refund for person fareTestPerson"), events.get(4)); } private @NotNull MutableScenario setUpScenario(Config config) { @@ -106,12 +136,18 @@ public void install() { Plan plan = fac.createPlan(); Activity home = fac.createActivityFromCoord("home", new Coord(710300.624, 5422165.737)); -// bus to Saal (Donau) work location departs at 09:14 + // bus to Saal (Donau) work location departs at 09:14 home.setEndTime(9 * 3600.); Activity work = fac.createActivityFromCoord("work", new Coord(714940.65, 5420707.78)); -// rb17 to regensburg 2nd home location departs at 13:59 + // rb17 to Gundelshausen 2nd work location departs at 13:59 (in distance fare 1 zone, 6992.797m) work.setEndTime(13 * 3600. + 45 * 60); - Activity home2 = fac.createActivityFromCoord("home", new Coord(726634.40, 5433508.07)); + Activity work2 = fac.createActivityFromCoord("work", new Coord(719916.02, 5425676.91)); + // rb17 to Regensburg 2nd home location departs at 16:52 (beyond distance fare 1 zone, distance fare 2 applies, 10230.93m) + work2.setEndTime(16 * 3600. + 40 * 60); + Activity work3 = fac.createActivityFromCoord("work", new Coord(726645.48, 5433383.16)); + // rb17 to Kelheim home location departs at 18:46, then transfer to bus 6022 (beyond distance fare 1 zone, distance fare 2 applies, 19871.38m) + work3.setEndTime(18 * 3600. + 40 * 60); + Activity home2 = fac.createActivityFromCoord("home", new Coord(710300.624, 5422165.737)); Leg leg = fac.createLeg(TransportMode.pt); @@ -119,6 +155,10 @@ public void install() { plan.addLeg(leg); plan.addActivity(work); plan.addLeg(leg); + plan.addActivity(work2); + plan.addLeg(leg); + plan.addActivity(work3); + plan.addLeg(leg); plan.addActivity(home2); person.addPlan(plan); diff --git a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java index 5a62cff6375..fcb72cedf27 100644 --- a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java @@ -76,4 +76,58 @@ private DistanceBasedPtFareCalculator getCalculator(String shapeFile) { params.setFareZoneShp(shapeFile); return new DistanceBasedPtFareCalculator(params); } + + @Test + void testModifyParams() { + var params = new DistanceBasedPtFareParams(); + params.setTransactionPartner(TRANSACTION_PARTNER); + + //2000m+: 3EUR + 0.5EUR/km + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClassLongFareParams = + params.getOrCreateDistanceClassFareParams(Double.POSITIVE_INFINITY); + distanceClassLongFareParams.setFareIntercept(3.0); + distanceClassLongFareParams.setFareSlope(0.0005); + + //0-2000m: 1EUR + 1EUR/km + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClass2kmFareParams = + params.getOrCreateDistanceClassFareParams(2000.0); + distanceClass2kmFareParams.setFareIntercept(1.0); + distanceClass2kmFareParams.setFareSlope(0.001); + + // get params for max distance 2km and modify + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClass2kmDuplicateFareParams = + params.getOrCreateDistanceClassFareParams(2000.0); + distanceClass2kmDuplicateFareParams.setFareIntercept(2.0); + distanceClass2kmDuplicateFareParams.setFareSlope(0.002); + + params.setMinFare(1.0); + + DistanceBasedPtFareCalculator distanceBasedPtFareCalculator = new DistanceBasedPtFareCalculator(params); + PtFareCalculator.FareResult fareResult = distanceBasedPtFareCalculator.calculateFare(new Coord(0, 0), new Coord(0, 100)).orElseThrow(); + Assertions.assertEquals(new PtFareCalculator.FareResult(2.2, TRANSACTION_PARTNER), fareResult); + } + + @Test + void testMultipleParamsWithSameMaxDistance() { + var params = new DistanceBasedPtFareParams(); + params.setTransactionPartner(TRANSACTION_PARTNER); + //0-2000m: 1EUR + 1EUR/km + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClass2kmFareParams = + params.getOrCreateDistanceClassFareParams(2000.0); + distanceClass2kmFareParams.setFareIntercept(1.0); + distanceClass2kmFareParams.setFareSlope(0.001); + + // add second distance class with same max distance + DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams distanceClass2kmDuplicateFareParams = + new DistanceBasedPtFareParams.DistanceClassLinearFareFunctionParams(); + distanceClass2kmDuplicateFareParams.setMaxDistance(2000.0); + distanceClass2kmDuplicateFareParams.setFareIntercept(2.0); + distanceClass2kmDuplicateFareParams.setFareSlope(0.002); + // add in a different way so no automatic overwrite + params.addParameterSet(distanceClass2kmDuplicateFareParams); + + Assertions.assertThrows(RuntimeException.class, () -> new DistanceBasedPtFareCalculator(params), + "DistanceBasedPtFareCalculator should crash if multiple DistanceClassLinearFareFunctionParams with the same max distance " + + " are present, because it is unclear which of them should be applied at that distance."); + } } diff --git a/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.cpg b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.cpg new file mode 100644 index 00000000000..3ad133c048f --- /dev/null +++ b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.cpg @@ -0,0 +1 @@ +UTF-8 \ No newline at end of file diff --git a/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.dbf b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.dbf new file mode 100644 index 0000000000000000000000000000000000000000..3193e4ca986ec5aeec9ea994c9db5f208e8b9b9b GIT binary patch literal 330 zcmZRs;gDuzU|=}N&;cYdL1qeE%n!ukf^#7ZKSy6zsE{*=4uEoClw**qBa{u+FToF! zfzY}6DXCBquzqy&(-Mnd@?ibk%&7W#72v?oB`8GKzaX_Ju_QA;PuH<1H4!dH7DEdM QNGU2oG0#xX)WARr0C(jf)Bpeg literal 0 HcmV?d00001 diff --git a/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.prj b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.prj new file mode 100644 index 00000000000..bd846aeb220 --- /dev/null +++ b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.prj @@ -0,0 +1 @@ +PROJCS["ETRS_1989_UTM_Zone_32N",GEOGCS["GCS_ETRS_1989",DATUM["D_ETRS_1989",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",9.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]] \ No newline at end of file diff --git a/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.shp b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.shp new file mode 100644 index 0000000000000000000000000000000000000000..1fded033e5ac59a5b24524837959ea4a7c365800 GIT binary patch literal 364 zcmZQzQ0HR64z|5uW?*0i$~B%pRI_f5s-x}KoKT)MA&xbRVtVaV)EwRH+MRT^gg9c? zjv~qkn(t8GjBQ zR&{LMbm8-z4Iz%n&+8|s{Z)m#3+B$|C*S&BZwzr1s#N2?C#&X|QSBrCV10<=p6y>n zX5UnGOxncRZ4LC-5iJ)1zB34a%KnWBvfr!f$bQm*-4`f-Q|sP?&K0VTVI3bQIIj(H ggoVq*{a2!5fadM}Jge*!Fr0qIu}(e;v=80=0FCr}$N&HU literal 0 HcmV?d00001 diff --git a/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.shx b/examples/scenarios/kelheim/pt-area_Kelheim-BadAbbach/pt-area_Kelheim-BadAbbach.shx new file mode 100644 index 0000000000000000000000000000000000000000..233d288c485abe1f1782fd58bf2dc0f7d6ab8ff4 GIT binary patch literal 108 zcmZQzQ0HR64$NLKGcd3Mc)s#!Nj)zS8APAJcs5XYKDF}-#wYL0Gp?M^ydLL9Mc KM-epw@)`hb{tp@e literal 0 HcmV?d00001 From 614fa89dce17904c85f7967463caabc4f9979999 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Wed, 28 Aug 2024 09:38:02 +0200 Subject: [PATCH 089/111] use getFirst --- .../freight/tripExtraction/ExtractRelevantFreightTrips.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripExtraction/ExtractRelevantFreightTrips.java b/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripExtraction/ExtractRelevantFreightTrips.java index 12c7c03866e..7747659fa18 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripExtraction/ExtractRelevantFreightTrips.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripExtraction/ExtractRelevantFreightTrips.java @@ -312,7 +312,7 @@ private void createActivitiesForIncomingTrips(boolean originIsInside, boolean de timeSpent += Math.floor(link.getLength() / link.getFreespeed()) + 1; } if (!isCoordSet) { - Coord originalCoord = route.links.get(0).getCoord(); + Coord originalCoord = route.links.getFirst().getCoord(); act0.setCoord(ct.transform(originalCoord)); act0.setEndTime(departureTime); } From 1abc0f9f4c2a31f640e8fd71b6c6de2cc48c52e6 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Wed, 28 Aug 2024 09:38:51 +0200 Subject: [PATCH 090/111] add variable for legMode for extracted plans --- .../freight/tripExtraction/ExtractRelevantFreightTrips.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripExtraction/ExtractRelevantFreightTrips.java b/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripExtraction/ExtractRelevantFreightTrips.java index 7747659fa18..84fce6b351a 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripExtraction/ExtractRelevantFreightTrips.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/freight/tripExtraction/ExtractRelevantFreightTrips.java @@ -74,6 +74,9 @@ private enum TripType { @CommandLine.Option(names = "--tripType", description = "Set the tripType: OUTGOING, INCOMING, TRANSIT, INTERNAL, ALL", defaultValue = "ALL") private TripType tripType; + @CommandLine.Option(names = "--LegMode", description = "Set leg mode for long distance freight legs.", defaultValue = "freight") + private String legMode; + private final SplittableRandom rnd = new SplittableRandom(4711); private final List fromCoords = new ArrayList<>(); @@ -161,7 +164,7 @@ public Integer call() throws Exception { boolean destinationIsInside = relevantArea.contains(MGC.coord2Point(sct.transform(endCoord))); Activity act0 = populationFactory.createActivityFromCoord("freight_start", null); - Leg leg = populationFactory.createLeg("freight"); + Leg leg = populationFactory.createLeg(legMode); Activity act1 = populationFactory.createActivityFromCoord("freight_end", null); switch (tripType) { From a6329100305938a5153c17e1fa80c1c92cbaffc3 Mon Sep 17 00:00:00 2001 From: vsp-gleich Date: Wed, 28 Aug 2024 14:22:34 +0200 Subject: [PATCH 091/111] pt fares interpret file paths to fare zone shapes relative to config file (#3430) --- .../vsp/pt/fare/DistanceBasedPtFareCalculator.java | 6 ++++-- .../vsp/pt/fare/FareZoneBasedPtFareCalculator.java | 6 ++++-- .../org/matsim/contrib/vsp/pt/fare/PtFareModule.java | 7 +++++-- .../vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java | 10 +++++----- .../vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java | 10 ++++------ 5 files changed, 22 insertions(+), 17 deletions(-) diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculator.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculator.java index 50ef21d6ff2..90e8d0079dc 100644 --- a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculator.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculator.java @@ -7,7 +7,9 @@ import org.matsim.application.options.ShpOptions; import org.matsim.core.utils.geometry.CoordUtils; import org.matsim.core.utils.geometry.geotools.MGC; +import org.matsim.core.utils.io.IOUtils; +import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.Optional; @@ -28,7 +30,7 @@ public class DistanceBasedPtFareCalculator implements PtFareCalculator { private final Map inShapeCache = new HashMap<>(); - public DistanceBasedPtFareCalculator(DistanceBasedPtFareParams params) { + public DistanceBasedPtFareCalculator(DistanceBasedPtFareParams params, URL context) { this.minFare = params.getMinFare(); this.distanceClassFareParams = params.getDistanceClassFareParams(); this.transactionPartner = params.getTransactionPartner(); @@ -36,7 +38,7 @@ public DistanceBasedPtFareCalculator(DistanceBasedPtFareParams params) { if (params.getFareZoneShp() != null) { log.info("For DistanceBasedPtFareCalculator '{}' a fare zone shape file was provided. During the computation, the fare will be " + "calculated only if the trip is within the shape.", params.getDescription()); - this.shp = new ShpOptions(params.getFareZoneShp(), null, null); + this.shp = new ShpOptions(IOUtils.extendUrl(context, params.getFareZoneShp()).toString(), null, null); } else { log.info("For DistanceBasedPtFareCalculator '{}' no fare zone shape file was provided. The fare will be calculated for all trips.", params.getDescription()); diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculator.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculator.java index 1066bb4b014..afe95481dab 100644 --- a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculator.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculator.java @@ -5,7 +5,9 @@ import org.matsim.api.core.v01.Coord; import org.matsim.application.options.ShpOptions; import org.matsim.core.utils.geometry.geotools.MGC; +import org.matsim.core.utils.io.IOUtils; +import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.Optional; @@ -20,8 +22,8 @@ public class FareZoneBasedPtFareCalculator implements PtFareCalculator { public static final String FARE = "fare"; - public FareZoneBasedPtFareCalculator(FareZoneBasedPtFareParams params) { - this.shp = new ShpOptions(params.getFareZoneShp(), null, null); + public FareZoneBasedPtFareCalculator(FareZoneBasedPtFareParams params, URL context) { + this.shp = new ShpOptions(IOUtils.extendUrl(context, params.getFareZoneShp()).toString(), null, null); transactionPartner = params.getTransactionPartner(); } diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareModule.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareModule.java index b13cf5c2af2..8bb27ba59b4 100644 --- a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareModule.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/PtFareModule.java @@ -6,6 +6,7 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.core.controler.AbstractModule; +import java.net.URL; import java.util.Collection; import java.util.Comparator; import java.util.stream.Stream; @@ -22,14 +23,16 @@ public void install() { Collection fareZoneBased = ptFareConfigGroup.getParameterSets(FareZoneBasedPtFareParams.SET_TYPE); Collection distanceBased = ptFareConfigGroup.getParameterSets(DistanceBasedPtFareParams.SET_TYPE); + URL context = getConfig().getContext(); + Stream.concat(fareZoneBased.stream(), distanceBased.stream()) .map(c -> (PtFareParams) c) .sorted(Comparator.comparing(PtFareParams::getOrder)) .forEach(p -> { if (p instanceof FareZoneBasedPtFareParams fareZoneBasedPtFareParams) { - ptFareCalculator.addBinding().toInstance(new FareZoneBasedPtFareCalculator(fareZoneBasedPtFareParams)); + ptFareCalculator.addBinding().toInstance(new FareZoneBasedPtFareCalculator(fareZoneBasedPtFareParams, context)); } else if (p instanceof DistanceBasedPtFareParams distanceBasedPtFareParams) { - ptFareCalculator.addBinding().toInstance(new DistanceBasedPtFareCalculator(distanceBasedPtFareParams)); + ptFareCalculator.addBinding().toInstance(new DistanceBasedPtFareCalculator(distanceBasedPtFareParams, context)); } else { throw new RuntimeException("Unknown PtFareParams: " + p.getClass()); } diff --git a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java index fcb72cedf27..71e5a803859 100644 --- a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareCalculatorTest.java @@ -13,6 +13,8 @@ class DistanceBasedPtFareCalculatorTest { private static final String TRANSACTION_PARTNER = "TP"; + private static final URL context = ExamplesUtils.getTestScenarioURL("kelheim"); + @Test void testNormalDistance() { //100m -> 1.1 EUR @@ -33,7 +35,6 @@ void testThreshold() { @Test void testNotInShapeFile() { - URL context = ExamplesUtils.getTestScenarioURL("kelheim"); String shape = IOUtils.extendUrl(context, "ptTestArea/pt-area.shp").toString(); Coord a = new Coord(726634.40, 5433508.07); Coord b = new Coord(736634.40, 5533508.07); @@ -43,7 +44,6 @@ void testNotInShapeFile() { @Test void testInShapeFile() { - URL context = ExamplesUtils.getTestScenarioURL("kelheim"); String shape = IOUtils.extendUrl(context, "ptTestArea/pt-area.shp").toString(); Coord a = new Coord(710300.624, 5422165.737); Coord b = new Coord(714940.65, 5420707.78); @@ -74,7 +74,7 @@ private DistanceBasedPtFareCalculator getCalculator(String shapeFile) { params.setMinFare(1.0); params.setFareZoneShp(shapeFile); - return new DistanceBasedPtFareCalculator(params); + return new DistanceBasedPtFareCalculator(params, context); } @Test @@ -102,7 +102,7 @@ void testModifyParams() { params.setMinFare(1.0); - DistanceBasedPtFareCalculator distanceBasedPtFareCalculator = new DistanceBasedPtFareCalculator(params); + DistanceBasedPtFareCalculator distanceBasedPtFareCalculator = new DistanceBasedPtFareCalculator(params, context); PtFareCalculator.FareResult fareResult = distanceBasedPtFareCalculator.calculateFare(new Coord(0, 0), new Coord(0, 100)).orElseThrow(); Assertions.assertEquals(new PtFareCalculator.FareResult(2.2, TRANSACTION_PARTNER), fareResult); } @@ -126,7 +126,7 @@ void testMultipleParamsWithSameMaxDistance() { // add in a different way so no automatic overwrite params.addParameterSet(distanceClass2kmDuplicateFareParams); - Assertions.assertThrows(RuntimeException.class, () -> new DistanceBasedPtFareCalculator(params), + Assertions.assertThrows(RuntimeException.class, () -> new DistanceBasedPtFareCalculator(params, context), "DistanceBasedPtFareCalculator should crash if multiple DistanceClassLinearFareFunctionParams with the same max distance " + " are present, because it is unclear which of them should be applied at that distance."); } diff --git a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java index a23019c86f3..e9e9080952e 100644 --- a/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java +++ b/contribs/vsp/src/test/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculatorTest.java @@ -2,7 +2,6 @@ import org.junit.jupiter.api.Test; import org.matsim.api.core.v01.Coord; -import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import java.net.URL; @@ -13,10 +12,11 @@ class FareZoneBasedPtFareCalculatorTest { private static final double COST_IN_SHP_FILE = 1.5; private static final String TRANSACTION_PARTNER = "TP"; + private static final URL context = ExamplesUtils.getTestScenarioURL("kelheim"); @Test void testCalculateFareInShape() { - FareZoneBasedPtFareCalculator fareZoneBasedPtFareCalculator = new FareZoneBasedPtFareCalculator(getParams()); + FareZoneBasedPtFareCalculator fareZoneBasedPtFareCalculator = new FareZoneBasedPtFareCalculator(getParams(), context); Coord inShape = new Coord(710300.624, 5422165.737); Coord inShape2 = new Coord(714940.65, 5420707.78); @@ -31,7 +31,7 @@ void testCalculateFareInShape() { @Test void testCalculateFareOutShape() { - FareZoneBasedPtFareCalculator fareZoneBasedPtFareCalculator = new FareZoneBasedPtFareCalculator(getParams()); + FareZoneBasedPtFareCalculator fareZoneBasedPtFareCalculator = new FareZoneBasedPtFareCalculator(getParams(), context); Coord inShape = new Coord(710300.624, 5422165.737); Coord inShape2 = new Coord(714940.65, 5420707.78); @@ -46,10 +46,8 @@ void testCalculateFareOutShape() { } private FareZoneBasedPtFareParams getParams() { - URL context = ExamplesUtils.getTestScenarioURL("kelheim"); - FareZoneBasedPtFareParams fareZoneBasedPtFareParams = new FareZoneBasedPtFareParams(); - fareZoneBasedPtFareParams.setFareZoneShp(IOUtils.extendUrl(context, "ptTestArea/pt-area.shp").toString()); + fareZoneBasedPtFareParams.setFareZoneShp("ptTestArea/pt-area.shp"); fareZoneBasedPtFareParams.setTransactionPartner(TRANSACTION_PARTNER); return fareZoneBasedPtFareParams; } From 508930697d57111b7d7c52e6499b4b188db0cde2 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Wed, 28 Aug 2024 14:39:52 +0200 Subject: [PATCH 092/111] fix rare insertion bug add test case for insertion scheduler --- .../DefaultRequestInsertionScheduler.java | 15 +- .../drt/run/examples/RunDrtExampleIT.java | 2 +- .../DefaultRequestInsertionSchedulerTest.java | 288 ++++++++++++++++++ 3 files changed, 301 insertions(+), 4 deletions(-) create mode 100644 contribs/drt/src/test/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionSchedulerTest.java diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java index bab43ffc742..5ef8ea8f31a 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionScheduler.java @@ -319,7 +319,11 @@ private DrtStopTask insertPickup(AcceptedDrtRequest request, InsertionWithDetour double nextBeginTime = pickupIdx == dropoffIdx ? // pickupStopTask.getEndTime() : // asap - stops.get(pickupIdx).task.getBeginTime(); // as planned + stops.get(pickupIdx).task.getPickupRequests().values() + .stream() + .mapToDouble(AcceptedDrtRequest::getEarliestStartTime) + .min() + .orElse(pickupStopTask.getEndTime()); if (request.getFromLink() == toLink) { // prebooking case when we are already at the stop location, but next stop task happens in the future @@ -434,8 +438,13 @@ private DrtStopTask insertDropoff(AcceptedDrtRequest request, InsertionWithDetou afterDropoffTask.getTaskIdx() + 1, afterDropoffTask.getEndTime()); } else { // may want to wait here or after driving before starting next stop + double earliestArrivalTime = stops.get(dropoffIdx).task.getPickupRequests().values() + .stream() + .mapToDouble(AcceptedDrtRequest::getEarliestStartTime) + .min() + .orElse(dropoffStopTask.getEndTime()); Task afterDropoffTask = insertDriveWithWait(vehicleEntry.vehicle, dropoffStopTask, vrpPath, - stops.get(dropoffIdx).task.getBeginTime()); + earliestArrivalTime); scheduleTimingUpdater.updateTimingsStartingFromTaskIdx(vehicleEntry.vehicle, afterDropoffTask.getTaskIdx() + 1, afterDropoffTask.getEndTime()); @@ -518,7 +527,7 @@ private Task insertDriveWithWait(DvrpVehicle vehicle, Task departureTask, VrpPat Task driveTask = taskFactory.createDriveTask(vehicle, path, DrtDriveTask.TYPE); schedule.addTask(leadingTask.getTaskIdx() + 1, driveTask); - if (driveTask.getEndTime() < latestArrivalTime) { + if (driveTask.getEndTime() < latestArrivalTime && !scheduleWaitBeforeDrive) { DrtStayTask waitTask = taskFactory.createStayTask(vehicle, driveTask.getEndTime(), latestArrivalTime, path.getToLink()); schedule.addTask(driveTask.getTaskIdx() + 1, waitTask); diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java index 7b62adcace0..807696d3710 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java @@ -388,7 +388,7 @@ void testRunDrtWithPrebooking() { var expectedStats = Stats.newBuilder() .rejectionRate(0.04) .rejections(14) - .waitAverage(232.47) + .waitAverage(232.48) .inVehicleTravelTimeMean(389.16) .totalTravelTimeMean(621.63) .build(); diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionSchedulerTest.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionSchedulerTest.java new file mode 100644 index 00000000000..b1924ad36b4 --- /dev/null +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/scheduler/DefaultRequestInsertionSchedulerTest.java @@ -0,0 +1,288 @@ +package org.matsim.contrib.drt.scheduler; + +import com.google.common.base.Verify; +import com.google.common.collect.ImmutableList; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.drt.optimizer.VehicleEntry; +import org.matsim.contrib.drt.optimizer.Waypoint; +import org.matsim.contrib.drt.optimizer.insertion.InsertionDetourTimeCalculator; +import org.matsim.contrib.drt.optimizer.insertion.InsertionGenerator; +import org.matsim.contrib.drt.optimizer.insertion.InsertionWithDetourData; +import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; +import org.matsim.contrib.drt.passenger.DrtRequest; +import org.matsim.contrib.drt.run.examples.RunDrtExampleIT; +import org.matsim.contrib.drt.schedule.*; +import org.matsim.contrib.drt.stops.MinimumStopDurationAdapter; +import org.matsim.contrib.drt.stops.PrebookingStopTimeCalculator; +import org.matsim.contrib.drt.stops.StaticPassengerStopDurationProvider; +import org.matsim.contrib.dvrp.fleet.*; +import org.matsim.contrib.dvrp.optimizer.Request; +import org.matsim.contrib.dvrp.path.OneToManyPathSearch; +import org.matsim.contrib.dvrp.path.VrpPathWithTravelData; +import org.matsim.contrib.dvrp.path.VrpPaths; +import org.matsim.contrib.dvrp.schedule.*; +import org.matsim.core.mobsim.framework.MobsimTimer; +import org.matsim.core.router.util.LeastCostPathCalculator; +import org.matsim.core.router.util.TravelTime; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.testcases.fakes.FakeLink; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.matsim.contrib.dvrp.path.VrpPaths.NODE_TRANSITION_TIME; + +/** + * @author nkuehnel / MOIA + */ +public class DefaultRequestInsertionSchedulerTest { + + @RegisterExtension + public MatsimTestUtils utils = new MatsimTestUtils(); + + public static final TravelTime TRAVEL_TIME = (link, time, person, vehicle) -> 10 - NODE_TRANSITION_TIME; + public static final double STOP_DURATION = 60.; + + private final static double DRIVE_TIME = 10.; + + public static final double CURRENT_TIME = 10; + public static final double R1_PU_TIME = CURRENT_TIME + DRIVE_TIME + STOP_DURATION; + public static final double R1_DO_TIME = R1_PU_TIME + DRIVE_TIME; + + //existing on-board request + public static final double R2_PU_TIME = 0.; + public static final double R2_DO_TIME = R1_DO_TIME + STOP_DURATION + DRIVE_TIME ; + + public static final int R3_PU_TIME = 20; + public static final int R3_DO_TIME = 30; + + public static final double ALLOWED_DETOUR = STOP_DURATION + 2 * DRIVE_TIME; + + public static final Id V_1_ID = Id.create("v1", DvrpVehicle.class); + + private final Link from1 = link("from1"); + private final Link to1 = link("to1"); + + private final Link from2 = link("from2"); + private final Link to2 = link("to2"); + private final Link from3 = from1; + private final Link to3 = link("to3"); + private final DrtRequest existingRequest1 = request("r1", from1, to1, 0., R1_DO_TIME + ALLOWED_DETOUR, R1_PU_TIME, R1_PU_TIME); + private final DrtRequest existingRequest2 = request("r2", from2, to2, 0., R2_DO_TIME + ALLOWED_DETOUR, R2_PU_TIME, R2_PU_TIME); + private final DrtRequest newRequest = request("r3", from3, to3, CURRENT_TIME, R3_DO_TIME + ALLOWED_DETOUR, R3_PU_TIME, R3_PU_TIME); + + private static final String mode = "DRT_MODE"; + + + @Test + public void testInsertion() { + Link startLink = link("start"); + FleetSpecificationImpl fleetSpecification = new FleetSpecificationImpl(); + fleetSpecification.addVehicleSpecification(ImmutableDvrpVehicleSpecification.newBuilder() + .id(V_1_ID) + .startLinkId(startLink.getId()) + .capacity(6) + .serviceBeginTime(0) + .serviceEndTime(1000) + .build() + ); + + Fleet fleet = Fleets.createDefaultFleet(fleetSpecification, dvrpVehicleSpecification -> startLink); + MobsimTimer timer = new MobsimTimer(1); + timer.setTime(CURRENT_TIME); + DefaultRequestInsertionScheduler insertionScheduler = getDefaultRequestInsertionScheduler(fleet, timer); + + + DvrpVehicle vehicle = fleet.getVehicles().get(V_1_ID); + + // vehicle schedule + Task task = vehicle.getSchedule().nextTask(); + + vehicle.getSchedule().getCurrentTask().setEndTime(CURRENT_TIME); + LeastCostPathCalculator.Path path = new LeastCostPathCalculator.Path(null, List.of(), 0., 0); + VrpPathWithTravelData vrpPath = VrpPaths.createPath(startLink, existingRequest1.getFromLink(), CURRENT_TIME, path, TRAVEL_TIME); + vehicle.getSchedule().addTask(new DrtDriveTask(vrpPath, DrtDriveTask.TYPE)); + + DefaultDrtStopTask stopTask0 = new DefaultDrtStopTask(R1_PU_TIME - STOP_DURATION, R1_PU_TIME, from1); + AcceptedDrtRequest acceptedExistingRequest = AcceptedDrtRequest.createFromOriginalRequest(existingRequest1); + stopTask0.addPickupRequest(acceptedExistingRequest); + vehicle.getSchedule().addTask(stopTask0); + + VrpPathWithTravelData vrpPath2 = VrpPaths.createPath(existingRequest1.getFromLink(), existingRequest1.getToLink(), stopTask0.getEndTime(), path, TRAVEL_TIME); + vehicle.getSchedule().addTask(new DrtDriveTask(vrpPath2, DrtDriveTask.TYPE)); + + DefaultDrtStopTask stopTask1 = new DefaultDrtStopTask(R1_DO_TIME, R1_DO_TIME + STOP_DURATION, to1); + stopTask1.addDropoffRequest(acceptedExistingRequest); + vehicle.getSchedule().addTask(stopTask1); + + LeastCostPathCalculator.Path longPath = new LeastCostPathCalculator.Path(null, List.of(), 200, 0); + VrpPathWithTravelData vrpPath3 = VrpPaths.createPath(existingRequest1.getToLink(), existingRequest2.getToLink(), stopTask1.getEndTime(), longPath, TRAVEL_TIME); + vehicle.getSchedule().addTask(new DrtDriveTask(vrpPath3, DrtDriveTask.TYPE)); + + DefaultDrtStopTask stopTask2 = new DefaultDrtStopTask(stopTask1.getEndTime() + longPath.travelTime + 10., stopTask1.getEndTime() + longPath.travelTime + STOP_DURATION, to2); + AcceptedDrtRequest acceptedExistingRequest2 = AcceptedDrtRequest.createFromOriginalRequest(existingRequest2); + stopTask2.addDropoffRequest(acceptedExistingRequest2); + vehicle.getSchedule().addTask(stopTask2); + + + // vehicle entry + Waypoint.Start start = start(null, CURRENT_TIME, startLink, 1);//not a STOP -> pickup cannot be appended + Waypoint.Stop stop0 = stop(stopTask0, 2); + Waypoint.Stop stop1 = stop(stopTask1, 1); + Waypoint.Stop stop2 = stop(stopTask2, 0); + var vehicleEntry = entry(vehicle, start, stop0, stop1, stop2); + + InsertionWithDetourData.InsertionDetourData detour = detourData(0, 10, 10, 10.); + InsertionDetourTimeCalculator.DetourTimeInfo detourTimeInfo = detourTimeInfo(); + InsertionWithDetourData insertion = insertion(vehicleEntry, 1, 2, detour, newRequest, + detourTimeInfo); + + RequestInsertionScheduler.PickupDropoffTaskPair pickupDropoffTaskPair = + insertionScheduler.scheduleRequest(AcceptedDrtRequest.createFromOriginalRequest(newRequest), insertion); + + ScheduleInfo actualScheduleInfo = getScheduleInfo(vehicle.getSchedule()); + ScheduleInfo expectedScheduleInfo = ScheduleInfo.newBuilder() + .addTask(new ScheduleBuilder.TaskInfo(0, 0, 10, Task.TaskStatus.STARTED, + DrtStayTask.TYPE, Set.of(), Set.of())) + .addTask(new ScheduleBuilder.TaskInfo(1, 10, 20, Task.TaskStatus.PLANNED, + DrtDriveTask.TYPE, Set.of(), Set.of())) + .addTask(new ScheduleBuilder.TaskInfo(2, 20, 80, Task.TaskStatus.PLANNED, + DefaultDrtStopTask.TYPE, Set.of(existingRequest1.getId(), newRequest.getId()), Set.of())) + .addTask(new ScheduleBuilder.TaskInfo(3, 80, 90, Task.TaskStatus.PLANNED, + DrtDriveTask.TYPE, Set.of(), Set.of())) + .addTask(new ScheduleBuilder.TaskInfo(4, 90, 150, Task.TaskStatus.PLANNED, + DefaultDrtStopTask.TYPE, Set.of(), Set.of(existingRequest1.getId()))) + .addTask(new ScheduleBuilder.TaskInfo(5, 150, 170, Task.TaskStatus.PLANNED, + DrtDriveTask.TYPE, Set.of(), Set.of())) + .addTask(new ScheduleBuilder.TaskInfo(6, 170, 230, Task.TaskStatus.PLANNED, + DefaultDrtStopTask.TYPE, Set.of(), Set.of(newRequest.getId()))) + .addTask(new ScheduleBuilder.TaskInfo(7, 230, 250, Task.TaskStatus.PLANNED, + DrtDriveTask.TYPE, Set.of(), Set.of())) + .addTask(new ScheduleBuilder.TaskInfo(8, 250, 310, Task.TaskStatus.PLANNED, + DefaultDrtStopTask.TYPE, Set.of(), Set.of(existingRequest2.getId()))) + .build(); + + compareTwoSchedules(actualScheduleInfo, expectedScheduleInfo); + + + } + + private InsertionDetourTimeCalculator.DetourTimeInfo detourTimeInfo() { + return new InsertionDetourTimeCalculator.DetourTimeInfo( + new InsertionDetourTimeCalculator.PickupDetourInfo(R1_PU_TIME + STOP_DURATION, 0.), + new InsertionDetourTimeCalculator.DropoffDetourInfo(R1_PU_TIME + STOP_DURATION + DRIVE_TIME, 20.) + ); + } + + private static DefaultRequestInsertionScheduler getDefaultRequestInsertionScheduler(Fleet fleet, MobsimTimer timer) { + MinimumStopDurationAdapter stopDuration = new MinimumStopDurationAdapter(new PrebookingStopTimeCalculator(StaticPassengerStopDurationProvider.of(STOP_DURATION, 0.0)), 60.); + ScheduleTimingUpdater scheduleTimingUpdater = new ScheduleTimingUpdater(timer, new DrtStayTaskEndTimeCalculator(stopDuration)); + DefaultRequestInsertionScheduler insertionScheduler = new DefaultRequestInsertionScheduler(fleet, timer, TRAVEL_TIME, scheduleTimingUpdater, + new DrtTaskFactoryImpl(), stopDuration, true); + return insertionScheduler; + } + + private InsertionWithDetourData.InsertionDetourData detourData(double toPickupTT, double fromPickupTT, double toDropoffTT, + double fromDropoffTT) { + var toPickupDetour = new OneToManyPathSearch.PathData(new LeastCostPathCalculator.Path(null, List.of(), toPickupTT, 0), 0); + var fromPickupDetour = new OneToManyPathSearch.PathData(new LeastCostPathCalculator.Path(null, List.of(), fromPickupTT, 0), 0); + var toDropoffDetour = new OneToManyPathSearch.PathData(new LeastCostPathCalculator.Path(null, List.of(), toDropoffTT, 0), 0); + var fromDropoffDetour = new OneToManyPathSearch.PathData(new LeastCostPathCalculator.Path(null, List.of(), fromDropoffTT, 0), 0); + return new InsertionWithDetourData.InsertionDetourData(toPickupDetour, fromPickupDetour, toDropoffDetour, fromDropoffDetour); + } + + private InsertionWithDetourData insertion(VehicleEntry entry, int pickupIdx, int dropoffIdx, + InsertionWithDetourData.InsertionDetourData detour, + DrtRequest drtRequest, InsertionDetourTimeCalculator.DetourTimeInfo detourTimeInfo) { + return new InsertionWithDetourData( + new InsertionGenerator.Insertion(drtRequest, entry, pickupIdx, dropoffIdx), + detour, + detourTimeInfo + ); + } + + + private VehicleEntry entry(DvrpVehicle vehicle, Waypoint.Start start, Waypoint.Stop... stops) { + List precedingStayTimes = Collections.nCopies(stops.length, 0.0); + return new VehicleEntry(vehicle, start, ImmutableList.copyOf(stops), null, precedingStayTimes, 0); + } + + private Waypoint.Start start(Task task, double time, Link link, int occupancy) { + return new Waypoint.Start(task, link, time, occupancy); + } + + private Waypoint.Stop stop(DefaultDrtStopTask stopTask, int outgoingOccupancy) { + return new Waypoint.Stop(stopTask, outgoingOccupancy); + } + + + private DrtRequest request(String id, Link fromLink, Link toLink, double submissionTime, + double latestArrivalTime, double earliestStartTime, double latestStartTime) { + return DrtRequest.newBuilder() + .id(Id.create(id, Request.class)) + .passengerIds(List.of(Id.createPersonId(id))) + .submissionTime(submissionTime) + .latestArrivalTime(latestArrivalTime) + .latestStartTime(latestStartTime) + .earliestStartTime(earliestStartTime) + .fromLink(fromLink) + .toLink(toLink) + .mode(mode) + .build(); + } + + private Link link(String id) { + return new FakeLink(Id.createLinkId(id)); + } + + + + private record ScheduleInfo(List taskInfos) { + public static ScheduleBuilder newBuilder() { + return new ScheduleBuilder(); + } + } + + private static ScheduleInfo getScheduleInfo(Schedule schedule) { + ScheduleBuilder scheduleBuilder = ScheduleInfo.newBuilder(); + for (Task task : schedule.getTasks()) { + scheduleBuilder.addTask(new ScheduleBuilder.TaskInfo(task.getTaskIdx(), task.getBeginTime(), + task.getEndTime(), task.getStatus(), task.getTaskType(), + task instanceof DrtStopTask ? ((DrtStopTask) task).getPickupRequests().keySet(): Set.of(), + task instanceof DrtStopTask ? ((DrtStopTask) task).getDropoffRequests().keySet(): Set.of() + )); + } + return scheduleBuilder.build(); + } + + + private static class ScheduleBuilder { + + private record TaskInfo(int taskIdx, double beginTime, double endTime, Task.TaskStatus status, + Task.TaskType taskType, Set> puRequests, Set> doRequests) {} + + private ScheduleBuilder(){} + + + private final List taskInfos = new ArrayList<>(); + + public ScheduleBuilder addTask(TaskInfo taskInfo) { + taskInfos.add(taskInfo.taskIdx, taskInfo); + return this; + } + + public ScheduleInfo build() { + return new ScheduleInfo(taskInfos); + } + } + + private static void compareTwoSchedules(ScheduleInfo actualScheduleInfo, ScheduleInfo expectedScheduleInfo) { + assertThat(actualScheduleInfo).usingRecursiveComparison().isEqualTo(expectedScheduleInfo); + } +} \ No newline at end of file From 349189c7d96d87f21c4cc4ef39ba3ae91754d278 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Wed, 28 Aug 2024 15:48:26 +0200 Subject: [PATCH 093/111] drt: add option to prevent agents re-attempting to book a rejected pre-booked ride --- .../drt/prebooking/PrebookingManager.java | 26 +++++++++++++++++-- .../prebooking/PrebookingModeQSimModule.java | 2 +- .../drt/prebooking/PrebookingParams.java | 6 +++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java index ed79cd0bf9f..85614dfa225 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java @@ -9,6 +9,7 @@ import org.matsim.api.core.v01.events.handler.PersonStuckEventHandler; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.population.Activity; import org.matsim.api.core.v01.population.Leg; import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.Plan; @@ -21,10 +22,12 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.mobsim.framework.MobsimAgent; import org.matsim.core.mobsim.framework.MobsimAgent.State; +import org.matsim.core.mobsim.framework.MobsimPassengerAgent; import org.matsim.core.mobsim.framework.MobsimTimer; import org.matsim.core.mobsim.framework.events.MobsimAfterSimStepEvent; import org.matsim.core.mobsim.framework.listeners.MobsimAfterSimStepListener; import org.matsim.core.mobsim.qsim.InternalInterface; +import org.matsim.core.mobsim.qsim.agents.HasModifiablePlan; import org.matsim.core.mobsim.qsim.agents.WithinDayAgentUtils; import org.matsim.core.mobsim.qsim.interfaces.MobsimEngine; @@ -59,12 +62,16 @@ public class PrebookingManager implements MobsimEngine, MobsimAfterSimStepListen private final VrpOptimizer optimizer; private final RequestUnscheduler unscheduler; + private final boolean abortRejectedPrebookings; private final MobsimTimer mobsimTimer; + private InternalInterface internalInterface; + + public PrebookingManager(String mode, Network network, PassengerRequestCreator requestCreator, - VrpOptimizer optimizer, MobsimTimer mobsimTimer, PassengerRequestValidator requestValidator, - EventsManager eventsManager, RequestUnscheduler unscheduler) { + VrpOptimizer optimizer, MobsimTimer mobsimTimer, PassengerRequestValidator requestValidator, + EventsManager eventsManager, RequestUnscheduler unscheduler, boolean abortRejectedPrebookings) { this.network = network; this.mode = mode; this.requestCreator = requestCreator; @@ -74,6 +81,7 @@ public PrebookingManager(String mode, Network network, PassengerRequestCreator r this.mobsimTimer = mobsimTimer; this.eventsManager = eventsManager; this.unscheduler = unscheduler; + this.abortRejectedPrebookings = abortRejectedPrebookings; } // Functionality for ID management @@ -386,6 +394,19 @@ private void processRejections(double now) { } else { unscheduleUponVehicleAssignment.add(requestId); } + + if(abortRejectedPrebookings) { + for (Id passengerId : item.request.getPassengerIds()) { + MobsimAgent agent = internalInterface.getMobsim().getAgents().get(passengerId); + ((Activity) WithinDayAgentUtils.getCurrentPlanElement(agent)).setEndTime(Double.POSITIVE_INFINITY); + ((Activity) WithinDayAgentUtils.getCurrentPlanElement(agent)).setMaximumDurationUndefined(); + ((HasModifiablePlan) agent).resetCaches(); + internalInterface.getMobsim().rescheduleActivityEnd(agent); + eventsManager.processEvent(new PersonStuckEvent(now, agent.getId(), agent.getCurrentLinkId(), + this.mode)); + internalInterface.getMobsim().getAgentCounter().incLost(); + } + } } } @@ -454,5 +475,6 @@ public void afterSim() { @Override public void setInternalInterface(InternalInterface internalInterface) { + this.internalInterface = internalInterface; } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingModeQSimModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingModeQSimModule.java index 19274c3fd8b..4ae7e1201a3 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingModeQSimModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingModeQSimModule.java @@ -59,7 +59,7 @@ protected void configureQSim() { MobsimTimer mobsimTimer = getter.get(MobsimTimer.class); return new PrebookingManager(getMode(), network, requestCreator, optimizer, mobsimTimer, requestValidator, - eventsManager, requestUnscheduler); + eventsManager, requestUnscheduler, prebookingParams.abortRejectedPrebookings); })).in(Singleton.class); addModalQSimComponentBinding().to(modalKey(PrebookingManager.class)); diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingParams.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingParams.java index fdf678bb272..4f1cdcb58e2 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingParams.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingParams.java @@ -38,4 +38,10 @@ public enum UnschedulingMode { @NotNull public UnschedulingMode unschedulingMode = UnschedulingMode.StopBased; + @Parameter + @Comment("Defines whether agents are set to stuck and abort when a prebooked request is rejected." + + "If false, prebooked agents will re-attempt to ride at their initially planned departure time." + + "Note that additional passenger events for submission, scheduling etc. will occur for re-attempts.") + public boolean abortRejectedPrebookings = true; + } \ No newline at end of file From 5924acd2641721f644a8ecddf2e3b20502bee49c Mon Sep 17 00:00:00 2001 From: Theresa Ziemke Date: Wed, 28 Aug 2024 15:51:55 +0200 Subject: [PATCH 094/111] bind NewScoreAssigner as singleton ...before it was created newly each iteration such that MSA counting did not work --- .../src/main/java/org/matsim/core/scoring/PlansScoringImpl.java | 2 +- .../main/java/org/matsim/core/scoring/PlansScoringModule.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/matsim/src/main/java/org/matsim/core/scoring/PlansScoringImpl.java b/matsim/src/main/java/org/matsim/core/scoring/PlansScoringImpl.java index bc774cc2c1d..a5671b0c673 100644 --- a/matsim/src/main/java/org/matsim/core/scoring/PlansScoringImpl.java +++ b/matsim/src/main/java/org/matsim/core/scoring/PlansScoringImpl.java @@ -52,11 +52,11 @@ final class PlansScoringImpl implements PlansScoring, ScoringListener, Iteration @Inject private OutputDirectoryHierarchy controlerIO; @Inject private ScoringFunctionsForPopulation scoringFunctionsForPopulation; @Inject private ExperiencedPlansService experiencedPlansService; + @Inject private NewScoreAssigner newScoreAssigner; @Override public void notifyScoring(final ScoringEvent event) { scoringFunctionsForPopulation.finishScoringFunctions(); - NewScoreAssignerImpl newScoreAssigner = new NewScoreAssignerImpl(this.scoringConfigGroup, this.controllerConfigGroup); newScoreAssigner.assignNewScores(event.getIteration(), this.scoringFunctionsForPopulation, this.population); } diff --git a/matsim/src/main/java/org/matsim/core/scoring/PlansScoringModule.java b/matsim/src/main/java/org/matsim/core/scoring/PlansScoringModule.java index 1e5f29c1114..2048613ebd5 100644 --- a/matsim/src/main/java/org/matsim/core/scoring/PlansScoringModule.java +++ b/matsim/src/main/java/org/matsim/core/scoring/PlansScoringModule.java @@ -32,5 +32,6 @@ public void install() { bind(ScoringFunctionsForPopulation.class).asEagerSingleton(); bind(PlansScoring.class).to(PlansScoringImpl.class); bind(ExperiencedPlansService.class).to(ExperiencedPlansServiceImpl.class).asEagerSingleton(); + bind(NewScoreAssigner.class).to(NewScoreAssignerImpl.class).asEagerSingleton(); } } From 115e50aec162c22ff1542277f6abf4ef7ccb145b Mon Sep 17 00:00:00 2001 From: vsp-gleich Date: Wed, 28 Aug 2024 17:15:06 +0200 Subject: [PATCH 095/111] correct german wide fare km / m conversion, add check fare != null in FareZoneBasedPtFareCalculator (#3434) --- .../contrib/vsp/pt/fare/DistanceBasedPtFareParams.java | 9 +++++---- .../vsp/pt/fare/FareZoneBasedPtFareCalculator.java | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java index 86780a92cec..363306b30df 100644 --- a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/DistanceBasedPtFareParams.java @@ -17,7 +17,7 @@ * The values are based on the standard unit of meter (m) and Euro (EUR) */ public class DistanceBasedPtFareParams extends PtFareParams { - public static final DistanceBasedPtFareParams GERMAN_WIDE_FARE = germanWideFare(); + public static final DistanceBasedPtFareParams GERMAN_WIDE_FARE_2024 = germanWideFare2024(); public static final String SET_TYPE = "ptFareCalculationDistanceBased"; public static final String MIN_FARE = "minFare"; @@ -53,7 +53,7 @@ public void setMinFare(double minFare) { // hence the following difference in data points // prices taken from https://deutschlandtarifverbund.de/wp-content/uploads/2024/07/20231201_TBDT_J_10_Preisliste_V07.pdf // TODO: This fare will change. We might need a way to select the fare of a specific year - private static DistanceBasedPtFareParams germanWideFare() { + private static DistanceBasedPtFareParams germanWideFare2024() { final double MIN_FARE = 1.70; SimpleRegression under100kmTrip = new SimpleRegression(); @@ -111,11 +111,12 @@ private static DistanceBasedPtFareParams germanWideFare() { var params = new DistanceBasedPtFareParams(); DistanceClassLinearFareFunctionParams distanceClass100kmFareParams = params.getOrCreateDistanceClassFareParams(100_000.); - distanceClass100kmFareParams.setFareSlope(under100kmTrip.getSlope()); + // above values are per km, fare deduction is based on meter instead + distanceClass100kmFareParams.setFareSlope(under100kmTrip.getSlope() / 1000.0); distanceClass100kmFareParams.setFareIntercept(under100kmTrip.getIntercept()); DistanceClassLinearFareFunctionParams distanceClassLongFareParams = params.getOrCreateDistanceClassFareParams(Double.POSITIVE_INFINITY); - distanceClassLongFareParams.setFareSlope(longDistanceTrip.getSlope()); + distanceClassLongFareParams.setFareSlope(longDistanceTrip.getSlope() / 1000.0); distanceClassLongFareParams.setFareIntercept(longDistanceTrip.getIntercept()); params.setTransactionPartner("Deutschlandtarif"); diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculator.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculator.java index afe95481dab..adf9971f914 100644 --- a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculator.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/pt/fare/FareZoneBasedPtFareCalculator.java @@ -1,5 +1,6 @@ package org.matsim.contrib.vsp.pt.fare; +import com.google.common.base.Verify; import org.geotools.api.feature.simple.SimpleFeature; import org.locationtech.jts.geom.Geometry; import org.matsim.api.core.v01.Coord; @@ -42,6 +43,8 @@ public Optional calculateFare(Coord from, Coord to) { } Double fare = (Double) departureZone.get().getAttribute(FARE); + Verify.verifyNotNull(fare, "Fare zone without attribute " + FARE + " in " + shp.getShapeFile() + + " found. Terminating."); return Optional.of(new FareResult(fare, transactionPartner)); } From ce6168aada0f0048ce985407dc907de3770a77e4 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Thu, 29 Aug 2024 10:21:07 +0200 Subject: [PATCH 096/111] update tests --- .../run/RunPrebookingShiftDrtScenarioIT.java | 98 ++++++++++++++----- .../drt/run/examples/RunDrtExampleIT.java | 4 +- 2 files changed, 75 insertions(+), 27 deletions(-) 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 9dc2e4ba071..2ef3b6d6d1b 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java @@ -1,5 +1,8 @@ package org.matsim.contrib.drt.extension.operations.shifts.run; +import com.google.common.collect.HashMultiset; +import com.google.common.collect.Multiset; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.matsim.api.core.v01.Coord; @@ -62,11 +65,77 @@ public class RunPrebookingShiftDrtScenarioIT { @Test - void test() { + void testWithReattempts() { MultiModeDrtConfigGroup multiModeDrtConfigGroup = new MultiModeDrtConfigGroup(DrtWithExtensionsConfigGroup::new); + DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup = (DrtWithExtensionsConfigGroup) multiModeDrtConfigGroup.createParameterSet("drt"); + final Controler run = prepare(drtWithShiftsConfigGroup, multiModeDrtConfigGroup); + + Multiset> rejectedPersons = HashMultiset.create(); + run.addOverridingModule(new AbstractModule() { + @Override + public void install() { + addEventHandlerBinding().toInstance((PassengerRequestRejectedEventHandler) event -> rejectedPersons.addAll(event.getPersonIds())); + } + }); + + PrebookingParams prebookingParams = new PrebookingParams(); + prebookingParams.maximumPassengerDelay = 600; + prebookingParams.unschedulingMode = PrebookingParams.UnschedulingMode.Routing; + prebookingParams.scheduleWaitBeforeDrive = true; + prebookingParams.abortRejectedPrebookings = false; + drtWithShiftsConfigGroup.addParameterSet(prebookingParams); + + run.addOverridingQSimModule(new PrebookingModeQSimModule(drtWithShiftsConfigGroup.getMode(), + prebookingParams)); + + run.run(); + + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(1) )); + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(3))); + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(5))); + Assertions.assertEquals(1, rejectedPersons.count(Id.createPersonId(2))); + Assertions.assertEquals(1, rejectedPersons.count(Id.createPersonId(4))); + Assertions.assertEquals(2, rejectedPersons.count(Id.createPersonId(6))); + } + + @Test + void testWithoutReattempts() { + MultiModeDrtConfigGroup multiModeDrtConfigGroup = new MultiModeDrtConfigGroup(DrtWithExtensionsConfigGroup::new); DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup = (DrtWithExtensionsConfigGroup) multiModeDrtConfigGroup.createParameterSet("drt"); + final Controler run = prepare(drtWithShiftsConfigGroup, multiModeDrtConfigGroup); + + Multiset> rejectedPersons = HashMultiset.create(); + run.addOverridingModule(new AbstractModule() { + @Override + public void install() { + addEventHandlerBinding().toInstance((PassengerRequestRejectedEventHandler) event -> rejectedPersons.addAll(event.getPersonIds())); + } + }); + + PrebookingParams prebookingParams = new PrebookingParams(); + prebookingParams.maximumPassengerDelay = 600; + prebookingParams.unschedulingMode = PrebookingParams.UnschedulingMode.Routing; + prebookingParams.scheduleWaitBeforeDrive = true; + prebookingParams.abortRejectedPrebookings = true; + drtWithShiftsConfigGroup.addParameterSet(prebookingParams); + + run.addOverridingQSimModule(new PrebookingModeQSimModule(drtWithShiftsConfigGroup.getMode(), + prebookingParams)); + + run.run(); + + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(1) )); + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(3))); + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(5))); + Assertions.assertEquals(1, rejectedPersons.count(Id.createPersonId(2))); + Assertions.assertEquals(1, rejectedPersons.count(Id.createPersonId(4))); + Assertions.assertEquals(1, rejectedPersons.count(Id.createPersonId(6))); + } + + @NotNull + private Controler prepare(DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup, MultiModeDrtConfigGroup multiModeDrtConfigGroup) { drtWithShiftsConfigGroup.mode = TransportMode.drt; DefaultDrtOptimizationConstraintsSet defaultConstraintsSet = (DefaultDrtOptimizationConstraintsSet) drtWithShiftsConfigGroup.addOrGetDrtOptimizationConstraintsParams() @@ -148,11 +217,6 @@ void test() { shiftsParams.shiftEndLookAhead = 900.; drtWithShiftsConfigGroup.addParameterSet(operationsParams); - PrebookingParams prebookingParams = new PrebookingParams(); - prebookingParams.maximumPassengerDelay = 600; - prebookingParams.unschedulingMode = PrebookingParams.UnschedulingMode.Routing; - prebookingParams.scheduleWaitBeforeDrive = true; - drtWithShiftsConfigGroup.addParameterSet(prebookingParams); Scenario scenario = DrtControlerCreator.createScenarioWithDrtRouteFactory(config); prepareNetwork(scenario); @@ -161,27 +225,9 @@ void test() { final Controler run = DrtOperationsControlerCreator.createControler(config, scenario, false); prepareOperations(run, drtWithShiftsConfigGroup); - run.addOverridingQSimModule(new PrebookingModeQSimModule(drtWithShiftsConfigGroup.getMode(), - prebookingParams)); - AttributeBasedPrebookingLogic.install(run, drtWithShiftsConfigGroup); - - Set> rejectedPersons = new HashSet<>(); - run.addOverridingModule(new AbstractModule() { - @Override - public void install() { - addEventHandlerBinding().toInstance((PassengerRequestRejectedEventHandler) event -> rejectedPersons.addAll(event.getPersonIds())); - } - }); - - run.run(); - - Assertions.assertFalse(rejectedPersons.contains(Id.createPersonId(1))); - Assertions.assertFalse(rejectedPersons.contains(Id.createPersonId(3))); - Assertions.assertFalse(rejectedPersons.contains(Id.createPersonId(5))); - Assertions.assertTrue(rejectedPersons.contains(Id.createPersonId(2))); - Assertions.assertTrue(rejectedPersons.contains(Id.createPersonId(4))); - Assertions.assertTrue(rejectedPersons.contains(Id.createPersonId(6))); + AttributeBasedPrebookingLogic.install(run, drtWithShiftsConfigGroup); + return run; } private void preparePopulation(Scenario scenario) { diff --git a/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java b/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java index 7b62adcace0..4a16f8daf3a 100644 --- a/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java +++ b/contribs/drt/src/test/java/org/matsim/contrib/drt/run/examples/RunDrtExampleIT.java @@ -370,7 +370,9 @@ void testRunDrtWithPrebooking() { config.controller().setOutputDirectory(utils.getOutputDirectory()); DrtConfigGroup drtConfig = DrtConfigGroup.getSingleModeDrtConfig(config); - drtConfig.addParameterSet(new PrebookingParams()); + PrebookingParams prebookingParams = new PrebookingParams(); + prebookingParams.abortRejectedPrebookings = false; + drtConfig.addParameterSet(prebookingParams); Controler controller = DrtControlerCreator.createControler(config, false); ProbabilityBasedPrebookingLogic.install(controller, drtConfig, 0.5, 4.0 * 3600.0); From 783360d92ed849d6498bcecadb429ffc96e03de9 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Thu, 29 Aug 2024 11:03:22 +0200 Subject: [PATCH 097/111] update test --- .../contrib/drt/extension/edrt/run/RunEDrtScenarioIT.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenarioIT.java index 1d23eb2a1c4..8aaa6a7af7f 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenarioIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenarioIT.java @@ -103,7 +103,9 @@ void testWithPrebooking() { new OTFVisConfigGroup(), new EvConfigGroup()); DrtConfigGroup drtConfig = DrtConfigGroup.getSingleModeDrtConfig(config); - drtConfig.addParameterSet(new PrebookingParams()); + PrebookingParams prebookingParams = new PrebookingParams(); + prebookingParams.abortRejectedPrebookings = false; + drtConfig.addParameterSet(prebookingParams); Controler controller = RunEDrtScenario.createControler(config, false); ProbabilityBasedPrebookingLogic.install(controller, drtConfig, 0.5, 4.0 * 3600.0); From b5529694cb9e89c365d344a1fc7987b5977a8174 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Aug 2024 05:08:32 +0000 Subject: [PATCH 098/111] Bump avro.version from 1.11.3 to 1.12.0 Bumps `avro.version` from 1.11.3 to 1.12.0. Updates `org.apache.avro:avro` from 1.11.3 to 1.12.0 Updates `org.apache.avro:avro-maven-plugin` from 1.11.3 to 1.12.0 --- updated-dependencies: - dependency-name: org.apache.avro:avro dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.avro:avro-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- contribs/application/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribs/application/pom.xml b/contribs/application/pom.xml index 70a548c2dc7..4035f096a83 100644 --- a/contribs/application/pom.xml +++ b/contribs/application/pom.xml @@ -22,7 +22,7 @@ - 1.11.3 + 1.12.0 From 6bd4b3618f53a88a7cfc5be4110cb1d8751e76e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Fri, 30 Aug 2024 10:47:57 +0200 Subject: [PATCH 099/111] potentially more efficient version of PrebookingStopActivity --- .../prebooking/PrebookingStopActivity.java | 96 +++++++++++++------ 1 file changed, 67 insertions(+), 29 deletions(-) diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingStopActivity.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingStopActivity.java index fd81c1745f3..3c04ba985a3 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingStopActivity.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingStopActivity.java @@ -1,15 +1,15 @@ package org.matsim.contrib.drt.prebooking; -import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.PriorityQueue; import java.util.Queue; -import java.util.Set; import java.util.function.Supplier; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.IdMap; +import org.matsim.api.core.v01.IdSet; import org.matsim.api.core.v01.Identifiable; import org.matsim.api.core.v01.population.Person; import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; @@ -39,9 +39,13 @@ public class PrebookingStopActivity extends FirstLastSimStepDynActivity implemen private final Map, ? extends AcceptedDrtRequest> pickupRequests; private final Map, ? extends AcceptedDrtRequest> dropoffRequests; - private final IdMap enterTimes = new IdMap<>(Request.class); + private final Queue enterTimes = new PriorityQueue<>(); private final Queue leaveTimes = new PriorityQueue<>(); - private final Set> enteredRequests = new HashSet<>(); + + private final IdSet enteredRequests = new IdSet<>(Request.class); + + private final IdSet registeredPickups = new IdSet<>(Request.class); + private final IdMap expectedPickups = new IdMap<>(Request.class); private final PrebookingManager prebookingManager; private final PassengerHandler passengerHandler; @@ -93,7 +97,6 @@ private void initDropoffRequests(double now) { } private boolean updateDropoffRequests(double now) { - while (!leaveTimes.isEmpty() && leaveTimes.peek().time <= now) { Id requestId = leaveTimes.poll().id; passengerHandler.dropOffPassengers(driver, requestId, now); @@ -105,60 +108,94 @@ private boolean updateDropoffRequests(double now) { } private record QueuedRequest(Id id, double time) implements Comparable { - @Override public int compareTo(QueuedRequest o) { return Double.compare(this.time, o.time); } } + private int cachedPickupRequestsHash = -1; + private boolean updatePickupRequests(double now, boolean isFirstStep) { - var pickupIterator = pickupRequests.values().iterator(); - - while (pickupIterator.hasNext()) { - var request = pickupIterator.next(); - - if (!enteredRequests.contains(request.getId()) && !enterTimes.containsKey(request.getId())) { - // this is a new request that has been added after the activity has been created - // or that had not arrived yet - - if (passengerHandler.notifyWaitForPassengers(this, this.driver, request.getId())) { - // agent starts to enter - queuePickup(request, now); - } else if (now > request.getEarliestStartTime() && !isFirstStep) { - if (abandonVoter.abandonRequest(now, vehicle, request)) { - prebookingManager.abandon(request.getId()); - } + int pickupRequestsHash = pickupRequests.hashCode(); + + // part 1: check if the pickup list has been updated dynamically + + if (isFirstStep || pickupRequestsHash != cachedPickupRequestsHash) { + cachedPickupRequestsHash = pickupRequestsHash; + + // added requests + for (AcceptedDrtRequest request : pickupRequests.values()) { + if (!registeredPickups.contains(request.getId())) { + // in the first step, this is a standard pickup request, later this is a request that has been added after the activity has been created + expectedPickups.put(request.getId(), request); + registeredPickups.add(request.getId()); + } + } + + // removed requests (for instance via cancellation) + var expectedIterator = expectedPickups.iterator(); + while (expectedIterator.hasNext()) { + if (!pickupRequests.containsKey(expectedIterator.next().getId())) { + // a request has been removed from the list of expected pickups + expectedIterator.remove(); } } } + + // part 2: handle the requests that we expect but which have not arrived yet + + var expectedIterator = expectedPickups.values().iterator(); + while (expectedIterator.hasNext()) { + AcceptedDrtRequest request = expectedIterator.next(); + + if (passengerHandler.notifyWaitForPassengers(this, this.driver, request.getId())) { + // agent starts to enter + queuePickup(request, now); + expectedIterator.remove(); + } else if (now > request.getEarliestStartTime() && !isFirstStep) { + if (abandonVoter.abandonRequest(now, vehicle, request)) { + // abandon the request, but not in the first time step for the sake of event timing + prebookingManager.abandon(request.getId()); + expectedIterator.remove(); + } + } + } + + // part 3: handle the requests that are currently entering the vehicle + + var enterIterator = enterTimes.iterator(); - var enterIterator = enterTimes.entrySet().iterator(); + // logic is as follows: + // - let people enter in the order at which they arrived + their interaction time + // - but in case there is no capacity (others still disembarking) they need to wait while (enterIterator.hasNext()) { var entry = enterIterator.next(); int availableCapacity = vehicle.getCapacity() - onboard; - if (entry.getValue() <= now) { - int requiredCapacity = pickupRequests.get(entry.getKey()).getPassengerCount(); + if (entry.time <= now) { + int requiredCapacity = pickupRequests.get(entry.id).getPassengerCount(); if (requiredCapacity <= availableCapacity) { // let agent enter now - Verify.verify(passengerHandler.tryPickUpPassengers(this, driver, entry.getKey(), now)); - enteredRequests.add(entry.getKey()); + Verify.verify(passengerHandler.tryPickUpPassengers(this, driver, entry.id, now)); + enteredRequests.add(entry.id); onboard += requiredCapacity; enterIterator.remove(); } + } else { + break; } } - return enterTimes.size() == 0 && pickupRequests.size() == enteredRequests.size(); + return expectedPickups.size() == 0 && pickupRequests.size() == enteredRequests.size(); } private void queuePickup(AcceptedDrtRequest request, double now) { prebookingManager.notifyPickup(now, request); double enterTime = now + stopDurationProvider.calcPickupDuration(vehicle, request.getRequest()); - enterTimes.put(request.getId(), enterTime); + enterTimes.add(new QueuedRequest(request.getId(), enterTime)); } @Override @@ -170,6 +207,7 @@ protected void simStep(double now) { public void notifyPassengersAreReadyForDeparture(List passengers, double now) { var request = getRequestForPassengers(passengers.stream().map(Identifiable::getId).toList()); queuePickup(request, now); + expectedPickups.remove(request.getId()); } private AcceptedDrtRequest getRequestForPassengers(List> passengerIds) { From 55226f46135d3fea04871a20527897cd948637ae Mon Sep 17 00:00:00 2001 From: Marcel Rieser Date: Fri, 30 Aug 2024 17:20:06 +0200 Subject: [PATCH 100/111] add github action to deploy dtds --- .github/workflows/deploy-dtds.yaml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/deploy-dtds.yaml diff --git a/.github/workflows/deploy-dtds.yaml b/.github/workflows/deploy-dtds.yaml new file mode 100644 index 00000000000..bb48f61d27b --- /dev/null +++ b/.github/workflows/deploy-dtds.yaml @@ -0,0 +1,24 @@ +name: deploy-dtds-on-website + +on: + push: + branches: + - master + paths: + - matsim/src/main/resources/dtd + +jobs: + rsync-dtds: + name: sync DTDs to website + runs-on: ubuntu-latest + + steps: + - name: rsync dtds + uses: burnett01/rsync-deployments@7.0.1 + with: + switches: -avz + path: matsim/src/main/resources/dtd/ + remote_path: ~/httpdocs/files/dtd/ + remote_host: ${{ secrets.WEBSITE_DEPLOY_HOST }} + remote_user: ${{ secrets.WEBSITE_DEPLOY_USER }} + remote_key: ${{ secrets.WEBSITE_SSH_PRIVATE_KEY }} From 57b300ddc118dc6bfdc5c1af7f579e7b213b2382 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Mon, 2 Sep 2024 10:10:46 +0200 Subject: [PATCH 101/111] update prebooking rejection handling --- .../contrib/drt/prebooking/PrebookingManager.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) 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 85614dfa225..7e8d739e526 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java @@ -9,10 +9,7 @@ import org.matsim.api.core.v01.events.handler.PersonStuckEventHandler; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; -import org.matsim.api.core.v01.population.Activity; -import org.matsim.api.core.v01.population.Leg; -import org.matsim.api.core.v01.population.Person; -import org.matsim.api.core.v01.population.Plan; +import org.matsim.api.core.v01.population.*; import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; import org.matsim.contrib.drt.prebooking.unscheduler.RequestUnscheduler; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; @@ -398,10 +395,13 @@ private void processRejections(double now) { if(abortRejectedPrebookings) { for (Id passengerId : item.request.getPassengerIds()) { MobsimAgent agent = internalInterface.getMobsim().getAgents().get(passengerId); - ((Activity) WithinDayAgentUtils.getCurrentPlanElement(agent)).setEndTime(Double.POSITIVE_INFINITY); - ((Activity) WithinDayAgentUtils.getCurrentPlanElement(agent)).setMaximumDurationUndefined(); + PlanElement planElement = WithinDayAgentUtils.getCurrentPlanElement(agent); + if(planElement instanceof Activity activity) { + activity.setEndTime(Double.POSITIVE_INFINITY); + activity.setMaximumDurationUndefined(); + internalInterface.getMobsim().rescheduleActivityEnd(agent); + } ((HasModifiablePlan) agent).resetCaches(); - internalInterface.getMobsim().rescheduleActivityEnd(agent); eventsManager.processEvent(new PersonStuckEvent(now, agent.getId(), agent.getCurrentLinkId(), this.mode)); internalInterface.getMobsim().getAgentCounter().incLost(); From 958577c32811da409045157b998ba852f27400c5 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Mon, 2 Sep 2024 10:44:46 +0200 Subject: [PATCH 102/111] update prebooking rejection handling --- .../matsim/contrib/drt/prebooking/PrebookingManager.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) 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 7e8d739e526..b610ececae7 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,9 @@ 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(); - internalInterface.getMobsim().rescheduleActivityEnd(agent); - } ((HasModifiablePlan) agent).resetCaches(); + agent.setStateToAbort(mobsimTimer.getTimeOfDay()); + internalInterface.arrangeNextAgentState(agent); eventsManager.processEvent(new PersonStuckEvent(now, agent.getId(), agent.getCurrentLinkId(), this.mode)); internalInterface.getMobsim().getAgentCounter().incLost(); From 7776adfc2b0c963c781a5d7e6ff8d1e7ac08b6cb Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Mon, 2 Sep 2024 12:05:03 +0200 Subject: [PATCH 103/111] pass money and additionalScore events through to carrierScoringFunction --- .../carriers/controler/CarrierDriverAgent.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java index 00233bbbf18..137e576f44e 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java @@ -97,6 +97,8 @@ void handleAnEvent(Event event){ case LinkEnterEvent linkEnterEvent -> handleEvent(linkEnterEvent); case ActivityEndEvent activityEndEvent -> handleEvent(activityEndEvent); case ActivityStartEvent activityStartEvent -> handleEvent(activityStartEvent); + case PersonMoneyEvent personMoneyEvent -> handleEvent( personMoneyEvent ); + case PersonScoreEvent personScoreEvent -> handleEvent( personScoreEvent ); case null, default -> createAdditionalEvents(event, null, scheduledTour, driverId, planElementCounter); } } @@ -145,6 +147,22 @@ private void handleEvent( LinkEnterEvent event ){ createAdditionalEvents( event, null, scheduledTour, driverId, planElementCounter ); } + private void handleEvent( PersonScoreEvent event ){ + if( scoringFunction != null ){ + scoringFunction.handleEvent( event ); + } +// currentRoute.add( event.getLinkId() ); +// createAdditionalEvents( event, null, scheduledTour, driverId, planElementCounter ); + } + + private void handleEvent( PersonMoneyEvent event ){ + if( scoringFunction != null ){ + scoringFunction.handleEvent( event ); + } +// currentRoute.add( event.getLinkId() ); +// createAdditionalEvents( event, null, scheduledTour, driverId, planElementCounter ); + } + private void handleEvent( ActivityEndEvent event ){ if( currentActivity == null ){ Activity firstActivity = PopulationUtils.createActivityFromLinkId( event.getActType(), event.getLinkId() ); From 621f289b54d3517767002ca4cca90952c493b4c8 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Mon, 2 Sep 2024 15:51:51 +0200 Subject: [PATCH 104/111] update prebooking rejections --- .../run/RunPrebookingShiftDrtScenarioIT.java | 52 ++++++++++++++++--- .../analysis/DrtEventSequenceCollector.java | 2 +- .../drt/prebooking/PrebookingManager.java | 10 ++-- .../passenger/DefaultPassengerEngine.java | 2 +- 4 files changed, 55 insertions(+), 11 deletions(-) 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 2ef3b6d6d1b..01f5e27b837 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java @@ -37,6 +37,8 @@ import org.matsim.contrib.dvrp.fleet.FleetSpecificationImpl; import org.matsim.contrib.dvrp.fleet.ImmutableDvrpVehicleSpecification; import org.matsim.contrib.dvrp.passenger.PassengerRequestRejectedEventHandler; +import org.matsim.contrib.dvrp.passenger.PassengerRequestScheduledEventHandler; +import org.matsim.contrib.dvrp.passenger.PassengerRequestSubmittedEventHandler; import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; import org.matsim.contrib.dvrp.run.DvrpConfigGroup; import org.matsim.contrib.zone.skims.DvrpTravelTimeMatrixParams; @@ -71,10 +73,15 @@ void testWithReattempts() { DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup = (DrtWithExtensionsConfigGroup) multiModeDrtConfigGroup.createParameterSet("drt"); final Controler run = prepare(drtWithShiftsConfigGroup, multiModeDrtConfigGroup); + Multiset> submittedPersons = HashMultiset.create(); + Multiset> scheduledPersons = HashMultiset.create(); Multiset> rejectedPersons = HashMultiset.create(); + run.addOverridingModule(new AbstractModule() { @Override public void install() { + addEventHandlerBinding().toInstance((PassengerRequestSubmittedEventHandler) event -> submittedPersons.addAll(event.getPersonIds())); + addEventHandlerBinding().toInstance((PassengerRequestScheduledEventHandler) event -> scheduledPersons.addAll(event.getPersonIds())); addEventHandlerBinding().toInstance((PassengerRequestRejectedEventHandler) event -> rejectedPersons.addAll(event.getPersonIds())); } }); @@ -91,11 +98,25 @@ public void install() { run.run(); - Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(1) )); - Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(3))); - Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(5))); + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(1))); + Assertions.assertEquals(2, submittedPersons.count(Id.createPersonId(2))); + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(3))); + Assertions.assertEquals(2, submittedPersons.count(Id.createPersonId(4))); + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(5))); + Assertions.assertEquals(2, submittedPersons.count(Id.createPersonId(6))); + + Assertions.assertEquals(1, scheduledPersons.count(Id.createPersonId(1))); + Assertions.assertEquals(1, scheduledPersons.count(Id.createPersonId(2))); + Assertions.assertEquals(1, scheduledPersons.count(Id.createPersonId(3))); + Assertions.assertEquals(1, scheduledPersons.count(Id.createPersonId(4))); + Assertions.assertEquals(1, scheduledPersons.count(Id.createPersonId(5))); + Assertions.assertEquals(0, scheduledPersons.count(Id.createPersonId(6))); + + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(1))); Assertions.assertEquals(1, rejectedPersons.count(Id.createPersonId(2))); + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(3))); Assertions.assertEquals(1, rejectedPersons.count(Id.createPersonId(4))); + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(5))); Assertions.assertEquals(2, rejectedPersons.count(Id.createPersonId(6))); } @@ -106,10 +127,15 @@ void testWithoutReattempts() { DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup = (DrtWithExtensionsConfigGroup) multiModeDrtConfigGroup.createParameterSet("drt"); final Controler run = prepare(drtWithShiftsConfigGroup, multiModeDrtConfigGroup); + Multiset> submittedPersons = HashMultiset.create(); + Multiset> scheduledPersons = HashMultiset.create(); Multiset> rejectedPersons = HashMultiset.create(); + run.addOverridingModule(new AbstractModule() { @Override public void install() { + addEventHandlerBinding().toInstance((PassengerRequestSubmittedEventHandler) event -> submittedPersons.addAll(event.getPersonIds())); + addEventHandlerBinding().toInstance((PassengerRequestScheduledEventHandler) event -> scheduledPersons.addAll(event.getPersonIds())); addEventHandlerBinding().toInstance((PassengerRequestRejectedEventHandler) event -> rejectedPersons.addAll(event.getPersonIds())); } }); @@ -126,11 +152,25 @@ public void install() { run.run(); - Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(1) )); - Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(3))); - Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(5))); + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(1))); + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(2))); + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(3))); + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(4))); + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(5))); + Assertions.assertEquals(1, submittedPersons.count(Id.createPersonId(6))); + + Assertions.assertEquals(1, scheduledPersons.count(Id.createPersonId(1))); + Assertions.assertEquals(0, scheduledPersons.count(Id.createPersonId(2))); + Assertions.assertEquals(1, scheduledPersons.count(Id.createPersonId(3))); + Assertions.assertEquals(0, scheduledPersons.count(Id.createPersonId(4))); + Assertions.assertEquals(1, scheduledPersons.count(Id.createPersonId(5))); + Assertions.assertEquals(0, scheduledPersons.count(Id.createPersonId(6))); + + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(1))); Assertions.assertEquals(1, rejectedPersons.count(Id.createPersonId(2))); + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(3))); Assertions.assertEquals(1, rejectedPersons.count(Id.createPersonId(4))); + Assertions.assertEquals(0, rejectedPersons.count(Id.createPersonId(5))); Assertions.assertEquals(1, rejectedPersons.count(Id.createPersonId(6))); } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/DrtEventSequenceCollector.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/DrtEventSequenceCollector.java index b8b095cd1dc..90836e785cc 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/DrtEventSequenceCollector.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/DrtEventSequenceCollector.java @@ -159,7 +159,7 @@ public List getDrtFares() { } public boolean isCompleted() { - return personEvents.values().stream().allMatch(pe -> pe.droppedOff != null); + return submitted.getPersonIds().stream().allMatch(personId -> personEvents.get(personId).droppedOff != null); } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java index b610ececae7..04d8df45161 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingManager.java @@ -395,9 +395,13 @@ private void processRejections(double now) { if(abortRejectedPrebookings) { for (Id passengerId : item.request.getPassengerIds()) { MobsimAgent agent = internalInterface.getMobsim().getAgents().get(passengerId); - ((HasModifiablePlan) agent).resetCaches(); - agent.setStateToAbort(mobsimTimer.getTimeOfDay()); - internalInterface.arrangeNextAgentState(agent); + PlanElement planElement = WithinDayAgentUtils.getCurrentPlanElement(agent); + if(planElement instanceof Activity activity) { + activity.setEndTime(Double.POSITIVE_INFINITY); + activity.setMaximumDurationUndefined(); + ((HasModifiablePlan) agent).resetCaches(); + internalInterface.getMobsim().rescheduleActivityEnd(agent); + } eventsManager.processEvent(new PersonStuckEvent(now, agent.getId(), agent.getCurrentLinkId(), this.mode)); internalInterface.getMobsim().getAgentCounter().incLost(); diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/passenger/DefaultPassengerEngine.java b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/passenger/DefaultPassengerEngine.java index 7406ceaa359..96571f584da 100644 --- a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/passenger/DefaultPassengerEngine.java +++ b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/passenger/DefaultPassengerEngine.java @@ -153,7 +153,7 @@ private void handleGroupDepartures(double now) { private void handleDepartureImpl(double now, List group) { List> groupIds = group.stream().map(Identifiable::getId).toList(); - MobsimPassengerAgent representative = group.get(0); + MobsimPassengerAgent representative = group.getFirst(); Id fromLinkId = representative.getCurrentLinkId(); Id toLinkId = representative.getDestinationLinkId(); From 137b99b36ad6e50fcbe92f6fc6b885a5863be640 Mon Sep 17 00:00:00 2001 From: Kai Martins-Turner Date: Mon, 2 Sep 2024 16:32:14 +0200 Subject: [PATCH 105/111] pass VehicleEnters/LeavesTrafficEvent events through to carrierScoringFunction --- .../controler/CarrierDriverAgent.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java index 137e576f44e..f234b30c599 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java @@ -97,6 +97,8 @@ void handleAnEvent(Event event){ case LinkEnterEvent linkEnterEvent -> handleEvent(linkEnterEvent); case ActivityEndEvent activityEndEvent -> handleEvent(activityEndEvent); case ActivityStartEvent activityStartEvent -> handleEvent(activityStartEvent); + case VehicleEntersTrafficEvent vehicleEntersTrafficEvent -> handleEvent(vehicleEntersTrafficEvent); + case VehicleLeavesTrafficEvent vehicleLeavesTrafficEvent -> handleEvent(vehicleLeavesTrafficEvent); case PersonMoneyEvent personMoneyEvent -> handleEvent( personMoneyEvent ); case PersonScoreEvent personScoreEvent -> handleEvent( personScoreEvent ); case null, default -> createAdditionalEvents(event, null, scheduledTour, driverId, planElementCounter); @@ -151,16 +153,25 @@ private void handleEvent( PersonScoreEvent event ){ if( scoringFunction != null ){ scoringFunction.handleEvent( event ); } -// currentRoute.add( event.getLinkId() ); -// createAdditionalEvents( event, null, scheduledTour, driverId, planElementCounter ); } private void handleEvent( PersonMoneyEvent event ){ if( scoringFunction != null ){ scoringFunction.handleEvent( event ); } -// currentRoute.add( event.getLinkId() ); -// createAdditionalEvents( event, null, scheduledTour, driverId, planElementCounter ); + } + + private void handleEvent( VehicleEntersTrafficEvent event ){ + if( scoringFunction != null ){ + scoringFunction.handleEvent( event ); + } + driver2EventHandler.handleAnEvent(event); + } + + private void handleEvent( VehicleLeavesTrafficEvent event ){ + if( scoringFunction != null ){ + scoringFunction.handleEvent( event ); + } } private void handleEvent( ActivityEndEvent event ){ @@ -214,7 +225,6 @@ private void createAdditionalEvents( Event event, Activity activity, ScheduledTo // if( scoringFunction == null ){ // (means "called from LSP". kai, jul'22) - driver2EventHandler.handleAnEvent(event); Id vehicleId = driver2EventHandler.getVehicleOfDriver(driverId); // Reason why this here is needed is that the more informative objects such as ScheduledTour cannot be @@ -293,9 +303,6 @@ public void handleAnEvent(Event event){ if (event instanceof VehicleEntersTrafficEvent vehicleEntersTrafficEvent) { driver2EventHandler.handleEvent(vehicleEntersTrafficEvent); } - if (event instanceof VehicleEntersTrafficEvent vehicleEntersTrafficEvent) { - driver2EventHandler.handleEvent(vehicleEntersTrafficEvent); - } } } From 369a0313a25ed5c66bfaff9836c6a0f12f09884c Mon Sep 17 00:00:00 2001 From: Kai Martins-Turner Date: Mon, 2 Sep 2024 16:34:37 +0200 Subject: [PATCH 106/111] inline method --- .../freight/carriers/controler/CarrierDriverAgent.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java index f234b30c599..c7f030f3457 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/controler/CarrierDriverAgent.java @@ -165,7 +165,9 @@ private void handleEvent( VehicleEntersTrafficEvent event ){ if( scoringFunction != null ){ scoringFunction.handleEvent( event ); } - driver2EventHandler.handleAnEvent(event); + if ((Event) event instanceof VehicleEntersTrafficEvent vehicleEntersTrafficEvent) { + driver2EventHandler.handleEvent(vehicleEntersTrafficEvent); + } } private void handleEvent( VehicleLeavesTrafficEvent event ){ @@ -299,12 +301,6 @@ public Id getVehicleOfDriver(Id personId){ return driversVehicles.get(personId); } - public void handleAnEvent(Event event){ - if (event instanceof VehicleEntersTrafficEvent vehicleEntersTrafficEvent) { - driver2EventHandler.handleEvent(vehicleEntersTrafficEvent); - } - } - } } From d399d554339438b1dfa4d90ab221ca1050063f85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 06:02:06 +0000 Subject: [PATCH 107/111] Bump it.unimi.dsi:fastutil from 8.5.13 to 8.5.14 Bumps [it.unimi.dsi:fastutil](https://github.com/vigna/fastutil) from 8.5.13 to 8.5.14. - [Changelog](https://github.com/vigna/fastutil/blob/master/CHANGES) - [Commits](https://github.com/vigna/fastutil/commits/8.5.14) --- updated-dependencies: - dependency-name: it.unimi.dsi:fastutil dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index be4f98f1127..f7866d67c0a 100644 --- a/pom.xml +++ b/pom.xml @@ -308,7 +308,7 @@ it.unimi.dsi fastutil - 8.5.13 + 8.5.14 From a1eb66709887c1a1fe3a32219a93b9d47555dbc0 Mon Sep 17 00:00:00 2001 From: Theresa Ziemke Date: Tue, 3 Sep 2024 11:02:27 +0200 Subject: [PATCH 108/111] add a test for msa with controller ...before there was only one which tested the msa functionality itself without a controller (only using EventsToScore and the separate binding there). This new test fails without the changes of this bugfix. --- .../core/scoring/EventsToScoreTest.java | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/matsim/src/test/java/org/matsim/core/scoring/EventsToScoreTest.java b/matsim/src/test/java/org/matsim/core/scoring/EventsToScoreTest.java index d7390a8bf70..8462f81ed19 100644 --- a/matsim/src/test/java/org/matsim/core/scoring/EventsToScoreTest.java +++ b/matsim/src/test/java/org/matsim/core/scoring/EventsToScoreTest.java @@ -23,17 +23,39 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.events.PersonDepartureEvent; import org.matsim.api.core.v01.events.PersonMoneyEvent; +import org.matsim.api.core.v01.events.handler.PersonDepartureEventHandler; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.network.Node; import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.Population; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.ReplanningConfigGroup; +import org.matsim.core.config.groups.RoutingConfigGroup; +import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controler; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.controler.events.IterationEndsEvent; +import org.matsim.core.controler.events.IterationStartsEvent; +import org.matsim.core.controler.listener.IterationEndsListener; +import org.matsim.core.controler.listener.IterationStartsListener; import org.matsim.core.events.EventsUtils; +import org.matsim.core.mobsim.framework.events.MobsimBeforeCleanupEvent; +import org.matsim.core.mobsim.framework.events.MobsimInitializedEvent; +import org.matsim.core.mobsim.framework.listeners.MobsimBeforeCleanupListener; +import org.matsim.core.mobsim.framework.listeners.MobsimInitializedListener; +import org.matsim.core.mobsim.qsim.AbstractQSimModule; import org.matsim.core.population.PopulationUtils; +import org.matsim.core.replanning.strategies.DefaultPlanStrategiesModule; import org.matsim.core.scenario.MutableScenario; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.core.scoring.functions.CharyparNagelScoringFunctionFactory; @@ -158,6 +180,119 @@ void testMsaAveraging() { } } + @Test + void testMsaAveragingWithController() { + Config config = ConfigUtils.createConfig() ; + config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.overwriteExistingFiles); + + config.controller().setFirstIteration(10); + config.controller().setLastIteration(110); + + config.scoring().setMarginalUtilityOfMoney(1.); + config.scoring().setFractionOfIterationsToStartScoreMSA(0.9); + + ReplanningConfigGroup.StrategySettings strat = new ReplanningConfigGroup.StrategySettings(); + strat.setStrategyName(DefaultPlanStrategiesModule.DefaultSelector.KeepLastSelected); + strat.setWeight(1.); + config.replanning().addStrategySettings(strat); + + config.routing().setNetworkRouteConsistencyCheck(RoutingConfigGroup.NetworkRouteConsistencyCheck.disable); + + Scenario scenario = ScenarioUtils.createScenario(config); + + Network network = scenario.getNetwork(); + Node node0 = network.getFactory().createNode(Id.createNodeId(0), new Coord(0, 0)); + Node node1 = network.getFactory().createNode(Id.createNodeId(1), new Coord(1, 0)); + network.addNode(node0); + network.addNode(node1); + Link link01 = network.getFactory().createLink(Id.createLinkId("0_1"), node0, node1); + network.addLink(link01); + + Population population = scenario.getPopulation(); + Person person = PopulationUtils.getFactory().createPerson(Id.create(1, Person.class)); + population.addPerson(person); + Plan plan = PopulationUtils.createPlan() ; + plan.addActivity(population.getFactory().createActivityFromLinkId("dummy", link01.getId())); + person.addPlan(plan); + + ScoringConfigGroup.ActivityParams dummyAct = new ScoringConfigGroup.ActivityParams("dummy"); + dummyAct.setScoringThisActivityAtAll(false); + config.scoring().addActivityParams(dummyAct); + + Controler controler = new Controler(scenario); + EventsManager events = controler.getEvents(); + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + final int[] iteration = new int[1]; + this.addControlerListenerBinding().toInstance(new IterationStartsListener() { + @Override + public void notifyIterationStarts(IterationStartsEvent event) { + iteration[0] = event.getIteration(); + } + }); + this.addMobsimListenerBinding().toInstance(new MobsimInitializedListener() { + @Override + public void notifyMobsimInitialized(MobsimInitializedEvent e) { + events.processEvent(new PersonMoneyEvent(3600.0, person.getId(), iteration[0] -98, "bribe", "contractor" )); + } + }); + } + }); + controler.addControlerListener(new IterationEndsListener() { + @Override + public void notifyIterationEnds(IterationEndsEvent event) { + System.out.println( "score: " + person.getSelectedPlan().getScore() ) ; + + switch(event.getIteration()){ + case 99: + Assertions.assertEquals(1.0, person.getSelectedPlan().getScore(), 0); + break ; + case 100: + // first MSA iteration; plain score should be ok: + Assertions.assertEquals(2.0, person.getSelectedPlan().getScore(), 0); + break ; + case 101: + // second MSA iteration + // (2+3)/2 = 2.5 + Assertions.assertEquals(2.5, person.getSelectedPlan().getScore(), 0); + break ; + case 102: + // 3rd MSA iteration + // (2+3+4)/3 = 3 + Assertions.assertEquals(3.0, person.getSelectedPlan().getScore(), 0); + break ; + case 103: + // (2+3+4+5)/4 = 3.5 + Assertions.assertEquals(3.5, person.getSelectedPlan().getScore(), 0); + break ; + case 104: + Assertions.assertEquals(4.0, person.getSelectedPlan().getScore(), 0); + break ; + case 105: + Assertions.assertEquals(4.5, person.getSelectedPlan().getScore(), 0); + break ; + case 106: + Assertions.assertEquals(5.0, person.getSelectedPlan().getScore(), 0); + break ; + case 107: + Assertions.assertEquals(5.5, person.getSelectedPlan().getScore(), 0); + break ; + case 108: + Assertions.assertEquals(6.0, person.getSelectedPlan().getScore(), 0); + break ; + case 109: + Assertions.assertEquals(6.5, person.getSelectedPlan().getScore(), 0); + break ; + case 110: + Assertions.assertEquals(7.0, person.getSelectedPlan().getScore(), 0); + break ; + } + } + }); + controler.run(); + } + private static class MockScoringFunctionFactory implements ScoringFunctionFactory { @Override From 9a2a3c3dcc0ecaf8b9a60d7a054c2afe1564bb7a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 14:08:21 +0000 Subject: [PATCH 109/111] Bump com.google.protobuf:protobuf-java from 4.27.2 to 4.28.0 Bumps [com.google.protobuf:protobuf-java](https://github.com/protocolbuffers/protobuf) from 4.27.2 to 4.28.0. - [Release notes](https://github.com/protocolbuffers/protobuf/releases) - [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/protobuf_release.bzl) - [Commits](https://github.com/protocolbuffers/protobuf/commits) --- updated-dependencies: - dependency-name: com.google.protobuf:protobuf-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- contribs/hybridsim/pom.xml | 2 +- contribs/protobuf/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contribs/hybridsim/pom.xml b/contribs/hybridsim/pom.xml index f58a572c939..b480aa197dd 100644 --- a/contribs/hybridsim/pom.xml +++ b/contribs/hybridsim/pom.xml @@ -10,7 +10,7 @@ hybridsim - 4.27.2 + 4.28.0 1.65.1 diff --git a/contribs/protobuf/pom.xml b/contribs/protobuf/pom.xml index a2c8a4ef62b..a08c2d527c8 100644 --- a/contribs/protobuf/pom.xml +++ b/contribs/protobuf/pom.xml @@ -11,7 +11,7 @@ protobuf - 4.27.2 + 4.28.0 From 358f5bca718c3675635a04ef3b46636b5e3023d7 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Tue, 3 Sep 2024 18:50:44 +0200 Subject: [PATCH 110/111] prebooking stop: check for expected pickups to prevent pickup and abandonment in the same second --- .../contrib/drt/prebooking/PrebookingStopActivity.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingStopActivity.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingStopActivity.java index 3c04ba985a3..e55af9e76a5 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingStopActivity.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/prebooking/PrebookingStopActivity.java @@ -206,8 +206,10 @@ protected void simStep(double now) { @Override public void notifyPassengersAreReadyForDeparture(List passengers, double now) { var request = getRequestForPassengers(passengers.stream().map(Identifiable::getId).toList()); - queuePickup(request, now); - expectedPickups.remove(request.getId()); + if(expectedPickups.containsKey(request.getId())) { + queuePickup(request, now); + expectedPickups.remove(request.getId()); + } } private AcceptedDrtRequest getRequestForPassengers(List> passengerIds) { From 7a5b1624df95242bd8896bd44c04fc3dc21d7f50 Mon Sep 17 00:00:00 2001 From: Tobias Kohl Date: Wed, 4 Sep 2024 16:31:27 +0200 Subject: [PATCH 111/111] fix parking proxy bug --- .../parkingproxy/CarEgressWalkChanger.java | 102 ++++++++++++------ .../parkingproxy/ParkingProxyModule.java | 4 +- 2 files changed, 72 insertions(+), 34 deletions(-) diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/CarEgressWalkChanger.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/CarEgressWalkChanger.java index ee231f716ed..20c0b113bed 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/CarEgressWalkChanger.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/CarEgressWalkChanger.java @@ -33,7 +33,7 @@ *

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

*

* More precisely, the class will...
@@ -49,13 +49,14 @@ * @author tkohl / Senozon * */ -class CarEgressWalkChanger implements BeforeMobsimListener, AfterMobsimListener { +class CarEgressWalkChanger implements BeforeMobsimListener { public static final String PENALTY_ATTRIBUTE = "parkingPenalty"; private final CarEgressWalkObserver observer; private final AccessEgressFinder egressFinder = new AccessEgressFinder(TransportMode.car); private final Iter0Method iter0Method; + private final CarEgressWalkBackChanger backChanger; /** * Sets the class up with the specified {@linkplain PenaltyGenerator} and {@linkplain PenaltyFunction}. @@ -66,6 +67,21 @@ class CarEgressWalkChanger implements BeforeMobsimListener, AfterMobsimListener public CarEgressWalkChanger(PenaltyGenerator penaltyGenerator, PenaltyFunction penaltyFunction, CarEgressWalkObserver observer, Iter0Method iter0Method) { this.observer = observer; this.iter0Method = iter0Method; + this.backChanger = new CarEgressWalkBackChanger(this); + } + + @Override + public double priority() { //we want this to happen very late, because it should only affect the mobsim, not other listeners + return -1001; + } + + /** + * Returns the class that changes the egress walks bag in AfterMobsim. Note that you need to bind this separately! + * + * @return the {@linkplain CarEgressWalkBackChanger} to this class + */ + public CarEgressWalkBackChanger getBackChanger() { + return this.backChanger; } /** @@ -93,33 +109,6 @@ public void notifyBeforeMobsim(BeforeMobsimEvent event) { this.changeEgressTimesByGridcell(event.getServices().getScenario().getPopulation().getPersons().values(), false); } } - - /** - * resets egress times before scoring / replanning - */ - @Override - public void notifyAfterMobsim(AfterMobsimEvent event) { - // we need to roll back the changes we made before the mobsim, otherwise we can't apply - // a different penalty next iteration. - if (event.getIteration() == 0) { - switch (this.iter0Method) { - case noPenalty: - case hourPenalty: - case estimateFromPlans: - this.changeEgressTimesByGridcell(event.getServices().getScenario().getPopulation().getPersons().values(), true); - break; - case takeFromAttributes: - this.changeEgressTimesByAttribute(event.getServices().getScenario().getPopulation().getPersons().values(), true); - break; - default: - throw new RuntimeException("Unknown iter0 mode"); - } - } else { - this.changeEgressTimesByGridcell(event.getServices().getScenario().getPopulation().getPersons().values(), true); - } - // yyyy this is something we do not like: to just "fake" something and take it back afterwards. Would be good to find some other design - // eventually. Not so obvious, though ... kai, mar'20 - } /** * Changes the egress times of all agents using cars according to the penalty for the corresponding space-time-gridcell and writes the penalty @@ -130,12 +119,13 @@ public void notifyAfterMobsim(AfterMobsimEvent event) { * by that time (calling this method twice, first with {@code false}, then with {@code true} should yield the original plans) */ private void changeEgressTimesByGridcell(Collection population, boolean reverse) { - int sign = reverse ? -1 : 1; for (Person p : population) { for (LegActPair walkActPair : this.egressFinder.findEgressWalks(p.getSelectedPlan())) { - double penalty = sign * this.observer.getPenaltyCalculator().getPenalty(walkActPair.leg.getDepartureTime().seconds(), walkActPair.act.getCoord()); - setTimes(walkActPair, penalty); - if (!reverse) { + double penalty = Math.round(this.observer.getPenaltyCalculator().getPenalty(walkActPair.leg.getDepartureTime().seconds(), walkActPair.act.getCoord())); + if (reverse) { + setTimes(walkActPair, -penalty); + } else { + setTimes(walkActPair, penalty); walkActPair.leg.getAttributes().putAttribute(PENALTY_ATTRIBUTE, penalty); } } @@ -171,4 +161,50 @@ private static void setTimes(LegActPair walkActPair, double penalty) { walkActPair.leg.getRoute().setTravelTime(walkActPair.leg.getRoute().getTravelTime().seconds() + penalty); walkActPair.act.setStartTime(walkActPair.act.getStartTime().seconds() + penalty); } + + /** + * The reverse to {@linkplain CarEgressWalkChanger} + * + * @author tkohl + * + */ + static class CarEgressWalkBackChanger implements AfterMobsimListener { + private final CarEgressWalkChanger forwardChanger; + + CarEgressWalkBackChanger(CarEgressWalkChanger forwardChanger) { + this.forwardChanger = forwardChanger; + } + + @Override + public double priority() { //we want this to happen very early to undo what we did before the mobsim before other listeners can pick it up + return 1001; + } + + /** + * resets egress times before scoring / replanning + */ + @Override + public void notifyAfterMobsim(AfterMobsimEvent event) { + // we need to roll back the changes we made before the mobsim, otherwise we can't apply + // a different penalty next iteration. + if (event.getIteration() == 0) { + switch (forwardChanger.iter0Method) { + case noPenalty: + case hourPenalty: + case estimateFromPlans: + forwardChanger.changeEgressTimesByGridcell(event.getServices().getScenario().getPopulation().getPersons().values(), true); + break; + case takeFromAttributes: + forwardChanger.changeEgressTimesByAttribute(event.getServices().getScenario().getPopulation().getPersons().values(), true); + break; + default: + throw new RuntimeException("Unknown iter0 mode"); + } + } else { + forwardChanger.changeEgressTimesByGridcell(event.getServices().getScenario().getPopulation().getPersons().values(), true); + } + // yyyy this is something we do not like: to just "fake" something and take it back afterwards. Would be good to find some other design + // eventually. Not so obvious, though ... kai, mar'20 + } + } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/ParkingProxyModule.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/ParkingProxyModule.java index f356f0911e8..41f179d4977 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/ParkingProxyModule.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/ParkingProxyModule.java @@ -92,7 +92,9 @@ public void install() { if (parkingConfig.getObserveOnly()) { super.addControlerListenerBinding().toInstance(walkObserver); } else { - super.addControlerListenerBinding().toInstance(new CarEgressWalkChanger(parkingHandler, penaltyFunction, walkObserver, parkingConfig.getIter0Method())); + CarEgressWalkChanger walkChanger = new CarEgressWalkChanger(parkingHandler, penaltyFunction, walkObserver, parkingConfig.getIter0Method()); + super.addControlerListenerBinding().toInstance(walkChanger); + super.addControlerListenerBinding().toInstance(walkChanger.getBackChanger()); } }