From 2ce5164d7c87aa8a8cd59fb4e4983342201c8979 Mon Sep 17 00:00:00 2001 From: simei94 <67737999+simei94@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:48:10 +0200 Subject: [PATCH 01/21] add dependency for geotools-api (#3302) --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index b6d1dece509..c23fbdfeb84 100644 --- a/pom.xml +++ b/pom.xml @@ -170,6 +170,11 @@ gt-epsg-extension ${geotools.version} + + org.geotools + gt-api + ${geotools.version} + org.geotools.jdbc gt-jdbc-postgis From 5b27550a3536084fe5cd6e41fb59d2067f3b8893 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 12:48:59 +0000 Subject: [PATCH 02/21] Bump org.hsqldb:hsqldb from 2.7.2 to 2.7.3 Bumps org.hsqldb:hsqldb from 2.7.2 to 2.7.3. --- updated-dependencies: - dependency-name: org.hsqldb:hsqldb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- contribs/freight/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribs/freight/pom.xml b/contribs/freight/pom.xml index 52eb3942031..e6bcdab4bb8 100644 --- a/contribs/freight/pom.xml +++ b/contribs/freight/pom.xml @@ -86,7 +86,7 @@ org.hsqldb hsqldb - 2.7.2 + 2.7.3 From 2fd7d6bab4e61396a17e288d3614c82abc9aa666 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 08:31:32 +0000 Subject: [PATCH 05/21] Bump geotools.version from 31.0 to 31.1 Bumps `geotools.version` from 31.0 to 31.1. Updates `org.geotools:gt-main` from 31.0 to 31.1 Updates `org.geotools:gt-referencing` from 31.0 to 31.1 Updates `org.geotools:gt-shapefile` from 31.0 to 31.1 Updates `org.geotools:gt-epsg-hsql` from 31.0 to 31.1 Updates `org.geotools:gt-epsg-extension` from 31.0 to 31.1 Updates `org.geotools:gt-api` from 31.0 to 31.1 Updates `org.geotools.jdbc:gt-jdbc-postgis` from 31.0 to 31.1 Updates `org.geotools:gt-geopkg` from 31.0 to 31.1 Updates `org.geotools:gt-geotiff` from 31.0 to 31.1 Updates `org.geotools:gt-geojson` from 31.0 to 31.1 Updates `org.geotools:gt-coverage` from 31.0 to 31.1 --- 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 1dc194a7b2d..3c90dead257 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 2.23.1 - 31.0 + 31.1 0.49.2 1.19.0 7.0.0 From 94932149537a04d3a38f4e197b32fb3fb804abb6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 08:31:32 +0000 Subject: [PATCH 06/21] build(deps): bump com.fasterxml.jackson:jackson-bom Bumps [com.fasterxml.jackson:jackson-bom](https://github.com/FasterXML/jackson-bom) from 2.16.2 to 2.17.1. - [Commits](https://github.com/FasterXML/jackson-bom/compare/jackson-bom-2.16.2...jackson-bom-2.17.1) --- updated-dependencies: - dependency-name: com.fasterxml.jackson:jackson-bom 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 1dc194a7b2d..9c4ad7ec7a5 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ 0.49.2 1.19.0 7.0.0 - 2.16.2 + 2.17.1 2.5.0 5.10.2 From 8e792c04f336233cc55ec0585876f58a568df58d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 14:58:16 +0000 Subject: [PATCH 07/21] Bump org.checkerframework:checker-qual from 3.43.0 to 3.44.0 Bumps [org.checkerframework:checker-qual](https://github.com/typetools/checker-framework) from 3.43.0 to 3.44.0. - [Release notes](https://github.com/typetools/checker-framework/releases) - [Changelog](https://github.com/typetools/checker-framework/blob/master/docs/CHANGELOG.md) - [Commits](https://github.com/typetools/checker-framework/compare/checker-framework-3.43.0...checker-framework-3.44.0) --- updated-dependencies: - dependency-name: org.checkerframework:checker-qual 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 1dc194a7b2d..1c2d66cdd39 100644 --- a/pom.xml +++ b/pom.xml @@ -296,7 +296,7 @@ org.checkerframework checker-qual - 3.43.0 + 3.44.0 From 78c849415ead0b72e6bc13b16973a720e7d4e31f Mon Sep 17 00:00:00 2001 From: Tobias Kohl Date: Thu, 6 Jun 2024 13:27:49 +0200 Subject: [PATCH 08/21] remove some confusing or unimplemented functionality --- .../LinearPenaltyFunctionWithCap.java | 6 +- .../parkingproxy/ParkingProxyModule.java | 72 +++++++------------ .../config/ParkingProxyConfigGroup.java | 28 +------- 3 files changed, 31 insertions(+), 75 deletions(-) diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/LinearPenaltyFunctionWithCap.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/LinearPenaltyFunctionWithCap.java index 810f7de6f35..af9b2fbb758 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/LinearPenaltyFunctionWithCap.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/LinearPenaltyFunctionWithCap.java @@ -31,17 +31,15 @@ class LinearPenaltyFunctionWithCap implements PenaltyFunction { private final double penaltyPerCar; private final double maxPenalty; - private final double areaFactor; - public LinearPenaltyFunctionWithCap(double gridSize, double penaltyPerCar, double maxPenalty) { + public LinearPenaltyFunctionWithCap(double penaltyPerCar, double maxPenalty) { this.penaltyPerCar = penaltyPerCar; this.maxPenalty = maxPenalty; - this.areaFactor = gridSize * gridSize / 2500.; } @Override public double calculatePenalty(int numberOfCars) { - return Math.max(Math.min(numberOfCars * penaltyPerCar / areaFactor, maxPenalty), 0); + return Math.max(Math.min(numberOfCars * penaltyPerCar, maxPenalty), 0); } } 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 8f83c20d126..f356f0911e8 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 @@ -44,6 +44,7 @@ */ public /*deliberately non-final*/ class ParkingProxyModule extends AbstractModule { + private final static int GRIDSIZE = 500; private final Scenario scenario; public ParkingProxyModule(Scenario scenario) { @@ -60,57 +61,38 @@ public void install() { initialLoad, parkingConfig.getTimeBinSize(), qsimEndTime, - parkingConfig.getGridSize() + GRIDSIZE ); - PenaltyFunction penaltyFunction = new LinearPenaltyFunctionWithCap(parkingConfig.getGridSize(), parkingConfig.getDelayPerCar(), parkingConfig.getMaxDelay()); + PenaltyFunction penaltyFunction = new LinearPenaltyFunctionWithCap(parkingConfig.getDelayPerCar(), parkingConfig.getMaxDelay()); //PenaltyFunction penaltyFunction = new ExponentialPenaltyFunctionWithCap(10, parkingConfig.getGridSize(), parkingConfig.getMaxDelay(), 360); - switch(parkingConfig.getCalculationMethod()) { - case none: + ParkingVehiclesCountEventHandler parkingHandler = new ParkingVehiclesCountEventHandler(carCounter, scenario.getNetwork(), parkingConfig.getScenarioScaleFactor()); + super.addEventHandlerBinding().toInstance(parkingHandler); + + CarEgressWalkObserver walkObserver; + switch (parkingConfig.getIter0Method()) { + case hourPenalty: + walkObserver = new CarEgressWalkObserver(parkingHandler, penaltyFunction, PenaltyCalculator.getDummyHourCalculator()); + break; + case noPenalty: + walkObserver = new CarEgressWalkObserver(parkingHandler, penaltyFunction, PenaltyCalculator.getDummyZeroCalculator()); break; - case events: - ParkingVehiclesCountEventHandler parkingHandler = new ParkingVehiclesCountEventHandler(carCounter, scenario.getNetwork(), parkingConfig.getScenarioScaleFactor()); - super.addEventHandlerBinding().toInstance(parkingHandler); - - CarEgressWalkObserver walkObserver; - switch (parkingConfig.getIter0Method()) { - case hourPenalty: - walkObserver = new CarEgressWalkObserver(parkingHandler, penaltyFunction, PenaltyCalculator.getDummyHourCalculator()); - break; - case noPenalty: - walkObserver = new CarEgressWalkObserver(parkingHandler, penaltyFunction, PenaltyCalculator.getDummyZeroCalculator()); - break; - case takeFromAttributes: - // CarEgressWalkChanger will handle this, we don't want to also change egress walks. Note that if it is observeOnly, the first iteration will put out zeros. - walkObserver = new CarEgressWalkObserver(parkingHandler, penaltyFunction, PenaltyCalculator.getDummyZeroCalculator()); - break; - case estimateFromPlans: - ParkingCounterByPlans plansCounter = new ParkingCounterByPlans(carCounter, parkingConfig.getScenarioScaleFactor()); - plansCounter.calculateByPopulation(scenario.getPopulation(), scenario.getNetwork()); - walkObserver = new CarEgressWalkObserver(parkingHandler, penaltyFunction, plansCounter.generatePenaltyCalculator()); - break; - default: - throw new RuntimeException("Unknown iter0 mode"); - } - if (parkingConfig.getObserveOnly()) { - super.addControlerListenerBinding().toInstance(walkObserver); - } else { - super.addControlerListenerBinding().toInstance(new CarEgressWalkChanger(parkingHandler, penaltyFunction, walkObserver, parkingConfig.getIter0Method())); - } + case takeFromAttributes: + // CarEgressWalkChanger will handle this, we don't want to also change egress walks. Note that if it is observeOnly, the first iteration will put out zeros. + walkObserver = new CarEgressWalkObserver(parkingHandler, penaltyFunction, PenaltyCalculator.getDummyZeroCalculator()); + break; + case estimateFromPlans: + ParkingCounterByPlans plansCounter = new ParkingCounterByPlans(carCounter, parkingConfig.getScenarioScaleFactor()); + plansCounter.calculateByPopulation(scenario.getPopulation(), scenario.getNetwork()); + walkObserver = new CarEgressWalkObserver(parkingHandler, penaltyFunction, plansCounter.generatePenaltyCalculator()); break; - case plans: - throw new RuntimeException("Mode \"plans\" is not working yet. Use \"events\" instead."); - /* - ParkingCounterByPlans planCounter = new ParkingCounterByPlans(carCounter, parkingConfig.getScenarioScaleFactor()); - super.addControlerListenerBinding().toInstance(planCounter); - if (parkingConfig.getObserveOnly()) { - super.addControlerListenerBinding().toInstance(new CarEgressWalkObserver(planCounter, penaltyFunction)); - } else { - super.addControlerListenerBinding().toInstance(new CarEgressWalkChanger(planCounter, penaltyFunction)); - } - break;*/ default: - throw new RuntimeException("Unsupported calculation method " + parkingConfig.getCalculationMethod()); + throw new RuntimeException("Unknown iter0 mode"); + } + if (parkingConfig.getObserveOnly()) { + super.addControlerListenerBinding().toInstance(walkObserver); + } else { + super.addControlerListenerBinding().toInstance(new CarEgressWalkChanger(parkingHandler, penaltyFunction, walkObserver, parkingConfig.getIter0Method())); } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/config/ParkingProxyConfigGroup.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/config/ParkingProxyConfigGroup.java index 060b072ecdc..0d0d0fec3af 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/config/ParkingProxyConfigGroup.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/config/ParkingProxyConfigGroup.java @@ -24,28 +24,23 @@ public class ParkingProxyConfigGroup extends ReflectiveConfigGroup { - public static enum CalculationMethod {none, events, plans}; public static enum Iter0Method {noPenalty, hourPenalty, takeFromAttributes, estimateFromPlans} public static final String GROUP_NAME = "parkingProxy"; - public static final String METHOD = "method"; public static final String ITER0 = "iter0"; public static final String OBSERVE_ONLY = "observeOnly"; public static final String DELAY_PER_CAR = "delayPerCar"; public static final String MAX_DELAY = "maxDelay"; public static final String SCALE_FACTOR = "scenarioScaleFactor"; public static final String TIME_BIN_SIZE = "timeBinSize"; - public static final String GRID_SIZE = "gridSize"; public static final String CARS_PER_1000_PERSONS = "carsPer1000Persons"; - private CalculationMethod method = CalculationMethod.events; private Iter0Method iter0Method = Iter0Method.hourPenalty; private boolean observeOnly = false; private double delayPerCar = 2.5; private double maxDelay = 900; private int scenarioScaleFactor = 100; private int timeBinSize = 900; - private int gridSize = 500; private int carsPer1000Persons = 500; public ParkingProxyConfigGroup() { @@ -58,22 +53,12 @@ public Map getComments() { comments.put(SCALE_FACTOR, "The inverse of the scenario perentage, i.e. the number with which to multiply the" + " number of agents to get the real life population, e.g. 4 in a 25% scenario. Needs to be an Intger," + " so in case of weird percentages (e.g. 1/3) please round."); - comments.put(DELAY_PER_CAR, "in seconds. Note that this should be scaled MANUALLY with the gridsize!"); - comments.put(MAX_DELAY, "in seconds. Note that this should be scaled MANUALLY with the gridsize!"); + comments.put(DELAY_PER_CAR, "in seconds"); + comments.put(MAX_DELAY, "in seconds"); comments.put(TIME_BIN_SIZE, "in seconds"); - comments.put(GRID_SIZE, "in CRS units, usually meters"); return comments; } - @StringGetter(METHOD) - public CalculationMethod getCalculationMethod() { - return this.method; - } - @StringSetter(METHOD) - public void setCalculationMethod(CalculationMethod method) { - this.method = method; - } - @StringGetter(ITER0) public Iter0Method getIter0Method() { return this.iter0Method; @@ -110,15 +95,6 @@ public void setMaxDelay(double maxDelay) { this.maxDelay = maxDelay; } - @StringGetter(GRID_SIZE) - public int getGridSize() { - return gridSize; - } - @StringSetter(GRID_SIZE) - public void setGridSize(int gridSize) { - this.gridSize = gridSize; - } - @StringGetter(TIME_BIN_SIZE) public int getTimeBinSize() { return timeBinSize; From 0ba57ce85f05da9834bd480cc283eabcbff2f6f3 Mon Sep 17 00:00:00 2001 From: marecabo <23156476+marecabo@users.noreply.github.com> Date: Thu, 6 Jun 2024 15:09:35 +0200 Subject: [PATCH 09/21] Use PriorityQueue for leaveTimes in PrebookingStopActivity --- .../prebooking/PrebookingStopActivity.java | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 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 1e1965d11a6..3551bb16a82 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 @@ -3,6 +3,8 @@ import java.util.HashSet; 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; @@ -38,7 +40,7 @@ public class PrebookingStopActivity extends FirstLastSimStepDynActivity implemen private final Map, ? extends AcceptedDrtRequest> dropoffRequests; private final IdMap enterTimes = new IdMap<>(Request.class); - private final IdMap leaveTimes = new IdMap<>(Request.class); + private final Queue leaveTimes = new PriorityQueue<>(); private final Set> enteredRequests = new HashSet<>(); private final PrebookingManager prebookingManager; @@ -84,27 +86,30 @@ protected void beforeFirstStep(double now) { private void initDropoffRequests(double now) { for (var request : dropoffRequests.values()) { double leaveTime = now + stopDurationProvider.calcDropoffDuration(vehicle, request.getRequest()); - leaveTimes.put(request.getId(), leaveTime); + leaveTimes.add(new RequestIdTime(request.getId(), leaveTime)); } updateDropoffRequests(now); } private boolean updateDropoffRequests(double now) { - var iterator = leaveTimes.entrySet().iterator(); - while (iterator.hasNext()) { - var entry = iterator.next(); - - if (entry.getValue() <= now) { // Request should leave now - passengerHandler.dropOffPassengers(driver, entry.getKey(), now); - prebookingManager.notifyDropoff(entry.getKey()); - onboard -= dropoffRequests.get(entry.getKey()).getPassengerCount(); - iterator.remove(); - } + while (!leaveTimes.isEmpty() && leaveTimes.peek().time <= now) { + RequestIdTime rit = leaveTimes.poll(); + passengerHandler.dropOffPassengers(driver, rit.id, now); + prebookingManager.notifyDropoff(rit.id); + onboard -= dropoffRequests.get(rit.id).getPassengerCount(); } - return leaveTimes.size() == 0; + return leaveTimes.isEmpty(); + } + + private record RequestIdTime(Id id, double time) implements Comparable { + + @Override + public int compareTo(RequestIdTime o) { + return Double.compare(this.time, o.time); + } } private boolean updatePickupRequests(double now) { From d3742de29805a1d94812cd0e22580f110e7dd776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20K=C3=BChnel?= Date: Fri, 7 Jun 2024 14:25:47 +0200 Subject: [PATCH 10/21] make header of detailed_distance_stats listen to custom delimiter (#3309) --- .../contrib/drt/analysis/DrtAnalysisControlerListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/DrtAnalysisControlerListener.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/DrtAnalysisControlerListener.java index 67ee1973686..3c50904db50 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/DrtAnalysisControlerListener.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/DrtAnalysisControlerListener.java @@ -365,7 +365,7 @@ private void writeIterationVehicleStats(String summarizeVehicles, String vehOcc, try (var bw = getAppendingBufferedWriter("drt_detailed_distanceStats", ".csv")) { if (!vheaderWritten) { vheaderWritten = true; - bw.write("runId;iteration"); + bw.write("runId" + delimiter + "iteration"); for (int i = 0; i <= maxcap; i++) { bw.write(delimiter + i + " pax distance_m"); } From 9d5f93a838b7d3dd3f36bff7135901949e48cc29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Fri, 7 Jun 2024 16:28:52 +0200 Subject: [PATCH 11/21] feat: construct srr connection map on-demand (#3289) --- .../config/SwissRailRaptorConfigGroup.java | 19 ++- .../routing/pt/raptor/RaptorStaticConfig.java | 25 ++++ .../matsim/routing/pt/raptor/RaptorUtils.java | 1 + .../pt/raptor/SwissRailRaptorCore.java | 13 +- .../pt/raptor/SwissRailRaptorData.java | 140 ++++++++++++++++-- .../MinimalTransferTimesImpl.java | 13 ++ .../api/MinimalTransferTimes.java | 4 + 7 files changed, 196 insertions(+), 19 deletions(-) diff --git a/matsim/src/main/java/ch/sbb/matsim/config/SwissRailRaptorConfigGroup.java b/matsim/src/main/java/ch/sbb/matsim/config/SwissRailRaptorConfigGroup.java index 3c8040a92fb..c5376acc84b 100644 --- a/matsim/src/main/java/ch/sbb/matsim/config/SwissRailRaptorConfigGroup.java +++ b/matsim/src/main/java/ch/sbb/matsim/config/SwissRailRaptorConfigGroup.java @@ -20,6 +20,9 @@ package ch.sbb.matsim.config; import com.google.common.base.Verify; + +import ch.sbb.matsim.routing.pt.raptor.RaptorStaticConfig.RaptorTransferCalculation; + import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -61,6 +64,8 @@ public class SwissRailRaptorConfigGroup extends ReflectiveConfigGroup { private static final String PARAM_TRANSFER_WALK_MARGIN_DESC = "time deducted from transfer walk leg during transfers between pt legs in order to avoid missing a vehicle by a few seconds due to delays."; private static final String PARAM_INTERMODAL_LEG_ONLYHANDLING = "intermodalLegOnlyHandling"; private static final String PARAM_INTERMODAL_LEG_ONLYHANDLING_DESC = "Define how routes containing only intermodal legs are handled: Useful options: alllow, avoid, forbid"; + private static final String PARAM_TRANSFER_CALCULATION = "transferCalculation"; + private static final String PARAM_TRANFER_CALCULATION_DESC = "Defines whether all potential transfers are precomputed at the beginning of the simulation (Initial) or whether they are constructed on-demand (Cached). The former incurs potentially long up-front caclulations, but quicker routing. The latter avoids any initial computation, but may require longer routing time."; private boolean useRangeQuery = false; private boolean useIntermodality = false; @@ -74,6 +79,7 @@ public class SwissRailRaptorConfigGroup extends ReflectiveConfigGroup { private double transferPenaltyHourlyCost = 0; private double transferWalkMargin = 5; private IntermodalLegOnlyHandling intermodalLegOnlyHandling = IntermodalLegOnlyHandling.forbid; + private RaptorTransferCalculation transferCalculation = RaptorTransferCalculation.Initial; private ScoringParameters scoringParameters = ScoringParameters.Default; @@ -128,9 +134,19 @@ public void setIntermodalLegOnlyHandling(IntermodalLegOnlyHandling intermodalLeg public String getIntermodalLegOnlyHandlingString() { return intermodalLegOnlyHandling.toString(); } - + public IntermodalLegOnlyHandling getIntermodalLegOnlyHandling() { return intermodalLegOnlyHandling; + } + + @StringSetter(PARAM_TRANSFER_CALCULATION) + public void setTransferCalculation(RaptorTransferCalculation transferCalculation) { + this.transferCalculation = transferCalculation; + } + + @StringGetter(PARAM_TRANSFER_CALCULATION) + public RaptorTransferCalculation getTransferCalculation() { + return transferCalculation; } @StringGetter(PARAM_USE_RANGE_QUERY) @@ -707,6 +723,7 @@ public Map getComments() { comments.put(PARAM_USE_CAPACITY_CONSTRAINTS, PARAM_USE_CAPACITY_CONSTRAINTS_DESC); comments.put(PARAM_TRANSFER_WALK_MARGIN, PARAM_TRANSFER_WALK_MARGIN_DESC); comments.put(PARAM_INTERMODAL_ACCESS_EGRESS_MODE_SELECTION,PARAM_INTERMODAL_ACCESS_EGRESS_MODE_SELECTION_DESC); + comments.put(PARAM_TRANSFER_CALCULATION, PARAM_TRANFER_CALCULATION_DESC); return comments; } diff --git a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorStaticConfig.java b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorStaticConfig.java index 20b94216349..8f49f121ab2 100644 --- a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorStaticConfig.java +++ b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorStaticConfig.java @@ -51,6 +51,22 @@ public enum RaptorOptimization { * (see {@link SwissRailRaptor#calcTree(TransitStopFacility, double, RaptorParameters, Person)} ). */ OneToAllRouting } + + public enum RaptorTransferCalculation { + /** + * Use this option if you want the algorithm to calculate all possible transfers + * up-front, which will allow for rapid lookup during routing, but may come with + * significant simulation startup time. + */ + Initial, + + /** + * Use this option if you want the algorithm to calculate transfers on demand, + * which avoids any simulation start-up time but may increase the routing time + * itself. + */ + Cached + } /** @@ -71,6 +87,7 @@ public enum RaptorOptimization { private boolean useCapacityConstraints = false; private RaptorOptimization optimization = RaptorOptimization.OneToOneRouting; + private RaptorTransferCalculation transferCalculation = RaptorTransferCalculation.Initial; private SwissRailRaptorConfigGroup.IntermodalLegOnlyHandling intermodalLegOnlyHandling = SwissRailRaptorConfigGroup.IntermodalLegOnlyHandling.forbid; @@ -167,4 +184,12 @@ public SwissRailRaptorConfigGroup.IntermodalLegOnlyHandling getIntermodalLegOnly public void setIntermodalLegOnlyHandling(SwissRailRaptorConfigGroup.IntermodalLegOnlyHandling intermodalLegOnlyHandling) { this.intermodalLegOnlyHandling = intermodalLegOnlyHandling; } + + public RaptorTransferCalculation getTransferCalculation() { + return this.transferCalculation; + } + + public void setTransferCalculation(RaptorTransferCalculation transferCalculation) { + this.transferCalculation = transferCalculation; + } } diff --git a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorUtils.java b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorUtils.java index f289b04e486..724af748454 100644 --- a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorUtils.java +++ b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorUtils.java @@ -63,6 +63,7 @@ public static RaptorStaticConfig createStaticConfig(Config config) { staticConfig.setTransferWalkMargin(srrConfig.getTransferWalkMargin()); staticConfig.setIntermodalLegOnlyHandling(srrConfig.getIntermodalLegOnlyHandling()); staticConfig.setMinimalTransferTime(config.transitRouter().getAdditionalTransferTime()); + staticConfig.setTransferCalculation(srrConfig.getTransferCalculation()); staticConfig.setUseModeMappingForPassengers(srrConfig.isUseModeMappingForPassengers()); if (srrConfig.isUseModeMappingForPassengers()) { diff --git a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java index 0242f5e91ab..37855f385f0 100644 --- a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java +++ b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java @@ -752,10 +752,17 @@ private void handleTransfers(boolean strict, RaptorParameters raptorParams) { continue; } RRouteStop fromRouteStop = fromPE.toRouteStop; // this is the route stop we arrive with least cost at stop - int firstTransferIndex = fromRouteStop.indexFirstTransfer; - int lastTransferIndex = firstTransferIndex + fromRouteStop.countTransfers; + + // obtain on-demand transfers if applicable (will return null if transfers are calculated initially) + RTransfer[] transfers = this.data.calculateTransfers(fromRouteStop); + + int firstTransferIndex = transfers == null ? fromRouteStop.indexFirstTransfer : 0; + int lastTransferIndex = transfers == null ? firstTransferIndex + fromRouteStop.countTransfers : transfers.length; + transfers = transfers == null ? this.data.transfers : transfers; + for (int transferIndex = firstTransferIndex; transferIndex < lastTransferIndex; transferIndex++) { - RTransfer transfer = this.data.transfers[transferIndex]; + RTransfer transfer = transfers[transferIndex]; + int toRouteStopIndex = transfer.toRouteStop; transferProvider.reset(transfer); int newArrivalTime = arrivalTime + transfer.transferTime; diff --git a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorData.java b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorData.java index 5abe7fb49e0..4813fafd95d 100644 --- a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorData.java +++ b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorData.java @@ -20,10 +20,26 @@ package ch.sbb.matsim.routing.pt.raptor; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Supplier; + +import javax.annotation.Nullable; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.IdMap; import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; @@ -41,18 +57,8 @@ import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.Vehicles; -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Supplier; +import ch.sbb.matsim.routing.pt.raptor.RaptorStaticConfig.RaptorOptimization; +import ch.sbb.matsim.routing.pt.raptor.RaptorStaticConfig.RaptorTransferCalculation; /** * @author mrieser / SBB @@ -75,12 +81,16 @@ public class SwissRailRaptorData { final QuadTree stopsQT; final Map>> stopFilterAttribute2Value2StopsQT; final OccupancyData occupancyData; + + // data needed if cached transfer construction is activated + final IdMap> staticTransferTimes; + final RTransfer[][] transferCache; private SwissRailRaptorData(RaptorStaticConfig config, int countStops, RRoute[] routes, int[] departures, Vehicle[] departureVehicles, Id[] departureIds, RRouteStop[] routeStops, RTransfer[] transfers, Map stopFacilityIndices, Map routeStopsPerStopFacility, QuadTree stopsQT, - OccupancyData occupancyData) { + OccupancyData occupancyData, IdMap> staticTransferTimes) { this.config = config; this.countStops = countStops; this.countRouteStops = routeStops.length; @@ -95,6 +105,10 @@ private SwissRailRaptorData(RaptorStaticConfig config, int countStops, this.stopsQT = stopsQT; this.stopFilterAttribute2Value2StopsQT = new HashMap<>(); this.occupancyData = occupancyData; + + // data needed if cached transfer construction is activated + this.staticTransferTimes = staticTransferTimes; + this.transferCache = new RTransfer[routeStops.length][]; } public static SwissRailRaptorData create(TransitSchedule schedule, @Nullable Vehicles transitVehicles, RaptorStaticConfig staticConfig, Network network, OccupancyData occupancyData) { @@ -200,7 +214,16 @@ public static SwissRailRaptorData create(TransitSchedule schedule, @Nullable Veh QuadTree stopsQT = TransitScheduleUtils.createQuadTreeOfTransitStopFacilities(stops); int countStopFacilities = stops.size(); - Map allTransfers = calculateRouteStopTransfers(schedule, stopsQT, routeStopsPerStopFacility, routeStops, staticConfig); + // if cached transfer calculation is active, don't generate any transfers here + final Map allTransfers; + + if (staticConfig.getTransferCalculation().equals(RaptorTransferCalculation.Initial)) { + allTransfers = calculateRouteStopTransfers(schedule, stopsQT, routeStopsPerStopFacility, routeStops, + staticConfig); + } else { + allTransfers = Collections.emptyMap(); + } + long countTransfers = 0; for (RTransfer[] transfers : allTransfers.values()) { countTransfers += transfers.length; @@ -221,8 +244,22 @@ public static SwissRailRaptorData create(TransitSchedule schedule, @Nullable Veh indexTransfer += transferCount; } } + + // if cached transfer calculation is used, build a map for quick lookup of minimal transfer times + IdMap> staticTransferTimes = null; + if (staticConfig.getTransferCalculation().equals(RaptorTransferCalculation.Cached)) { + staticTransferTimes = new IdMap<>(TransitStopFacility.class); - SwissRailRaptorData data = new SwissRailRaptorData(staticConfig, countStopFacilities, routes, departures, departureVehicles, departureIds, routeStops, transfers, stopFacilityIndices, routeStopsPerStopFacility, stopsQT, occupancyData); + MinimalTransferTimes.MinimalTransferTimesIterator iterator = schedule.getMinimalTransferTimes().iterator(); + while (iterator.hasNext()) { + iterator.next(); + + staticTransferTimes.computeIfAbsent(iterator.getFromStopId(), id -> new HashMap<>()) + .put(schedule.getFacilities().get(iterator.getToStopId()), iterator.getSeconds()); + } + } + + SwissRailRaptorData data = new SwissRailRaptorData(staticConfig, countStopFacilities, routes, departures, departureVehicles, departureIds, routeStops, transfers, stopFacilityIndices, routeStopsPerStopFacility, stopsQT, occupancyData, staticTransferTimes); long endMillis = System.currentTimeMillis(); log.info("SwissRailRaptor data preparation done. Took " + (endMillis - startMillis) / 1000 + " seconds."); @@ -604,4 +641,77 @@ public Transfer get() { return this.transfer; } } + + RTransfer[] calculateTransfers(RRouteStop fromRouteStop) { + if (config.getTransferCalculation().equals(RaptorTransferCalculation.Initial)) { + return null; + } + + // We tested this in a parallel set-up and things seem to work as they are + // implemented. The routing threads will access the cache as read-only an + // retrieve the cached stop connections. It can happen that two of them try to + // obtain a non-existent entry at the same time. In that case, the calculation + // is performed twice, but this is not critical. Then this function writes the + // connections into the cache. This is a replacement of one address in the array + // from null to a concrete value, and our tests show that this seems to appear + // as atomic to the using threads. However, it is not 100% excluded that there + // is some parallelization issue here and that we rather should shield the cache + // using a lock in some way. But so far, we didn't experience any problem. /sh + // may 2024 + + RTransfer[] cache = transferCache[fromRouteStop.index]; + if (cache != null) return cache; // we had a cache hit + + // setting up useful constants + final double minimalTransferTime = config.getMinimalTransferTime(); + final double beelineWalkConnectionDistance = config.getBeelineWalkConnectionDistance(); + final double beelineDistanceFactor = config.getBeelineWalkDistanceFactor(); + final double beelineWalkSpeed = config.getBeelineWalkSpeed(); + final RaptorOptimization optimization = config.getOptimization(); + + // the facility from which we want to transfer + TransitStopFacility fromRouteFacility = fromRouteStop.routeStop.getStopFacility(); + Collection transferCandidates = new LinkedList<>(); + + // find transfer candidates by distance + transferCandidates.addAll(stopsQT.getDisk(fromRouteFacility.getCoord().getX(), fromRouteFacility.getCoord().getY(), config.getBeelineWalkConnectionDistance())); + + // find transfer candidates with predefined transfer time + Map transferTimes = staticTransferTimes.get(fromRouteFacility.getId()); + + if (transferTimes != null) { // some transfer times are predefined + transferCandidates.addAll(transferTimes.keySet()); + } + + // now evaluate whether transfers are useful, distance, and travel time + List transfers = new LinkedList<>(); + for (TransitStopFacility toRouteFacility : transferCandidates) { + for (int toRouteStopIndex : routeStopsPerStopFacility.get(toRouteFacility)) { + RRouteStop toRouteStop = routeStops[toRouteStopIndex]; + + double beelineDistance = CoordUtils.calcEuclideanDistance(fromRouteFacility.getCoord(), toRouteFacility.getCoord()); + double transferTime = beelineDistance / beelineWalkSpeed; + + if (transferTime < minimalTransferTime) { + transferTime = minimalTransferTime; + } + + if (transferTimes != null) { + // check if we find a predefined transfer time + transferTime = transferTimes.getOrDefault(toRouteFacility, transferTime); + } + + if (SwissRailRaptorData.isUsefulTransfer(fromRouteStop, toRouteStop, beelineWalkConnectionDistance, optimization)) { + transfers.add(new RTransfer(fromRouteStop.index, toRouteStop.index, transferTime, beelineDistance * beelineDistanceFactor)); + } + } + } + + // convert to array + RTransfer[] stopTransfers = transfers.toArray(new RTransfer[transfers.size()]); + + // save to cache (no issue regarding parallel execution because we simply set an element) + transferCache[fromRouteStop.index] = stopTransfers; + return stopTransfers; + } } diff --git a/matsim/src/main/java/org/matsim/pt/transitSchedule/MinimalTransferTimesImpl.java b/matsim/src/main/java/org/matsim/pt/transitSchedule/MinimalTransferTimesImpl.java index f8e5bf92d9f..c78b1b1687e 100644 --- a/matsim/src/main/java/org/matsim/pt/transitSchedule/MinimalTransferTimesImpl.java +++ b/matsim/src/main/java/org/matsim/pt/transitSchedule/MinimalTransferTimesImpl.java @@ -19,9 +19,11 @@ package org.matsim.pt.transitSchedule; +import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.matsim.api.core.v01.Id; @@ -164,4 +166,15 @@ public double getSeconds() { throw new NoSuchElementException(); } } + + @Override + public Set> getCandidates(Id fromStop) { + var inner = minimalTransferTimes.get(fromStop); + + if (inner == null) { + return Collections.emptySet(); + } + + return inner.keySet(); + } } diff --git a/matsim/src/main/java/org/matsim/pt/transitSchedule/api/MinimalTransferTimes.java b/matsim/src/main/java/org/matsim/pt/transitSchedule/api/MinimalTransferTimes.java index 72819f5cf70..c567093f865 100644 --- a/matsim/src/main/java/org/matsim/pt/transitSchedule/api/MinimalTransferTimes.java +++ b/matsim/src/main/java/org/matsim/pt/transitSchedule/api/MinimalTransferTimes.java @@ -19,6 +19,8 @@ package org.matsim.pt.transitSchedule.api; +import java.util.Set; + import org.matsim.api.core.v01.Id; /** @@ -66,6 +68,8 @@ public interface MinimalTransferTimes { * @return the previously set minimal transfer time, or Double.NaN if none was set. */ double remove(Id fromStop, Id toStop); + + Set> getCandidates(Id fromStop); /** * @return an iterator to iterate over all minimal transfer times set. From db7d822addae8b6e8d86f33081864e0c13b4641e Mon Sep 17 00:00:00 2001 From: marecabo <23156476+marecabo@users.noreply.github.com> Date: Sat, 8 Jun 2024 09:33:15 +0200 Subject: [PATCH 12/21] Improve code from comments --- .../drt/prebooking/PrebookingStopActivity.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 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 3551bb16a82..762c80500b1 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 @@ -40,7 +40,7 @@ public class PrebookingStopActivity extends FirstLastSimStepDynActivity implemen private final Map, ? extends AcceptedDrtRequest> dropoffRequests; private final IdMap enterTimes = new IdMap<>(Request.class); - private final Queue leaveTimes = new PriorityQueue<>(); + private final Queue leaveTimes = new PriorityQueue<>(); private final Set> enteredRequests = new HashSet<>(); private final PrebookingManager prebookingManager; @@ -86,7 +86,7 @@ protected void beforeFirstStep(double now) { private void initDropoffRequests(double now) { for (var request : dropoffRequests.values()) { double leaveTime = now + stopDurationProvider.calcDropoffDuration(vehicle, request.getRequest()); - leaveTimes.add(new RequestIdTime(request.getId(), leaveTime)); + leaveTimes.add(new QueuedRequest(request.getId(), leaveTime)); } updateDropoffRequests(now); @@ -95,19 +95,19 @@ private void initDropoffRequests(double now) { private boolean updateDropoffRequests(double now) { while (!leaveTimes.isEmpty() && leaveTimes.peek().time <= now) { - RequestIdTime rit = leaveTimes.poll(); - passengerHandler.dropOffPassengers(driver, rit.id, now); - prebookingManager.notifyDropoff(rit.id); - onboard -= dropoffRequests.get(rit.id).getPassengerCount(); + Id requestId = leaveTimes.poll().id; + passengerHandler.dropOffPassengers(driver, requestId, now); + prebookingManager.notifyDropoff(requestId); + onboard -= dropoffRequests.get(requestId).getPassengerCount(); } return leaveTimes.isEmpty(); } - private record RequestIdTime(Id id, double time) implements Comparable { + private record QueuedRequest(Id id, double time) implements Comparable { @Override - public int compareTo(RequestIdTime o) { + public int compareTo(QueuedRequest o) { return Double.compare(this.time, o.time); } } From 44b4da19e4f4dbfaa5ca043e33fd8f5944dbf4eb Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Wed, 12 Jun 2024 15:42:38 +0200 Subject: [PATCH 13/21] use globally defined csv delimiter more consistently --- ...ftEfficiencyAnalysisControlerListener.java | 7 ++- .../h3/RunDrtWithH3ZonalSystemIT.java | 3 +- .../zonal/DrtModeZonalSystemModule.java | 2 +- .../zonal/DrtZonalWaitTimesAnalyzer.java | 53 +++++++++---------- .../DvrpBenchmarkTravelTimeModule.java | 3 +- .../DvrpOfflineTravelTimeEstimator.java | 20 ++++--- .../DvrpOfflineTravelTimes.java | 27 +++++----- .../DvrpTravelTimeModule.java | 3 +- .../DvrpOfflineTravelTimeEstimatorTest.java | 7 +-- .../DvrpOfflineTravelTimesTest.java | 6 ++- 10 files changed, 71 insertions(+), 60 deletions(-) diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyAnalysisControlerListener.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyAnalysisControlerListener.java index 57e451f31b0..9ea39e1a75f 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyAnalysisControlerListener.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyAnalysisControlerListener.java @@ -43,6 +43,8 @@ public final class ShiftEfficiencyAnalysisControlerListener implements Iteration private final DrtConfigGroup drtConfigGroup; private final ShiftEfficiencyTracker shiftEfficiencyTracker; + private final String delimiter; + @Inject public ShiftEfficiencyAnalysisControlerListener(DrtConfigGroup drtConfigGroup, ShiftEfficiencyTracker shiftEfficiencyTracker, @@ -52,6 +54,7 @@ public ShiftEfficiencyAnalysisControlerListener(DrtConfigGroup drtConfigGroup, this.shiftEfficiencyTracker = shiftEfficiencyTracker; this.drtShiftsSpecification = drtShiftsSpecification; this.matsimServices = matsimServices; + this.delimiter = matsimServices.getConfig().global().getDefaultDelimiter(); } @Override @@ -131,7 +134,7 @@ private String filename(IterationEndsEvent event, String prefix, String extensio .getIterationFilename(event.getIteration(), prefix + "_" + drtConfigGroup.getMode() + extension); } - private static String line(Object... cells) { - return Arrays.stream(cells).map(Object::toString).collect(Collectors.joining(";", "", "\n")); + private String line(Object... cells) { + return Arrays.stream(cells).map(Object::toString).collect(Collectors.joining(delimiter, "", "\n")); } } diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/RunDrtWithH3ZonalSystemIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/RunDrtWithH3ZonalSystemIT.java index d1ef4e2fea7..c79a868144f 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/RunDrtWithH3ZonalSystemIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/h3/RunDrtWithH3ZonalSystemIT.java @@ -61,13 +61,12 @@ public void install() { public void install() { bindModal(DrtZonalWaitTimesAnalyzer.class).toProvider(modalProvider( getter -> new DrtZonalWaitTimesAnalyzer(drtConfig, getter.getModal(DrtEventSequenceCollector.class), - getter.getModal(ZoneSystem.class)))).asEagerSingleton(); + getter.getModal(ZoneSystem.class), config.global().getDefaultDelimiter()))).asEagerSingleton(); addControlerListenerBinding().to(modalKey(DrtZonalWaitTimesAnalyzer.class)); } }); } }); - } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtModeZonalSystemModule.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtModeZonalSystemModule.java index 05129ba7faf..aebb8b44686 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtModeZonalSystemModule.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtModeZonalSystemModule.java @@ -90,7 +90,7 @@ public void install() { bindModal(DrtZonalWaitTimesAnalyzer.class).toProvider(modalProvider( getter -> new DrtZonalWaitTimesAnalyzer(drtCfg, getter.getModal(DrtEventSequenceCollector.class), - getter.getModal(ZoneSystem.class)))).asEagerSingleton(); + getter.getModal(ZoneSystem.class), getConfig().global().getDefaultDelimiter()))).asEagerSingleton(); addControlerListenerBinding().to(modalKey(DrtZonalWaitTimesAnalyzer.class)); } } diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalWaitTimesAnalyzer.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalWaitTimesAnalyzer.java index d16a0cd8e0a..ce140ce1772 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalWaitTimesAnalyzer.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZonalWaitTimesAnalyzer.java @@ -58,13 +58,16 @@ public final class DrtZonalWaitTimesAnalyzer implements IterationEndsListener, S private final ZoneSystem zones; private static final Id zoneIdForOutsideOfZonalSystem = Id.create("outsideOfDrtZonalSystem", Zone.class); private static final String notAvailableString = "NaN"; + + private final String delimiter; private static final Logger log = LogManager.getLogger(DrtZonalWaitTimesAnalyzer.class); public DrtZonalWaitTimesAnalyzer(DrtConfigGroup configGroup, DrtEventSequenceCollector requestAnalyzer, - ZoneSystem zones) { + ZoneSystem zones, String delimiter) { this.drtCfg = configGroup; this.requestAnalyzer = requestAnalyzer; this.zones = zones; + this.delimiter = delimiter; } @Override @@ -76,7 +79,6 @@ public void notifyIterationEnds(IterationEndsEvent event) { } public void write(String fileName) { - String delimiter = ";"; Map, DescriptiveStatistics> zoneStats = createZonalStats(); BufferedWriter bw = IOUtils.getBufferedWriter(fileName); try { @@ -85,7 +87,11 @@ public void write(String fileName) { format.setMinimumIntegerDigits(1); format.setMaximumFractionDigits(2); format.setGroupingUsed(false); - bw.append("zone;centerX;centerY;nRequests;sumWaitTime;meanWaitTime;min;max;p95;p90;p80;p75;p50"); + String header = new StringJoiner(delimiter) + .add("zone").add("centerX").add("centerY").add("nRequests") + .add("sumWaitTime").add("meanWaitTime").add("min").add("max") + .add("p95").add("p90").add("p80").add("p75").add("p50").toString(); + bw.append(header); // sorted output SortedSet> zoneIdsAndOutside = new TreeSet<>(zones.getZones().keySet()); zoneIdsAndOutside.add(zoneIdForOutsideOfZonalSystem); @@ -96,31 +102,22 @@ public void write(String fileName) { String centerY = drtZone != null ? String.valueOf(drtZone.getCentroid().getY()) : notAvailableString; DescriptiveStatistics stats = zoneStats.get(zoneId); bw.newLine(); - bw.append(zoneId.toString()) - .append(delimiter) - .append(centerX) - .append(delimiter) - .append(centerY) - .append(delimiter) - .append(format.format(stats.getN())) - .append(delimiter) - .append(format.format(stats.getSum())) - .append(delimiter) - .append(String.valueOf(stats.getMean())) - .append(delimiter) - .append(String.valueOf(stats.getMin())) - .append(delimiter) - .append(String.valueOf(stats.getMax())) - .append(delimiter) - .append(String.valueOf(stats.getPercentile(95))) - .append(delimiter) - .append(String.valueOf(stats.getPercentile(90))) - .append(delimiter) - .append(String.valueOf(stats.getPercentile(80))) - .append(delimiter) - .append(String.valueOf(stats.getPercentile(75))) - .append(delimiter) - .append(String.valueOf(stats.getPercentile(50))); + bw.append( + new StringJoiner(delimiter) + .add(zoneId.toString()) + .add(centerX) + .add(centerY) + .add(format.format(stats.getN())) + .add(format.format(stats.getSum())) + .add(String.valueOf(stats.getMean())) + .add(String.valueOf(stats.getMin())) + .add(String.valueOf(stats.getMax())) + .add(String.valueOf(stats.getPercentile(95))) + .add(String.valueOf(stats.getPercentile(90))) + .add(String.valueOf(stats.getPercentile(80))) + .add(String.valueOf(stats.getPercentile(75))) + .add(String.valueOf(stats.getPercentile(50))).toString() + ); } bw.flush(); bw.close(); diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/benchmark/DvrpBenchmarkTravelTimeModule.java b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/benchmark/DvrpBenchmarkTravelTimeModule.java index 7dad30dbd34..f46302a0d40 100644 --- a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/benchmark/DvrpBenchmarkTravelTimeModule.java +++ b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/benchmark/DvrpBenchmarkTravelTimeModule.java @@ -47,7 +47,8 @@ public void install() { addTravelTimeBinding(DvrpTravelTimeModule.DVRP_ESTIMATED).toProvider(() -> { URL url = ConfigGroup.getInputFileURL(getConfig().getContext(), dvrpCfg.initialTravelTimesFile); var timeDiscretizer = new TimeDiscretizer(getConfig().travelTimeCalculator()); - var linkTravelTimes = DvrpOfflineTravelTimes.loadLinkTravelTimes(timeDiscretizer, url); + var linkTravelTimes = DvrpOfflineTravelTimes.loadLinkTravelTimes(timeDiscretizer, url, + getConfig().global().getDefaultDelimiter()); return DvrpOfflineTravelTimes.asTravelTime(timeDiscretizer, linkTravelTimes); }).asEagerSingleton(); } else { diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpOfflineTravelTimeEstimator.java b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpOfflineTravelTimeEstimator.java index 33b22634347..5d80e161462 100644 --- a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpOfflineTravelTimeEstimator.java +++ b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpOfflineTravelTimeEstimator.java @@ -28,6 +28,7 @@ import org.matsim.contrib.dvrp.router.DvrpGlobalRoutingNetworkProvider; import org.matsim.contrib.dvrp.run.DvrpConfigGroup; import org.matsim.contrib.common.timeprofile.TimeDiscretizer; +import org.matsim.core.config.groups.GlobalConfigGroup; import org.matsim.core.config.groups.TravelTimeCalculatorConfigGroup; import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.core.controler.events.AfterMobsimEvent; @@ -63,18 +64,21 @@ public class DvrpOfflineTravelTimeEstimator private final double[][] linkTravelTimes; private final double alpha; + private final String delimiter; + @Inject public DvrpOfflineTravelTimeEstimator(@Named(DvrpTravelTimeModule.DVRP_INITIAL) TravelTime initialTT, - @Named(DvrpTravelTimeModule.DVRP_OBSERVED) TravelTime observedTT, - @Named(DvrpGlobalRoutingNetworkProvider.DVRP_ROUTING) Network network, - TravelTimeCalculatorConfigGroup ttCalcConfig, DvrpConfigGroup dvrpConfig, - OutputDirectoryHierarchy outputDirectoryHierarchy) { - this(initialTT, observedTT, network, new TimeDiscretizer(ttCalcConfig), dvrpConfig.travelTimeEstimationAlpha, outputDirectoryHierarchy); + @Named(DvrpTravelTimeModule.DVRP_OBSERVED) TravelTime observedTT, + @Named(DvrpGlobalRoutingNetworkProvider.DVRP_ROUTING) Network network, + TravelTimeCalculatorConfigGroup ttCalcConfig, DvrpConfigGroup dvrpConfig, + OutputDirectoryHierarchy outputDirectoryHierarchy, GlobalConfigGroup globalConfig) { + this(initialTT, observedTT, network, new TimeDiscretizer(ttCalcConfig), dvrpConfig.travelTimeEstimationAlpha, + outputDirectoryHierarchy, globalConfig.getDefaultDelimiter()); } public DvrpOfflineTravelTimeEstimator(TravelTime initialTT, TravelTime observedTT, Network network, TimeDiscretizer timeDiscretizer, double travelTimeEstimationAlpha, - OutputDirectoryHierarchy outputDirectoryHierarchy) { + OutputDirectoryHierarchy outputDirectoryHierarchy, String delimiter) { this.observedTT = observedTT; this.network = network; @@ -83,6 +87,7 @@ public DvrpOfflineTravelTimeEstimator(TravelTime initialTT, TravelTime observedT this.timeInterval = timeDiscretizer.getTimeInterval(); this.outputDirectoryHierarchy = outputDirectoryHierarchy; + this.delimiter = delimiter; alpha = travelTimeEstimationAlpha; checkArgument(alpha > 0 && alpha <= 1, "travelTimeEstimationAlpha must be in (0,1]"); @@ -115,7 +120,8 @@ public void notifyMobsimBeforeCleanup(@SuppressWarnings("rawtypes") MobsimBefore @Override public void notifyAfterMobsim(AfterMobsimEvent event) { DvrpOfflineTravelTimes.saveLinkTravelTimes(timeDiscretizer, linkTravelTimes, - outputDirectoryHierarchy.getIterationFilename(event.getIteration(), "dvrp_travel_times.csv.gz")); + outputDirectoryHierarchy.getIterationFilename(event.getIteration(), + "dvrp_travel_times.csv.gz"), delimiter); } private void updateTTs(TravelTime travelTime, double alpha) { diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpOfflineTravelTimes.java b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpOfflineTravelTimes.java index 67882267db2..d8bc99c89b1 100644 --- a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpOfflineTravelTimes.java +++ b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpOfflineTravelTimes.java @@ -41,25 +41,25 @@ * @author Michal Maciejewski (michalm) */ public class DvrpOfflineTravelTimes { - private static final String DELIMITER = ";"; public static void saveLinkTravelTimes(TimeDiscretizer timeDiscretizer, double[][] linkTravelTimes, - String filename) { + String filename, String delimiter) { try (Writer writer = IOUtils.getBufferedWriter(filename)) { - saveLinkTravelTimes(timeDiscretizer, linkTravelTimes, writer); + saveLinkTravelTimes(timeDiscretizer, linkTravelTimes, writer, delimiter); } catch (IOException e) { throw new RuntimeException(e); } } - public static void saveLinkTravelTimes(TimeDiscretizer timeDiscretizer, double[][] linkTravelTimes, Writer writer) + public static void saveLinkTravelTimes(TimeDiscretizer timeDiscretizer, double[][] linkTravelTimes, + Writer writer, String delimiter) throws IOException { int intervalCount = timeDiscretizer.getIntervalCount(); //header row - writer.append("linkId" + DELIMITER); + writer.append("linkId").append(delimiter); for (int i = 0; i < intervalCount; i++) { double time = i * timeDiscretizer.getTimeInterval(); - writer.append(time + DELIMITER); + writer.append(String.valueOf(time)).append(delimiter); } writer.append('\n'); @@ -71,12 +71,12 @@ public static void saveLinkTravelTimes(TimeDiscretizer timeDiscretizer, double[] if (ttRow != null) { checkArgument(ttRow.length == intervalCount); - writer.append(Id.get(idx, Link.class) + DELIMITER); + writer.append(String.valueOf(Id.get(idx, Link.class))).append(delimiter); for (int t = 0; t < intervalCount; t++) { // rounding up to full seconds, otherwise the output files are sometimes huge (even when gzipped) // consider having a switch for enabling/disabling rounding int tt = (int)Math.ceil(ttRow[t]);//rounding up to avoid zeros; also QSim rounds up - writer.append(tt + DELIMITER); + writer.append(String.valueOf(tt)).append(delimiter); } writer.append('\n'); } @@ -101,27 +101,28 @@ public static TravelTime asTravelTime(TimeDiscretizer timeDiscretizer, double[][ }; } - public static double[][] loadLinkTravelTimes(TimeDiscretizer timeDiscretizer, URL url) { + public static double[][] loadLinkTravelTimes(TimeDiscretizer timeDiscretizer, URL url, String delimiter) { try (BufferedReader reader = IOUtils.getBufferedReader(url)) { - return loadLinkTravelTimes(timeDiscretizer, reader); + return loadLinkTravelTimes(timeDiscretizer, reader, delimiter); } catch (IOException e) { throw new RuntimeException(e); } } - public static double[][] loadLinkTravelTimes(TimeDiscretizer timeDiscretizer, BufferedReader reader) + public static double[][] loadLinkTravelTimes(TimeDiscretizer timeDiscretizer, BufferedReader reader, + String delimiter) throws IOException { //start with IdMap and then convert to array (to avoid index out of bounds) IdMap linkTravelTimes = new IdMap<>(Link.class); //header row - String[] headerLine = reader.readLine().split(";"); + String[] headerLine = reader.readLine().split(delimiter); verify(timeDiscretizer.getIntervalCount() == headerLine.length - 1); verify(headerLine[0].equals("linkId")); timeDiscretizer.forEach((bin, time) -> verify(Double.parseDouble(headerLine[bin + 1]) == time)); //regular rows - reader.lines().map(line -> line.split(DELIMITER)).forEach(cells -> { + reader.lines().map(line -> line.split(delimiter)).forEach(cells -> { verify(timeDiscretizer.getIntervalCount() == cells.length - 1); double[] row = new double[timeDiscretizer.getIntervalCount()]; diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpTravelTimeModule.java b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpTravelTimeModule.java index 798ac1166c1..c295c70ac6a 100644 --- a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpTravelTimeModule.java +++ b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpTravelTimeModule.java @@ -48,7 +48,8 @@ public void install() { addTravelTimeBinding(DvrpTravelTimeModule.DVRP_INITIAL).toProvider(() -> { URL url = ConfigGroup.getInputFileURL(getConfig().getContext(), dvrpCfg.initialTravelTimesFile); var timeDiscretizer = new TimeDiscretizer(getConfig().travelTimeCalculator()); - var linkTravelTimes = DvrpOfflineTravelTimes.loadLinkTravelTimes(timeDiscretizer, url); + var linkTravelTimes = DvrpOfflineTravelTimes.loadLinkTravelTimes(timeDiscretizer, url, + getConfig().global().getDefaultDelimiter()); return DvrpOfflineTravelTimes.asTravelTime(timeDiscretizer, linkTravelTimes); }).asEagerSingleton(); } else { diff --git a/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpOfflineTravelTimeEstimatorTest.java b/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpOfflineTravelTimeEstimatorTest.java index 808df1ff835..2260a2f0979 100644 --- a/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpOfflineTravelTimeEstimatorTest.java +++ b/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpOfflineTravelTimeEstimatorTest.java @@ -61,7 +61,7 @@ public class DvrpOfflineTravelTimeEstimatorTest { @Test void getLinkTravelTime_timeAreCorrectlyBinned() { - var estimator = new DvrpOfflineTravelTimeEstimator(initialTT, null, network, timeDiscretizer, 0.25, null); + var estimator = new DvrpOfflineTravelTimeEstimator(initialTT, null, network, timeDiscretizer, 0.25, null, ";"); //bin 0 assertThat(linkTravelTime(estimator, linkAB, -1)).isEqualTo(1); @@ -98,7 +98,7 @@ void getLinkTravelTime_exponentialAveragingOverIterations() { }; var estimator = new DvrpOfflineTravelTimeEstimator(initialTT, observedTT, network, timeDiscretizer, alpha, - null); + null,";"); //expected TTs for each time bin double expectedTT_0 = 1; @@ -125,7 +125,8 @@ void getLinkTravelTime_exponentialAveragingOverIterations() { @Test void getLinkTravelTime_linkOutsideNetwork_fail() { var linkOutsideNetwork = new FakeLink(Id.createLinkId("some-link")); - var estimator = new DvrpOfflineTravelTimeEstimator(initialTT, null, network, timeDiscretizer, 0.25, null); + var estimator = new DvrpOfflineTravelTimeEstimator(initialTT, null, network, timeDiscretizer, + 0.25, null, ";"); assertThatThrownBy(() -> linkTravelTime(estimator, linkOutsideNetwork, 0)).isExactlyInstanceOf( NullPointerException.class) diff --git a/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpOfflineTravelTimesTest.java b/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpOfflineTravelTimesTest.java index e3b904d4084..f8270e2f8b3 100644 --- a/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpOfflineTravelTimesTest.java +++ b/contribs/dvrp/src/test/java/org/matsim/contrib/dvrp/trafficmonitoring/DvrpOfflineTravelTimesTest.java @@ -59,7 +59,8 @@ void saveLinkTravelTimes() throws IOException { linkTTs[linkIdB.index()] = new double[] { 5.5, 6.6, 7.7, 8.8, 9.9 }; var stringWriter = new StringWriter(); - DvrpOfflineTravelTimes.saveLinkTravelTimes(new TimeDiscretizer(3600, 900), linkTTs, stringWriter); + DvrpOfflineTravelTimes.saveLinkTravelTimes(new TimeDiscretizer(3600, 900), + linkTTs, stringWriter, ";"); var lines = stringWriter.toString().split("\n"); assertThat(lines).hasSize(3); @@ -76,7 +77,8 @@ void loadLinkTravelTimes() throws IOException { var lines = String.join("\n", line0, line1, line2); var stringReader = new BufferedReader(new StringReader(lines)); - var linkTTs = DvrpOfflineTravelTimes.loadLinkTravelTimes(new TimeDiscretizer(3600, 900), stringReader); + var linkTTs = DvrpOfflineTravelTimes.loadLinkTravelTimes(new TimeDiscretizer(3600, 900), + stringReader, ";"); //the matrix may have more than 2 rows (depends on how many link ids are cached) //all rows are null (except for links A and B) From 8d23274f4d541cf1bbe38811a994b33dd8b291bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Jun 2024 14:33:15 +0000 Subject: [PATCH 14/21] Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.3 to 3.7.0 Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.3 to 3.7.0. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.3...maven-javadoc-plugin-3.7.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin 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 1c2d66cdd39..98907107783 100644 --- a/pom.xml +++ b/pom.xml @@ -450,7 +450,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.6.3 + 3.7.0 org.codehaus.mojo From 9cbec8bc5d6f7b19bc70af804e615ec34864824f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Jun 2024 14:47:06 +0000 Subject: [PATCH 15/21] Bump com.google.guava:guava from 33.2.0-jre to 33.2.1-jre Bumps [com.google.guava:guava](https://github.com/google/guava) from 33.2.0-jre to 33.2.1-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) --- updated-dependencies: - dependency-name: com.google.guava:guava 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 1c2d66cdd39..cb15146370a 100644 --- a/pom.xml +++ b/pom.xml @@ -103,7 +103,7 @@ com.google.guava guava - 33.2.0-jre + 33.2.1-jre org.apache.commons From 24d54d3aa65a3d1cb85dac82e484ffec4a9bb4f1 Mon Sep 17 00:00:00 2001 From: u229187 Date: Thu, 13 Jun 2024 10:56:45 +0200 Subject: [PATCH 16/21] change quotation marks in test file --- .../input/org/matsim/simwrapper/viz/PlotlyTest/multiple.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contribs/simwrapper/test/input/org/matsim/simwrapper/viz/PlotlyTest/multiple.yaml b/contribs/simwrapper/test/input/org/matsim/simwrapper/viz/PlotlyTest/multiple.yaml index 69e91fd0d56..9430e2d0711 100644 --- a/contribs/simwrapper/test/input/org/matsim/simwrapper/viz/PlotlyTest/multiple.yaml +++ b/contribs/simwrapper/test/input/org/matsim/simwrapper/viz/PlotlyTest/multiple.yaml @@ -36,7 +36,7 @@ traces: font: fontfamily: Open Sans size: 12 - color: '#444' + color: "#444" namelength: 15 line: width: 1.0 @@ -53,7 +53,7 @@ traces: whiskerwidth: 0.0 decreasing: changeline: - color: '#3D9970' + color: "#3D9970" width: 10 type: scatter - x: [] From abbfc70964446472d2a3868e4b3db9626e9a5d8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20K=C3=BChnel?= Date: Thu, 13 Jun 2024 10:58:03 +0200 Subject: [PATCH 17/21] Add drt shift efficiency iteration stats (#3314) --- ...ftEfficiencyAnalysisControlerListener.java | 89 +++++++++++++++++-- .../efficiency/ShiftEfficiencyTracker.java | 2 +- .../shifts/run/RunShiftDrtScenarioIT.java | 6 ++ 3 files changed, 91 insertions(+), 6 deletions(-) diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyAnalysisControlerListener.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyAnalysisControlerListener.java index 9ea39e1a75f..6dc1a10ce81 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyAnalysisControlerListener.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyAnalysisControlerListener.java @@ -10,6 +10,7 @@ package org.matsim.contrib.drt.extension.operations.shifts.analysis.efficiency; import com.google.inject.Inject; +import jakarta.inject.Provider; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartUtils; import org.jfree.chart.JFreeChart; @@ -27,7 +28,7 @@ import org.matsim.core.controler.listener.IterationEndsListener; import org.matsim.core.utils.io.IOUtils; -import jakarta.inject.Provider; +import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.IOException; import java.util.*; @@ -44,6 +45,10 @@ public final class ShiftEfficiencyAnalysisControlerListener implements Iteration private final ShiftEfficiencyTracker shiftEfficiencyTracker; private final String delimiter; + private final String runId; + private boolean headerWritten = false; + private static final String notAvailableString = "NA"; + @Inject public ShiftEfficiencyAnalysisControlerListener(DrtConfigGroup drtConfigGroup, @@ -55,6 +60,7 @@ public ShiftEfficiencyAnalysisControlerListener(DrtConfigGroup drtConfigGroup, this.drtShiftsSpecification = drtShiftsSpecification; this.matsimServices = matsimServices; this.delimiter = matsimServices.getConfig().global().getDefaultDelimiter(); + this.runId = Optional.ofNullable(matsimServices.getConfig().controller().getRunId()).orElse(notAvailableString); } @Override @@ -62,14 +68,57 @@ public void notifyIterationEnds(IterationEndsEvent event) { int createGraphsInterval = event.getServices().getConfig().controller().getCreateGraphsInterval(); boolean createGraphs = createGraphsInterval >0 && event.getIteration() % createGraphsInterval == 0; - writeAndPlotShiftEfficiency( - shiftEfficiencyTracker.getCurrentRecord().getRevenueByShift(), - shiftEfficiencyTracker.getCurrentRecord().getRequestsByShift(), - shiftEfficiencyTracker.getCurrentRecord().getFinishedShifts(), + ShiftEfficiencyTracker.Record record = shiftEfficiencyTracker.getCurrentRecord(); + writeAndPlotShiftEfficiency( + record.getRevenueByShift(), + record.getRequestsByShift(), + record.getFinishedShifts(), filename(event, "shiftRevenue", ".png"), filename(event, "shiftRidesPerVrh", ".png"), filename(event, "shiftEfficiency", ".csv"), createGraphs); + + List finishedShifts = record.finishedShifts() + .keySet() + .stream() + .map(id -> drtShiftsSpecification.get().getShiftSpecifications().get(id)) + .toList(); + + double earliestShiftStart = finishedShifts.stream().map(DrtShiftSpecification::getStartTime).mapToDouble(d -> d).min().orElse(Double.NaN); + double latestShiftEnd = finishedShifts.stream().map(DrtShiftSpecification::getEndTime).mapToDouble(d -> d).min().orElse(Double.NaN); + + double numberOfShifts = finishedShifts.size(); + double numberOfShiftHours = finishedShifts. + stream() + .map(s -> (s.getEndTime() - s.getStartTime()) - (s.getBreak().isPresent() ? s.getBreak().get().getDuration() : 0.)) + .mapToDouble(d -> d) + .sum() / 3600.; + + long uniqueVehicles = record.getFinishedShifts().values().stream().distinct().count(); + + double totalRevenue = record.revenueByShift().values().stream().mapToDouble(d -> d).sum(); + double meanRevenuePerShift = record.revenueByShift().values().stream().mapToDouble(d -> d).average().orElse(Double.NaN); + double meanRevenuePerShiftHour = totalRevenue / numberOfShiftHours; + + double totalRides = record.getRequestsByShift().values().stream().mapToDouble(List::size).sum(); + double meanRidesPerShift = record.getRequestsByShift().values().stream().mapToDouble(List::size).average().orElse(Double.NaN); + double meanRidesPerShiftHour = totalRides / numberOfShiftHours; + + StringJoiner stringJoiner = new StringJoiner(delimiter); + stringJoiner + .add(earliestShiftStart + "") + .add(latestShiftEnd + "") + .add(numberOfShifts + "") + .add(numberOfShiftHours + "") + .add(uniqueVehicles + "") + .add(meanRevenuePerShift + "") + .add(meanRevenuePerShiftHour + "") + .add(totalRevenue + "") + .add(meanRidesPerShift + "") + .add(meanRidesPerShiftHour + "") + .add(totalRides + ""); + writeIterationShiftEfficiencyStats(stringJoiner.toString(), event.getIteration()); + } private void writeAndPlotShiftEfficiency(Map, Double> revenuePerShift, @@ -129,6 +178,32 @@ private void writeAndPlotShiftEfficiency(Map, Double> revenuePerShi } } + private void writeIterationShiftEfficiencyStats(String summarizeShiftEfficiency, int it) { + try (var bw = getAppendingBufferedWriter("drt_shift_efficiency_metrics", ".csv")) { + if (!headerWritten) { + headerWritten = true; + StringJoiner stringJoiner = new StringJoiner(delimiter); + stringJoiner + .add("earliestShiftStart") + .add("latestShiftEnd") + .add("numberOfShifts") + .add("numberOfShiftHours") + .add("uniqueVehicles") + .add("meanRevenuePerShift") + .add("meanRevenuePerShiftHour") + .add("totalRevenue") + .add("meanRidesPerShift") + .add("meanRidesPerShiftHour") + .add("totalRides"); + bw.write(line("runId", "iteration", stringJoiner.toString())); + } + bw.write(runId + delimiter + it + delimiter + summarizeShiftEfficiency); + bw.newLine(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + private String filename(IterationEndsEvent event, String prefix, String extension) { return matsimServices.getControlerIO() .getIterationFilename(event.getIteration(), prefix + "_" + drtConfigGroup.getMode() + extension); @@ -137,4 +212,8 @@ private String filename(IterationEndsEvent event, String prefix, String extensio private String line(Object... cells) { return Arrays.stream(cells).map(Object::toString).collect(Collectors.joining(delimiter, "", "\n")); } + + private BufferedWriter getAppendingBufferedWriter(String prefix, String extension) { + return IOUtils.getAppendingBufferedWriter(matsimServices.getControlerIO().getOutputFilename(prefix + "_" + drtConfigGroup.getMode() + extension)); + } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyTracker.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyTracker.java index ce4c39a882b..7ccb1edbbfc 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyTracker.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyTracker.java @@ -45,7 +45,7 @@ public final class ShiftEfficiencyTracker implements PersonMoneyEventHandler, private Record currentRecord; - public static record Record(Map, Double> revenueByShift, + public record Record(Map, Double> revenueByShift, Map, Id> shiftByRequest, Map, Id> finishedShifts){ public Map, Double> getRevenueByShift() { diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunShiftDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunShiftDrtScenarioIT.java index c2b671c90e7..522aff3db1b 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunShiftDrtScenarioIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunShiftDrtScenarioIT.java @@ -9,6 +9,7 @@ import org.matsim.contrib.drt.extension.operations.DrtWithOperationsConfigGroup; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesParams; import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; +import org.matsim.contrib.drt.fare.DrtFareParams; import org.matsim.contrib.drt.optimizer.DrtOptimizationConstraintsSet; import org.matsim.contrib.drt.optimizer.insertion.extensive.ExtensiveInsertionSearchParams; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams; @@ -142,6 +143,11 @@ void test() { 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.run(); } From 757d9d6fc5c8ed5df130c0c568ec35701297efa6 Mon Sep 17 00:00:00 2001 From: schlenther Date: Thu, 13 Jun 2024 13:34:33 +0200 Subject: [PATCH 18/21] MatsimVehicleReader: provide more meaningful error message --- .../main/java/org/matsim/vehicles/MatsimVehicleReader.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/matsim/src/main/java/org/matsim/vehicles/MatsimVehicleReader.java b/matsim/src/main/java/org/matsim/vehicles/MatsimVehicleReader.java index 069d90dba83..f22edb704b4 100644 --- a/matsim/src/main/java/org/matsim/vehicles/MatsimVehicleReader.java +++ b/matsim/src/main/java/org/matsim/vehicles/MatsimVehicleReader.java @@ -83,6 +83,11 @@ public void startTag(final String name, final Attributes atts, final Stack Date: Thu, 13 Jun 2024 13:41:43 +0200 Subject: [PATCH 19/21] NoiseAnalysis: specifically read output_vehicles --- .../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 8238eec25da..eb76c273c61 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 @@ -110,7 +110,8 @@ public Integer call() throws Exception { private Config prepareConfig() { Config config = ConfigUtils.loadConfig(ApplicationUtils.matchInput("config.xml", input.getRunDirectory()).toAbsolutePath().toString(), new NoiseConfigGroup()); - config.vehicles().setVehiclesFile(ApplicationUtils.matchInput("vehicles", input.getRunDirectory()).toAbsolutePath().toString()); + //it is important to match "output_vehicles" because otherwise dvrpVehicle files might be matched and the code crashes later + config.vehicles().setVehiclesFile(ApplicationUtils.matchInput("output_vehicles", input.getRunDirectory()).toAbsolutePath().toString()); config.network().setInputFile(ApplicationUtils.matchInput("network", input.getRunDirectory()).toAbsolutePath().toString()); config.transit().setTransitScheduleFile(null); config.transit().setVehiclesFile(null); From 4390f0a626c29a8bd562ed619d5c7a69e34d6722 Mon Sep 17 00:00:00 2001 From: u229187 Date: Thu, 13 Jun 2024 15:31:23 +0200 Subject: [PATCH 20/21] add a fixme and comment out API change in LinkTurnDirectionAttributesFromGraphHopper --- .../LinkTurnDirectionAttributesFromGraphHopper.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contribs/vsp/src/main/java/playground/vsp/flowEfficiency/LinkTurnDirectionAttributesFromGraphHopper.java b/contribs/vsp/src/main/java/playground/vsp/flowEfficiency/LinkTurnDirectionAttributesFromGraphHopper.java index eaddca54ee5..dccd3716f6c 100644 --- a/contribs/vsp/src/main/java/playground/vsp/flowEfficiency/LinkTurnDirectionAttributesFromGraphHopper.java +++ b/contribs/vsp/src/main/java/playground/vsp/flowEfficiency/LinkTurnDirectionAttributesFromGraphHopper.java @@ -26,6 +26,7 @@ import com.graphhopper.ResponsePath; import com.graphhopper.config.CHProfile; import com.graphhopper.config.Profile; +import com.graphhopper.util.CustomModel; import com.graphhopper.util.Instruction; import com.graphhopper.util.InstructionList; import org.apache.logging.log4j.LogManager; @@ -162,7 +163,8 @@ private static GraphHopper createGraphHopperInstance(String ghLoc) { hopper.setGraphHopperLocation("target/routing-graph-cache"); // see docs/core/profiles.md to learn more about profiles - hopper.setProfiles(new Profile("car").setVehicle("car").setWeighting("fastest").setTurnCosts(false)); + //fixme: "Graphhopper profiles have changed" + //hopper.setProfiles(new Profile("car").setCustomModel(new CustomModel()).setWeighting("fastest").setTurnCosts(false)); // this enables speed mode for the profile we called car hopper.getCHPreparationHandler().setCHProfiles(new CHProfile("car")); From d0dae9b3b819079f11cc8cf6bfcc198e48ca41e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 14:29:04 +0000 Subject: [PATCH 21/21] Bump com.google.protobuf:protobuf-java from 4.27.0 to 4.27.1 Bumps [com.google.protobuf:protobuf-java](https://github.com/protocolbuffers/protobuf) from 4.27.0 to 4.27.1. - [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-patch ... 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 fa6c86d2f52..a94a59e4058 100644 --- a/contribs/hybridsim/pom.xml +++ b/contribs/hybridsim/pom.xml @@ -10,7 +10,7 @@ hybridsim - 4.27.0 + 4.27.1 1.64.0 diff --git a/contribs/protobuf/pom.xml b/contribs/protobuf/pom.xml index a824085d737..b93c87b1246 100644 --- a/contribs/protobuf/pom.xml +++ b/contribs/protobuf/pom.xml @@ -11,7 +11,7 @@ protobuf - 4.27.0 + 4.27.1