From 486644026977f1a0b1e2c7dfea916c2162250bbc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Feb 2024 14:46:22 +0000 Subject: [PATCH 01/15] build(deps): bump log4j.version from 2.22.1 to 2.23.0 Bumps `log4j.version` from 2.22.1 to 2.23.0. Updates `org.apache.logging.log4j:log4j-api` from 2.22.1 to 2.23.0 Updates `org.apache.logging.log4j:log4j-core` from 2.22.1 to 2.23.0 Updates `org.apache.logging.log4j:log4j-slf4j2-impl` from 2.22.1 to 2.23.0 --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-api dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-slf4j2-impl 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 8f8e6e86576..37708358923 100644 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ 17 - 2.22.1 + 2.23.0 29.2 0.49.2 1.19.0 From e1a2cb713e2757518a0ad3dc2a230a9dd5f72f9d Mon Sep 17 00:00:00 2001 From: rakow Date: Wed, 21 Feb 2024 18:17:45 +0100 Subject: [PATCH 02/15] Update pebble dependency (#3126) * pin updated pebble version * exclude old pebble version * exclude some unneeded dependencies --- contribs/application/pom.xml | 13 +++++++++++++ .../application/analysis/traffic/LinkStats.java | 2 +- .../application/prepare/CreateLandUseShp.java | 4 ++-- contribs/simwrapper/pom.xml | 12 ++++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/contribs/application/pom.xml b/contribs/application/pom.xml index 546d465e7d2..f15326461c8 100644 --- a/contribs/application/pom.xml +++ b/contribs/application/pom.xml @@ -79,6 +79,7 @@ gtfs2matsim master-33809c4f0f-1 + org.geotools * @@ -87,6 +88,18 @@ org.matsim * + + com.amazonaws + * + + + com.graphql-java + * + + + org.postgresql + * + diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/traffic/LinkStats.java b/contribs/application/src/main/java/org/matsim/application/analysis/traffic/LinkStats.java index 09c3e910238..f5e2abbb323 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/traffic/LinkStats.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/traffic/LinkStats.java @@ -1,6 +1,6 @@ package org.matsim.application.analysis.traffic; -import com.beust.jcommander.internal.Lists; +import com.google.common.collect.Lists; import it.unimi.dsi.fastutil.doubles.DoubleArrayList; import it.unimi.dsi.fastutil.doubles.DoubleList; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/CreateLandUseShp.java b/contribs/application/src/main/java/org/matsim/application/prepare/CreateLandUseShp.java index c2abbfe1ae3..4f10c61e745 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/CreateLandUseShp.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/CreateLandUseShp.java @@ -1,6 +1,5 @@ package org.matsim.application.prepare; -import com.beust.jcommander.internal.Lists; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.geotools.data.DataStore; @@ -24,6 +23,7 @@ import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; @@ -90,7 +90,7 @@ public Integer call() throws Exception { STRtree index = new STRtree(); boolean built = false; - List paths = Lists.newArrayList(); + List paths =new ArrayList<>(); if (input.toString().endsWith("zip")) { FileSystem fs = FileSystems.newFileSystem(input, ClassLoader.getSystemClassLoader()); for (String l : layer) { diff --git a/contribs/simwrapper/pom.xml b/contribs/simwrapper/pom.xml index 26bff793134..b7557529aec 100644 --- a/contribs/simwrapper/pom.xml +++ b/contribs/simwrapper/pom.xml @@ -38,6 +38,18 @@ tech.tablesaw tablesaw-jsplot + + + io.pebbletemplates + pebble + + + + + + io.pebbletemplates + pebble + 3.1.6 From c6c9c5cc9f6211278b2dc3b81516a8f6a4450b60 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Thu, 22 Feb 2024 14:27:42 +0100 Subject: [PATCH 03/15] use specific randoms to make results reproducible --- ...rateSmallScaleCommercialTrafficDemand.java | 13 ++--- .../TrafficVolumeGeneration.java | 2 +- .../TripDistributionMatrix.java | 18 +++---- .../ValueSelectorUnderGivenProbability.java | 4 +- ...nerateSmallScaleCommercialTrafficTest.java | 47 ++++++++++-------- .../TripDistributionMatrixTest.java | 4 +- ...mercialPersonTraffic_startPerZone_10pt.csv | 4 ++ ...mmercialPersonTraffic_stopPerZone_10pt.csv | 4 ++ .../dataDistributionPerZone.csv | 4 ++ ...commercialPersonTraffic_total_purpose1.csv | 4 ++ ...commercialPersonTraffic_total_purpose2.csv | 4 ++ ...commercialPersonTraffic_total_purpose3.csv | 4 ++ ...commercialPersonTraffic_total_purpose4.csv | 4 ++ ...commercialPersonTraffic_total_purpose5.csv | 4 ++ .../test.output_events.xml.gz | Bin 0 -> 35753 bytes 15 files changed, 80 insertions(+), 40 deletions(-) create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_commercialPersonTraffic_startPerZone_10pt.csv create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_commercialPersonTraffic_stopPerZone_10pt.csv create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/dataDistributionPerZone.csv create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose1.csv create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose2.csv create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose3.csv create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose4.csv create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose5.csv create mode 100644 contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/test.output_events.xml.gz 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 46ec4a745b6..724763e26fc 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 @@ -39,6 +39,7 @@ import org.matsim.application.options.ShpOptions; import org.matsim.application.options.ShpOptions.Index; import org.matsim.core.config.consistency.UnmaterializedConfigGroupChecker; +import org.matsim.core.gbl.MatsimRandom; import org.matsim.core.scenario.ProjectionUtils; import org.matsim.core.utils.geometry.CoordUtils; import org.matsim.core.utils.geometry.CoordinateTransformation; @@ -491,8 +492,8 @@ private Config readAndCheckConfig(Path configPath, String modelName, String samp new OutputDirectoryHierarchy(config.controller().getOutputDirectory(), config.controller().getRunId(), config.controller().getOverwriteFileSetting(), ControllerConfigGroup.CompressionType.gzip); new File(Path.of(config.controller().getOutputDirectory()).resolve("calculatedData").toString()).mkdir(); - rnd = new Random(config.global().getRandomSeed()); - + MatsimRandom.getRandom().setSeed(config.global().getRandomSeed()); + rnd = MatsimRandom.getRandom(); if (config.network().getInputFile() == null) throw new Exception("No network file in config"); if (config.global().getCoordinateSystem() == null) @@ -950,13 +951,13 @@ private TripDistributionMatrix createTripDistribution( String smallScaleCommercialTrafficType, Scenario scenario, Path output, Map, Link>> regionLinksMap) throws Exception { - final TripDistributionMatrix odMatrix = TripDistributionMatrix.Builder - .newInstance(indexZones, trafficVolume_start, trafficVolume_stop, smallScaleCommercialTrafficType).build(); - List listOfZones = new ArrayList<>(); + ArrayList listOfZones = new ArrayList<>(); trafficVolume_start.forEach((k, v) -> { if (!listOfZones.contains(k.getZone())) listOfZones.add(k.getZone()); }); + final TripDistributionMatrix odMatrix = TripDistributionMatrix.Builder + .newInstance(indexZones, trafficVolume_start, trafficVolume_stop, smallScaleCommercialTrafficType, listOfZones).build(); Network network = scenario.getNetwork(); int count = 0; @@ -968,7 +969,7 @@ private TripDistributionMatrix createTripDistribution( String startZone = trafficVolumeKey.getZone(); String modeORvehType = trafficVolumeKey.getModeORvehType(); for (Integer purpose : trafficVolume_start.get(trafficVolumeKey).keySet()) { - Collections.shuffle(listOfZones); + Collections.shuffle(listOfZones, rnd); for (String stopZone : listOfZones) { odMatrix.setTripDistributionValue(startZone, stopZone, modeORvehType, purpose, smallScaleCommercialTrafficType, network, regionLinksMap, resistanceFactor); diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java index 7e9e591eabc..a4633cfaf10 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TrafficVolumeGeneration.java @@ -406,7 +406,7 @@ private static void reduceVolumeForOtherArea( Integer purpose, String volumeType, String originalZone) { ArrayList shuffledKeys = new ArrayList<>( trafficVolumePerTypeAndZone.keySet()); - Collections.shuffle(shuffledKeys); + Collections.shuffle(shuffledKeys, MatsimRandom.getRandom()); for (TrafficVolumeKey trafficVolumeKey : shuffledKeys) { if (trafficVolumeKey.getModeORvehType().equals(modeORvehType) && trafficVolumePerTypeAndZone.get(trafficVolumeKey).getDouble(purpose) > 0) { diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java index 7d631a6b96d..99def962079 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java @@ -33,6 +33,7 @@ import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; import org.matsim.application.options.ShpOptions.Index; +import org.matsim.core.gbl.MatsimRandom; import org.matsim.core.utils.io.IOUtils; import org.matsim.freight.carriers.jsprit.NetworkBasedTransportCosts; import org.matsim.smallScaleCommercialTrafficGeneration.TrafficVolumeGeneration.TrafficVolumeKey; @@ -60,7 +61,7 @@ public class TripDistributionMatrix { private static final Logger log = LogManager.getLogger(TripDistributionMatrix.class); private static final Joiner JOIN = Joiner.on("\t"); - private final ArrayList listOfZones = new ArrayList<>(); + private final ArrayList listOfZones; private final ArrayList listOfModesORvehTypes = new ArrayList<>(); private final ArrayList listOfPurposes = new ArrayList<>(); private final List zonesFeatures; @@ -238,23 +239,25 @@ public static class Builder { private final Map> trafficVolume_start; private final Map> trafficVolume_stop; private final String smallScaleCommercialTrafficType; + private final ArrayList listOfZones; public static Builder newInstance(Index indexZones, Map> trafficVolume_start, Map> trafficVolume_stop, - String smallScaleCommercialTrafficType) { - return new Builder(indexZones, trafficVolume_start, trafficVolume_stop, smallScaleCommercialTrafficType); + String smallScaleCommercialTrafficType, ArrayList listOfZones) { + return new Builder(indexZones, trafficVolume_start, trafficVolume_stop, smallScaleCommercialTrafficType, listOfZones); } private Builder(Index indexZones, Map> trafficVolume_start, Map> trafficVolume_stop, - String smallScaleCommercialTrafficType) { + String smallScaleCommercialTrafficType, ArrayList listOfZones) { super(); this.zonesFeatures = indexZones.getAllFeatures(); this.trafficVolume_start = trafficVolume_start; this.trafficVolume_stop = trafficVolume_stop; this.smallScaleCommercialTrafficType = smallScaleCommercialTrafficType; + this.listOfZones = new ArrayList<>(listOfZones); } public TripDistributionMatrix build() { @@ -267,6 +270,7 @@ private TripDistributionMatrix(Builder builder) { trafficVolume_start = builder.trafficVolume_start; trafficVolume_stop = builder.trafficVolume_stop; smallScaleCommercialTrafficType = builder.smallScaleCommercialTrafficType; + listOfZones = builder.listOfZones; } private final ConcurrentHashMap matrixCache = new ConcurrentHashMap<>(); @@ -309,10 +313,6 @@ void setTripDistributionValue(String startZone, String stopZone, String modeORve roundedVolume++; roundingError.get(stopZone).merge((modeORvehType + "_" + purpose), -1, Double::sum); } - if (!listOfZones.contains(startZone)) - listOfZones.add(startZone); - if (!listOfZones.contains(stopZone)) - listOfZones.add(stopZone); } else roundedVolume = 0; TripDistributionMatrixKey matrixKey = makeKey(startZone, stopZone, modeORvehType, purpose, smallScaleCommercialTrafficType); @@ -412,7 +412,7 @@ void clearRoundingError() { smallScaleCommercialTrafficType); } else { ArrayList shuffledZones = new ArrayList<>(getListOfZones()); - Collections.shuffle(shuffledZones); + Collections.shuffle(shuffledZones, MatsimRandom.getRandom()); for (String startZone : shuffledZones) { TripDistributionMatrixKey matrixKey = makeKey(startZone, stopZone, modeORvehType, purpose, smallScaleCommercialTrafficType); 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 index f0aff20d0e1..01446db9c0c 100644 --- 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 @@ -45,8 +45,8 @@ private void weightedProbability() { sum += l.getProbability(); cumulativeProbabilities.add(sum); } - //Generate a random number between 0 and 1 - double r = Math.random() * 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 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 62127e7e2f5..d88d2318fd1 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 @@ -25,14 +25,16 @@ import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.Population; -import org.matsim.freight.carriers.FreightCarriersConfigGroup; -import org.matsim.freight.carriers.Carrier; -import org.matsim.freight.carriers.CarriersUtils; 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.scenario.ScenarioUtils; +import org.matsim.freight.carriers.Carrier; +import org.matsim.freight.carriers.CarriersUtils; +import org.matsim.freight.carriers.FreightCarriersConfigGroup; import org.matsim.testcases.MatsimTestUtils; +import org.matsim.utils.eventsfilecomparison.EventsFileComparator; import java.io.File; import java.util.Objects; @@ -59,6 +61,7 @@ void testMainRunAndResults() { String buildingsShapeFileName = utils.getPackageInputDirectory() + "/shp/testBuildings.shp"; String landuseShapeFileName = utils.getPackageInputDirectory() + "/shp/testLanduse.shp"; String shapeCRS = "EPSG:4326"; + String resultPopulation = "testPopulation.xml.gz"; new GenerateSmallScaleCommercialTrafficDemand().execute( inputDataDirectory, @@ -71,36 +74,25 @@ void testMainRunAndResults() { "--zoneShapeFileName", zoneShapeFileName, "--buildingsShapeFileName", buildingsShapeFileName, "--landuseShapeFileName", landuseShapeFileName, - "--shapeCRS", shapeCRS); + "--shapeCRS", shapeCRS, + "--nameOutputPopulation", resultPopulation, + "--pathOutput", output); // test results of complete run before Config config = ConfigUtils.createConfig(); Scenario scenarioWOSolution = ScenarioUtils.createScenario(config); Scenario scenarioWSolution = ScenarioUtils.createScenario(config); - File outputFolder = Objects.requireNonNull(new File(output).listFiles())[0]; - Population population = null; - String carriersWOSolutionFileLocation = null; - String carriersWSolutionFileLocation = null; + Population population = PopulationUtils.readPopulation(utils.getOutputDirectory() + "testPopulation.xml.gz"); + String carriersWOSolutionFileLocation = utils.getOutputDirectory() + "test.output_CarrierDemand.xml"; + String carriersWSolutionFileLocation = utils.getOutputDirectory() + "test.output_CarrierDemandWithPlans.xml"; FreightCarriersConfigGroup freightCarriersConfigGroup = ConfigUtils.addOrGetModule(config, FreightCarriersConfigGroup.class); - - for (File outputFiles : Objects.requireNonNull(Objects.requireNonNull(outputFolder.listFiles())[0].listFiles())) { - - if (outputFiles.getName().contains("pct_plans.xml.gz")) - population = PopulationUtils.readPopulation(outputFiles.getPath()); - if (outputFiles.getName().contains("output_CarrierDemand.xml")) - carriersWOSolutionFileLocation = outputFiles.getPath(); - if (outputFiles.getName().contains("output_CarrierDemandWithPlans.xml")) - carriersWSolutionFileLocation = outputFiles.getPath(); - if (outputFiles.getName().contains("output_carriersVehicleTypes.xml.gz")) - freightCarriersConfigGroup.setCarriersVehicleTypesFile(outputFiles.getPath()); - } + freightCarriersConfigGroup.setCarriersVehicleTypesFile(utils.getOutputDirectory() + "test.output_carriersVehicleTypes.xml.gz"); freightCarriersConfigGroup.setCarriersFile(carriersWOSolutionFileLocation); CarriersUtils.loadCarriersAccordingToFreightConfig(scenarioWOSolution); freightCarriersConfigGroup.setCarriersFile(carriersWSolutionFileLocation); CarriersUtils.loadCarriersAccordingToFreightConfig(scenarioWSolution); - assert population != null; for (Person person : population.getPersons().values()) { Assertions.assertNotNull(person.getSelectedPlan()); Assertions.assertTrue(person.getAttributes().getAsMap().containsKey("tourStartArea")); @@ -116,5 +108,18 @@ void testMainRunAndResults() { countedTours += carrier_withSolution.getSelectedPlan().getScheduledTours().size(); } Assertions.assertEquals(population.getPersons().size(), countedTours, 0); + + for (File caculatedFile : Objects.requireNonNull( + Objects.requireNonNull(new File(utils.getOutputDirectory() + "calculatedData").listFiles()))) { + MatsimTestUtils.assertEqualFilesLineByLine( + utils.getPackageInputDirectory() + "calculatedData/" + caculatedFile.getName(), + caculatedFile.getAbsolutePath()); + } + + // compare events + String expected = utils.getPackageInputDirectory() + "test.output_events.xml.gz" ; + String actual = utils.getOutputDirectory() + "test.output_events.xml.gz" ; + EventsFileComparator.Result result = EventsUtils.compareEventsFiles( expected, actual ); + Assertions.assertEquals( EventsFileComparator.Result.FILES_ARE_EQUAL, result ); } } diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java index adc41f61191..2520cc95888 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java @@ -75,8 +75,10 @@ void testTripDistributionCommercialPersonTrafficTraffic() throws IOException { .createTrafficVolume_start(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); Map> trafficVolumePerTypeAndZone_stop = TrafficVolumeGeneration .createTrafficVolume_stop(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); + ArrayList listOfZones = new ArrayList<>( List.of("testArea1_area1", "testArea1_area2", "testArea2_area3")); final TripDistributionMatrix odMatrix = TripDistributionMatrix.Builder - .newInstance(getZoneIndex(inputDataDirectory), trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop, usedTrafficType).build(); + .newInstance(getZoneIndex(inputDataDirectory), trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop, usedTrafficType, + listOfZones).build(); Map, Link>> regionLinksMap = new HashMap<>(); regionLinksMap.put("testArea1_area1", new HashMap<>()); diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_commercialPersonTraffic_startPerZone_10pt.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_commercialPersonTraffic_startPerZone_10pt.csv new file mode 100644 index 00000000000..bfdf8e63f8c --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_commercialPersonTraffic_startPerZone_10pt.csv @@ -0,0 +1,4 @@ +areaID mode/vehType 1 2 3 4 5 +testArea2_area3 total 1 3 8 6 9 +testArea1_area2 total 3 21 51 44 63 +testArea1_area1 total 3 12 28 18 25 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_commercialPersonTraffic_stopPerZone_10pt.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_commercialPersonTraffic_stopPerZone_10pt.csv new file mode 100644 index 00000000000..0c53286d73b --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/TrafficVolume_commercialPersonTraffic_stopPerZone_10pt.csv @@ -0,0 +1,4 @@ +areaID mode/vehType 1 2 3 4 5 +testArea2_area3 total 0 3 13 4 2 +testArea1_area2 total 1 20 86 25 10 +testArea1_area1 total 1 10 43 12 6 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/dataDistributionPerZone.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/dataDistributionPerZone.csv new file mode 100644 index 00000000000..70857ece6c1 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/dataDistributionPerZone.csv @@ -0,0 +1,4 @@ +areaID areaName Inhabitants Employee Employee Primary Sector Employee Construction Employee Secondary Sector Rest Employee Retail Employee Traffic/Parcels Employee Tertiary Sector Rest +testArea1_area2 area2 4000 6500 500 1500 500 500 1500 2000 +testArea2_area3 area3 800 1000 50 200 100 150 200 300 +testArea1_area1 area1 4000 3500 0 500 500 1000 500 1000 \ No newline at end of file diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose1.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose1.csv new file mode 100644 index 00000000000..38573c7f4c0 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose1.csv @@ -0,0 +1,4 @@ + testArea2_area3 testArea1_area2 testArea1_area1 +testArea2_area3 0 0 0 +testArea1_area2 0 1 0 +testArea1_area1 0 0 1 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose2.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose2.csv new file mode 100644 index 00000000000..30cf57e5fc3 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose2.csv @@ -0,0 +1,4 @@ + testArea2_area3 testArea1_area2 testArea1_area1 +testArea2_area3 0 0 0 +testArea1_area2 0 8 7 +testArea1_area1 1 5 3 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose3.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose3.csv new file mode 100644 index 00000000000..44108374c44 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose3.csv @@ -0,0 +1,4 @@ + testArea2_area3 testArea1_area2 testArea1_area1 +testArea2_area3 2 7 3 +testArea1_area2 7 52 25 +testArea1_area1 4 27 15 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose4.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose4.csv new file mode 100644 index 00000000000..6cebadd2f70 --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose4.csv @@ -0,0 +1,4 @@ + testArea2_area3 testArea1_area2 testArea1_area1 +testArea2_area3 0 2 2 +testArea1_area2 2 17 7 +testArea1_area1 2 6 3 diff --git a/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose5.csv b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose5.csv new file mode 100644 index 00000000000..5d7cb865fbf --- /dev/null +++ b/contribs/small-scale-traffic-generation/test/input/org/matsim/smallScaleCommercialTrafficGeneration/calculatedData/odMatrix_commercialPersonTraffic_total_purpose5.csv @@ -0,0 +1,4 @@ + testArea2_area3 testArea1_area2 testArea1_area1 +testArea2_area3 0 0 0 +testArea1_area2 1 7 4 +testArea1_area1 1 3 2 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 new file mode 100644 index 0000000000000000000000000000000000000000..a3f7231747b670ea68e7ba42dd8450140bb559ba GIT binary patch literal 35753 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 literal 0 HcmV?d00001 From 06a2fbbcd8dd4ca713eada1b1e79f78c3d293589 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Thu, 22 Feb 2024 14:28:16 +0100 Subject: [PATCH 04/15] use specific randoms to make results reproducible --- .../TripDistributionMatrixTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java index 2520cc95888..0cf215c836c 100644 --- a/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java +++ b/contribs/small-scale-traffic-generation/src/test/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrixTest.java @@ -157,6 +157,8 @@ void testTripDistributionGoodsTraffic() throws IOException { ArrayList modesORvehTypes = new ArrayList( Arrays.asList("vehTyp1", "vehTyp2", "vehTyp3", "vehTyp4", "vehTyp5")); + ArrayList listOfZones = new ArrayList<>( List.of("testArea1_area1", "testArea1_area2", "testArea2_area3")); + TrafficVolumeGeneration.setInputParameters(usedTrafficType); Map> trafficVolumePerTypeAndZone_start = TrafficVolumeGeneration @@ -164,7 +166,8 @@ void testTripDistributionGoodsTraffic() throws IOException { Map> trafficVolumePerTypeAndZone_stop = TrafficVolumeGeneration .createTrafficVolume_stop(resultingDataPerZone, output, sample, modesORvehTypes, usedTrafficType); final TripDistributionMatrix odMatrix = TripDistributionMatrix.Builder - .newInstance(getZoneIndex(inputDataDirectory), trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop, usedTrafficType).build(); + .newInstance(getZoneIndex(inputDataDirectory), trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop, usedTrafficType, + listOfZones).build(); Map, Link>> regionLinksMap = new HashMap<>(); regionLinksMap.put("testArea1_area1", new HashMap<>()); From 6c4d48263111ec444258869d92dcc371091301c5 Mon Sep 17 00:00:00 2001 From: Ricardo Ewert Date: Thu, 22 Feb 2024 14:29:41 +0100 Subject: [PATCH 05/15] cleanup --- .../GenerateSmallScaleCommercialTrafficDemand.java | 14 ++++++-------- .../TripDistributionMatrix.java | 10 ---------- .../ValueSelectorUnderGivenProbability.java | 8 -------- 3 files changed, 6 insertions(+), 26 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 724763e26fc..b15a3d7d99c 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 @@ -228,8 +228,6 @@ public Integer call() throws Exception { } Path inputDataDirectory = Path.of(config.getContext().toURI()).getParent(); - ShpOptions shpZones = new ShpOptions(shapeFileZonePath, shapeCRS, StandardCharsets.UTF_8); - indexZones = SmallScaleCommercialTrafficUtils.getIndexZones(shapeFileZonePath, shapeCRS); indexBuildings = SmallScaleCommercialTrafficUtils.getIndexBuildings(shapeFileBuildingsPath, shapeCRS); indexLanduse = SmallScaleCommercialTrafficUtils.getIndexLanduse(shapeFileLandusePath, shapeCRS); @@ -243,14 +241,14 @@ public Integer call() throws Exception { switch (usedSmallScaleCommercialTrafficType) { case commercialPersonTraffic, goodsTraffic -> - createCarriersAndDemand(output, scenario, shpZones, resultingDataPerZone, regionLinksMap, + createCarriersAndDemand(output, scenario, resultingDataPerZone, regionLinksMap, usedSmallScaleCommercialTrafficType.toString(), includeExistingModels); case completeSmallScaleCommercialTraffic -> { - createCarriersAndDemand(output, scenario, shpZones, resultingDataPerZone, regionLinksMap, "commercialPersonTraffic", + createCarriersAndDemand(output, scenario, resultingDataPerZone, regionLinksMap, "commercialPersonTraffic", includeExistingModels); includeExistingModels = false; // because already included in the step before - createCarriersAndDemand(output, scenario, shpZones, resultingDataPerZone, regionLinksMap, "goodsTraffic", + createCarriersAndDemand(output, scenario, resultingDataPerZone, regionLinksMap, "goodsTraffic", includeExistingModels); } default -> throw new RuntimeException("No traffic type selected."); @@ -424,7 +422,7 @@ private void solveSeparatedVRPs(Scenario originalScenario, Map> resultingDataPerZone, Map, Link>> regionLinksMap, String smallScaleCommercialTrafficType, boolean includeExistingModels) throws Exception { @@ -451,7 +449,7 @@ else if (smallScaleCommercialTrafficType.equals("commercialPersonTraffic")) trafficVolumePerTypeAndZone_start, trafficVolumePerTypeAndZone_stop); } final TripDistributionMatrix odMatrix = createTripDistribution(trafficVolumePerTypeAndZone_start, - trafficVolumePerTypeAndZone_stop, shpZones, smallScaleCommercialTrafficType, scenario, output, regionLinksMap); + trafficVolumePerTypeAndZone_stop, smallScaleCommercialTrafficType, scenario, output, regionLinksMap); createCarriers(scenario, odMatrix, resultingDataPerZone, smallScaleCommercialTrafficType, regionLinksMap); } @@ -947,7 +945,7 @@ private static void findNearestLinkForZonesWithoutLinks(Network networkToChange, */ private TripDistributionMatrix createTripDistribution( Map> trafficVolume_start, - Map> trafficVolume_stop, ShpOptions shpZones, + Map> trafficVolume_stop, String smallScaleCommercialTrafficType, Scenario scenario, Path output, Map, Link>> regionLinksMap) throws Exception { diff --git a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java index 99def962079..ce06aa2b34c 100644 --- a/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java +++ b/contribs/small-scale-traffic-generation/src/main/java/org/matsim/smallScaleCommercialTrafficGeneration/TripDistributionMatrix.java @@ -519,16 +519,6 @@ private GravityConstantKey makeGravityKey(String fromZone, String modeOrVehType, * @return listOfZones */ ArrayList getListOfZones() { -// int count = 0; -// if (listOfZones.isEmpty()) -// for (TripDistributionMatrixKey key : matrixCache.keySet()) { -// count++; -// System.out.println(count); -// if (!listOfZones.contains(key.getFromZone())) -// listOfZones.add(key.getFromZone()); -// if (!listOfZones.contains(key.getToZone())) -// listOfZones.add(key.getToZone()); -// } return listOfZones; } 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 index 01446db9c0c..8a2d7ef9407 100644 --- 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 @@ -58,14 +58,6 @@ private void weightedProbability() { .filter(a -> a.getValue().equals(selectedLetter)) .findFirst() .ifPresent(l -> l.setExpectedCount(l.getExpectedCount() + 1)); - - //After 'testCount' loops, print out the number of times each value was selected and the percentage it represents -// 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 void writeResults(){ for (ProbabilityForValue probabilityForValue : ProbabilityDistribution) { From 788b93f138a4cf3298436ec33f6c01af43a415fe Mon Sep 17 00:00:00 2001 From: rakow Date: Thu, 22 Feb 2024 19:11:22 +0100 Subject: [PATCH 06/15] fix default args and add more tests for config update (#3129) --- .../matsim/application/ApplicationUtils.java | 18 ++++- .../matsim/application/MATSimApplication.java | 2 +- .../application/ConfigYamlUpdateTest.java | 44 +++++++++++ .../ConfigYamlUpdateTest/config.xml | 75 +++++++++++++++++++ .../ConfigYamlUpdateTest/params.yml | 13 ++++ 5 files changed, 147 insertions(+), 5 deletions(-) create mode 100644 contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/config.xml create mode 100644 contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/params.yml diff --git a/contribs/application/src/main/java/org/matsim/application/ApplicationUtils.java b/contribs/application/src/main/java/org/matsim/application/ApplicationUtils.java index 24b3d712bb8..083a315ecb5 100644 --- a/contribs/application/src/main/java/org/matsim/application/ApplicationUtils.java +++ b/contribs/application/src/main/java/org/matsim/application/ApplicationUtils.java @@ -119,7 +119,7 @@ else if (property.equalsIgnoreCase("false") || property.equals("0")) public static void applyConfigUpdate(Config config, Path yaml) { if (!Files.exists(yaml)) { - throw new IllegalArgumentException("Desired run config does not exist:" + yaml); + throw new IllegalArgumentException("Given config yaml does not exist: " + yaml); } ObjectMapper mapper = new ObjectMapper(new YAMLFactory() @@ -139,8 +139,8 @@ public static void applyConfigUpdate(Config config, Path yaml) { String configGroupName = aliases.resolveAlias(field.getKey(), emptyStack); ConfigGroup group = config.getModules().get(configGroupName); if (group == null) { - log.warn("Config group not found: {}", configGroupName); - continue; + group = new ConfigGroup(configGroupName); + config.addModule(group); } applyNodeToConfigGroup(field.getValue(), group); @@ -168,7 +168,17 @@ private static void applyNodeToConfigGroup(JsonNode node, ConfigGroup group) { List params = new ArrayList<>(group.getParameterSets(field.getKey())); for (JsonNode item : field.getValue()) { - applyNodeAsParameterSet(field.getKey(), item, group, params); + + + // Special case of parameter sets that have only one entry + if (field.getValue().size() == 1 && params.size() == 1 && field.getValue().get(0).isObject()) { + + applyNodeToConfigGroup(field.getValue().get(0), params.get(0)); + + } else { + + applyNodeAsParameterSet(field.getKey(), item, group, params); + } } } else { 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 ecda5e0200a..7d63518e323 100644 --- a/contribs/application/src/main/java/org/matsim/application/MATSimApplication.java +++ b/contribs/application/src/main/java/org/matsim/application/MATSimApplication.java @@ -404,7 +404,7 @@ public static void runWithDefaults(Class clazz, Str } else { // Automatically add run command String[] runArgs = ApplicationUtils.mergeArgs(new String[]{"run"}, defaultArgs); - args = ApplicationUtils.mergeArgs(defaultArgs, runArgs); + args = ApplicationUtils.mergeArgs(runArgs, args); } } else diff --git a/contribs/application/src/test/java/org/matsim/application/ConfigYamlUpdateTest.java b/contribs/application/src/test/java/org/matsim/application/ConfigYamlUpdateTest.java index 0c90c69c854..8c6c4768b22 100644 --- a/contribs/application/src/test/java/org/matsim/application/ConfigYamlUpdateTest.java +++ b/contribs/application/src/test/java/org/matsim/application/ConfigYamlUpdateTest.java @@ -3,10 +3,12 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.api.core.v01.TransportMode; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigGroup; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.ReflectiveConfigGroup; +import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.testcases.MatsimTestUtils; import java.nio.file.Path; @@ -22,6 +24,32 @@ public class ConfigYamlUpdateTest { @RegisterExtension private MatsimTestUtils utils = new MatsimTestUtils(); + @Test + void params() { + + Path input = Path.of(utils.getClassInputDirectory()); + + Config config = ConfigUtils.loadConfig(input.resolve("config.xml").toString()); + + ApplicationUtils.applyConfigUpdate( + config, input.resolve("params.yml") + ); + + ScoringConfigGroup scoring = ConfigUtils.addOrGetModule(config, ScoringConfigGroup.class); + + assertThat(scoring.getModes()) + .hasSize(7); + + assertThat(scoring.getPerforming_utils_hr()) + .isEqualTo(6.88); + + ScoringConfigGroup.ModeParams car = scoring.getModes().get(TransportMode.car); + + assertThat(car.getConstant()).isEqualTo(-0.62); + assertThat(car.getMarginalUtilityOfTraveling()).isEqualTo(0); + + } + @Test void standard() { @@ -74,6 +102,22 @@ void createParamSet() { assertThat(next.getParams().get("extra")).isEqualTo("extra"); } + @Test + void createGroup() { + Config config = ConfigUtils.createConfig(); + Path input = Path.of(utils.getClassInputDirectory()); + + ApplicationUtils.applyConfigUpdate( + config, input.resolve("multiLevel.yml") + ); + + + TestConfigGroup test = ConfigUtils.addOrGetModule(config, TestConfigGroup.class); + + assertThat(test.values).containsExactly(1, 2, 3); + + } + @Test void multiLevel() { diff --git a/contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/config.xml b/contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/config.xml new file mode 100644 index 00000000000..c67cc24de58 --- /dev/null +++ b/contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/config.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/params.yml b/contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/params.yml new file mode 100644 index 00000000000..31d0f926bd2 --- /dev/null +++ b/contribs/application/test/input/org/matsim/application/ConfigYamlUpdateTest/params.yml @@ -0,0 +1,13 @@ +scoring: + scoringParameters: + - modeParams: + - mode: walk + constant: 0.0 + - mode: car + constant: -0.62 + - mode: pt + constant: -0.25 + - mode: bike + constant: -2.23 + - mode: ride + constant: -1.37 \ No newline at end of file From 29598614846b5bac09afa2678924f3ba42323614 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 24 Feb 2024 09:29:41 +0000 Subject: [PATCH 07/15] build(deps): bump org.apache.commons:commons-compress Bumps org.apache.commons:commons-compress from 1.25.0 to 1.26.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-compress 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 37708358923..50bc9b1ba3a 100644 --- a/pom.xml +++ b/pom.xml @@ -118,7 +118,7 @@ org.apache.commons commons-compress - 1.25.0 + 1.26.0 commons-logging From 05216ec29ce2f80d85c513f0ced885a40a58224c Mon Sep 17 00:00:00 2001 From: Michal Maciejewski Date: Sat, 24 Feb 2024 10:36:43 +0100 Subject: [PATCH 08/15] mvn: set Apache Commons IO to 2.15.1 --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index 50bc9b1ba3a..4e1fc61382c 100644 --- a/pom.xml +++ b/pom.xml @@ -135,6 +135,11 @@ commons-text 1.11.0 + + commons-io + commons-io + 2.15.1 + com.opencsv opencsv From 510e4264bfb6a44f8c4bf67b606a56978cdf7bf4 Mon Sep 17 00:00:00 2001 From: rakow Date: Tue, 27 Feb 2024 16:25:01 +0100 Subject: [PATCH 09/15] remove unnecessary overwrite of interaction activities (#3133) --- .../java/org/matsim/contrib/vsp/scenario/SnzActivities.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/scenario/SnzActivities.java b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/scenario/SnzActivities.java index 5687f8b2116..5e1705a677d 100644 --- a/contribs/vsp/src/main/java/org/matsim/contrib/vsp/scenario/SnzActivities.java +++ b/contribs/vsp/src/main/java/org/matsim/contrib/vsp/scenario/SnzActivities.java @@ -74,10 +74,6 @@ public static void addScoringParams(Config config) { } } - config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams("car interaction").setTypicalDuration(60)); - config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams("ride interaction").setTypicalDuration(60)); - config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams("bike interaction").setTypicalDuration(60)); - config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams("other").setTypicalDuration(600 * 3)); config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams("freight_start").setTypicalDuration(60 * 15)); From 7867b93131155ea1f7e355b5b8012faf26a834fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Feb 2024 16:37:35 +0000 Subject: [PATCH 10/15] build(deps): bump com.fasterxml.woodstox:woodstox-core Bumps [com.fasterxml.woodstox:woodstox-core](https://github.com/FasterXML/woodstox) from 6.6.0 to 6.6.1. - [Commits](https://github.com/FasterXML/woodstox/compare/woodstox-core-6.6.0...woodstox-core-6.6.1) --- updated-dependencies: - dependency-name: com.fasterxml.woodstox:woodstox-core 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 4e1fc61382c..68c3e2ed945 100644 --- a/pom.xml +++ b/pom.xml @@ -212,7 +212,7 @@ com.fasterxml.woodstox woodstox-core - 6.6.0 + 6.6.1 From 428a1238857467ad3a9e7296daed9588d23cfd96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Feb 2024 16:57:38 +0000 Subject: [PATCH 11/15] build(deps): bump io.grpc:grpc-all from 1.61.1 to 1.62.2 Bumps [io.grpc:grpc-all](https://github.com/grpc/grpc-java) from 1.61.1 to 1.62.2. - [Release notes](https://github.com/grpc/grpc-java/releases) - [Commits](https://github.com/grpc/grpc-java/compare/v1.61.1...v1.62.2) --- updated-dependencies: - dependency-name: io.grpc:grpc-all dependency-type: direct:production update-type: version-update:semver-minor ... 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 d1a36e0cec5..57b42a70d8a 100644 --- a/contribs/hybridsim/pom.xml +++ b/contribs/hybridsim/pom.xml @@ -11,7 +11,7 @@ 3.25.3 - 1.61.1 + 1.62.2 From 97c94baa0140f9cbb26d8dd123432181e84a4bab Mon Sep 17 00:00:00 2001 From: marecabo <23156476+marecabo@users.noreply.github.com> Date: Fri, 1 Mar 2024 15:30:14 +0100 Subject: [PATCH 12/15] Add getter for totalWeight to WeightedRandomSelection --- .../matsim/contrib/common/util/WeightedRandomSelection.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contribs/common/src/main/java/org/matsim/contrib/common/util/WeightedRandomSelection.java b/contribs/common/src/main/java/org/matsim/contrib/common/util/WeightedRandomSelection.java index 6e305111108..148174d67af 100644 --- a/contribs/common/src/main/java/org/matsim/contrib/common/util/WeightedRandomSelection.java +++ b/contribs/common/src/main/java/org/matsim/contrib/common/util/WeightedRandomSelection.java @@ -67,6 +67,10 @@ public int size() { return entryList.size(); } + public double getTotalWeight() { + return totalWeight; + } + private record Entry(E e, double cumulativeWeight) implements Comparable> { public int compareTo(Entry o) { double diff = this.cumulativeWeight - o.cumulativeWeight; From c5a9204fa28ed480aab229d2428c1e2fef73c4f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 3 Mar 2024 16:04:55 +0000 Subject: [PATCH 13/15] build(deps): bump org.mockito:mockito-core from 5.10.0 to 5.11.0 Bumps [org.mockito:mockito-core](https://github.com/mockito/mockito) from 5.10.0 to 5.11.0. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v5.10.0...v5.11.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-core 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 68c3e2ed945..eb874831c9e 100644 --- a/pom.xml +++ b/pom.xml @@ -316,7 +316,7 @@ org.mockito mockito-core - 5.10.0 + 5.11.0 test From 76b4c72aec670ba836b54218e4742effc9824e84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 3 Mar 2024 16:25:32 +0000 Subject: [PATCH 14/15] build(deps): bump org.mockito:mockito-junit-jupiter Bumps [org.mockito:mockito-junit-jupiter](https://github.com/mockito/mockito) from 5.10.0 to 5.11.0. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v5.10.0...v5.11.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-junit-jupiter 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 eb874831c9e..1251711bfa6 100644 --- a/pom.xml +++ b/pom.xml @@ -322,7 +322,7 @@ org.mockito mockito-junit-jupiter - 5.10.0 + 5.11.0 test From ad7970501912959b01cc987b9d326455b1060ccb Mon Sep 17 00:00:00 2001 From: Markus Straub Date: Mon, 4 Mar 2024 11:45:09 +0100 Subject: [PATCH 15/15] guarantees sorted modes per link fixes #3134 --- .../org/matsim/core/network/LinkImpl.java | 8 +++++--- .../AbstractNetworkWriterReaderTest.java | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/matsim/src/main/java/org/matsim/core/network/LinkImpl.java b/matsim/src/main/java/org/matsim/core/network/LinkImpl.java index eab36be649f..1f9b660f9e2 100644 --- a/matsim/src/main/java/org/matsim/core/network/LinkImpl.java +++ b/matsim/src/main/java/org/matsim/core/network/LinkImpl.java @@ -36,6 +36,8 @@ import org.matsim.utils.objectattributes.attributable.Attributes; import org.matsim.utils.objectattributes.attributable.AttributesImpl; +import com.google.common.collect.ImmutableSortedSet; + /*deliberately package*/ class LinkImpl implements Link { private final static Logger log = LogManager.getLogger(Link.class); @@ -131,7 +133,7 @@ private void checkLengthSemantics(){ } } - + ////////////////////////////////////////////////////////////////////// // get methods @@ -184,7 +186,7 @@ public double getCapacityPeriod() { } // --- - + @Override public double getFreespeed() { return this.freespeed; @@ -281,7 +283,7 @@ public static Set get(final Set set) { if (set == null) { return null; } - return cache.computeIfAbsent(set.hashCode(), key -> Set.copyOf(set)); + return cache.computeIfAbsent(set.hashCode(), key -> ImmutableSortedSet.copyOf(set)); } } } diff --git a/matsim/src/test/java/org/matsim/core/network/AbstractNetworkWriterReaderTest.java b/matsim/src/test/java/org/matsim/core/network/AbstractNetworkWriterReaderTest.java index b3c47aecbf7..c479667c573 100644 --- a/matsim/src/test/java/org/matsim/core/network/AbstractNetworkWriterReaderTest.java +++ b/matsim/src/test/java/org/matsim/core/network/AbstractNetworkWriterReaderTest.java @@ -93,6 +93,12 @@ public abstract class AbstractNetworkWriterReaderTest { */ protected abstract void readNetwork(final Scenario scenario, final InputStream stream); + @Test + void testAllowedModes_manyUnsortedModes() { + doTestAllowedModes(createHashSet("train", "drt", "car", "bus", "walk", "freight"), + utils.getOutputDirectory() + "network.xml"); + } + @Test void testAllowedModes_multipleModes() { doTestAllowedModes(createHashSet("bus", "train"), utils.getOutputDirectory() + "network.xml"); @@ -245,6 +251,19 @@ private void doTestAllowedModes(final Set modes, final String filename) Set modes2 = link1.getAllowedModes(); assertEquals(modes.size(), modes2.size(), "wrong number of allowed modes."); assertTrue(modes2.containsAll(modes), "wrong mode."); + + assertModesSorted(modes2); + } + + private static void assertModesSorted(Set modes) { + List originalModes = new ArrayList<>(modes); + List sortedModes = new ArrayList<>(modes); + Collections.sort(sortedModes); + + for (int i = 0; i < originalModes.size(); i++) { + assertEquals(sortedModes.get(i), originalModes.get(i), + "modes are not sorted. expected '" + sortedModes + "'' but got '" + originalModes + "'"); + } } private static Set createHashSet(T... mode) {